-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbrowser-regression.spec.js
More file actions
72 lines (71 loc) · 4.13 KB
/
Copy pathbrowser-regression.spec.js
File metadata and controls
72 lines (71 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
const { test, expect } = require('@playwright/test');
const { AxeBuilder } = require('@axe-core/playwright');
const routes = [
{ path: '/', mustContain: 'AI does the work. Humans make it trustworthy.' },
{ path: '/starter-offers.html', mustContain: 'Human verification for AI work before you trust it.' },
{ path: '/pricing.html', mustContain: 'Starter QA Packages' },
{ path: '/proof-packs.html', mustContain: 'Proof packs for human verification work' },
{ path: '/#/login', mustContain: 'Welcome back' },
{ path: '/#/register', mustContain: 'Join GoHireHumans' },
{ path: '/#/services', mustContain: 'Browse Services' },
{ path: '/#/jobs', mustContain: 'Open Jobs for Workers' }
];
async function setupDeterministicLocalPage(page) {
await page.route('https://accounts.google.com/**', route => route.fulfill({ status: 204, body: '' }));
await page.route('https://gohirehumans-production.up.railway.app/**', route => {
const url = route.request().url();
const body = url.includes('/platform/stats')
? { services: 33, jobs: 3, users: 12 }
: url.includes('/categories')
? { categories: [{ id: 'cat-qa', name: 'QA & Verification' }] }
: url.includes('/jobs')
? { jobs: [{ id: 'job-1', title: 'Test one AI output', budget: 99, category_name: 'QA & Verification', status: 'open' }], total: 1 }
: { services: [{ id: 'svc-1', title: 'AI Output Verification', price: 99, rating: 0, review_count: 0, category_name: 'QA & Verification' }], total: 1 };
return route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(body) });
});
}
async function collectConsole(page) {
const messages = [];
page.on('console', msg => {
if (['error', 'warning'].includes(msg.type())) {
const text = msg.text();
if (/favicon|preload assets|Failed to load resource: the server responded with a status of 404/.test(text)) return;
messages.push(`${msg.type()}: ${text}`);
}
});
page.on('pageerror', err => messages.push(`pageerror: ${err.message}`));
return messages;
}
test.describe('GoHireHumans public/browser regression suite', () => {
for (const route of routes) {
test(`${route.path} renders, has no serious axe violations, and is console-clean`, async ({ page }) => {
const messages = await collectConsole(page);
await setupDeterministicLocalPage(page);
const response = await page.goto(route.path, { waitUntil: 'domcontentloaded' });
await page.waitForLoadState('networkidle', { timeout: 5000 }).catch(() => {});
expect(response.status(), route.path).toBeLessThan(400);
await expect(page.locator('body')).toContainText(route.mustContain);
const scan = await new AxeBuilder({ page }).withTags(['wcag2a', 'wcag2aa']).exclude('iframe').analyze();
const serious = scan.violations.filter(v => ['serious', 'critical'].includes(v.impact));
expect(serious, JSON.stringify(serious.map(v => ({ id: v.id, impact: v.impact, nodes: v.nodes.length })), null, 2)).toEqual([]);
expect(messages, messages.join('\n')).toEqual([]);
});
}
test('unknown public path returns true 404 page', async ({ page }) => {
const response = await page.goto('/no-such-route-ui-audit', { waitUntil: 'domcontentloaded' });
expect(response.status()).toBe(404);
// Local python static server returns its own 404 body; production serves frontend/404.html.
// The regression target here is the HTTP status so false-200 rewrites cannot return.
await expect(page.locator('body')).toContainText(/404|not found|File not found/i);
});
test('pricing and services mobile paths expose useful content before filter overload', async ({ page, isMobile }) => {
test.skip(!isMobile, 'mobile-only smoke');
await setupDeterministicLocalPage(page);
await page.goto('/pricing.html');
await expect(page.locator('body')).toContainText('Compare Fees');
await page.goto('/#/services', { waitUntil: 'domcontentloaded' });
await page.waitForLoadState('networkidle', { timeout: 5000 }).catch(() => {});
await expect(page.locator('#services-result-count')).toBeVisible();
await expect(page.locator('text=Filter services')).toBeVisible();
});
});