| name | lage-steps |
| description | Lag Playwright step-definisjoner for BDD-tester. Veileder brukeren gjennom prosessen med å bruke codegen, strukturere steps, og gjenbruke eksisterende kode. Bruk når brukeren vil implementere tester, lage steps, eller automatisere scenarios.
|
Lage Steps
Skill for å lage Playwright step-definisjoner fra Gherkin-scenarios.
Arbeidsflyt
1. Identifiser scenarios
Spør brukeren:
- Hvilken feature-fil skal implementeres?
- Hvilke scenarios skal automatiseres?
Les feature-filen og list opp steps som trenger implementasjon.
2. Finn eksisterende steps
Søk etter gjenbrukbare steps i tester/steps/**/*.ts:
grep -r "Given\|When\|Then" tester/steps/
Presenter funn:
## Eksisterende steps som kan gjenbrukes
- `at jeg er logget inn som {word}` - bruker-kontekst.steps.ts:25
- `skal jeg se {string} på siden` - bruker-kontekst.steps.ts:55
## Steps som må lages
- `jeg oppretter en ny søknad`
- `skal søknaden være lagret`
3. Bruk Playwright Codegen
For å fange opp interaksjoner, bruk codegen med norsk locale:
FS-Admin (administrator):
npx playwright codegen --lang no-Nb $FS_ADMIN_URL
MinKompetanse (person/søker):
npx playwright codegen --lang no-Nb $MIN_KOMPETANSE_URL
Instruksjoner til brukeren:
- Kjør kommandoen over i terminalen
- Logg inn manuelt (bruk Feide testbruker)
- Utfør handlingene fra scenarioet
- Kopier den genererte koden
- Lim inn koden her, så hjelper jeg med å strukturere den
4. Strukturer steps
Når brukeren limer inn codegen-output:
- Ekstraher gjenbrukbare deler - Identifiser mønstre som kan bli generelle steps
- Bruk riktig fixture -
userContext for multi-rolle, page for enkelt-rolle
- Følg navnekonvensjoner - Filnavn:
[domene].steps.ts
- Legg til JSDoc - Dokumenter hva steget gjør
Eksempel transformasjon:
Fra codegen:
await page.getByRole('link', { name: 'Opptak' }).click()
await page.getByRole('button', { name: 'Nytt opptak' }).click()
await page.getByLabel('Navn').fill('Test opptak')
Til strukturert step:
When('jeg oppretter et nytt opptak med navn {string}', async ({ userContext }, navn: string) => {
const page = userContext.currentPage
await page.getByRole('link', { name: 'Opptak' }).click()
await page.getByRole('button', { name: 'Nytt opptak' }).click()
await page.getByLabel('Navn').fill(navn)
})
5. Plasser i riktig fil
Filstruktur:
tester/
├── steps/
│ ├── bruker-kontekst.steps.ts # Innlogging, rollebytte
│ ├── feide-innlogging.steps.ts # Auth setup
│ ├── opptak.steps.ts # Opptak-domene
│ └── [domene].steps.ts # Nye domener
├── fixtures/
│ └── user-context.ts # userContext fixture
├── helpers/
│ └── combobox.ts # Gjenbrukbare hjelpefunksjoner
└── pages/
└── [side]/ # Page Object Model (valgfritt)
Velg fil basert på domene:
- Opptak-relatert →
opptak.steps.ts
- Person/profil →
person.steps.ts
- Generell navigasjon →
navigasjon.steps.ts
Step-mønster
Grunnleggende struktur
import { createBdd } from 'playwright-bdd'
import { test, expect } from '../fixtures/user-context'
const { Given, When, Then } = createBdd(test)
Given('at jeg er på {string}', async ({ userContext }, side: string) => {
await userContext.currentPage.goto(side)
})
Med parametere
When('jeg fyller inn {string} i feltet {string}',
async ({ userContext }, verdi: string, felt: string) => {
await userContext.currentPage.getByLabel(felt).fill(verdi)
}
)
Given('at jeg er logget inn som {word}', async ({ userContext }, rolle: string) => {
await userContext.switchTo(rolle as UserRole)
})
Med datatabell
When('jeg fyller ut skjemaet:', async ({ userContext }, dataTable: DataTable) => {
const data = dataTable.rowsHash()
for (const [felt, verdi] of Object.entries(data)) {
await userContext.currentPage.getByLabel(felt).fill(verdi)
}
})
Viktig Prinsipp: Scenariene er krav
Scenariene i feature-filer er kravspesifikasjoner, ikke bare tester. Hvis en test feiler, vurder først om feilen ligger i step-implementasjonen eller testdata.
OK å endre scenario:
- Omformulere for å gjenbruke eksisterende steps (f.eks. "Når jeg lagrer opptaket" → "Når jeg lagrer")
- Rette skrivefeil eller forbedre lesbarhet
Ikke OK å endre scenario:
- Endre forventet resultat for å få testen til å passere
- Fjerne steg som beskriver viktig forretningslogikk
- Endre logikken i kravet
Hvis et scenario ikke kan testes med tilgjengelig testdata, merk det som @planned og dokumenter hva som mangler - ikke endre kravet.
Beste Praksis
Gjenbruk fixtures
Bruk userContext for tester med flere roller:
Given('at jeg er logget inn som {word}', async ({ userContext }, rolle: string) => {
await userContext.switchTo(rolle as UserRole)
})
Vent på nettverksaktivitet
await page.waitForLoadState('networkidle')
Bruk robuste selektorer
Prioriter i denne rekkefølgen:
getByRole() - Beste praksis
getByLabel() - For skjemafelt
getByText() - For synlig tekst
getByTestId() - Siste utvei
Håndter asynkrone elementer
await page.getByRole('button', { name: 'Lagre' }).waitFor({ state: 'visible' })
const element = page.getByText('Lastet')
if (await element.isVisible({ timeout: 2000 }).catch(() => false)) {
await element.click()
}
Eksempel
Se examples/step-example.ts for et komplett eksempel på godt strukturerte steps.