test(e2e): fix wx suite — header deps, port pinning, drop legacy-GL tests, wx+pthread worker fix
Suite went 64 failed → 291 passed / 0 failed: - Makefile.wasm: compile with -MMD -MP and include .d files — stale objects relinked against a newer wx lib crashed apps at startup with "function signature mismatch" after any header/vtable change - playwright(.coroutine).config.ts: pin the server port for the whole run (resolvePort from playwright-kicad.config.ts); the 60s freshness window made workers restarted after a failure rotate to a dead port (ERR_CONNECTION_REFUSED cascade across ~50 tests) - drop legacy-GL testing: KiCad renders via WebGL GAL (gal-webgl.spec.ts); remove minimal_test's OpenGL tab/GLTestCanvas, opengl.spec.ts, GL z-order describes, -sLEGACY_GL_EMULATION + gl_immediate_shim.js from the test build, and the orphaned GL baselines - coroutine-pthread repro apps join the `all` target (make clean used to delete them while all never rebuilt them); clean no longer eats checked-in JS like worker_dom_stub.js - bump wxwidgets: guard module-eval document access so wx+pthread apps (threadpool tests) survive Web Worker eval Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
107fc7513f
commit
7629ab978d
53 changed files with 119 additions and 1060 deletions
|
|
@ -1,94 +0,0 @@
|
|||
import { test, expect, MAIN_CANVAS, waitForApp, getCanvasBox } from './utils/fixtures';
|
||||
import { clickTab, clickByLabel, selectComboItem } from './utils/element-tracker';
|
||||
|
||||
async function switchToOpenGLTab(page: any) {
|
||||
// Click OpenGL tab using element registry
|
||||
const clicked = await clickTab(page, 'OpenGL');
|
||||
if (!clicked) {
|
||||
// Fallback: try clicking by label
|
||||
await clickByLabel(page, 'OpenGL');
|
||||
}
|
||||
await page.waitForTimeout(1000);
|
||||
}
|
||||
|
||||
// Open the test dropdown and select by name
|
||||
async function selectGLTest(page: any, testName: string) {
|
||||
// Use combo helper to select from wxChoice dropdown
|
||||
await selectComboItem(page, testName);
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
|
||||
test.describe('OpenGL Tests', () => {
|
||||
test('Vertex Arrays test - debug freeze', async ({ page, testLogger }) => {
|
||||
await page.goto('/minimal_test.html');
|
||||
await waitForApp(page);
|
||||
|
||||
// Switch to OpenGL tab using element registry
|
||||
await switchToOpenGLTab(page);
|
||||
await page.screenshot({ path: 'test-results/gl-01-opengl-tab.png', fullPage: true });
|
||||
|
||||
// Select "Vertex Arrays" test by name
|
||||
await selectGLTest(page, 'Vertex Arrays');
|
||||
|
||||
await page.screenshot({ path: 'test-results/gl-02-vertex-arrays-selected.png', fullPage: true });
|
||||
|
||||
// Wait a bit to see if it freezes
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.screenshot({ path: 'test-results/gl-03-after-wait.png', fullPage: true });
|
||||
|
||||
// Check if app is still responsive
|
||||
const isResponsive = await page.evaluate(() => {
|
||||
return document.querySelector('#canvas') !== null;
|
||||
});
|
||||
expect(isResponsive).toBe(true);
|
||||
});
|
||||
|
||||
test('All GL tests individually', async ({ page, testLogger }) => {
|
||||
await page.goto('/minimal_test.html');
|
||||
await waitForApp(page);
|
||||
|
||||
await switchToOpenGLTab(page);
|
||||
|
||||
const testNames = [
|
||||
'Immediate Mode',
|
||||
'Matrix Operations',
|
||||
'Vertex Arrays',
|
||||
'State Management'
|
||||
];
|
||||
|
||||
for (let i = 0; i < testNames.length; i++) {
|
||||
try {
|
||||
await selectGLTest(page, testNames[i]);
|
||||
await page.screenshot({
|
||||
path: `test-results/gl-test-${i}-${testNames[i].replace(/\s+/g, '-').toLowerCase()}.png`,
|
||||
fullPage: true
|
||||
});
|
||||
} catch (e) {
|
||||
await page.screenshot({
|
||||
path: `test-results/gl-test-${i}-${testNames[i].replace(/\s+/g, '-').toLowerCase()}-error.png`,
|
||||
fullPage: true
|
||||
});
|
||||
}
|
||||
|
||||
await page.waitForTimeout(500);
|
||||
}
|
||||
});
|
||||
|
||||
test('Run All Tests button', async ({ page, testLogger }) => {
|
||||
await page.goto('/minimal_test.html');
|
||||
await waitForApp(page);
|
||||
|
||||
await switchToOpenGLTab(page);
|
||||
|
||||
// Click "Run All Tests" button using element registry
|
||||
const clicked = await clickByLabel(page, 'Run All Tests');
|
||||
expect(clicked, 'Run All Tests button should be found and clicked').toBe(true);
|
||||
await page.waitForTimeout(2000);
|
||||
|
||||
await page.screenshot({ path: 'test-results/gl-run-all-tests.png', fullPage: true });
|
||||
|
||||
// App should remain stable
|
||||
await expect(page.locator(MAIN_CANVAS)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
|
@ -212,24 +212,6 @@ test.describe('wxWidgets WASM - Diagnostics', () => {
|
|||
await page.keyboard.press('Escape');
|
||||
await page.waitForTimeout(300);
|
||||
|
||||
// === TAB 5: OpenGL ===
|
||||
// Click OpenGL tab using element registry
|
||||
await clickTab(page, 'OpenGL');
|
||||
await page.waitForTimeout(1000); // Give GL time to initialize
|
||||
|
||||
await page.screenshot({ path: 'test-results/14-opengl-tab.png', fullPage: true });
|
||||
|
||||
// Click on different GL tests in the dropdown using element tracking
|
||||
const glDropdownOpened = await clickComboButton(page);
|
||||
expect(glDropdownOpened, 'Should be able to open GL test dropdown').toBe(true);
|
||||
await page.waitForTimeout(300);
|
||||
|
||||
// Click "Run All Tests" button using element registry
|
||||
await clickByLabel(page, 'Run All Tests');
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
await page.screenshot({ path: 'test-results/15-opengl-tests.png', fullPage: true });
|
||||
|
||||
// === Menu interaction ===
|
||||
// Click File menu using element registry
|
||||
await clickMenuBarItem(page, 'File');
|
||||
|
|
@ -491,265 +473,3 @@ test.describe('wxWidgets WASM - Stability', () => {
|
|||
await expect(page.locator(MAIN_CANVAS)).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('wxWidgets WASM - OpenGL', () => {
|
||||
test('OpenGL tab switches successfully', async ({ page, testLogger }) => {
|
||||
await page.goto('/minimal_test.html');
|
||||
await waitForApp(page);
|
||||
|
||||
// Click OpenGL tab using element registry
|
||||
await clickTab(page, 'OpenGL');
|
||||
await page.waitForTimeout(1500); // Give GL time to initialize
|
||||
|
||||
// Check that we switched to the OpenGL tab
|
||||
const tabChanged = testLogger.consoleLogs.some(log => log.includes('Tab changed to: OpenGL'));
|
||||
expect(tabChanged).toBe(true);
|
||||
|
||||
// Save screenshot for visual verification
|
||||
await page.screenshot({ path: 'test-results/opengl-tab-initial.png', fullPage: true });
|
||||
});
|
||||
|
||||
test('OpenGL tab interaction without crashes', async ({ page, testLogger }) => {
|
||||
await page.goto('/minimal_test.html');
|
||||
await waitForApp(page);
|
||||
|
||||
// Switch to OpenGL tab using element registry
|
||||
await clickTab(page, 'OpenGL');
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Click "Run All Tests" button using element registry
|
||||
await clickByLabel(page, 'Run All Tests');
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Save screenshot after running tests
|
||||
await page.screenshot({ path: 'test-results/opengl-after-tests.png', fullPage: true });
|
||||
|
||||
// App should remain stable - no crashes or critical errors
|
||||
await expect(page.locator(MAIN_CANVAS)).toBeVisible();
|
||||
|
||||
// Note: wxPrintf logs go to stdout which may not appear in browser console
|
||||
// The main verification is that the app doesn't crash
|
||||
const criticalErrors = testLogger.errors.filter(e => !isKnownWarning(e));
|
||||
expect(criticalErrors.length).toBe(0);
|
||||
});
|
||||
|
||||
test('OpenGL tab renders without errors', async ({ page, testLogger }) => {
|
||||
await page.goto('/minimal_test.html');
|
||||
await waitForApp(page);
|
||||
|
||||
// Switch to OpenGL tab using element registry
|
||||
await clickTab(page, 'OpenGL');
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Click "Run All Tests" button using element registry
|
||||
await clickByLabel(page, 'Run All Tests');
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
// Take screenshot before checking GL canvas
|
||||
await page.screenshot({ path: 'test-results/opengl-before-debug.png', fullPage: true });
|
||||
|
||||
// Debug: Check GL canvas element position and visibility
|
||||
const glCanvasInfo = await page.evaluate(() => {
|
||||
const glCanvas = document.querySelector('[id^="glcanvas-"]') as HTMLCanvasElement;
|
||||
if (!glCanvas) return { exists: false };
|
||||
const style = window.getComputedStyle(glCanvas);
|
||||
return {
|
||||
exists: true,
|
||||
id: glCanvas.id,
|
||||
display: style.display,
|
||||
visibility: style.visibility,
|
||||
pointerEvents: style.pointerEvents,
|
||||
position: style.position,
|
||||
left: style.left,
|
||||
top: style.top,
|
||||
width: style.width,
|
||||
height: style.height,
|
||||
canvasWidth: glCanvas.width,
|
||||
canvasHeight: glCanvas.height,
|
||||
zIndex: style.zIndex,
|
||||
boundingRect: glCanvas.getBoundingClientRect()
|
||||
};
|
||||
});
|
||||
|
||||
// Take screenshot of GL canvas
|
||||
const screenshot = await page.screenshot();
|
||||
expect(screenshot.length).toBeGreaterThan(0);
|
||||
|
||||
// App should still be responsive after GL rendering
|
||||
await expect(page.locator(MAIN_CANVAS)).toBeVisible();
|
||||
|
||||
// No critical JavaScript errors
|
||||
const criticalErrors = testLogger.errors.filter(e => !isKnownWarning(e));
|
||||
expect(criticalErrors.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('wxWidgets WASM - Canvas Z-Ordering and Visibility', () => {
|
||||
test('GL canvas should hide when switching away from OpenGL tab', async ({ page, testLogger }) => {
|
||||
await page.goto('/minimal_test.html');
|
||||
await waitForApp(page);
|
||||
|
||||
// Step 1: Go to OpenGL tab first using element registry
|
||||
await clickTab(page, 'OpenGL');
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
// Verify we're on OpenGL tab
|
||||
const onOpenGLTab = testLogger.consoleLogs.some(log => log.includes('Tab changed to: OpenGL'));
|
||||
expect(onOpenGLTab).toBe(true);
|
||||
|
||||
await page.screenshot({ path: 'test-results/glcanvas-01-on-opengl-tab.png', fullPage: true });
|
||||
|
||||
// Check GL canvas is visible
|
||||
const glCanvasBefore = await page.evaluate(() => {
|
||||
const glCanvas = document.querySelector('[id^="glcanvas-"]') as HTMLCanvasElement;
|
||||
if (!glCanvas) return { exists: false, display: 'none' };
|
||||
return {
|
||||
exists: true,
|
||||
id: glCanvas.id,
|
||||
display: window.getComputedStyle(glCanvas).display,
|
||||
zIndex: window.getComputedStyle(glCanvas).zIndex
|
||||
};
|
||||
});
|
||||
|
||||
// Step 2: Switch to Controls tab using element registry
|
||||
await clickTab(page, 'Controls');
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
await page.screenshot({ path: 'test-results/glcanvas-02-after-switch-to-controls.png', fullPage: true });
|
||||
|
||||
// Check GL canvas visibility after switching tabs
|
||||
const glCanvasAfter = await page.evaluate(() => {
|
||||
const glCanvas = document.querySelector('[id^="glcanvas-"]') as HTMLCanvasElement;
|
||||
if (!glCanvas) return { exists: false, display: 'none' };
|
||||
return {
|
||||
exists: true,
|
||||
id: glCanvas.id,
|
||||
display: window.getComputedStyle(glCanvas).display,
|
||||
visibility: window.getComputedStyle(glCanvas).visibility,
|
||||
zIndex: window.getComputedStyle(glCanvas).zIndex
|
||||
};
|
||||
});
|
||||
|
||||
// Step 3: Switch to Drawing tab using element registry
|
||||
await clickTab(page, 'Drawing');
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
await page.screenshot({ path: 'test-results/glcanvas-03-on-drawing-tab.png', fullPage: true });
|
||||
|
||||
// Step 4: Switch to Lists tab using element registry
|
||||
await clickTab(page, 'Lists');
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
await page.screenshot({ path: 'test-results/glcanvas-04-on-lists-tab.png', fullPage: true });
|
||||
|
||||
// GL canvas should be hidden (display: none) when not on OpenGL tab
|
||||
if (glCanvasAfter.exists) {
|
||||
expect(glCanvasAfter.display).toBe('none');
|
||||
}
|
||||
});
|
||||
|
||||
test('dropdown should appear above GL canvas on OpenGL tab', async ({ page, testLogger }) => {
|
||||
await page.goto('/minimal_test.html');
|
||||
await waitForApp(page);
|
||||
|
||||
const canvas = page.locator(MAIN_CANVAS);
|
||||
const box = await canvas.boundingBox();
|
||||
if (!box) throw new Error('Canvas not found');
|
||||
|
||||
// Step 1: Go to OpenGL tab using element registry
|
||||
await clickTab(page, 'OpenGL');
|
||||
await page.waitForTimeout(1000);
|
||||
|
||||
await page.screenshot({ path: 'test-results/zorder-01-opengl-tab.png', fullPage: true });
|
||||
|
||||
// Step 2: Click on the test selection dropdown (wxChoice) on the OpenGL tab using element tracking
|
||||
// Open dropdown using element tracking
|
||||
const dropdownClicked = await clickComboButton(page);
|
||||
expect(dropdownClicked, 'Should be able to click dropdown on OpenGL tab').toBe(true);
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
await page.screenshot({ path: 'test-results/zorder-02-dropdown-clicked.png', fullPage: true });
|
||||
|
||||
// Check z-index values
|
||||
const zIndexInfo = await page.evaluate(() => {
|
||||
const glCanvas = document.querySelector('[id^="glcanvas-"]') as HTMLCanvasElement;
|
||||
const popupWindows = document.querySelectorAll('[id^="window-"]');
|
||||
|
||||
const result: any = {
|
||||
glCanvas: null,
|
||||
popupWindows: []
|
||||
};
|
||||
|
||||
if (glCanvas) {
|
||||
const style = window.getComputedStyle(glCanvas);
|
||||
result.glCanvas = {
|
||||
id: glCanvas.id,
|
||||
zIndex: style.zIndex,
|
||||
display: style.display
|
||||
};
|
||||
}
|
||||
|
||||
popupWindows.forEach((w) => {
|
||||
const el = w as HTMLElement;
|
||||
const style = window.getComputedStyle(el);
|
||||
if (style.display !== 'none') {
|
||||
result.popupWindows.push({
|
||||
id: el.id,
|
||||
zIndex: style.zIndex,
|
||||
display: style.display,
|
||||
width: style.width,
|
||||
height: style.height
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
// Step 3: Close the dropdown using Escape
|
||||
await page.keyboard.press('Escape');
|
||||
await page.waitForTimeout(300);
|
||||
|
||||
await page.screenshot({ path: 'test-results/zorder-03-dropdown-closed.png', fullPage: true });
|
||||
|
||||
// After the fix, popup z-index should be higher than GL canvas z-index
|
||||
// This will be verified by visual inspection of screenshots
|
||||
});
|
||||
|
||||
test('switching tabs multiple times maintains correct visibility', async ({ page, testLogger }) => {
|
||||
await page.goto('/minimal_test.html');
|
||||
await waitForApp(page);
|
||||
|
||||
const canvas = page.locator(MAIN_CANVAS);
|
||||
const box = await canvas.boundingBox();
|
||||
if (!box) throw new Error('Canvas not found');
|
||||
|
||||
// Tab switch sequence: Controls -> OpenGL -> Lists -> OpenGL -> Drawing -> Controls
|
||||
const tabNames = ['Controls', 'OpenGL', 'Lists', 'OpenGL', 'Drawing', 'Controls'];
|
||||
|
||||
for (let i = 0; i < tabNames.length; i++) {
|
||||
const tabName = tabNames[i];
|
||||
await clickTab(page, tabName);
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
await page.screenshot({
|
||||
path: `test-results/tabswitch-${String(i + 1).padStart(2, '0')}-${tabName.toLowerCase()}.png`,
|
||||
fullPage: true
|
||||
});
|
||||
|
||||
// Check GL canvas visibility
|
||||
const glVisible = await page.evaluate(() => {
|
||||
const glCanvas = document.querySelector('[id^="glcanvas-"]') as HTMLCanvasElement;
|
||||
if (!glCanvas) return 'not-created';
|
||||
return window.getComputedStyle(glCanvas).display;
|
||||
});
|
||||
|
||||
// GL canvas should only be visible on OpenGL tab
|
||||
if (tabName === 'OpenGL') {
|
||||
expect(glVisible).toBe('block');
|
||||
} else {
|
||||
expect(glVisible).toBe('none');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue