doesitarm/test/playwright/pagefind-native-filter.playwright.ts
ThatGuySam 0480c47bbb test(playwright): lock browser coverage before scanner refactors
Add a typed Playwright harness for Pagefind and the Apple Silicon app-test flow so scanner work has browser-level protection. Keep the rollout plan in the same stack so the TypeScript conversion stays staged and reviewable.

Constraint: Must not change production runtime behavior in this commit
Rejected: Leave the old JS browser test and add a second harness | duplicates setup and leaves the targeted browser script broken
Confidence: high
Scope-risk: narrow
Reversibility: clean
Directive: Keep browser-only helpers under test/playwright/support until the runtime scanner surface is fully typed
Tested: pnpm run typecheck; pnpm run test:browser; pnpm run test:browser:pagefind
Not-tested: Live browser checks against doesitarm.com
2026-04-04 14:55:13 -05:00

149 lines
5 KiB
TypeScript

import type { Browser } from 'playwright-core'
import {
afterAll,
beforeAll,
describe,
expect,
it
} from 'vitest'
import {
launchBrowser,
startAstroDevServer,
stopChildProcess,
type AstroDevServer
} from './support/astro-browser-test'
describe( 'Pagefind dev search', () => {
let browser: Browser
let devServer: AstroDevServer
beforeAll( async () => {
devServer = await startAstroDevServer({
env: {
PUBLIC_SEARCH_PROVIDER: 'pagefind'
}
})
browser = await launchBrowser()
} )
afterAll( async () => {
await browser?.close()
await stopChildProcess( devServer?.process || null )
} )
it( 'renders visible Pagefind results when Native Support is clicked', async () => {
const page = await browser.newPage()
const consoleErrors: string[] = []
const pageErrors: string[] = []
const pagefindResponses: Array<{
status: number
url: string
}> = []
const failedRequests: Array<{
errorText: string
url: string
}> = []
let fragmentRequests = 0
let failedFragmentRequests = 0
page.on( 'console', message => {
if ( message.type() === 'error' ) {
consoleErrors.push( message.text() )
}
} )
page.on( 'pageerror', error => {
pageErrors.push( error.message )
} )
page.on( 'response', response => {
if ( response.url().includes( '/pagefind/pagefind.js' ) ) {
pagefindResponses.push({
status: response.status(),
url: response.url()
})
}
} )
page.on( 'request', request => {
if ( request.url().includes( '/pagefind/' ) && request.url().includes( 'pf_fragment' ) ) {
fragmentRequests++
}
} )
page.on( 'requestfailed', request => {
if ( request.url().includes( '/pagefind/pagefind.js' ) ) {
failedRequests.push({
errorText: request.failure()?.errorText || 'unknown',
url: request.url()
})
}
if ( request.url().includes( '/pagefind/' ) && request.url().includes( 'pf_fragment' ) ) {
failedFragmentRequests++
}
} )
await page.goto( devServer.baseUrl, {
waitUntil: 'domcontentloaded'
} )
await page.waitForTimeout( 3000 )
await Promise.all([
page.waitForResponse( response => {
return response.url().includes( '/pagefind/pagefind.js' )
}, {
timeout: 10 * 1000
} ),
page.getByRole( 'button', {
name: /native support/i
} ).click()
])
await page.waitForFunction( () => {
return [ ...document.querySelectorAll( 'li[data-app-slug] h3' ) ].some( node => {
const text = node.textContent || ''
return text.trim().length > 0 && !/loading/i.test( text )
} )
}, {
timeout: 15 * 1000
} )
const bodyText = await page.locator( 'body' ).textContent()
const renderedResults = await page.evaluate( () => {
const headings = [ ...document.querySelectorAll( 'li[data-app-slug] h3' ) ].map( node => {
return ( node.textContent || '' ).trim()
} )
return {
loadingRows: headings.filter( text => /loading/i.test( text ) ).length,
rows: document.querySelectorAll( 'li[data-app-slug]' ).length,
visibleHeadings: headings.slice( 0, 5 )
}
} )
expect( pagefindResponses.some( response => response.status === 200 ), devServer.output.text ).toBe( true )
expect(
pagefindResponses.some( response => response.status >= 400 ),
[
pagefindResponses.map( response => `${ response.status } ${ response.url }` ).join( '\n' ),
failedRequests.map( request => `${ request.errorText } ${ request.url }` ).join( '\n' ),
pageErrors.join( '\n' ),
consoleErrors.join( '\n' )
].join( '\n\n' )
).toBe( false )
expect( fragmentRequests, JSON.stringify( renderedResults ) ).toBeGreaterThan( 0 )
expect( fragmentRequests, JSON.stringify( renderedResults ) ).toBeLessThan( 100 )
expect( failedFragmentRequests, JSON.stringify( renderedResults ) ).toBe( 0 )
expect( renderedResults.rows, bodyText ).toBeGreaterThan( 0 )
expect( renderedResults.loadingRows, JSON.stringify( renderedResults ) ).toBe( 0 )
expect( bodyText?.includes( 'No results found' ) ?? false, JSON.stringify( renderedResults ) ).toBe( false )
expect( consoleErrors, devServer.output.text ).toEqual( [] )
expect( pageErrors, devServer.output.text ).toEqual( [] )
await page.close()
} )
} )