Add Playwright E2E testing with recorded workflows

- Add @playwright/test as dev dependency
- Create playwright.config.ts with Chrome-only testing config
- Add npm scripts: test:record, test:e2e, test:replay
- Create 13 test recordings covering:
  - 2-player and 3-player games
  - 8-ball, 9-ball, and 10-ball game types
  - Various race-to values (1, 3, 5, 7, 9) and "endlos" mode
  - Both wechselbreak (alternating) and winnerbreak rules
- Fix Infinity handling in gameService.ts and NewGameScreen.tsx
  - Parse "endlos" and "Infinity" strings as Infinity number
  - Properly serialize Infinity as string in form data
- Increase GameDetail score font size from 20vh to 40vh
- Update README.md with testing documentation:
  - Quick start guide for recording and running tests
  - Move E2E testing from "Future Improvements" (now implemented)
- Add comprehensive tests/recordings/README.md documentation

Purpose: Establishes browser automation testing infrastructure with
real workflow recordings, enabling regression testing and interaction
documentation for all game configuration combinations.
This commit is contained in:
Frank Schwenk
2025-10-31 14:41:36 +01:00
parent 9175d505c2
commit 65aaa92359
22 changed files with 757 additions and 12 deletions

View File

@@ -0,0 +1,26 @@
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('http://localhost:3000/');
await page.getByRole('button', { name: 'Neues Spiel starten' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Kim');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Leo');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('button', { name: 'Überspringen' }).click();
await page.getByRole('button', { name: '10-Ball' }).click();
await page.getByRole('button', { name: 'Endlos' }).click();
await page.getByRole('button', { name: 'Break-Regel wählen: Wechselbreak' }).click();
await page.getByRole('button', { name: 'Zuerst: Leo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Leo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Kim' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Leo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Kim' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Leo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Kim' }).click();
await page.getByRole('button', { name: 'Spiel beenden' }).click();
await page.getByRole('button', { name: 'Bestätigen' }).click();
});

View File

@@ -0,0 +1,24 @@
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('http://localhost:3000/');
await page.getByRole('button', { name: 'Neues Spiel starten' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Charlie');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Diana');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('button', { name: 'Überspringen' }).click();
await page.getByRole('button', { name: '10-Ball' }).click();
await page.getByRole('button', { name: '3' }).click();
await page.getByRole('button', { name: 'Break-Regel wählen: Wechselbreak' }).click();
await page.getByRole('button', { name: 'Zuerst: Diana' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Diana' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Charlie' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Diana' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Diana' }).click();
await page.getByRole('button', { name: 'Bestätigen' }).click();
await page.getByRole('button', { name: 'Zurück zur Liste' }).click();
});

View File

