Skip to content

ui: Add tests for silences datasource#5128

Open
sysadmind wants to merge 2 commits intoprometheus:mainfrom
sysadmind:uiv2-silence-tests
Open

ui: Add tests for silences datasource#5128
sysadmind wants to merge 2 commits intoprometheus:mainfrom
sysadmind:uiv2-silence-tests

Conversation

@sysadmind
Copy link
Copy Markdown
Contributor

@sysadmind sysadmind commented Mar 28, 2026

Adds tests for silences data component for list of silences and query by ID. It covers the typical happy path and a few that result in an error.

Pull Request Checklist

Please check all the applicable boxes.

Which user-facing changes does this PR introduce?

NONE

Summary by CodeRabbit

  • Tests
    • Added comprehensive tests for data-fetching hooks covering successful responses (including empty results), API-level errors, and network failures; verifies correct endpoint usage for distinct IDs and expected caching/distinct-query behavior; includes error-capture checks to ensure error messages propagate as expected.

Adds tests for silences data component for list of silences and query by ID. It covers the typical happy path and a few that result in an error.

Signed-off-by: Joe Adams <github@joeadams.io>
@sysadmind sysadmind requested a review from a team as a code owner March 28, 2026 18:44
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cdf56353-1ac2-42aa-9e01-922d076937c3

📥 Commits

Reviewing files that changed from the base of the PR and between 60ece37 and 613b3f3.

📒 Files selected for processing (1)
  • ui/mantine-ui/src/data/silences.test.tsx
✅ Files skipped from review due to trivial changes (1)
  • ui/mantine-ui/src/data/silences.test.tsx

📝 Walkthrough

Walkthrough

Adds a new Vitest/React Testing Library test suite that exercises useSilences and useSilence React Query hooks with mocked fetch, covering success, empty results, API errors, network failures, endpoint correctness, and caching behavior via separate query instances.

Changes

Cohort / File(s) Summary
React Query Hooks Test Suite
ui/mantine-ui/src/data/silences.test.tsx
New test file (~331 lines) introducing tests for useSilences and useSilence. Sets up a QueryClient with retries disabled, renders hooks inside QueryClientProvider, mocks global.fetch for success/empty/error/network cases, adds a local ErrorBoundary to capture Suspense errors, asserts response shapes and endpoint calls, and verifies caching/ID isolation.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hopped through mocks and queries deep,

Fetches danced and silences sleep.
ErrorBound held what might have flown,
Tests now hum in quiet tone.
— a rabbit's tiny testing thrum 🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title 'ui: Add tests for silences datasource' directly summarizes the main change: adding test coverage for the silences data component.
Description check ✅ Passed The PR description covers the main objective (adding tests for silences), specifies the scope (happy path and error cases), includes required checklist items (signed-off commits, best practices), and properly marks release notes as NONE.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
ui/mantine-ui/src/data/silences.test.tsx (2)

77-80: Wrap test wrappers with Suspense for proper suspense-based query handling.

The test uses useSuspenseAPIQuery, which is implemented via useSuspenseQuery and suspends during loading. Currently, wrappers at lines 77–80, 150–153, 176–178, and 264–266 provide QueryClientProvider and/or ErrorBoundary, but no Suspense boundary. This can cause incomplete test behavior since Suspense is required to properly handle suspension states thrown by useSuspenseQuery.

🔧 Suggested wrapper adjustment
-import React, { ReactNode } from 'react';
+import React, { ReactNode, Suspense } from 'react';
@@
   const getWrapper = (client: QueryClient) => {
     return ({ children }: { children: ReactNode }) => (
-      <QueryClientProvider client={client}>{children}</QueryClientProvider>
+      <QueryClientProvider client={client}>
+        <Suspense fallback={null}>{children}</Suspense>
+      </QueryClientProvider>
     );
   };

