Skip to content

Commit 16de5e6

Browse files
✅ [open-formulieren/open-forms#4929] Add test for summary -> status -> error submission flow
There's now a test to lock in the behaviour after confirming the submission, getting the status page with spinner and redirect back to summary page if there's a background processing error. Now we can refactor the error message state handling to get these props out of the Summary component. The fake timer situation is... complicated. See testing-library/react-testing-library#1197
1 parent 3f5f557 commit 16de5e6

File tree

2 files changed

+66
-6
lines changed

2 files changed

+66
-6
lines changed

src/components/Form.jsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,12 +318,10 @@ const Form = () => {
318318
<SessionTrackerModal>
319319
<RequireSubmission
320320
retrieveSubmissionFromContext
321+
component={SubmissionSummary}
321322
processingError={state.processingError}
322323
onConfirm={onSubmitForm}
323-
component={SubmissionSummary}
324324
onClearProcessingErrors={() => dispatch({type: 'CLEAR_PROCESSING_ERROR'})}
325-
onDestroySession={onDestroySession}
326-
form={form}
327325
/>
328326
</SessionTrackerModal>
329327
</ErrorBoundary>

src/components/Form.spec.jsx

Lines changed: 65 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,45 @@
1-
import {render, screen} from '@testing-library/react';
1+
import {render, screen, waitForElementToBeRemoved} from '@testing-library/react';
22
import userEvent from '@testing-library/user-event';
33
import messagesEN from 'i18n/compiled/en.json';
44
import {IntlProvider} from 'react-intl';
55
import {RouterProvider, createMemoryRouter} from 'react-router-dom';
66

77
import {ConfigContext, FormContext} from 'Context';
8-
import {BASE_URL, buildForm, mockAnalyticsToolConfigGet} from 'api-mocks';
8+
import {BASE_URL, buildForm, buildSubmission, mockAnalyticsToolConfigGet} from 'api-mocks';
99
import mswServer from 'api-mocks/msw-server';
10-
import {mockSubmissionPost, mockSubmissionStepGet} from 'api-mocks/submissions';
10+
import {
11+
mockSubmissionCompletePost,
12+
mockSubmissionGet,
13+
mockSubmissionPost,
14+
mockSubmissionProcessingStatusErrorGet,
15+
mockSubmissionStepGet,
16+
mockSubmissionSummaryGet,
17+
} from 'api-mocks/submissions';
1118
import {routes} from 'components/App';
19+
import {SUBMISSION_ALLOWED} from 'components/constants';
1220

1321
window.scrollTo = vi.fn();
1422

23+
beforeAll(() => {
24+
vi.stubGlobal('jest', {
25+
advanceTimersByTime: vi.advanceTimersByTime.bind(vi),
26+
});
27+
});
28+
1529
beforeEach(() => {
1630
localStorage.clear();
1731
});
1832

1933
afterEach(() => {
34+
if (vi.isFakeTimers()) {
35+
vi.runOnlyPendingTimers();
36+
vi.useRealTimers();
37+
}
2038
localStorage.clear();
2139
});
2240

2341
afterAll(() => {
42+
vi.unstubAllGlobals();
2443
vi.clearAllMocks();
2544
});
2645

@@ -129,3 +148,46 @@ test('Navigation through form without introduction page', async () => {
129148
const formInput = await screen.findByLabelText('Component 1');
130149
expect(formInput).toBeVisible();
131150
});
151+
152+
test('Submitting the form with failing background processing', async () => {
153+
const user = userEvent.setup({
154+
advanceTimers: vi.advanceTimersByTime,
155+
});
156+
// The summary page submits the form and needs to trigger the appropriate redirects.
157+
// When the status check reports failure, we need to be redirected back to the summary
158+
// page for a retry.
159+
const form = buildForm({loginRequired: false, submissionStatementsConfiguration: []});
160+
const submission = buildSubmission({
161+
submissionAllowed: SUBMISSION_ALLOWED.yes,
162+
payment: {
163+
isRequired: false,
164+
amount: undefined,
165+
hasPaid: false,
166+
},
167+
MARKER: true,
168+
});
169+
mswServer.use(
170+
mockAnalyticsToolConfigGet(),
171+
mockSubmissionGet(submission),
172+
mockSubmissionSummaryGet(),
173+
mockSubmissionCompletePost(),
174+
mockSubmissionProcessingStatusErrorGet
175+
);
176+
177+
render(<Wrapper form={form} initialEntry={`/overzicht?submission_uuid=${submission.id}`} />);
178+
179+
expect(await screen.findByRole('heading', {name: 'Check and confirm'})).toBeVisible();
180+
181+
// confirm the submission and complete it
182+
vi.useFakeTimers();
183+
await user.click(screen.getByRole('button', {name: 'Confirm'}));
184+
expect(await screen.findByRole('heading', {name: 'Processing...'})).toBeVisible();
185+
const loader = await screen.findByRole('status');
186+
vi.runOnlyPendingTimers();
187+
vi.useRealTimers();
188+
await waitForElementToBeRemoved(loader);
189+
190+
// due to the error we get redirected back to the summary page.
191+
expect(await screen.findByRole('heading', {name: 'Check and confirm'})).toBeVisible();
192+
expect(screen.getByText('Computer says no.')).toBeVisible();
193+
});

0 commit comments

Comments
 (0)