From 4619e546bf60ceb77e272ef1c290eae6e488c0d4 Mon Sep 17 00:00:00 2001 From: XiaoSeS <87064762+XiaoSeS@users.noreply.github.com> Date: Wed, 15 Apr 2026 16:58:21 +0800 Subject: [PATCH] fix(search): show default discovery list on empty query (#312) --- web/e2e/search-page-full.spec.ts | 7 ++-- web/src/pages/search.test.tsx | 59 +++++++++++++++++++++++++++++++- web/src/pages/search.tsx | 16 ++++----- 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/web/e2e/search-page-full.spec.ts b/web/e2e/search-page-full.spec.ts index f5775bfb..be14db8f 100644 --- a/web/e2e/search-page-full.spec.ts +++ b/web/e2e/search-page-full.spec.ts @@ -39,12 +39,11 @@ test.describe('Search Input (Real API)', () => { await expect(getSearchCards(page).first()).toBeVisible({ timeout: 10_000 }) }) - // TC_SEARCH_INPUT_003 P0 - empty search guidance - test('TC_SEARCH_INPUT_003: empty search shows keyword guidance instead of a default list', async ({ page }) => { + // TC_SEARCH_INPUT_003 P0 - empty search shows the default discovery list + test('TC_SEARCH_INPUT_003: empty search shows the default discovery list', async ({ page }) => { await page.goto(searchUrl('')) await expect(page).toHaveURL(/\/search/) - await expect(page.getByRole('heading', { name: 'No results found' })).toBeVisible() - await expect(page.getByText('Please enter a search keyword')).toBeVisible() + await expect(getSearchCards(page).first()).toBeVisible({ timeout: 10_000 }) }) // TC_SEARCH_INPUT_004 P0 - Enter key triggers search diff --git a/web/src/pages/search.test.tsx b/web/src/pages/search.test.tsx index 726b5553..a921d5d3 100644 --- a/web/src/pages/search.test.tsx +++ b/web/src/pages/search.test.tsx @@ -46,7 +46,13 @@ vi.mock('@/shared/components/skeleton-loader', () => ({ })) vi.mock('@/shared/components/empty-state', () => ({ - EmptyState: () =>
empty-state
, + EmptyState: ({ title, description }: { title: string; description?: string }) => ( +
+ empty-state + {title} + {description ? {description} : null} +
+ ), })) vi.mock('@/shared/components/pagination', () => ({ @@ -202,4 +208,55 @@ describe('SearchPage', () => { }, }) }) + + it('renders the default skill list when the empty query still returns items', () => { + useSearchMock.mockReturnValue({ + q: '', + label: '', + sort: 'newest', + page: 0, + starredOnly: false, + }) + useSearchSkillsMock.mockReturnValue({ + data: { + items: [{ id: 1, displayName: 'Demo Skill', summary: 'summary', namespace: 'global', slug: 'demo', downloadCount: 1, starCount: 1, ratingCount: 0, updatedAt: '2026-03-20T00:00:00Z', canSubmitPromotion: false }], + total: 1, + page: 0, + size: 12, + }, + isLoading: false, + isFetching: false, + }) + + const html = renderToStaticMarkup() + + expect(html).toContain('skill-card') + expect(html).not.toContain('empty-state') + }) + + it('shows a generic empty state when the default discovery list is empty', () => { + useSearchMock.mockReturnValue({ + q: '', + label: '', + sort: 'newest', + page: 0, + starredOnly: false, + }) + useSearchSkillsMock.mockReturnValue({ + data: { + items: [], + total: 0, + page: 0, + size: 12, + }, + isLoading: false, + isFetching: false, + }) + + const html = renderToStaticMarkup() + + expect(html).toContain('empty-state') + expect(html).toContain('search.noResults') + expect(html).not.toContain('search.enterKeyword') + }) }) diff --git a/web/src/pages/search.tsx b/web/src/pages/search.tsx index 6258ca19..58c421db 100644 --- a/web/src/pages/search.tsx +++ b/web/src/pages/search.tsx @@ -125,8 +125,6 @@ export function SearchPage() { isLoading: isLoadingStarred, isFetching: isFetchingStarred, } = useMyStars(starredOnly && isAuthenticated) - const shouldShowGuidance = !starredOnly && !q && !selectedLabel - useEffect(() => { // Debounce URL updates while the user is typing so query state stays shareable without // triggering a navigation on every keystroke. @@ -202,10 +200,10 @@ export function SearchPage() { : data ? Math.ceil(data.total / data.size) : 0 - const displayItems = shouldShowGuidance ? [] : (starredOnly ? starredPageItems : (data?.items ?? [])) - const isPageLoading = shouldShowGuidance ? false : (starredOnly ? isLoadingStarred : isLoading) - const isUpdatingResults = shouldShowGuidance ? false : (starredOnly ? isFetchingStarred && !isLoadingStarred : isFetching && !isLoading) - const resultCount = shouldShowGuidance ? 0 : (starredOnly ? filteredStarredSkills.length : (data?.total ?? 0)) + const displayItems = starredOnly ? starredPageItems : (data?.items ?? []) + const isPageLoading = starredOnly ? isLoadingStarred : isLoading + const isUpdatingResults = starredOnly ? isFetchingStarred && !isLoadingStarred : isFetching && !isLoading + const resultCount = starredOnly ? filteredStarredSkills.length : (data?.total ?? 0) return (
@@ -313,11 +311,9 @@ export function SearchPage() { )}