diff --git a/comprehensive-demo-react18/README.md b/comprehensive-demo-react18/README.md
index a4fa3a294b1..87aae5716be 100644
--- a/comprehensive-demo-react18/README.md
+++ b/comprehensive-demo-react18/README.md
@@ -18,10 +18,10 @@ Included apps:
- App #5 (LitElement): [http://localhost:3005](http://localhost:3005)
-# Running Cypress E2E Tests
+# Running Playwright E2E Tests
-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)
+To run the Playwright test suite locally in headless mode, execute `pnpm test:e2e` from this workspace. The tests automatically start the demo and verify each application.
-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.
+For an interactive UI to debug or explore tests, run `pnpm test:e2e:ui`.
-["Best Practices, Rules amd more interesting information here](../../cypress-e2e/README.md)
+In CI scenarios run `pnpm e2e:ci`. This command builds the applications, installs the required Playwright browsers and runs the tests with a concise reporter.
diff --git a/comprehensive-demo-react18/e2e/checkApp1.spec.ts b/comprehensive-demo-react18/e2e/checkApp1.spec.ts
new file mode 100644
index 00000000000..d25051560e7
--- /dev/null
+++ b/comprehensive-demo-react18/e2e/checkApp1.spec.ts
@@ -0,0 +1,190 @@
+import { test, expect } from '@playwright/test';
+import type { Page } from '@playwright/test';
+
+const base = 'http://localhost:3001';
+
+const demoPages = [
+ { name: 'Main', hash: '#/' },
+ { name: 'UI Library', hash: '#/ui-library' },
+ { name: 'Dialog', hash: '#/dialog' },
+ { name: 'Svelte Page', hash: '#/svelte' },
+ { name: 'Routing', hash: '#/routing/foo' },
+];
+
+const appLinks = [
+ { name: 'App #1', href: 'http://localhost:3001' },
+ { name: 'App #2', href: 'http://localhost:3002' },
+ { name: 'App #3', href: 'http://localhost:3003' },
+ { name: 'App #4', href: 'http://localhost:3004' },
+ { name: 'App #5', href: 'http://localhost:3005' },
+];
+
+const mainPageParagraphs = [
+ 'Welcome to the Module Federation Demo!',
+ 'Click any of the items on the left to get started.',
+ 'Feel free to leave me feedback',
+];
+
+const uiLibraryParagraphs = [
+ 'Simple example showing host app and external component using separate CSS solutions.',
+ 'This Button component can be found in App #3.',
+ 'This button is also used in the routing demo.',
+];
+
+const routingParagraphs = [
+ 'The following tab components are being imported remotely from "bravo-app".',
+ "Notice that your browser's route is /routing/ depending on which tab is active.",
+ 'If you open http://localhost:3002 you will see the same tab components at the root level',
+ 'The "Bar" tab also lazily renders the styled-component Button from the UI Library demo only when rendered.',
+];
+
+const expectAppBar = async (page: Page, title: string) => {
+ const appBar = page.locator('header').first();
+ await expect(appBar).toBeVisible();
+ await expect(appBar).toHaveCSS('background-color', 'rgb(63, 81, 181)');
+ await expect(page.getByRole('heading', { name: title })).toBeVisible();
+};
+
+test.describe('Comprehensive Demo App1', () => {
+ test('main page displays sidebar links and elements', async ({ page }) => {
+ await page.goto(base);
+
+ await expect(page.getByRole('heading', { name: 'SideNav' })).toBeVisible();
+ await expect(page.getByText('Demo Pages')).toBeVisible();
+ await expect(page.getByText('Apps')).toBeVisible();
+
+ for (const { name, hash } of demoPages) {
+ const link = page.locator('a', { hasText: name }).first();
+ await expect(link).toBeVisible();
+ await expect(link).toHaveAttribute('href', hash);
+ }
+
+ for (const { name, href } of appLinks) {
+ const link = page.locator(`a[href="${href}"]`).first();
+ await expect(link).toBeVisible();
+ await expect(link).toHaveAttribute('href', href);
+ await expect(link).toContainText(name);
+ await expect(link).toContainText(href);
+ }
+
+ await expectAppBar(page, 'Module Federation Demo');
+
+ const alert = page.locator('.alert');
+ await expect(alert).toBeVisible();
+ await expect(alert).toHaveText(/Alert from LitElement/);
+ await expect(page.locator('.closebtn')).toBeVisible();
+
+ for (const paragraph of mainPageParagraphs) {
+ await expect(page.locator('p', { hasText: paragraph })).toBeVisible();
+ }
+
+ await expect(
+ page.getByRole('link', { name: 'https://github.com/module-federation/mfe-webpack-demo' }),
+ ).toHaveAttribute('href', 'https://github.com/module-federation/mfe-webpack-demo');
+
+ const actionButton = page.locator('action-button button');
+ await expect(actionButton).toHaveText('Lit Element Action');
+ await expect(actionButton).toHaveCSS('background-color', 'rgb(219, 112, 147)');
+ });
+
+ test('main tab functionality', async ({ page }) => {
+ await page.goto(base);
+
+ page.once('dialog', async dialog => {
+ expect(dialog.message()).toBe('You have pressed a button.');
+ await dialog.accept();
+ });
+
+ await page.locator('action-button button').click();
+ await page.locator('.closebtn').click();
+ await expect(page.locator('.alert')).toBeHidden();
+
+ for (const { name, hash } of demoPages) {
+ await page.locator('a', { hasText: name }).first().click();
+ await expect(page).toHaveURL(`${base}/${hash}`);
+ }
+
+ await page.locator('a', { hasText: 'Main' }).first().click();
+ await expect(page).toHaveURL(`${base}/#/`);
+
+ for (const { href } of appLinks) {
+ const response = await page.request.get(href);
+ expect(response.ok()).toBeTruthy();
+ }
+ });
+
+ test('UI library page renders remote button', async ({ page }) => {
+ await page.goto(`${base}/#/ui-library`);
+
+ await expectAppBar(page, 'UI Library Demo');
+
+ for (const paragraph of uiLibraryParagraphs) {
+ await expect(page.locator('p', { hasText: paragraph })).toBeVisible();
+ }
+
+ await expect(page.locator('a[href="http://localhost:3003/"]').first()).toHaveAttribute(
+ 'href',
+ 'http://localhost:3003/',
+ );
+ await expect(page.locator('a[href="http://localhost:3001/#/routing/foo"]').first()).toHaveAttribute(
+ 'href',
+ 'http://localhost:3001/#/routing/foo',
+ );
+
+ const styledButton = page.getByRole('button', { name: '💅 Button' });
+ await expect(styledButton).toBeVisible();
+ await expect(styledButton).toHaveCSS('background-color', 'rgb(219, 112, 147)');
+ });
+
+ test('dialog page loads and dialog opens', async ({ page }) => {
+ await page.goto(`${base}/#/dialog`);
+
+ await expectAppBar(page, 'Dialog Demo');
+ await expect(
+ page.locator('p', {
+ hasText:
+ 'Clicking the button below will render a Dialog using React Portal. This dialog component is being lazy loaded from the app #2.',
+ }),
+ ).toBeVisible();
+
+ await page.getByRole('button', { name: 'Open Dialog' }).click();
+ const dialog = page.locator('[role="dialog"]');
+ await expect(dialog.getByRole('heading', { name: 'Dialog Example' })).toBeVisible();
+ await expect(
+ dialog.getByText('This is a dialog from the Material UI app rendered in a React Portal.'),
+ ).toBeVisible();
+ await dialog.getByRole('button', { name: 'Nice' }).click();
+ await expect(dialog).not.toBeVisible();
+ });
+
+ test('svelte page updates greeting', async ({ page }) => {
+ await page.goto(`${base}/#/svelte`);
+
+ await expectAppBar(page, 'Svelte Demo');
+
+ const input = page.locator('input');
+ await expect(input).toBeVisible();
+ await input.fill('May The Force Be With You');
+ await expect(page.locator('h1')).toHaveText('Hello From Svelte May The Force Be With You!');
+ });
+
+ test('routing page renders tabs', async ({ page }) => {
+ await page.goto(`${base}/#/routing/foo`);
+
+ await expectAppBar(page, 'Routing Demo');
+
+ for (const paragraph of routingParagraphs) {
+ await expect(page.locator('p', { hasText: paragraph })).toBeVisible();
+ }
+
+ await expect(page.getByRole('tab', { name: 'Foo' })).toBeVisible();
+ await expect(page.getByText('Foo Content')).toBeVisible();
+
+ await page.getByRole('tab', { name: 'Bar' }).click();
+ await expect(page.getByText('Bar Content')).toBeVisible();
+
+ const barButton = page.getByRole('button', { name: 'Bar Button' });
+ await expect(barButton).toBeVisible();
+ await expect(barButton).toHaveCSS('background-color', 'rgb(219, 112, 147)');
+ });
+});
diff --git a/comprehensive-demo-react18/e2e/checkApp2.spec.ts b/comprehensive-demo-react18/e2e/checkApp2.spec.ts
new file mode 100644
index 00000000000..059c44e4573
--- /dev/null
+++ b/comprehensive-demo-react18/e2e/checkApp2.spec.ts
@@ -0,0 +1,39 @@
+import { test, expect } from '@playwright/test';
+
+const base = 'http://localhost:3002';
+
+test.describe('Comprehensive Demo App2', () => {
+ test('renders blocks, dialog and tabs', async ({ page }) => {
+ await page.goto(base);
+
+ await expect(page.locator('header').first()).toHaveCSS('background-color', 'rgb(63, 81, 181)');
+ await expect(page.getByRole('heading', { name: 'Material UI App' })).toBeVisible();
+ await expect(page.getByRole('heading', { name: 'Dialog Component' })).toBeVisible();
+
+ const openDialogButton = page.getByRole('button', { name: 'Open Dialog' });
+ await expect(openDialogButton).toBeVisible();
+ await openDialogButton.click();
+
+ const dialog = page.locator('[role="dialog"]');
+ await expect(dialog.getByRole('heading', { name: 'Dialog Example' })).toBeVisible();
+ await expect(
+ dialog.getByText('This is a dialog from the Material UI app rendered in a React Portal.'),
+ ).toBeVisible();
+ await dialog.getByRole('button', { name: 'Nice' }).click();
+ await expect(dialog).not.toBeVisible();
+
+ await expect(page.getByRole('heading', { name: 'Tabs Component' })).toBeVisible();
+ const fooTab = page.getByRole('tab', { name: 'Foo' });
+ const barTab = page.getByRole('tab', { name: 'Bar' });
+ await expect(fooTab).toBeVisible();
+ await expect(barTab).toBeVisible();
+ await expect(page.getByText('Foo Content')).toBeVisible();
+
+ await barTab.click();
+ await expect(page.getByText('Bar Content')).toBeVisible();
+ await expect(page.getByRole('button', { name: 'Bar Button' })).toHaveCSS(
+ 'background-color',
+ 'rgb(219, 112, 147)',
+ );
+ });
+});
diff --git a/comprehensive-demo-react18/e2e/checkApp3.spec.ts b/comprehensive-demo-react18/e2e/checkApp3.spec.ts
new file mode 100644
index 00000000000..fb19a7ad376
--- /dev/null
+++ b/comprehensive-demo-react18/e2e/checkApp3.spec.ts
@@ -0,0 +1,16 @@
+import { test, expect } from '@playwright/test';
+
+const base = 'http://localhost:3003';
+
+test.describe('Comprehensive Demo App3', () => {
+ test('shows styled button', async ({ page }) => {
+ await page.goto(base);
+
+ await expect(page.locator('header').first()).toHaveCSS('background-color', 'rgb(63, 81, 181)');
+ await expect(page.getByRole('heading', { name: 'Styled Components App' })).toBeVisible();
+
+ const button = page.getByRole('button', { name: '💅 Test Button' });
+ await expect(button).toBeVisible();
+ await expect(button).toHaveCSS('background-color', 'rgb(219, 112, 147)');
+ });
+});
diff --git a/comprehensive-demo-react18/e2e/checkApp4.spec.ts b/comprehensive-demo-react18/e2e/checkApp4.spec.ts
new file mode 100644
index 00000000000..156c3808b70
--- /dev/null
+++ b/comprehensive-demo-react18/e2e/checkApp4.spec.ts
@@ -0,0 +1,8 @@
+import { test, expect } from '@playwright/test';
+
+test.describe('Comprehensive Demo App4', () => {
+ test('shows svelte greeting', async ({ page }) => {
+ await page.goto('http://localhost:3004');
+ await expect(page.locator('h1')).toHaveText('Hello From Svelte world!');
+ });
+});
diff --git a/comprehensive-demo-react18/e2e/checkApp5.spec.ts b/comprehensive-demo-react18/e2e/checkApp5.spec.ts
new file mode 100644
index 00000000000..707dc8e281f
--- /dev/null
+++ b/comprehensive-demo-react18/e2e/checkApp5.spec.ts
@@ -0,0 +1,27 @@
+import { test, expect } from '@playwright/test';
+
+const base = 'http://localhost:3005';
+
+test.describe('Comprehensive Demo App5', () => {
+ test('shows button and alert', async ({ page }) => {
+ await page.goto(base);
+
+ const button = page.locator('action-button').locator('button');
+ await expect(button).toHaveText('bar');
+ await expect(page.locator('.alert')).toHaveText(/Hello/);
+ await expect(page.locator('.closebtn')).toBeVisible();
+ });
+
+ test('button triggers alert and close hides it', async ({ page }) => {
+ await page.goto(base);
+
+ page.once('dialog', async dialog => {
+ expect(dialog.message()).toBe('You have pressed a button.');
+ await dialog.accept();
+ });
+
+ await page.locator('action-button').locator('button').click();
+ await page.locator('.closebtn').click();
+ await expect(page.locator('.alert')).toBeHidden();
+ });
+});
diff --git a/comprehensive-demo-react18/e2e/checkApplications.spec.ts b/comprehensive-demo-react18/e2e/checkApplications.spec.ts
new file mode 100644
index 00000000000..17caba324ed
--- /dev/null
+++ b/comprehensive-demo-react18/e2e/checkApplications.spec.ts
@@ -0,0 +1,18 @@
+import { test, expect } from '@playwright/test';
+
+const apps = [
+ { port: 3001, name: 'App 1', selector: 'h6', text: 'Module Federation Demo' },
+ { port: 3002, name: 'App 2', selector: 'h6', text: 'Material UI App' },
+ { port: 3003, name: 'App 3', selector: 'h6', text: 'Styled Components App' },
+ { port: 3004, name: 'App 4', selector: 'h1', text: 'Hello From Svelte world!' },
+ { port: 3005, name: 'App 5', selector: 'action-button button', text: 'bar' },
+];
+
+apps.forEach(({ port, name, selector, text }) => {
+ test.describe(name, () => {
+ test(`build and run ${name}`, async ({ page }) => {
+ await page.goto(`http://localhost:${port}`);
+ await expect(page.locator(selector, { hasText: text })).toBeVisible();
+ });
+ });
+});
diff --git a/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App1.cy.ts b/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App1.cy.ts
deleted file mode 100644
index 05ebf8ba48b..00000000000
--- a/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App1.cy.ts
+++ /dev/null
@@ -1,328 +0,0 @@
-import { Constants } from '../../cypress-e2e/fixtures/constants';
-import { baseSelectors, selectors } from '../../cypress-e2e/common/selectors';
-import { BaseMethods } from '../../cypress-e2e/common/base';
-import { CssAttr } from '../../cypress-e2e/types/cssAttr';
-
-const basePage: BaseMethods = new BaseMethods();
-
-describe('Comprehencive Demo React 18', () => {
- context('Check is Comprehensive Demo App1 working and have elements', () => {
- beforeEach(() => {
- basePage.openLocalhost({
- number: 3001,
- });
- });
-
- it('Check App build and running & Check app elements exist', () => {
- basePage.checkElementVisibility({
- selector: selectors.comprehensiveDemoApp.blockSelectors.sideBarBlock,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.headers.h6,
- text: Constants.elementsText.comprehensiveDemoApp.App1.sideNavHeaderText,
- });
- Constants.elementsText.comprehensiveDemoApp.comprehensiveDemoDemoPages.forEach(demoPage => {
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.spans.span,
- text: demoPage.name,
- });
- basePage.checkElementHaveProperty({
- selector: baseSelectors.tags.coreElements.link,
- index: demoPage.index,
- attr: Constants.commonConstantsData.commonAttributes.attr,
- prop: Constants.commonConstantsData.commonAttributes.href,
- value: demoPage.link,
- });
- });
- Constants.elementsText.comprehensiveDemoApp.comprehensiveDemoDemoPages.forEach(
- application => {
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.spans.span,
- text: application.name,
- });
- basePage.checkElementHaveProperty({
- selector: baseSelectors.tags.coreElements.link,
- index: application.index,
- attr: Constants.commonConstantsData.commonAttributes.attr,
- prop: Constants.commonConstantsData.commonAttributes.href,
- value: application.link,
- });
- },
- );
- basePage.checkElementVisibility({
- selector: baseSelectors.tags.headers.header,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.headers.h6,
- text: Constants.elementsText.comprehensiveDemoApp.App1.mainPage.headerText,
- });
- basePage.checkElementHaveProperty({
- selector: baseSelectors.tags.headers.header,
- prop: CssAttr.backgroundColor,
- value: Constants.color.oceanBluePearl,
- });
- basePage.checkElementVisibility({
- selector: selectors.comprehensiveDemoApp.alert,
- });
- basePage.checkElementWithTextPresence({
- selector: selectors.comprehensiveDemoApp.alert,
- text: Constants.elementsText.comprehensiveDemoApp.App1.mainPage.alertMessage,
- });
- basePage.checkElementVisibility({
- selector: selectors.comprehensiveDemoApp.closeButton,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.paragraph,
- text: Constants.elementsText.comprehensiveDemoApp.App1.mainPage.paragraphs.first,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.paragraph,
- text: Constants.elementsText.comprehensiveDemoApp.App1.mainPage.paragraphs.second,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.paragraph,
- text: Constants.elementsText.comprehensiveDemoApp.App1.mainPage.paragraphs.third,
- });
- basePage.checkElementHaveProperty({
- selector: baseSelectors.tags.coreElements.link,
- index: Constants.commonConstantsData.commonIndexes.ten,
- attr: Constants.commonConstantsData.commonAttributes.attr,
- prop: Constants.commonConstantsData.commonAttributes.href,
- value: Constants.hrefs.comprehensiveDemoApp.gitHub,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App1.mainPage.buttonText,
- });
- basePage.checkElementHaveProperty({
- selector: baseSelectors.tags.coreElements.button,
- prop: CssAttr.backgroundColor,
- value: Constants.color.paleVioletRed,
- });
- });
-
- it('Check Main Tab Functionality', () => {
- basePage.checkBrowserAlertByText({
- selector: baseSelectors.tags.coreElements.button,
- alertMessage: Constants.elementsText.comprehensiveDemoApp.alertMessage,
- });
- basePage.clickElementBySelector({
- selector: selectors.comprehensiveDemoApp.closeButton,
- });
- basePage.checkElementHaveProperty({
- selector: selectors.comprehensiveDemoApp.alert,
- attr: Constants.commonConstantsData.commonAttributes.attr,
- prop: Constants.commonConstantsData.commonAttributes.style,
- value: Constants.commonConstantsData.commonAttributes.displayNone,
- });
- Constants.elementsText.comprehensiveDemoApp.comprehensiveDemoDemoPages.forEach(demoPage => {
- basePage.clickElementWithText({
- selector: baseSelectors.tags.coreElements.link,
- text: demoPage.name,
- });
- basePage.checkUrlText(demoPage.link, true);
- });
- Constants.elementsText.comprehensiveDemoApp.comprehensiveDemoDemoPages.forEach(
- application => {
- basePage.clickElementWithText({
- selector: baseSelectors.tags.coreElements.link,
- text: application.name,
- });
- basePage.checkUrlText(application.link, true);
- basePage.goBack();
- },
- );
- });
-
- it('Check UI Library elements', () => {
- basePage.openLocalhost({
- number: 3001,
- path: Constants.hrefs.comprehensiveDemoApp.uiLibrary,
- });
- basePage.checkElementVisibility({
- selector: baseSelectors.tags.headers.header,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.headers.h6,
- text: Constants.elementsText.comprehensiveDemoApp.App1.uiLibrary.headerText,
- });
- basePage.checkElementHaveProperty({
- selector: baseSelectors.tags.headers.header,
- prop: CssAttr.backgroundColor,
- value: Constants.color.oceanBluePearl,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.paragraph,
- text: Constants.elementsText.comprehensiveDemoApp.App1.uiLibrary.paragraphs.first,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.paragraph,
- text: Constants.elementsText.comprehensiveDemoApp.App1.uiLibrary.paragraphs.second,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.paragraph,
- text: Constants.elementsText.comprehensiveDemoApp.App1.uiLibrary.paragraphs.third,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.commonConstantsData.commonButtonWithEmoji,
- });
- basePage.checkElementHaveProperty({
- selector: baseSelectors.tags.coreElements.link,
- index: Constants.commonConstantsData.commonIndexes.ten,
- attr: Constants.commonConstantsData.commonAttributes.attr,
- prop: Constants.commonConstantsData.commonAttributes.href,
- value: Constants.hrefs.comprehensiveDemoApp.app3,
- });
- basePage.checkElementHaveProperty({
- selector: baseSelectors.tags.coreElements.link,
- index: Constants.commonConstantsData.commonIndexes.eleven,
- attr: Constants.commonConstantsData.commonAttributes.attr,
- prop: Constants.commonConstantsData.commonAttributes.href,
- value: Constants.hrefs.comprehensiveDemoApp.routingDemo,
- });
- });
-
- it('Check Dialog elements', () => {
- basePage.openLocalhost({
- number: 3001,
- path: Constants.hrefs.comprehensiveDemoApp.demoDialog,
- });
- basePage.checkElementVisibility({
- selector: baseSelectors.tags.headers.header,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.headers.h6,
- text: Constants.elementsText.comprehensiveDemoApp.App1.uiLibrary.dialogHeader,
- });
- basePage.checkElementHaveProperty({
- selector: baseSelectors.tags.headers.header,
- prop: CssAttr.backgroundColor,
- value: Constants.color.oceanBluePearl,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.paragraph,
- text: Constants.elementsText.comprehensiveDemoApp.App1.uiLibrary.dialogParagraph,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.openDialogButtonText,
- });
- basePage.clickElementWithText({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.openDialogButtonText,
- });
- basePage.checkElementVisibility({
- selector: selectors.comprehensiveDemoApp.app2Dialog,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.headers.h2,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogHeader,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.paragraph,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogParagraph,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogButtonText,
- });
- basePage.clickElementWithText({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogButtonText,
- });
- });
-
- it('Check Svelte Page elements', () => {
- basePage.openLocalhost({
- number: 3001,
- path: Constants.hrefs.comprehensiveDemoApp.demoSvelte,
- });
- basePage.checkElementVisibility({
- selector: baseSelectors.tags.headers.header,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.headers.h6,
- text: Constants.elementsText.comprehensiveDemoApp.App1.svelte.headerText,
- });
- basePage.checkElementVisibility({
- selector: baseSelectors.tags.inputs.input,
- });
- basePage.fillField({
- selector: baseSelectors.tags.inputs.input,
- text: Constants.commonConstantsData.standardPhrase,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.headers.h1,
- text: Constants.updatedConstantsData.baseSvelteIntroMessage,
- });
- });
-
- it('Check Routing elements', () => {
- basePage.openLocalhost({
- number: 3001,
- path: Constants.hrefs.comprehensiveDemoApp.routingDemo.replace(
- 'http://localhost:3001/',
- '',
- ),
- });
- basePage.checkElementVisibility({
- selector: baseSelectors.tags.headers.header,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.headers.h6,
- text: Constants.elementsText.comprehensiveDemoApp.App1.routing.headerText,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.paragraph,
- text: Constants.elementsText.comprehensiveDemoApp.App1.routing.paragraphs.first,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.paragraph,
- text: Constants.elementsText.comprehensiveDemoApp.App1.routing.paragraphs.second,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.paragraph,
- text: Constants.elementsText.comprehensiveDemoApp.App1.routing.paragraphs.third,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.paragraph,
- text: Constants.elementsText.comprehensiveDemoApp.App1.routing.paragraphs.forth,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.paragraph,
- text: Constants.elementsText.comprehensiveDemoApp.App1.routing.paragraphs.forth,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.firstTab.name,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.firstTab.name,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.div,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.firstTab.paragraphText,
- });
- basePage.clickElementWithText({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.secondTab.name,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.div,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.secondTab.paragraphText,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.secondTab.buttonText,
- });
- basePage.checkElementHaveProperty({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.secondTab.buttonText,
- prop: CssAttr.backgroundColor,
- value: Constants.color.paleVioletRed,
- });
- });
- });
-});
diff --git a/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App2.cy.ts b/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App2.cy.ts
deleted file mode 100644
index 0fc24d62ef9..00000000000
--- a/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App2.cy.ts
+++ /dev/null
@@ -1,116 +0,0 @@
-import { selectors } from '../../cypress-e2e/common/selectors';
-import { BaseMethods } from '../../cypress-e2e/common/base';
-import { baseSelectors } from '../../cypress-e2e/common/selectors';
-import { Constants } from '../../cypress-e2e/fixtures/constants';
-import { CssAttr } from '../../cypress-e2e/types/cssAttr';
-
-const basePage: BaseMethods = new BaseMethods();
-
-describe('Comprehencive Demo React 18', () => {
- context('Check is Comprehensive Demo App2 working and have elements', () => {
- beforeEach(() => {
- basePage.openLocalhost({
- number: 3002,
- });
- });
-
- it('Check App build and running & Check app elements exist', () => {
- basePage.checkElementVisibility({
- selector: selectors.comprehensiveDemoApp.blockSelectors.firstBlock,
- });
- basePage.checkElementVisibility({
- selector: baseSelectors.tags.headers.header,
- });
- basePage.checkElementHaveProperty({
- selector: baseSelectors.tags.headers.header,
- prop: CssAttr.backgroundColor,
- value: Constants.color.oceanBluePearl,
- });
- basePage.checkElementVisibility({
- selector: selectors.comprehensiveDemoApp.blockSelectors.secondBlock,
- });
- basePage.checkElementHaveProperty({
- selector: selectors.comprehensiveDemoApp.blockSelectors.secondBlock,
- prop: CssAttr.backgroundColor,
- value: Constants.color.alabaster,
- });
- basePage.checkElementVisibility({
- selector: selectors.comprehensiveDemoApp.blockSelectors.thirdBlock,
- });
- basePage.checkElementHaveProperty({
- selector: selectors.comprehensiveDemoApp.blockSelectors.thirdBlock,
- prop: CssAttr.backgroundColor,
- value: Constants.color.white,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.headers.h6,
- text: Constants.elementsText.comprehensiveDemoApp.App2.headerText,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.headers.h6,
- text: Constants.elementsText.comprehensiveDemoApp.App2.paragraphText,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.openDialogButtonText,
- });
- basePage.clickElementWithText({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.openDialogButtonText,
- });
- basePage.checkElementVisibility({
- selector: selectors.comprehensiveDemoApp.app2Dialog,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.headers.h2,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogHeader,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.paragraph,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogParagraph,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogButtonText,
- });
- basePage.clickElementWithText({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogButtonText,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.headers.h6,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.headerText,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.firstTab.name,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.div,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.firstTab.paragraphText,
- });
- basePage.clickElementWithText({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.secondTab.name,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.secondTab.name,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.div,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.secondTab.paragraphText,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.secondTab.buttonText,
- });
- basePage.checkElementHaveProperty({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App2.dialogTabs.secondTab.buttonText,
- prop: CssAttr.backgroundColor,
- value: Constants.color.paleVioletRed,
- });
- });
- });
-});
diff --git a/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App3.cy.ts b/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App3.cy.ts
deleted file mode 100644
index 3c481e20eb0..00000000000
--- a/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App3.cy.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import { Constants } from '../../cypress-e2e/fixtures/constants';
-import { baseSelectors, selectors } from '../../cypress-e2e/common/selectors';
-import { BaseMethods } from '../../cypress-e2e/common/base';
-import { CssAttr } from '../../cypress-e2e/types/cssAttr';
-
-const basePage: BaseMethods = new BaseMethods();
-
-describe('Comprehencive Demo React 18', () => {
- context('Check is Comprehensive Demo App3 working and have elements', () => {
- beforeEach(() => {
- basePage.openLocalhost({
- number: 3003,
- });
- });
-
- it('Check App build and running & Check app elements exist', () => {
- basePage.checkElementVisibility({
- selector: selectors.comprehensiveDemoApp.blockSelectors.firstBlock,
- });
- basePage.checkElementVisibility({
- selector: baseSelectors.tags.headers.header,
- });
- basePage.checkElementHaveProperty({
- selector: baseSelectors.tags.headers.header,
- prop: CssAttr.backgroundColor,
- value: Constants.color.oceanBluePearl,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.headers.h6,
- text: Constants.elementsText.comprehensiveDemoApp.App3.headerText,
- });
- basePage.checkElementVisibility({
- selector: selectors.comprehensiveDemoApp.blockSelectors.secondBlock,
- });
- basePage.checkElementHaveProperty({
- selector: selectors.comprehensiveDemoApp.blockSelectors.secondBlock,
- prop: CssAttr.backgroundColor,
- value: Constants.color.alabaster,
- });
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.commonConstantsData.commonButtonWithEmoji.replace(
- Constants.commonConstantsData.button,
- Constants.elementsText.comprehensiveDemoApp.App3.buttonText,
- ),
- });
- basePage.checkElementHaveProperty({
- selector: baseSelectors.tags.coreElements.button,
- prop: CssAttr.backgroundColor,
- value: Constants.color.paleVioletRed,
- });
- });
- });
-});
diff --git a/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App4.cy.ts b/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App4.cy.ts
deleted file mode 100644
index fdb2b4b78eb..00000000000
--- a/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App4.cy.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { Constants } from '../../cypress-e2e/fixtures/constants';
-import { baseSelectors } from '../../cypress-e2e/common/selectors';
-import { BaseMethods } from '../../cypress-e2e/common/base';
-
-const basePage: BaseMethods = new BaseMethods();
-
-describe('Comprehencive Demo React 18', () => {
- context('Check is Comprehensive Demo App4 working and have elements', () => {
- beforeEach(() => {
- basePage.openLocalhost({
- number: 3004,
- });
- });
-
- it('Check App build and running & Check app elements exist', () => {
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.headers.h1,
- text: Constants.elementsText.comprehensiveDemoApp.App4.headerText,
- });
- });
- });
-});
diff --git a/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App5.cy.ts b/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App5.cy.ts
deleted file mode 100644
index 7e16ffd5e01..00000000000
--- a/comprehensive-demo-react18/e2e/checkComrehensiveDemoReact18App5.cy.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import { Constants } from '../../cypress-e2e/fixtures/constants';
-import { baseSelectors, selectors } from '../../cypress-e2e/common/selectors';
-import { BaseMethods } from '../../cypress-e2e/common/base';
-
-const basePage: BaseMethods = new BaseMethods();
-
-describe('Comprehencive Demo React 18', () => {
- context('Check is Comprehensive Demo App5 working and have elements', () => {
- beforeEach(() => {
- basePage.openLocalhost({
- number: 3005,
- });
- });
-
- it('Check App build and running & Check app elements exist', () => {
- basePage.checkElementWithTextPresence({
- selector: baseSelectors.tags.coreElements.button,
- text: Constants.elementsText.comprehensiveDemoApp.App5.buttonText,
- });
- basePage.checkElementVisibility({
- selector: selectors.comprehensiveDemoApp.alert,
- });
- basePage.checkElementWithTextPresence({
- selector: selectors.comprehensiveDemoApp.alert,
- text: Constants.elementsText.comprehensiveDemoApp.App5.alertText,
- });
- basePage.checkElementVisibility({
- selector: selectors.comprehensiveDemoApp.closeButton,
- });
- });
-
- it('Check Application functionality (Alert message & close button exist)', () => {
- basePage.checkBrowserAlertByText({
- selector: baseSelectors.tags.coreElements.button,
- alertMessage: Constants.elementsText.comprehensiveDemoApp.alertMessage,
- });
- basePage.clickElementBySelector({
- selector: selectors.comprehensiveDemoApp.closeButton,
- });
- basePage.checkElementHaveProperty({
- selector: selectors.comprehensiveDemoApp.alert,
- attr: Constants.commonConstantsData.commonAttributes.attr,
- prop: Constants.commonConstantsData.commonAttributes.style,
- value: Constants.commonConstantsData.commonAttributes.displayNone,
- });
- });
- });
-});
diff --git a/comprehensive-demo-react18/e2e/runAllComprehensiveDemoReact18Tests.cy.ts b/comprehensive-demo-react18/e2e/runAllComprehensiveDemoReact18Tests.cy.ts
deleted file mode 100644
index 29469f47c24..00000000000
--- a/comprehensive-demo-react18/e2e/runAllComprehensiveDemoReact18Tests.cy.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-import './checkComrehensiveDemoReact18App1.cy';
-import './checkComrehensiveDemoReact18App2.cy';
-import './checkComrehensiveDemoReact18App3.cy';
-import './checkComrehensiveDemoReact18App4.cy';
-import './checkComrehensiveDemoReact18App5.cy';
diff --git a/comprehensive-demo-react18/package.json b/comprehensive-demo-react18/package.json
index 4a500446d51..07df0696566 100644
--- a/comprehensive-demo-react18/package.json
+++ b/comprehensive-demo-react18/package.json
@@ -5,19 +5,24 @@
"scripts": {
"start": "pnpm build && pnpm serve",
"legacy:start": "pnpm legacy:build && pnpm serve",
- "build": "time pnpm --filter comprehensive-demo-react18_app* --parallel build",
- "legacy:build": "time pnpm --filter comprehensive-demo-react18_app* legacy:build",
+ "build": "pnpm --filter comprehensive-demo-react18_app* --parallel build",
+ "legacy:build": "pnpm --filter comprehensive-demo-react18_app* legacy:build",
"serve": "pnpm --filter comprehensive-demo-react18_app* --parallel serve",
"dev": "pnpm --filter comprehensive-demo-react18_app* --parallel dev",
"legacy:dev": "pnpm --filter comprehensive-demo-react18_app* --parallel legacy:dev",
"clean": "pnpm --filter comprehensive-demo-react18_app* --parallel clean",
- "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",
- "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"
+ "test:e2e": "npx playwright test",
+ "test:e2e:ui": "npx playwright test --ui",
+ "test:e2e:debug": "npx playwright test --debug",
+ "e2e:ci": "pnpm build && npx playwright install --with-deps && npx playwright test --reporter=list",
+ "legacy:e2e:ci": "pnpm legacy:build && npx playwright install --with-deps && LEGACY_START=true npx playwright test --reporter=list"
},
"devDependencies": {
+ "@playwright/test": "^1.54.2",
"@rsdoctor/rspack-plugin": "0.3.7",
"@rsdoctor/webpack-plugin": "0.3.7",
"concurrently": "8.2.2",
+ "playwright": "^1.54.2",
"wait-on": "7.2.0"
}
}
diff --git a/comprehensive-demo-react18/playwright.config.ts b/comprehensive-demo-react18/playwright.config.ts
new file mode 100644
index 00000000000..91b4184c4f6
--- /dev/null
+++ b/comprehensive-demo-react18/playwright.config.ts
@@ -0,0 +1,40 @@
+import { defineConfig, devices } from '@playwright/test';
+
+const useLegacyStart = !!process.env.LEGACY_START;
+
+export default defineConfig({
+ testDir: './e2e',
+ timeout: 60000,
+ expect: {
+ timeout: 15000,
+ },
+ fullyParallel: true,
+ forbidOnly: !!process.env.CI,
+ retries: process.env.CI ? 1 : 0,
+ workers: process.env.CI ? 1 : undefined,
+ reporter: [
+ ['html', { outputFolder: 'playwright-report', open: 'never' }],
+ ['list'],
+ ],
+ use: {
+ baseURL: 'http://localhost:3001',
+ trace: 'on-first-retry',
+ screenshot: 'only-on-failure',
+ video: 'retain-on-failure',
+ viewport: { width: 1920, height: 1080 },
+ },
+
+ projects: [
+ {
+ name: 'chromium',
+ use: { ...devices['Desktop Chrome'] },
+ },
+ ],
+
+ webServer: {
+ command: useLegacyStart ? 'pnpm legacy:start' : 'pnpm start',
+ port: 3001,
+ reuseExistingServer: !process.env.CI,
+ timeout: 120000,
+ },
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 8c2e31dbbc5..b5a3fb9ba5d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -893,7 +893,7 @@ importers:
dependencies:
'@modern-js/runtime':
specifier: 2.54.6
- version: 2.54.6(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.101.0(@swc/core@1.11.31(@swc/helpers@0.5.17)))
+ version: 2.54.6(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.101.0(@swc/core@1.11.31(@swc/helpers@0.5.3))(esbuild@0.17.19))
react:
specifier: ~18.3.0
version: 18.3.1
@@ -903,22 +903,22 @@ importers:
devDependencies:
'@modern-js-app/eslint-config':
specifier: 2.54.6
- version: 2.54.6(@swc/helpers@0.5.17)(typescript@5.6.2)
+ version: 2.54.6(@swc/helpers@0.5.3)(typescript@5.6.2)
'@modern-js/app-tools':
specifier: 2.54.6
- version: 2.54.6(@rspack/core@1.4.11(@swc/helpers@0.5.17))(@swc/core@1.11.31(@swc/helpers@0.5.17))(@types/webpack@5.28.0(@swc/core@1.11.31(@swc/helpers@0.5.17)))(encoding@0.1.13)(eslint@9.6.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@5.3.11(@babel/core@7.28.3)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1))(ts-node@10.9.2(@swc/core@1.11.31(@swc/helpers@0.5.17))(@types/node@20.16.5)(typescript@5.6.2))(tsconfig-paths@4.2.0)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.15.2(webpack@5.101.0(@swc/core@1.11.31(@swc/helpers@0.5.17))))(webpack-hot-middleware@2.26.1)
+ version: 2.54.6(@rspack/core@0.4.5)(@swc/core@1.11.31(@swc/helpers@0.5.3))(@types/webpack@5.28.0(@swc/core@1.11.31(@swc/helpers@0.5.3))(esbuild@0.17.19))(encoding@0.1.13)(eslint@8.57.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@5.3.11(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1))(ts-node@10.9.2(@swc/core@1.11.31(@swc/helpers@0.5.3))(@types/node@20.16.5)(typescript@5.6.2))(tsconfig-paths@4.2.0)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.15.2(webpack@5.101.0(@swc/core@1.11.31(@swc/helpers@0.5.3))(esbuild@0.17.19)))(webpack-hot-middleware@2.26.1)
'@modern-js/builder-rspack-provider':
specifier: 2.46.1
- version: 2.46.1(@babel/traverse@7.28.3)(@rsbuild/core@1.4.12)(@swc/core@1.11.31(@swc/helpers@0.5.17))(@types/express@4.17.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(ts-node@10.9.2(@swc/core@1.11.31(@swc/helpers@0.5.17))(@types/node@20.16.5)(typescript@5.6.2))(tsconfig-paths@4.2.0)(typescript@5.6.2)
+ version: 2.46.1(@babel/traverse@7.28.3)(@rsbuild/core@0.7.10)(@swc/core@1.11.31(@swc/helpers@0.5.3))(@types/express@4.17.21)(esbuild@0.17.19)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(ts-node@10.9.2(@swc/core@1.11.31(@swc/helpers@0.5.3))(@types/node@20.16.5)(typescript@5.6.2))(tsconfig-paths@4.2.0)(typescript@5.6.2)
'@modern-js/eslint-config':
specifier: 2.54.6
- version: 2.54.6(@swc/helpers@0.5.17)(typescript@5.6.2)
+ version: 2.54.6(@swc/helpers@0.5.3)(typescript@5.6.2)
'@modern-js/tsconfig':
specifier: 2.54.6
version: 2.54.6
'@module-federation/enhanced':
specifier: 0.17.1
- version: 0.17.1(@rspack/core@1.4.11(@swc/helpers@0.5.17))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.101.0(@swc/core@1.11.31(@swc/helpers@0.5.17)))
+ version: 0.17.1(@rspack/core@0.4.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.101.0(@swc/core@1.11.31(@swc/helpers@0.5.3))(esbuild@0.17.19))
husky:
specifier: 9.0.11
version: 9.0.11
@@ -936,7 +936,7 @@ importers:
dependencies:
'@modern-js/runtime':
specifier: 2.54.6
- version: 2.54.6(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.101.0(@swc/core@1.11.31(@swc/helpers@0.5.3))(esbuild@0.17.19))
+ version: 2.54.6(@types/react-dom@18.3.0)(@types/react@18.3.10)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(webpack@5.101.0(@swc/core@1.11.31(@swc/helpers@0.5.17)))
react:
specifier: ~18.3.0
version: 18.3.1
@@ -946,22 +946,22 @@ importers:
devDependencies:
'@modern-js-app/eslint-config':
specifier: 2.54.6
- version: 2.54.6(@swc/helpers@0.5.3)(typescript@5.6.2)
+ version: 2.54.6(@swc/helpers@0.5.17)(typescript@5.6.2)
'@modern-js/app-tools':
specifier: 2.54.6
- version: 2.54.6(@rspack/core@0.4.5)(@swc/core@1.11.31(@swc/helpers@0.5.3))(@types/webpack@5.28.0(@swc/core@1.11.31(@swc/helpers@0.5.3))(esbuild@0.17.19))(encoding@0.1.13)(eslint@8.57.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@5.3.11(@babel/core@7.24.7)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1))(ts-node@10.9.2(@swc/core@1.11.31(@swc/helpers@0.5.3))(@types/node@20.16.5)(typescript@5.6.2))(tsconfig-paths@4.2.0)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.15.2(webpack@5.101.0(@swc/core@1.11.31(@swc/helpers@0.5.3))(esbuild@0.17.19)))(webpack-hot-middleware@2.26.1)
+ version: 2.54.6(@rspack/core@1.4.11(@swc/helpers@0.5.17))(@swc/core@1.11.31(@swc/helpers@0.5.17))(@types/webpack@5.28.0(@swc/core@1.11.31(@swc/helpers@0.5.17)))(encoding@0.1.13)(eslint@9.6.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(styled-components@5.3.11(@babel/core@7.28.3)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1))(ts-node@10.9.2(@swc/core@1.11.31(@swc/helpers@0.5.17))(@types/node@20.16.5)(typescript@5.6.2))(tsconfig-paths@4.2.0)(type-fest@2.19.0)(typescript@5.6.2)(webpack-dev-server@4.15.2(webpack@5.101.0(@swc/core@1.11.31(@swc/helpers@0.5.17))))(webpack-hot-middleware@2.26.1)
'@modern-js/builder-rspack-provider':
specifier: 2.46.1
- version: 2.46.1(@babel/traverse@7.28.3)(@rsbuild/core@0.7.10)(@swc/core@1.11.31(@swc/helpers@0.5.3))(@types/express@4.17.21)(esbuild@0.17.19)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(ts-node@10.9.2(@swc/core@1.11.31(@swc/helpers@0.5.3))(@types/node@20.16.5)(typescript@5.6.2))(tsconfig-paths@4.2.0)(typescript@5.6.2)
+ version: 2.46.1(@babel/traverse@7.28.3)(@rsbuild/core@1.4.12)(@swc/core@1.11.31(@swc/helpers@0.5.17))(@types/express@4.17.21)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(ts-node@10.9.2(@swc/core@1.11.31(@swc/helpers@0.5.17))(@types/node@20.16.5)(typescript@5.6.2))(tsconfig-paths@4.2.0)(typescript@5.6.2)
'@modern-js/eslint-config':
specifier: 2.54.6
- version: 2.54.6(@swc/helpers@0.5.3)(typescript@5.6.2)
+ version: 2.54.6(@swc/helpers@0.5.17)(typescript@5.6.2)
'@modern-js/tsconfig':
specifier: 2.54.6
version: 2.54.6
'@module-federation/enhanced':
specifier: 0.17.1
- version: 0.17.1(@rspack/core@0.4.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.101.0(@swc/core@1.11.31(@swc/helpers@0.5.3))(esbuild@0.17.19))
+ version: 0.17.1(@rspack/core@1.4.11(@swc/helpers@0.5.17))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.6.2)(webpack@5.101.0(@swc/core@1.11.31(@swc/helpers@0.5.17)))
husky:
specifier: 9.0.11
version: 9.0.11
@@ -1592,6 +1592,9 @@ importers:
comprehensive-demo-react18:
devDependencies:
+ '@playwright/test':
+ specifier: ^1.54.2
+ version: 1.54.2
'@rsdoctor/rspack-plugin':
specifier: 0.3.7
version: 0.3.7(@rspack/core@1.4.11(@swc/helpers@0.5.17))(@swc/core@1.11.31(@swc/helpers@0.5.17))
@@ -1601,6 +1604,9 @@ importers:
concurrently:
specifier: 8.2.2
version: 8.2.2
+ playwright:
+ specifier: ^1.54.2
+ version: 1.54.2
wait-on:
specifier: 7.2.0
version: 7.2.0