mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-26 19:01:39 -04:00
Six helpers turned a non-OK response into an empty value, so their
consumers rendered a server error as "nothing here":
* getConfigBackups -> {dates: []}: "No backups available for this
config." A thrown request also left "Loading backups..." forever.
* getInventoryBackups -> []: "No backups yet."
* getDownloaders -> {downloaders: []} on a throw, the error body on a
non-OK response (which then crashed the .map): the RSS form's
Downloader select sat empty.
* searchMap -> {results: []}: "No map locations found".
* getMapSearchStatus -> {indexed: [], missing: []}: "No maps are
installed".
* flasherSearch -> [null, null], then `|| []`: "No .bin firmware
found".
Invariants now enforced and tested:
* On a non-OK response each helper returns undefined; an empty value
only ever comes from the server.
* Each consumer shows an error for a failed or thrown fetch and keeps
its "none" message for a confirmed empty result. The Downloader
select is disabled and says it is loading or could not fetch. A
failed map status is unknown, never "no maps are installed".
* The map search tab loads from the first render, and a query shorter
than the two characters the request needs now says so instead of
"No map locations found".
Archive browsers and recent tags are left as they are: a failed fetch
there hides an optional picker or suggestion list without claiming
anything.
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
43 lines
1.6 KiB
JavaScript
43 lines
1.6 KiB
JavaScript
import React from 'react';
|
|
import {act, render, screen} from '../test-utils';
|
|
import {createTestForm} from '../test-utils';
|
|
import {DownloaderSelector} from './Download';
|
|
import {getDownloaders} from '../api';
|
|
|
|
// The RSS form's Downloader select is filled from the API. Until the list arrives, or if it could
|
|
// not be fetched, the select must say so rather than sit empty as though there were no downloaders.
|
|
|
|
jest.mock('../api', () => ({
|
|
...jest.requireActual('../api'),
|
|
getDownloaders: jest.fn(),
|
|
}));
|
|
|
|
const makeForm = () => createTestForm({}, {
|
|
overrides: {getSelectionProps: () => [{value: null, onChange: jest.fn(), disabled: false, error: null}]},
|
|
});
|
|
|
|
beforeEach(() => getDownloaders.mockReset());
|
|
|
|
test('pending: the select says it is loading and is disabled', () => {
|
|
getDownloaders.mockReturnValue(new Promise(() => {
|
|
}));
|
|
render(<DownloaderSelector form={makeForm()}/>);
|
|
const input = screen.getByPlaceholderText('Loading downloaders…');
|
|
expect(input).toBeDisabled();
|
|
});
|
|
|
|
test('failed: the select says the downloaders could not be fetched', async () => {
|
|
getDownloaders.mockResolvedValue(undefined);
|
|
render(<DownloaderSelector form={makeForm()}/>);
|
|
await act(async () => {
|
|
});
|
|
expect(screen.getByPlaceholderText('Could not fetch downloaders')).toBeDisabled();
|
|
});
|
|
|
|
test('loaded: the select offers the downloaders', async () => {
|
|
getDownloaders.mockResolvedValue({downloaders: [{name: 'video', pretty_name: 'Videos'}]});
|
|
render(<DownloaderSelector form={makeForm()}/>);
|
|
await act(async () => {
|
|
});
|
|
expect(screen.getByPlaceholderText('Select a downloader')).toBeEnabled();
|
|
});
|