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! ๐