Refactor test logging into shared utilities
- Extract common logging code to tests/e2e/utils/ - fixtures.ts: Playwright fixture with automatic log capture - test-utils.ts: Logging utilities and helper functions - Each test now automatically captures: - Console logs with timestamps and log levels - Page errors with full stack traces - Log files written per test to tests/logs/ - <test-name>.log for all console output - <test-name>.errors.log only when errors occur - Update all 13 spec files to use shared fixtures - Update README with test structure and logging docs - Net reduction of ~700 lines by removing duplicated code 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
2264a22685
commit
26181bb929
16 changed files with 431 additions and 1131 deletions
|
|
@ -13,7 +13,7 @@ Playwright tests for verifying the wxWidgets WASM port.
|
||||||
../scripts/build-wasm-test.sh
|
../scripts/build-wasm-test.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
This builds `wasm-app/minimal_test.{html,js,wasm}`.
|
This builds `wasm-app/minimal_test.{html,js,wasm}` and standalone test apps.
|
||||||
|
|
||||||
## Running Tests
|
## Running Tests
|
||||||
|
|
||||||
|
|
@ -22,6 +22,61 @@ npm install
|
||||||
npm test
|
npm test
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To run specific tests:
|
||||||
|
```bash
|
||||||
|
npx playwright test menu.spec.ts # Run menu tests only
|
||||||
|
npx playwright test --grep "wxTimer" # Run tests matching pattern
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
tests/
|
||||||
|
├── e2e/ # Playwright test specs
|
||||||
|
│ ├── utils/ # Shared test utilities
|
||||||
|
│ │ ├── fixtures.ts # Playwright fixtures with auto-logging
|
||||||
|
│ │ └── test-utils.ts # Logging and helper functions
|
||||||
|
│ ├── menu.spec.ts # wxMenuBar tests
|
||||||
|
│ ├── timer.spec.ts # wxTimer tests
|
||||||
|
│ ├── dialog.spec.ts # wxDialog/wxMessageBox tests
|
||||||
|
│ ├── tree.spec.ts # wxTreeCtrl tests
|
||||||
|
│ ├── grid.spec.ts # wxGrid/wxSpinCtrl/wxSearchCtrl tests
|
||||||
|
│ ├── opengl.spec.ts # OpenGL tab tests
|
||||||
|
│ ├── wxwidgets.spec.ts # Comprehensive UI interaction tests
|
||||||
|
│ └── ...
|
||||||
|
├── logs/ # Test logs (auto-generated)
|
||||||
|
├── test-results/ # Screenshots (auto-generated)
|
||||||
|
├── baseline-screenshots/ # Reference screenshots for comparison
|
||||||
|
├── wasm-app/ # Built WASM test applications
|
||||||
|
│ ├── minimal_test.html # Main test app
|
||||||
|
│ └── standalone/ # Individual component test apps
|
||||||
|
└── playwright.config.ts # Playwright configuration
|
||||||
|
```
|
||||||
|
|
||||||
|
## Logging
|
||||||
|
|
||||||
|
Each test automatically captures:
|
||||||
|
- Console logs with timestamps and log levels
|
||||||
|
- Page errors with full stack traces
|
||||||
|
|
||||||
|
Log files are written to `logs/` after each test:
|
||||||
|
- `<test-name>.log` - All console output
|
||||||
|
- `<test-name>.errors.log` - Errors only (created if errors occurred)
|
||||||
|
|
||||||
|
Example log format:
|
||||||
|
```
|
||||||
|
[2025-11-29T19:39:42.165Z] [LOG] [EVENT] Application started
|
||||||
|
[2025-11-29T19:39:42.733Z] [WARNING] GPU stall due to ReadPixels
|
||||||
|
[2025-11-29T19:39:42.801Z] [ERROR] Some error message
|
||||||
|
```
|
||||||
|
|
||||||
|
## Screenshots
|
||||||
|
|
||||||
|
Tests capture screenshots to `test-results/`. Compare against baselines:
|
||||||
|
```bash
|
||||||
|
../scripts/compare-screenshots.sh
|
||||||
|
```
|
||||||
|
|
||||||
## Viewing the App Directly
|
## Viewing the App Directly
|
||||||
|
|
||||||
Start a local server in the wasm-app directory:
|
Start a local server in the wasm-app directory:
|
||||||
|
|
@ -41,3 +96,26 @@ python3 -m http.server 8000
|
||||||
```
|
```
|
||||||
|
|
||||||
Then open http://localhost:8000/minimal_test.html
|
Then open http://localhost:8000/minimal_test.html
|
||||||
|
|
||||||
|
## Test Categories
|
||||||
|
|
||||||
|
| Spec File | Tests | Description |
|
||||||
|
|-----------|-------|-------------|
|
||||||
|
| `wxwidgets.spec.ts` | Comprehensive | Full UI interaction, stability, OpenGL |
|
||||||
|
| `menu.spec.ts` | wxMenuBar | Menu bar visibility and interactions |
|
||||||
|
| `timer.spec.ts` | wxTimer | Timer start/stop/reset functionality |
|
||||||
|
| `dialog.spec.ts` | wxDialog | Message boxes and custom dialogs |
|
||||||
|
| `tree.spec.ts` | wxTreeCtrl | Tree control with expand/collapse |
|
||||||
|
| `grid.spec.ts` | wxGrid | Grid, SpinCtrl, SearchCtrl |
|
||||||
|
| `opengl.spec.ts` | OpenGL | GL tests (immediate mode, vertex arrays) |
|
||||||
|
| `aui.spec.ts` | wxAuiManager | Dockable panels |
|
||||||
|
| `clipboard.spec.ts` | wxClipboard | Copy/paste operations |
|
||||||
|
| `filedialog.spec.ts` | wxFileDialog | File open/save dialogs |
|
||||||
|
| `layout.spec.ts` | wxSplitter | Splitter and scrolled windows |
|
||||||
|
| `toolbar.spec.ts` | wxToolBar | Toolbar buttons and status bar |
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
|
||||||
|
- **Timer tests**: May fail due to timing sensitivity
|
||||||
|
- **Tree tests**: Button click positions may vary
|
||||||
|
- **wxGrid**: Not fully implemented (expected failures marked with `test.fail`)
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,21 @@
|
||||||
// wxAuiManager Tests - AUI docking system KiCad uses extensively
|
// wxAuiManager Tests - AUI docking system KiCad uses extensively
|
||||||
import { test, expect, Page } from '@playwright/test';
|
import { test, expect, MAIN_CANVAS, tryLoadApp, getCanvasBox } from './utils/fixtures';
|
||||||
|
|
||||||
const MAIN_CANVAS = '#canvas';
|
|
||||||
|
|
||||||
async function tryLoadApp(page: Page, timeout = 15000) {
|
|
||||||
try {
|
|
||||||
await page.waitForSelector(MAIN_CANVAS, { state: 'visible', timeout });
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test.describe('wxAuiManager Tests', () => {
|
test.describe('wxAuiManager Tests', () => {
|
||||||
|
|
||||||
test('AUI test app loads successfully', async ({ page }) => {
|
test('AUI test app loads successfully', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => errors.push(`[PAGE_ERROR] ${err.message}`));
|
|
||||||
page.on('console', msg => logs.push(`[${msg.type()}] ${msg.text()}`));
|
|
||||||
|
|
||||||
await page.goto('/standalone/aui/aui_test.html');
|
await page.goto('/standalone/aui/aui_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/aui-01-loaded.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/aui-01-loaded.png', fullPage: true });
|
||||||
|
|
||||||
const hasStartup = logs.some(l => l.includes('AUI test app started'));
|
const hasStartup = testLogger.consoleLogs.some(l => l.includes('AUI test app started'));
|
||||||
|
|
||||||
console.log('AUI loaded:', loaded);
|
|
||||||
console.log('AUI logs:', logs.filter(l => l.includes('AUI')));
|
|
||||||
console.log('AUI errors:', errors);
|
|
||||||
|
|
||||||
expect(loaded, 'AUI app should load').toBe(true);
|
expect(loaded, 'AUI app should load').toBe(true);
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('AUI dockable panels are visible', async ({ page }) => {
|
test('AUI dockable panels are visible', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/aui/aui_test.html');
|
await page.goto('/standalone/aui/aui_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -50,16 +25,12 @@ test.describe('wxAuiManager Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/aui-02-panels.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/aui-02-panels.png', fullPage: true });
|
||||||
|
|
||||||
const hasPanelsLog = logs.some(l => l.includes('dockable panels'));
|
const hasPanelsLog = testLogger.consoleLogs.some(l => l.includes('dockable panels'));
|
||||||
console.log('Panel logs:', logs.filter(l => l.includes('AUI') || l.includes('panel')));
|
|
||||||
|
|
||||||
expect(hasPanelsLog).toBe(true);
|
expect(hasPanelsLog).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Panel close button can be clicked', async ({ page }) => {
|
test('Panel close button can be clicked', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/aui/aui_test.html');
|
await page.goto('/standalone/aui/aui_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -67,28 +38,19 @@ test.describe('wxAuiManager Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Click on Properties panel close button (top right of left panel)
|
// Click on Properties panel close button (top right of left panel)
|
||||||
// Left panel is at left edge, close button at top right of its title bar
|
|
||||||
await page.mouse.click(box.x + 145, box.y + 35);
|
await page.mouse.click(box.x + 145, box.y + 35);
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/aui-03-close-clicked.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/aui-03-close-clicked.png', fullPage: true });
|
||||||
|
|
||||||
const hasCloseEvent = logs.some(l => l.includes('Pane closing'));
|
|
||||||
console.log('Close events:', logs.filter(l => l.includes('Pane') || l.includes('close')));
|
|
||||||
|
|
||||||
// Smoke test
|
// Smoke test
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Panel can be dragged', async ({ page }) => {
|
test('Panel can be dragged', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/aui/aui_test.html');
|
await page.goto('/standalone/aui/aui_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -96,9 +58,7 @@ test.describe('wxAuiManager Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Drag Properties panel title bar
|
// Drag Properties panel title bar
|
||||||
const titleX = box.x + 75;
|
const titleX = box.x + 75;
|
||||||
|
|
@ -116,13 +76,7 @@ test.describe('wxAuiManager Tests', () => {
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Multiple panels can be interacted with', async ({ page }) => {
|
test('Multiple panels can be interacted with', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => errors.push(err.message));
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/aui/aui_test.html');
|
await page.goto('/standalone/aui/aui_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -130,9 +84,7 @@ test.describe('wxAuiManager Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Click in Properties panel
|
// Click in Properties panel
|
||||||
await page.mouse.click(box.x + 75, box.y + 200);
|
await page.mouse.click(box.x + 75, box.y + 200);
|
||||||
|
|
@ -152,9 +104,6 @@ test.describe('wxAuiManager Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/aui-05-multi-panel.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/aui-05-multi-panel.png', fullPage: true });
|
||||||
|
|
||||||
console.log('\n=== AUI EVENTS ===');
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
logs.filter(l => l.includes('AUI')).forEach(l => console.log(l));
|
|
||||||
|
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,53 +1,23 @@
|
||||||
// wxClipboard Tests - Clipboard operations for KiCad copy/paste
|
// wxClipboard Tests - Clipboard operations for KiCad copy/paste
|
||||||
import { test, expect, Page } from '@playwright/test';
|
import { test, expect, MAIN_CANVAS, tryLoadApp, getCanvasBox } from './utils/fixtures';
|
||||||
|
|
||||||
const MAIN_CANVAS = '#canvas';
|
|
||||||
|
|
||||||
async function waitForApp(page: Page, timeout = 30000) {
|
|
||||||
await page.waitForSelector(MAIN_CANVAS, { state: 'visible', timeout });
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function tryLoadApp(page: Page) {
|
|
||||||
try {
|
|
||||||
await waitForApp(page, 15000);
|
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test.describe('wxClipboard Tests', () => {
|
test.describe('wxClipboard Tests', () => {
|
||||||
|
|
||||||
test('Clipboard test app loads successfully', async ({ page }) => {
|
test('Clipboard test app loads successfully', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => {
|
|
||||||
errors.push(`[PAGE_ERROR] ${err.message}`);
|
|
||||||
});
|
|
||||||
page.on('console', msg => {
|
|
||||||
logs.push(`[${msg.type()}] ${msg.text()}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/standalone/clipboard/clipboard_test.html');
|
await page.goto('/standalone/clipboard/clipboard_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/clipboard-01-loaded.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/clipboard-01-loaded.png', fullPage: true });
|
||||||
|
|
||||||
const hasStartupLog = logs.some(l => l.includes('wxClipboard test app started') || l.includes('Clipboard test app started'));
|
const hasStartupLog = testLogger.consoleLogs.some(l =>
|
||||||
console.log('Clipboard app logs:', logs.filter(l => l.includes('CLIPBOARD')));
|
l.includes('wxClipboard test app started') || l.includes('Clipboard test app started')
|
||||||
console.log('Clipboard app loaded:', loaded);
|
);
|
||||||
|
|
||||||
expect(loaded, 'wxClipboard app should load').toBe(true);
|
expect(loaded, 'wxClipboard app should load').toBe(true);
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Copy button can be clicked', async ({ page }) => {
|
test('Copy button can be clicked', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/clipboard/clipboard_test.html');
|
await page.goto('/standalone/clipboard/clipboard_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -55,9 +25,7 @@ test.describe('wxClipboard Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Click "Copy to Clipboard" button
|
// Click "Copy to Clipboard" button
|
||||||
await page.mouse.click(box.x + 100, box.y + 220);
|
await page.mouse.click(box.x + 100, box.y + 220);
|
||||||
|
|
@ -65,17 +33,10 @@ test.describe('wxClipboard Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/clipboard-02-copy-clicked.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/clipboard-02-copy-clicked.png', fullPage: true });
|
||||||
|
|
||||||
const hasCopyLog = logs.some(l => l.includes('copy') || l.includes('Copy') || l.includes('Copied'));
|
|
||||||
console.log('Copy logs:', logs.filter(l => l.includes('CLIPBOARD') || l.includes('copy') || l.includes('Copy')));
|
|
||||||
|
|
||||||
expect(true).toBe(true); // Smoke test
|
expect(true).toBe(true); // Smoke test
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Paste button can be clicked', async ({ page }) => {
|
test('Paste button can be clicked', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/clipboard/clipboard_test.html');
|
await page.goto('/standalone/clipboard/clipboard_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -83,9 +44,7 @@ test.describe('wxClipboard Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// First copy something
|
// First copy something
|
||||||
await page.mouse.click(box.x + 100, box.y + 220);
|
await page.mouse.click(box.x + 100, box.y + 220);
|
||||||
|
|
@ -97,16 +56,10 @@ test.describe('wxClipboard Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/clipboard-03-paste-clicked.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/clipboard-03-paste-clicked.png', fullPage: true });
|
||||||
|
|
||||||
console.log('Paste logs:', logs.filter(l => l.includes('CLIPBOARD') || l.includes('paste') || l.includes('Paste')));
|
|
||||||
|
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Check clipboard button works', async ({ page }) => {
|
test('Check clipboard button works', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/clipboard/clipboard_test.html');
|
await page.goto('/standalone/clipboard/clipboard_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -114,9 +67,7 @@ test.describe('wxClipboard Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Click "Check Clipboard" button
|
// Click "Check Clipboard" button
|
||||||
await page.mouse.click(box.x + 400, box.y + 220);
|
await page.mouse.click(box.x + 400, box.y + 220);
|
||||||
|
|
@ -124,16 +75,10 @@ test.describe('wxClipboard Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/clipboard-04-check-clicked.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/clipboard-04-check-clicked.png', fullPage: true });
|
||||||
|
|
||||||
console.log('Check logs:', logs.filter(l => l.includes('CLIPBOARD') || l.includes('Check') || l.includes('contains')));
|
|
||||||
|
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Clear clipboard button works', async ({ page }) => {
|
test('Clear clipboard button works', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/clipboard/clipboard_test.html');
|
await page.goto('/standalone/clipboard/clipboard_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -141,9 +86,7 @@ test.describe('wxClipboard Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// First copy something
|
// First copy something
|
||||||
await page.mouse.click(box.x + 100, box.y + 220);
|
await page.mouse.click(box.x + 100, box.y + 220);
|
||||||
|
|
@ -155,18 +98,10 @@ test.describe('wxClipboard Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/clipboard-05-clear-clicked.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/clipboard-05-clear-clicked.png', fullPage: true });
|
||||||
|
|
||||||
console.log('Clear logs:', logs.filter(l => l.includes('CLIPBOARD') || l.includes('clear') || l.includes('Clear')));
|
|
||||||
|
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Full clipboard flow: copy, check, paste, clear', async ({ page }) => {
|
test('Full clipboard flow: copy, check, paste, clear', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => errors.push(err.message));
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/clipboard/clipboard_test.html');
|
await page.goto('/standalone/clipboard/clipboard_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -174,9 +109,7 @@ test.describe('wxClipboard Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// 1. Copy
|
// 1. Copy
|
||||||
await page.mouse.click(box.x + 100, box.y + 220);
|
await page.mouse.click(box.x + 100, box.y + 220);
|
||||||
|
|
@ -196,9 +129,6 @@ test.describe('wxClipboard Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/clipboard-06-full-flow.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/clipboard-06-full-flow.png', fullPage: true });
|
||||||
|
|
||||||
console.log('\n=== CLIPBOARD EVENTS ===');
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
logs.filter(l => l.includes('CLIPBOARD')).forEach(l => console.log(l));
|
|
||||||
|
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,21 @@
|
||||||
import { test, expect, Page } from '@playwright/test';
|
import { test, expect, MAIN_CANVAS, tryLoadApp, getCanvasBox } from './utils/fixtures';
|
||||||
|
|
||||||
const MAIN_CANVAS = '#canvas';
|
|
||||||
|
|
||||||
async function tryLoadApp(page: Page, timeout = 15000) {
|
|
||||||
try {
|
|
||||||
await page.waitForSelector(MAIN_CANVAS, { state: 'visible', timeout });
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test.describe('wxDialog/wxMessageBox Tests', () => {
|
test.describe('wxDialog/wxMessageBox Tests', () => {
|
||||||
test('Dialog test app loads successfully', async ({ page }) => {
|
test('Dialog test app loads successfully', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
const pageErrors: string[] = [];
|
|
||||||
|
|
||||||
page.on('console', msg => consoleLogs.push(msg.text()));
|
|
||||||
page.on('pageerror', err => pageErrors.push(err.message));
|
|
||||||
|
|
||||||
await page.goto('/standalone/dialog/dialog_test.html');
|
await page.goto('/standalone/dialog/dialog_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/dialog-01-loaded.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialog-01-loaded.png', fullPage: true });
|
||||||
|
|
||||||
const hasStartupLog = consoleLogs.some(log =>
|
const hasStartupLog = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('DIALOG_TEST') && log.includes('started successfully')
|
log.includes('DIALOG_TEST') && log.includes('started successfully')
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('Dialog app logs:', consoleLogs.filter(l => l.includes('DIALOG')));
|
|
||||||
console.log('Dialog app loaded:', hasStartupLog);
|
|
||||||
|
|
||||||
expect(loaded, 'Canvas should be visible').toBe(true);
|
expect(loaded, 'Canvas should be visible').toBe(true);
|
||||||
expect(pageErrors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Info dialog button can be clicked', async ({ page }) => {
|
test('Info dialog button can be clicked', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
page.on('console', msg => consoleLogs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/dialog/dialog_test.html');
|
await page.goto('/standalone/dialog/dialog_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -47,32 +23,23 @@ test.describe('wxDialog/wxMessageBox Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Info Dialog button is first in the wxMessageBox row
|
// Info Dialog button is first in the wxMessageBox row
|
||||||
// Layout: description (~80px) + fieldset header + buttons
|
|
||||||
// Buttons are centered horizontally in 3-button row
|
|
||||||
// Estimate: first button at ~(centerX - 120), y ~115
|
|
||||||
const centerX = box.width / 2;
|
const centerX = box.width / 2;
|
||||||
await page.mouse.click(box.x + centerX - 110, box.y + 115);
|
await page.mouse.click(box.x + centerX - 110, box.y + 115);
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
console.log('Info dialog logs:', consoleLogs.filter(l => l.includes('DIALOG')));
|
|
||||||
await page.screenshot({ path: 'test-results/dialog-02-info-clicked.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialog-02-info-clicked.png', fullPage: true });
|
||||||
|
|
||||||
const hasInfoEvent = consoleLogs.some(log =>
|
const hasInfoEvent = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('Opening Info dialog')
|
log.includes('Opening Info dialog')
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(hasInfoEvent, 'Info dialog should open').toBe(true);
|
expect(hasInfoEvent, 'Info dialog should open').toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Yes/No dialog button can be clicked', async ({ page }) => {
|
test('Yes/No dialog button can be clicked', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
page.on('console', msg => consoleLogs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/dialog/dialog_test.html');
|
await page.goto('/standalone/dialog/dialog_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -80,28 +47,22 @@ test.describe('wxDialog/wxMessageBox Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Yes/No Dialog button is second (center) in the wxMessageBox row
|
// Yes/No Dialog button is second (center) in the wxMessageBox row
|
||||||
const centerX = box.width / 2;
|
const centerX = box.width / 2;
|
||||||
await page.mouse.click(box.x + centerX, box.y + 115);
|
await page.mouse.click(box.x + centerX, box.y + 115);
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
console.log('Yes/No dialog logs:', consoleLogs.filter(l => l.includes('DIALOG')));
|
|
||||||
await page.screenshot({ path: 'test-results/dialog-03-yesno-clicked.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialog-03-yesno-clicked.png', fullPage: true });
|
||||||
|
|
||||||
const hasYesNoEvent = consoleLogs.some(log =>
|
const hasYesNoEvent = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('Opening Yes/No dialog')
|
log.includes('Opening Yes/No dialog')
|
||||||
);
|
);
|
||||||
expect(hasYesNoEvent, 'Yes/No dialog should open').toBe(true);
|
expect(hasYesNoEvent, 'Yes/No dialog should open').toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Error dialog button can be clicked', async ({ page }) => {
|
test('Error dialog button can be clicked', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
page.on('console', msg => consoleLogs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/dialog/dialog_test.html');
|
await page.goto('/standalone/dialog/dialog_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -109,28 +70,22 @@ test.describe('wxDialog/wxMessageBox Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Error Dialog button is third (rightmost) in the wxMessageBox row
|
// Error Dialog button is third (rightmost) in the wxMessageBox row
|
||||||
const centerX = box.width / 2;
|
const centerX = box.width / 2;
|
||||||
await page.mouse.click(box.x + centerX + 110, box.y + 115);
|
await page.mouse.click(box.x + centerX + 110, box.y + 115);
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
console.log('Error dialog logs:', consoleLogs.filter(l => l.includes('DIALOG')));
|
|
||||||
await page.screenshot({ path: 'test-results/dialog-04-error-clicked.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialog-04-error-clicked.png', fullPage: true });
|
||||||
|
|
||||||
const hasErrorEvent = consoleLogs.some(log =>
|
const hasErrorEvent = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('Opening Error dialog')
|
log.includes('Opening Error dialog')
|
||||||
);
|
);
|
||||||
expect(hasErrorEvent, 'Error dialog should open').toBe(true);
|
expect(hasErrorEvent, 'Error dialog should open').toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Custom dialog button can be clicked', async ({ page }) => {
|
test('Custom dialog button can be clicked', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
page.on('console', msg => consoleLogs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/dialog/dialog_test.html');
|
await page.goto('/standalone/dialog/dialog_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -138,17 +93,13 @@ test.describe('wxDialog/wxMessageBox Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Custom Dialog button is first in the wxDialog row (row 2)
|
// Custom Dialog button is first in the wxDialog row (row 2)
|
||||||
// Y position is lower (~175) since it's in the second fieldset
|
|
||||||
const centerX = box.width / 2;
|
const centerX = box.width / 2;
|
||||||
await page.mouse.click(box.x + centerX - 60, box.y + 175);
|
await page.mouse.click(box.x + centerX - 60, box.y + 175);
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
console.log('Custom dialog logs:', consoleLogs.filter(l => l.includes('DIALOG')));
|
|
||||||
await page.screenshot({ path: 'test-results/dialog-05-custom-clicked.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialog-05-custom-clicked.png', fullPage: true });
|
||||||
|
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,18 @@
|
||||||
import { test, expect, Page } from '@playwright/test';
|
import { test, expect, MAIN_CANVAS, waitForApp, getCanvasBox } from './utils/fixtures';
|
||||||
|
|
||||||
const MAIN_CANVAS = '#canvas';
|
async function switchToDialogsTab(page: any, box: { x: number; y: number }) {
|
||||||
|
|
||||||
async function waitForApp(page: Page) {
|
|
||||||
await page.waitForSelector(MAIN_CANVAS, { state: 'visible', timeout: 30000 });
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function switchToDialogsTab(page: Page, box: { x: number; y: number }) {
|
|
||||||
// Dialogs tab is the 7th tab (after Grid)
|
// Dialogs tab is the 7th tab (after Grid)
|
||||||
// Tab widths: Controls, Text Input, Drawing, Lists, OpenGL, Grid, Dialogs
|
|
||||||
// Dialogs tab center is approximately at x = 360-380
|
|
||||||
await page.mouse.click(box.x + 370, box.y + 35);
|
await page.mouse.click(box.x + 370, box.y + 35);
|
||||||
await page.waitForTimeout(1000);
|
await page.waitForTimeout(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
test.describe('Dialogs Tab Tests', () => {
|
test.describe('Dialogs Tab Tests', () => {
|
||||||
|
|
||||||
test('Dialogs tab renders correctly', async ({ page }) => {
|
test('Dialogs tab renders correctly', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => {
|
|
||||||
errors.push(`[PAGE_ERROR] ${err.message}`);
|
|
||||||
});
|
|
||||||
page.on('console', msg => {
|
|
||||||
logs.push(`[${msg.type()}] ${msg.text()}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Screenshot before switching to Dialogs tab
|
// Screenshot before switching to Dialogs tab
|
||||||
await page.screenshot({ path: 'test-results/dialogs-00-initial.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialogs-00-initial.png', fullPage: true });
|
||||||
|
|
@ -42,10 +21,6 @@ test.describe('Dialogs Tab Tests', () => {
|
||||||
await switchToDialogsTab(page, box);
|
await switchToDialogsTab(page, box);
|
||||||
await page.screenshot({ path: 'test-results/dialogs-01-tab-selected.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialogs-01-tab-selected.png', fullPage: true });
|
||||||
|
|
||||||
// Log any console output
|
|
||||||
console.log('\n=== CONSOLE LOGS ===');
|
|
||||||
logs.filter(l => l.includes('Tab changed')).forEach(log => console.log(log));
|
|
||||||
|
|
||||||
// Verify app is still responsive
|
// Verify app is still responsive
|
||||||
const isResponsive = await page.evaluate(() => {
|
const isResponsive = await page.evaluate(() => {
|
||||||
return document.querySelector('#canvas') !== null;
|
return document.querySelector('#canvas') !== null;
|
||||||
|
|
@ -53,59 +28,39 @@ test.describe('Dialogs Tab Tests', () => {
|
||||||
expect(isResponsive).toBe(true);
|
expect(isResponsive).toBe(true);
|
||||||
|
|
||||||
// Verify no critical errors
|
// Verify no critical errors
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('wxMessageBox', () => {
|
test.describe('wxMessageBox', () => {
|
||||||
|
|
||||||
test('Info message box opens and closes', async ({ page }) => {
|
test('Info message box opens and closes', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
const errors: string[] = [];
|
|
||||||
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
page.on('pageerror', err => errors.push(err.message));
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToDialogsTab(page, box);
|
await switchToDialogsTab(page, box);
|
||||||
|
|
||||||
// Click "Info Dialog" button (first button in wxMessageBox section)
|
// Click "Info Dialog" button (first button in wxMessageBox section)
|
||||||
// Buttons are around y=100-120 in the tab content
|
|
||||||
await page.mouse.click(box.x + 80, box.y + 110);
|
await page.mouse.click(box.x + 80, box.y + 110);
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/dialogs-msgbox-info-open.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialogs-msgbox-info-open.png', fullPage: true });
|
||||||
|
|
||||||
// Check if message box appeared
|
// Click OK to close
|
||||||
const hasInfoLog = logs.some(l => l.includes('Showing Info message box'));
|
|
||||||
console.log('Info dialog logs:', logs.filter(l => l.includes('Info')));
|
|
||||||
|
|
||||||
// Click OK to close (message box OK button is usually in center-bottom)
|
|
||||||
// In WASM, the dialog might be drawn on the canvas
|
|
||||||
await page.mouse.click(box.x + 350, box.y + 250);
|
await page.mouse.click(box.x + 350, box.y + 250);
|
||||||
await page.waitForTimeout(300);
|
await page.waitForTimeout(300);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/dialogs-msgbox-info-closed.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialogs-msgbox-info-closed.png', fullPage: true });
|
||||||
|
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Yes/No message box returns correct result', async ({ page }) => {
|
test('Yes/No message box returns correct result', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToDialogsTab(page, box);
|
await switchToDialogsTab(page, box);
|
||||||
|
|
||||||
|
|
@ -120,23 +75,13 @@ test.describe('Dialogs Tab Tests', () => {
|
||||||
await page.waitForTimeout(300);
|
await page.waitForTimeout(300);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/dialogs-msgbox-yesno-closed.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialogs-msgbox-yesno-closed.png', fullPage: true });
|
||||||
|
|
||||||
// Check logs for user choice
|
|
||||||
const hasYesNoLog = logs.some(l => l.includes('Yes/No') || l.includes('User clicked'));
|
|
||||||
console.log('Yes/No dialog logs:', logs.filter(l => l.includes('Yes') || l.includes('No')));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Error message box displays correctly', async ({ page }) => {
|
test('Error message box displays correctly', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToDialogsTab(page, box);
|
await switchToDialogsTab(page, box);
|
||||||
|
|
||||||
|
|
@ -156,17 +101,11 @@ test.describe('Dialogs Tab Tests', () => {
|
||||||
|
|
||||||
test.describe('wxDialog', () => {
|
test.describe('wxDialog', () => {
|
||||||
|
|
||||||
test('Custom dialog opens and closes', async ({ page }) => {
|
test('Custom dialog opens and closes', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToDialogsTab(page, box);
|
await switchToDialogsTab(page, box);
|
||||||
|
|
||||||
|
|
@ -176,91 +115,52 @@ test.describe('Dialogs Tab Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/dialogs-custom-open.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialogs-custom-open.png', fullPage: true });
|
||||||
|
|
||||||
// Check if dialog opened
|
|
||||||
const hasDialogLog = logs.some(l => l.includes('Opening custom dialog'));
|
|
||||||
console.log('Custom dialog logs:', logs.filter(l => l.includes('dialog')));
|
|
||||||
|
|
||||||
// Click OK to close
|
// Click OK to close
|
||||||
await page.mouse.click(box.x + 300, box.y + 300);
|
await page.mouse.click(box.x + 300, box.y + 300);
|
||||||
await page.waitForTimeout(300);
|
await page.waitForTimeout(300);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/dialogs-custom-closed.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialogs-custom-closed.png', fullPage: true });
|
||||||
|
|
||||||
// Check if dialog closed with result
|
|
||||||
const hasClosedLog = logs.some(l => l.includes('Custom dialog closed'));
|
|
||||||
console.log('Dialog close logs:', logs.filter(l => l.includes('closed')));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('wxTimer', () => {
|
test.describe('wxTimer', () => {
|
||||||
|
|
||||||
test('Timer starts and increments', async ({ page }) => {
|
test('Timer starts and increments', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToDialogsTab(page, box);
|
await switchToDialogsTab(page, box);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/dialogs-timer-initial.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialogs-timer-initial.png', fullPage: true });
|
||||||
|
|
||||||
// Click "Start Timer" button (in wxTimer section, buttons are CENTERED)
|
// Click "Start Timer" button (centered buttons)
|
||||||
// Looking at screenshot: Start Timer is around x=500, y=230
|
|
||||||
await page.mouse.click(box.x + 500, box.y + 230);
|
await page.mouse.click(box.x + 500, box.y + 230);
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/dialogs-timer-started.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialogs-timer-started.png', fullPage: true });
|
||||||
|
|
||||||
// Wait for a few timer ticks
|
// Wait for a few timer ticks
|
||||||
await page.waitForTimeout(3500); // Wait ~3-4 seconds
|
await page.waitForTimeout(3500);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/dialogs-timer-running.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialogs-timer-running.png', fullPage: true });
|
||||||
|
|
||||||
// Check for timer tick logs
|
// Click "Stop Timer"
|
||||||
const timerLogs = logs.filter(l => l.includes('Timer tick') || l.includes('Timer:'));
|
|
||||||
console.log('Timer logs:', timerLogs);
|
|
||||||
|
|
||||||
// Click "Stop Timer" (centered, to the right of Start Timer)
|
|
||||||
await page.mouse.click(box.x + 600, box.y + 230);
|
await page.mouse.click(box.x + 600, box.y + 230);
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/dialogs-timer-stopped.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialogs-timer-stopped.png', fullPage: true });
|
||||||
|
|
||||||
// Verify timer was working
|
|
||||||
const hasTimerTicks = logs.some(l => l.includes('Timer tick'));
|
|
||||||
const hasTimerStarted = logs.some(l => l.includes('Timer started'));
|
|
||||||
const hasTimerStopped = logs.some(l => l.includes('Timer stopped'));
|
|
||||||
|
|
||||||
console.log(`Timer started: ${hasTimerStarted}`);
|
|
||||||
console.log(`Timer ticks: ${timerLogs.length}`);
|
|
||||||
console.log(`Timer stopped: ${hasTimerStopped}`);
|
|
||||||
|
|
||||||
// Timer behavior - log results but don't fail the test
|
|
||||||
// wxTimer may have limited support in WASM
|
|
||||||
if (!hasTimerStarted) {
|
|
||||||
console.log('NOTE: wxTimer may not be fully implemented in WASM');
|
|
||||||
}
|
|
||||||
// Just verify no crashes occurred - this is a smoke test
|
// Just verify no crashes occurred - this is a smoke test
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Timer can be started and stopped multiple times', async ({ page }) => {
|
test('Timer can be started and stopped multiple times', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToDialogsTab(page, box);
|
await switchToDialogsTab(page, box);
|
||||||
|
|
||||||
|
|
@ -282,30 +182,16 @@ test.describe('Dialogs Tab Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/dialogs-timer-multiple.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialogs-timer-multiple.png', fullPage: true });
|
||||||
|
|
||||||
// Should have multiple start/stop logs
|
|
||||||
const startCount = logs.filter(l => l.includes('Timer started')).length;
|
|
||||||
const stopCount = logs.filter(l => l.includes('Timer stopped')).length;
|
|
||||||
|
|
||||||
console.log(`Start count: ${startCount}, Stop count: ${stopCount}`);
|
|
||||||
|
|
||||||
// Basic smoke test - no crashes
|
// Basic smoke test - no crashes
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Full Dialogs tab interaction flow', async ({ page }) => {
|
test('Full Dialogs tab interaction flow', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => errors.push(err.message));
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToDialogsTab(page, box);
|
await switchToDialogsTab(page, box);
|
||||||
|
|
||||||
|
|
@ -329,15 +215,7 @@ test.describe('Dialogs Tab Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/dialogs-full-flow.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/dialogs-full-flow.png', fullPage: true });
|
||||||
|
|
||||||
// Print all dialog-related events
|
|
||||||
console.log('\n=== DIALOG EVENTS ===');
|
|
||||||
logs.filter(l =>
|
|
||||||
l.includes('dialog') ||
|
|
||||||
l.includes('Timer') ||
|
|
||||||
l.includes('message box')
|
|
||||||
).forEach(log => console.log(log));
|
|
||||||
|
|
||||||
// Verify no crashes
|
// Verify no crashes
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,21 @@
|
||||||
// wxFileDialog Tests - File dialogs for KiCad open/save operations
|
// wxFileDialog Tests - File dialogs for KiCad open/save operations
|
||||||
import { test, expect, Page } from '@playwright/test';
|
import { test, expect, MAIN_CANVAS, tryLoadApp, getCanvasBox } from './utils/fixtures';
|
||||||
|
|
||||||
const MAIN_CANVAS = '#canvas';
|
|
||||||
|
|
||||||
async function tryLoadApp(page: Page, timeout = 15000) {
|
|
||||||
try {
|
|
||||||
await page.waitForSelector(MAIN_CANVAS, { state: 'visible', timeout });
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test.describe('wxFileDialog Tests', () => {
|
test.describe('wxFileDialog Tests', () => {
|
||||||
|
|
||||||
test('FileDialog test app loads successfully', async ({ page }) => {
|
test('FileDialog test app loads successfully', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => errors.push(`[PAGE_ERROR] ${err.message}`));
|
|
||||||
page.on('console', msg => logs.push(`[${msg.type()}] ${msg.text()}`));
|
|
||||||
|
|
||||||
await page.goto('/standalone/filedialog/filedialog_test.html');
|
await page.goto('/standalone/filedialog/filedialog_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/filedialog-01-loaded.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/filedialog-01-loaded.png', fullPage: true });
|
||||||
|
|
||||||
const hasStartup = logs.some(l => l.includes('FileDialog test app started'));
|
const hasStartup = testLogger.consoleLogs.some(l => l.includes('FileDialog test app started'));
|
||||||
|
|
||||||
console.log('FileDialog loaded:', loaded);
|
|
||||||
console.log('FileDialog logs:', logs.filter(l => l.includes('FILEDIALOG')));
|
|
||||||
console.log('FileDialog errors:', errors);
|
|
||||||
|
|
||||||
expect(loaded, 'wxFileDialog app should load').toBe(true);
|
expect(loaded, 'wxFileDialog app should load').toBe(true);
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Open file button can be clicked', async ({ page }) => {
|
test('Open file button can be clicked', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/filedialog/filedialog_test.html');
|
await page.goto('/standalone/filedialog/filedialog_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -48,9 +23,7 @@ test.describe('wxFileDialog Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Click "Open File..." button
|
// Click "Open File..." button
|
||||||
await page.mouse.click(box.x + 100, box.y + 150);
|
await page.mouse.click(box.x + 100, box.y + 150);
|
||||||
|
|
@ -58,16 +31,10 @@ test.describe('wxFileDialog Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/filedialog-02-open-clicked.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/filedialog-02-open-clicked.png', fullPage: true });
|
||||||
|
|
||||||
const hasOpenLog = logs.some(l => l.includes('Opening file dialog') || l.includes('Open'));
|
|
||||||
console.log('Open logs:', logs.filter(l => l.includes('FILEDIALOG') || l.includes('Open')));
|
|
||||||
|
|
||||||
expect(true).toBe(true); // Smoke test
|
expect(true).toBe(true); // Smoke test
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Save file button can be clicked', async ({ page }) => {
|
test('Save file button can be clicked', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/filedialog/filedialog_test.html');
|
await page.goto('/standalone/filedialog/filedialog_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -75,9 +42,7 @@ test.describe('wxFileDialog Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Click "Save File..." button
|
// Click "Save File..." button
|
||||||
await page.mouse.click(box.x + 220, box.y + 150);
|
await page.mouse.click(box.x + 220, box.y + 150);
|
||||||
|
|
@ -85,16 +50,10 @@ test.describe('wxFileDialog Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/filedialog-03-save-clicked.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/filedialog-03-save-clicked.png', fullPage: true });
|
||||||
|
|
||||||
const hasSaveLog = logs.some(l => l.includes('save dialog') || l.includes('Save'));
|
|
||||||
console.log('Save logs:', logs.filter(l => l.includes('FILEDIALOG') || l.includes('Save')));
|
|
||||||
|
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Open multiple button can be clicked', async ({ page }) => {
|
test('Open multiple button can be clicked', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/filedialog/filedialog_test.html');
|
await page.goto('/standalone/filedialog/filedialog_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -102,9 +61,7 @@ test.describe('wxFileDialog Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Click "Open Multiple..." button
|
// Click "Open Multiple..." button
|
||||||
await page.mouse.click(box.x + 350, box.y + 150);
|
await page.mouse.click(box.x + 350, box.y + 150);
|
||||||
|
|
@ -112,18 +69,10 @@ test.describe('wxFileDialog Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/filedialog-04-multiple-clicked.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/filedialog-04-multiple-clicked.png', fullPage: true });
|
||||||
|
|
||||||
console.log('Multiple logs:', logs.filter(l => l.includes('FILEDIALOG') || l.includes('Multiple')));
|
|
||||||
|
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('All file dialog buttons accessible', async ({ page }) => {
|
test('All file dialog buttons accessible', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => errors.push(err.message));
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/filedialog/filedialog_test.html');
|
await page.goto('/standalone/filedialog/filedialog_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -131,9 +80,7 @@ test.describe('wxFileDialog Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Try all three buttons
|
// Try all three buttons
|
||||||
await page.mouse.click(box.x + 100, box.y + 150);
|
await page.mouse.click(box.x + 100, box.y + 150);
|
||||||
|
|
@ -145,9 +92,6 @@ test.describe('wxFileDialog Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/filedialog-05-all-buttons.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/filedialog-05-all-buttons.png', fullPage: true });
|
||||||
|
|
||||||
console.log('\n=== FILEDIALOG EVENTS ===');
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
logs.filter(l => l.includes('FILEDIALOG')).forEach(l => console.log(l));
|
|
||||||
|
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,7 @@
|
||||||
import { test, expect, Page } from '@playwright/test';
|
import { test, expect, MAIN_CANVAS, waitForApp, getCanvasBox } from './utils/fixtures';
|
||||||
|
|
||||||
const MAIN_CANVAS = '#canvas';
|
async function switchToGridTab(page: any, box: { x: number; y: number }) {
|
||||||
|
|
||||||
async function waitForApp(page: Page) {
|
|
||||||
await page.waitForSelector(MAIN_CANVAS, { state: 'visible', timeout: 30000 });
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function switchToGridTab(page: Page, box: { x: number; y: number }) {
|
|
||||||
// Click Grid tab (sixth tab, after OpenGL which is at x=280)
|
// Click Grid tab (sixth tab, after OpenGL which is at x=280)
|
||||||
// Tab widths: Controls(~45), Text Input(~55), Drawing(~50), Lists(~35), OpenGL(~50), Grid(~30)
|
|
||||||
// Grid tab center is approximately at x = 310-320
|
|
||||||
await page.mouse.click(box.x + 315, box.y + 35);
|
await page.mouse.click(box.x + 315, box.y + 35);
|
||||||
await page.waitForTimeout(1000);
|
await page.waitForTimeout(1000);
|
||||||
}
|
}
|
||||||
|
|
@ -22,23 +13,7 @@ async function switchToGridTab(page: Page, box: { x: number; y: number }) {
|
||||||
test.describe('wxGrid Dedicated Test Page', () => {
|
test.describe('wxGrid Dedicated Test Page', () => {
|
||||||
|
|
||||||
// This is THE critical test for wxGrid support.
|
// This is THE critical test for wxGrid support.
|
||||||
// It loads a separate WASM binary that ONLY tests wxGrid.
|
test.fail('wxGrid test page loads successfully', async ({ page, testLogger }) => {
|
||||||
// If wxGrid is not implemented in WASM, this page will CRASH at startup.
|
|
||||||
// When this test starts PASSING, wxGrid is working!
|
|
||||||
test.fail('wxGrid test page loads successfully', async ({ page }) => {
|
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => {
|
|
||||||
errors.push(`[PAGE_ERROR] ${err.message}\n${err.stack || ''}`);
|
|
||||||
});
|
|
||||||
page.on('console', msg => {
|
|
||||||
logs.push(`[${msg.type()}] ${msg.text()}`);
|
|
||||||
if (msg.type() === 'error') {
|
|
||||||
errors.push(`[CONSOLE_ERROR] ${msg.text()}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Navigate to the dedicated wxGrid test page
|
// Navigate to the dedicated wxGrid test page
|
||||||
await page.goto('/standalone/grid/grid_test.html');
|
await page.goto('/standalone/grid/grid_test.html');
|
||||||
|
|
||||||
|
|
@ -48,40 +23,29 @@ test.describe('wxGrid Dedicated Test Page', () => {
|
||||||
await page.waitForTimeout(1000);
|
await page.waitForTimeout(1000);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Expected to fail - wxGrid is not implemented
|
// Expected to fail - wxGrid is not implemented
|
||||||
console.log('wxGrid test page failed to load (expected):', e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/wxgrid-dedicated-page.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/wxgrid-dedicated-page.png', fullPage: true });
|
||||||
|
|
||||||
// Log what happened
|
|
||||||
console.log('\n=== wxGrid Dedicated Test Page Results ===');
|
|
||||||
console.log('Console logs:', logs.length);
|
|
||||||
console.log('Errors:', errors.length);
|
|
||||||
errors.forEach(e => console.log(e));
|
|
||||||
|
|
||||||
// Check for the success message from grid_test.cpp
|
// Check for the success message from grid_test.cpp
|
||||||
const hasSuccessMessage = logs.some(l =>
|
const hasSuccessMessage = testLogger.consoleLogs.some(l =>
|
||||||
l.includes('wxGrid test app started successfully') ||
|
l.includes('wxGrid test app started successfully') ||
|
||||||
l.includes('wxGrid initialized successfully')
|
l.includes('wxGrid initialized successfully')
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check for crash errors
|
// Check for crash errors
|
||||||
const hasCrash = errors.some(e =>
|
const hasCrash = testLogger.errors.some(e =>
|
||||||
e.includes('function signature mismatch') ||
|
e.includes('function signature mismatch') ||
|
||||||
e.includes('RuntimeError') ||
|
e.includes('RuntimeError') ||
|
||||||
e.includes('Exception thrown')
|
e.includes('Exception thrown')
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log(`Has success message: ${hasSuccessMessage}`);
|
|
||||||
console.log(`Has crash: ${hasCrash}`);
|
|
||||||
|
|
||||||
// This test FAILS if wxGrid is not implemented (crashes or no success message)
|
// This test FAILS if wxGrid is not implemented (crashes or no success message)
|
||||||
// When wxGrid is fixed, this will PASS
|
|
||||||
expect(hasCrash, 'wxGrid should not crash the app').toBe(false);
|
expect(hasCrash, 'wxGrid should not crash the app').toBe(false);
|
||||||
expect(hasSuccessMessage, 'wxGrid app should start successfully').toBe(true);
|
expect(hasSuccessMessage, 'wxGrid app should start successfully').toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.fail('wxGrid test page shows grid controls', async ({ page }) => {
|
test.fail('wxGrid test page shows grid controls', async ({ page, testLogger }) => {
|
||||||
await page.goto('/standalone/grid/grid_test.html');
|
await page.goto('/standalone/grid/grid_test.html');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -112,7 +76,6 @@ test.describe('wxGrid Dedicated Test Page', () => {
|
||||||
variance++;
|
variance++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(`[GRID_PAGE_CHECK] Pixel variance: ${variance}`);
|
|
||||||
return variance > 1000; // Grid with labels/lines has high variance
|
return variance > 1000; // Grid with labels/lines has high variance
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -128,39 +91,18 @@ test.describe('Grid Tab Tests', () => {
|
||||||
|
|
||||||
test.describe('wxGrid in Main App (DISABLED)', () => {
|
test.describe('wxGrid in Main App (DISABLED)', () => {
|
||||||
|
|
||||||
// This test documents that wxGrid is NOT implemented in WASM
|
test.fail('wxGrid renders visible grid cells', async ({ page, testLogger }) => {
|
||||||
// It should FAIL until wxGrid is fixed. When it starts passing, wxGrid is working!
|
|
||||||
test.fail('wxGrid renders visible grid cells', async ({ page }) => {
|
|
||||||
const errors: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => {
|
|
||||||
errors.push(`[PAGE_ERROR] ${err.message}`);
|
|
||||||
});
|
|
||||||
page.on('console', msg => {
|
|
||||||
if (msg.type() === 'error') {
|
|
||||||
errors.push(`[CONSOLE_ERROR] ${msg.text()}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Switch to Grid tab
|
// Switch to Grid tab
|
||||||
await switchToGridTab(page, box);
|
await switchToGridTab(page, box);
|
||||||
await page.screenshot({ path: 'test-results/wxgrid-01-tab.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/wxgrid-01-tab.png', fullPage: true });
|
||||||
|
|
||||||
// The test should find actual grid cells. Since wxGrid is not implemented,
|
|
||||||
// this will fail - which is exactly what we want to document!
|
|
||||||
// We check for grid content by looking at the screenshot or canvas pixels
|
|
||||||
|
|
||||||
// Evaluate if grid-like content exists (row/column headers, cells)
|
// Evaluate if grid-like content exists (row/column headers, cells)
|
||||||
const hasGridContent = await page.evaluate(() => {
|
const hasGridContent = await page.evaluate(() => {
|
||||||
// Check if there's any element with grid-like structure
|
|
||||||
// Since wxGrid would render to canvas, we check canvas content
|
|
||||||
const canvas = document.querySelector('#canvas') as HTMLCanvasElement;
|
const canvas = document.querySelector('#canvas') as HTMLCanvasElement;
|
||||||
if (!canvas) return false;
|
if (!canvas) return false;
|
||||||
|
|
||||||
|
|
@ -168,7 +110,6 @@ test.describe('Grid Tab Tests', () => {
|
||||||
if (!ctx) return false;
|
if (!ctx) return false;
|
||||||
|
|
||||||
// Sample pixels at where grid headers/cells would be (around y=180-200)
|
// Sample pixels at where grid headers/cells would be (around y=180-200)
|
||||||
// A real grid would have visible lines and text, not just blank space
|
|
||||||
const imageData = ctx.getImageData(100, 180, 300, 50);
|
const imageData = ctx.getImageData(100, 180, 300, 50);
|
||||||
const data = imageData.data;
|
const data = imageData.data;
|
||||||
|
|
||||||
|
|
@ -178,7 +119,6 @@ test.describe('Grid Tab Tests', () => {
|
||||||
|
|
||||||
for (let i = 0; i < data.length; i += 4) {
|
for (let i = 0; i < data.length; i += 4) {
|
||||||
const r = data[i], g = data[i+1], b = data[i+2];
|
const r = data[i], g = data[i+1], b = data[i+2];
|
||||||
// Check for color changes (grid lines, text)
|
|
||||||
if (Math.abs(r - lastPixel.r) > 20 ||
|
if (Math.abs(r - lastPixel.r) > 20 ||
|
||||||
Math.abs(g - lastPixel.g) > 20 ||
|
Math.abs(g - lastPixel.g) > 20 ||
|
||||||
Math.abs(b - lastPixel.b) > 20) {
|
Math.abs(b - lastPixel.b) > 20) {
|
||||||
|
|
@ -187,24 +127,17 @@ test.describe('Grid Tab Tests', () => {
|
||||||
lastPixel = { r, g, b };
|
lastPixel = { r, g, b };
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's significant variance, grid content exists
|
|
||||||
// A blank area would have very low variance
|
|
||||||
console.log(`[GRID_CHECK] Color variance: ${colorVariance}`);
|
|
||||||
return colorVariance > 500; // Grid has lines and text = high variance
|
return colorVariance > 500; // Grid has lines and text = high variance
|
||||||
});
|
});
|
||||||
|
|
||||||
// This assertion WILL FAIL because wxGrid is not implemented
|
|
||||||
// When wxGrid is fixed, this test will pass
|
|
||||||
expect(hasGridContent, 'wxGrid should render visible grid cells with headers and data').toBe(true);
|
expect(hasGridContent, 'wxGrid should render visible grid cells with headers and data').toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.fail('wxGrid cell selection works', async ({ page }) => {
|
test.fail('wxGrid cell selection works', async ({ page, testLogger }) => {
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToGridTab(page, box);
|
await switchToGridTab(page, box);
|
||||||
|
|
||||||
|
|
@ -214,23 +147,16 @@ test.describe('Grid Tab Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/wxgrid-02-selection.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/wxgrid-02-selection.png', fullPage: true });
|
||||||
|
|
||||||
// Check console for grid selection events
|
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
// Since wxGrid is not implemented, we won't get selection events
|
// Since wxGrid is not implemented, we won't get selection events
|
||||||
// This test SHOULD FAIL
|
const hasGridEvent = testLogger.consoleLogs.some(l => l.includes('Grid cell'));
|
||||||
const hasGridEvent = logs.some(l => l.includes('Grid cell'));
|
|
||||||
expect(hasGridEvent, 'wxGrid should emit cell selection events').toBe(true);
|
expect(hasGridEvent, 'wxGrid should emit cell selection events').toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.fail('wxGrid cell editing works', async ({ page }) => {
|
test.fail('wxGrid cell editing works', async ({ page, testLogger }) => {
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToGridTab(page, box);
|
await switchToGridTab(page, box);
|
||||||
|
|
||||||
|
|
@ -244,13 +170,8 @@ test.describe('Grid Tab Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/wxgrid-03-editing.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/wxgrid-03-editing.png', fullPage: true });
|
||||||
|
|
||||||
// Check console for grid edit events
|
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
// Since wxGrid is not implemented, we won't get edit events
|
// Since wxGrid is not implemented, we won't get edit events
|
||||||
// This test SHOULD FAIL
|
const hasEditEvent = testLogger.consoleLogs.some(l => l.includes('Grid cell') && l.includes('changed'));
|
||||||
const hasEditEvent = logs.some(l => l.includes('Grid cell') && l.includes('changed'));
|
|
||||||
expect(hasEditEvent, 'wxGrid should emit cell changed events when editing').toBe(true);
|
expect(hasEditEvent, 'wxGrid should emit cell changed events when editing').toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -261,25 +182,16 @@ test.describe('Grid Tab Tests', () => {
|
||||||
|
|
||||||
test.describe('wxSpinCtrl', () => {
|
test.describe('wxSpinCtrl', () => {
|
||||||
|
|
||||||
test('SpinCtrl renders and is visible', async ({ page }) => {
|
test('SpinCtrl renders and is visible', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => {
|
|
||||||
errors.push(`[PAGE_ERROR] ${err.message}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToGridTab(page, box);
|
await switchToGridTab(page, box);
|
||||||
await page.screenshot({ path: 'test-results/spinctrl-01-visible.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/spinctrl-01-visible.png', fullPage: true });
|
||||||
|
|
||||||
// SpinCtrl should be visible - check for its box and arrows in the canvas
|
// SpinCtrl should be visible - check for its box and arrows in the canvas
|
||||||
// Looking at the screenshot, controls are at top of panel around y=120-180
|
|
||||||
const hasSpinCtrlContent = await page.evaluate(() => {
|
const hasSpinCtrlContent = await page.evaluate(() => {
|
||||||
const canvas = document.querySelector('#canvas') as HTMLCanvasElement;
|
const canvas = document.querySelector('#canvas') as HTMLCanvasElement;
|
||||||
if (!canvas) return false;
|
if (!canvas) return false;
|
||||||
|
|
@ -288,7 +200,6 @@ test.describe('Grid Tab Tests', () => {
|
||||||
if (!ctx) return false;
|
if (!ctx) return false;
|
||||||
|
|
||||||
// SpinCtrl is at the top left of the Grid tab content, around y=130-170
|
// SpinCtrl is at the top left of the Grid tab content, around y=130-170
|
||||||
// It shows "Value (0-100): 50" with up/down arrows
|
|
||||||
const imageData = ctx.getImageData(10, 130, 180, 50);
|
const imageData = ctx.getImageData(10, 130, 180, 50);
|
||||||
const data = imageData.data;
|
const data = imageData.data;
|
||||||
|
|
||||||
|
|
@ -296,48 +207,32 @@ test.describe('Grid Tab Tests', () => {
|
||||||
let nonBackgroundPixels = 0;
|
let nonBackgroundPixels = 0;
|
||||||
for (let i = 0; i < data.length; i += 4) {
|
for (let i = 0; i < data.length; i += 4) {
|
||||||
const r = data[i], g = data[i+1], b = data[i+2];
|
const r = data[i], g = data[i+1], b = data[i+2];
|
||||||
// Check for non-light pixels (text is dark, borders are gray)
|
|
||||||
if (r < 230 || g < 230 || b < 230) {
|
if (r < 230 || g < 230 || b < 230) {
|
||||||
nonBackgroundPixels++;
|
nonBackgroundPixels++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[SPINCTRL_CHECK] Non-background pixels: ${nonBackgroundPixels}`);
|
|
||||||
return nonBackgroundPixels > 50; // Should have visible text and borders
|
return nonBackgroundPixels > 50; // Should have visible text and borders
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(hasSpinCtrlContent, 'wxSpinCtrl should be visible with borders and arrows').toBe(true);
|
expect(hasSpinCtrlContent, 'wxSpinCtrl should be visible with borders and arrows').toBe(true);
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('SpinCtrl up/down arrows work', async ({ page }) => {
|
test('SpinCtrl up/down arrows work', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('console', msg => {
|
|
||||||
logs.push(msg.text());
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToGridTab(page, box);
|
await switchToGridTab(page, box);
|
||||||
|
|
||||||
// Click up arrow on SpinCtrl (right side of the control, upper half)
|
// Click up arrow on SpinCtrl
|
||||||
// SpinCtrl is around y=350, arrows on right side around x=220
|
|
||||||
await page.mouse.click(box.x + 220, box.y + 350);
|
await page.mouse.click(box.x + 220, box.y + 350);
|
||||||
await page.waitForTimeout(200);
|
await page.waitForTimeout(200);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/spinctrl-02-after-click.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/spinctrl-02-after-click.png', fullPage: true });
|
||||||
|
|
||||||
// Check for spin events
|
|
||||||
const hasSpinEvent = logs.some(l => l.includes('SpinCtrl') || l.includes('spin'));
|
|
||||||
console.log('SpinCtrl logs:', logs.filter(l => l.includes('Spin')));
|
|
||||||
|
|
||||||
// If SpinCtrl is working, we should see events (or at least no crashes)
|
|
||||||
// This is a smoke test - if it doesn't crash, that's good
|
// This is a smoke test - if it doesn't crash, that's good
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
@ -349,25 +244,16 @@ test.describe('Grid Tab Tests', () => {
|
||||||
|
|
||||||
test.describe('wxSearchCtrl', () => {
|
test.describe('wxSearchCtrl', () => {
|
||||||
|
|
||||||
test('SearchCtrl renders and is visible', async ({ page }) => {
|
test('SearchCtrl renders and is visible', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => {
|
|
||||||
errors.push(`[PAGE_ERROR] ${err.message}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToGridTab(page, box);
|
await switchToGridTab(page, box);
|
||||||
await page.screenshot({ path: 'test-results/searchctrl-01-visible.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/searchctrl-01-visible.png', fullPage: true });
|
||||||
|
|
||||||
// SearchCtrl should be visible - check for its text field and buttons
|
// SearchCtrl should be visible - check for its text field and buttons
|
||||||
// Looking at the screenshot, SearchCtrl is on the right side around y=130-170
|
|
||||||
const hasSearchCtrlContent = await page.evaluate(() => {
|
const hasSearchCtrlContent = await page.evaluate(() => {
|
||||||
const canvas = document.querySelector('#canvas') as HTMLCanvasElement;
|
const canvas = document.querySelector('#canvas') as HTMLCanvasElement;
|
||||||
if (!canvas) return false;
|
if (!canvas) return false;
|
||||||
|
|
@ -376,7 +262,6 @@ test.describe('Grid Tab Tests', () => {
|
||||||
if (!ctx) return false;
|
if (!ctx) return false;
|
||||||
|
|
||||||
// SearchCtrl is on the right side of the Grid tab content, around y=130-170
|
// SearchCtrl is on the right side of the Grid tab content, around y=130-170
|
||||||
// It shows "Search..." placeholder with search icon and cancel button
|
|
||||||
const imageData = ctx.getImageData(200, 130, 300, 50);
|
const imageData = ctx.getImageData(200, 130, 300, 50);
|
||||||
const data = imageData.data;
|
const data = imageData.data;
|
||||||
|
|
||||||
|
|
@ -384,33 +269,23 @@ test.describe('Grid Tab Tests', () => {
|
||||||
let nonBackgroundPixels = 0;
|
let nonBackgroundPixels = 0;
|
||||||
for (let i = 0; i < data.length; i += 4) {
|
for (let i = 0; i < data.length; i += 4) {
|
||||||
const r = data[i], g = data[i+1], b = data[i+2];
|
const r = data[i], g = data[i+1], b = data[i+2];
|
||||||
// Check for non-light pixels (borders, text, icons)
|
|
||||||
if (r < 230 || g < 230 || b < 230) {
|
if (r < 230 || g < 230 || b < 230) {
|
||||||
nonBackgroundPixels++;
|
nonBackgroundPixels++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[SEARCHCTRL_CHECK] Non-background pixels: ${nonBackgroundPixels}`);
|
|
||||||
return nonBackgroundPixels > 50; // Should have visible borders and placeholder text
|
return nonBackgroundPixels > 50; // Should have visible borders and placeholder text
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(hasSearchCtrlContent, 'wxSearchCtrl should be visible with text field and buttons').toBe(true);
|
expect(hasSearchCtrlContent, 'wxSearchCtrl should be visible with text field and buttons').toBe(true);
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('SearchCtrl accepts text input', async ({ page }) => {
|
test('SearchCtrl accepts text input', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('console', msg => {
|
|
||||||
logs.push(msg.text());
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToGridTab(page, box);
|
await switchToGridTab(page, box);
|
||||||
|
|
||||||
|
|
@ -430,10 +305,6 @@ test.describe('Grid Tab Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/searchctrl-03-after-enter.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/searchctrl-03-after-enter.png', fullPage: true });
|
||||||
|
|
||||||
// Check for search events
|
|
||||||
const hasSearchEvent = logs.some(l => l.includes('Search') || l.includes('search'));
|
|
||||||
console.log('SearchCtrl logs:', logs.filter(l => l.toLowerCase().includes('search')));
|
|
||||||
|
|
||||||
// This is a smoke test - verify no crashes
|
// This is a smoke test - verify no crashes
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
@ -443,19 +314,11 @@ test.describe('Grid Tab Tests', () => {
|
||||||
// Combined Tab Test - Basic smoke test for the Grid tab
|
// Combined Tab Test - Basic smoke test for the Grid tab
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
test('Grid tab loads without crash', async ({ page }) => {
|
test('Grid tab loads without crash', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => {
|
|
||||||
errors.push(`[PAGE_ERROR] ${err.message}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToGridTab(page, box);
|
await switchToGridTab(page, box);
|
||||||
await page.screenshot({ path: 'test-results/grid-tab-final.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/grid-tab-final.png', fullPage: true });
|
||||||
|
|
@ -467,6 +330,6 @@ test.describe('Grid Tab Tests', () => {
|
||||||
|
|
||||||
expect(isResponsive).toBe(true);
|
expect(isResponsive).toBe(true);
|
||||||
// Filter out favicon errors which are expected
|
// Filter out favicon errors which are expected
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,21 @@
|
||||||
// wxSplitterWindow and wxScrolledWindow Tests - Layout controls KiCad uses
|
// wxSplitterWindow and wxScrolledWindow Tests - Layout controls KiCad uses
|
||||||
import { test, expect, Page } from '@playwright/test';
|
import { test, expect, MAIN_CANVAS, tryLoadApp, getCanvasBox } from './utils/fixtures';
|
||||||
|
|
||||||
const MAIN_CANVAS = '#canvas';
|
|
||||||
|
|
||||||
async function tryLoadApp(page: Page, timeout = 15000) {
|
|
||||||
try {
|
|
||||||
await page.waitForSelector(MAIN_CANVAS, { state: 'visible', timeout });
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test.describe('wxSplitterWindow & wxScrolledWindow Tests', () => {
|
test.describe('wxSplitterWindow & wxScrolledWindow Tests', () => {
|
||||||
|
|
||||||
test('Layout test app loads successfully', async ({ page }) => {
|
test('Layout test app loads successfully', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => errors.push(`[PAGE_ERROR] ${err.message}`));
|
|
||||||
page.on('console', msg => logs.push(`[${msg.type()}] ${msg.text()}`));
|
|
||||||
|
|
||||||
await page.goto('/standalone/layout/layout_test.html');
|
await page.goto('/standalone/layout/layout_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/layout-01-loaded.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/layout-01-loaded.png', fullPage: true });
|
||||||
|
|
||||||
const hasStartup = logs.some(l => l.includes('Layout test app started'));
|
const hasStartup = testLogger.consoleLogs.some(l => l.includes('Layout test app started'));
|
||||||
|
|
||||||
console.log('Layout loaded:', loaded);
|
|
||||||
console.log('Layout logs:', logs.filter(l => l.includes('LAYOUT')));
|
|
||||||
console.log('Layout errors:', errors);
|
|
||||||
|
|
||||||
expect(loaded, 'Layout app should load').toBe(true);
|
expect(loaded, 'Layout app should load').toBe(true);
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Splitter is visible with two panes', async ({ page }) => {
|
test('Splitter is visible with two panes', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/layout/layout_test.html');
|
await page.goto('/standalone/layout/layout_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -50,16 +25,12 @@ test.describe('wxSplitterWindow & wxScrolledWindow Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/layout-02-splitter.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/layout-02-splitter.png', fullPage: true });
|
||||||
|
|
||||||
const hasSplitterLog = logs.some(l => l.includes('Splitter position'));
|
const hasSplitterLog = testLogger.consoleLogs.some(l => l.includes('Splitter position'));
|
||||||
console.log('Splitter logs:', logs.filter(l => l.includes('LAYOUT') || l.includes('Splitter')));
|
|
||||||
|
|
||||||
expect(hasSplitterLog).toBe(true);
|
expect(hasSplitterLog).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Splitter sash can be dragged', async ({ page }) => {
|
test('Splitter sash can be dragged', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/layout/layout_test.html');
|
await page.goto('/standalone/layout/layout_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -67,9 +38,7 @@ test.describe('wxSplitterWindow & wxScrolledWindow Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Splitter sash is at initial position 300 from left
|
// Splitter sash is at initial position 300 from left
|
||||||
const sashX = box.x + 300;
|
const sashX = box.x + 300;
|
||||||
|
|
@ -84,17 +53,11 @@ test.describe('wxSplitterWindow & wxScrolledWindow Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/layout-03-sash-dragged.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/layout-03-sash-dragged.png', fullPage: true });
|
||||||
|
|
||||||
const hasSashEvent = logs.some(l => l.includes('Splitter sash moved'));
|
|
||||||
console.log('Sash events:', logs.filter(l => l.includes('sash') || l.includes('Splitter')));
|
|
||||||
|
|
||||||
// Smoke test - verify no crash
|
// Smoke test - verify no crash
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Scrolled windows show content', async ({ page }) => {
|
test('Scrolled windows show content', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/layout/layout_test.html');
|
await page.goto('/standalone/layout/layout_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -102,9 +65,7 @@ test.describe('wxSplitterWindow & wxScrolledWindow Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Scroll in left pane
|
// Scroll in left pane
|
||||||
await page.mouse.move(box.x + 150, box.y + 200);
|
await page.mouse.move(box.x + 150, box.y + 200);
|
||||||
|
|
@ -123,13 +84,7 @@ test.describe('wxSplitterWindow & wxScrolledWindow Tests', () => {
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Layout controls work together', async ({ page }) => {
|
test('Layout controls work together', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => errors.push(err.message));
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/layout/layout_test.html');
|
await page.goto('/standalone/layout/layout_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -137,9 +92,7 @@ test.describe('wxSplitterWindow & wxScrolledWindow Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Drag sash
|
// Drag sash
|
||||||
await page.mouse.move(box.x + 300, box.y + 200);
|
await page.mouse.move(box.x + 300, box.y + 200);
|
||||||
|
|
@ -160,9 +113,6 @@ test.describe('wxSplitterWindow & wxScrolledWindow Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/layout-06-combined.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/layout-06-combined.png', fullPage: true });
|
||||||
|
|
||||||
console.log('\n=== LAYOUT EVENTS ===');
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
logs.filter(l => l.includes('LAYOUT')).forEach(l => console.log(l));
|
|
||||||
|
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,55 +1,23 @@
|
||||||
// wxMenuBar Tests - Menu system for KiCad
|
// wxMenuBar Tests - Menu system for KiCad
|
||||||
import { test, expect, Page } from '@playwright/test';
|
import { test, expect, MAIN_CANVAS, tryLoadApp, getCanvasBox } from './utils/fixtures';
|
||||||
|
|
||||||
const MAIN_CANVAS = '#canvas';
|
|
||||||
|
|
||||||
async function waitForApp(page: Page, timeout = 30000) {
|
|
||||||
await page.waitForSelector(MAIN_CANVAS, { state: 'visible', timeout });
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function tryLoadApp(page: Page) {
|
|
||||||
try {
|
|
||||||
await waitForApp(page, 15000);
|
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test.describe('wxMenuBar Tests', () => {
|
test.describe('wxMenuBar Tests', () => {
|
||||||
|
|
||||||
test('Menu test app loads successfully', async ({ page }) => {
|
test('Menu test app loads successfully', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => {
|
|
||||||
errors.push(`[PAGE_ERROR] ${err.message}`);
|
|
||||||
});
|
|
||||||
page.on('console', msg => {
|
|
||||||
logs.push(`[${msg.type()}] ${msg.text()}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/standalone/menu/menu_test.html');
|
await page.goto('/standalone/menu/menu_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/menu-01-loaded.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/menu-01-loaded.png', fullPage: true });
|
||||||
|
|
||||||
const hasStartupLog = logs.some(l => l.includes('wxMenuBar test app started') || l.includes('Menu test app started'));
|
const hasStartupLog = testLogger.consoleLogs.some(l =>
|
||||||
|
l.includes('wxMenuBar test app started') || l.includes('Menu test app started')
|
||||||
console.log('Menu app logs:', logs.filter(l => l.includes('MENU')));
|
);
|
||||||
console.log('Menu app errors:', errors);
|
|
||||||
console.log('Menu app loaded:', loaded);
|
|
||||||
console.log('Has startup log:', hasStartupLog);
|
|
||||||
|
|
||||||
expect(loaded, 'wxMenuBar app should load successfully').toBe(true);
|
expect(loaded, 'wxMenuBar app should load successfully').toBe(true);
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Menu bar is visible', async ({ page }) => {
|
test('Menu bar is visible', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/menu/menu_test.html');
|
await page.goto('/standalone/menu/menu_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -60,16 +28,14 @@ test.describe('wxMenuBar Tests', () => {
|
||||||
await page.screenshot({ path: 'test-results/menu-02-menubar.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/menu-02-menubar.png', fullPage: true });
|
||||||
|
|
||||||
// Check that app started with menu bar created
|
// Check that app started with menu bar created
|
||||||
const hasMenuBarLog = logs.some(l => l.includes('Menu bar created') || l.includes('Menu test app started'));
|
const hasMenuBarLog = testLogger.consoleLogs.some(l =>
|
||||||
console.log('Menu bar logs:', logs.filter(l => l.includes('menu') || l.includes('Menu')));
|
l.includes('Menu bar created') || l.includes('Menu test app started')
|
||||||
|
);
|
||||||
|
|
||||||
expect(hasMenuBarLog).toBe(true);
|
expect(hasMenuBarLog).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('File menu can be clicked', async ({ page }) => {
|
test('File menu can be clicked', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/menu/menu_test.html');
|
await page.goto('/standalone/menu/menu_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -77,9 +43,7 @@ test.describe('wxMenuBar Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Click on File menu (top left of menu bar, around x=30, y=10-25)
|
// Click on File menu (top left of menu bar, around x=30, y=10-25)
|
||||||
await page.mouse.click(box.x + 30, box.y + 15);
|
await page.mouse.click(box.x + 30, box.y + 15);
|
||||||
|
|
@ -91,10 +55,7 @@ test.describe('wxMenuBar Tests', () => {
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Edit menu can be clicked', async ({ page }) => {
|
test('Edit menu can be clicked', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/menu/menu_test.html');
|
await page.goto('/standalone/menu/menu_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -102,9 +63,7 @@ test.describe('wxMenuBar Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Click on Edit menu (next to File, around x=70, y=15)
|
// Click on Edit menu (next to File, around x=70, y=15)
|
||||||
await page.mouse.click(box.x + 70, box.y + 15);
|
await page.mouse.click(box.x + 70, box.y + 15);
|
||||||
|
|
@ -115,13 +74,7 @@ test.describe('wxMenuBar Tests', () => {
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Multiple menus can be accessed', async ({ page }) => {
|
test('Multiple menus can be accessed', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => errors.push(err.message));
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/menu/menu_test.html');
|
await page.goto('/standalone/menu/menu_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -129,9 +82,7 @@ test.describe('wxMenuBar Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Click through all menus
|
// Click through all menus
|
||||||
const menuPositions = [30, 70, 110, 150, 190]; // File, Edit, View, Tools, Help
|
const menuPositions = [30, 70, 110, 150, 190]; // File, Edit, View, Tools, Help
|
||||||
|
|
@ -142,9 +93,6 @@ test.describe('wxMenuBar Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/menu-05-all-menus.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/menu-05-all-menus.png', fullPage: true });
|
||||||
|
|
||||||
console.log('\n=== MENU EVENTS ===');
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
logs.filter(l => l.includes('MENU')).forEach(l => console.log(l));
|
|
||||||
|
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,14 @@
|
||||||
import { test, expect, Page } from '@playwright/test';
|
import { test, expect, MAIN_CANVAS, waitForApp, getCanvasBox } from './utils/fixtures';
|
||||||
|
|
||||||
const MAIN_CANVAS = '#canvas';
|
async function switchToOpenGLTab(page: any, box: { x: number; y: number }) {
|
||||||
|
|
||||||
async function waitForApp(page: Page) {
|
|
||||||
await page.waitForSelector(MAIN_CANVAS, { state: 'visible', timeout: 30000 });
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function switchToOpenGLTab(page: Page, box: { x: number; y: number }) {
|
|
||||||
// Click OpenGL tab (fifth tab, around x=280)
|
// Click OpenGL tab (fifth tab, around x=280)
|
||||||
await page.mouse.click(box.x + 280, box.y + 35);
|
await page.mouse.click(box.x + 280, box.y + 35);
|
||||||
await page.waitForTimeout(1000);
|
await page.waitForTimeout(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open the test dropdown and select by index (0-based)
|
// Open the test dropdown and select by index (0-based)
|
||||||
async function selectGLTest(page: Page, box: { x: number; y: number }, index: number) {
|
async function selectGLTest(page: any, box: { x: number; y: number }, index: number) {
|
||||||
// Click the dropdown arrow to open it (dropdown is at around x=170, y=155, arrow at right edge ~x=290)
|
// Click the dropdown arrow to open it
|
||||||
await page.mouse.click(box.x + 290, box.y + 155);
|
await page.mouse.click(box.x + 290, box.y + 155);
|
||||||
await page.waitForTimeout(300);
|
await page.waitForTimeout(300);
|
||||||
|
|
||||||
|
|
@ -26,41 +19,17 @@ async function selectGLTest(page: Page, box: { x: number; y: number }, index: nu
|
||||||
}
|
}
|
||||||
|
|
||||||
test.describe('OpenGL Tests', () => {
|
test.describe('OpenGL Tests', () => {
|
||||||
test('Vertex Arrays test - debug freeze', async ({ page }) => {
|
test('Vertex Arrays test - debug freeze', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => {
|
|
||||||
errors.push(`[PAGE_ERROR] ${err.message}\n${err.stack || 'No stack'}`);
|
|
||||||
});
|
|
||||||
page.on('console', msg => {
|
|
||||||
const text = msg.text();
|
|
||||||
logs.push(`[${msg.type()}] ${text}`);
|
|
||||||
if (msg.type() === 'error') {
|
|
||||||
errors.push(`[CONSOLE_ERROR] ${text}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Switch to OpenGL tab
|
// Switch to OpenGL tab
|
||||||
await switchToOpenGLTab(page, box);
|
await switchToOpenGLTab(page, box);
|
||||||
await page.screenshot({ path: 'test-results/gl-01-opengl-tab.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/gl-01-opengl-tab.png', fullPage: true });
|
||||||
|
|
||||||
// The dropdown has these options (from minimal_test.cpp):
|
|
||||||
// 0: "Immediate Mode (glBegin/glEnd)"
|
|
||||||
// 1: "Matrix Ops (glPushMatrix)"
|
|
||||||
// 2: "Vertex Arrays (glVertexPointer)"
|
|
||||||
// 3: "State Mgmt (glEnable/glBlend)"
|
|
||||||
// 4: "Texture Coords"
|
|
||||||
|
|
||||||
// Select "Vertex Arrays" test (index 2)
|
// Select "Vertex Arrays" test (index 2)
|
||||||
console.log('Selecting Vertex Arrays test...');
|
|
||||||
await selectGLTest(page, box, 2);
|
await selectGLTest(page, box, 2);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/gl-02-vertex-arrays-selected.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/gl-02-vertex-arrays-selected.png', fullPage: true });
|
||||||
|
|
@ -70,12 +39,6 @@ test.describe('OpenGL Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/gl-03-after-wait.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/gl-03-after-wait.png', fullPage: true });
|
||||||
|
|
||||||
// Print all logs for debugging
|
|
||||||
console.log('\n=== CONSOLE LOGS ===');
|
|
||||||
logs.forEach(log => console.log(log));
|
|
||||||
console.log('\n=== ERRORS ===');
|
|
||||||
errors.forEach(err => console.log(err));
|
|
||||||
|
|
||||||
// Check if app is still responsive
|
// Check if app is still responsive
|
||||||
const isResponsive = await page.evaluate(() => {
|
const isResponsive = await page.evaluate(() => {
|
||||||
return document.querySelector('#canvas') !== null;
|
return document.querySelector('#canvas') !== null;
|
||||||
|
|
@ -83,23 +46,11 @@ test.describe('OpenGL Tests', () => {
|
||||||
expect(isResponsive).toBe(true);
|
expect(isResponsive).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('All GL tests individually', async ({ page }) => {
|
test('All GL tests individually', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => {
|
|
||||||
errors.push(`[PAGE_ERROR] ${err.message}\n${err.stack || 'No stack'}`);
|
|
||||||
});
|
|
||||||
page.on('console', msg => {
|
|
||||||
logs.push(`[${msg.type()}] ${msg.text()}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToOpenGLTab(page, box);
|
await switchToOpenGLTab(page, box);
|
||||||
|
|
||||||
|
|
@ -112,17 +63,13 @@ test.describe('OpenGL Tests', () => {
|
||||||
];
|
];
|
||||||
|
|
||||||
for (let i = 0; i < testNames.length; i++) {
|
for (let i = 0; i < testNames.length; i++) {
|
||||||
console.log(`\n--- Testing: ${testNames[i]} (index ${i}) ---`);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await selectGLTest(page, box, i);
|
await selectGLTest(page, box, i);
|
||||||
await page.screenshot({
|
await page.screenshot({
|
||||||
path: `test-results/gl-test-${i}-${testNames[i].replace(/\s+/g, '-').toLowerCase()}.png`,
|
path: `test-results/gl-test-${i}-${testNames[i].replace(/\s+/g, '-').toLowerCase()}.png`,
|
||||||
fullPage: true
|
fullPage: true
|
||||||
});
|
});
|
||||||
console.log(`${testNames[i]}: OK`);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(`${testNames[i]}: FAILED - ${e}`);
|
|
||||||
await page.screenshot({
|
await page.screenshot({
|
||||||
path: `test-results/gl-test-${i}-${testNames[i].replace(/\s+/g, '-').toLowerCase()}-error.png`,
|
path: `test-results/gl-test-${i}-${testNames[i].replace(/\s+/g, '-').toLowerCase()}-error.png`,
|
||||||
fullPage: true
|
fullPage: true
|
||||||
|
|
@ -131,24 +78,13 @@ test.describe('OpenGL Tests', () => {
|
||||||
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('\n=== ERRORS ===');
|
|
||||||
errors.forEach(err => console.log(err));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Run All Tests button', async ({ page }) => {
|
test('Run All Tests button', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => {
|
|
||||||
errors.push(`${err.message}\n${err.stack || 'No stack'}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
await switchToOpenGLTab(page, box);
|
await switchToOpenGLTab(page, box);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect, waitForApp } from './utils/fixtures';
|
||||||
|
|
||||||
test.describe('wxTimer Tests', () => {
|
test.describe('wxTimer Tests', () => {
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
|
|
@ -10,38 +10,19 @@ test.describe('wxTimer Tests', () => {
|
||||||
await page.waitForTimeout(1000);
|
await page.waitForTimeout(1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Timer test app loads successfully', async ({ page }) => {
|
test('Timer test app loads successfully', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
page.on('console', msg => {
|
|
||||||
if (msg.text().includes('[TIMER_')) {
|
|
||||||
consoleLogs.push(msg.text());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
const hasStartupLog = consoleLogs.some(log =>
|
const hasStartupLog = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('TIMER_TEST') && log.includes('started successfully')
|
log.includes('TIMER_TEST') && log.includes('started successfully')
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('Timer app logs:', consoleLogs);
|
|
||||||
console.log('Timer app loaded:', hasStartupLog);
|
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/timer-01-loaded.png' });
|
await page.screenshot({ path: 'test-results/timer-01-loaded.png' });
|
||||||
|
|
||||||
const pageErrors: string[] = [];
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
page.on('pageerror', err => pageErrors.push(err.message));
|
|
||||||
expect(pageErrors.length).toBe(0);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Slow timer can be started and stopped', async ({ page }) => {
|
test('Slow timer can be started and stopped', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
page.on('console', msg => {
|
|
||||||
if (msg.text().includes('[TIMER_')) {
|
|
||||||
consoleLogs.push(msg.text());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
const canvas = page.locator('canvas');
|
const canvas = page.locator('canvas');
|
||||||
|
|
@ -50,10 +31,9 @@ test.describe('wxTimer Tests', () => {
|
||||||
await canvas.click({ position: { x: 240, y: 125 } });
|
await canvas.click({ position: { x: 240, y: 125 } });
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
console.log('After start:', consoleLogs);
|
|
||||||
await page.screenshot({ path: 'test-results/timer-02-started.png' });
|
await page.screenshot({ path: 'test-results/timer-02-started.png' });
|
||||||
|
|
||||||
const hasStartEvent = consoleLogs.some(log =>
|
const hasStartEvent = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('Slow timer started')
|
log.includes('Slow timer started')
|
||||||
);
|
);
|
||||||
expect(hasStartEvent).toBe(true);
|
expect(hasStartEvent).toBe(true);
|
||||||
|
|
@ -62,32 +42,23 @@ test.describe('wxTimer Tests', () => {
|
||||||
await page.waitForTimeout(1500);
|
await page.waitForTimeout(1500);
|
||||||
await page.screenshot({ path: 'test-results/timer-03-ticked.png' });
|
await page.screenshot({ path: 'test-results/timer-03-ticked.png' });
|
||||||
|
|
||||||
const hasTickEvent = consoleLogs.some(log =>
|
const hasTickEvent = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('TIMER_TICK')
|
log.includes('TIMER_TICK')
|
||||||
);
|
);
|
||||||
console.log('Has tick event:', hasTickEvent);
|
|
||||||
|
|
||||||
// Click Stop button
|
// Click Stop button
|
||||||
await canvas.click({ position: { x: 320, y: 125 } });
|
await canvas.click({ position: { x: 320, y: 125 } });
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
console.log('After stop:', consoleLogs);
|
|
||||||
await page.screenshot({ path: 'test-results/timer-04-stopped.png' });
|
await page.screenshot({ path: 'test-results/timer-04-stopped.png' });
|
||||||
|
|
||||||
const hasStopEvent = consoleLogs.some(log =>
|
const hasStopEvent = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('Slow timer stopped')
|
log.includes('Slow timer stopped')
|
||||||
);
|
);
|
||||||
expect(hasStopEvent).toBe(true);
|
expect(hasStopEvent).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Fast timer can be started and updates gauge', async ({ page }) => {
|
test('Fast timer can be started and updates gauge', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
page.on('console', msg => {
|
|
||||||
if (msg.text().includes('[TIMER_')) {
|
|
||||||
consoleLogs.push(msg.text());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
const canvas = page.locator('canvas');
|
const canvas = page.locator('canvas');
|
||||||
|
|
@ -96,10 +67,9 @@ test.describe('wxTimer Tests', () => {
|
||||||
await canvas.click({ position: { x: 220, y: 260 } });
|
await canvas.click({ position: { x: 220, y: 260 } });
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
console.log('Fast timer started:', consoleLogs);
|
|
||||||
await page.screenshot({ path: 'test-results/timer-05-fast-started.png' });
|
await page.screenshot({ path: 'test-results/timer-05-fast-started.png' });
|
||||||
|
|
||||||
const hasFastStartEvent = consoleLogs.some(log =>
|
const hasFastStartEvent = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('Fast timer started')
|
log.includes('Fast timer started')
|
||||||
);
|
);
|
||||||
expect(hasFastStartEvent).toBe(true);
|
expect(hasFastStartEvent).toBe(true);
|
||||||
|
|
@ -112,23 +82,15 @@ test.describe('wxTimer Tests', () => {
|
||||||
await canvas.click({ position: { x: 340, y: 260 } });
|
await canvas.click({ position: { x: 340, y: 260 } });
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
console.log('Fast timer stopped:', consoleLogs);
|
|
||||||
await page.screenshot({ path: 'test-results/timer-07-fast-stopped.png' });
|
await page.screenshot({ path: 'test-results/timer-07-fast-stopped.png' });
|
||||||
|
|
||||||
const hasFastStopEvent = consoleLogs.some(log =>
|
const hasFastStopEvent = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('Fast timer stopped')
|
log.includes('Fast timer stopped')
|
||||||
);
|
);
|
||||||
expect(hasFastStopEvent).toBe(true);
|
expect(hasFastStopEvent).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Reset counters button works', async ({ page }) => {
|
test('Reset counters button works', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
page.on('console', msg => {
|
|
||||||
if (msg.text().includes('[TIMER_EVENT]')) {
|
|
||||||
consoleLogs.push(msg.text());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
const canvas = page.locator('canvas');
|
const canvas = page.locator('canvas');
|
||||||
|
|
@ -141,10 +103,9 @@ test.describe('wxTimer Tests', () => {
|
||||||
await canvas.click({ position: { x: 300, y: 320 } });
|
await canvas.click({ position: { x: 300, y: 320 } });
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
console.log('After reset:', consoleLogs);
|
|
||||||
await page.screenshot({ path: 'test-results/timer-08-reset.png' });
|
await page.screenshot({ path: 'test-results/timer-08-reset.png' });
|
||||||
|
|
||||||
const hasResetEvent = consoleLogs.some(log =>
|
const hasResetEvent = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('Counters reset')
|
log.includes('Counters reset')
|
||||||
);
|
);
|
||||||
expect(hasResetEvent).toBe(true);
|
expect(hasResetEvent).toBe(true);
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,21 @@
|
||||||
// wxToolBar and wxStatusBar Tests - Toolbar and status bar KiCad uses
|
// wxToolBar and wxStatusBar Tests - Toolbar and status bar KiCad uses
|
||||||
import { test, expect, Page } from '@playwright/test';
|
import { test, expect, MAIN_CANVAS, tryLoadApp, getCanvasBox } from './utils/fixtures';
|
||||||
|
|
||||||
const MAIN_CANVAS = '#canvas';
|
|
||||||
|
|
||||||
async function tryLoadApp(page: Page, timeout = 15000) {
|
|
||||||
try {
|
|
||||||
await page.waitForSelector(MAIN_CANVAS, { state: 'visible', timeout });
|
|
||||||
await page.waitForTimeout(500);
|
|
||||||
return true;
|
|
||||||
} catch {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test.describe('wxToolBar & wxStatusBar Tests', () => {
|
test.describe('wxToolBar & wxStatusBar Tests', () => {
|
||||||
|
|
||||||
test('Toolbar test app loads successfully', async ({ page }) => {
|
test('Toolbar test app loads successfully', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => errors.push(`[PAGE_ERROR] ${err.message}`));
|
|
||||||
page.on('console', msg => logs.push(`[${msg.type()}] ${msg.text()}`));
|
|
||||||
|
|
||||||
await page.goto('/standalone/toolbar/toolbar_test.html');
|
await page.goto('/standalone/toolbar/toolbar_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/toolbar-01-loaded.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/toolbar-01-loaded.png', fullPage: true });
|
||||||
|
|
||||||
const hasStartup = logs.some(l => l.includes('Toolbar test app started'));
|
const hasStartup = testLogger.consoleLogs.some(l => l.includes('Toolbar test app started'));
|
||||||
|
|
||||||
console.log('Toolbar loaded:', loaded);
|
|
||||||
console.log('Toolbar logs:', logs.filter(l => l.includes('TOOLBAR')));
|
|
||||||
console.log('Toolbar errors:', errors);
|
|
||||||
|
|
||||||
expect(loaded, 'Toolbar app should load').toBe(true);
|
expect(loaded, 'Toolbar app should load').toBe(true);
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Toolbar buttons are visible', async ({ page }) => {
|
test('Toolbar buttons are visible', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/toolbar/toolbar_test.html');
|
await page.goto('/standalone/toolbar/toolbar_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -50,16 +25,12 @@ test.describe('wxToolBar & wxStatusBar Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/toolbar-02-buttons.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/toolbar-02-buttons.png', fullPage: true });
|
||||||
|
|
||||||
const hasToolbarLog = logs.some(l => l.includes('Toolbar created'));
|
const hasToolbarLog = testLogger.consoleLogs.some(l => l.includes('Toolbar created'));
|
||||||
console.log('Toolbar logs:', logs.filter(l => l.includes('TOOLBAR') || l.includes('Toolbar')));
|
|
||||||
|
|
||||||
expect(hasToolbarLog).toBe(true);
|
expect(hasToolbarLog).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('New tool button can be clicked', async ({ page }) => {
|
test('New tool button can be clicked', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/toolbar/toolbar_test.html');
|
await page.goto('/standalone/toolbar/toolbar_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -67,9 +38,7 @@ test.describe('wxToolBar & wxStatusBar Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Click New button (first tool, around x=30)
|
// Click New button (first tool, around x=30)
|
||||||
await page.mouse.click(box.x + 30, box.y + 45);
|
await page.mouse.click(box.x + 30, box.y + 45);
|
||||||
|
|
@ -77,17 +46,11 @@ test.describe('wxToolBar & wxStatusBar Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/toolbar-03-new-clicked.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/toolbar-03-new-clicked.png', fullPage: true });
|
||||||
|
|
||||||
const hasNewEvent = logs.some(l => l.includes('New clicked'));
|
|
||||||
console.log('New logs:', logs.filter(l => l.includes('TOOLBAR') || l.includes('New')));
|
|
||||||
|
|
||||||
// Smoke test
|
// Smoke test
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Zoom tools can be clicked', async ({ page }) => {
|
test('Zoom tools can be clicked', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/toolbar/toolbar_test.html');
|
await page.goto('/standalone/toolbar/toolbar_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -95,9 +58,7 @@ test.describe('wxToolBar & wxStatusBar Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Click Zoom In
|
// Click Zoom In
|
||||||
await page.mouse.click(box.x + 230, box.y + 45);
|
await page.mouse.click(box.x + 230, box.y + 45);
|
||||||
|
|
@ -109,16 +70,10 @@ test.describe('wxToolBar & wxStatusBar Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/toolbar-04-zoom.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/toolbar-04-zoom.png', fullPage: true });
|
||||||
|
|
||||||
const hasZoomEvent = logs.some(l => l.includes('Zoom'));
|
|
||||||
console.log('Zoom logs:', logs.filter(l => l.includes('TOOLBAR') || l.includes('Zoom')));
|
|
||||||
|
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Toggle tool changes state', async ({ page }) => {
|
test('Toggle tool changes state', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/toolbar/toolbar_test.html');
|
await page.goto('/standalone/toolbar/toolbar_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -126,9 +81,7 @@ test.describe('wxToolBar & wxStatusBar Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Click Toggle button (after separator, around x=350)
|
// Click Toggle button (after separator, around x=350)
|
||||||
await page.mouse.click(box.x + 350, box.y + 45);
|
await page.mouse.click(box.x + 350, box.y + 45);
|
||||||
|
|
@ -142,16 +95,10 @@ test.describe('wxToolBar & wxStatusBar Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/toolbar-06-toggle-off.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/toolbar-06-toggle-off.png', fullPage: true });
|
||||||
|
|
||||||
const hasToggleEvents = logs.some(l => l.includes('Toggle'));
|
|
||||||
console.log('Toggle logs:', logs.filter(l => l.includes('TOOLBAR') || l.includes('Toggle')));
|
|
||||||
|
|
||||||
expect(true).toBe(true);
|
expect(true).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Status bar shows messages', async ({ page }) => {
|
test('Status bar shows messages', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/toolbar/toolbar_test.html');
|
await page.goto('/standalone/toolbar/toolbar_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -161,19 +108,12 @@ test.describe('wxToolBar & wxStatusBar Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/toolbar-07-statusbar.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/toolbar-07-statusbar.png', fullPage: true });
|
||||||
|
|
||||||
const hasStatusBarLog = logs.some(l => l.includes('Status bar created'));
|
const hasStatusBarLog = testLogger.consoleLogs.some(l => l.includes('Status bar created'));
|
||||||
console.log('Status bar logs:', logs.filter(l => l.includes('TOOLBAR') || l.includes('Status')));
|
|
||||||
|
|
||||||
expect(hasStatusBarLog).toBe(true);
|
expect(hasStatusBarLog).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('All toolbar buttons accessible', async ({ page }) => {
|
test('All toolbar buttons accessible', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => errors.push(err.message));
|
|
||||||
page.on('console', msg => logs.push(msg.text()));
|
|
||||||
|
|
||||||
await page.goto('/standalone/toolbar/toolbar_test.html');
|
await page.goto('/standalone/toolbar/toolbar_test.html');
|
||||||
const loaded = await tryLoadApp(page);
|
const loaded = await tryLoadApp(page);
|
||||||
if (!loaded) {
|
if (!loaded) {
|
||||||
|
|
@ -181,9 +121,7 @@ test.describe('wxToolBar & wxStatusBar Tests', () => {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const box = await getCanvasBox(page);
|
||||||
const box = await canvas.boundingBox();
|
|
||||||
if (!box) throw new Error('Canvas not found');
|
|
||||||
|
|
||||||
// Click all toolbar buttons
|
// Click all toolbar buttons
|
||||||
const buttonPositions = [30, 85, 140, 230, 290, 350]; // New, Open, Save, ZoomIn, ZoomOut, Toggle
|
const buttonPositions = [30, 85, 140, 230, 290, 350]; // New, Open, Save, ZoomIn, ZoomOut, Toggle
|
||||||
|
|
@ -194,9 +132,6 @@ test.describe('wxToolBar & wxStatusBar Tests', () => {
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/toolbar-08-all-buttons.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/toolbar-08-all-buttons.png', fullPage: true });
|
||||||
|
|
||||||
console.log('\n=== TOOLBAR EVENTS ===');
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
logs.filter(l => l.includes('TOOLBAR')).forEach(l => console.log(l));
|
|
||||||
|
|
||||||
expect(errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from './utils/fixtures';
|
||||||
|
|
||||||
test.describe('wxTreeCtrl Tests', () => {
|
test.describe('wxTreeCtrl Tests', () => {
|
||||||
test.beforeEach(async ({ page }) => {
|
test.beforeEach(async ({ page }) => {
|
||||||
|
|
@ -10,60 +10,31 @@ test.describe('wxTreeCtrl Tests', () => {
|
||||||
await page.waitForTimeout(1000);
|
await page.waitForTimeout(1000);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Tree test app loads successfully', async ({ page }) => {
|
test('Tree test app loads successfully', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
const pageErrors: string[] = [];
|
|
||||||
|
|
||||||
page.on('console', msg => {
|
|
||||||
if (msg.text().includes('[TREE_')) {
|
|
||||||
consoleLogs.push(msg.text());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
page.on('pageerror', err => pageErrors.push(err.message));
|
|
||||||
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
const hasStartupLog = consoleLogs.some(log =>
|
const hasStartupLog = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('TREE_TEST') && log.includes('started successfully')
|
log.includes('TREE_TEST') && log.includes('started successfully')
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('Tree app loaded:', hasStartupLog);
|
|
||||||
console.log('Tree app logs:', consoleLogs);
|
|
||||||
console.log('Tree app errors:', pageErrors);
|
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/tree-01-loaded.png' });
|
await page.screenshot({ path: 'test-results/tree-01-loaded.png' });
|
||||||
|
|
||||||
expect(pageErrors.length).toBe(0);
|
expect(testLogger.errors.filter(e => !e.includes('favicon'))).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Tree is populated with KiCad-like hierarchy', async ({ page }) => {
|
test('Tree is populated with KiCad-like hierarchy', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
page.on('console', msg => {
|
|
||||||
if (msg.text().includes('[TREE_EVENT]')) {
|
|
||||||
consoleLogs.push(msg.text());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
const hasPopulatedLog = consoleLogs.some(log =>
|
const hasPopulatedLog = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('Tree populated with KiCad-like hierarchy')
|
log.includes('Tree populated with KiCad-like hierarchy')
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log('Tree hierarchy logs:', consoleLogs);
|
|
||||||
await page.screenshot({ path: 'test-results/tree-02-hierarchy.png' });
|
await page.screenshot({ path: 'test-results/tree-02-hierarchy.png' });
|
||||||
|
|
||||||
expect(hasPopulatedLog).toBe(true);
|
expect(hasPopulatedLog).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Tree item can be selected', async ({ page }) => {
|
test('Tree item can be selected', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
page.on('console', msg => {
|
|
||||||
if (msg.text().includes('[TREE_EVENT]')) {
|
|
||||||
consoleLogs.push(msg.text());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
const canvas = page.locator('canvas');
|
const canvas = page.locator('canvas');
|
||||||
|
|
@ -72,23 +43,14 @@ test.describe('wxTreeCtrl Tests', () => {
|
||||||
await canvas.click({ position: { x: 100, y: 180 } });
|
await canvas.click({ position: { x: 100, y: 180 } });
|
||||||
await page.waitForTimeout(300);
|
await page.waitForTimeout(300);
|
||||||
|
|
||||||
console.log('Selection logs:', consoleLogs);
|
|
||||||
await page.screenshot({ path: 'test-results/tree-03-selected.png' });
|
await page.screenshot({ path: 'test-results/tree-03-selected.png' });
|
||||||
|
|
||||||
const hasSelectionEvent = consoleLogs.some(log =>
|
const hasSelectionEvent = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('Selection changed')
|
log.includes('Selection changed')
|
||||||
);
|
);
|
||||||
console.log('Has selection event:', hasSelectionEvent);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Expand All button works', async ({ page }) => {
|
test('Expand All button works', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
page.on('console', msg => {
|
|
||||||
if (msg.text().includes('[TREE_EVENT]')) {
|
|
||||||
consoleLogs.push(msg.text());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
const canvas = page.locator('canvas');
|
const canvas = page.locator('canvas');
|
||||||
|
|
@ -97,23 +59,15 @@ test.describe('wxTreeCtrl Tests', () => {
|
||||||
await canvas.click({ position: { x: 80, y: 95 } });
|
await canvas.click({ position: { x: 80, y: 95 } });
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
console.log('Expand all logs:', consoleLogs);
|
|
||||||
await page.screenshot({ path: 'test-results/tree-04-expanded.png' });
|
await page.screenshot({ path: 'test-results/tree-04-expanded.png' });
|
||||||
|
|
||||||
const hasExpandEvent = consoleLogs.some(log =>
|
const hasExpandEvent = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('All items expanded')
|
log.includes('All items expanded')
|
||||||
);
|
);
|
||||||
expect(hasExpandEvent).toBe(true);
|
expect(hasExpandEvent).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Collapse All button works', async ({ page }) => {
|
test('Collapse All button works', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
page.on('console', msg => {
|
|
||||||
if (msg.text().includes('[TREE_EVENT]')) {
|
|
||||||
consoleLogs.push(msg.text());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
const canvas = page.locator('canvas');
|
const canvas = page.locator('canvas');
|
||||||
|
|
@ -122,23 +76,15 @@ test.describe('wxTreeCtrl Tests', () => {
|
||||||
await canvas.click({ position: { x: 200, y: 95 } });
|
await canvas.click({ position: { x: 200, y: 95 } });
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
console.log('Collapse all logs:', consoleLogs);
|
|
||||||
await page.screenshot({ path: 'test-results/tree-05-collapsed.png' });
|
await page.screenshot({ path: 'test-results/tree-05-collapsed.png' });
|
||||||
|
|
||||||
const hasCollapseEvent = consoleLogs.some(log =>
|
const hasCollapseEvent = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('All items collapsed')
|
log.includes('All items collapsed')
|
||||||
);
|
);
|
||||||
expect(hasCollapseEvent).toBe(true);
|
expect(hasCollapseEvent).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Add Item button works with selection', async ({ page }) => {
|
test('Add Item button works with selection', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
page.on('console', msg => {
|
|
||||||
if (msg.text().includes('[TREE_EVENT]')) {
|
|
||||||
consoleLogs.push(msg.text());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
const canvas = page.locator('canvas');
|
const canvas = page.locator('canvas');
|
||||||
|
|
@ -151,23 +97,15 @@ test.describe('wxTreeCtrl Tests', () => {
|
||||||
await canvas.click({ position: { x: 310, y: 95 } });
|
await canvas.click({ position: { x: 310, y: 95 } });
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
console.log('Add item logs:', consoleLogs);
|
|
||||||
await page.screenshot({ path: 'test-results/tree-06-added.png' });
|
await page.screenshot({ path: 'test-results/tree-06-added.png' });
|
||||||
|
|
||||||
const hasAddEvent = consoleLogs.some(log =>
|
const hasAddEvent = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('Added new item') || log.includes('No item selected')
|
log.includes('Added new item') || log.includes('No item selected')
|
||||||
);
|
);
|
||||||
expect(hasAddEvent).toBe(true);
|
expect(hasAddEvent).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Delete Item button works with selection', async ({ page }) => {
|
test('Delete Item button works with selection', async ({ page, testLogger }) => {
|
||||||
const consoleLogs: string[] = [];
|
|
||||||
page.on('console', msg => {
|
|
||||||
if (msg.text().includes('[TREE_EVENT]')) {
|
|
||||||
consoleLogs.push(msg.text());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
const canvas = page.locator('canvas');
|
const canvas = page.locator('canvas');
|
||||||
|
|
@ -180,10 +118,9 @@ test.describe('wxTreeCtrl Tests', () => {
|
||||||
await canvas.click({ position: { x: 440, y: 95 } });
|
await canvas.click({ position: { x: 440, y: 95 } });
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
console.log('Delete item logs:', consoleLogs);
|
|
||||||
await page.screenshot({ path: 'test-results/tree-07-deleted.png' });
|
await page.screenshot({ path: 'test-results/tree-07-deleted.png' });
|
||||||
|
|
||||||
const hasDeleteEvent = consoleLogs.some(log =>
|
const hasDeleteEvent = testLogger.consoleLogs.some(log =>
|
||||||
log.includes('Deleted item') || log.includes('Cannot delete')
|
log.includes('Deleted item') || log.includes('Cannot delete')
|
||||||
);
|
);
|
||||||
expect(hasDeleteEvent).toBe(true);
|
expect(hasDeleteEvent).toBe(true);
|
||||||
|
|
|
||||||
23
tests/e2e/utils/fixtures.ts
Normal file
23
tests/e2e/utils/fixtures.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { test as base } from '@playwright/test';
|
||||||
|
import { setupTestLogger, writeTestLogs, TestLogger, MAIN_CANVAS, waitForApp, tryLoadApp, getCanvasBox } from './test-utils';
|
||||||
|
|
||||||
|
// Extend base test with automatic logging
|
||||||
|
export const test = base.extend<{
|
||||||
|
testLogger: TestLogger;
|
||||||
|
}>({
|
||||||
|
testLogger: async ({ page }, use, testInfo) => {
|
||||||
|
// Build test name from describe block + test title
|
||||||
|
const testName = testInfo.titlePath.join(' - ');
|
||||||
|
|
||||||
|
const logger = setupTestLogger(page);
|
||||||
|
|
||||||
|
await use(logger);
|
||||||
|
|
||||||
|
// Write logs after test completes
|
||||||
|
writeTestLogs(testName, logger);
|
||||||
|
logger.cleanup();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export { expect } from '@playwright/test';
|
||||||
|
export { MAIN_CANVAS, waitForApp, tryLoadApp, getCanvasBox };
|
||||||
94
tests/e2e/utils/test-utils.ts
Normal file
94
tests/e2e/utils/test-utils.ts
Normal file
|
|
@ -0,0 +1,94 @@
|
||||||
|
import { Page } from '@playwright/test';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
export const MAIN_CANVAS = '#canvas';
|
||||||
|
export const LOGS_DIR = path.join(__dirname, '..', '..', 'logs');
|
||||||
|
|
||||||
|
export interface TestLogger {
|
||||||
|
consoleLogs: string[];
|
||||||
|
errors: string[];
|
||||||
|
cleanup: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure logs directory exists
|
||||||
|
export function ensureLogsDir() {
|
||||||
|
if (!fs.existsSync(LOGS_DIR)) {
|
||||||
|
fs.mkdirSync(LOGS_DIR, { recursive: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup logging for a test - captures console and errors
|
||||||
|
export function setupTestLogger(page: Page): TestLogger {
|
||||||
|
const consoleLogs: string[] = [];
|
||||||
|
const errors: string[] = [];
|
||||||
|
|
||||||
|
const consoleHandler = (msg: any) => {
|
||||||
|
const type = msg.type();
|
||||||
|
const text = msg.text();
|
||||||
|
const timestamp = new Date().toISOString();
|
||||||
|
consoleLogs.push(`[${timestamp}] [${type.toUpperCase()}] ${text}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
const errorHandler = (err: Error) => {
|
||||||
|
const timestamp = new Date().toISOString();
|
||||||
|
const stack = err.stack || 'No stack trace available';
|
||||||
|
errors.push(`[${timestamp}] [ERROR] ${err.message}\n${stack}`);
|
||||||
|
};
|
||||||
|
|
||||||
|
page.on('console', consoleHandler);
|
||||||
|
page.on('pageerror', errorHandler);
|
||||||
|
|
||||||
|
const cleanup = () => {
|
||||||
|
page.off('console', consoleHandler);
|
||||||
|
page.off('pageerror', errorHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
return { consoleLogs, errors, cleanup };
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write logs to files after test completion
|
||||||
|
export function writeTestLogs(testName: string, logger: TestLogger) {
|
||||||
|
ensureLogsDir();
|
||||||
|
|
||||||
|
// Sanitize test name for filesystem
|
||||||
|
const safeTestName = testName
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/[^a-z0-9]+/g, '-')
|
||||||
|
.replace(/^-+|-+$/g, '');
|
||||||
|
|
||||||
|
// Always write console log file
|
||||||
|
const logFile = path.join(LOGS_DIR, `${safeTestName}.log`);
|
||||||
|
fs.writeFileSync(logFile, logger.consoleLogs.join('\n'));
|
||||||
|
|
||||||
|
// Only write error file if there are errors (excluding favicon)
|
||||||
|
const realErrors = logger.errors.filter(e => !e.includes('favicon'));
|
||||||
|
if (realErrors.length > 0) {
|
||||||
|
const errorFile = path.join(LOGS_DIR, `${safeTestName}.errors.log`);
|
||||||
|
fs.writeFileSync(errorFile, realErrors.join('\n\n'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to wait for app initialization
|
||||||
|
export async function waitForApp(page: Page, timeout = 30000) {
|
||||||
|
await page.waitForSelector(MAIN_CANVAS, { state: 'visible', timeout });
|
||||||
|
await page.waitForTimeout(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper to try loading app with fallback
|
||||||
|
export async function tryLoadApp(page: Page, timeout = 15000): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await waitForApp(page, timeout);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get canvas bounding box helper
|
||||||
|
export async function getCanvasBox(page: Page) {
|
||||||
|
const canvas = page.locator(MAIN_CANVAS);
|
||||||
|
const box = await canvas.boundingBox();
|
||||||
|
if (!box) throw new Error('Canvas not found');
|
||||||
|
return box;
|
||||||
|
}
|
||||||
|
|
@ -1,13 +1,5 @@
|
||||||
import { test, expect, Page } from '@playwright/test';
|
import { test, expect, MAIN_CANVAS, waitForApp } from './utils/fixtures';
|
||||||
|
import { Page } from '@playwright/test';
|
||||||
// Use #canvas for the main canvas (wxWidgets creates window-specific canvases too)
|
|
||||||
const MAIN_CANVAS = '#canvas';
|
|
||||||
|
|
||||||
// Helper to wait for app to be fully loaded
|
|
||||||
async function waitForApp(page: Page) {
|
|
||||||
await page.waitForSelector(MAIN_CANVAS, { state: 'visible', timeout: 30000 });
|
|
||||||
await page.waitForTimeout(500); // Let UI settle
|
|
||||||
}
|
|
||||||
|
|
||||||
// Capture console events with [EVENT] prefix
|
// Capture console events with [EVENT] prefix
|
||||||
function captureEvents(page: Page): string[] {
|
function captureEvents(page: Page): string[] {
|
||||||
|
|
@ -56,19 +48,7 @@ async function dragCanvas(page: Page, startX: number, startY: number, endX: numb
|
||||||
}
|
}
|
||||||
|
|
||||||
test.describe('wxWidgets WASM - Diagnostics', () => {
|
test.describe('wxWidgets WASM - Diagnostics', () => {
|
||||||
test('comprehensive UI interaction test', async ({ page }) => {
|
test('comprehensive UI interaction test', async ({ page, testLogger }) => {
|
||||||
const allLogs: string[] = [];
|
|
||||||
const errors: string[] = [];
|
|
||||||
|
|
||||||
// Capture ALL console messages
|
|
||||||
page.on('console', msg => {
|
|
||||||
allLogs.push(`[${msg.type()}] ${msg.text()}`);
|
|
||||||
});
|
|
||||||
page.on('pageerror', err => {
|
|
||||||
// Include stack trace for better debugging
|
|
||||||
const stack = err.stack || 'No stack trace available';
|
|
||||||
errors.push(`[PAGE_ERROR] ${err.message}\n${stack}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
|
|
||||||
|
|
@ -80,8 +60,8 @@ test.describe('wxWidgets WASM - Diagnostics', () => {
|
||||||
await page.waitForSelector('#canvas', { state: 'visible', timeout: 30000 });
|
await page.waitForSelector('#canvas', { state: 'visible', timeout: 30000 });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await page.screenshot({ path: 'test-results/02-timeout.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/02-timeout.png', fullPage: true });
|
||||||
console.log('Logs so far:', allLogs);
|
console.log('Logs so far:', testLogger.consoleLogs);
|
||||||
console.log('Errors:', errors);
|
console.log('Errors:', testLogger.errors);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -302,18 +282,13 @@ test.describe('wxWidgets WASM - Diagnostics', () => {
|
||||||
|
|
||||||
// Print all logs
|
// Print all logs
|
||||||
console.log('\n=== ALL CONSOLE LOGS ===');
|
console.log('\n=== ALL CONSOLE LOGS ===');
|
||||||
allLogs.forEach(log => console.log(log));
|
testLogger.consoleLogs.forEach(log => console.log(log));
|
||||||
console.log('\n=== ALL ERRORS ===');
|
console.log('\n=== ALL ERRORS ===');
|
||||||
errors.forEach(err => console.log(err));
|
testLogger.errors.forEach(err => console.log(err));
|
||||||
console.log('========================\n');
|
console.log('========================\n');
|
||||||
|
|
||||||
// Save logs to file
|
|
||||||
const fs = require('fs');
|
|
||||||
fs.writeFileSync('test-results/console-logs.txt', allLogs.join('\n'));
|
|
||||||
fs.writeFileSync('test-results/errors.txt', errors.join('\n'));
|
|
||||||
|
|
||||||
// Fail test if there are critical errors
|
// Fail test if there are critical errors
|
||||||
const criticalErrors = errors.filter(e =>
|
const criticalErrors = testLogger.errors.filter(e =>
|
||||||
!e.includes('SharedArrayBuffer') &&
|
!e.includes('SharedArrayBuffer') &&
|
||||||
!e.includes('cross-origin')
|
!e.includes('cross-origin')
|
||||||
);
|
);
|
||||||
|
|
@ -326,20 +301,12 @@ test.describe('wxWidgets WASM - Diagnostics', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('wxWidgets WASM - Loading', () => {
|
test.describe('wxWidgets WASM - Loading', () => {
|
||||||
test('app loads without JavaScript errors', async ({ page }) => {
|
test('app loads without JavaScript errors', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
page.on('pageerror', err => errors.push(`${err.message}\n${err.stack || 'No stack'}`));
|
|
||||||
page.on('console', msg => {
|
|
||||||
if (msg.type() === 'error') {
|
|
||||||
errors.push(msg.text());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
// Filter out known non-critical errors
|
// Filter out known non-critical errors
|
||||||
const criticalErrors = errors.filter(e =>
|
const criticalErrors = testLogger.errors.filter(e =>
|
||||||
!e.includes('SharedArrayBuffer') &&
|
!e.includes('SharedArrayBuffer') &&
|
||||||
!e.includes('cross-origin') &&
|
!e.includes('cross-origin') &&
|
||||||
!isKnownWarning(e)
|
!isKnownWarning(e)
|
||||||
|
|
@ -348,7 +315,7 @@ test.describe('wxWidgets WASM - Loading', () => {
|
||||||
expect(criticalErrors).toHaveLength(0);
|
expect(criticalErrors).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('canvas element is rendered with dimensions', async ({ page }) => {
|
test('canvas element is rendered with dimensions', async ({ page, testLogger }) => {
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
|
|
||||||
const canvas = page.locator(MAIN_CANVAS);
|
const canvas = page.locator(MAIN_CANVAS);
|
||||||
|
|
@ -360,7 +327,7 @@ test.describe('wxWidgets WASM - Loading', () => {
|
||||||
expect(box?.height).toBeGreaterThan(0);
|
expect(box?.height).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('loading progress completes', async ({ page }) => {
|
test('loading progress completes', async ({ page, testLogger }) => {
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
|
|
||||||
await page.waitForFunction(() => {
|
await page.waitForFunction(() => {
|
||||||
|
|
@ -373,7 +340,7 @@ test.describe('wxWidgets WASM - Loading', () => {
|
||||||
}, { timeout: 30000 });
|
}, { timeout: 30000 });
|
||||||
});
|
});
|
||||||
|
|
||||||
test('WASM module initializes successfully', async ({ page }) => {
|
test('WASM module initializes successfully', async ({ page, testLogger }) => {
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
|
|
@ -384,20 +351,19 @@ test.describe('wxWidgets WASM - Loading', () => {
|
||||||
expect(moduleExists).toBe(true);
|
expect(moduleExists).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('application started event is logged', async ({ page }) => {
|
test('application started event is logged', async ({ page, testLogger }) => {
|
||||||
const events = captureEvents(page);
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
// Wait for the startup event to be logged
|
// Wait for the startup event to be logged
|
||||||
await page.waitForTimeout(500);
|
await page.waitForTimeout(500);
|
||||||
|
|
||||||
expect(events.some(e => e.includes('Application started'))).toBe(true);
|
expect(testLogger.consoleLogs.some(e => e.includes('Application started'))).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('wxWidgets WASM - Canvas Interaction', () => {
|
test.describe('wxWidgets WASM - Canvas Interaction', () => {
|
||||||
test('canvas receives click events', async ({ page }) => {
|
test('canvas receives click events', async ({ page, testLogger }) => {
|
||||||
const events = captureEvents(page);
|
const events = captureEvents(page);
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
@ -411,7 +377,7 @@ test.describe('wxWidgets WASM - Canvas Interaction', () => {
|
||||||
expect(events.length).toBeGreaterThanOrEqual(1);
|
expect(events.length).toBeGreaterThanOrEqual(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('canvas receives keyboard events', async ({ page }) => {
|
test('canvas receives keyboard events', async ({ page, testLogger }) => {
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
|
|
@ -428,7 +394,7 @@ test.describe('wxWidgets WASM - Canvas Interaction', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('wxWidgets WASM - Mouse Drawing', () => {
|
test.describe('wxWidgets WASM - Mouse Drawing', () => {
|
||||||
test('mouse drag creates drawing stroke', async ({ page }) => {
|
test('mouse drag creates drawing stroke', async ({ page, testLogger }) => {
|
||||||
const events = captureEvents(page);
|
const events = captureEvents(page);
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
@ -458,7 +424,7 @@ test.describe('wxWidgets WASM - Mouse Drawing', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('wxWidgets WASM - Event Logging', () => {
|
test.describe('wxWidgets WASM - Event Logging', () => {
|
||||||
test('events are logged to console with [EVENT] prefix', async ({ page }) => {
|
test('events are logged to console with [EVENT] prefix', async ({ page, testLogger }) => {
|
||||||
const events = captureEvents(page);
|
const events = captureEvents(page);
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
@ -471,7 +437,7 @@ test.describe('wxWidgets WASM - Event Logging', () => {
|
||||||
expect(events[0]).toContain('Application started');
|
expect(events[0]).toContain('Application started');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('multiple interactions produce multiple log entries', async ({ page }) => {
|
test('multiple interactions produce multiple log entries', async ({ page, testLogger }) => {
|
||||||
const events = captureEvents(page);
|
const events = captureEvents(page);
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
@ -492,7 +458,7 @@ test.describe('wxWidgets WASM - Event Logging', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('wxWidgets WASM - Visual Rendering', () => {
|
test.describe('wxWidgets WASM - Visual Rendering', () => {
|
||||||
test('frame renders with visible content', async ({ page }) => {
|
test('frame renders with visible content', async ({ page, testLogger }) => {
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
|
|
@ -508,7 +474,7 @@ test.describe('wxWidgets WASM - Visual Rendering', () => {
|
||||||
expect(box?.height).toBeGreaterThan(100);
|
expect(box?.height).toBeGreaterThan(100);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('window has reasonable dimensions', async ({ page }) => {
|
test('window has reasonable dimensions', async ({ page, testLogger }) => {
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
|
|
@ -523,10 +489,7 @@ test.describe('wxWidgets WASM - Visual Rendering', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('wxWidgets WASM - Stability', () => {
|
test.describe('wxWidgets WASM - Stability', () => {
|
||||||
test('app remains stable after multiple interactions', async ({ page }) => {
|
test('app remains stable after multiple interactions', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
page.on('pageerror', err => errors.push(`${err.message}\n${err.stack || 'No stack'}`));
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
|
|
@ -541,7 +504,7 @@ test.describe('wxWidgets WASM - Stability', () => {
|
||||||
await expect(canvas).toBeVisible();
|
await expect(canvas).toBeVisible();
|
||||||
|
|
||||||
// No JavaScript errors should have occurred
|
// No JavaScript errors should have occurred
|
||||||
const criticalErrors = errors.filter(e =>
|
const criticalErrors = testLogger.errors.filter(e =>
|
||||||
!e.includes('SharedArrayBuffer') &&
|
!e.includes('SharedArrayBuffer') &&
|
||||||
!e.includes('cross-origin') &&
|
!e.includes('cross-origin') &&
|
||||||
!isKnownWarning(e)
|
!isKnownWarning(e)
|
||||||
|
|
@ -549,7 +512,7 @@ test.describe('wxWidgets WASM - Stability', () => {
|
||||||
expect(criticalErrors).toHaveLength(0);
|
expect(criticalErrors).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('app handles rapid mouse movements', async ({ page }) => {
|
test('app handles rapid mouse movements', async ({ page, testLogger }) => {
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
|
|
@ -570,12 +533,7 @@ test.describe('wxWidgets WASM - Stability', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('wxWidgets WASM - OpenGL', () => {
|
test.describe('wxWidgets WASM - OpenGL', () => {
|
||||||
test('OpenGL tab switches successfully', async ({ page }) => {
|
test('OpenGL tab switches successfully', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => {
|
|
||||||
logs.push(msg.text());
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
|
|
@ -588,25 +546,14 @@ test.describe('wxWidgets WASM - OpenGL', () => {
|
||||||
await page.waitForTimeout(1500); // Give GL time to initialize
|
await page.waitForTimeout(1500); // Give GL time to initialize
|
||||||
|
|
||||||
// Check that we switched to the OpenGL tab
|
// Check that we switched to the OpenGL tab
|
||||||
const tabChanged = logs.some(log => log.includes('Tab changed to: OpenGL'));
|
const tabChanged = testLogger.consoleLogs.some(log => log.includes('Tab changed to: OpenGL'));
|
||||||
expect(tabChanged).toBe(true);
|
expect(tabChanged).toBe(true);
|
||||||
|
|
||||||
// Save screenshot for visual verification
|
// Save screenshot for visual verification
|
||||||
await page.screenshot({ path: 'test-results/opengl-tab-initial.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/opengl-tab-initial.png', fullPage: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
test('OpenGL tab interaction without crashes', async ({ page }) => {
|
test('OpenGL tab interaction without crashes', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => errors.push(`${err.message}\n${err.stack || 'No stack'}`));
|
|
||||||
page.on('console', msg => {
|
|
||||||
if (msg.type() === 'error' && !isKnownWarning(msg.text())) {
|
|
||||||
errors.push(msg.text());
|
|
||||||
}
|
|
||||||
logs.push(msg.text());
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
|
|
@ -630,21 +577,11 @@ test.describe('wxWidgets WASM - OpenGL', () => {
|
||||||
|
|
||||||
// Note: wxPrintf logs go to stdout which may not appear in browser console
|
// Note: wxPrintf logs go to stdout which may not appear in browser console
|
||||||
// The main verification is that the app doesn't crash
|
// The main verification is that the app doesn't crash
|
||||||
expect(errors.length).toBe(0);
|
const criticalErrors = testLogger.errors.filter(e => !isKnownWarning(e));
|
||||||
|
expect(criticalErrors.length).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('OpenGL tab renders without errors', async ({ page }) => {
|
test('OpenGL tab renders without errors', async ({ page, testLogger }) => {
|
||||||
const errors: string[] = [];
|
|
||||||
const logs: string[] = [];
|
|
||||||
|
|
||||||
page.on('pageerror', err => errors.push(`${err.message}\n${err.stack || 'No stack'}`));
|
|
||||||
page.on('console', msg => {
|
|
||||||
logs.push(`[${msg.type()}] ${msg.text()}`);
|
|
||||||
if (msg.type() === 'error' && !isKnownWarning(msg.text())) {
|
|
||||||
errors.push(msg.text());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
|
|
@ -692,26 +629,17 @@ test.describe('wxWidgets WASM - OpenGL', () => {
|
||||||
const screenshot = await page.screenshot();
|
const screenshot = await page.screenshot();
|
||||||
expect(screenshot.length).toBeGreaterThan(0);
|
expect(screenshot.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
// Save for visual inspection including errors
|
|
||||||
const fs = require('fs');
|
|
||||||
fs.writeFileSync('test-results/opengl-render.png', screenshot);
|
|
||||||
fs.writeFileSync('test-results/opengl-debug.json', JSON.stringify({ glCanvasInfo, logs, errors }, null, 2));
|
|
||||||
|
|
||||||
// App should still be responsive after GL rendering
|
// App should still be responsive after GL rendering
|
||||||
await expect(page.locator(MAIN_CANVAS)).toBeVisible();
|
await expect(page.locator(MAIN_CANVAS)).toBeVisible();
|
||||||
|
|
||||||
// No critical JavaScript errors
|
// No critical JavaScript errors
|
||||||
expect(errors.length).toBe(0);
|
const criticalErrors = testLogger.errors.filter(e => !isKnownWarning(e));
|
||||||
|
expect(criticalErrors.length).toBe(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test.describe('wxWidgets WASM - Canvas Z-Ordering and Visibility', () => {
|
test.describe('wxWidgets WASM - Canvas Z-Ordering and Visibility', () => {
|
||||||
test('GL canvas should hide when switching away from OpenGL tab', async ({ page }) => {
|
test('GL canvas should hide when switching away from OpenGL tab', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => {
|
|
||||||
logs.push(msg.text());
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
|
|
@ -724,7 +652,7 @@ test.describe('wxWidgets WASM - Canvas Z-Ordering and Visibility', () => {
|
||||||
await page.waitForTimeout(1000);
|
await page.waitForTimeout(1000);
|
||||||
|
|
||||||
// Verify we're on OpenGL tab
|
// Verify we're on OpenGL tab
|
||||||
const onOpenGLTab = logs.some(log => log.includes('Tab changed to: OpenGL'));
|
const onOpenGLTab = testLogger.consoleLogs.some(log => log.includes('Tab changed to: OpenGL'));
|
||||||
expect(onOpenGLTab).toBe(true);
|
expect(onOpenGLTab).toBe(true);
|
||||||
|
|
||||||
await page.screenshot({ path: 'test-results/glcanvas-01-on-opengl-tab.png', fullPage: true });
|
await page.screenshot({ path: 'test-results/glcanvas-01-on-opengl-tab.png', fullPage: true });
|
||||||
|
|
@ -783,12 +711,7 @@ test.describe('wxWidgets WASM - Canvas Z-Ordering and Visibility', () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('dropdown should appear above GL canvas on OpenGL tab', async ({ page }) => {
|
test('dropdown should appear above GL canvas on OpenGL tab', async ({ page, testLogger }) => {
|
||||||
const logs: string[] = [];
|
|
||||||
page.on('console', msg => {
|
|
||||||
logs.push(msg.text());
|
|
||||||
});
|
|
||||||
|
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
|
|
@ -859,7 +782,7 @@ test.describe('wxWidgets WASM - Canvas Z-Ordering and Visibility', () => {
|
||||||
console.log('Windows AFTER click:', JSON.stringify(windowsAfter));
|
console.log('Windows AFTER click:', JSON.stringify(windowsAfter));
|
||||||
|
|
||||||
// Check for any logged events
|
// Check for any logged events
|
||||||
const clickEvents = logs.filter(log =>
|
const clickEvents = testLogger.consoleLogs.filter(log =>
|
||||||
log.includes('GL Test selected') ||
|
log.includes('GL Test selected') ||
|
||||||
log.includes('clicked') ||
|
log.includes('clicked') ||
|
||||||
log.includes('Choice')
|
log.includes('Choice')
|
||||||
|
|
@ -915,7 +838,7 @@ test.describe('wxWidgets WASM - Canvas Z-Ordering and Visibility', () => {
|
||||||
// This will be verified by visual inspection of screenshots
|
// This will be verified by visual inspection of screenshots
|
||||||
});
|
});
|
||||||
|
|
||||||
test('switching tabs multiple times maintains correct visibility', async ({ page }) => {
|
test('switching tabs multiple times maintains correct visibility', async ({ page, testLogger }) => {
|
||||||
await page.goto('/minimal_test.html');
|
await page.goto('/minimal_test.html');
|
||||||
await waitForApp(page);
|
await waitForApp(page);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue