Claude-skill-registry flow-create
Creer un nouveau flow d'automatisation de formulaire complet, incluant exploration du site web, implementation et tests. (project)
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/flow-create" ~/.claude/skills/majiayu000-claude-skill-registry-flow-create && rm -rf "$T"
skills/data/flow-create/SKILL.mdflow-create
Cree un nouveau flow d'automatisation de formulaire web complet.
Declenchement
/flow-create {platform} {product}
Exemples :
/flow-create alptis prevoyance-tns/flow-create swisslifeone sante-famille
Journal de bord
IMPORTANT : Tout au long du processus, maintenir un fichier journal qui documente chaque action.
Fichier journal
.claude/flow-logs/{platform}-{product}-create.md
Format du journal
# Journal de creation : {platform} {product} **Debut** : {date et heure} **Branche** : flow/{platform}-{product} **Status** : EN COURS | TERMINE | BLOQUE --- ## Phase 0 : Verification initiale **Debut** : {timestamp} - [x] Flow existe deja : NON - [x] Credentials trouves : ALPTIS_TEST_USERNAME, ALPTIS_TEST_PASSWORD - [x] Branche creee : flow/{platform}-{product} **Fin** : {timestamp} **Duree** : 2 min --- ## Phase 1 : Exploration **Debut** : {timestamp} ### Actions - Creation du test d'exploration : `e2e/{platform}/{product}/.detailed/explore-selectors.spec.ts` - Lancement exploration headless... ### Resultats exploration - Sections trouvees : 4 - Champs totaux : 18 - Selectors STABLE : 12 - Selectors UNSTABLE : 6 ### Champs identifies | Section | Champ | Type | Selector | Stabilite | |---------|-------|------|----------|-----------| | 1 | date_effet | date | input[placeholder='...'] | MODERATE | | 2 | nom | text | #nom | STABLE | | ... | ... | ... | ... | ... | - Cartographie generee : `src/main/flows/cartography/{platform}/{platform}-{product}-exhaustive-mapping.json` **Fin** : {timestamp} **Duree** : 15 min **Commit** : feat({platform}/{product}): add form cartography --- ## Phase 2 : Scaffolding **Debut** : {timestamp} ### Fichiers crees - `src/main/flows/config/products/{platform}-{product}.ts` - `src/main/flows/platforms/{platform}/products/{product}/transformers/types.ts` - `src/main/flows/platforms/{platform}/products/{product}/transformers/LeadTransformer.ts` - ... (liste complete) **Fin** : {timestamp} **Duree** : 10 min **Commit** : feat({platform}/{product}): scaffold flow structure --- ## Phase 3 : Implementation **Debut** : {timestamp} ### Section 1 : Mise en place - Selectors implementes : 3/3 - Operations utilisees : DateOperations, ToggleOperations - Test detaille : PASS - Commit : feat({platform}/{product}): implement section 1 - Mise en place ### Section 2 : Adherent - Selectors implementes : 8/8 - Operations utilisees : DateOperations, DropdownOperations, RadioOperations - Test detaille : PASS - Commit : feat({platform}/{product}): implement section 2 - Adherent ### Section 3 : Conjoint (optionnel) - Selectors implementes : 4/4 - Test detaille : PASS (avec lead conjoint) - Commit : feat({platform}/{product}): implement section 3 - Conjoint ### Section 4 : Enfants (dynamique) - Selectors implementes : 2/2 par enfant - Logique dynamique : OK (jusqu'a 5 enfants) - Test detaille : PASS - Commit : feat({platform}/{product}): implement section 4 - Enfants **Fin** : {timestamp} **Duree** : 45 min --- ## Phase 4 : Integration **Debut** : {timestamp} - FormFillOrchestrator : OK - Enregistrement PRODUCT_CONFIGS : OK - Test single lead (LEAD_INDEX=0) : PASS **Fin** : {timestamp} **Duree** : 10 min **Commit** : feat({platform}/{product}): integrate flow with FlowEngine --- ## Phase 5 : Tests bulk **Debut** : {timestamp} ### Premier run - Leads testes : 22 - Resultats : 18 PASS, 4 FAIL - Problemes identifies : - Lead #5 : profession non mappee "consultant senior" - Lead #12 : date format invalide - Lead #15, #18 : meme probleme profession ### Corrections - Ajout mapping "consultant senior" -> PROFESSIONS_LIBERALES - Fix parsing date avec format alternatif ### Second run - Leads testes : 22 - Resultats : 22 PASS, 0 FAIL **Fin** : {timestamp} **Duree** : 20 min **Commit** : test({platform}/{product}): add test fixtures and bulk validation --- ## Phase 6 : Validation **Debut** : {timestamp} ### Status final - Sections implementees : 4/4 - Tests bulk : 22/22 PASS (100%) - Commits : 8 ### En attente - Review utilisateur - Merge de la branche **Fin** : {timestamp} --- ## Problemes rencontres ### Probleme 1 : Dropdown ville ne se charge pas **Symptome** : Timeout sur selection ville **Cause** : Le dropdown attend que le code postal soit valide **Solution** : Ajouter waitForTimeout(2000) apres remplissage code postal ### Probleme 2 : Profession non mappee **Symptome** : 4 leads en echec avec erreur "Unknown profession" **Cause** : Mapping manquant pour "consultant senior" **Solution** : Ajout dans profession-mapper.ts --- ## Resume - **Temps total** : 1h42 - **Commits** : 8 - **Tests** : 22/22 PASS - **Status** : PRET POUR REVIEW
Regles du journal
- Creer le fichier au debut de la Phase 0
- Mettre a jour en temps reel a chaque action importante
- Documenter les problemes rencontres et leurs solutions
- Inclure les timestamps pour chaque phase
- Lister tous les fichiers crees/modifies
- Noter les resultats de tests (PASS/FAIL avec details)
Workflow complet
Phase 0 : Verification initiale
-
Verifier si le flow existe deja
ls src/main/flows/config/products/{platform}-{product}.tsSi le flow existe, suggerer
a la place./flow-fix -
Verifier les credentials
grep -q "{PLATFORM}_USERNAME" .env && grep -q "{PLATFORM}_PASSWORD" .envVariables requises :
- Pour Alptis :
,ALPTIS_TEST_USERNAMEALPTIS_TEST_PASSWORD - Pour SwissLife :
,SWISSLIFE_USERNAMESWISSLIFE_PASSWORD
Si manquants, demander a l'utilisateur de les ajouter au fichier
..env - Pour Alptis :
-
Creer la branche de travail
git checkout -b flow/{platform}-{product}COMMIT :
chore: create branch flow/{platform}-{product}
Phase 1 : Exploration du formulaire
L'exploration se fait en mode headless (pas de fenetre visible).
-
Creer le test d'exploration Playwright
Creer le fichier :
e2e/{platform}/{product}/.detailed/explore-selectors.spec.tsTemplate base sur :
e2e/swisslifeone/slsis/.detailed/inspect-section6-selectors.spec.tsimport { test } from '@playwright/test'; import { create{Platform}Services } from '@/main/flows/engine/services'; import { get{Platform}Credentials } from '@/main/flows/config'; test.describe('Selector Exploration - {Product}', () => { test('Explore all form sections', async ({ page }) => { test.setTimeout(600000); // 10 minutes // 1. Auth const services = create{Platform}Services(get{Platform}Credentials()); await services.auth.login(page); // 2. Navigate to form await page.goto('{FORM_URL}'); await page.waitForLoadState('networkidle'); // 3. For each section: inspect elements console.log('\n====== SECTION 1 ======'); const snapshot1 = await page.locator('body').ariaSnapshot(); console.log('ARIA Snapshot:', snapshot1.substring(0, 2000)); // 4. Inspect all inputs const inputs = await page.locator('input, select, textarea').all(); for (const input of inputs) { const id = await input.getAttribute('id'); const name = await input.getAttribute('name'); const type = await input.getAttribute('type'); const placeholder = await input.getAttribute('placeholder'); const isVisible = await input.isVisible(); if (isVisible) { // Evaluate stability let stability = 'STABLE'; if (!id) stability = 'UNSTABLE'; else if (/^[0-9a-f]{8}-/.test(id)) stability = 'UNSTABLE (UUID)'; console.log({ id, name, type, placeholder, stability }); } } // 5. Capture screenshot await page.screenshot({ path: `src/main/flows/cartography/{platform}/{product}-section1.png` }); // Repeter pour chaque section... }); }); -
Lancer l'exploration en headless
npx playwright test e2e/{platform}/{product}/.detailed/explore-selectors.spec.ts --timeout=600000 -
Generer le JSON de cartographie
Creer :
src/main/flows/cartography/{platform}/{platform}-{product}-exhaustive-mapping.jsonTemplate base sur :
src/main/flows/cartography/alptis/alptis-sante-select-exhaustive-mapping.json{ "product": { "name": "{Product Display Name}", "platform": "{platform}", "url": "https://...", "cartography_date": "YYYY-MM-DD" }, "metadata": { "form_title": "...", "total_steps": 2, "framework": "Vue.js | Angular | React", "design_system": "Totem | Bootstrap | Custom" }, "form_structure": { "sections": [ { "name": "Section 1", "fields_count": 3 }, { "name": "Section 2", "fields_count": 8 } ] }, "fields": [ { "field_id": "nom", "section": "Adherent", "type": "text", "selector": { "primary": "#nom", "alternative": "input[placeholder='Ex : Durand']", "stability": "STABLE" }, "validation": { "required": true, "pattern": "^[a-zA-Z-' ]+$" } } ] }COMMIT :
feat({platform}/{product}): add form cartography
Phase 2 : Scaffolding
Creer l'arborescence complete :
src/main/flows/ ├── config/products/{platform}-{product}.ts # ProductConfiguration └── platforms/{platform}/products/{product}/ ├── steps/ │ ├── form-fill/ │ │ ├── FormFillOrchestrator.ts │ │ ├── index.ts │ │ ├── selectors/ │ │ │ ├── section1.ts │ │ │ ├── section2.ts │ │ │ ├── common.ts │ │ │ └── index.ts │ │ ├── sections/ │ │ │ ├── Section1Fill.ts │ │ │ └── Section2Fill.ts │ │ └── operations/ │ │ ├── DateOperations.ts │ │ ├── DropdownOperations.ts │ │ ├── RadioOperations.ts │ │ ├── ToggleOperations.ts │ │ └── index.ts │ └── navigation/ │ └── index.ts └── transformers/ ├── LeadTransformer.ts ├── types.ts ├── mappers/ │ ├── civilite-mapper.ts │ ├── profession-mapper.ts │ └── regime-mapper.ts └── validators/ ├── lead-validator.ts └── eligibility-validator.ts e2e/{platform}/{product}/ ├── fixtures.ts ├── single-lead-journey.spec.ts ├── bulk-validation.spec.ts └── .detailed/ ├── explore-selectors.spec.ts ├── form-fill.section1.spec.ts ├── form-fill.section2.spec.ts └── transformer.spec.ts
Fichiers de reference a copier/adapter :
| Type | Fichier de reference |
|---|---|
| ProductConfiguration | |
| FormFillOrchestrator | |
| Selectors | |
| Operations | |
| LeadTransformer | |
| Mappers | |
| Fixtures e2e | |
| Single lead test | |
COMMIT :
feat({platform}/{product}): scaffold flow structure
Phase 3 : Implementation section par section
Pour chaque section du formulaire (en ordre) :
-
Types : Definir
base sur la cartographie{Product}FormDataexport type {Product}FormData = { mise_en_place: { remplacement_contrat: boolean; date_effet: string; }; adherent: { civilite: 'M.' | 'Mme'; nom: string; prenom: string; date_naissance: string; // ... autres champs }; conjoint?: { ... }; enfants?: Array<{ ... }>; }; -
Mappers : Creer un mapper pour chaque enum
// mappers/profession-mapper.ts const PROFESSION_MAPPING: Record<string, string> = { 'profession liberale': 'PROFESSIONS_LIBERALES', "chef d'entreprise": 'CHEFS_D_ENTREPRISE', // ... base sur la cartographie }; export function mapProfession(value: string | undefined): string { if (!value) return 'AUTRES'; return PROFESSION_MAPPING[value.toLowerCase().trim()] ?? 'AUTRES'; } -
Selectors : Definir avec stabilite
// selectors/section2.ts export const SECTION_2_SELECTORS = { nom: { primary: '#nom', stability: 'STABLE', }, civilite: { primary: "input[name*='form-radio']", byValue: (v: 'monsieur' | 'madame') => `input[value='${v}']`, stability: 'UNSTABLE', }, date_naissance: { primary: "input[placeholder='Ex : 01/01/2020']", note: "Use .nth(1) - first date field is date_effet", stability: 'MODERATE', }, } as const; -
SectionFill : Implementer le remplissage
// sections/Section2Fill.ts export class Section2Fill { async fill(page: Page, data: FormData, logger?: FlowLogger): Promise<void> { // Civilite const civiliteSelector = SELECTORS.civilite.byValue( data.adherent.civilite === 'M.' ? 'monsieur' : 'madame' ); await page.locator(civiliteSelector).click({ force: true }); // Nom await page.locator(SELECTORS.nom.primary).fill(data.adherent.nom); // ... etc } } -
Test detaille : Tester la section isolement (headless)
npx playwright test e2e/{platform}/{product}/.detailed/form-fill.section{n}.spec.ts
COMMIT apres chaque section :
feat({platform}/{product}): implement section {n} - {name}
Phase 4 : Integration
-
Implementer le FormFillOrchestrator
export class FormFillOrchestrator { private section1 = new Section1Fill(); private section2 = new Section2Fill(); async fillMiseEnPlace(page: Page, data: FormData, logger?: FlowLogger) { await this.section1.fill(page, data, logger); } async fillAdherent(page: Page, data: FormData, logger?: FlowLogger) { await this.section2.fill(page, data, logger); } // ... } -
Enregistrer dans PRODUCT_CONFIGS
Editer
:src/main/flows/config/products/index.tsimport { {PLATFORM}_{PRODUCT} } from "./{platform}-{product}"; export const PRODUCT_CONFIGS: Record<string, ProductConfiguration> = { // ... existing [{PLATFORM}_{PRODUCT}.flowKey]: {PLATFORM}_{PRODUCT}, }; -
Creer ServiceFactory si nouvelle plateforme
-
Tester single lead (headless)
LEAD_INDEX=0 npx playwright test e2e/{platform}/{product}/single-lead-journey.spec.ts
COMMIT :
feat({platform}/{product}): integrate flow with FlowEngine
Phase 5 : Tests bulk et generation de leads
-
Tester sur tous les leads existants (headless)
npx playwright test e2e/{platform}/{product}/bulk-validation.spec.ts -
Si aucun lead compatible : Generer des fixtures JSON programmatiquement
Creer dans
:src/main/__tests__/fixtures/emails/
: Lead sans conjoint ni enfantsemail-{next}-solo.json
: Lead avec conjointemail-{next}-conjoint.json
: Lead avec enfantsemail-{next}-enfants.json
: Lead avec conjoint ET enfantsemail-{next}-both.json
Format :
{ "id": "fixture-{product}-solo", "subject": "Nouveau lead - {Product} Solo", "from": "test@fixture.com", "date": 1700000000000, "text": "Civilite: M.\nNom: DUPONT\nPrenom: Jean\n..." } -
Iterer jusqu'a 100% de succes
- Si un test echoue : identifier le probleme, corriger, re-tester
- Repeter jusqu'a ce que bulk-validation passe a 100%
COMMIT :
test({platform}/{product}): add test fixtures and bulk validation
Phase 6 : Validation utilisateur
Quand tous les tests passent OU si bloque :
Flow {platform}_{product} pret pour review. Status: - Sections implementees: {n}/{total} - Tests bulk: {passed}/{total} leads - Coverage: {percentage}% Prochaines etapes: 1. Review du code 2. Merge de la branche 3. Test manuel si necessaire
Demander a l'utilisateur s'il veut :
- Merger la branche
- Faire des ajustements
- Voir les details d'un probleme
Conventions
Nommage
| Element | Pattern | Exemple |
|---|---|---|
| flowKey | | |
| Branche | | |
| Config file | | |
Pattern de selectors
{ primary: "#semantic-id", // Le plus stable alternative: ".class-selector", // Fallback byValue: (v) => `[value='${v}']`, // Pour radios/options byRole: "combobox", // Pour Playwright roles byPosition: ".item:nth(0)", // Si necessaire fallback: "label:has-text('...')", // Dernier recours stability: 'STABLE' | 'MODERATE' | 'UNSTABLE', }
Format commits
{type}({platform}/{product}): {description} - Detail 1 - Detail 2 Generated with Claude Code Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Types :
feat, fix, test, chore, docs
Checklist
- Branche
creeeflow/{platform}-{product} - Credentials disponibles dans .env
- Exploration terminee
- Cartographie JSON generee
- ProductConfiguration creee et enregistree
- Types FormData definis
- Tous les mappers implementes
- Tous les validators implementes
- LeadTransformer fonctionnel
- Tous les selectors definis avec stabilite
- Toutes les operations implementees
- FormFillOrchestrator complet
- Fixtures de test creees
- Tests single-lead passent (headless)
- Tests bulk-validation passent 100% (headless)
- Commits apres chaque etape majeure