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=141 defines')).toBeVisible(); await expect(page.locator('text=2501 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(); }); });