import { describe, expect, it } from 'vitest' import { parseUseCases } from '../ba-use-cases.js' // The AC-contract behaviour (acs, level, scheduled, ALT/EXC, lost channel, // lexical tolerances) is exercised by the historical suite at // development/testing/cli/scaffold-tests-from-ac/__tests__/parse-ac.test.ts, // which now runs THROUGH this module (parse-ac is a re-export shim). // This suite covers the EXTENDED fields the promotion added — the carriers // of audit rules UC-003..009. const FULL_UC = [ '### UC-CRM-PIPELINE-opportunites-001 — Créer une opportunité', '- **Acteur principal** : BA-001-AC-001 (Commercial)', '- **Acteurs secondaires** : BA-001-AC-002 (Manager), BA-001-AC-003 (Assistant)', '- **Préconditions** : le prospect existe.', '- **Flux principal** :', ' 1. Le commercial ouvre le formulaire.', ' 2. Il saisit le montant', ' et la probabilité.', ' 3. Il enregistre.', '- **Flux alternatifs** :', ' - ALT-1 : montant inconnu → brouillon.', '- **Exceptions** :', ' - EXC-1 : prospect archivé → refus.', '- **Postconditions** : opportunité visible dans la liste.', '- **Acceptance Criteria** :', ' - [ ] AC-01 — POST renvoie 201.', '', ].join('\n') describe('ba-use-cases — extended fields (UC-003..009 carriers)', () => { it('a parenthesised secondary actor with a comma stays ONE actor', () => { const { ucs } = parseUseCases( [ '### UC-CRM-PIPELINE-opportunites-002 — Valider une opportunité', '- **Acteur principal** : BA-001-AC-001 (Commercial)', '- **Acteurs secondaires** : BA-001-AC-002 (Manager, N+1), BA-001-AC-003 (Assistant)', '', ].join('\n'), 'opportunites/use-case.md', ) expect(ucs[0]!.secondaryActors).toEqual(['BA-001-AC-002 (Manager, N+1)', 'BA-001-AC-003 (Assistant)']) }) it('parses actors, preconditions, postconditions and the numbered main flow', () => { const { ucs, warnings, lost } = parseUseCases(FULL_UC, 'opportunites/use-case.md') expect(ucs).toHaveLength(1) const uc = ucs[0]! expect(uc.primaryActor).toBe('BA-001-AC-001 (Commercial)') expect(uc.secondaryActors).toEqual(['BA-001-AC-002 (Manager)', 'BA-001-AC-003 (Assistant)']) expect(uc.preconditions).toEqual(['le prospect existe.']) expect(uc.postconditions).toEqual(['opportunité visible dans la liste.']) expect(uc.mainFlow).toEqual([ 'Le commercial ouvre le formulaire.', 'Il saisit le montant et la probabilité.', 'Il enregistre.', ]) // The AC contract still parses alongside. expect(uc.acs).toHaveLength(1) expect(uc.alternatives).toHaveLength(1) expect(uc.exceptions).toHaveLength(1) expect(warnings).toEqual([]) expect(lost).toEqual([]) }) it('a plain indented line FOLDS into the previous main-flow step (multi-line step)', () => { const { ucs } = parseUseCases(FULL_UC, 'opportunites/use-case.md') expect(ucs[0]!.mainFlow[1]).toBe('Il saisit le montant et la probabilité.') }) it('préconditions as SUB-BULLETS yield one entry each', () => { const md = [ '### UC-A-B-C-001 — Créer', '- **Préconditions** :', ' - le prospect existe', ' - le quota est ouvert', '- **Flux principal** :', ' 1. X.', '', ].join('\n') const { ucs } = parseUseCases(md, 'c/use-case.md') expect(ucs[0]!.preconditions).toEqual(['le prospect existe', 'le quota est ouvert']) }) it('missing extended fields stay EMPTY — the parser never invents (the audit rules verdict)', () => { const md = '### UC-A-B-C-001 — Minimal\n- **Acceptance Criteria** :\n - [ ] AC-01 — X.\n' const { ucs } = parseUseCases(md, 'c/use-case.md') const uc = ucs[0]! expect(uc.primaryActor).toBeUndefined() expect(uc.secondaryActors).toEqual([]) expect(uc.preconditions).toEqual([]) expect(uc.postconditions).toEqual([]) expect(uc.mainFlow).toEqual([]) }) it('NFD accents and typographic apostrophes in field names are folded', () => { const md = [ '### UC-A-B-C-001 — Créer', `- **Pr${'é'}conditions** : décomposé accepté.`, '- **Flux principal** :', ' 1. X.', '', ].join('\n') const { ucs } = parseUseCases(md, 'c/use-case.md') expect(ucs[0]!.preconditions).toEqual(['décomposé accepté.']) }) it('field routing never bleeds across UCs', () => { const md = [ '### UC-A-B-C-001 — Premier', '- **Flux principal** :', ' 1. Étape du premier.', '', '### UC-A-B-C-002 — Second', '- **Préconditions** : propre au second.', '', ].join('\n') const { ucs } = parseUseCases(md, 'c/use-case.md') expect(ucs[0]!.mainFlow).toEqual(['Étape du premier.']) expect(ucs[0]!.preconditions).toEqual([]) expect(ucs[1]!.mainFlow).toEqual([]) expect(ucs[1]!.preconditions).toEqual(['propre au second.']) }) })