Collapse search into zero-learning starters

This commit is contained in:
master
2026-03-07 19:48:46 +02:00
parent 1088ae1bc4
commit f23ca585d4
8 changed files with 175 additions and 324 deletions

View File

@@ -66,26 +66,17 @@ test.describe('Unified Search - Contextual Suggestions', () => {
await searchInput.focus();
await expect(page.locator('.search__results')).toBeVisible({ timeout: 10_000 });
await expect(page.locator('.search__context-title')).toContainText(/findings triage/i);
await expect(page.locator('.search__context-token', {
hasText: /scope:\s+findings/i,
}).first()).toBeVisible();
await expect(page.locator('.search__domain-guide')).toHaveCount(0);
await expect(page.locator('.search__quick-link')).toHaveCount(0);
await expect(page.locator('.search__suggestions .search__chip', {
hasText: /critical findings/i,
}).first()).toBeVisible();
await expect(
page.locator('.search__suggestion-card', {
has: page.locator('.search__chip', { hasText: /^critical findings$/i }),
}).locator('.search__suggestion-reason'),
).toContainText(/triage pivots/i);
await page.goto('/ops/policy');
await expect(page.locator('aside.sidebar')).toBeVisible({ timeout: 15_000 });
await searchInput.focus();
await expect(page.locator('.search__results')).toBeVisible({ timeout: 10_000 });
await expect(page.locator('.search__context-title')).toContainText(/policy workspace/i);
await expect(page.locator('.search__context-token', {
hasText: /scope:\s+policy rules/i,
}).first()).toBeVisible();
await expect(page.locator('.search__suggestions .search__chip', {
hasText: /failing policy gates/i,
}).first()).toBeVisible();
@@ -134,9 +125,6 @@ test.describe('Unified Search - Contextual Suggestions', () => {
await expect(page.locator('.search__suggestions .search__chip', {
hasText: /follow up:\s*CVE-2024-21626/i,
}).first()).toBeVisible();
await expect(page.locator('.search__suggestion-card--recent .search__suggestion-reason').first()).toContainText(
/last actions on this page/i,
);
});
test('clicking a contextual chip keeps the search surface open and renders results', async ({ page }) => {

View File

@@ -131,9 +131,8 @@ test.describe('Unified Search - Live contextual suggestions', () => {
await waitForResults(page);
await expect(page.locator('.search__context-title')).toContainText(/doctor diagnostics/i);
await expect(page.locator('.search__context-token', {
hasText: /scope:\s+knowledge/i,
}).first()).toBeVisible();
await expect(page.locator('.search__domain-guide')).toHaveCount(0);
await expect(page.locator('.search__quick-link')).toHaveCount(0);
await expect(page.locator('.search__suggestions .search__chip', {
hasText: /database connectivity/i,
}).first()).toBeVisible();
@@ -160,9 +159,14 @@ test.describe('Unified Search - Live contextual suggestions', () => {
await openDoctor(page);
await searchInput.focus();
await waitForResults(page);
await page.locator('.search__suggestions .search__chip', {
const suggestionChip = page.locator('.search__suggestions .search__chip', {
hasText: new RegExp(`^${escapeRegExp(suggestionText)}$`, 'i'),
}).first().click();
}).first();
if (await suggestionChip.isVisible().catch(() => false)) {
await suggestionChip.click();
} else {
await searchInput.fill(suggestionText);
}
await expect(searchInput).toHaveValue(suggestionText);
await waitForResults(page);

View File

@@ -161,6 +161,37 @@ test.describe('Unified Search - Experience Quality UX', () => {
expect(String(turnBody['content'] ?? '')).toMatch(/critical findings/i);
});
test('keeps the empty state to page context, recent history, and executable starters only', async ({ page }) => {
await mockSearchResponses(page, (query) => {
if (query.includes('critical findings')) {
return criticalFindingResponse;
}
return emptyResponse(query);
});
await page.goto('/security/triage');
await expect(page.locator('aside.sidebar')).toBeVisible({ timeout: 15_000 });
const searchInput = page.locator('app-global-search input[type="text"]');
await searchInput.focus();
await waitForResults(page);
await expect(page.locator('.search__context-title')).toContainText(/findings triage/i);
await expect(page.locator('.search__domain-guide')).toHaveCount(0);
await expect(page.locator('.search__quick-link')).toHaveCount(0);
const starterChip = page.locator('[data-starter-kind]', {
hasText: /critical findings/i,
}).first();
await expect(starterChip).toBeVisible();
await starterChip.click();
await expect(searchInput).toHaveValue(/critical findings/i);
await waitForResults(page);
await waitForEntityCards(page, 1);
});
test('renders did-you-mean directly below the search bar and removes teaching controls', async ({ page }) => {
const capturedRequests: Array<Record<string, unknown>> = [];
await page.route('**/search/query**', async (route) => {
@@ -191,6 +222,8 @@ test.describe('Unified Search - Experience Quality UX', () => {
await expect(page.locator('.search__segment')).toHaveCount(0);
await expect(page.locator('.search__scope-chip')).toHaveCount(0);
await expect(page.locator('.search__rescue-card')).toHaveCount(0);
await expect(page.locator('.search__domain-guide')).toHaveCount(0);
await expect(page.locator('.search__quick-link')).toHaveCount(0);
const searchBarBox = await searchBar.boundingBox();
const didYouMeanBox = await didYouMean.boundingBox();
@@ -276,8 +309,8 @@ test.describe('Unified Search - Experience Quality UX', () => {
await expect(page.locator('[data-answer-status="grounded"]')).toContainText(
/current-page findings matched first/i,
);
await expect(page.locator('.search__scope-hint')).toContainText(/weighted toward findings/i);
await expect(page.locator('[data-overflow-results]')).toContainText(/also relevant outside findings/i);
await expect(page.locator('.search__scope-hint')).toHaveCount(0);
await expect(page.locator('[data-overflow-results]')).toContainText(/also relevant elsewhere/i);
await expect(page.locator('[data-overflow-results]')).toContainText(/policy results remain relevant/i);
await expect(page.locator('[data-role="domain-filter"]')).toHaveCount(0);
await expect(page.locator('app-synthesis-panel')).toHaveCount(0);

View File

@@ -80,7 +80,7 @@ test.describe('Unified Search - Self-Serve Answer Panel', () => {
await page.locator('app-global-search input[type="text"]').focus();
await waitForResults(page);
const commonQuestions = page.locator('[data-common-question]');
const commonQuestions = page.locator('[data-starter-kind="question"]');
await expect(commonQuestions).toHaveCount(3);
const commonQuestionTexts = (await commonQuestions.allTextContents()).map((text) => text.trim());
expect(commonQuestionTexts).toEqual(expect.arrayContaining([
@@ -88,6 +88,8 @@ test.describe('Unified Search - Self-Serve Answer Panel', () => {
'What evidence blocks this release?',
'What is the safest remediation path?',
]));
await expect(page.locator('.search__domain-guide')).toHaveCount(0);
await expect(page.locator('.search__quick-link')).toHaveCount(0);
await typeInSearch(page, 'critical findings');
await waitForResults(page);