Complex playwright tests using xstate #5536
Unanswered
sshehu-max
asked this question in
Q&A
Replies: 1 comment 1 reply
|
Hey! Here is an example of how you would use First you'd create your test machine that represents how the model-based tests should flow (btw this might not be the same as the actual machine, or it might be; up to you): import { setup } from 'xstate';
export const testFormMachine = setup({
types: {} as { events:
| { type: 'fill.valid' }
| { type: 'fill.invalid' }
| { type: 'submit' }
| { type: 'open.details' }
| { type: 'details.complete' }
| { type: 'back' }
}
}).createMachine({
id: 'form',
initial: 'step1',
states: {
step1: {
on: {
'fill.invalid': 'step1.invalid',
'fill.valid': 'step1.valid'
}
},
'step1.invalid': { on: { submit: 'step1' } }, // stays, shows error
'step1.valid': { on: { submit: 'step2' } },
step2: {
on: {
'open.details': 'detailsPage', // opens a new page/form
submit: 'done'
}
},
detailsPage: {
on: {
'details.complete': 'step2',
back: 'step2'
}
},
done: { type: 'final' }
}
});Then you'd hook it up to Playwright: import { test } from '@playwright/test';
import { createTestModel } from '@xstate/graph';
import { formMachine } from './formMachine';
const model = createTestModel(formMachine);
// One Playwright test per generated path — full coverage of the graph
for (const path of model.getShortestPaths()) { // or .getSimplePaths() etc.
test(path.description, async ({ page }) => {
await page.goto('/form');
await path.test({
// run after the machine enters a matching state — assert the UI
states: {
step1: (s) => page.getByrole('heading', { name: 'Step 1' }).waitFor(),
'step1.invalid': (s) => page.getByText('Required field').waitFor(),
step2: (s) => page.getByRole('heading', { name: 'Step 2' }).waitFor(),
detailsPage: (s) => page.getByRole('heading', { name: 'Details' }).waitFor(),
done: (s) => page.getByText('Submitted!').waitFor()
},
// run to drive each transition — perform the UI action
events: {
'fill.valid': async () => { await page.getByLabel('Email').fill('a@b.com'); },
'fill.invalid': async () => { await page.getByLabel('Email').fill(''); },
submit: async () => { await page.getByRole('button', { name: 'Next' }).click(); },
'open.details': async () => { await page.getByRole('button', { name: 'Add details' }).click(); },
'details.complete': async () => {
await page.getByLabel('Note').fill('hi');
await page.getByRole('button', { name: 'Save' }).click();
},
back: async () => { await page.getByRole('button', { name: 'Back' }).click(); }
}
});
});
}I'll try to write up docs for this soon. |
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Hi everyone, I have a very complex multi-step form that even opens new pages with additional forms. Since there are so many possible events and states, I’d like to use xstate to automate the tests with Playwright. Unfortunately, I haven’t been able to find much educational material, good documentation, or any examples online that I could use to learn from. For example, I think that in my case I need to combine several machines with each other.
So I was wondering if anyone knows of an open-source project that uses xstate for testing, or where else I might be able to find some learning materials.
Best regards
All reactions