|
|
|
|
@@ -268,13 +268,12 @@ describe('FlyerUploader', () => {
|
|
|
|
|
|
|
|
|
|
// We need at least one 'active' response to establish a timeout loop so we have something to clear
|
|
|
|
|
// The second call should be a rejection, as this is how getJobStatus signals a failure.
|
|
|
|
|
mockedAiApiClient.getJobStatus.mockImplementation(async () => {
|
|
|
|
|
// Fail on the second call by checking the number of times the mock has been invoked.
|
|
|
|
|
if (mockedAiApiClient.getJobStatus.mock.calls.length > 1) {
|
|
|
|
|
throw new aiApiClientModule.JobFailedError('Fatal Error', 'UNKNOWN_ERROR');
|
|
|
|
|
}
|
|
|
|
|
return { state: 'active', progress: { message: 'Working...' } } as aiApiClientModule.JobStatus;
|
|
|
|
|
});
|
|
|
|
|
mockedAiApiClient.getJobStatus
|
|
|
|
|
.mockResolvedValueOnce({
|
|
|
|
|
state: 'active',
|
|
|
|
|
progress: { message: 'Working...' },
|
|
|
|
|
} as aiApiClientModule.JobStatus)
|
|
|
|
|
.mockRejectedValueOnce(new aiApiClientModule.JobFailedError('Fatal Error', 'UNKNOWN_ERROR'));
|
|
|
|
|
|
|
|
|
|
renderComponent();
|
|
|
|
|
const file = new File(['content'], 'flyer.pdf', { type: 'application/pdf' });
|
|
|
|
|
@@ -289,10 +288,10 @@ describe('FlyerUploader', () => {
|
|
|
|
|
await waitFor(() => expect(screen.getByText(/Polling failed: Fatal Error/i)).toBeInTheDocument(), { timeout: 4000 });
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should clear the polling timeout when the component unmounts', async () => {
|
|
|
|
|
const clearTimeoutSpy = vi.spyOn(global, 'clearTimeout');
|
|
|
|
|
console.log('--- [TEST LOG] ---: 1. Setting up mocks for unmount timeout clearance.');
|
|
|
|
|
it('should stop polling for job status when the component unmounts', async () => {
|
|
|
|
|
console.log('--- [TEST LOG] ---: 1. Setting up mocks for unmount polling stop.');
|
|
|
|
|
mockedAiApiClient.uploadAndProcessFlyer.mockResolvedValue({ jobId: 'job-unmount' });
|
|
|
|
|
// Mock getJobStatus to always return 'active' to keep polling
|
|
|
|
|
mockedAiApiClient.getJobStatus.mockResolvedValue({
|
|
|
|
|
state: 'active',
|
|
|
|
|
progress: { message: 'Polling...' },
|
|
|
|
|
@@ -304,18 +303,29 @@ describe('FlyerUploader', () => {
|
|
|
|
|
|
|
|
|
|
fireEvent.change(input, { target: { files: [file] } });
|
|
|
|
|
|
|
|
|
|
// Wait for the first poll to complete and the UI to show the polling state
|
|
|
|
|
// Wait for the first poll to complete and UI to update
|
|
|
|
|
await screen.findByText('Polling...');
|
|
|
|
|
|
|
|
|
|
// Now that we are in a polling state (and a timeout is set), unmount the component
|
|
|
|
|
console.log('--- [TEST LOG] ---: 2. Unmounting component to trigger cleanup effect.');
|
|
|
|
|
// Wait for exactly one call to be sure polling has started.
|
|
|
|
|
await waitFor(() => {
|
|
|
|
|
expect(mockedAiApiClient.getJobStatus).toHaveBeenCalledTimes(1);
|
|
|
|
|
});
|
|
|
|
|
console.log('--- [TEST LOG] ---: 2. First poll confirmed.');
|
|
|
|
|
|
|
|
|
|
// Record the number of calls before unmounting.
|
|
|
|
|
const callsBeforeUnmount = mockedAiApiClient.getJobStatus.mock.calls.length;
|
|
|
|
|
|
|
|
|
|
// Now unmount the component, which should stop the polling.
|
|
|
|
|
console.log('--- [TEST LOG] ---: 3. Unmounting component.');
|
|
|
|
|
unmount();
|
|
|
|
|
|
|
|
|
|
// Verify that the cleanup function in the useEffect hook was called
|
|
|
|
|
expect(clearTimeoutSpy).toHaveBeenCalled();
|
|
|
|
|
console.log('--- [TEST LOG] ---: 3. clearTimeout confirmed.');
|
|
|
|
|
// Wait for a duration longer than the polling interval (3s) to see if more calls are made.
|
|
|
|
|
console.log('--- [TEST LOG] ---: 4. Waiting for 4 seconds to check for further polling.');
|
|
|
|
|
await act(() => new Promise((resolve) => setTimeout(resolve, 4000)));
|
|
|
|
|
|
|
|
|
|
clearTimeoutSpy.mockRestore();
|
|
|
|
|
// Verify that getJobStatus was not called again after unmounting.
|
|
|
|
|
console.log('--- [TEST LOG] ---: 5. Asserting no new polls occurred.');
|
|
|
|
|
expect(mockedAiApiClient.getJobStatus).toHaveBeenCalledTimes(callsBeforeUnmount);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should handle a duplicate flyer error (409)', async () => {
|
|
|
|
|
|