Files
decision/web/tests/unit/objections.test.ts
T
YvvandClaude Opus 5.5 83f8ca0981 v3 : interface des objections, des coquilles validées et de la messagerie ; contrôles C28–C31
Une version retenue par une objection le dit sous l'article, à chacun
selon son rôle : la personne qui vote voit qu'elle ne se vote plus (les
votes faits restent) ; l'auteur, quoi faire (« Modifier l'article visé »
pour une redite, « Reformuler » pour une contradiction) ; la personne qui
objecte, lever ou réitérer avant l'échéance. Le panier la montre sans
choix et ne l'envoie jamais.

« Détails » : faire une objection (redit / contredit), les objections et
où elles en sont, les coquilles proposées par d'autres avec leur diff
resserré, valider / refuser / revenir, l'historique dit qui a validé.
Une coquille se propose sur toute version ouverte ou en vigueur.

Boîte « Messages » dans le menu, avec le nombre de non-lus (pastille sur
le bouton du menu en mobile) : objet, texte, gestes, échéance ; un message
traité n'a plus de geste. Répondre à une objection lit son message.

Trilingue (fr, en, es). C6 suit la règle : la coquille d'un administrateur
sur un texte du seed passe tout de suite ; C28–C31 couvrent le reste.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 04:21:20 +01:00

38 lines
2.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, expect, it } from 'vitest';
import { answerPanel, holding } from '../../src/lib/objections';
import type { Objection, VersionRef } from '../../src/lib/types';
const ref = (id: string, over: Partial<VersionRef> = {}): VersionRef => ({
id, title: id, status: 'open', unitId: `u-${id}`, code: id.toUpperCase(), author: null, authorId: null, ...over,
});
function objection(over: Partial<Objection> = {}): Objection {
return {
id: 'o1', kind: 'redit', reason: 'Ces deux textes disent la même chose.', objector: 'Yvv', objectorInvited: false,
mine: false, at: '', phase: 'author', cycle: 1, dueAt: null, answer: null, answerId: null, answeredAt: null,
lift: null, liftedAt: null, heldVersion: ref('k1', { author: 'Chiara', authorId: 'dev:chiara' }),
other: ref('e2', { status: 'in_force' }), iAnswer: true, canLift: false, canReiterate: false, held: true, ...over,
};
}
describe('answering an objection', () => {
it('a repetition: a proposal linked to it, on the article repeated, from its text', () => {
expect(answerPanel(objection(), 'dev:chiara')).toEqual({ tab: 'propose', unitId: 'u-e2', proposalId: 'e2', objectionId: 'o1' });
});
it('a contradiction: one rewords one’s own version in place', () => {
expect(answerPanel(objection({ kind: 'contredit' }), 'dev:chiara')).toEqual({ tab: 'details', unitId: 'u-k1', proposalId: 'k1', edit: true });
});
it('a contradiction on a seeded version: a linked proposal on its article', () => {
const o = objection({ kind: 'contredit', heldVersion: ref('k1') });
expect(answerPanel(o, 'dev:chiara')).toEqual({ tab: 'propose', unitId: 'u-k1', proposalId: 'k1', objectionId: 'o1' });
});
it('nothing held back, nothing to answer; a lifted objection holds nothing', () => {
expect(answerPanel(objection({ heldVersion: null }), 'dev:chiara')).toBeNull();
const list = [objection(), objection({ id: 'o2', phase: 'lifted' }), objection({ id: 'o3', held: false })];
expect(holding(list).map((o) => o.id)).toEqual(['o1']);
});
});