Skip to content

Commit a1896e2

Browse files
committed
test(react-router): adding playwright test structure, creating animation tests in playwright
1 parent 9621f8e commit a1896e2

File tree

15 files changed

+1204
-29
lines changed

15 files changed

+1204
-29
lines changed

.github/workflows/actions/test-react-router-e2e/action.yml

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,11 @@ runs:
2929
shell: bash
3030
working-directory: ./packages/react-router/test
3131
- name: 🕸️ Install Dependencies
32-
run: npm install
32+
run: npm install --legacy-peer-deps
33+
shell: bash
34+
working-directory: ./packages/react-router/test/build/${{ inputs.app }}
35+
- name: 📦 Install Playwright Browsers
36+
run: npx playwright install chromium
3337
shell: bash
3438
working-directory: ./packages/react-router/test/build/${{ inputs.app }}
3539
- name: 🔄 Sync Built Changes
@@ -40,7 +44,13 @@ runs:
4044
run: npm run build
4145
shell: bash
4246
working-directory: ./packages/react-router/test/build/${{ inputs.app }}
43-
- name: 🧪 Run Tests
47+
- name: 🧪 Run Cypress Tests
4448
run: npm run e2e
4549
shell: bash
4650
working-directory: ./packages/react-router/test/build/${{ inputs.app }}
51+
- name: 🎭 Run Playwright Tests
52+
run: npx playwright test --retries=2
53+
env:
54+
CI: true
55+
shell: bash
56+
working-directory: ./packages/react-router/test/build/${{ inputs.app }}

packages/react-router/scripts/test_runner.sh

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ echo "Installing dependencies..."
3434
npm install --legacy-peer-deps > npm_install.log 2>&1
3535
npm run sync
3636

37+
# Install Playwright browsers if not already present
38+
npx playwright install chromium 2>/dev/null || true
39+
3740
echo "Cleaning up port 3000..."
3841
lsof -ti:3000 | xargs kill -9 || true
3942

@@ -45,24 +48,29 @@ SERVER_PID=$!
4548
# Ensure server is killed on script exit
4649
trap "kill $SERVER_PID" EXIT
4750

48-
echo "Waiting for server to start (30s)..."
49-
sleep 30
51+
echo "Waiting for server to start..."
52+
# Poll until the server responds (up to 60s)
53+
for i in $(seq 1 60); do
54+
if curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 2>/dev/null | grep -q "200"; then
55+
echo "Server is healthy."
56+
break
57+
fi
58+
if [ "$i" -eq 60 ]; then
59+
echo "Server did not start within 60s. Exiting."
60+
cat server.log
61+
exit 1
62+
fi
63+
sleep 1
64+
done
5065

