From 81b687a2eb8ae1fd37433a9d44222992c1d81330 Mon Sep 17 00:00:00 2001 From: ZDDC Date: Sat, 9 May 2026 18:39:17 -0500 Subject: [PATCH] test(browse): smoke test for empty state and mock-fs row render Browse was the only one of the eight HTML tools with no Playwright spec. Added two tests at the depth of mdedit.spec.js: - loads with the empty state visible and add-directory button enabled - renders rows from a mock directory after picking Both use the existing tests/fixtures/mock-fs-api.js machinery (no new test scaffolding) and run in ~2s under the existing chromium-only project. Co-Authored-By: Claude Opus 4.7 (1M context) --- playwright.config.js | 4 ++++ tests/browse.spec.js | 50 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 tests/browse.spec.js diff --git a/playwright.config.js b/playwright.config.js index 94196ff..58f9dda 100644 --- a/playwright.config.js +++ b/playwright.config.js @@ -51,6 +51,10 @@ export default defineConfig({ name: 'mdedit', testMatch: 'mdedit.spec.js', }, + { + name: 'browse', + testMatch: 'browse.spec.js', + }, { name: 'zddc', testMatch: 'zddc.spec.js', diff --git a/tests/browse.spec.js b/tests/browse.spec.js new file mode 100644 index 0000000..f619c73 --- /dev/null +++ b/tests/browse.spec.js @@ -0,0 +1,50 @@ +import { test, expect } from '@playwright/test'; +import { MOCK_FS_INIT_SCRIPT } from './fixtures/mock-fs-api.js'; +import * as path from 'path'; + +const HTML_PATH = path.resolve('browse/dist/browse.html'); + +test.describe('Browse', () => { + test.beforeEach(async ({ page }) => { + await page.addInitScript(MOCK_FS_INIT_SCRIPT); + }); + + test('loads with the empty state visible and add-directory button enabled', async ({ page }) => { + await page.goto(`file://${HTML_PATH}`, { waitUntil: 'load' }); + await page.waitForSelector('#addDirectoryBtn', { timeout: 15000 }); + + // file:// + no auto-server-root → the empty state is shown and the + // browse table stays hidden until the user picks a directory. + await expect(page.locator('#emptyState')).toBeVisible(); + await expect(page.locator('#browseRoot')).toBeHidden(); + + const addDirBtn = page.locator('#addDirectoryBtn'); + await expect(addDirBtn).toBeVisible(); + await expect(addDirBtn).not.toBeDisabled(); + }); + + test('renders rows from a mock directory after picking', async ({ page }) => { + await page.goto(`file://${HTML_PATH}`, { waitUntil: 'load' }); + await page.waitForSelector('#addDirectoryBtn', { timeout: 15000 }); + + await page.evaluate(() => { + window.__setMockDirectory('docs', [ + { name: 'spec.pdf', content: '%PDF-fixture', size: 1024 }, + { name: 'readme.md', content: '# Hello\n', size: 8 }, + { name: 'notes.txt', content: 'note one\nnote two\n', size: 16 }, + ]); + }); + + await page.locator('#addDirectoryBtn').click(); + + // Browse swaps from empty state to the populated table. + await page.waitForSelector('#browseRoot:not(.hidden)', { timeout: 10000 }); + await page.waitForFunction( + () => document.querySelectorAll('#browseTable tbody tr.tree-row').length >= 3, + { timeout: 10000 } + ); + + const rows = await page.locator('#browseTable tbody tr.tree-row').count(); + expect(rows).toBeGreaterThanOrEqual(3); + }); +});