Skip to content

Commit a178a54

Browse files
Merge branch 'federation' into json-manifest
2 parents 99eace5 + b4f11c1 commit a178a54

32 files changed

+2968
-21452
lines changed

.github/workflows/e2e-tests.yml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
name: E2E Tests
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
e2e-tests:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Setup Node.js
17+
uses: actions/setup-node@v4
18+
with:
19+
node-version-file: '.nvmrc'
20+
21+
- name: Setup pnpm
22+
uses: pnpm/action-setup@v2
23+
with:
24+
version: 9.15.3
25+
run_install: false
26+
27+
- name: Get pnpm store directory
28+
id: pnpm-cache
29+
shell: bash
30+
run: |
31+
echo "STORE_PATH=$(pnpm store path)" >> $GITHUB_OUTPUT
32+
33+
- uses: actions/cache@v3
34+
name: Setup pnpm cache
35+
with:
36+
path: ${{ steps.pnpm-cache.outputs.STORE_PATH }}
37+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
38+
restore-keys: |
39+
${{ runner.os }}-pnpm-store-
40+
41+
- name: Install dependencies
42+
run: pnpm install
43+
44+
- name: Install Playwright browsers
45+
run: npx playwright install --with-deps chromium
46+
47+
- name: Run E2E tests
48+
run: pnpm e2e

.prettierignore

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Build artifacts
2+
dist/
3+
node_modules/
4+
.git/
5+
.vscode/
6+
.idea/
7+
8+
# Examples directory (not our focus)
9+
examples/
10+
11+
# Test files (only focusing on src)
12+
tests/
13+
14+
# Coverage reports
15+
coverage/
16+
17+
# Lock files
18+
pnpm-lock.yaml
19+
package-lock.json
20+
yarn.lock

.prettierrc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"semi": true,
3+
"singleQuote": true,
4+
"tabWidth": 2,
5+
"trailingComma": "es5",
6+
"printWidth": 80,
7+
"arrowParens": "avoid",
8+
"endOfLine": "lf"
9+
}