51-
echo "Checking server status..."
52-
SERVER_RESPONSE=$(curl -s -v http://localhost:3000 2>&1)
53-
if echo "$SERVER_RESPONSE" | grep -q "Child compilation failed"; then
54-
echo "Server started but has compilation errors. Exiting."
55-
echo "$SERVER_RESPONSE"
56-
exit 1
57-
fi
66+
echo "Running Cypress tests..."
67+
npm run cypress || CYPRESS_FAILED=1
5868

59-
if ! echo "$SERVER_RESPONSE" | grep -q "200 OK"; then
60-
echo "Server did not return 200 OK. Exiting."
61-
echo "$SERVER_RESPONSE"
69+
echo "Running Playwright tests..."
70+
npx playwright test --retries=2 || PLAYWRIGHT_FAILED=1
71+
72+
if [ "${CYPRESS_FAILED:-0}" = "1" ] || [ "${PLAYWRIGHT_FAILED:-0}" = "1" ]; then
73+
echo "One or more test suites failed."
6274
exit 1
6375
fi
64-
echo "Server is healthy."
65-
66-
echo "Running Cypress tests..."
67-
npm run cypress
6876

packages/react-router/test/apps/reactrouter6/package.json

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,19 @@
2121
"react-dom": "^18.2.0",
2222
"react-router": "^6.0.0",
2323
"react-router-dom": "^6.0.0",
24-
"react-scripts": "^5.0.1",
25-
"sass-loader": "8.0.2",
26-
"typescript": "^4.4.2",
27-
"wait-on": "^5.3.0"
24+
"typescript": "^4.4.2"
2825
},
2926
"scripts": {
30-
"start": "react-scripts start",
31-
"build": "react-scripts build",
27+
"dev": "vite",
28+
"start": "vite",
29+
"build": "vite build",
3230
"test": "cypress open",
3331
"cypress": "node_modules/.bin/cypress run --headless --browser chrome",
3432
"cypress.open": "cypress open",
3533
"e2e": "concurrently \"serve -s build -l 3000\" \"wait-on http-get://localhost:3000 && npm run cypress\" --kill-others --success first",
34+
"playwright": "npx playwright test",
35+
"playwright.open": "npx playwright test --ui",
36+
"playwright.headed": "npx playwright test --headed",
3637
"sync": "sh ./scripts/sync.sh"
3738
},
3839
"eslintConfig": {
@@ -54,12 +55,14 @@
5455
]
5556
},
5657
"devDependencies": {
58+
"@playwright/test": "^1.40.0",
59+
"@vitejs/plugin-react": "^4.0.0",
5760
"concurrently": "^6.3.0",
5861
"cypress": "^13.2.0",
5962
"cypress-terminal-report": "^5.3.0",
6063
"serve": "^14.0.1",
61-
"wait-on": "^6.0.0",
62-
"webpack-cli": "^4.9.1"
64+
"vite": "^5.0.0",
65+
"wait-on": "^6.0.0"
6366
},
6467
"description": "An Ionic project",
6568
"engines": {
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import react from '@vitejs/plugin-react';
2+
import { defineConfig } from 'vite';
3+
4+
export default defineConfig({
5+
plugins: [react()],
6+
server: {
7+
port: 3000,
8+
},
9+
});

packages/react-router/test/base/public/index.html renamed to packages/react-router/test/base/index.html

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
<meta name="format-detection" content="telephone=no" />
1515
<meta name="msapplication-tap-highlight" content="no" />
1616

17-
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
17+
<link rel="manifest" href="/manifest.json" />
1818

19-
<link rel="shortcut icon" type="image/png" href="%PUBLIC_URL%/assets/icon/favicon.png" />
19+
<link rel="shortcut icon" type="image/png" href="/assets/icon/favicon.png" />
2020

2121
<!-- add to homescreen for ios -->
2222
<meta name="apple-mobile-web-app-capable" content="yes" />
@@ -26,5 +26,6 @@
2626

2727
<body>
2828
<div id="root"></div>
29+
<script type="module" src="/src/index.tsx"></script>
2930
</body>
3031
</html>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { defineConfig, devices } from '@playwright/test';
2+
3+
export default defineConfig({
4+
testDir: './tests/e2e/playwright',
5+
fullyParallel: false,
6+
forbidOnly: !!process.env['CI'],
7+
retries: process.env['CI'] ? 2 : 0,
8+
workers: 1,
9+
reporter: 'html',
10+
use: {
11+
baseURL: 'http://localhost:3000',
12+
trace: 'on-first-retry',
13+
actionTimeout: 5000,
14+
},
15+
projects: [
16+
{
17+
name: 'Mobile Chrome',
18+
use: {
19+
browserName: 'chromium',
20+
...devices['Pixel 5'],
21+
},
22+
},
23+
],
24+
webServer: {
25+
command: 'npm run dev',
26+
url: 'http://localhost:3000',
27+
// Always reuse an existing server. In the test_runner.sh pipeline, the
28+
// server is started before Cypress and stays running for Playwright.
29+
// Locally, developers can start the server manually with `npm run dev`.
30+
reuseExistingServer: true,
31+
},
32+
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { test, expect } from '@playwright/test';
2+
import { withTestingMode } from './utils/test-utils';
3+
4+
test.describe('Overlays', () => {
5+
test('should remove the overlay when going back to the previous route', async ({ page }) => {
6+
// Requires navigation history to perform a pop
7+
await page.goto(withTestingMode('/'));
8+
await page.goto(withTestingMode('/overlays'));
9+
10+
await page.locator('#openModal').click();
11+
12+
await expect(page.locator('ion-modal')).toBeAttached();
13+
14+
await page.locator('#goBack').click();
15+
16+
await expect(page.locator('ion-modal')).not.toBeAttached();
17+
});
18+
19+
test('should remove the overlay when pushing to a new route', async ({ page }) => {
20+
await page.goto(withTestingMode('/overlays'));
21+
22+
await page.locator('#openModal').click();
23+
24+
await expect(page.locator('ion-modal')).toBeAttached();
25+
26+
await page.locator('#push').click();
27+
28+
await expect(page.locator('ion-modal')).not.toBeAttached();
29+
});
30+
31+
test('should remove the overlay when replacing the route', async ({ page }) => {
32+
await page.goto(withTestingMode('/overlays'));
33+
34+
await page.locator('#openModal').click();
35+
36+
await expect(page.locator('ion-modal')).toBeAttached();
37+
38+
await page.locator('#replace').click();
39+
40+
await expect(page.locator('ion-modal')).not.toBeAttached();
41+
});
42+
});

0 commit comments

Comments
 (0)