diff --git a/src/app/(protected)/completion-docs/_components/completion-templates-table.tsx b/src/app/(protected)/completion-docs/_components/completion-templates-table.tsx index 0a8bd5d7..5756ad64 100644 --- a/src/app/(protected)/completion-docs/_components/completion-templates-table.tsx +++ b/src/app/(protected)/completion-docs/_components/completion-templates-table.tsx @@ -23,6 +23,8 @@ const BODY_CELL_SX = { fontSize: 13, padding: "8px 12px" } as const; type CompletionTemplatesTableProps = { templates: CompletionTemplate[]; isLoading: boolean; + /** The load failed: the page shows the error, so there is no search result to explain. */ + hasError: boolean; canEdit: boolean; onView: (template: CompletionTemplate) => void; onEdit: (template: CompletionTemplate) => void; @@ -79,7 +81,7 @@ function TemplateRow({ canEdit, onView, onEdit, -}: Omit & { +}: Omit & { template: CompletionTemplate; }) { return ( @@ -120,6 +122,7 @@ function TemplateRow({ export function CompletionTemplatesTable({ templates, isLoading, + hasError, canEdit, onView, onEdit, @@ -143,7 +146,7 @@ export function CompletionTemplatesTable({ {isLoading && } - {!isLoading && templates.length === 0 && } + {!isLoading && !hasError && templates.length === 0 && } {templates.map((template) => ( setDialog({ template, mode: "view" })} onEdit={(template) => setDialog({ template, mode: "edit" })} diff --git a/src/test/app/(protected)/completion-docs/completion-docs-page.test.tsx b/src/test/app/(protected)/completion-docs/completion-docs-page.test.tsx index 3521c871..30f1070c 100644 --- a/src/test/app/(protected)/completion-docs/completion-docs-page.test.tsx +++ b/src/test/app/(protected)/completion-docs/completion-docs-page.test.tsx @@ -1,4 +1,4 @@ -import { screen, within } from "@testing-library/react"; +import { screen, waitFor, within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { beforeEach, describe, expect, it, vi } from "vitest"; import CompletionDocsPage from "@/app/(protected)/completion-docs/index"; @@ -88,6 +88,21 @@ describe("Completion Docs page", { timeout: 15_000 }, () => { expect(screen.queryByRole("row", { name: /Backflow Test Report/ })).not.toBeInTheDocument(); }); + it("reports a failed load without the empty-search message, including after a failed Retry", async () => { + api.apiGet.mockRejectedValue(new Error("Templates are unavailable")); + renderPage(); + + const retry = await screen.findByRole("button", { name: "Retry" }); + expect(screen.getByText("Templates are unavailable")).toBeInTheDocument(); + expect(screen.queryByText("No templates found")).not.toBeInTheDocument(); + + const callsBeforeRetry = api.apiGet.mock.calls.length; + await user.click(retry); + await waitFor(() => expect(api.apiGet.mock.calls.length).toBeGreaterThan(callsBeforeRetry)); + expect(await screen.findByText("Templates are unavailable")).toBeInTheDocument(); + expect(screen.queryByText("No templates found")).not.toBeInTheDocument(); + }); + it("opens a read-only detail panel from a row with every part of the template", async () => { renderPage(); const dialog = await openTemplate("Backflow Test Report");