v3 : les versions d'un article tiennent une seule ligne (L8)

- « Propositions en cours » : une ligne par article. Un article à plusieurs versions montre
  leur nombre et la meilleure en tête (niveau d'eau, pour / contre, « en tête » quand elle
  devance vraiment) ; la ligne se déplie (bouton à aria-expanded, clavier) sur ses versions,
  chacune avec son étiquette (variante, auteur), son niveau, ses marques, et un extrait qui
  part de là où les versions divergent ; un clic ouvre son vote comme avant.
- Règle pure dans versions.ts (vitest) : ordre du document, meilleure d'abord (niveau d'eau,
  puis pour, puis contre ; une version bloquée jamais en tête), un article reste dans un
  filtre dès qu'une de ses versions passe.
- e2e : C3 compte 30 lignes, C14 déplie « Connaissance suffisante » au clavier ; C11 passe
  par un article à une seule version.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-10-30 10:42:27 +01:00
co-authored by Claude Opus 5.5
parent a5b92faa96
commit edc88111e0
10 changed files with 397 additions and 40 deletions
+28 -3
View File
@@ -33,7 +33,8 @@ test('C3 — le texte en vigueur : raison d’être et deux engagements, seed a
await expect(units.nth(2).locator('h2')).toHaveText('Réciprocité');
await expect(page.getByText('seed a minima · 0 vote')).toHaveCount(3);
await expect(page.getByRole('heading', { name: 'Propositions en cours' })).toBeVisible();
await expect(page.locator('ul.deep button.row')).toHaveCount(32);
// One line per article: E3 and E7 hold their two variants inside.
await expect(page.locator('ul.deep button.row')).toHaveCount(30);
});
test('C4 — les actions sont contextuelles, le vote s’ouvre en panneau', async ({ page }) => {
@@ -147,13 +148,13 @@ test('C11 — une personne, une voix : dans Monnaie libre, seuls les membres de
await invited.goto(`/invitation#${link.split('#')[1]}`);
await expect(invited).toHaveURL(/\/groupes$/);
await invited.goto(DOC);
await invited.locator('ul.deep button.row', { hasText: 'Connaissance suffisante' }).first().click();
await invited.locator('ul.deep button.row', { hasText: 'Vérification personnelle de la clé' }).click();
const panel = invited.locator('aside.panel');
await expect(panel.getByText('Ici, seuls les membres de la toile de confiance Ğ1 votent', { exact: false })).toBeVisible();
await expect(panel.getByRole('button', { name: 'Pour', exact: true })).toHaveCount(0);
// In the test group, the same person votes.
await invited.goto(TEST_DOC);
await invited.locator('ul.deep button.row', { hasText: 'Connaissance suffisante' }).first().click();
await invited.locator('ul.deep button.row', { hasText: 'Vérification personnelle de la clé' }).click();
await expect(invited.locator('aside.panel').getByRole('button', { name: 'Pour', exact: true })).toBeVisible();
});
@@ -205,3 +206,27 @@ test('C13 — la Raison d’être ouvre le texte en vigueur, en trois langues',
await page.getByRole('radiogroup', { name: 'Text language' }).getByRole('radio', { name: 'ES' }).click();
await expect(first.locator('h2')).toHaveText('Razón de ser');
});
test('C14 — un article, une ligne : ses versions se déplient', async ({ page }) => {
await signIn(page, 'Chiara');
await page.goto(DOC);
const e3 = page.locator('ul.deep button.row', { hasText: 'Connaissance suffisante' });
await expect(e3).toHaveCount(1);
await expect(e3).toContainText('2 versions');
await expect(e3).toHaveAttribute('aria-expanded', 'false');
// Unfolded with the keyboard: its two versions, each with its label.
await e3.focus();
await page.keyboard.press('Enter');
await expect(e3).toHaveAttribute('aria-expanded', 'true');
const versions = page.locator(`#${await e3.getAttribute('aria-controls')}`).getByRole('button');
await expect(versions).toHaveCount(2);
await expect(versions.nth(0)).toContainText('variante 1.0.0');
await expect(versions.nth(1)).toContainText('variante 0.4.0-draft');
// A version opens its vote, as any proposal.
await versions.nth(1).click();
await expect(page.locator('aside.panel').getByText('Seuil : 50 voix pour')).toBeVisible();
await expect(page).toHaveURL(/version=/);
await e3.click();
await expect(e3).toHaveAttribute('aria-expanded', 'false');
await expect(versions).toHaveCount(0);
});