diff --git a/tests/e2e/ai-vault-panel-search.spec.ts b/tests/e2e/ai-vault-panel-search.spec.ts index f0b272ab7ac..49c5790b1a9 100644 --- a/tests/e2e/ai-vault-panel-search.spec.ts +++ b/tests/e2e/ai-vault-panel-search.spec.ts @@ -202,41 +202,49 @@ test('panel consent enables real local transcript search; clearing restores hist await cdp.detach() }) -test('panel renders transport failure and unavailable reasons without a local fallback', async ({ - electronApp, - orcaPage -}, testInfo) => { - await orcaPage.evaluate(async () => { - await window.__store - ?.getState() - .updateSettingsOrThrow({ aiVaultSearch: { enabled: true, historyDays: null } }) - window.__store?.getState().setRightSidebarOpen(true) - window.__store?.getState().setRightSidebarTab('vault') - }) - await electronApp.evaluate(({ ipcMain }) => { - ipcMain.removeHandler('aiVault:searchSessions') - ipcMain.handle('aiVault:searchSessions', () => { - throw new Error('Synthetic transport failure') +// Title-only fallback persists for the host, so each reason needs a fresh panel. +for (const reason of ['disabled', 'not-ready', 'no-service'] as const) { + test(`panel retries transport failure and handles ${reason} search availability`, async ({ + electronApp, + orcaPage + }, testInfo) => { + await orcaPage.evaluate(async () => { + await window.__store + ?.getState() + .updateSettingsOrThrow({ aiVaultSearch: { enabled: true, historyDays: null } }) + window.__store?.getState().setRightSidebarOpen(true) + window.__store?.getState().setRightSidebarTab('vault') }) - }) - const input = orcaPage.getByRole('textbox', { name: 'Search sessions', exact: true }) - await input.fill('needle') - await expect( - orcaPage.getByText('Could not search this computer.', { exact: false }) - ).toBeVisible() - await orcaPage.screenshot({ path: testInfo.outputPath('failure.png') }) - for (const reason of ['disabled', 'not-ready', 'no-service'] as const) { + await electronApp.evaluate(({ ipcMain }) => { + ipcMain.removeHandler('aiVault:searchSessions') + ipcMain.handle('aiVault:searchSessions', () => { + throw new Error('Synthetic transport failure') + }) + }) + const input = orcaPage.getByRole('textbox', { name: 'Search sessions', exact: true }) + await input.fill('needle') + await expect( + orcaPage.getByText('Could not search this computer.', { exact: false }) + ).toBeVisible() + await orcaPage.screenshot({ path: testInfo.outputPath('failure.png') }) await electronApp.evaluate(({ ipcMain }, value) => { ipcMain.removeHandler('aiVault:searchSessions') ipcMain.handle('aiVault:searchSessions', () => ({ kind: 'unavailable', reason: value })) }, reason) - await orcaPage.getByRole('button', { name: 'Try again', exact: true }).click() + const retry = orcaPage.getByRole('button', { name: 'Try again', exact: true }) + await retry.click() const copy = - reason === 'disabled' - ? 'Search is disabled on this computer.' - : reason === 'not-ready' - ? 'The search index is not ready yet.' - : 'Search is unavailable on this computer.' + reason === 'not-ready' + ? 'The search index is not ready yet.' + : 'Full-text search is off on this computer, so only session titles are matched.' await expect(orcaPage.getByText(copy, { exact: false })).toBeVisible() - } -}) + if (reason === 'not-ready') { + await expect(retry).toBeVisible() + } else { + await expect(retry).toHaveCount(0) + await input.fill('another needle') + await expect(orcaPage.getByText(copy, { exact: false })).toBeVisible() + } + await orcaPage.screenshot({ path: testInfo.outputPath(`${reason}.png`) }) + }) +}