feat: integration search bar

This commit is contained in:
Florian Sylvain committed 2026-10-25 21:57:43 +01:00
1 parent a8fea8d900
commit 25d9c30b8a
22 files changed
+2558 -41

No files matched your search

+15
View File
@@ -230,6 +230,21 @@ const extraSources: Record<string, Source[]> = {
},
],
integration: [
{
board: officeBoard,
group: 'Integration',
states: [
'8a. Search: trigger focused',
'8b. Search: open, empty',
'8c. Search: typing, results',
'8d. Search: keyboard-selected, status code',
'8e. Search: body field match',
'8f. Search: session-only results',
'8g. Search: no results',
'8h. Search: after selecting an endpoint',
],
alias: {},
},
{
board: officeBoard,
group: 'Integration: images',
+60
View File
@@ -1246,6 +1246,45 @@ function integrationState(overrides: Partial<VisualState> = {}): VisualState {
}
}
const integrationSearchLabel = 'Search the API reference'
const desktopMinWidth = 1024
async function focusIntegrationTrigger(page: Page) {
const width = page.viewportSize()?.width ?? 0
if (width >= desktopMinWidth) {
await page.getByRole('button', { name: integrationSearchLabel, exact: true }).focus()
await page.keyboard.press('Shift+Tab')
await page.keyboard.press('Tab')
}
}
async function openIntegrationSearch(page: Page) {
await page.getByRole('button', { name: integrationSearchLabel, exact: true }).click()
await page.getByRole('combobox').waitFor()
await page.mouse.move(0, 0)
}
function searchingIntegration(query: string, arrowDowns = 0): VisualState['steps'] {
return async (page) => {
await openIntegrationSearch(page)
await page.getByRole('combobox').fill(query)
for (let press = 0; press < arrowDowns; press++) {
await page.keyboard.press('ArrowDown')
}
}
}
async function selectIntegrationMerge(page: Page) {
const flash = page.locator('.endpoint-flash, .endpoint-flash-static')
await page.addStyleTag({ content: '.endpoint-flash { animation: none !important; }' })
await openIntegrationSearch(page)
await page.getByRole('combobox').fill('keep_id')
await page.keyboard.press('Enter')
await flash.waitFor()
await flash.waitFor({ state: 'detached' })
await page.mouse.move(0, 0)
}
function integrationImagesState(
list: ApiMock | null,
overrides: Partial<VisualState> & { session?: ApiMock } = {},
@@ -8678,6 +8717,27 @@ export const visualStates: Record<string, Record<string, VisualState>> = {
approvedBy: 'fsylvain',
},
}),
'8a. Search: trigger focused': integrationState({ steps: focusIntegrationTrigger }),
'8b. Search: open, empty': integrationState({ steps: searchingIntegration('') }),
'8c. Search: typing, results': integrationState({ steps: searchingIntegration('media') }),
'8d. Search: keyboard-selected, status code': integrationState({
steps: searchingIntegration('404', 2),
}),
'8e. Search: body field match': integrationState({
steps: searchingIntegration('keep_id'),
}),
'8f. Search: session-only results': integrationState({
steps: searchingIntegration('login'),
}),
'8g. Search: no results': integrationState({ steps: searchingIntegration('xyz') }),
'8h. Search: after selecting an endpoint': integrationState({
steps: selectIntegrationMerge,
exception: {
maxPercent: 50,
reason: 'Expanded card body predates the search slice: Query parameters block and four-column field table differ from the board, and the real catalogue lists more media routes',
approvedBy: 'Florian Sylvain',
},
}),
'I1 · Many variants': integrationImagesState(integrationManyVariants),
'I2 · One variant': integrationImagesState(
integrationVariantsList(integrationVariantRows.slice(0, 1)),