Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 14 additions & 44 deletions crates/templates/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@

//! Templates rendering

use std::{collections::HashSet, sync::Arc};
use std::{
collections::{BTreeMap, HashSet},
sync::Arc,
};

use anyhow::Context as _;
use arc_swap::ArcSwap;
Expand Down Expand Up @@ -383,7 +386,7 @@ register_templates! {
pub fn render_recovery_disabled(WithLanguage<EmptyContext>) { "pages/recovery/disabled.html" }

/// Render the form used by the `form_post` response mode
pub fn render_form_post<T: Serialize>(WithLanguage<FormPostContext<T>>) { "form_post.html" }
pub fn render_form_post<#[sample(EmptyContext)] T: Serialize>(WithLanguage<FormPostContext<T>>) { "form_post.html" }

/// Render the HTML error page
pub fn render_error(ErrorContext) { "pages/error.html" }
Expand Down Expand Up @@ -439,7 +442,13 @@ register_templates! {

impl Templates {
/// Render all templates with the generated samples to check if they render
/// properly
/// properly.
///
/// Returns the renders in a map whose keys are template names
/// and the values are lists of renders (according to the list
/// of samples).
/// Samples are stable across re-runs and can be used for
/// acceptance testing.
///
/// # Errors
///
Expand All @@ -448,47 +457,8 @@ impl Templates {
&self,
now: chrono::DateTime<chrono::Utc>,
rng: &mut impl Rng,
) -> anyhow::Result<()> {
check::render_not_found(self, now, rng)?;
check::render_app(self, now, rng)?;
check::render_swagger(self, now, rng)?;
check::render_swagger_callback(self, now, rng)?;
check::render_login(self, now, rng)?;
check::render_register(self, now, rng)?;
check::render_password_register(self, now, rng)?;
check::render_register_steps_verify_email(self, now, rng)?;
check::render_register_steps_email_in_use(self, now, rng)?;
check::render_register_steps_display_name(self, now, rng)?;
check::render_register_steps_registration_token(self, now, rng)?;
check::render_consent(self, now, rng)?;
check::render_policy_violation(self, now, rng)?;
check::render_sso_login(self, now, rng)?;
check::render_index(self, now, rng)?;
check::render_recovery_start(self, now, rng)?;
check::render_recovery_progress(self, now, rng)?;
check::render_recovery_finish(self, now, rng)?;
check::render_recovery_expired(self, now, rng)?;
check::render_recovery_consumed(self, now, rng)?;
check::render_recovery_disabled(self, now, rng)?;
check::render_form_post::<EmptyContext>(self, now, rng)?;
check::render_error(self, now, rng)?;
check::render_email_recovery_txt(self, now, rng)?;
check::render_email_recovery_html(self, now, rng)?;
check::render_email_recovery_subject(self, now, rng)?;
check::render_email_verification_txt(self, now, rng)?;
check::render_email_verification_html(self, now, rng)?;
check::render_email_verification_subject(self, now, rng)?;
check::render_upstream_oauth2_link_mismatch(self, now, rng)?;
check::render_upstream_oauth2_login_link(self, now, rng)?;
check::render_upstream_oauth2_suggest_link(self, now, rng)?;
check::render_upstream_oauth2_do_register(self, now, rng)?;
check::render_device_link(self, now, rng)?;
check::render_device_consent(self, now, rng)?;
check::render_account_deactivated(self, now, rng)?;
check::render_account_locked(self, now, rng)?;
check::render_account_logged_out(self, now, rng)?;
check::render_device_name(self, now, rng)?;
Ok(())
) -> anyhow::Result<BTreeMap<&'static str, Vec<String>>> {
check::all(self, now, rng)
}
}

Expand Down
26 changes: 25 additions & 1 deletion crates/templates/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ macro_rules! register_templates {
pub fn $name:ident
// Optional list of generics. Taken from
// https://newbedev.com/rust-macro-accepting-type-with-generic-parameters
$(< $( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)?
// For sample rendering, we also require a 'sample' generic parameter to be provided,
// using #[sample(Type)] attribute syntax
$(< $( #[sample( $generic_default:tt )] $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+ >)?
// Type of context taken by the template
( $param:ty )
{
Expand Down Expand Up @@ -69,9 +71,31 @@ macro_rules! register_templates {
pub mod check {
use super::*;

/// Check and render all templates with all samples.
///
/// Returns the sample renders. The keys in the map are the template names.
///
/// # Errors
///
/// Returns an error if any template fails to render with any of the sample.
pub(crate) fn all(templates: &Templates, now: chrono::DateTime<chrono::Utc>, rng: &mut impl rand::Rng) -> anyhow::Result<::std::collections::BTreeMap<&'static str, Vec<String>>> {
let mut out = ::std::collections::BTreeMap::new();
// TODO shouldn't the Rng be independent for each render?
$(
out.insert(
$template,
$name $(::< $( $generic_default ),* >)? (templates, now, rng)?
);
)*

Ok(out)
}

$(
#[doc = concat!("Render the `", $template, "` template with sample contexts")]
///
/// Returns the sample renders.
///
/// # Errors
///
/// Returns an error if the template fails to render with any of the sample.
Expand Down