From 088e8f4bf80b36b98f8c7a2b68bbffc7b4328219 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Fri, 8 May 2026 23:11:35 -0400 Subject: [PATCH] test(web/admin): align Lidarr bootstrap tests with file conventions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refactors the new describe block to use the existing setupFresh() helper pattern (mirrors setup() but with empty profile/folder lists so we can verify the test response is what populates the dropdowns), the lidarrSection() scoping helper (the cover-providers and SMTP panels also have "Save changes" buttons that match unscoped queries), and the correct mockQuery({ data: ... }) shape used elsewhere in the file. Drops the duplicate afterEach (the file already has a global one at line 131). No behavior change in the tests themselves — same three cases. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../admin/integrations/integrations.test.ts | 85 +++++++++---------- 1 file changed, 41 insertions(+), 44 deletions(-) diff --git a/web/src/routes/admin/integrations/integrations.test.ts b/web/src/routes/admin/integrations/integrations.test.ts index 30b33732..a89eb2be 100644 --- a/web/src/routes/admin/integrations/integrations.test.ts +++ b/web/src/routes/admin/integrations/integrations.test.ts @@ -522,29 +522,38 @@ describe('/admin/integrations — SMTP card', () => { }); describe('Lidarr first-time setup (Test-then-Save)', () => { - afterEach(() => { - vi.clearAllMocks(); - }); + // Fresh-install variant of setup() — the three list queries return + // empty arrays so we can verify the dropdowns get populated from the + // test response, not from the (empty) cached query data. + function setupFresh() { + (createLidarrConfigQuery as ReturnType).mockReturnValue( + mockQuery({ data: cfgUnset }) + ); + (createQualityProfilesQuery as ReturnType).mockReturnValue(mockQuery({ data: [] })); + (createMetadataProfilesQuery as ReturnType).mockReturnValue(mockQuery({ data: [] })); + (createRootFoldersQuery as ReturnType).mockReturnValue(mockQuery({ data: [] })); + (createCoverProvidersQuery as ReturnType).mockReturnValue( + mockQuery({ data: defaultCoverProviders }) + ); + (createSMTPConfigQuery as ReturnType).mockReturnValue( + mockQuery({ data: smtpUnset }) + ); + return render(IntegrationsPage); + } test('Save calls test first, fills defaults from response, then put-config', async () => { - vi.mocked(createLidarrConfigQuery).mockReturnValue(mockQuery(cfgUnset)); - vi.mocked(createQualityProfilesQuery).mockReturnValue(mockQuery([])); - vi.mocked(createMetadataProfilesQuery).mockReturnValue(mockQuery([])); - vi.mocked(createRootFoldersQuery).mockReturnValue(mockQuery([])); - vi.mocked(createCoverProvidersQuery).mockReturnValue(mockQuery(defaultCoverProviders)); - vi.mocked(createSMTPConfigQuery).mockReturnValue(mockQuery(smtpUnset)); - vi.mocked(testLidarrConnection).mockResolvedValue(testResponseOk); - vi.mocked(putLidarrConfig).mockResolvedValue(cfgConnected); + setupFresh(); + (testLidarrConnection as ReturnType).mockResolvedValueOnce(testResponseOk); + (putLidarrConfig as ReturnType).mockResolvedValueOnce(cfgConnected); - render(IntegrationsPage); - - await fireEvent.input(screen.getByLabelText(/Base URL/i), { + const section = lidarrSection(); + await fireEvent.input(within(section).getByLabelText(/Base URL/i), { target: { value: 'http://lidarr.local' } }); - await fireEvent.input(screen.getByLabelText(/API key/i), { + await fireEvent.input(within(section).getByLabelText(/API key/i), { target: { value: 'secret-key' } }); - await fireEvent.click(screen.getByRole('button', { name: /Save changes/i })); + await fireEvent.click(within(section).getByRole('button', { name: /Save changes/i })); await waitFor(() => { expect(testLidarrConnection).toHaveBeenCalledWith({ @@ -565,64 +574,52 @@ describe('Lidarr first-time setup (Test-then-Save)', () => { }); test('Save aborts when test fails and surfaces the error', async () => { - vi.mocked(createLidarrConfigQuery).mockReturnValue(mockQuery(cfgUnset)); - vi.mocked(createQualityProfilesQuery).mockReturnValue(mockQuery([])); - vi.mocked(createMetadataProfilesQuery).mockReturnValue(mockQuery([])); - vi.mocked(createRootFoldersQuery).mockReturnValue(mockQuery([])); - vi.mocked(createCoverProvidersQuery).mockReturnValue(mockQuery(defaultCoverProviders)); - vi.mocked(createSMTPConfigQuery).mockReturnValue(mockQuery(smtpUnset)); - vi.mocked(testLidarrConnection).mockResolvedValue({ + setupFresh(); + (testLidarrConnection as ReturnType).mockResolvedValueOnce({ ok: false, error: 'lidarr_unreachable' }); - render(IntegrationsPage); - - await fireEvent.input(screen.getByLabelText(/Base URL/i), { + const section = lidarrSection(); + await fireEvent.input(within(section).getByLabelText(/Base URL/i), { target: { value: 'http://wrong.local' } }); - await fireEvent.input(screen.getByLabelText(/API key/i), { + await fireEvent.input(within(section).getByLabelText(/API key/i), { target: { value: 'k' } }); - await fireEvent.click(screen.getByRole('button', { name: /Save changes/i })); + await fireEvent.click(within(section).getByRole('button', { name: /Save changes/i })); await waitFor(() => { expect(testLidarrConnection).toHaveBeenCalled(); }); expect(putLidarrConfig).not.toHaveBeenCalled(); await waitFor(() => { - expect(screen.getByText(/Save failed — lidarr_unreachable/i)).toBeInTheDocument(); + expect(within(lidarrSection()).getByText(/save failed — lidarr_unreachable/i)).toBeInTheDocument(); }); }); test('Save preserves operator-picked defaults over auto-defaults', async () => { - vi.mocked(createLidarrConfigQuery).mockReturnValue(mockQuery(cfgUnset)); - vi.mocked(createQualityProfilesQuery).mockReturnValue(mockQuery([])); - vi.mocked(createMetadataProfilesQuery).mockReturnValue(mockQuery([])); - vi.mocked(createRootFoldersQuery).mockReturnValue(mockQuery([])); - vi.mocked(createCoverProvidersQuery).mockReturnValue(mockQuery(defaultCoverProviders)); - vi.mocked(createSMTPConfigQuery).mockReturnValue(mockQuery(smtpUnset)); - vi.mocked(testLidarrConnection).mockResolvedValue(testResponseOk); - vi.mocked(putLidarrConfig).mockResolvedValue(cfgConnected); + setupFresh(); + (testLidarrConnection as ReturnType).mockResolvedValue(testResponseOk); + (putLidarrConfig as ReturnType).mockResolvedValueOnce(cfgConnected); - render(IntegrationsPage); - - await fireEvent.input(screen.getByLabelText(/Base URL/i), { + const section = lidarrSection(); + await fireEvent.input(within(section).getByLabelText(/Base URL/i), { target: { value: 'http://lidarr.local' } }); - await fireEvent.input(screen.getByLabelText(/API key/i), { + await fireEvent.input(within(section).getByLabelText(/API key/i), { target: { value: 'secret-key' } }); // Click Test first to populate the dropdowns, then change the // quality profile selection before clicking Save. - await fireEvent.click(screen.getByRole('button', { name: /Test connection/i })); + await fireEvent.click(within(section).getByRole('button', { name: /Test connection/i })); await waitFor(() => { expect(testLidarrConnection).toHaveBeenCalledTimes(1); }); - const qualitySelect = screen.getByLabelText(/Default quality profile/i); + const qualitySelect = within(section).getByLabelText(/Default quality profile/i); await fireEvent.change(qualitySelect, { target: { value: '2' } }); - await fireEvent.click(screen.getByRole('button', { name: /Save changes/i })); + await fireEvent.click(within(section).getByRole('button', { name: /Save changes/i })); await waitFor(() => { expect(putLidarrConfig).toHaveBeenCalledWith(