v3 : liens d'équipe, publication sur git.open.us.org, huitième relecture

Liens d'équipe (Yvv, 2026-10-21) : un lien réutilisable jusqu'à une date
et pour un nombre de personnes, révocable. Chaque ouverture demande un nom
et crée sa propre identité d'invitation, jamais administratrice ; un nom
déjà pris est refusé ; une personne déjà connectée reçoit les groupes.
trustinWallet montre par quel lien chaque identité est venue, et donne un
nouveau lien de connexion à une personne invitée (autre appareil).
Migration additive 0002 (table team_links, colonne identities.team_link).

Publication : yvv/libredecision-textes sur git.open.us.org, pour
l'instant (un dépôt pour l'ouverture, puis le dépôt officiel, viendront).

Huitième relecture (c3d6bf8 : ok), points corrigés :
- une négation n'est jamais coupée ni formée par collage (« ja mais ») ;
- caractères invisibles : tout l'ensemble Unicode des ignorables et les
  contrôles autres que saut de ligne et tabulation ;
- sauts de ligne et indentation font partie de la forme (listes) ;
- un titre tient sur une ligne.

Boucle : 65 tests Rust, svelte-check, 9 vitest, e2e 13/13 (C12 ajouté).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Yvv
2026-10-21 08:12:21 +02:00
co-authored by Claude Opus 5.5
parent c3d6bf88b9
commit fd19dbf4ec
29 changed files with 938 additions and 85 deletions
+24
View File
@@ -155,3 +155,27 @@ test('C11 — une personne, une voix : dans Monnaie libre, seuls les membres de
await invited.locator('ul.deep button.row', { hasText: 'Connaissance suffisante' }).first().click();
await expect(invited.locator('aside.panel').getByRole('button', { name: 'Pour', exact: true })).toBeVisible();
});
test('C12 — lien d’équipe : chaque personne qui l’ouvre a sa propre identité', async ({ browser }) => {
const yvv = await person(browser, 'Yvv', true);
await yvv.goto('/acces');
const team = yvv.locator('section', { has: yvv.getByRole('heading', { name: "Liens d'équipe" }) });
await team.getByLabel('Pour quelle équipe').fill('Équipe de test');
await team.getByLabel("Groupe d'essai").check();
await team.getByRole('button', { name: "Créer le lien d'équipe" }).click();
const link = (await team.locator('.link code').textContent()) ?? '';
expect(link).toContain('/equipe#');
for (const name of ['Luna', 'Paul']) {
const ctx = await browser.newContext({ locale: 'fr-FR' });
const page = await ctx.newPage();
await page.goto(`/equipe#${link.split('#')[1]}`);
await expect(page.getByText('« Équipe de test » t’ouvre', { exact: false })).toBeVisible();
await page.getByLabel('Ton nom').fill(name);
await page.getByRole('button', { name: 'Rejoindre' }).click();
await expect(page).toHaveURL(/\/groupes$/);
await ctx.close();
}
await yvv.reload();
await expect(team.getByText('2 / 30 personnes', { exact: false })).toBeVisible();
await expect(yvv.getByText('venue par « Équipe de test »')).toHaveCount(2);
});