Skip to content

Commit b7fef3a

Browse files
committed
test: add Playwright integration testing framework
Add Playwright for end-to-end testing of demos to validate worker thread communication and ensemble.json configuration work correctly. Setup includes: - Playwright configuration with separate projects per demo - Test scripts in root package.json (test:e2e, test:e2e:ui, etc.) - Comprehensive counter demo tests covering: - Basic UI functionality (increment/decrement/reset) - Worker thread communication - Rapid click stress testing - Complex operation sequences - State consistency validation Tests validate the recent @thread to ensemble.json refactoring works correctly in real browser environments.
1 parent 3180d9a commit b7fef3a

File tree

4 files changed

+476
-3
lines changed

4 files changed

+476
-3
lines changed

e2e/counter-react.spec.ts

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
import { test, expect } from '@playwright/test';
2+
3+
/**
4+
* Counter Demo Integration Tests
5+
*
6+
* These tests validate the React counter demo works correctly with:
7+
* - Actor system initialization
8+
* - Worker thread communication (CounterActor runs in worker thread)
9+
* - State updates and UI reactivity
10+
* - ensemble.json configuration
11+
*/
12+
13+
test.describe('Counter React Demo', () => {
14+
test('should load the counter demo page', async ({ page }) => {
15+
await page.goto('/');
16+
17+
// Verify the title is present
18+
await expect(page.locator('h1')).toHaveText('Ensemble Counter Demo');
19+
20+
// Verify the counter card is present
21+
await expect(page.locator('.counter-card')).toBeVisible();
22+
});
23+
24+
test('should display initial counter value', async ({ page }) => {
25+
await page.goto('/');
26+
27+
// Verify counter starts at 0
28+
await expect(page.locator('.counter-value')).toHaveText('Counter: 0');
29+
});
30+
31+
test('should increment counter when clicking increment button', async ({ page }) => {
32+
await page.goto('/');
33+
34+
// Click increment button
35+
await page.getByRole('button', { name: 'Increment' }).click();
36+
37+
// Verify counter increased to 1
38+
await expect(page.locator('.counter-value')).toHaveText('Counter: 1');
39+
40+
// Click again
41+
await page.getByRole('button', { name: 'Increment' }).click();
42+
43+
// Verify counter increased to 2
44+
await expect(page.locator('.counter-value')).toHaveText('Counter: 2');
45+
});
46+
47+
test('should decrement counter when clicking decrement button', async ({ page }) => {
48+
await page.goto('/');
49+
50+
// Start by incrementing to 5
51+
const incrementBtn = page.getByRole('button', { name: 'Increment' });
52+
for (let i = 0; i < 5; i++) {
53+
await incrementBtn.click();
54+
}
55+
await expect(page.locator('.counter-value')).toHaveText('Counter: 5');
56+
57+
// Click decrement button
58+
await page.getByRole('button', { name: 'Decrement' }).click();
59+
60+
// Verify counter decreased to 4
61+
await expect(page.locator('.counter-value')).toHaveText('Counter: 4');
62+
63+
// Click again
64+
await page.getByRole('button', { name: 'Decrement' }).click();
65+
66+
// Verify counter decreased to 3
67+
await expect(page.locator('.counter-value')).toHaveText('Counter: 3');
68+
});
69+
70+
test('should reset counter to 0 when clicking reset button', async ({ page }) => {
71+
await page.goto('/');
72+
73+
// Increment counter several times
74+
const incrementBtn = page.getByRole('button', { name: 'Increment' });
75+
for (let i = 0; i < 10; i++) {
76+
await incrementBtn.click();
77+
}
78+
await expect(page.locator('.counter-value')).toHaveText('Counter: 10');
79+
80+
// Click reset button
81+
await page.getByRole('button', { name: 'Reset' }).click();
82+
83+
// Verify counter is back to 0
84+
await expect(page.locator('.counter-value')).toHaveText('Counter: 0');
85+
});
86+
87+
test('should handle rapid clicks correctly', async ({ page }) => {
88+
await page.goto('/');
89+
90+
// Rapidly click increment button multiple times
91+
const incrementBtn = page.getByRole('button', { name: 'Increment' });
92+
93+
// Click 20 times in quick succession
94+
const clickPromises = [];
95+
for (let i = 0; i < 20; i++) {
96+
clickPromises.push(incrementBtn.click());
97+
}
98+
await Promise.all(clickPromises);
99+
100+
// Wait a bit for all state updates to propagate from worker thread
101+
await page.waitForTimeout(100);
102+
103+
// Verify counter is at 20 (worker thread handled all messages)
104+
await expect(page.locator('.counter-value')).toHaveText('Counter: 20');
105+
});
106+
107+
test('should maintain counter state through multiple operations', async ({ page }) => {
108+
await page.goto('/');
109+
110+
const incrementBtn = page.getByRole('button', { name: 'Increment' });
111+
const decrementBtn = page.getByRole('button', { name: 'Decrement' });
112+
const resetBtn = page.getByRole('button', { name: 'Reset' });
113+
114+
// Complex sequence of operations
115+
await incrementBtn.click();
116+
await incrementBtn.click();
117+
await incrementBtn.click();
118+
await expect(page.locator('.counter-value')).toHaveText('Counter: 3');
119+
120+
await decrementBtn.click();
121+
await expect(page.locator('.counter-value')).toHaveText('Counter: 2');
122+
123+
await incrementBtn.click();
124+
await incrementBtn.click();
125+
await expect(page.locator('.counter-value')).toHaveText('Counter: 4');
126+
127+
await resetBtn.click();
128+
await expect(page.locator('.counter-value')).toHaveText('Counter: 0');
129+
130+
await decrementBtn.click();
131+
await expect(page.locator('.counter-value')).toHaveText('Counter: -1');
132+
});
133+
134+
test('should have all three buttons visible and enabled', async ({ page }) => {
135+
await page.goto('/');
136+
137+
const incrementBtn = page.getByRole('button', { name: 'Increment' });
138+
const decrementBtn = page.getByRole('button', { name: 'Decrement' });
139+
const resetBtn = page.getByRole('button', { name: 'Reset' });
140+
141+
// Verify all buttons are visible
142+
await expect(incrementBtn).toBeVisible();
143+
await expect(decrementBtn).toBeVisible();
144+
await expect(resetBtn).toBeVisible();
145+
146+
// Verify all buttons are enabled
147+
await expect(incrementBtn).toBeEnabled();
148+
await expect(decrementBtn).toBeEnabled();
149+
await expect(resetBtn).toBeEnabled();
150+
});
151+
});

0 commit comments

Comments
 (0)