test(acceptance): prove zero-record runs and single widget loads against the v1 routes (#713)

The batch 3 gate ran PRC-003 and WID-065 against assumptions from before
the v1 migration (#699): the v1 records route answers a zero-record run
with an empty list rather than omitting it, and widget data now loads from
/qqq/v1/widget/, so the request counter saw no requests at all. PRC-003 now
proves a zero total with no records in either serialization, and WID-065
counts the v1 widget route, so its once-only and not-yet-requested checks
are no longer vacuous. A unit test covers the v1 zero-record shape.
This commit is contained in:
james.maes committed 2026-09-25 20:57:41 -05:00
1 parent f46ae2aa09
commit e9fc79b5cb
4 files changed
+18 -5

No files matched your search

+7
View File
@@ -193,6 +193,13 @@ describe('Processes API', () => {
await expect(processRecords('p', 'u')).resolves.toEqual({ totalRecords: 0, records: [] })
})
it('reads the v1 zero-record response, an empty list and a zero total, as an empty page', async () => {
const { default: apiClient } = await import('./client')
vi.mocked(apiClient.get).mockResolvedValue({ records: [], totalRecords: 0 })
const { processRecords } = await import('./processes')
await expect(processRecords('p', 'u')).resolves.toEqual({ totalRecords: 0, records: [] })
})
it('rejects a malformed records response', async () => {
const { default: apiClient } = await import('./client')
vi.mocked(apiClient.get).mockResolvedValue({ error: 'Could not find process results.' })
+1 -1
View File
@@ -383,7 +383,7 @@ export async function processRecords(
`/processes/${encodeURIComponent(processName)}/${encodeURIComponent(processUUID)}/records`,
{ params: { skip, limit } }
)
// v1 omits an empty records list
// v1 sends an empty list for a run with no records; an omitted list reads the same way
const records = body && body.records === undefined && typeof body.totalRecords === 'number' ? [] : body?.records
if (!body || !Array.isArray(records) || typeof body.totalRecords !== 'number') {
throw new Error('Invalid process records response')
@@ -33,13 +33,16 @@ test.describe('Record selection', () => {
document.querySelectorAll('[data-sonner-toast][data-type="error"]').forEach((toast) => { shown.push(toast.textContent ?? '') })
}).observe(document, { childList: true, subtree: true })
})
// the backend answers a run without records with `{"totalRecords":0}` (no empty list)
// the v1 records route answers a run without records with a zero total and no records
const previews = page.waitForResponse((response) => /^\/qqq\/v1\/processes\/clonePeople\/[^/]+\/records$/.test(new URL(response.url()).pathname))
await openProcess(page, 'clonePeople', { filter: NOBODY })
const review = await expectScreen(page, 'review', 'Review')
await expect(review.locator('[data-qqq-id="process-validation-input"]')).toHaveText('Input: 0 Person records.')
await expect(review.getByText('No record previews are available at this time.')).toBeVisible()
expect(await (await previews).json()).toEqual({ totalRecords: 0 })
const preview = (await (await previews).json()) as { records?: unknown[], totalRecords?: number }
expect(preview.totalRecords).toBe(0)
// an empty list may be sent or omitted; either way no record is previewed
expect(preview.records ?? []).toEqual([])
await advance(page, 'Next')
const validated = await expectScreen(page, 'review', 'Review')
await expect(validated.locator('[data-qqq-id="process-validation-complete"]')).toHaveText('Validation complete on 0 Person records.')
@@ -122,13 +122,16 @@ test('[WID-032] script viewer marks the current revision and shows each revision
await expect(files.first()).toContainText('return \'owned one\';')
})
/** The v1 widget data route prefix (the UI calls no unversioned route; the diagnostics fixture enforces it). */
const WIDGET_ROUTE = '/qqq/v1/widget/'
/** Records the widget data requests the page makes, by widget name. */
function widgetRequests(page: Page): Map<string, number> {
const counts = new Map<string, number>()
page.on('request', (request) => {
const { pathname } = new URL(request.url())
if (!pathname.startsWith('/widget/')) return
const name = decodeURIComponent(pathname.slice('/widget/'.length))
if (!pathname.startsWith(WIDGET_ROUTE)) return
const name = decodeURIComponent(pathname.slice(WIDGET_ROUTE.length))
counts.set(name, (counts.get(name) ?? 0) + 1)
})
return counts