This guide covers how to run, analyze, and extend tests comparing the AngularJS and React versions of the PhoneCat application.
- Node.js 16+ installed
- Both Angular and React applications installed
# Install dependencies for React app
cd react-phonecat
npm install
# Install Playwright browsers
npx playwright install
# Install dependencies for Angular app
cd ../angular-phonecat
npm installThe test suite is organized into:
- Visual Comparison Tests - Compare screenshots between Angular and React applications
- Functional Tests - Test behavior and interactions in both applications
- Unit Tests - Test individual components (React app only)
# From react-phonecat directory
npm run test:e2e # Run all tests
npm run test:comparison # Run comparison tests only
npm run test:ui # Run tests with UI mode
npm run test:report # View test results| Command | Description |
|---|---|
test:e2e |
Runs all end-to-end tests |
test:comparison |
Runs visual comparison tests between Angular and React |
test:ui |
Opens Playwright UI for interactive testing |
test:report |
Opens the HTML report of the last test run |
# Run a specific test file
npx playwright test tests/scripts/visual-comparison.spec.js
# Run tests with a specific tag
npx playwright test --grep @visualAfter running tests, a detailed HTML report is generated. View it with:
npm run test:reportThe report includes:
- Pass/fail status for each test
- Screenshots and videos (when enabled)
- Error messages and stack traces
- Test duration and other metadata
Visual comparison tests generate screenshots in the tests/results directory:
angular-phone-list.png- AngularJS list pagereact-phone-list.png- React list pageangular-phone-detail.png- AngularJS detail pagereact-phone-detail.png- React detail pagediff-*.png- Difference highlights (when enabled)
-
Visual Differences:
- CSS styling mismatches
- Layout positioning issues
- Font rendering differences
- Animation state differences
-
Functional Differences:
- Different behavior on user interactions
- Data loading discrepancies
- Routing differences
- Event handling differences
// Problem: Different margins or padding
<div className="phone-list">...</div>
// Solution: Match exact CSS values
<div className="phone-list" style={{
margin: '10px 0',
padding: '15px'
}}>...</div>/* Problem: Font rendering differences */
.phone-name { font-family: Arial; }
/* Solution: Match exact font specifications */
.phone-name {
font-family: Arial, sans-serif;
font-weight: 400;
font-size: 16px;
letter-spacing: normal;
}// Problem: Click event behaves differently
<button onClick={handleClick}>Click Me</button>
// Solution: Ensure event handling is identical
<button
onClick={handleClick}
onKeyDown={(e) => e.key === 'Enter' && handleClick()}
>
Click Me
</button>// Problem: Route parameter handling differs
// Solution: Ensure route parameter extraction is identical
useEffect(() => {
// Extract parameter exactly as Angular would
const phoneId = params.phoneId;
fetchPhone(phoneId);
}, [params.phoneId]);// In tests/scripts/visual-comparison.spec.js
test('compare new component', async ({ page, angularPage }) => {
// Navigate to pages
await page.goto('/new-component');
await angularPage.goto('/app/new-component');
// Take screenshots
await page.screenshot({ path: 'tests/results/react-new-component.png' });
await angularPage.screenshot({ path: 'tests/results/angular-new-component.png' });
// Optional: Compare screenshots
const comparison = await compareScreenshots(
'tests/results/angular-new-component.png',
'tests/results/react-new-component.png'
);
expect(comparison.diffPercentage).toBeLessThan(0.5);
});// In tests/scripts/functional.spec.js
test('new interaction test', async ({ page, angularPage }) => {
// Test in React app
await page.goto('/phones');
await page.click('.new-button');
const reactResult = await page.textContent('.result');
// Test same interaction in Angular app
await angularPage.goto('/app/phones');
await angularPage.click('.new-button');
const angularResult = await angularPage.textContent('.result');
// Compare results
expect(reactResult).toEqual(angularResult);
});Edit playwright.config.js to customize:
- Viewport sizes
- Timeout settings
- Browser configurations
- Parallel execution settings
Example:
// Add mobile viewport testing
const config = {
projects: [
{
name: 'Desktop Chrome',
use: { browserName: 'chromium', viewport: { width: 1280, height: 720 } },
},
{
name: 'Mobile Chrome',
use: { browserName: 'chromium', viewport: { width: 375, height: 667 } },
}
]
};- Port conflicts: Ensure Angular runs on port 8000 and React on port 3000
- Timeout errors: Increase timeouts in Playwright config
- Missing screenshots: Ensure the tests/results directory exists
- Inconsistent results: Clear browser caches and restart test servers
-
Enable trace viewer:
npx playwright test --trace on -
Slow down test execution:
// In test file test.slow(); // Makes the test run 3x slower
-
Capture video of test runs:
// In playwright.config.js use: { video: 'on-first-retry' }
-
Interactive debugging:
npx playwright test --debug
The tests can be run in CI/CD pipelines:
# Example GitHub Actions workflow
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Install dependencies
run: npm ci
- name: Install Playwright browsers
run: npx playwright install --with-deps
- name: Run tests
run: npm run test:e2e
- name: Upload test results
if: always()
uses: actions/upload-artifact@v3
with:
name: playwright-report
path: playwright-report/Customize test reporting by adding custom reporters in playwright.config.js:
reporter: [
['html'],
['json', { outputFile: 'test-results/results.json' }],
['junit', { outputFile: 'test-results/results.xml' }]
]This testing approach ensures that the React conversion maintains perfect visual and functional parity with the original AngularJS application. By running these tests regularly during development, you can catch and fix discrepancies early in the conversion process.