# Un instantané de rendu HTML qui casse à cause d’un nonce généré

> Un test de régression basé sur un instantané échoue à chaque exécution, alors que le contenu affiché n'a visiblement pas changé. La cause se cache dans un champ dynamique jamais neutralisé.

- Auteur : Clément Hadrot
- Publié le : 2026-03-22
- Mis à jour le : 2026-03-22
- Catégorie : Tests
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tests/instantane-rendu-html-casse-nonce-genere/

## L’essentiel

- Un nonce WordPress change à chaque génération, ce qui rend un instantané brut inutilisable tel quel
- Comparer un rendu HTML complet nécessite de neutraliser tous les champs intrinsèquement variables
- Une expression régulière ciblée normalise le nonce sans masquer un changement réel ailleurs dans le rendu

« Failed asserting that two strings are identical » : ce message s'affichait à chaque exécution du test de régression visuelle sur le formulaire d'inscription à une newsletter associative, alors qu'aucune modification volontaire du template concerné n'avait été apportée depuis la création de l'instantané de référence. Le diff affiché par PHPUnit montrait deux chaînes quasi identiques, à l'exception d'une poignée de caractères en plein milieu d'un attribut caché.

La cause, une fois isolée : le formulaire intègre un champ `wp_nonce_field()`, dont la valeur change à chaque génération de la page par construction, puisqu'un nonce WordPress dépend de l'identifiant de session et de l'horodatage. Comparer deux rendus HTML capturés à des instants différents fait donc systématiquement échouer la comparaison, indépendamment de toute régression réelle du template.

## Symptôme : un test instable sans changement de contenu

Le test comparait le rendu HTML complet retourné par la fonction de template à un fichier d'instantané enregistré lors de la création du test. Chaque exécution régénérait un nonce différent, ce qui produisait un diff non nul même lorsque le template lui-même restait rigoureusement inchangé entre deux exécutions.

## Diagnostic : localiser la source de variation

> L'essentiel à retenir : Un nonce WordPress change à chaque génération, ce qui rend un instantané brut inutilisable tel quel ; Comparer un rendu HTML complet nécessite de neutraliser tous les champs intrinsèquement variables ; Une expression régulière ciblée normalise le nonce sans masquer un changement réel ailleurs dans le rendu

Un affichage côte à côte des deux versions du rendu a rapidement isolé la variation à une seule ligne, celle générée par `wp_nonce_field('inscription_newsletter', 'nonce_inscription')` :

```
<!-- Instantané de référence -->
<input type="hidden" id="nonce_inscription" name="nonce_inscription"
       value="a1b2c3d4e5" />

<!-- Rendu obtenu lors de l'exécution du test -->
<input type="hidden" id="nonce_inscription" name="nonce_inscription"
       value="f9e8d7c6b5" />
```

Le reste du rendu, y compris les libellés de champs et la structure du formulaire, restait strictement identique entre les deux versions. Le nonce, seul champ dynamique par nature, portait à lui seul la responsabilité de l'échec systématique.

## Correctif : normaliser le champ variable avant comparaison

La correction ne consiste pas à retirer le nonce du rendu testé, ce qui masquerait sa présence réelle dans le HTML produit, mais à le remplacer par une valeur fixe avant comparaison, à l'aide d'une expression régulière ciblée appliquée aux deux côtés de la comparaison :

```
private function normaliserRenduPourComparaison(string $html): string
{
    return preg_replace(
        '/name="nonce_inscription" value="[a-f0-9]+"/',
        'name="nonce_inscription" value="NONCE_NORMALISE"',
        $html
    );
}

public function leRenduDuFormulaireResteIdentiqueAuTemplate(): void
{
    $rendu = wpm_rendre_formulaire_inscription();
    $reference = file_get_contents(__DIR__ . '/instantanes/formulaire-inscription.html');

    $this->assertSame(
        $this->normaliserRenduPourComparaison($reference),
        $this->normaliserRenduPourComparaison($rendu)
    );
}
```

### Vérifier que la normalisation ne masque rien d'autre

Le risque d'une expression régulière trop large est de neutraliser également une variation réelle du template qui devrait faire échouer le test à juste titre. L'expression retenue cible précisément l'attribut `value` du champ nommé `nonce_inscription`, sans toucher aux autres attributs `value` du formulaire, qui doivent, eux, rester strictement comparés sans normalisation.

## Prévention : lister les champs intrinsèquement variables

- Tout champ généré par `wp_nonce_field()`, `wp_create_nonce()` ou un horodatage affiché directement dans le HTML doit être identifié avant la création d'un instantané de référence.
- Un identifiant auto-incrémenté de base de données, inséré dans un attribut `id` HTML, mérite la même vigilance que le nonce, pour la même raison.
- La liste des champs à normaliser gagne à être documentée dans le fichier de test lui-même, plutôt que déduite implicitement d'une expression régulière isolée.

> Un instantané de référence ne doit comparer que ce qui est censé rester stable, jamais ce qui varie par construction.

## En résumé

Un test de régression basé sur un instantané HTML échouait systématiquement à cause d'un nonce WordPress régénéré à chaque exécution, un champ intrinsèquement variable que la comparaison brute ne pouvait pas ignorer. Normaliser ce champ précis avant comparaison, sans toucher au reste du rendu, a suffi à retrouver un test stable, capable de détecter une régression réelle sans faux positif systématique.
