Lot U2 : les contrôles d'abord, vus rouges sur l'interface d'avant — cibles de 44 px sur téléphone et les trois lectures entières (M2), « Proposer cet ordre » dit pourquoi il est éteint (C35), une information à un seul endroit dans le vote déplié (onceonly, C19, C36), l'en-tête compte ce que montre la liste et un changement d'inertie d'un module se trouve à sa ligne (C38), settings.reading et l'anglais (lexicon)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-11-03 11:24:00 +01:00
co-authored by Claude Opus 5.5
parent cbf477c562
commit b39f7678b0
5 changed files with 275 additions and 1 deletions
+54
View File
@@ -48,6 +48,10 @@ test('C35 — réordonner une section : les poignées sur ses articles, au gliss
await expect(list.locator('.grip')).toHaveCount(3);
const submit = page.getByRole('button', { name: 'Proposer cet ordre' });
await expect(submit).toBeDisabled();
// Off, and it says why (UX-lecteur.md: « le bouton reste éteint et le dit » — lot U2).
const why = "C'est l'ordre en vigueur : déplace au moins un article.";
await expect(page.getByText(why)).toBeVisible();
await expect(submit).toHaveAccessibleDescription(why);
await shot(page, 'c35-2-poignees');
// By dragging its handle: Réciprocité onto the place of Unicité du compte.
@@ -55,6 +59,7 @@ test('C35 — réordonner une section : les poignées sur ses articles, au gliss
await expect(names).toHaveText([EF, E2, E1]);
await expect(page.getByText(`« ${E2} » en place 2 sur 3.`)).toBeAttached();
await expect(submit).toBeEnabled();
await expect(page.getByText(why)).toHaveCount(0);
// With the keyboard: the article keeps the focus, the arrows move it.
const items = list.locator('button.item');
await items.nth(1).focus();
@@ -67,6 +72,7 @@ test('C35 — réordonner une section : les poignées sur ses articles, au gliss
await list.getByRole('button', { name: `Descendre « ${E2} »` }).click();
await expect(names).toHaveText([EF, E1, E2]);
await expect(submit).toBeDisabled();
await expect(page.getByText(why)).toBeVisible();
await items.nth(2).click();
await expect(items.nth(2)).toHaveAttribute('aria-pressed', 'true');
await items.nth(1).click();
@@ -145,6 +151,9 @@ test('C36 — combien de oui pour passer, combien de non pour bloquer : sous l
await expect(need).toBeVisible();
// The quorum in a tooltip, never as a title.
await expect(need).toHaveAttribute('title', 'Quorum : 12 votants. En dessous, les votants qui manquent comptent comme « non ».');
// Said once: the line of the seed proposal, right above its vote, does not say it again (lot U2).
await expect(i1.locator('footer')).not.toContainText(/oui (sur|pour)/);
await expect(i1.locator('footer')).not.toContainText(/\d+ pour · \d+ contre/);
// In the list, short: at level 3, quorum 50.
await unfold(page);
await expect(deepRow(page, 'Vérification personnelle de la clé')).toContainText('39 oui sur 50');
@@ -237,3 +246,48 @@ test('C37 — le quorum d’un article : son auteur le fixe avant le premier vot
await expect(fold.getByRole('region', { name: /^Quorum/ })).toHaveCount(0);
await yvv.context().close();
});
test('C38 — l’en-tête compte ce que montre la liste ; un changement d’inertie d’un ordre ou du titre se trouve à sa ligne', async ({ page }) => {
await signIn(page, 'Chiara');
/** The versions « Propositions en cours » shows: one per line, or those inside a line of several. */
const listed = () =>
page.locator('ul.deep li.article').evaluateAll((lis) => lis.reduce((n, li) => n + Math.max(1, li.querySelectorAll('ul.versions > li').length), 0));
// Monnaie libre, nothing in force: the seed proposals at the head, said apart; the count of the
// proposals in progress is what the list below shows (lot U2: the orders are not counted there).
await page.goto(DOC);
await unfold(page);
const facts = page.locator('.facts');
await expect.soft(facts).toContainText('0 article en vigueur · 3 Propositions seed · ');
await expect.soft(facts).toContainText(new RegExp(`· ${await listed()} propositions en cours`));
// A change of inertia on the order of a section and on the title (test group): each is found at
// the line of its module, where its vote unfolds — never a line of « Propositions en cours ».
const g = await (await page.request.get('/api/groups/essai')).json();
const d = await (await page.request.get(`/api/docs/${g.docs[0].id}`)).json();
const modules: { id: string; inertia: number }[] = [d.modules.orders.find((o: { section: string }) => o.section === 'conclusion'), d.modules.title];
const made: string[] = [];
for (const unit of modules) {
const r = await page.request.post(`/api/units/${unit.id}/inertia`, { data: { target: unit.inertia === 5 ? 4 : unit.inertia + 1 }, headers: CSRF });
expect(r.ok()).toBe(true);
made.push((await r.json()).id);
}
await page.goto(TEST_DOC);
const title = page.getByRole('group', { name: 'Titre du document' });
const titleChange = title.getByRole('button', { name: "1 changement d'inertie proposé" });
await expect(titleChange).toBeVisible();
await titleChange.click();
await expect(title.getByRole('region', { name: /^Le vote de « inertie vers \d \/ 5 · / })).toBeVisible();
await shot(page, 'c38-1-titre-inertie');
await unfold(page);
await expect.soft(facts).toContainText(new RegExp(`· ${await listed()} propositions en cours`));
await expect(page.locator('ul.deep').getByText(/inertie vers/)).toHaveCount(0);
const order = page.getByRole('group', { name: 'Ordre des articles · Conclusion' });
const orderChange = order.getByRole('button', { name: "1 changement d'inertie proposé" });
await expect(orderChange).toBeVisible();
await orderChange.click();
await expect(order.getByRole('region', { name: /^Le vote de « inertie vers \d \/ 5 · / })).toBeVisible();
await order.scrollIntoViewIfNeeded();
await shot(page, 'c38-2-ordre-inertie');
// Withdrawn: the group is left as found.
for (const id of made) expect((await page.request.post(`/api/proposals/${id}/withdraw`, { headers: CSRF })).ok()).toBe(true);
});