@@ -0,0 +1,29 @@
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('http://localhost:3000/');
await page.getByRole('button', { name: 'Neues Spiel starten' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Wendy');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Xavier');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('button', { name: 'Überspringen' }).click();
await page.getByRole('button', { name: '8-Ball' }).click();
await page.getByRole('button', { name: '5' }).click();
await page.getByRole('button', { name: 'Break-Regel wählen: Wechselbreak' }).click();
await page.getByRole('button', { name: 'Zuerst: Xavier' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Xavier' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Wendy' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Xavier' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Wendy' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Xavier' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Wendy' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Xavier' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Wendy' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Xavier' }).click();
await page.getByRole('button', { name: 'Bestätigen' }).click();
await page.getByRole('button', { name: 'Zurück zur Liste' }).click();
});

View File

@@ -0,0 +1,31 @@
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('http://localhost:3000/');
await page.getByRole('button', { name: 'Neues Spiel starten' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Mia');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Noah');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('button', { name: 'Überspringen' }).click();
await page.getByRole('button', { name: '8-Ball' }).click();
await page.getByRole('button', { name: '9' }).click();
await page.getByRole('button', { name: 'Break-Regel wählen: Winnerbreak' }).click();
await page.getByRole('button', { name: 'Zuerst: Mia' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Mia' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Noah' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Mia' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Mia' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Noah' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Mia' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Mia' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Mia' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Mia' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Mia' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Mia' }).click();
await page.getByRole('button', { name: 'Bestätigen' }).click();
await page.getByRole('button', { name: 'Zurück zur Liste' }).click();
});

View File

@@ -0,0 +1,26 @@
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('http://localhost:3000/');
await page.getByRole('button', { name: 'Neues Spiel starten' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Foo');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Bar');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('button', { name: 'Überspringen' }).click();
await page.getByRole('button', { name: '8-Ball' }).click();
await page.getByRole('button', { name: 'Endlos' }).click();
await page.getByRole('button', { name: 'Break-Regel wählen: Winnerbreak' }).click();
await page.getByRole('button', { name: 'Zuerst: Foo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Foo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Bar' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Foo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Bar' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Foo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Foo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Foo' }).click();
await page.getByRole('button', { name: 'Spiel beenden' }).click();
await page.getByRole('button', { name: 'Bestätigen' }).click();
});

View File

@@ -0,0 +1,21 @@
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('http://localhost:3000/');
await page.getByRole('button', { name: 'Neues Spiel starten' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Rita');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Sam');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('button', { name: 'Überspringen' }).click();
await page.getByRole('button', { name: '9-Ball' }).click();
await page.getByRole('button', { name: '1' }).click();
await page.getByRole('button', { name: 'Break-Regel wählen: Wechselbreak' }).click();
await page.getByRole('button', { name: 'Zuerst: Sam' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Sam' }).click();
await page.getByRole('button', { name: 'Bestätigen' }).click();
await page.getByRole('button', { name: 'Zurück zur Liste' }).click();
});

View File

@@ -0,0 +1,26 @@
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('http://localhost:3000/');
await page.getByRole('button', { name: 'Neues Spiel starten' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Alice');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Bob');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('button', { name: 'Überspringen' }).click();
await page.getByRole('button', { name: '9-Ball' }).click();
await page.getByRole('button', { name: '5' }).click();
await page.getByRole('button', { name: 'Break-Regel wählen: Winnerbreak' }).click();
await page.getByRole('button', { name: 'Zuerst: Alice' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Alice' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Bob' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Alice' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Alice' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Alice' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Alice' }).click();
await page.getByRole('button', { name: 'Bestätigen' }).click();
await page.getByRole('button', { name: 'Zurück zur Liste' }).click();
});

View File

@@ -0,0 +1,29 @@
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('http://localhost:3000/');
await page.getByRole('button', { name: 'Neues Spiel starten' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Oscar');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Paula');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Quinn');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('button', { name: '10-Ball' }).click();
await page.getByRole('button', { name: '5' }).click();
await page.getByRole('button', { name: 'Break-Regel wählen: Winnerbreak' }).click();
await page.getByRole('button', { name: 'Zuerst: Quinn' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Quinn' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Oscar' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Paula' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Quinn' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Quinn' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Quinn' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Quinn' }).click();
await page.getByRole('button', { name: 'Bestätigen' }).click();
await page.getByRole('button', { name: 'Zurück zur Liste' }).click();
});

View File

@@ -0,0 +1,29 @@
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('http://localhost:3000/');
await page.getByRole('button', { name: 'Neues Spiel starten' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Eva');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Frank');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Grace');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('button', { name: '8-Ball' }).click();
await page.getByRole('button', { name: 'Endlos' }).click();
await page.getByRole('button', { name: 'Break-Regel wählen: Winnerbreak' }).click();
await page.getByRole('button', { name: 'Zuerst: Eva' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Eva' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Frank' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Grace' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Eva' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Frank' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Grace' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Eva' }).click();
await page.getByRole('button', { name: 'Spiel beenden' }).click();
await page.getByRole('button', { name: 'Bestätigen' }).click();
});

View File

@@ -0,0 +1,28 @@
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('http://localhost:3000/');
await page.getByRole('button', { name: 'Neues Spiel starten' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Tom');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Uma');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Victor');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('button', { name: '8-Ball' }).click();
await page.getByRole('button', { name: '3' }).click();
await page.getByRole('button', { name: 'Break-Regel wählen: Wechselbreak' }).click();
await page.getByRole('button', { name: 'Zuerst: Tom' }).click();
await page.getByRole('button', { name: 'Zweites Break: Uma' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Tom' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Uma' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Victor' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Tom' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Tom' }).click();
await page.getByRole('button', { name: 'Bestätigen' }).click();
await page.getByRole('button', { name: 'Zurück zur Liste' }).click();
});

View File

@@ -0,0 +1,33 @@
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('http://localhost:3000/');
await page.getByRole('button', { name: 'Neues Spiel starten' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Henry');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Iris');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Jack');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('button', { name: '9-Ball' }).click();
await page.getByRole('button', { name: '7' }).click();
await page.getByRole('button', { name: 'Break-Regel wählen: Wechselbreak' }).click();
await page.getByRole('button', { name: 'Zuerst: Iris' }).click();
await page.getByRole('button', { name: 'Zweites Break: Jack' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Iris' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Henry' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Jack' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Iris' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Henry' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Iris' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Iris' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Iris' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Iris' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Iris' }).click();
await page.getByRole('button', { name: 'Bestätigen' }).click();
await page.getByRole('button', { name: 'Zurück zur Liste' }).click();
});

147
tests/recordings/README.md Normal file
View File

@@ -0,0 +1,147 @@
# Playwright Recordings
This directory contains recorded browser interaction scripts for BSC Score. Use Playwright's codegen to record interactions once, then replay them anytime.
## Quick Start
### Recording Interactions
1. **Start the dev server** (in a separate terminal):
```bash
npm run dev
```
2. **Start Playwright codegen**:
```bash
npm run test:record
```
This opens:
- A browser window (use the app normally)
- Playwright Inspector (shows generated code in real-time)
3. **Interact with the app**:
- Click buttons, fill forms, navigate
- All actions are automatically captured
- Code appears in the Playwright Inspector window
4. **Save your recording**:
- Copy the generated code from the Inspector
- Create a new `.ts` file in this directory
- Paste the code and save (e.g., `create-game-basic.ts`)
### Running Recordings
Run all recordings:
```bash
npm run test:e2e
```
Run a specific recording:
```bash
npx playwright test tests/recordings/create-game-basic.ts
```
Run with UI mode (helpful for debugging):
```bash
npx playwright test --ui
```
## Naming Conventions
Use descriptive names that indicate the flow:
- `create-game-basic.ts` - Basic game creation flow
- `create-game-3players.ts` - Game creation with 3 players
- `score-update.ts` - Score update flow
- `undo-action.ts` - Undo functionality
## Duplicating & Modifying Scripts
This is the key feature! Copy any script to create a variant:
1. **Copy a script**:
```bash
cp create-game-basic.ts create-game-variant.ts
```
2. **Modify the copy**:
- Change player names
- Modify game type
- Change the last step (e.g., click 'a' instead of 'z')
- Add or remove steps
3. **Run the variant**:
```bash
npx playwright test tests/recordings/create-game-variant.ts
```
### Example Modification
```typescript
// Original: create-game-basic.ts
await page.click('button:has-text("Option Z")');
// Modified: create-game-variant.ts
await page.click('button:has-text("Option A")'); // changed from Z to A
```
## Script Structure
All recordings follow this structure:
```typescript
import { test, expect } from '@playwright/test';
test('description of what this script does', async ({ page }) => {
await page.goto('http://localhost:3000');
// Your recorded interactions here
await page.click('text=Neues Spiel');
await page.fill('input[name="player1"]', 'Alice');
// ... more steps
});
```
## Tips
- **Use the dev server**: Make sure `npm run dev` is running on port 3000 before recording or running scripts
- **Descriptive test names**: The test name helps identify what the script does
- **Comments**: Add comments in scripts to explain non-obvious steps
- **Wait for navigation**: If something doesn't work, you might need to add `await page.waitForNavigation()` or `await page.waitForSelector()`
## Common Patterns
### Fill a form field
```typescript
await page.fill('input[name="fieldName"]', 'value');
```
### Click a button
```typescript
await page.click('button:has-text("Button Text")');
```
### Wait for element
```typescript
await page.waitForSelector('text=Expected Text');
```
### Check element is visible
```typescript
await expect(page.locator('text=Some Text')).toBeVisible();
```
## Troubleshooting
**Script fails with "element not found"**:
- Add wait statements: `await page.waitForSelector('selector')`
- Check if the selector changed (use Playwright Inspector to find new selectors)
**Browser doesn't open during recording**:
- Make sure dev server is running on port 3000
- Check if port 3000 is available
**Test runs but doesn't do anything**:
- Check that baseURL in `playwright.config.ts` is correct
- Verify the app is accessible at `http://localhost:3000`

View File

@@ -0,0 +1,26 @@
import { test, expect } from '@playwright/test';
test('test', async ({ page }) => {
await page.goto('http://localhost:3000/');
await page.getByRole('button', { name: 'Neues Spiel starten' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Foo');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).click();
await page.getByRole('textbox', { name: 'Name Spieler' }).fill('Bar');
await page.getByRole('button', { name: 'Weiter' }).click();
await page.getByRole('button', { name: 'Überspringen' }).click();
await page.getByRole('button', { name: '8-Ball' }).click();
await page.getByRole('button', { name: '6' }).click();
await page.getByRole('button', { name: 'Break-Regel wählen: Wechselbreak' }).click();
await page.getByRole('button', { name: 'Zuerst: Foo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Foo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Bar' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Foo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Foo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Foo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Foo' }).click();
await page.getByRole('button', { name: 'Aktueller Punktestand für Foo' }).click();
await page.getByRole('button', { name: 'Bestätigen' }).click();
await page.getByRole('button', { name: 'Zurück zur Liste' }).click();
});