examples/cloudflare/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@
1010
"typecheck": "tsc -b"
1111
},
1212
"dependencies": {
13-
"@react-router/node": "^7.3.0",
14-
"@react-router/serve": "^7.3.0",
13+
"@react-router/node": "^7.4.0",
14+
"@react-router/serve": "^7.4.0",
1515
"isbot": "^5.1.17",
1616
"react": "^19.0.0",
1717
"react-dom": "^19.0.0",
18-
"react-router": "7.3.0"
18+
"react-router": "^7.4.0"
1919
},
2020
"devDependencies": {
2121
"@cloudflare/workers-types": "^4.20241112.0",
22-
"@react-router/cloudflare": "^7.3.0",
23-
"@react-router/dev": "^7.3.0",
22+
"@react-router/cloudflare": "^7.4.0",
23+
"@react-router/dev": "^7.4.0",
2424
"@rsbuild/core": "^1.2.19",
2525
"@rsbuild/plugin-react": "^1.1.1",
2626
"@rsbuild/plugin-react-router": "workspace:*",

examples/custom-node-server/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,16 @@
1414
"author": "",
1515
"license": "ISC",
1616
"dependencies": {
17-
"@react-router/express": "^7.3.0",
18-
"@react-router/node": "^7.3.0",
17+
"@react-router/express": "^7.4.0",
18+
"@react-router/node": "^7.4.0",
1919
"express": "^4.21.2",
2020
"isbot": "^5.1.22",
2121
"react": "^19.0.0",
2222
"react-dom": "^19.0.0",
23-
"react-router": "7.3.0"
23+
"react-router": "^7.4.0"
2424
},
2525
"devDependencies": {
26-
"@react-router/dev": "^7.3.0",
26+
"@react-router/dev": "^7.4.0",
2727
"@rsbuild/core": "^1.2.19",
2828
"@rsbuild/plugin-react": "^1.1.1",
2929
"@rsbuild/plugin-react-router": "workspace:*",

examples/default-template/package.json

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,23 @@
66
"build": "rsbuild build",
77
"dev": "rsbuild dev",
88
"start": "react-router-serve ./build/server/index.js",
9-
"typecheck": "react-router typegen && tsc"
9+
"typecheck": "react-router typegen && tsc",
10+
"test:e2e": "pnpm run dev & sleep 5 && playwright test",
11+
"test:e2e:debug": "playwright test --debug",
12+
"test:e2e:ui": "playwright test --ui"
1013
},
1114
"dependencies": {
12-
"@react-router/express": "^7.3.0",
13-
"@react-router/node": "^7.3.0",
14-
"@react-router/serve": "^7.3.0",
15+
"@react-router/express": "^7.4.0",
16+
"@react-router/node": "^7.4.0",
17+
"@react-router/serve": "^7.4.0",
1518
"isbot": "^5.1.17",
1619
"react": "^19.0.0",
1720
"react-dom": "^19.0.0",
18-
"react-router": "7.3.0"
21+
"react-router": "^7.4.0"
1922
},
2023
"devDependencies": {
21-
"@react-router/dev": "^7.3.0",
24+
"@playwright/test": "^1.50.1",
25+
"@react-router/dev": "^7.4.0",
2226
"@rsbuild/core": "^1.2.19",
2327
"@rsbuild/plugin-react": "^1.1.1",
2428
"@rsbuild/plugin-react-router": "workspace:*",
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { defineConfig, devices } from '@playwright/test';
2+
3+
export default defineConfig({
4+
testDir: './tests/e2e',
5+
// Maximum time one test can run for
6+
timeout: 30 * 1000,
7+
expect: {
8+
timeout: 5000
9+
},
10+
// Run tests in files in parallel
11+
fullyParallel: false,
12+
// Fail the build on CI if you accidentally left test.only in the source code
13+
forbidOnly: !!process.env.CI,
14+
// Retry on CI only
15+
retries: process.env.CI ? 2 : 0,
16+
17+
// Shared settings for all the projects below
18+
use: {
19+
// Base URL to use in actions like `await page.goto('/')`
20+
baseURL: 'http://localhost:3000',
21+
22+
// Collect trace when retrying the failed test
23+
trace: 'on-first-retry',
24+
25+
// Take screenshot on test failure
26+
screenshot: 'only-on-failure',
27+
},
28+
29+
// Configure only Chrome desktop browser
30+
projects: [
31+
{
32+
name: 'chromium',
33+
use: { ...devices['Desktop Chrome'] },
34+
},
35+
]
36+
});

examples/default-template/rsbuild.config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { defineConfig } from '@rsbuild/core';
22
import { pluginReact } from '@rsbuild/plugin-react';
33
import { pluginReactRouter } from '@rsbuild/plugin-react-router';
44
import 'react-router';
5-
5+
import path from 'path';
66
declare module 'react-router' {
77
interface AppLoadContext {
88
VALUE_FROM_EXPRESS: string;
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# End-to-End Tests
2+
3+
This directory contains end-to-end tests for the React Router default template application using Playwright.
4+
5+
## Test Structure
6+
7+
The tests are organized by feature area:
8+
9+
- `home.test.ts` - Tests for the home page and welcome component
10+
- `about.test.ts` - Tests for the about page
11+
- `docs.test.ts` - Tests for the docs section with nested routes
12+
- `projects.test.ts` - Tests for the projects section with dynamic routes
13+
- `navigation.test.ts` - General navigation flows across the application
14+
15+
## Running Tests
16+
17+
You can run the tests using the following npm scripts:
18+
19+
```bash
20+
# Run all tests
21+
npm run test:e2e
22+
23+
# Run tests with the Playwright UI
24+
npm run test:e2e:ui
25+
26+
# Run tests in debug mode
27+
npm run test:e2e:debug
28+
```
29+
30+
## Test Configuration
31+
32+
Test configuration is defined in `playwright.config.ts` in the project root. The configuration:
33+
34+
- Runs tests in the `tests/e2e` directory
35+
- Tests across multiple browsers (Chrome, Firefox, Safari)
36+
- Tests across desktop and mobile viewports
37+
- Automatically starts the development server before running tests
38+
- Takes screenshots on test failures
39+
- Generates HTML reports
40+
41+
## Adding New Tests
42+
43+
To add new tests:
44+
45+
1. Create a new file in the `tests/e2e` directory with the `.test.ts` extension
46+
2. Import the required Playwright utilities:
47+
```typescript
48+
import { test, expect } from '@playwright/test';
49+
```
50+
3. Write your tests using the Playwright API
51+
4. Run your tests with `npm run test:e2e`
52+
53+
## Generating Base Screenshots
54+
55+
If you need to generate baseline screenshots for visual comparison:
56+
57+
```bash
58+
npx playwright test --update-snapshots
59+
```
60+
61+
## CI Integration
62+
63+
These tests can be integrated into CI pipelines. The configuration includes special settings for CI environments:
64+
65+
- More retries on CI
66+
- Forbidding `.only` tests on CI
67+
- Not reusing existing servers on CI
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { test, expect } from '@playwright/test';
2+
3+
test.describe('About Page', () => {
4+
test('should display about page content and team members', async ({ page }) => {
5+
// Navigate to about page
6+
await page.goto('/about');
7+
8+
// Check page heading
9+
const heading = page.locator('h1:has-text("About This Demo")');
10+
await expect(heading).toBeVisible();
11+
12+
// Check team member cards
13+
const teamCards = page.locator('.card');
14+
await expect(teamCards).toHaveCount(3);
15+
16+
// Verify each team member
17+
const expectedMembers = ['React Router', 'Tailwind CSS', 'TypeScript'];
18+
for (let i = 0; i < expectedMembers.length; i++) {
19+
const memberName = expectedMembers[i];
20+
await expect(teamCards.nth(i).locator('h2')).toContainText(memberName);
21+
}
22+
23+
// Check that back to home link works
24+
const backLink = page.locator('a:has-text("← Back to Home")');
25+
await expect(backLink).toBeVisible();
26+
await backLink.click();
27+
28+
// Verify navigation back to home page
29+
await expect(page).toHaveURL(/\/$/);
30+
await expect(page.locator('h1:has-text("Welcome to React Router")')).toBeVisible();
31+
});
32+
33+
test('should have working external links', async ({ page }) => {
34+
// Navigate to about page
35+
await page.goto('/about');
36+
37+
// Get all external links
38+
const externalLinks = page.locator('.card a[target="_blank"]');
39+
40+
// Verify each link has correct attributes
41+
for (const link of await externalLinks.all()) {
42+
await expect(link).toHaveAttribute('rel', 'noopener noreferrer');
43+
await expect(link).toHaveText('Learn more →');
44+
}
45+
});
46+
});

0 commit comments

Comments
 (0)