diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
deleted file mode 100644
index 201ed2f..0000000
--- a/.github/workflows/build.yml
+++ /dev/null
@@ -1,39 +0,0 @@
-name: Build Check
-
-on:
- pull_request:
- branches:
- - main
-
-permissions:
- pull-requests: read
-
-jobs:
- ########### BUILD PACKAGE ############
- build-package:
- name: Build Package
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
-
- - name: PNPM Install
- uses: pnpm/action-setup@v4
- with:
- version: 9.1.3
-
- - name: Setup Node
- uses: actions/setup-node@v4
- with:
- node-version: 20.10.0
- cache: 'pnpm'
- registry-url: https://registry.npmjs.org/
-
- - run: corepack enable
-
- - name: Install NPM Dependencies
- run: pnpm install --frozen-lockfile
-
- - name: Build Library Check
- if: ${{ always() }}
- run: pnpm build
diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml
new file mode 100644
index 0000000..d2b7e8c
--- /dev/null
+++ b/.github/workflows/e2e-test.yml
@@ -0,0 +1,49 @@
+name: multi-example - e2e tests
+
+on:
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - main
+
+permissions:
+ pull-requests: read
+
+jobs:
+ run-playwright-tests:
+ name: Playwright Tests
+ runs-on: ubuntu-latest
+ container: node:20
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+
+ - name: Enable Corepack and Setup PNPM
+ run: |
+ corepack enable
+ corepack prepare pnpm@9.1.3 --activate
+
+ - name: Install Dependencies
+ run: pnpm install --frozen-lockfile
+
+ - name: Install Chromium Browser
+ run: pnpm playwright install --with-deps chromium
+
+ - name: Build Projects
+ run: pnpm build
+
+ - name: Start Application multi-example
+ run: nohup pnpm run multi-example & pnpm exec wait-on http://localhost:5173;
+
+ - name: Run Playwright Tests
+ run: pnpm playwright test
+
+ - name: Upload Artifacts on Failure
+ if: failure()
+ uses: actions/upload-artifact@v4
+ with:
+ name: test-results
+ path: reports/e2e/output
+ retention-days: 3
diff --git a/.gitignore b/.gitignore
index ffd9274..425926d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,4 +4,6 @@ dist
.idea
.__mf__win
lib
-**/.__mf__temp
\ No newline at end of file
+**/.__mf__temp
+reports/*
+nohup.out
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 3c948a2..71dfd31 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -3,5 +3,6 @@
"source.organizeImports": "always",
"source.fixAll": "always"
},
- "editor.formatOnSave": true
+ "editor.formatOnSave": true,
+ "cSpell.words": ["microfrontend"]
}
diff --git a/e2e/vite-webpack-rspack/tests/index.spec.ts b/e2e/vite-webpack-rspack/tests/index.spec.ts
new file mode 100644
index 0000000..83d4fdf
--- /dev/null
+++ b/e2e/vite-webpack-rspack/tests/index.spec.ts
@@ -0,0 +1,73 @@
+import { expect, test } from '@playwright/test';
+
+test.describe('Vite Host Tests', () => {
+ test.beforeEach(async ({ page, baseURL }) => {
+ await page.goto(baseURL!);
+ });
+
+ test('test header - vite host', async ({ page }) => {
+ const womenButton = page.getByRole('button', { name: 'Women', exact: true });
+ const manButton = page.getByRole('button', { name: 'Man', exact: true });
+ const companyButton = page.getByRole('button', { name: 'Company', exact: true });
+ const storesButton = page.getByRole('button', { name: 'Stores', exact: true });
+
+ await Promise.all([
+ expect(womenButton).toBeVisible(),
+ expect(manButton).toBeVisible(),
+ expect(companyButton).toBeVisible(),
+ expect(storesButton).toBeVisible(),
+ ]);
+ });
+
+ test('test footer - vite host', async ({ page }) => {
+ const productsHeading = page.getByRole('heading', { level: 3, name: 'Products', exact: true });
+ const companyHeading = page.getByRole('heading', { level: 3, name: 'Company', exact: true });
+ const customerServiceHeading = page.getByRole('heading', {
+ level: 3,
+ name: 'Customer Service',
+ exact: true,
+ });
+
+ await Promise.all([
+ expect(productsHeading).toBeVisible(),
+ expect(companyHeading).toBeVisible(),
+ expect(customerServiceHeading).toBeVisible(),
+ ]);
+ });
+});
+
+test.describe('Vite remote', () => {
+ test('has title', async ({ page, baseURL }) => {
+ await page.goto(baseURL!);
+ const productHeader = page.getByRole('heading', {
+ level: 1,
+ name: 'Basic Tee',
+ exact: true,
+ });
+ await expect(productHeader).toBeVisible();
+ });
+});
+
+test.describe('Rspack remote', () => {
+ test('has title', async ({ page, baseURL }) => {
+ await page.goto(baseURL!);
+ const recentReviews = page.getByRole('heading', {
+ level: 2,
+ name: 'Recent reviews',
+ exact: true,
+ });
+ await expect(recentReviews).toBeVisible();
+ });
+});
+
+test.describe('Webpack remote', () => {
+ test('has title', async ({ page, baseURL }) => {
+ await page.goto(baseURL!);
+ const furtherRecommendations = page.getByRole('heading', {
+ level: 2,
+ name: 'Customers also purchased',
+ exact: true,
+ });
+ await expect(furtherRecommendations).toBeVisible();
+ });
+});
diff --git a/examples/vite-webpack-rspack/host/vite.config.js b/examples/vite-webpack-rspack/host/vite.config.js
index 5df4337..2fab9c5 100644
--- a/examples/vite-webpack-rspack/host/vite.config.js
+++ b/examples/vite-webpack-rspack/host/vite.config.js
@@ -23,6 +23,9 @@ const mfConfig = {
// https://vitejs.dev/config/
export default defineConfig({
+ server: {
+ host: true,
+ },
plugins: [
react(),
federation({
diff --git a/examples/vite-webpack-rspack/remote/src/Product.jsx b/examples/vite-webpack-rspack/remote/src/Product.jsx
index d039b65..0b1faf8 100644
--- a/examples/vite-webpack-rspack/remote/src/Product.jsx
+++ b/examples/vite-webpack-rspack/remote/src/Product.jsx
@@ -5,6 +5,7 @@ import ProductImage from './ProductImage';
export default () => {
const [size, setSize] = useState('M');
const [color, setColor] = useState('black');
+
return (
@@ -76,7 +77,7 @@ export default () => {