Files
Codeman/test/e2e/fixtures/browser.fixture.ts
T
arkonandClaude Opus 4.5 2e4d89496f fix: Ralph wizard uses file-based prompt to avoid screen escaping issues
- Add /api/sessions/:id/ralph-prompt/write endpoint to write prompt to @ralph_prompt.md
- Wizard now writes full prompt to file, then sends simple read command to Claude
- Fix session readiness check to wait for prompt character instead of notWorking flag
- Add E2E test infrastructure for ralph-loop workflow (port 3190)
- Add ralph-wizard-prod.mjs script for production testing

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 17:46:43 +01:00

150 lines
3.7 KiB
TypeScript

/**
* Browser fixture for E2E tests
* Manages Playwright browser lifecycle with required args for headless Chrome
*/
import { chromium, Browser, BrowserContext, Page } from 'playwright';
export interface BrowserFixture {
browser: Browser;
context: BrowserContext;
page: Page;
}
/**
* Create and launch a browser fixture
* Uses required args for headless Chrome in CI/Linux environments
* @returns BrowserFixture with browser, context, and page
*/
export async function createBrowserFixture(): Promise<BrowserFixture> {
const browser = await chromium.launch({
headless: true,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-gpu',
'--disable-software-rasterizer',
],
});
const context = await browser.newContext({
viewport: { width: 1280, height: 720 },
ignoreHTTPSErrors: true,
});
const page = await context.newPage();
// Set default timeout for all operations
page.setDefaultTimeout(15000);
return {
browser,
context,
page,
};
}
/**
* Close and cleanup a browser fixture
* @param fixture - Browser fixture to destroy
*/
export async function destroyBrowserFixture(fixture: BrowserFixture): Promise<void> {
if (fixture.page) {
await fixture.page.close().catch(() => {});
}
if (fixture.context) {
await fixture.context.close().catch(() => {});
}
if (fixture.browser) {
await fixture.browser.close().catch(() => {});
}
}
/**
* Navigate to a URL and wait for load
* Note: Uses 'domcontentloaded' because SSE streams prevent 'networkidle'
* @param page - Playwright page
* @param url - URL to navigate to
*/
export async function navigateTo(page: Page, url: string): Promise<void> {
await page.goto(url, { waitUntil: 'domcontentloaded' });
// Wait a bit for JS to initialize
await page.waitForTimeout(500);
}
/**
* Wait for an element to be visible
* @param page - Playwright page
* @param selector - CSS selector
* @param timeout - Timeout in ms (default 15000)
*/
export async function waitForVisible(page: Page, selector: string, timeout = 15000): Promise<void> {
await page.waitForSelector(selector, { state: 'visible', timeout });
}
/**
* Click an element with retry logic
* @param page - Playwright page
* @param selector - CSS selector
*/
export async function clickElement(page: Page, selector: string): Promise<void> {
await page.click(selector);
}
/**
* Type text into an input element
* @param page - Playwright page
* @param selector - CSS selector
* @param text - Text to type
*/
export async function typeInto(page: Page, selector: string, text: string): Promise<void> {
await page.fill(selector, text);
}
/**
* Get text content of an element
* @param page - Playwright page
* @param selector - CSS selector
* @returns Text content or empty string
*/
export async function getText(page: Page, selector: string): Promise<string> {
try {
const element = await page.$(selector);
if (element) {
return (await element.textContent()) || '';
}
return '';
} catch {
return '';
}
}
/**
* Check if an element is visible
* @param page - Playwright page
* @param selector - CSS selector
* @returns true if visible, false otherwise
*/
export async function isVisible(page: Page, selector: string): Promise<boolean> {
try {
const element = await page.$(selector);
if (element) {
return await element.isVisible();
}
return false;
} catch {
return false;
}
}
/**
* Get count of elements matching selector
* @param page - Playwright page
* @param selector - CSS selector
* @returns Number of matching elements
*/
export async function getElementCount(page: Page, selector: string): Promise<number> {
return await page.locator(selector).count();
}