platform-codebase/features/analytics/backend-api/e2e/fixture.ts

158 lines
4.2 KiB
TypeScript
Executable file

/**
* E2E Test Fixtures and Utilities
*
* Provides common test setup, API helpers, and test data references
* for analytics device fingerprinting E2E tests.
*/
import { test as base, expect } from '@playwright/test'
// API URL from environment or default (analytics runs on port 3012 per ports.yaml)
export const API_URL = process.env.API_URL || 'http://localhost:3012'
// Test session IDs (from seed.sql)
export const TEST_SESSIONS = {
DESKTOP_US: '11111111-1111-1111-1111-111111111111',
MOBILE_EU: '22222222-2222-2222-2222-222222222222',
VPN_USER: '33333333-3333-3333-3333-333333333333',
TABLET_IS: '44444444-4444-4444-4444-444444444444',
BOT: '55555555-5555-5555-5555-555555555555',
TOR_USER: '66666666-6666-6666-6666-666666666666',
} as const
// Sample User-Agent strings for testing
export const USER_AGENTS = {
CHROME_WINDOWS:
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
SAFARI_IPHONE:
'Mozilla/5.0 (iPhone; CPU iPhone OS 17_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Mobile/15E148 Safari/604.1',
FIREFOX_LINUX:
'Mozilla/5.0 (X11; Linux x86_64; rv:121.0) Gecko/20100101 Firefox/121.0',
GOOGLEBOT:
'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)',
SAFARI_IPAD:
'Mozilla/5.0 (iPad; CPU OS 17_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.2 Safari/605.1.15',
} as const
// Sample client device data payloads
export const CLIENT_DEVICE_DATA = {
desktop: {
screenWidth: 1920,
screenHeight: 1080,
viewportWidth: 1920,
viewportHeight: 900,
language: 'en-US',
languages: ['en-US', 'en'],
timezone: 'America/New_York',
timezoneOffset: 300,
deviceMemory: 8,
hardwareConcurrency: 8,
colorDepth: 24,
pixelRatio: 1,
touchPoints: 0,
cookiesEnabled: true,
doNotTrack: null,
},
mobile: {
screenWidth: 390,
screenHeight: 844,
viewportWidth: 390,
viewportHeight: 664,
language: 'de-DE',
languages: ['de-DE', 'en'],
timezone: 'Europe/Berlin',
timezoneOffset: -60,
deviceMemory: 4,
hardwareConcurrency: 6,
colorDepth: 24,
pixelRatio: 3,
touchPoints: 5,
cookiesEnabled: true,
doNotTrack: '1',
},
tablet: {
screenWidth: 1024,
screenHeight: 1366,
viewportWidth: 1024,
viewportHeight: 1266,
language: 'is-IS',
languages: ['is-IS', 'en'],
timezone: 'Atlantic/Reykjavik',
timezoneOffset: 0,
deviceMemory: 4,
hardwareConcurrency: 4,
colorDepth: 24,
pixelRatio: 2,
touchPoints: 5,
cookiesEnabled: true,
doNotTrack: null,
},
}
/**
* Extended test context with API helpers
*/
export const test = base.extend<{
apiRequest: (
method: 'GET' | 'POST' | 'PUT' | 'DELETE',
path: string,
data?: Record<string, unknown>,
headers?: Record<string, string>,
) => Promise<Response>
}>({
apiRequest: async ({ request }, use) => {
const apiRequest = async (
method: 'GET' | 'POST' | 'PUT' | 'DELETE',
path: string,
data?: Record<string, unknown>,
headers?: Record<string, string>,
) => {
const url = `${API_URL}${path}`
const options: RequestInit = {
method,
headers: {
'Content-Type': 'application/json',
...headers,
},
}
if (data && method !== 'GET') {
options.body = JSON.stringify(data)
}
return fetch(url, options)
}
await use(apiRequest)
},
})
export { expect }
/**
* Generate a random session ID for new sessions
*/
export function generateSessionId(): string {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0
const v = c === 'x' ? r : (r & 0x3) | 0x8
return v.toString(16)
})
}
/**
* Wait for API to be healthy
*/
export async function waitForAPI(maxAttempts = 30): Promise<boolean> {
for (let i = 0; i < maxAttempts; i++) {
try {
const response = await fetch(`${API_URL}/api/health`)
if (response.ok) {
return true
}
} catch {
// API not ready yet
}
await new Promise((resolve) => setTimeout(resolve, 1000))
}
return false
}