Commit 18b5ff3c authored by Kourser's avatar Kourser
Browse files

Les mêmes émojis s'affichaient deux fois sous chaque message

Le salon portait deux rendus des réactions d'un message : une liste passive de
pastilles, héritée de la première coque, et le composant interactif qui l'a
remplacée sans que l'ancienne soit retirée. Les deux lisaient la même liste,
dans le même bloc, l'une sous l'autre — seule celle du haut réagit au clic.

Ni le typage ni l'API ne pouvaient s'en apercevoir : les deux rendus sont
valides, et le serveur sert la même chose aux deux.

Le passif ignorait de surcroît « supprime », que l'interactif respecte : un
message effacé montrait encore ce que les gens en avaient pensé.

La garantie ne dit pas « le salon affiche les réactions » mais qu'un seul
endroit du produit les affiche — c'est la duplication qui était le défaut, pas
l'absence.

Co-Authored-By: default avatarClaude Opus 5 <noreply@anthropic.com>
parent 333495df
Loading
Loading
Loading
Loading
+21 −0
Changes for apps/api/src/verification/interface.ts: 21 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -370,6 +370,27 @@ export async function verifierInterface(r: Rapport): Promise<void> {
    srvManquantes.length === 0,
    srvManquantes.slice(0, 4).map((m) => `« ${m.slice(0, 40)} »`).join(", "));

  // ── Les réactions d'un message ne s'affichent qu'une fois (EF-702) ───────
  //
  // Le salon en portait deux rendus : une liste passive de pastilles, héritée
  // de la première coque, et le composant interactif qui l'a remplacée sans
  // que l'ancienne soit retirée. Les deux s'affichaient l'une sous l'autre,
  // avec les mêmes émojis et les mêmes comptes. Le typage n'y voit rien — les
  // deux sont valides — et l'API non plus, qui sert la même liste aux deux.
  //
  // Le passif ignorait de surcroît « supprime » : un message effacé montrait
  // encore ce que les gens en avaient pensé.
  const rendus: string[] = [];
  for (const f of fichiers) {
    if (f.includes("/langues/")) continue;
    const texte = await readFile(f, "utf8");
    for (const _ of texte.matchAll(/\.reactions\b/g)) {
      rendus.push(f.split("/").slice(-2).join("/"));
    }
  }
  r.verifie("EF-702", "un seul endroit du produit affiche les réactions d'un message",
    rendus.length === 1, rendus.join(", ") || "aucun");

  // ── Aucune phrase n'échappe au dictionnaire (EX-21) ──────────────────────
  //
  // « window.prompt », « confirm » et « alert » affichent un texte que le
+0 −9
Changes for apps/web/src/ecrans/Salon.tsx: 0 added lines, 9 removed lines.
Original line number Diff line number Diff line
@@ -365,15 +365,6 @@ export function Salon({
                    ))}
                  </div>
                )}
                {(m.reactions?.length ?? 0) > 0 && (
                  <div className="ligne" style={{ gap: 4, marginTop: 3 }}>
                    {m.reactions!.map((r) => (
                      <span key={r.emoji} className="pastille neutre sans-point">
                        {r.emoji} {r.comptes.length}
                      </span>
                    ))}
                  </div>
                )}
              </div>
            </div>
          ))}