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.
🧪 Testing Strategy Overview
Section titled “🧪 Testing Strategy Overview”Testing Levels
Section titled “Testing Levels”- Unit Testing: Individual MFE components and services
 - Integration Testing: Host-Remote interactions
 - End-to-End Testing: Complete user workflows
 - Performance Testing: Bundle sizes and load times
 - Error Handling Testing: Fallback mechanisms
 
Testing Environment Setup
Section titled “Testing Environment Setup”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”1.1 Enhanced Development Scripts
Section titled “1.1 Enhanced Development Scripts”Create comprehensive development scripts in your root directory:
Unix/macOS (start-all-dev.sh):
#!/bin/bash
# Color codes for outputRED='\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 directorymkdir -p logs
# Function to start an applicationstart_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 applicationsstart_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 functionhealth_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 stopwhile true; do    read -n 1 key    if [[ $key == 'q' || $key == 'Q' ]]; then        break    fidone
echo ""echo -e "${YELLOW}🛑 Stopping all applications...${NC}"
# Stop all applicationsfor 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"    fidone
echo -e "${GREEN}🏁 All applications stopped successfully!${NC}"Windows (start-all-dev.ps1):
# Set console colors for output$Colors = @{    Red = 'Red'    Green = 'Green'    Yellow = 'Yellow'    Blue = 'Blue'    White = 'White'}
Write-Host "🚀 Starting Angular MFE Development Environment" -ForegroundColor BlueWrite-Host "===============================================" -ForegroundColor Blue
# Create logs directoryNew-Item -Path "logs" -ItemType Directory -Force | Out-Null
# Function to start an applicationfunction 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 GreenWrite-Host ""Write-Host "📱 Application URLs:" -ForegroundColor CyanWrite-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 CyanWrite-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 YellowStart-Sleep -Seconds 15
# Health check functionfunction 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 BlueTest-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 GreenWrite-Host "Press 'q' to stop all applications..." -ForegroundColor Yellow
# Wait for user input to stopdo {    $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 applicationstry {    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 filesGet-ChildItem -Path "logs\*.pid" | Remove-Item -Force -ErrorAction SilentlyContinue
Write-Host "🏁 All applications stopped successfully!" -ForegroundColor Greenpackage.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"  }}1.2 Health Check Script
Section titled “1.2 Health Check Script”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 servicescheck_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 endpointscurl -s "http://localhost:4201/remoteEntry.js" | head -5echo ""echo "📊 Health check complete!"Windows (health-check.ps1):
Write-Host "🔍 MFE Health Check Report" -ForegroundColor BlueWrite-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 servicesTest-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 endpointstry {    $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”2.1 Browser DevTools Configuration
Section titled “2.1 Browser DevTools Configuration”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.');})();2.2 VS Code Debugging Configuration
Section titled “2.2 VS Code Debugging Configuration”.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/*"            }        }    ]}🧪 Step 3: Integration Testing
Section titled “🧪 Step 3: Integration Testing”3.1 MFE Integration Test Suite
Section titled “3.1 MFE Integration Test Suite”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);    });});3.2 Performance Testing
Section titled “3.2 Performance Testing”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 auditasync 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();🛠️ Step 4: Testing Automation
Section titled “🛠️ Step 4: Testing Automation”4.1 Automated Test Suite
Section titled “4.1 Automated Test Suite”test-all.sh:
#!/bin/bash
echo "🧪 Running Complete MFE Test Suite"echo "================================="
# ColorsGREEN='\033[0;32m'RED='\033[0;31m'YELLOW='\033[1;33m'NC='\033[0m'
# Test resultsTESTS_PASSED=0TESTS_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 runningecho "🚀 Ensuring applications are running..."./start-all-dev.sh &START_PID=$!sleep 20
# Run health checksrun_test "Health Check" "./health-check.sh"
# Run unit tests for each MFErun_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 testsrun_test "Integration Tests" "npm run test:integration"
# Run performance testsrun_test "Performance Tests" "node performance-test.js"
# Run E2E testsrun_test "E2E Tests" "npx cypress run --headless"
# Generate test reportecho "📊 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 0else    echo -e "${RED}💥 Some tests failed!${NC}"    exit 1fi4.2 Continuous Integration Setup
Section titled “4.2 Continuous Integration Setup”.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/🔍 Step 5: Manual Testing Checklist
Section titled “🔍 Step 5: Manual Testing Checklist”5.1 Browser Compatibility Testing
Section titled “5.1 Browser Compatibility Testing”Test matrix for different browsers:
| Feature | Chrome | Firefox | Safari | Edge | 
|---|---|---|---|---|
| Host App Loading | ✅ | ✅ | ✅ | ✅ | 
| MFE Navigation | ✅ | ✅ | ⚠️ | ✅ | 
| Remote Loading | ✅ | ✅ | ❌ | ✅ | 
| Responsive Design | ✅ | ✅ | ✅ | ✅ | 
5.2 Mobile Testing Checklist
Section titled “5.2 Mobile Testing Checklist”- 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
 
5.3 Error Scenario Testing
Section titled “5.3 Error Scenario Testing”Test these error scenarios:
- 
MFE Unavailable:
- Stop one MFE service
 - Navigate to that route
 - Verify fallback content displays
 
 - 
Network Issues:
- Throttle network to 3G
 - Test MFE loading performance
 - Verify loading indicators work
 
 - 
JavaScript Errors:
- Introduce intentional errors
 - Verify error boundaries work
 - Check console for proper error reporting
 
 
📊 Step 6: Testing Metrics & Reporting
Section titled “📊 Step 6: Testing Metrics & Reporting”6.1 Test Coverage Report
Section titled “6.1 Test Coverage Report”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();6.2 Performance Metrics Dashboard
Section titled “6.2 Performance Metrics Dashboard”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>✅ Local Testing Verification Checklist
Section titled “✅ Local Testing Verification Checklist”Complete Testing Checklist
Section titled “Complete Testing Checklist”- 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
 
Performance Targets
Section titled “Performance Targets”- ⚡ First Load: < 2 seconds
 - 📦 Bundle Size: < 500KB total
 - 🔄 MFE Load Time: < 1 second
 - 📱 Mobile Performance: Score > 80
 - ♿ Accessibility: Score > 90
 
🚀 What’s Next?
Section titled “🚀 What’s Next?”Your local testing environment is complete! Next steps:
- ✅ Local Testing Complete
 - ➡️ Continue to: Azure Deployment - Deploy to production
 - 📚 Alternative: Remote Configuration - Advanced remote setup
 
Your Angular MFE application is now thoroughly tested and ready for deployment! 🎉