diff --git a/web/e2e/vote.spec.ts b/web/e2e/vote.spec.ts index 2126685..132e719 100644 --- a/web/e2e/vote.spec.ts +++ b/web/e2e/vote.spec.ts @@ -260,6 +260,10 @@ test('C34 — la chaîne fermée, Monnaie libre vote quand même : le vote simul await expect(fold.getByText("La chaîne Ğ1 n'est pas encore ouverte : ton vote est simulé.", { exact: false })).toHaveCount(1); const n = before.p.tallySimulated.against + 1; await expect(fold.getByText(n === 1 ? 'dont 1 simulé' : `dont ${n} simulés`, { exact: true })).toBeVisible(); + // The line reads with its space: never « 0 contredont 1 simulé » (review of M6b). + await expect(fold.locator('p.tally')).toHaveText( + `0 pour · ${before.p.tally.against + 1} contre ${n === 1 ? 'dont 1 simulé' : `dont ${n} simulés`}`, + ); // Counted at once, marked as simulated. const after = await version(page, title); expect(after.p.myVoteState).toBe('simulated'); diff --git a/web/src/lib/components/VersionDetails.svelte b/web/src/lib/components/VersionDetails.svelte index 3457cd6..a511600 100644 --- a/web/src/lib/components/VersionDetails.svelte +++ b/web/src/lib/components/VersionDetails.svelte @@ -242,7 +242,7 @@ {:else if p.confirmedAt}{t('doc.confirmed')} {:else if p.enteredAt && p.status === 'in_force'}{t('doc.adopted', { date: i18n.date(p.enteredAt) })}{/if} {#if p.blocked}{t('deep.held')}{/if} - {#if p.author}{t('panel.by', { name: p.author })}{#if p.authorInvited} · {t('author.invited')}{/if}{:else if p.origin === 'seed'}{t('panel.seed.origin')}{/if} + {#if p.author}{t('panel.by', { name: p.author })}{#if p.authorInvited}{' '}· {t('author.invited')}{/if}{:else if p.origin === 'seed'}{t('panel.seed.origin')}{/if}
@@ -255,7 +255,7 @@ {#if detail.diff} {/if} - {#if text.translated}{t('doc.lang.translation')}{#if text.stale} · {t('doc.lang.stale')}{/if}
{/if} + {#if text.translated}{t('doc.lang.translation')}{#if text.stale}{' '}· {t('doc.lang.stale')}{/if}
{/if} {:else if p.kind === 'remove' && detail.inForce}{note}
{/each}{t('module.order.rule')}
{:else if p.kind === 'title'} -{t('module.title.name')} · {inertiaBadge(detail.unit.inertia)}{#if text.translated} · {t('doc.lang.translation')}{#if text.stale} · {t('doc.lang.stale')}{/if}{/if}
+{t('module.title.name')} · {inertiaBadge(detail.unit.inertia)}{#if text.translated}{' '}· {t('doc.lang.translation')}{#if text.stale}{' '}· {t('doc.lang.stale')}{/if}{/if}
{/if} {#if live} @@ -302,7 +302,7 @@- {t('typo.by', { name: fix.writer ?? '' })}{#if fix.writerInvited} · {t('author.invited')}{/if} · {i18n.date(fix.at)} + {t('typo.by', { name: fix.writer ?? '' })}{#if fix.writerInvited}{' '}· {t('author.invited')}{/if} · {i18n.date(fix.at)}
{typoState(fix)}
{#if fix.gestures.length} @@ -339,7 +339,7 @@ {#each detail.history.slice(1) as h (h.at + h.revision)}- {t(`history.${h.kind}`)} · {i18n.date(h.at)}{#if h.author} · {t('history.by', { name: h.author })}{#if h.authorInvited} · {t('author.invited')}{/if}{/if} + {t(`history.${h.kind}`)} · {i18n.date(h.at)}{#if h.author}{' '}· {t('history.by', { name: h.author })}{#if h.authorInvited}{' '}· {t('author.invited')}{/if}{/if} {#if h.typo?.deadline} · {t('history.typo.deadline')}{:else if h.typo?.answeredBy} · {t('history.typo.validated', { name: h.typo.answeredBy })}{/if}
{#if h.diff}{o.reason}
- {t('objection.by', { name: o.objector ?? '' })}{#if o.objectorInvited} · {t('author.invited')}{/if} · {i18n.date(o.at)} - · {stateOf(o)}{#if standing && o.answer} · {t(`objection.answer.${o.answer}`)}{/if} + {t('objection.by', { name: o.objector ?? '' })}{#if o.objectorInvited}{' '}· {t('author.invited')}{/if} · {i18n.date(o.at)} + · {stateOf(o)}{#if standing && o.answer}{' '}· {t(`objection.answer.${o.answer}`)}{/if}
{#if standing && o.held}{t('objection.held.here')}
{/if} {#if standing} diff --git a/web/src/lib/components/VoteFold.svelte b/web/src/lib/components/VoteFold.svelte index 201424f..1deecb0 100644 --- a/web/src/lib/components/VoteFold.svelte +++ b/web/src/lib/components/VoteFold.svelte @@ -160,7 +160,7 @@{t('tally.short', { for: p.tally.for, against: p.tally.against })}{#if p.tallySimulated?.for || p.tallySimulated?.against} {i18n.plural('vote.tally.simulated', p.tallySimulated.for + p.tallySimulated.against)}{/if}
+{t('tally.short', { for: p.tally.for, against: p.tally.against })}{#if p.tallySimulated?.for || p.tallySimulated?.against}{' '}{i18n.plural('vote.tally.simulated', p.tallySimulated.for + p.tallySimulated.against)}{/if}
{#if p.evaluation} {#if need}{need.long}
{/if}{p.evaluation.reached ? t('tally.reached') : i18n.plural('tally.missing', p.evaluation.missing)}
diff --git a/web/src/routes/+layout.svelte b/web/src/routes/+layout.svelte index 787e4e5..73a60fd 100644 --- a/web/src/routes/+layout.svelte +++ b/web/src/routes/+layout.svelte @@ -44,7 +44,7 @@{a}{#if s} x{/if}
')).toHaveLength(1); + expect(dropped('{a}{#if s} · x{:else if t} · y{:else} · z{/if}
')).toHaveLength(3); + expect(dropped('{#each xs as x}{x} {/each}y
')).toHaveLength(1); + // Kept: `{' '}`, a space outside the block, or a newline that lays the markup out. + expect(dropped("{a}{#if s}{' '}x{/if}
")).toEqual([]); + expect(dropped('{a} {#if s} · x{/if}
')).toEqual([]); + expect(dropped('x
\n{/if}([\s\S]*?)<\/p>/.exec(body)?.[1]; + if (line === undefined) throw new Error(`no line of totals in ${body}`); + // The text read: tags and the markers of the server rendering left out. + return line.replace(//g, '').replace(/<[^>]+>/g, ''); +} + +describe('the totals of the vote unfolded', () => { + it('say the simulated votes after a space', () => { + expect(fold(proposal({ for: 0, against: 1 }, { for: 0, against: 1 }))).toBe('0 pour · 1 contre dont 1 simulé'); + expect(fold(proposal({ for: 2, against: 1 }, { for: 2, against: 1 }))).toBe('2 pour · 1 contre dont 3 simulés'); + }); + it('say nothing more without a simulated vote', () => { + expect(fold(proposal({ for: 4, against: 2 }, { for: 0, against: 0 }))).toBe('4 pour · 2 contre'); + }); +});