Skip to content

Commit c3990db

Browse files
docs(css-isolation): update e2e guidance (#4382)
* docs(css-isolation): update e2e guidance * test(css-isolation): expand playwright host coverage * chore: regenerate pnpm lockfile
1 parent 9417a97 commit c3990db

File tree

7 files changed

+283
-247
lines changed

7 files changed

+283
-247
lines changed

css-isolation/README.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ By default the Webpack style-loader will inject CSS in `<style>` tags into the `
2929

3030
**An additional wrapping `<body>` tag is always intentionally inserted into each Shadow DOM container. This makes it possible to use global reboot CSS rules inside the remote app which usually target the `<body>` tag and its contents. This should enable the user, for example, to have two different versions of Bootstrap one in the host and one in the remote.**
3131

32-
**Testing such a setup with tools like Cypress is possible with some additional settings and tweaks. Make sure to consult with the testing tool's documentation.**
32+
**Testing such a setup with tools like Playwright is possible with some additional settings and tweaks. Make sure to consult with the testing tool's documentation for handling Shadow DOM interactions.**
3333

3434
# Running Demo
3535

@@ -40,10 +40,13 @@ Run `pnpm run start`. This will build and serve both `app1` and `app2` on ports
4040

4141
<img src="https://ssl.google-analytics.com/collect?v=1&t=event&ec=email&ea=open&t=event&tid=UA-120967034-1&z=1589682154&cid=ae045149-9d17-0367-bbb0-11c41d92b411&dt=ModuleFederationExamples&dp=/email/BasicRemoteHost">
4242

43-
# Running Cypress E2E Tests
43+
# Running Playwright E2E Tests
4444

45-
To run tests in interactive mode, run `npm run cypress:debug` from the root directory of the project. It will open Cypress Test Runner and allow to run tests in interactive mode. [More info about "How to run tests"](../../cypress-e2e/README.md#how-to-run-tests)
45+
Run `pnpm test:e2e` from this workspace to execute the Playwright end-to-end suite against the development servers configured in [`playwright.config.ts`](./playwright.config.ts).
4646

47-
To build app and run test in headless mode, run `yarn e2e:ci`. It will build app and run tests for this workspace in headless mode. If tets failed cypress will create `cypress` directory in sample root folder with screenshots and videos.
47+
For local debugging you can use the helper scripts:
4848

49-
["Best Practices, Rules amd more interesting information here](../../cypress-e2e/README.md)
49+
- `pnpm test:e2e:ui` to explore the tests in Playwright UI mode.
50+
- `pnpm test:e2e:debug` to launch the suite with Playwright's debug tools enabled.
51+
52+
In CI environments run `pnpm e2e:ci` to install the required browsers and execute the tests in headless mode. Use `pnpm legacy:e2e:ci` (or set `LEGACY_START=true`) to run the same checks against the legacy Webpack builds.

css-isolation/cypress.env.json

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

css-isolation/e2e/checkApplications.cy.ts

Lines changed: 0 additions & 128 deletions
This file was deleted.
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { test, expect } from '@playwright/test';
2+
3+
const hostUrl = 'http://localhost:3001';
4+
const remoteUrl = 'http://localhost:3002';
5+
6+
test.describe('CSS isolation example', () => {
7+
test.describe('host application', () => {
8+
test.beforeEach(async ({ page }) => {
9+
await page.goto(hostUrl);
10+
});
11+
12+
test('renders host headings', async ({ page }) => {
13+
await expect(
14+
page.getByRole('heading', { level: 1, name: /Host Application - React Version/ }),
15+
).toBeVisible();
16+
await expect(page.getByRole('heading', { level: 2, name: 'App 1' })).toBeVisible();
17+
});
18+
19+
test('mounts the remote inside a shadow DOM', async ({ page }) => {
20+
const remoteMount = page.locator('#parent');
21+
await expect(remoteMount).toBeVisible();
22+
23+
const hasShadowRoot = await remoteMount.evaluate(element => Boolean(element.shadowRoot));
24+
expect(hasShadowRoot).toBe(true);
25+
26+
const remoteHeading = remoteMount.getByRole('heading', {
27+
level: 1,
28+
name: /Remote Application - React Version/,
29+
});
30+
const remoteButton = remoteMount.getByRole('button', { name: 'Make Everything Yellow' });
31+
32+
await expect(remoteHeading).toBeVisible();
33+
await expect(remoteButton).toBeVisible();
34+
35+
await expect(
36+
page.getByRole('heading', { level: 1, name: /Host Application - React Version/ }),
37+
).toHaveCSS('font-style', 'italic');
38+
});
39+
40+
test('retains host styles after interacting with the remote', async ({ page }) => {
41+
const remoteMount = page.locator('#parent');
42+
const remoteButton = remoteMount.getByRole('button', { name: 'Make Everything Yellow' });
43+
44+
await remoteButton.click();
45+
46+
await expect(remoteButton).toBeVisible();
47+
await expect(remoteMount.getByRole('heading', { level: 2, name: 'App 2' })).toBeVisible();
48+
await expect(
49+
page.getByRole('heading', { level: 1, name: /Host Application - React Version/ }),
50+
).toHaveCSS('font-style', 'italic');
51+
});
52+
});
53+
54+
test.describe('standalone remote application', () => {
55+
test.beforeEach(async ({ page }) => {
56+
await page.goto(remoteUrl);
57+
});
58+
59+
test('renders remote headings and button', async ({ page }) => {
60+
await expect(
61+
page.getByRole('heading', { level: 1, name: /Remote Application - React Version/ }),
62+
).toBeVisible();
63+
await expect(page.getByRole('heading', { level: 2, name: 'App 2' })).toBeVisible();
64+
await expect(page.getByRole('button', { name: 'Make Everything Yellow' })).toBeVisible();
65+
});
66+
67+
test('applies yellow styles after clicking the button', async ({ page }) => {
68+
const button = page.getByRole('button', { name: 'Make Everything Yellow' });
69+
await button.click();
70+
71+
await expect(page.locator('#root')).toHaveCSS('background-color', 'rgb(255, 255, 0)');
72+
await expect(button).toHaveCSS('background-color', 'rgb(255, 255, 0)');
73+
});
74+
});
75+
});

css-isolation/package.json

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,14 @@
1010
"legacy:build": "pnpm --filter css-isolation_app* --parallel legacy:build",
1111
"serve": "pnpm --filter css-isolation_app* --parallel serve",
1212
"clean": "pnpm --filter css-isolation_app* --parallel clean",
13-
"e2e:ci": "pnpm start & wait-on http-get://localhost:3001/ && npx cypress run --config-file ../cypress-e2e/config/cypress.config.ts --config '{\"supportFile\": \"../cypress-e2e/support/e2e.ts\"}' --spec \"./e2e/*.cy.ts\" --browser=chrome",
14-
"legacy:e2e:ci": "pnpm legacy:start & wait-on http-get://localhost:3001/ && npx cypress run --config-file ../cypress-e2e/config/cypress.config.ts --config '{\"supportFile\": \"../cypress-e2e/support/e2e.ts\"}' --spec \"./e2e/*.cy.ts\" --browser=chrome"
13+
"test:e2e": "pnpm exec playwright test",
14+
"test:e2e:ui": "pnpm exec playwright test --ui",
15+
"test:e2e:debug": "pnpm exec playwright test --debug",
16+
"e2e:ci": "pnpm exec playwright install --with-deps && pnpm exec playwright test --reporter=list",
17+
"legacy:e2e:ci": "LEGACY_START=true pnpm exec playwright install --with-deps && LEGACY_START=true pnpm exec playwright test --reporter=list"
1518
},
1619
"devDependencies": {
17-
"wait-on": "7.2.0"
20+
"@playwright/test": "^1.54.2",
21+
"playwright": "^1.54.2"
1822
}
1923
}

css-isolation/playwright.config.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { defineConfig, devices } from '@playwright/test';
2+
3+
const useLegacyStart = !!process.env.LEGACY_START;
4+
const startCommand = useLegacyStart ? 'pnpm legacy:start' : 'pnpm start';
5+
6+
export default defineConfig({
7+
testDir: './e2e',
8+
timeout: 60_000,
9+
expect: {
10+
timeout: 15_000,
11+
},
12+
fullyParallel: true,
13+
forbidOnly: !!process.env.CI,
14+
retries: process.env.CI ? 1 : 0,
15+
workers: process.env.CI ? 1 : undefined,
16+
reporter: [
17+
['html', { outputFolder: 'playwright-report', open: 'never' }],
18+
['list'],
19+
],
20+
use: {
21+
baseURL: 'http://localhost:3001',
22+
trace: 'on-first-retry',
23+
screenshot: 'only-on-failure',
24+
video: 'retain-on-failure',
25+
viewport: { width: 1920, height: 1080 },
26+
},
27+
28+
projects: [
29+
{
30+
name: 'chromium',
31+
use: { ...devices['Desktop Chrome'] },
32+
},
33+
],
34+
35+
webServer: [
36+
{
37+
command: startCommand,
38+
cwd: 'app2',
39+
port: 3002,
40+
reuseExistingServer: !process.env.CI,
41+
timeout: 120_000,
42+
},
43+
{
44+
command: startCommand,
45+
cwd: 'app1',
46+
port: 3001,
47+
reuseExistingServer: !process.env.CI,
48+
timeout: 120_000,
49+
},
50+
],
51+
});

0 commit comments

Comments
 (0)