Apply the same Suspense wrapping to the error wrappers at lines 150–153, 176–178, and 264–266.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/mantine-ui/src/data/silences.test.tsx` around lines 77 - 80, The test
wrappers for suspense-based queries (e.g., getWrapper) are missing a Suspense
boundary which breaks useSuspenseAPIQuery/useSuspenseQuery behavior; update the
wrapper factories (the getWrapper function and the ErrorBoundary-wrapping
factories used around tests) to wrap QueryClientProvider (and ErrorBoundary
where used) inside a React.Suspense with a fallback (e.g., null) so suspended
renders are handled properly; locate getWrapper and the other wrapper functions
referenced in tests and nest their returned JSX inside <Suspense
fallback={null}> ... </Suspense> while keeping QueryClientProvider and
ErrorBoundary in place.

66-75: Add global cleanup to prevent fetch mock leakage between tests.

The afterEach hook only clears mock call history with vi.clearAllMocks() but does not restore stubbed globals. Since lines 92, 121, 147, 172, 199, 230, 260, and 301 directly reassign global.fetch, stub implementations persist across tests and create cross-test coupling.

Use vi.restoreAllMocks() in beforeEach and vi.unstubAllGlobals() in afterEach, and replace direct assignments with vi.stubGlobal('fetch', mockFetch).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/mantine-ui/src/data/silences.test.tsx` around lines 66 - 75, Test teardown
is leaking stubbed globals because tests directly reassign global.fetch and only
call vi.clearAllMocks(); update the test setup to call vi.restoreAllMocks() in
beforeEach and vi.unstubAllGlobals() in afterEach, and change any direct
assignments to global.fetch in the tests to use vi.stubGlobal('fetch',
mockFetch) so each test gets an isolated stub that is properly restored; look
for beforeEach, afterEach, global.fetch assignments, and replace them with
vi.restoreAllMocks(), vi.unstubAllGlobals(), and vi.stubGlobal calls
respectively.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ui/mantine-ui/src/data/silences.test.tsx`:
- Around line 282-315: The test is falsely passing because it creates two
QueryClient instances; to actually validate cache key isolation, use a single
QueryClient for both renderHook calls so they share cache. Update the test that
uses useSilence, QueryClient, renderHook and getWrapper to create one client
(const client = new QueryClient(...)), renderHook(() => useSilence(id1), {
wrapper: getWrapper(client) }) and renderHook(() => useSilence(id2), { wrapper:
getWrapper(client) }), then assert mockFetch was called twice; additionally add
(or modify) an assertion that rendering useSilence(id1) twice with the same
client results in only one fetch call to ensure same-ID cache hits.

---

Nitpick comments:
In `@ui/mantine-ui/src/data/silences.test.tsx`:
- Around line 77-80: The test wrappers for suspense-based queries (e.g.,
getWrapper) are missing a Suspense boundary which breaks
useSuspenseAPIQuery/useSuspenseQuery behavior; update the wrapper factories (the
getWrapper function and the ErrorBoundary-wrapping factories used around tests)
to wrap QueryClientProvider (and ErrorBoundary where used) inside a
React.Suspense with a fallback (e.g., null) so suspended renders are handled
properly; locate getWrapper and the other wrapper functions referenced in tests
and nest their returned JSX inside <Suspense fallback={null}> ... </Suspense>
while keeping QueryClientProvider and ErrorBoundary in place.
- Around line 66-75: Test teardown is leaking stubbed globals because tests
directly reassign global.fetch and only call vi.clearAllMocks(); update the test
setup to call vi.restoreAllMocks() in beforeEach and vi.unstubAllGlobals() in
afterEach, and change any direct assignments to global.fetch in the tests to use
vi.stubGlobal('fetch', mockFetch) so each test gets an isolated stub that is
properly restored; look for beforeEach, afterEach, global.fetch assignments, and
replace them with vi.restoreAllMocks(), vi.unstubAllGlobals(), and vi.stubGlobal
calls respectively.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4a2407b9-e6eb-4966-9d34-8329109cd49d

📥 Commits

Reviewing files that changed from the base of the PR and between 4aac704 and 60ece37.

📒 Files selected for processing (1)
  • ui/mantine-ui/src/data/silences.test.tsx

Signed-off-by: Joe Adams <github@joeadams.io>
@SoloJacobs
Copy link
Copy Markdown
Contributor

I have deep scars from mocking, and we really prefer seeing tests running against a real server. Maybe like so:

  let queryClient: QueryClient;
  let respond: (req: IncomingMessage, res: ServerResponse) => void;

  const server = createServer((req, res) => respond(req, res));

  beforeAll(async () => {
    await new Promise<void>((resolve) => server.listen(0, resolve));
    const { port } = server.address() as AddressInfo;
    vi.stubEnv('VITE_API_PREFIX', `http://localhost:${port}`);
  });

  afterAll(async () => {
    vi.unstubAllEnvs();
    await new Promise<void>((resolve) => server.close(resolve));
  });

  beforeEach(() => {
    queryClient = new QueryClient({
      defaultOptions: { queries: { retry: false } },
    });
    respond = (_, res) => { res.writeHead(500); res.end(); };
  });

  afterEach(() => {
    queryClient.clear();
  });

It's probably not ideal code, since I'm a complete typescript novice and have to trust the AI. But it does run locally: SoloJacobs@541a729
The main thing I hoping for is that we eventually will have some proper playwright integration tests. That is out of scope here, but we should at least make it simple to move the tests here to that framework, if we so choose.

Another thing: It appears we are mostly testing api.ts. Should first focus on testing that functionality?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants