Files
rose-ash/tests/playwright/spec-explorer.spec.js
giles 9594362427 Spec explorer: full source in drill-in, explore any .sx file
- spec-explore-define uses serialize (full body) instead of signature
- _spec-search-dirs expanded: spec/, web/, lib/, shared/sx/ref/, sx/, sxc/, shared/sx/templates/
- explore() works with any filename, not just nav spec items
- Playwright tests use flexible regex for line/define counts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 00:10:45 +00:00

75 lines
3.0 KiB
JavaScript

const { test, expect } = require('playwright/test');
const { BASE_URL, trackErrors } = require('./helpers');
const LOAD_TIMEOUT = 30000;
async function loadExplorer(page, path) {
await page.goto(BASE_URL + '/sx/' + path, {
waitUntil: 'domcontentloaded',
timeout: LOAD_TIMEOUT,
});
await page.waitForSelector('h1, .sx-render-error, [data-sx-boundary]', {
timeout: LOAD_TIMEOUT,
});
}
test.describe('Spec Explorer', () => {
test('overview loads with evaluator definitions', async ({ page }) => {
await loadExplorer(page, '(language.(spec.(explore.evaluator)))');
await expect(page.locator('h1')).toHaveText('Evaluator');
await expect(page.locator('text=/\\d+ defines/')).toBeVisible();
await expect(page.locator('text=/\\d+ lines/')).toBeVisible();
await expect(page.locator('h2:has-text("Definitions")')).toBeVisible();
await expect(page.locator('#fn-make-cek-state')).toBeVisible();
await expect(page.locator('#fn-cek-step')).toBeVisible();
// eval-expr has 2 entries (forward decl + real), just check at least 1
await expect(page.locator('#fn-eval-expr').first()).toBeVisible();
await expect(page.locator('.sx-render-error')).toHaveCount(0);
});
test('no errors on initial load', async ({ page }) => {
const tracker = trackErrors(page);
await loadExplorer(page, '(language.(spec.(explore.evaluator)))');
await expect(page.locator('h1')).toHaveText('Evaluator');
expect(tracker.errors()).toEqual([]);
});
test('SPA nav to explorer has no render error', async ({ page }) => {
await page.goto(BASE_URL + '/sx/(language.(spec))', {
waitUntil: 'domcontentloaded',
timeout: LOAD_TIMEOUT,
});
await page.waitForSelector('h1, h2', { timeout: LOAD_TIMEOUT });
const link = page.locator('a[href*="explore.evaluator"]');
if (await link.count() > 0) {
await link.click();
await page.waitForSelector('#fn-cek-step', { timeout: LOAD_TIMEOUT });
await expect(page.locator('h1')).toHaveText('Evaluator');
const content = await page.locator('#sx-content').textContent();
expect(content).not.toContain('Render error');
expect(content).not.toContain('Not callable');
}
});
test('drill-in shows definition detail', async ({ page }) => {
await loadExplorer(page, '(language.(spec.(explore.evaluator.cek-step)))');
await expect(page.locator('text=cek-step').first()).toBeVisible();
await expect(page.locator('text=function').first()).toBeVisible();
await expect(page.locator('a:has-text("Back to evaluator")')).toBeVisible();
await expect(page.locator('text=define cek-step')).toBeVisible();
});
test('drill-in shows params and pure badge', async ({ page }) => {
await loadExplorer(page, '(language.(spec.(explore.evaluator.make-cek-state)))');
await expect(page.locator('text=control').first()).toBeVisible();
await expect(page.locator('text=env').first()).toBeVisible();
await expect(page.locator('text=kont').first()).toBeVisible();
await expect(page.locator('text=pure').first()).toBeVisible();
});
});