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:
26
tests/recordings/2-10-ball-endlos-wechsel.ts
Normal file
26
tests/recordings/2-10-ball-endlos-wechsel.ts
Normal 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();
|
||||
});
|
||||
|
||||
24
tests/recordings/2-10-ball-race3-wechsel.ts
Normal file
24
tests/recordings/2-10-ball-race3-wechsel.ts
Normal 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();
|
||||
});
|
||||
|
||||
29
tests/recordings/2-8-ball-race5-wechsel.ts
Normal file
29
tests/recordings/2-8-ball-race5-wechsel.ts
Normal 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();
|
||||
});
|
||||
|
||||
31
tests/recordings/2-8-ball-race9-winner.ts
Normal file
31
tests/recordings/2-8-ball-race9-winner.ts
Normal 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();
|
||||
});
|
||||
|
||||
26
tests/recordings/2-8-endlos-winner.ts
Normal file
26
tests/recordings/2-8-endlos-winner.ts
Normal 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();
|
||||
});
|
||||
21
tests/recordings/2-9-ball-race1-wechsel.ts
Normal file
21
tests/recordings/2-9-ball-race1-wechsel.ts
Normal 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();
|
||||
});
|
||||
|
||||
26
tests/recordings/2-9-ball-race5-winner.ts
Normal file
26
tests/recordings/2-9-ball-race5-winner.ts
Normal 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();
|
||||
});
|
||||
|
||||
29
tests/recordings/3-10-ball-race5-winner.ts
Normal file
29
tests/recordings/3-10-ball-race5-winner.ts
Normal 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();
|
||||
});
|
||||
|
||||
29
tests/recordings/3-8-ball-endlos-winner.ts
Normal file
29
tests/recordings/3-8-ball-endlos-winner.ts
Normal 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();
|
||||
});
|
||||
|
||||
28
tests/recordings/3-8-ball-race3-wechsel.ts
Normal file
28
tests/recordings/3-8-ball-race3-wechsel.ts
Normal 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();
|
||||
});
|
||||
|
||||
33
tests/recordings/3-9-ball-race7-wechsel.ts
Normal file
33
tests/recordings/3-9-ball-race7-wechsel.ts
Normal 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
147
tests/recordings/README.md
Normal 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`
|
||||
|
||||
26
tests/recordings/example-flow.ts
Normal file
26
tests/recordings/example-flow.ts
Normal 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();
|
||||
});
|
||||
Reference in New Issue
Block a user