Skip to content

Commit 4cb24b2

Browse files
committed
reworking examples
1 parent 85ad223 commit 4cb24b2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1349
-426
lines changed

.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
GLOBAL_LOCK_TIMEOUT=2

Taskfile.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ tasks:
44
test:
55
desc: Runs all tests
66
cmds:
7-
- docker run --rm -v $(pwd):/app -v /var/run/docker.sock:/var/run/docker.sock airlock php vendor/bin/phpunit --display-phpunit-notices --testdox
7+
- docker compose exec php vendor/bin/phpunit --display-phpunit-notices --testdox
88

99
phpstan:
1010
desc: Runs PHPStan

compose.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@ services:
1212
environment:
1313
REDIS_HOST: redis
1414
REDIS_PORT: 6379
15-
SERVER_ROOT: /app
15+
SERVER_ROOT: /app/examples/public
16+
env_file:
17+
- .env
1618
tty: true
1719
depends_on:
1820
- redis
@@ -29,9 +31,11 @@ services:
2931
environment:
3032
REDIS_HOST: redis
3133
REDIS_PORT: 6379
34+
env_file:
35+
- .env
3236
depends_on:
3337
- redis
34-
command: php examples/worker.php
38+
command: php examples/bin/console app:worker
3539

3640
redis:
3741
image: redis:8.4.0
@@ -47,6 +51,8 @@ services:
4751
- ./e2e:/app/e2e
4852
environment:
4953
BASE_URL: http://php
54+
env_file:
55+
- .env
5056
depends_on:
5157
- worker
5258
- redis

composer.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"ext-memcached": "*",
2828
"ext-zookeeper": "*",
2929
"amphp/sync": "^2.3",
30+
"clue/framework-x": "^0.17",
3031
"illuminate/cache": "^12.47",
3132
"phpstan/phpstan": "^2.1",
3233
"phpunit/phpunit": "12.5.4",
@@ -41,8 +42,7 @@
4142
"symfony/lock": "^8.0",
4243
"symfony/mercure": "^0.7.2",
4344
"symfony/rate-limiter": "^8.0",
44-
"symfony/semaphore": "^8.0",
45-
"testcontainers/testcontainers": "^1.0"
45+
"symfony/semaphore": "^8.0"
4646
},
4747
"suggest": {
4848
"symfony/lock": "Recommended Lock implementation",

e2e/package-lock.json

Lines changed: 19 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

e2e/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"test:debug": "playwright test --debug"
99
},
1010
"devDependencies": {
11-
"@playwright/test": "^1.50.0"
11+
"@playwright/test": "^1.50.0",
12+
"@types/node": "^25.0.9"
1213
}
13-
}
14+
}

e2e/tests/01-lock.spec.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
1-
import { test, expect } from '@playwright/test';
1+
import {test, expect} from '@playwright/test';
22

3-
const EXAMPLE = '01-lock';
43
const BASE_URL = process.env.BASE_URL || 'http://localhost';
54

6-
test.describe.serial('01-lock - Double-Click Protection', () => {
7-
test.beforeEach(async ({ request }) => {
5+
test.describe.serial('01-global-lock - Double-Click Protection', () => {
6+
test.beforeEach(async ({request}) => {
87
// Clear all Redis keys for this example
9-
const response = await request.get(`${BASE_URL}/examples/reset.php?example=${EXAMPLE}`);
8+
const response = await request.get(`${BASE_URL}/reset`);
109
console.log('Reset response:', await response.json());
1110
});
1211

13-
test('should display initial state correctly', async ({ page }) => {
14-
await page.goto('/examples/01-lock/');
12+
test('should display initial state correctly', async ({page}) => {
13+
await page.goto('/global-lock/');
1514

1615
await expect(page.locator('h1')).toHaveText('Airlock: Double-Click Protection');
1716
await expect(page.locator('#go')).toBeEnabled();
1817
await expect(page.locator('#status')).toBeEmpty();
1918
});
2019

21-
test('should process action and show done state', async ({ page }) => {
22-
await page.goto('/examples/01-lock/');
20+
test('should process action and show done state', async ({page}) => {
21+
await page.goto('/global-lock/');
2322

2423
await page.locator('#go').click();
2524

@@ -28,12 +27,12 @@ test.describe.serial('01-lock - Double-Click Protection', () => {
2827
await expect(page.locator('#status')).toHaveClass(/wait/);
2928

3029
// Wait for completion (5s work + buffer)
31-
await expect(page.locator('#status')).toContainText('Done', { timeout: 10000 });
30+
await expect(page.locator('#status')).toContainText('Done', {timeout: 4000});
3231
await expect(page.locator('#status')).toHaveClass(/ok/);
3332
});
3433

35-
test('should block double-click with instant rejection', async ({ page }) => {
36-
await page.goto('/examples/01-lock/');
34+
test('should block double-click with instant rejection', async ({page}) => {
35+
await page.goto('/global-lock/');
3736

3837
// First click - starts processing
3938
await page.locator('#go').click();
@@ -45,7 +44,7 @@ test.describe.serial('01-lock - Double-Click Protection', () => {
4544
await expect(page.locator('#status')).toHaveClass(/error/);
4645
});
4746

48-
test('second user should be blocked when lock is held', async ({ browser }) => {
47+
test('second user should be blocked when lock is held', async ({browser}) => {
4948
// Create two browser contexts (simulating two users)
5049
const context1 = await browser.newContext();
5150
const context2 = await browser.newContext();
@@ -54,18 +53,18 @@ test.describe.serial('01-lock - Double-Click Protection', () => {
5453

5554
try {
5655
// First user starts action
57-
await page1.goto('/examples/01-lock/');
56+
await page1.goto('/global-lock/');
5857
await page1.locator('#go').click();
5958
await expect(page1.locator('#status')).toContainText('Submitting');
6059

6160
// Second user tries to start - should be instantly blocked
62-
await page2.goto('/examples/01-lock/');
61+
await page2.goto('/global-lock/');
6362
await page2.locator('#go').click();
6463
await expect(page2.locator('#status')).toContainText('Already processing');
6564
await expect(page2.locator('#status')).toHaveClass(/error/);
6665

6766
// Wait for first user to complete
68-
await expect(page1.locator('#status')).toContainText('Done', { timeout: 10000 });
67+
await expect(page1.locator('#status')).toContainText('Done', {timeout: 5000});
6968

7069
// Second user can now start
7170
await page2.locator('#go').click();

e2e/tsconfig.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2020",
4+
"lib": ["ES2020", "DOM"],
5+
"module": "CommonJS",
6+
"moduleResolution": "node",
7+
"types": ["node", "@playwright/test"],
8+
"strict": true,
9+
"skipLibCheck": true
10+
}
11+
}

examples/.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Symfony cache
2+
var/cache/
3+
4+
# Composer dependencies
5+
vendor/
6+
composer.lock
7+
8+
# IDE
9+
/.idea
10+
11+
/config/reference.php

examples/01-lock/index.html

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)