Public Access
refactor: item 29 cleanup
F16 F17 F18 F19 F20 F21: import polling backs off and pauses in a hidden tab, one date format module, fake timers in the import tests, error codes instead of raw messages, one safe storage wrapper, dead code.
This commit is contained in:
1 parent
aa5832225d
commit
89d0b29698
31 files changed
+238
-81
No files matched your search
@@ -1,6 +1,6 @@
|
||||
// @vitest-environment jsdom
|
||||
import {afterEach, beforeEach, describe, expect, it, vi} from 'vitest';
|
||||
import {cleanup, fireEvent, render, screen, waitFor, within} from '@testing-library/react';
|
||||
import {act, cleanup, fireEvent, render, screen, waitFor, within} from '@testing-library/react';
|
||||
import {MemoryRouter, Route, Routes} from 'react-router-dom';
|
||||
import {toast} from 'sonner';
|
||||
import ImportPage from './ImportPage.jsx';
|
||||
@@ -49,13 +49,17 @@ function renderPage(routes, entry = '/import') {
|
||||
}
|
||||
|
||||
const posted = (method, path) => fetch.mock.calls.find(([url, init]) => init?.method === method && url.endsWith(path));
|
||||
const polls = (path) => fetch.mock.calls.filter(([url, init]) => !init?.method && url.endsWith(path)).length;
|
||||
const wait = (ms) => act(() => vi.advanceTimersByTimeAsync(ms));
|
||||
|
||||
beforeEach(() => {
|
||||
vi.useFakeTimers({shouldAdvanceTime: true});
|
||||
localStorage.setItem('tbp_session', '1');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cleanup();
|
||||
vi.useRealTimers();
|
||||
localStorage.clear();
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
@@ -138,7 +142,8 @@ describe('ImportPage', () => {
|
||||
});
|
||||
|
||||
expect(await screen.findByText('IMPORT.MATCHING')).toBeTruthy();
|
||||
expect(await screen.findByText('IMPORT.LINE: Hades', {}, {timeout: 3000})).toBeTruthy();
|
||||
await wait(2000);
|
||||
expect(await screen.findByText('IMPORT.LINE: Hades')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('preselects the favorite, checks only sure matches, and saves the checked lines', async () => {
|
||||
@@ -240,8 +245,10 @@ describe('ImportPage', () => {
|
||||
'GET /5': () => (++polls > 1 ? json(200, ready) : json(200, matching)),
|
||||
});
|
||||
|
||||
expect(await screen.findByText('IMPORT.LINE: Hades', {}, {timeout: 4000})).toBeTruthy();
|
||||
}, 10000);
|
||||
await screen.findByText('IMPORT.MATCHING');
|
||||
await wait(2000);
|
||||
expect(await screen.findByText('IMPORT.LINE: Hades')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('keeps polling after a 502 while Core restarts', async () => {
|
||||
let calls = 0;
|
||||
@@ -251,8 +258,51 @@ describe('ImportPage', () => {
|
||||
total: 4, matched: 1, chosen: 0, saved: 0, added: 0, ahead: null, attempts: 0})),
|
||||
}, '/import?id=8');
|
||||
|
||||
expect(await screen.findByText('IMPORT.MATCHING', {}, {timeout: 4000})).toBeTruthy();
|
||||
}, 10000);
|
||||
await waitFor(() => expect(polls('/8')).toBe(1));
|
||||
await wait(4000);
|
||||
expect(await screen.findByText('IMPORT.MATCHING')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('stops polling after repeated 500', async () => {
|
||||
renderPage({'GET ': json(200, {imports: []}), 'GET /8': json(500, null)}, '/import?id=8');
|
||||
|
||||
await waitFor(() => expect(polls('/8')).toBe(1));
|
||||
await wait(10 * 30_000);
|
||||
expect(screen.getByText('IMPORT.LOAD_FAILED')).toBeTruthy();
|
||||
expect(polls('/8')).toBe(10);
|
||||
await wait(60_000);
|
||||
expect(polls('/8')).toBe(10);
|
||||
});
|
||||
|
||||
it('doubles the delay after each failure', async () => {
|
||||
renderPage({'GET ': json(200, {imports: []}), 'GET /8': json(503, null)}, '/import?id=8');
|
||||
|
||||
await waitFor(() => expect(polls('/8')).toBe(1));
|
||||
await wait(3500);
|
||||
expect(polls('/8')).toBe(1);
|
||||
await wait(1000);
|
||||
expect(polls('/8')).toBe(2);
|
||||
await wait(7000);
|
||||
expect(polls('/8')).toBe(2);
|
||||
await wait(1500);
|
||||
expect(polls('/8')).toBe(3);
|
||||
});
|
||||
|
||||
it('pauses polling in a hidden tab and goes on when it is visible again', async () => {
|
||||
const hidden = vi.spyOn(document, 'hidden', 'get').mockReturnValue(true);
|
||||
renderPage({'GET ': json(200, {imports: []}), 'GET /9': json(200, {id: 9, source: 'TEXT', status: 'MATCHING',
|
||||
total: 2, matched: 1})}, '/import?id=9');
|
||||
|
||||
await screen.findByText('IMPORT.MATCHING');
|
||||
await wait(20_000);
|
||||
expect(polls('/9')).toBe(1);
|
||||
|
||||
hidden.mockReturnValue(false);
|
||||
await act(async () => document.dispatchEvent(new Event('visibilitychange')));
|
||||
expect(polls('/9')).toBe(2);
|
||||
await wait(2000);
|
||||
expect(polls('/9')).toBe(3);
|
||||
});
|
||||
});
|
||||
|
||||
describe('review findings', () => {
|
||||
@@ -271,7 +321,7 @@ describe('review findings', () => {
|
||||
</MemoryRouter>,
|
||||
);
|
||||
|
||||
expect(await screen.findByLabelText('IMPORT.LINE: Hades', {}, {timeout: 2000})).toBeTruthy();
|
||||
expect(await screen.findByLabelText('IMPORT.LINE: Hades')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user