From e2eac9370452ce1bef95934a541b4d13fc8e13c0 Mon Sep 17 00:00:00 2001 From: Myasnikov Daniil Date: Thu, 27 Aug 2026 17:58:32 +0500 Subject: [PATCH] test(dashboard): wait out the tenant list before pinning the picker to non-admin pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The admin assertion looked for "No tenants found", which the picker only renders once an empty tenant list has arrived. With the list still in flight the picker says "Loading tenants…" instead, so the assertion passed whether or not the picker was there -- restoring the unconditional subtitle left the suite green. Give the provider a tenant list, wait out the loading branch, and match the picker's own label on a route that has no "Tenant" text of its own, plus the other direction: the picker still renders outside admin. Assisted-by: LLM Signed-off-by: Myasnikov Daniil --- .../apps/console/src/App.routing.test.tsx | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/packages/system/dashboard/images/console/apps/console/src/App.routing.test.tsx b/packages/system/dashboard/images/console/apps/console/src/App.routing.test.tsx index 08821dcb7..bffb82fd5 100644 --- a/packages/system/dashboard/images/console/apps/console/src/App.routing.test.tsx +++ b/packages/system/dashboard/images/console/apps/console/src/App.routing.test.tsx @@ -1,5 +1,5 @@ import { describe, it, expect, vi, beforeAll } from "vitest" -import { screen } from "@testing-library/react" +import { screen, waitFor } from "@testing-library/react" import { useLocation } from "react-router" import { K8sClient, @@ -15,14 +15,14 @@ function LocationProbe() { return
{pathname}
} -function makeClient(): K8sClient { +function makeClient(tenants: unknown[] = []): K8sClient { const client = new K8sClient() vi.spyOn(client, "list").mockImplementation(async (_g, _v, plural) => { return { apiVersion: "v1", kind: `${plural}List`, metadata: {}, - items: [], + items: plural === "tenantnamespaces" ? tenants : [], } as K8sList }) vi.spyOn(client, "getApiGroups").mockResolvedValue({ @@ -113,11 +113,31 @@ describe("runtime config", () => { }) describe("shell subtitle", () => { - it("hides the tenant picker in the admin portal", async () => { - const client = makeClient() - renderWithK8sProvider(, { client, initialRoute: "/admin/tenants" }) + // The picker only renders its "Tenant /" label once a tenant list has + // arrived; asserting against an empty list passes whether or not the picker + // is there, because its empty and loading branches say something else. + // The picker labels itself "Tenant"; the admin route is Modules rather than + // the tenant list, whose own "Tenant" create button would match too. + const TENANTS = ["tenant-acme", "tenant-globex"].map((name) => ({ + apiVersion: "core.cozystack.io/v1alpha1", + kind: "TenantNamespace", + metadata: { name, labels: {} }, + })) - expect(await screen.findByRole("heading", { name: "Tenants" })).toBeTruthy() - expect(screen.queryByText("No tenants found")).toBeNull() + it("hides the tenant picker in the admin portal", async () => { + const client = makeClient(TENANTS) + renderWithK8sProvider(, { client, initialRoute: "/admin/modules" }) + + // The picker's first render says "Loading tenants…"; wait that out, or the + // absence below passes only because the list had not arrived yet. + await waitFor(() => expect(screen.queryByText("Loading tenants…")).toBeNull()) + expect(screen.queryByText("Tenant", { exact: true })).toBeNull() + }) + + it("still shows the tenant picker outside the admin portal", async () => { + const client = makeClient(TENANTS) + renderWithK8sProvider(, { client, initialRoute: "/console" }) + + expect(await screen.findByText("Tenant", { exact: true })).toBeTruthy() }) })