Public: anyone can read this; the crew can change it.

A search that matches nothing anywhere says so once and offers Explore #8625

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/8484-a-search-that-matches-nothing-anywhere-s → main 1 commit fork

  • Merged. scout/8484-a-search-that-matches-nothing-anywhere-s was merged into main as 051c8d0.

Review

Sign in to review this change.
2 files changed +58 −13
src/web/pages/search.ts +29 −8
@@ -296,7 +296,18 @@ function section(
296296 >`}
297297 </h2>
298298 ${rows.length === 0
299 ? empty({ icon: emptyIcon, title: emptyText })
299 ? empty({
300 icon: emptyIcon,
301 title: emptyText,
302 ...(a.kind === "all"
303 ? {}
304 : {
305 action: btn("Search everything", {
306 href: searchHref(a, { kind: "all" }),
307 size: "sm",
308 }),
309 }),
310 })
300311 : listCard(rows)}
301312 ${after}
302313 ${when(
@@ -483,6 +494,9 @@ export async function searchPage(ctx: Ctx): Promise<Response> {
483494 </p>`,
484495 );
485496
497 const nothing =
498 a.kind === "all" &&
499 found.repos.length + found.issues.length + found.code.length === 0;
486500 const body = html`${pageHead(html`Results for “${a.query}”`)} ${form}
487501 <div class="bar mb">${chips}</div>
488502 ${liveToggle}
@@ -503,13 +517,20 @@ export async function searchPage(ctx: Ctx): Promise<Response> {
503517 shortly.
504518 </p>`,
505519 )}
506 ${WORDS
507 .filter(
508 ([kind]) => kind !== "all" && (a.kind === "all" || a.kind === kind),
509 )
510 .map((w) =>
511 section(a, w, ...rows[w[0]](), w[0] === "code" ? moreCode : null),
512 )}`;
520 ${nothing
521 ? empty({
522 icon: "search",
523 title: `Nothing matches “${a.query}”`,
524 note: "Search reads app and repository names and descriptions, issues, pull requests and the code you can see.",
525 action: btn("Explore", { href: "/explore", size: "sm" }),
526 })
527 : WORDS
528 .filter(
529 ([kind]) => kind !== "all" && (a.kind === "all" || a.kind === kind),
530 )
531 .map((w) =>
532 section(a, w, ...rows[w[0]](), w[0] === "code" ? moreCode : null),
533 )}`;
513534 const response = page({ ctx, title: `Search · ${a.query}`, body });
514535 notePhase(ctx.request, "render", performance.now() - rendering);
515536 return response;
test/search-more-code.test.ts +29 −5
@@ -85,11 +85,35 @@ test("a roomy budget shows every row and offers nothing more", async () => {
8585 expect(html).not.toContain("data-more-code");
8686 });
8787
88 test("a search with no hits draws the empty state, not .no-hits", async () => {
88 test("a search with no hits in any kind says so once and offers Explore", async () => {
8989 const html = await page(roomy, "q=qqqxnothingmatchesqqq");
9090 expect(html).not.toContain("no-hits");
91 expect(html).toContain("No app or repository matches");
92 expect(html).toContain("No issue or pull request matches");
93 expect(html).toContain("No line of code matches");
94 expect(html).toContain("empty-title");
91 expect(html).toContain("Nothing matches “qqqxnothingmatchesqqq”");
92 expect(html).toContain("code you can see");
93 expect(html).toContain('href="/explore"');
94 expect(html).not.toContain("No app or repository matches");
95 expect(html).not.toContain('id="repos"');
96 expect(html).not.toContain('id="code"');
97 });
98
99 test("the empty state escapes the query", async () => {
100 const html = await page(roomy, "q=" + encodeURIComponent("<b>qqzz</b>"));
101 expect(html).toContain("Nothing matches “&lt;b&gt;qqzz&lt;/b&gt;”");
102 expect(html).not.toContain("<b>qqzz</b>");
103 });
104
105 test("a narrowed kind with no match keeps its empty state and offers everything", async () => {
106 const html = await page(roomy, "q=qqqxnothingmatchesqqq&kind=code");
107 expect(html).toContain("No line of code matches");
108 expect(html).not.toContain("Nothing matches");
109 expect(html).toContain('href="/search?q=qqqxnothingmatchesqqq"');
110 expect(html).toContain("Search everything");
111 });
112
113 test("one result in any kind keeps the sections", async () => {
114 const html = await page(roomy, "q=zebrafish");
115 expect(html).not.toContain("Nothing matches");
116 expect(html).toContain('id="repos"');
117 expect(html).toContain("No app or repository matches");
118 expect(html).toContain('id="code"');
95119 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs