mirror of
https://github.com/AutoMaker-Org/automaker.git
synced 2026-03-17 10:03:08 +00:00
* Changes from fix/memory-and-context-mobile-friendly * fix: Improve file extension detection and add path traversal protection * refactor: Extract file extension utilities and add path traversal guards Code review improvements: - Extract isMarkdownFilename and isImageFilename to shared image-utils.ts - Remove duplicated code from context-view.tsx and memory-view.tsx - Add path traversal guard for context fixture utilities (matching memory) - Add 7 new tests for context fixture path traversal protection - Total 61 tests pass Addresses code review feedback from PR #813 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: Add e2e tests for profiles crud and board background persistence * Update apps/ui/playwright.config.ts Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fix: Add robust test navigation handling and file filtering * fix: Format NODE_OPTIONS configuration on single line * test: Update profiles and board background persistence tests * test: Replace iPhone 13 Pro with Pixel 5 for mobile test consistency * Update apps/ui/src/components/views/context-view.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * chore: Remove test project directory * feat: Filter context files by type and improve mobile menu visibility --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
113 lines
3.8 KiB
TypeScript
113 lines
3.8 KiB
TypeScript
import { Page, Locator } from '@playwright/test';
|
|
|
|
/**
|
|
* Default timeout for element waiting operations in E2E tests.
|
|
* Increased from 5000ms to 10000ms to accommodate CI environments
|
|
* where dialog rendering may take longer due to React Query data fetching.
|
|
*/
|
|
export const DEFAULT_ELEMENT_TIMEOUT_MS = 10000;
|
|
|
|
/**
|
|
* Wait for the page to load
|
|
* Uses 'load' state instead of 'networkidle' because the app has persistent
|
|
* connections (websockets/polling) that prevent network from ever being idle.
|
|
* Tests should wait for specific elements to verify page is ready.
|
|
*/
|
|
export async function waitForNetworkIdle(page: Page): Promise<void> {
|
|
await page.waitForLoadState('load');
|
|
}
|
|
|
|
/**
|
|
* Wait for an element with a specific data-testid to appear
|
|
*/
|
|
export async function waitForElement(
|
|
page: Page,
|
|
testId: string,
|
|
options?: { timeout?: number; state?: 'attached' | 'visible' | 'hidden' }
|
|
): Promise<Locator> {
|
|
const element = page.locator(`[data-testid="${testId}"]`);
|
|
await element.waitFor({
|
|
timeout: options?.timeout ?? DEFAULT_ELEMENT_TIMEOUT_MS,
|
|
state: options?.state ?? 'visible',
|
|
});
|
|
return element;
|
|
}
|
|
|
|
/**
|
|
* Wait for an element with a specific data-testid to be hidden
|
|
*/
|
|
export async function waitForElementHidden(
|
|
page: Page,
|
|
testId: string,
|
|
options?: { timeout?: number }
|
|
): Promise<void> {
|
|
const element = page.locator(`[data-testid="${testId}"]`);
|
|
await element.waitFor({
|
|
timeout: options?.timeout ?? DEFAULT_ELEMENT_TIMEOUT_MS,
|
|
state: 'hidden',
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Wait for the splash screen to disappear
|
|
* The splash screen has z-[9999] and blocks interactions, so we need to wait for it
|
|
*/
|
|
export async function waitForSplashScreenToDisappear(page: Page, timeout = 5000): Promise<void> {
|
|
try {
|
|
// Check if splash screen is disabled or already shown (fastest check)
|
|
const splashDisabled = await page.evaluate(() => {
|
|
return (
|
|
localStorage.getItem('automaker-disable-splash') === 'true' ||
|
|
localStorage.getItem('automaker-splash-shown-session') === 'true'
|
|
);
|
|
});
|
|
|
|
// If splash is disabled or already shown, it won't appear, so we're done
|
|
if (splashDisabled) {
|
|
return;
|
|
}
|
|
|
|
// Otherwise, wait for the splash screen element to disappear
|
|
// The splash screen is a div with z-[9999] and fixed inset-0
|
|
// We check for elements that match the splash screen pattern
|
|
await page.waitForFunction(
|
|
() => {
|
|
// Check if splash is disabled or already shown
|
|
if (
|
|
localStorage.getItem('automaker-disable-splash') === 'true' ||
|
|
localStorage.getItem('automaker-splash-shown-session') === 'true'
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
// Check for splash screen element by looking for fixed inset-0 with high z-index
|
|
const allDivs = document.querySelectorAll('div');
|
|
for (const div of allDivs) {
|
|
const style = window.getComputedStyle(div);
|
|
const classes = div.className || '';
|
|
// Check if it matches splash screen pattern: fixed, inset-0, and high z-index
|
|
if (
|
|
style.position === 'fixed' &&
|
|
(classes.includes('inset-0') ||
|
|
(style.top === '0px' &&
|
|
style.left === '0px' &&
|
|
style.right === '0px' &&
|
|
style.bottom === '0px')) &&
|
|
(classes.includes('z-[') || parseInt(style.zIndex) >= 9999)
|
|
) {
|
|
// Check if it's visible and blocking (opacity > 0 and pointer-events not none)
|
|
if (style.opacity !== '0' && style.pointerEvents !== 'none') {
|
|
return false; // Splash screen is still visible
|
|
}
|
|
}
|
|
}
|
|
return true; // No visible splash screen found
|
|
},
|
|
{ timeout }
|
|
);
|
|
} catch {
|
|
// Splash screen might not exist or already gone, which is fine
|
|
// No need to wait - if it doesn't exist, we're good
|
|
}
|
|
}
|