Skip to content

Angular MFE Local Testing Guide | Complete Testing Strategy

This guide provides comprehensive strategies for testing your Angular Micro Frontend application locally, including debugging techniques, performance monitoring, and integration testing approaches.

  1. Unit Testing: Individual MFE components and services
  2. Integration Testing: Host-Remote interactions
  3. End-to-End Testing: Complete user workflows
  4. Performance Testing: Bundle sizes and load times
  5. Error Handling Testing: Fallback mechanisms
Testing Environment Structure:
├── Unit Tests (Jest/Jasmine)
├── Integration Tests (Custom scripts)
├── E2E Tests (Cypress/Protractor)
├── Performance Tests (Lighthouse/Bundle Analyzer)
└── Manual Testing (Browser DevTools)

🚀 Step 1: Local Development Environment

Section titled “🚀 Step 1: Local Development Environment”

Create comprehensive development scripts in your root directory:

Unix/macOS (start-all-dev.sh):

#!/bin/bash
# Color codes for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}🚀 Starting Angular MFE Development Environment${NC}"
echo "==============================================="
# Create logs directory
mkdir -p logs
# Function to start an application
start_app() {
local app_name=$1
local port=$2
local color=$3
echo -e "${color}📦 Starting $app_name on port $port...${NC}"
cd $app_name
# Install dependencies if node_modules doesn't exist
if [ ! -d "node_modules" ]; then
echo -e "${YELLOW}📋 Installing dependencies for $app_name...${NC}"
npm install
fi
# Start the application
npm start > ../logs/$app_name.log 2>&1 &
local pid=$!
echo $pid > ../logs/$app_name.pid
cd ..
echo -e "${GREEN}✅ $app_name started with PID $pid${NC}"
return $pid
}
# Start all applications
start_app "mfe-loan-calculator" 4201 "$BLUE"
start_app "mfe-user-dashboard" 4202 "$GREEN"
start_app "mfe-transaction-history" 4203 "$YELLOW"
start_app "host-banking-app" 4200 "$RED"
echo ""
echo -e "${GREEN}🎉 All applications started successfully!${NC}"
echo ""
echo "📱 Application URLs:"
echo " 🏠 Host App: http://localhost:4200"
echo " 🧮 Loan Calculator: http://localhost:4201"
echo " 📊 User Dashboard: http://localhost:4202"
echo " 💳 Transactions: http://localhost:4203"
echo ""
echo "📊 Remote Entry Points:"
echo " http://localhost:4201/remoteEntry.js"
echo " http://localhost:4202/remoteEntry.js"
echo " http://localhost:4203/remoteEntry.js"
echo ""
echo -e "${YELLOW}⏳ Waiting 15 seconds for applications to start...${NC}"
sleep 15
# Health check function
health_check() {
local url=$1
local name=$2
if curl -s -f "$url" > /dev/null; then
echo -e "${GREEN}✅ $name is healthy${NC}"
return 0
else
echo -e "${RED}❌ $name is not responding${NC}"
return 1
fi
}
echo ""
echo -e "${BLUE}🔍 Performing health checks...${NC}"
health_check "http://localhost:4200" "Host Application"
health_check "http://localhost:4201/remoteEntry.js" "Loan Calculator MFE"
health_check "http://localhost:4202/remoteEntry.js" "User Dashboard MFE"
health_check "http://localhost:4203/remoteEntry.js" "Transaction History MFE"
echo ""
echo -e "${GREEN}🎯 Development environment ready!${NC}"
echo "Press 'q' to stop all applications..."
# Wait for user input to stop
while true; do
read -n 1 key
if [[ $key == 'q' || $key == 'Q' ]]; then
break
fi
done
echo ""
echo -e "${YELLOW}🛑 Stopping all applications...${NC}"
# Stop all applications
for pidfile in logs/*.pid; do
if [ -f "$pidfile" ]; then
pid=$(cat "$pidfile")
if kill -0 $pid > /dev/null 2>&1; then
kill $pid
echo -e "${GREEN}✅ Stopped process $pid${NC}"
fi
rm "$pidfile"
fi
done
echo -e "${GREEN}🏁 All applications stopped successfully!${NC}"

Windows (start-all-dev.ps1):

Terminal window
# Set console colors for output
$Colors = @{
Red = 'Red'
Green = 'Green'
Yellow = 'Yellow'
Blue = 'Blue'
White = 'White'
}
Write-Host "🚀 Starting Angular MFE Development Environment" -ForegroundColor Blue
Write-Host "===============================================" -ForegroundColor Blue
# Create logs directory
New-Item -Path "logs" -ItemType Directory -Force | Out-Null
# Function to start an application
function Start-App {
param(
[string]$AppName,
[int]$Port,
[string]$Color
)
Write-Host "📦 Starting $AppName on port $Port..." -ForegroundColor $Color
Set-Location $AppName
# Install dependencies if node_modules doesn't exist
if (!(Test-Path "node_modules")) {
Write-Host "📋 Installing dependencies for $AppName..." -ForegroundColor Yellow
npm install
}
# Start the application
$process = Start-Process npm -ArgumentList "start" -PassThru -WindowStyle Hidden -RedirectStandardOutput "..\logs\$AppName.log" -RedirectStandardError "..\logs\$AppName.log"
$process.Id | Out-File -FilePath "..\logs\$AppName.pid" -Encoding UTF8
Set-Location ..
Write-Host "$AppName started with PID $($process.Id)" -ForegroundColor Green
return $process
}
# Start all applications
$loanCalcProcess = Start-App "mfe-loan-calculator" 4201 "Blue"
$dashboardProcess = Start-App "mfe-user-dashboard" 4202 "Green"
$transactionProcess = Start-App "mfe-transaction-history" 4203 "Yellow"
$hostProcess = Start-App "host-banking-app" 4200 "Red"
Write-Host ""
Write-Host "🎉 All applications started successfully!" -ForegroundColor Green
Write-Host ""
Write-Host "📱 Application URLs:" -ForegroundColor Cyan
Write-Host " 🏠 Host App: http://localhost:4200"
Write-Host " 🧮 Loan Calculator: http://localhost:4201"
Write-Host " 📊 User Dashboard: http://localhost:4202"
Write-Host " 💳 Transactions: http://localhost:4203"
Write-Host ""
Write-Host "📊 Remote Entry Points:" -ForegroundColor Cyan
Write-Host " http://localhost:4201/remoteEntry.js"
Write-Host " http://localhost:4202/remoteEntry.js"
Write-Host " http://localhost:4203/remoteEntry.js"
Write-Host ""
Write-Host "⏳ Waiting 15 seconds for applications to start..." -ForegroundColor Yellow
Start-Sleep -Seconds 15
# Health check function
function Test-HealthCheck {
param(
[string]$Url,
[string]$Name
)
try {
$response = Invoke-WebRequest -Uri $Url -UseBasicParsing -TimeoutSec 5
if ($response.StatusCode -eq 200) {
Write-Host "$Name is healthy" -ForegroundColor Green
return $true
} else {
Write-Host "$Name is not responding" -ForegroundColor Red
return $false
}
} catch {
Write-Host "$Name is not responding" -ForegroundColor Red
return $false
}
}
Write-Host ""
Write-Host "🔍 Performing health checks..." -ForegroundColor Blue
Test-HealthCheck "http://localhost:4200" "Host Application"
Test-HealthCheck "http://localhost:4201/remoteEntry.js" "Loan Calculator MFE"
Test-HealthCheck "http://localhost:4202/remoteEntry.js" "User Dashboard MFE"
Test-HealthCheck "http://localhost:4203/remoteEntry.js" "Transaction History MFE"
Write-Host ""
Write-Host "🎯 Development environment ready!" -ForegroundColor Green
Write-Host "Press 'q' to stop all applications..." -ForegroundColor Yellow
# Wait for user input to stop
do {
$key = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
} while ($key.Character -ne 'q' -and $key.Character -ne 'Q')
Write-Host ""
Write-Host "🛑 Stopping all applications..." -ForegroundColor Yellow
# Stop all applications
try {
Stop-Process -Id $loanCalcProcess.Id -Force -ErrorAction SilentlyContinue
Write-Host "✅ Stopped loan calculator process" -ForegroundColor Green
} catch { }
try {
Stop-Process -Id $dashboardProcess.Id -Force -ErrorAction SilentlyContinue
Write-Host "✅ Stopped dashboard process" -ForegroundColor Green
} catch { }
try {
Stop-Process -Id $transactionProcess.Id -Force -ErrorAction SilentlyContinue
Write-Host "✅ Stopped transaction process" -ForegroundColor Green
} catch { }
try {
Stop-Process -Id $hostProcess.Id -Force -ErrorAction SilentlyContinue
Write-Host "✅ Stopped host process" -ForegroundColor Green
} catch { }
# Clean up pid files
Get-ChildItem -Path "logs\*.pid" | Remove-Item -Force -ErrorAction SilentlyContinue
Write-Host "🏁 All applications stopped successfully!" -ForegroundColor Green

package.json (root level):

{
"name": "angular-mfe-workspace",
"version": "1.0.0",
"scripts": {
"start:all": "./start-all-dev.sh",
"start:all:win": "powershell -ExecutionPolicy Bypass -File .\\start-all-dev.ps1",
"test:all": "./test-all.sh",
"test:all:win": "powershell -ExecutionPolicy Bypass -File .\\test-all.ps1",
"build:all": "./build-all.sh",
"build:all:win": "powershell -ExecutionPolicy Bypass -File .\\build-all.ps1",
"health:check": "./health-check.sh",
"health:check:win": "powershell -ExecutionPolicy Bypass -File .\\health-check.ps1",
"logs:view": "tail -f logs/*.log",
"logs:view:win": "Get-Content logs\\*.log -Wait",
"logs:clear": "rm -rf logs/*.log",
"logs:clear:win": "Remove-Item logs\\*.log -Force"
}
}

Unix/macOS (health-check.sh):

#!/bin/bash
echo "🔍 MFE Health Check Report"
echo "=========================="
check_service() {
local name=$1
local url=$2
local expected_content=$3
echo -n "Checking $name... "
if curl -s -f "$url" > /dev/null; then
if [ ! -z "$expected_content" ]; then
if curl -s "$url" | grep -q "$expected_content"; then
echo "✅ Healthy (Content verified)"
else
echo "⚠️ Responding but content mismatch"
fi
else
echo "✅ Healthy"
fi
else
echo "❌ Not responding"
fi
}
# Check all services
check_service "Host Application" "http://localhost:4200" "banking"
check_service "Loan Calculator" "http://localhost:4201/remoteEntry.js"
check_service "User Dashboard" "http://localhost:4202/remoteEntry.js"
check_service "Transaction History" "http://localhost:4203/remoteEntry.js"
echo ""
echo "🌐 Testing MFE Integration..."
# Test module federation endpoints
curl -s "http://localhost:4201/remoteEntry.js" | head -5
echo ""
echo "📊 Health check complete!"

Windows (health-check.ps1):

Terminal window
Write-Host "🔍 MFE Health Check Report" -ForegroundColor Blue
Write-Host "==========================" -ForegroundColor Blue
function Test-Service {
param(
[string]$Name,
[string]$Url,
[string]$ExpectedContent = $null
)
Write-Host "Checking $Name... " -NoNewline
try {
$response = Invoke-WebRequest -Uri $Url -UseBasicParsing -TimeoutSec 10
if ($response.StatusCode -eq 200) {
if ($ExpectedContent) {
if ($response.Content -match $ExpectedContent) {
Write-Host "✅ Healthy (Content verified)" -ForegroundColor Green
} else {
Write-Host "⚠️ Responding but content mismatch" -ForegroundColor Yellow
}
} else {
Write-Host "✅ Healthy" -ForegroundColor Green
}
} else {
Write-Host "❌ Not responding" -ForegroundColor Red
}
} catch {
Write-Host "❌ Not responding" -ForegroundColor Red
}
}
# Check all services
Test-Service "Host Application" "http://localhost:4200" "banking"
Test-Service "Loan Calculator" "http://localhost:4201/remoteEntry.js"
Test-Service "User Dashboard" "http://localhost:4202/remoteEntry.js"
Test-Service "Transaction History" "http://localhost:4203/remoteEntry.js"
Write-Host ""
Write-Host "🌐 Testing MFE Integration..." -ForegroundColor Cyan
# Test module federation endpoints
try {
$response = Invoke-WebRequest -Uri "http://localhost:4201/remoteEntry.js" -UseBasicParsing
$content = $response.Content
$lines = $content -split "`n" | Select-Object -First 5
$lines | ForEach-Object { Write-Host $_ }
} catch {
Write-Host "Failed to fetch remote entry: $($_.Exception.Message)" -ForegroundColor Red
}
Write-Host ""
Write-Host "📊 Health check complete!" -ForegroundColor Green

🔍 Step 2: Development Tools & Debugging

Section titled “🔍 Step 2: Development Tools & Debugging”

Create a browser extension or bookmarklet for MFE debugging:

mfe-debug.js:

// MFE Debug Helper - Run in browser console
(function() {
const MfeDebugger = {
// Check if Module Federation is working
checkModuleFederation() {
console.group('🔍 Module Federation Status');
// Check if webpack is available
if (typeof __webpack_require__ !== 'undefined') {
console.log('✅ Webpack is available');
// Check loaded modules
const loadedModules = Object.keys(__webpack_require__.cache || {});
console.log(`📦 Loaded modules: ${loadedModules.length}`);
// Check for remote entries
const remoteEntries = loadedModules.filter(m => m.includes('remoteEntry'));
console.log('🌐 Remote entries:', remoteEntries);
} else {
console.log('❌ Webpack not available');
}
console.groupEnd();
},
// Check MFE health
async checkMfeHealth() {
console.group('🏥 MFE Health Check');
const mfes = [
{ name: 'Loan Calculator', url: 'http://localhost:4201/remoteEntry.js' },
{ name: 'User Dashboard', url: 'http://localhost:4202/remoteEntry.js' },
{ name: 'Transaction History', url: 'http://localhost:4203/remoteEntry.js' }
];
for (const mfe of mfes) {
try {
const response = await fetch(mfe.url, { method: 'HEAD' });
console.log(`${response.ok ? '' : ''} ${mfe.name}: ${response.status}`);
} catch (error) {
console.log(`${mfe.name}: Not reachable`);
}
}
console.groupEnd();
},
// Performance monitoring
checkPerformance() {
console.group('⚡ Performance Metrics');
if (window.performance) {
const navigation = window.performance.getEntriesByType('navigation')[0];
console.log(`🚀 DOM Content Loaded: ${navigation.domContentLoadedEventEnd - navigation.domContentLoadedEventStart}ms`);
console.log(`📄 Page Load: ${navigation.loadEventEnd - navigation.loadEventStart}ms`);
// Check resource loading times
const resources = window.performance.getEntriesByType('resource');
const remoteEntries = resources.filter(r => r.name.includes('remoteEntry.js'));
remoteEntries.forEach(entry => {
console.log(`📦 ${entry.name}: ${entry.responseEnd - entry.requestStart}ms`);
});
}
console.groupEnd();
},
// Bundle analysis
analyzeBundles() {
console.group('📊 Bundle Analysis');
if (typeof __webpack_require__ !== 'undefined') {
const cache = __webpack_require__.cache || {};
const modules = Object.keys(cache);
// Group by source
const bundleStats = modules.reduce((stats, moduleId) => {
const module = cache[moduleId];
if (module && module.id) {
const source = moduleId.includes('remoteEntry') ? 'Remote' : 'Local';
stats[source] = (stats[source] || 0) + 1;
}
return stats;
}, {});
console.table(bundleStats);
}
console.groupEnd();
},
// Run all checks
runAllChecks() {
console.clear();
console.log('🔧 MFE Debug Report - ' + new Date().toLocaleTimeString());
console.log('='.repeat(50));
this.checkModuleFederation();
this.checkMfeHealth();
this.checkPerformance();
this.analyzeBundles();
console.log('✅ Debug report complete!');
}
};
// Make available globally
window.MfeDebugger = MfeDebugger;
console.log('🛠️ MFE Debugger loaded! Use MfeDebugger.runAllChecks() to start.');
})();

.vscode/launch.json:

{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Host App",
"type": "chrome",
"request": "launch",
"url": "http://localhost:4200",
"webRoot": "${workspaceFolder}/host-banking-app/src",
"sourceMapPathOverrides": {
"webpack:/*": "${webRoot}/*"
}
},
{
"name": "Debug Loan Calculator MFE",
"type": "chrome",
"request": "launch",
"url": "http://localhost:4201",
"webRoot": "${workspaceFolder}/mfe-loan-calculator/src",
"sourceMapPathOverrides": {
"webpack:/*": "${webRoot}/*"
}
},
{
"name": "Debug All MFEs",
"type": "chrome",
"request": "launch",
"url": "http://localhost:4200",
"webRoot": "${workspaceFolder}",
"sourceMapPathOverrides": {
"webpack:/*": "${webRoot}/*/src/*"
}
}
]
}

test-integration.js:

const puppeteer = require('puppeteer');
const { expect } = require('chai');
describe('MFE Integration Tests', () => {
let browser;
let page;
before(async () => {
browser = await puppeteer.launch({
headless: false, // Set to true for CI
devtools: true
});
page = await browser.newPage();
// Enable console logging
page.on('console', msg => console.log('PAGE LOG:', msg.text()));
page.on('pageerror', error => console.log('PAGE ERROR:', error.message));
});
after(async () => {
await browser.close();
});
it('Should load host application', async () => {
await page.goto('http://localhost:4200');
await page.waitForSelector('.app-header');
const title = await page.title();
expect(title).to.include('Banking');
});
it('Should load Loan Calculator MFE', async () => {
await page.goto('http://localhost:4200/loan-calculator');
await page.waitForSelector('.loan-calculator', { timeout: 10000 });
const calculator = await page.$('.loan-calculator');
expect(calculator).to.not.be.null;
});
it('Should interact with Loan Calculator', async () => {
await page.goto('http://localhost:4200/loan-calculator');
await page.waitForSelector('.loan-calculator');
// Test slider interaction
const slider = await page.$('#loanAmount');
await slider.click();
// Test dropdown selection
await page.select('#interestRate', '5.1');
// Verify calculation updates
await page.waitForFunction(() => {
const result = document.querySelector('.monthly-payment');
return result && result.textContent.includes('$');
});
});
it('Should navigate between MFEs', async () => {
await page.goto('http://localhost:4200');
// Click navigation links
await page.click('a[routerLink="/dashboard"]');
await page.waitForSelector('.user-dashboard', { timeout: 5000 });
await page.click('a[routerLink="/loan-calculator"]');
await page.waitForSelector('.loan-calculator', { timeout: 5000 });
await page.click('a[routerLink="/transactions"]');
await page.waitForSelector('.transaction-history', { timeout: 5000 });
});
it('Should handle MFE loading errors gracefully', async () => {
// Simulate network error
await page.setOfflineMode(true);
await page.goto('http://localhost:4200/loan-calculator');
// Check for error handling
await page.waitForSelector('.error-message', { timeout: 5000 });
await page.setOfflineMode(false);
});
});

performance-test.js:

const puppeteer = require('puppeteer');
const lighthouse = require('lighthouse');
async function runPerformanceTest() {
const browser = await puppeteer.launch({
headless: true,
args: ['--remote-debugging-port=9222']
});
const page = await browser.newPage();
// Enable performance monitoring
await page.coverage.startJSCoverage();
await page.coverage.startCSSCoverage();
console.log('🚀 Starting performance test...');
// Test host application
await page.goto('http://localhost:4200');
await page.waitForLoadState('networkidle');
// Measure bundle sizes
const jsCoverage = await page.coverage.stopJSCoverage();
const cssCoverage = await page.coverage.stopCSSCoverage();
let totalJSBytes = 0;
let usedJSBytes = 0;
jsCoverage.forEach(entry => {
totalJSBytes += entry.text.length;
entry.ranges.forEach(range => {
usedJSBytes += range.end - range.start - 1;
});
});
console.log(`📦 Total JS: ${(totalJSBytes / 1024).toFixed(2)} KB`);
console.log(`✅ Used JS: ${(usedJSBytes / 1024).toFixed(2)} KB`);
console.log(`📊 JS Usage: ${((usedJSBytes / totalJSBytes) * 100).toFixed(2)}%`);
// Test MFE loading times
const mfeTests = [
{ name: 'Loan Calculator', url: '/loan-calculator' },
{ name: 'User Dashboard', url: '/dashboard' },
{ name: 'Transactions', url: '/transactions' }
];
for (const test of mfeTests) {
const startTime = Date.now();
await page.goto(`http://localhost:4200${test.url}`);
await page.waitForLoadState('networkidle');
const loadTime = Date.now() - startTime;
console.log(`⏱️ ${test.name}: ${loadTime}ms`);
}
await browser.close();
}
// Run Lighthouse audit
async function runLighthouseAudit() {
const browser = await puppeteer.launch({
headless: true,
args: ['--remote-debugging-port=9222']
});
const result = await lighthouse('http://localhost:4200', {
port: 9222,
output: 'json',
logLevel: 'info'
});
console.log('📊 Lighthouse Results:');
console.log(`Performance: ${result.lhr.categories.performance.score * 100}`);
console.log(`Accessibility: ${result.lhr.categories.accessibility.score * 100}`);
console.log(`Best Practices: ${result.lhr.categories['best-practices'].score * 100}`);
console.log(`SEO: ${result.lhr.categories.seo.score * 100}`);
await browser.close();
}
runPerformanceTest();
runLighthouseAudit();

test-all.sh:

#!/bin/bash
echo "🧪 Running Complete MFE Test Suite"
echo "================================="
# Colors
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m'
# Test results
TESTS_PASSED=0
TESTS_FAILED=0
run_test() {
local test_name=$1
local test_command=$2
echo -e "${YELLOW}🔄 Running $test_name...${NC}"
if eval $test_command; then
echo -e "${GREEN}✅ $test_name passed${NC}"
((TESTS_PASSED++))
else
echo -e "${RED}❌ $test_name failed${NC}"
((TESTS_FAILED++))
fi
echo ""
}
# Start applications if not running
echo "🚀 Ensuring applications are running..."
./start-all-dev.sh &
START_PID=$!
sleep 20
# Run health checks
run_test "Health Check" "./health-check.sh"
# Run unit tests for each MFE
run_test "Host App Unit Tests" "cd host-banking-app && npm test -- --watch=false"
run_test "Loan Calculator Unit Tests" "cd mfe-loan-calculator && npm test -- --watch=false"
run_test "User Dashboard Unit Tests" "cd mfe-user-dashboard && npm test -- --watch=false"
# Run integration tests
run_test "Integration Tests" "npm run test:integration"
# Run performance tests
run_test "Performance Tests" "node performance-test.js"
# Run E2E tests
run_test "E2E Tests" "npx cypress run --headless"
# Generate test report
echo "📊 Test Results Summary"
echo "======================"
echo -e "✅ Tests Passed: ${GREEN}$TESTS_PASSED${NC}"
echo -e "❌ Tests Failed: ${RED}$TESTS_FAILED${NC}"
if [ $TESTS_FAILED -eq 0 ]; then
echo -e "${GREEN}🎉 All tests passed!${NC}"
exit 0
else
echo -e "${RED}💥 Some tests failed!${NC}"
exit 1
fi

.github/workflows/mfe-ci.yml:

name: MFE CI/CD Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies for all projects
run: |
cd host-banking-app && npm ci
cd ../mfe-loan-calculator && npm ci
cd ../mfe-user-dashboard && npm ci
cd ../mfe-transaction-history && npm ci
- name: Run linting
run: |
cd host-banking-app && npm run lint
cd ../mfe-loan-calculator && npm run lint
cd ../mfe-user-dashboard && npm run lint
cd ../mfe-transaction-history && npm run lint
- name: Run unit tests
run: |
cd host-banking-app && npm test -- --watch=false --browsers=ChromeHeadless
cd ../mfe-loan-calculator && npm test -- --watch=false --browsers=ChromeHeadless
cd ../mfe-user-dashboard && npm test -- --watch=false --browsers=ChromeHeadless
cd ../mfe-transaction-history && npm test -- --watch=false --browsers=ChromeHeadless
- name: Build all applications
run: |
cd host-banking-app && npm run build
cd ../mfe-loan-calculator && npm run build
cd ../mfe-user-dashboard && npm run build
cd ../mfe-transaction-history && npm run build
- name: Start applications for integration tests
run: |
./start-all-dev.sh &
sleep 30
- name: Run integration tests
run: npm run test:integration
- name: Upload test results
uses: actions/upload-artifact@v3
with:
name: test-results
path: test-results/

Test matrix for different browsers:

FeatureChromeFirefoxSafariEdge
Host App Loading
MFE Navigation⚠️
Remote Loading
Responsive Design
  • Navigation: Mobile menu works correctly
  • Touch interactions: All buttons and links are touchable
  • Responsive design: Layouts adapt to different screen sizes
  • Performance: App loads quickly on mobile networks
  • MFE loading: Remote modules load correctly on mobile

Test these error scenarios:

  1. MFE Unavailable:

    • Stop one MFE service
    • Navigate to that route
    • Verify fallback content displays
  2. Network Issues:

    • Throttle network to 3G
    • Test MFE loading performance
    • Verify loading indicators work
  3. JavaScript Errors:

    • Introduce intentional errors
    • Verify error boundaries work
    • Check console for proper error reporting

Generate comprehensive test coverage:

coverage-report.js:

const fs = require('fs');
const path = require('path');
function generateCoverageReport() {
const projects = [
'host-banking-app',
'mfe-loan-calculator',
'mfe-user-dashboard',
'mfe-transaction-history'
];
let totalLines = 0;
let coveredLines = 0;
const projectReports = [];
projects.forEach(project => {
const coveragePath = path.join(project, 'coverage/lcov-report/index.html');
if (fs.existsSync(coveragePath)) {
// Parse coverage data (simplified)
const coverage = {
project: project,
lines: Math.floor(Math.random() * 100), // Mock data
functions: Math.floor(Math.random() * 100),
branches: Math.floor(Math.random() * 100),
statements: Math.floor(Math.random() * 100)
};
projectReports.push(coverage);
totalLines += 100;
coveredLines += coverage.lines;
}
});
console.log('📊 Test Coverage Report');
console.log('='.repeat(50));
console.table(projectReports);
console.log(`Overall Coverage: ${(coveredLines / totalLines * 100).toFixed(2)}%`);
}
generateCoverageReport();

Create a simple HTML dashboard for monitoring:

performance-dashboard.html:

<!DOCTYPE html>
<html>
<head>
<title>MFE Performance Dashboard</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.metric { background: #f5f5f5; padding: 15px; margin: 10px 0; border-radius: 5px; }
.good { border-left: 5px solid #27ae60; }
.warning { border-left: 5px solid #f39c12; }
.error { border-left: 5px solid #e74c3c; }
</style>
</head>
<body>
<h1>🚀 MFE Performance Dashboard</h1>
<div id="metrics"></div>
<script>
async function loadMetrics() {
const metrics = [
{ name: 'Host App Load Time', value: '1.2s', status: 'good' },
{ name: 'Loan Calculator Load', value: '0.8s', status: 'good' },
{ name: 'Bundle Size (Host)', value: '245KB', status: 'warning' },
{ name: 'Bundle Size (Total)', value: '680KB', status: 'warning' },
{ name: 'Time to Interactive', value: '2.1s', status: 'good' }
];
const container = document.getElementById('metrics');
metrics.forEach(metric => {
const div = document.createElement('div');
div.className = `metric ${metric.status}`;
div.innerHTML = `<strong>${metric.name}:</strong> ${metric.value}`;
container.appendChild(div);
});
}
loadMetrics();
// Auto-refresh every 30 seconds
setInterval(loadMetrics, 30000);
</script>
</body>
</html>

  • Development environment starts all MFEs successfully
  • Health checks pass for all applications
  • Navigation works between all MFEs
  • Unit tests pass for all projects
  • Integration tests verify MFE interactions
  • Performance tests meet acceptance criteria
  • Error handling works correctly
  • Browser compatibility verified across browsers
  • Mobile responsiveness tested on multiple devices
  • Accessibility requirements met
  • Security headers and HTTPS working
  • CI/CD pipeline runs successfully
  • First Load: < 2 seconds
  • 📦 Bundle Size: < 500KB total
  • 🔄 MFE Load Time: < 1 second
  • 📱 Mobile Performance: Score > 80
  • Accessibility: Score > 90

Your local testing environment is complete! Next steps:

  1. Local Testing Complete
  2. ➡️ Continue to: Azure Deployment - Deploy to production
  3. 📚 Alternative: Remote Configuration - Advanced remote setup

Your Angular MFE application is now thoroughly tested and ready for deployment! 🎉