forked from yvv/decision
Lot V : contrôle C34 (la chaîne fermée, Monnaie libre vote quand même : le vote simulé compte aussitôt, marqué dans « Tes bulletins ») ; C24 dit que le serveur sans compte des votes simule depuis le lot V ; CLAUDE.md et CONTROLES.md (buffer, casts_simulated, simulation.rs, C34, 35 contrôles / 36 tests)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+50
-2
@@ -176,8 +176,9 @@ test('C23 — le vote par la chaîne Ğ1 : un geste, confirmé par l’indexeur
|
||||
|
||||
test('C24 — sans compte de vote, le vote par la chaîne est fermé et le dit ; le groupe d’essai vote', async ({ page }) => {
|
||||
await signIn(page, 'Chiara');
|
||||
// The e2e server has its vote account: the page is shown what a server without one answers
|
||||
// (the server itself: `without_a_vote_account_the_chain_vote_is_off_and_the_test_group_still_votes`).
|
||||
// The e2e server has its vote account: the page is shown a vote closed, as a server without
|
||||
// one answered before lot V. Since lot V (ADR 0012) a server without one votes in simulation
|
||||
// instead (the server: `without_a_vote_account_monnaie_libre_votes_in_simulation_…`; here, C34).
|
||||
await page.route(/\/api\/docs\/[^/?]+$/, async (route) => {
|
||||
const res = await route.fetch();
|
||||
const body = await res.json();
|
||||
@@ -213,3 +214,50 @@ test('C24 — sans compte de vote, le vote par la chaîne est fermé et le dit ;
|
||||
await unit.getByRole('button', { name: 'Le vote' }).click();
|
||||
await expect(unit.locator('section.fold').getByRole('button', { name: 'Pour', exact: true })).toBeVisible();
|
||||
});
|
||||
|
||||
/** The version of an article of Monnaie libre, by its title, as the API tells it to `page`. */
|
||||
async function version(page: import('@playwright/test').Page, title: string) {
|
||||
const g = await (await page.request.get('/api/groups/monnaie-libre')).json();
|
||||
const d = await (await page.request.get(`/api/docs/${g.docs[0].id}`)).json();
|
||||
type P = { title: string; tally: { against: number }; tallySimulated: { against: number }; myVoteState: string | null };
|
||||
const all: P[] = d.units.flatMap((u: { proposals: P[] }) => u.proposals);
|
||||
const p = all.find((x) => x.title === title);
|
||||
if (!p) throw new Error(`no version « ${title} »`);
|
||||
return { vote: d.vote as { way: string; open: boolean; simulated: boolean }, p };
|
||||
}
|
||||
|
||||
test('C34 — la chaîne fermée, Monnaie libre vote quand même : le vote simulé compte aussitôt, marqué « simulé » dans tes bulletins', async ({ page }) => {
|
||||
// Lot V (ADR 0012, Yvv 2026-11-02: « Il compte, puis s'efface »). The e2e server has its
|
||||
// chain: it is closed for this control only, then opened again. The vote goes to a
|
||||
// proposal no other control reads, and only « contre »: nothing enters into force.
|
||||
await signIn(page, 'Sacha');
|
||||
const chainOpen = async (open: boolean) =>
|
||||
(await (await page.request.post('/api/dev/vote-chain', { data: { open }, headers: { 'x-requested-with': 'libredecision' } })).json()).open;
|
||||
const title = 'Logiciel auditable';
|
||||
expect(await chainOpen(false)).toBe(false);
|
||||
try {
|
||||
const before = await version(page, title);
|
||||
expect(before.vote).toMatchObject({ way: 'server', open: true, simulated: true });
|
||||
await page.goto(DOC);
|
||||
// The basket is there, without a wallet: the vote leaves by the server.
|
||||
await expect(page.getByRole('button', { name: /^Voter en lot/ })).toBeVisible();
|
||||
await deepRow(page, title).click();
|
||||
const fold = page.getByRole('region', { name: `Le vote de « ${title} »` });
|
||||
await fold.getByRole('button', { name: 'Contre', exact: true }).click();
|
||||
await expect(page.getByRole('dialog', { name: 'Voter avec ton portefeuille Ğ1' })).toHaveCount(0);
|
||||
await expect(fold.locator('.voted')).toHaveText(/^Ton vote : contre/);
|
||||
await expect(fold.getByText(`0 pour · ${before.p.tally.against + 1} contre`)).toBeVisible();
|
||||
// Counted at once, marked as simulated.
|
||||
const after = await version(page, title);
|
||||
expect(after.p.myVoteState).toBe('simulated');
|
||||
expect(after.p.tallySimulated.against).toBe(before.p.tallySimulated.against + 1);
|
||||
// In her ballots: simulated, counted for her session, never a block of the chain.
|
||||
await page.goto('/bulletins');
|
||||
const ballot = page.locator('li.ballot').first();
|
||||
await expect(ballot.locator('.state')).toHaveText("Simulé : compté pour « Sacha » jusqu'à l'ouverture de la chaîne Ğ1");
|
||||
await expect(ballot.getByText('bloc', { exact: false })).toHaveCount(0);
|
||||
} finally {
|
||||
// The next controls need the chain.
|
||||
expect(await chainOpen(true)).toBe(true);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user