jam-cloud/jam-ui/test/capture-session-flow.spec.ts

166 lines
5.3 KiB
TypeScript

import { test, chromium } from '@playwright/test';
import * as fs from 'fs';
import * as path from 'path';
/**
* This test captures the complete network traffic (HAR file) for the "Join Session" flow
* from the legacy JamKazam application. The captured data will be used to:
* 1. Document all API calls to /api/*
* 2. Document all WebSocket messages
* 3. Create a migration test plan for the new jam-ui interface
*/
test('Capture network traffic for joining a music session', async () => {
// Launch browser with ability to capture network traffic
const browser = await chromium.launch({
headless: false, // Use headed mode to see what's happening
slowMo: 1000, // Slow down by 1 second to make actions visible
});
const context = await browser.newContext({
ignoreHTTPSErrors: true,
recordHar: {
path: path.join(__dirname, '../test-results/session-join-flow.har'),
mode: 'full', // Capture full request/response bodies
},
});
const page = await context.newPage();
// Array to collect all WebSocket messages
const wsMessages: any[] = [];
const apiCalls: any[] = [];
// Listen to all network requests
page.on('request', request => {
const url = request.url();
if (url.includes('/api/')) {
console.log(`API REQUEST: ${request.method()} ${url}`);
apiCalls.push({
type: 'request',
method: request.method(),
url: url,
headers: request.headers(),
timestamp: new Date().toISOString(),
});
}
});
page.on('response', async response => {
const url = response.url();
if (url.includes('/api/')) {
console.log(`API RESPONSE: ${response.status()} ${url}`);
let body = null;
try {
body = await response.text();
} catch (e) {
// Some responses can't be read
}
apiCalls.push({
type: 'response',
status: response.status(),
url: url,
headers: response.headers(),
body: body,
timestamp: new Date().toISOString(),
});
}
});
// Listen to WebSocket events
page.on('websocket', ws => {
console.log(`WebSocket opened: ${ws.url()}`);
wsMessages.push({
type: 'websocket-open',
url: ws.url(),
timestamp: new Date().toISOString(),
});
ws.on('framesent', frame => {
console.log(`WS SENT: ${frame.payload}`);
wsMessages.push({
type: 'sent',
payload: frame.payload,
timestamp: new Date().toISOString(),
});
});
ws.on('framereceived', frame => {
console.log(`WS RECEIVED: ${frame.payload}`);
wsMessages.push({
type: 'received',
payload: frame.payload,
timestamp: new Date().toISOString(),
});
});
ws.on('close', () => {
console.log('WebSocket closed');
wsMessages.push({
type: 'websocket-close',
timestamp: new Date().toISOString(),
});
});
});
try {
console.log('Step 1: Navigate to signin page');
await page.goto('http://www.jamkazam.com:3000/signin', {
waitUntil: 'networkidle',
timeout: 30000,
});
console.log('Step 2: Login with credentials');
// Fill in login form
await page.fill('input[name="email"], input[type="email"]', 'nuwan@jamkazam.com');
await page.fill('input[name="password"], input[type="password"]', 'jam123');
// Click sign in button
await page.click('button[type="submit"], input[type="submit"], button:has-text("Sign in"), button:has-text("Login")');
// Wait for navigation after login
await page.waitForLoadState('networkidle');
await page.waitForTimeout(2000);
console.log('Step 3: Click "create session" tile');
// Look for create session button/tile
await page.click('[data-testid="create-session"], button:has-text("Create Session"), a:has-text("Create Session")');
await page.waitForLoadState('networkidle');
await page.waitForTimeout(2000);
console.log('Step 4: Press Control+Shift+0 to trick browser as native client');
await page.keyboard.press('Control+Shift+Digit0');
await page.waitForTimeout(1000);
console.log('Step 5: Click "create quick start" button');
await page.click('button:has-text("Create Quick Start"), button:has-text("Quick Start")');
// Wait for session to load
await page.waitForLoadState('networkidle');
await page.waitForTimeout(5000); // Give time for WebSocket messages
console.log('Recording complete. Saving captured data...');
// Save API calls to a separate JSON file
const apiCallsPath = path.join(__dirname, '../test-results/api-calls.json');
fs.writeFileSync(apiCallsPath, JSON.stringify(apiCalls, null, 2));
console.log(`API calls saved to: ${apiCallsPath}`);
// Save WebSocket messages to a separate JSON file
const wsMessagesPath = path.join(__dirname, '../test-results/websocket-messages.json');
fs.writeFileSync(wsMessagesPath, JSON.stringify(wsMessages, null, 2));
console.log(`WebSocket messages saved to: ${wsMessagesPath}`);
// Keep browser open for manual inspection
console.log('Keeping browser open for 30 seconds for manual inspection...');
await page.waitForTimeout(30000);
} catch (error) {
console.error('Error during test:', error);
throw error;
} finally {
// Close context to save HAR file
await context.close();
await browser.close();
}
});