test(web/admin): align Lidarr bootstrap tests with file conventions
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) <noreply@anthropic.com>
This commit is contained in:
@@ -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<typeof vi.fn>).mockReturnValue(
|
||||
mockQuery({ data: cfgUnset })
|
||||
);
|
||||
(createQualityProfilesQuery as ReturnType<typeof vi.fn>).mockReturnValue(mockQuery({ data: [] }));
|
||||
(createMetadataProfilesQuery as ReturnType<typeof vi.fn>).mockReturnValue(mockQuery({ data: [] }));
|
||||
(createRootFoldersQuery as ReturnType<typeof vi.fn>).mockReturnValue(mockQuery({ data: [] }));
|
||||
(createCoverProvidersQuery as ReturnType<typeof vi.fn>).mockReturnValue(
|
||||
mockQuery({ data: defaultCoverProviders })
|
||||
);
|
||||
(createSMTPConfigQuery as ReturnType<typeof vi.fn>).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<typeof vi.fn>).mockResolvedValueOnce(testResponseOk);
|
||||
(putLidarrConfig as ReturnType<typeof vi.fn>).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<typeof vi.fn>).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<typeof vi.fn>).mockResolvedValue(testResponseOk);
|
||||
(putLidarrConfig as ReturnType<typeof vi.fn>).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(
|
||||
|
||||
Reference in New Issue
Block a user