diff --git a/frontend/app/component/form/data_entry/candidates_votes/CandidatesVotesForm.test.tsx b/frontend/app/component/form/data_entry/candidates_votes/CandidatesVotesForm.test.tsx index 40cbf5fd4..daccea930 100644 --- a/frontend/app/component/form/data_entry/candidates_votes/CandidatesVotesForm.test.tsx +++ b/frontend/app/component/form/data_entry/candidates_votes/CandidatesVotesForm.test.tsx @@ -12,15 +12,16 @@ import { getUrlMethodAndBody, overrideOnce, render, screen, server, within } fro import { DataEntryProvider } from "../state/DataEntryProvider"; import { DataEntryState } from "../state/types"; -import { defaultFormSection, overrideServerGetDataEntryResponse } from "../test.util"; import { + defaultFormSection, emptyDataEntryRequest, expectFieldsToBeInvalidAndToHaveAccessibleErrorMessage, expectFieldsToBeValidAndToNotHaveAccessibleErrorMessage, expectFieldsToHaveIconAndToHaveAccessibleName, expectFieldsToNotHaveIcon, getCandidateFullNamesFromMockData, -} from "../testHelperFunctions"; + overrideServerGetDataEntryResponse, +} from "../test.util"; import { CandidatesVotesForm } from "./CandidatesVotesForm"; const defaultDataEntryState: DataEntryState = { diff --git a/frontend/app/component/form/data_entry/check_and_save/CheckAndSaveForm.test.tsx b/frontend/app/component/form/data_entry/check_and_save/CheckAndSaveForm.test.tsx index 9565c7554..709fb8f59 100644 --- a/frontend/app/component/form/data_entry/check_and_save/CheckAndSaveForm.test.tsx +++ b/frontend/app/component/form/data_entry/check_and_save/CheckAndSaveForm.test.tsx @@ -12,8 +12,12 @@ import { overrideOnce, renderReturningRouter, screen, server, within } from "@ki import { DataEntryProvider } from "../state/DataEntryProvider"; import { DataEntryState } from "../state/types"; -import { defaultFormSection, overrideServerGetDataEntryResponse } from "../test.util"; -import { emptyDataEntryRequest, errorWarningMocks } from "../testHelperFunctions"; +import { + defaultFormSection, + emptyDataEntryRequest, + errorWarningMocks, + overrideServerGetDataEntryResponse, +} from "../test.util"; import { CheckAndSaveForm } from "./CheckAndSaveForm"; const defaultValues = emptyDataEntryRequest.data; diff --git a/frontend/app/component/form/data_entry/differences/DifferenceForm.test.tsx b/frontend/app/component/form/data_entry/differences/DifferenceForm.test.tsx index 2b5e6b1ee..515939152 100644 --- a/frontend/app/component/form/data_entry/differences/DifferenceForm.test.tsx +++ b/frontend/app/component/form/data_entry/differences/DifferenceForm.test.tsx @@ -2,12 +2,14 @@ import { userEvent } from "@testing-library/user-event"; import { beforeEach, describe, expect, test, vi } from "vitest"; import { + defaultFormSection, emptyDataEntryRequest, expectFieldsToBeInvalidAndToHaveAccessibleErrorMessage, expectFieldsToBeValidAndToNotHaveAccessibleErrorMessage, expectFieldsToHaveIconAndToHaveAccessibleName, expectFieldsToNotHaveIcon, -} from "app/component/form/data_entry/testHelperFunctions"; + overrideServerGetDataEntryResponse, +} from "app/component/form/data_entry/test.util"; import { POLLING_STATION_DATA_ENTRY_SAVE_REQUEST_BODY } from "@kiesraad/api"; import { @@ -19,7 +21,6 @@ import { getUrlMethodAndBody, overrideOnce, render, screen, server, userTypeInpu import { DataEntryProvider } from "../state/DataEntryProvider"; import { DataEntryState } from "../state/types"; -import { defaultFormSection, overrideServerGetDataEntryResponse } from "../test.util"; import { DifferencesForm } from "./DifferencesForm"; const defaultDataEntryState: DataEntryState = { diff --git a/frontend/app/component/form/data_entry/recounted/RecountedForm.test.tsx b/frontend/app/component/form/data_entry/recounted/RecountedForm.test.tsx index b1686efff..35aff42ca 100644 --- a/frontend/app/component/form/data_entry/recounted/RecountedForm.test.tsx +++ b/frontend/app/component/form/data_entry/recounted/RecountedForm.test.tsx @@ -1,7 +1,7 @@ import { userEvent } from "@testing-library/user-event"; import { beforeEach, describe, expect, test, vi } from "vitest"; -import { emptyDataEntryRequest, errorWarningMocks } from "app/component/form/data_entry/testHelperFunctions"; +import { emptyDataEntryRequest, errorWarningMocks } from "app/component/form/data_entry/test.util"; import { POLLING_STATION_DATA_ENTRY_SAVE_REQUEST_BODY, SaveDataEntryResponse } from "@kiesraad/api"; import { diff --git a/frontend/app/component/form/data_entry/state/dataEntryUtils.test.ts b/frontend/app/component/form/data_entry/state/dataEntryUtils.test.ts index bf44cd2cb..cd1fc9a94 100644 --- a/frontend/app/component/form/data_entry/state/dataEntryUtils.test.ts +++ b/frontend/app/component/form/data_entry/state/dataEntryUtils.test.ts @@ -2,8 +2,7 @@ import { assert, describe, expect, test } from "vitest"; import { ValidationResult } from "@kiesraad/api"; -import { defaultDataEntryState, initialValues } from "../test.util"; -import { errorWarningMocks } from "../testHelperFunctions"; +import { defaultDataEntryState, errorWarningMocks, initialValues } from "../test.util"; import { addValidationResultToFormState, formSectionComplete, diff --git a/frontend/app/component/form/data_entry/test.util.ts b/frontend/app/component/form/data_entry/test.util.ts index 8709a3ab4..f482e55b5 100644 --- a/frontend/app/component/form/data_entry/test.util.ts +++ b/frontend/app/component/form/data_entry/test.util.ts @@ -1,6 +1,15 @@ -import { GetDataEntryResponse, PollingStationResults } from "@kiesraad/api"; +import { expect } from "vitest"; + +import { + GetDataEntryResponse, + PoliticalGroup, + POLLING_STATION_DATA_ENTRY_SAVE_REQUEST_BODY, + PollingStationResults, + ValidationResult, + ValidationResultCode, +} from "@kiesraad/api"; import { electionMockData } from "@kiesraad/api-mocks"; -import { overrideOnce } from "@kiesraad/test"; +import { overrideOnce, screen, within } from "@kiesraad/test"; import { getClientState } from "./state/dataEntryUtils"; import { DataEntryState, FormSection, FormState } from "./state/types"; @@ -119,3 +128,130 @@ export function overrideServerGetDataEntryResponse({ validation_results: validationResults, } satisfies GetDataEntryResponse); } + +export function expectFieldsToBeInvalidAndToHaveAccessibleErrorMessage(fields: Array, feedbackMessage: string) { + fields.forEach((field) => { + const inputField = within(screen.getByTestId(`cell-${field}`)).getByRole("textbox"); + expect(inputField).toBeInvalid(); + expect(inputField).toHaveAccessibleErrorMessage(feedbackMessage); + }); +} + +export function expectFieldsToHaveIconAndToHaveAccessibleName(fields: Array, accessibleName: string) { + fields.forEach((field) => { + const icon = within(screen.getByTestId(`cell-${field}`)).getByRole("img"); + expect(icon).toHaveAccessibleName(accessibleName); + }); +} + +export function expectFieldsToBeValidAndToNotHaveAccessibleErrorMessage(fields: Array) { + fields.forEach((field) => { + const inputField = within(screen.getByTestId(`cell-${field}`)).getByRole("textbox"); + expect(inputField).toBeValid(); + expect(inputField).not.toHaveAccessibleErrorMessage(); + }); +} + +export function expectFieldsToNotHaveIcon(fields: Array) { + fields.forEach((field) => { + const icon = within(screen.getByTestId(`cell-${field}`)).queryByRole("img"); + expect(icon).toBeNull(); + }); +} + +export const emptyDataEntryRequest: POLLING_STATION_DATA_ENTRY_SAVE_REQUEST_BODY = { + progress: 0, + data: { + voters_counts: { + poll_card_count: 0, + proxy_certificate_count: 0, + voter_card_count: 0, + total_admitted_voters_count: 0, + }, + votes_counts: { + votes_candidates_count: 0, + blank_votes_count: 0, + invalid_votes_count: 0, + total_votes_cast_count: 0, + }, + differences_counts: { + more_ballots_count: 0, + fewer_ballots_count: 0, + unreturned_ballots_count: 0, + too_few_ballots_handed_out_count: 0, + too_many_ballots_handed_out_count: 0, + other_explanation_count: 0, + no_explanation_count: 0, + }, + political_group_votes: electionMockData.political_groups.map((group) => ({ + number: group.number, + total: 0, + candidate_votes: group.candidates.map((candidate) => ({ + number: candidate.number, + votes: 0, + })), + })), + }, + client_state: { + test: "test", + }, +}; + +type ErrorWarningsMap = { + [C in Code]: ValidationResult & { code: C }; +}; + +export const errorWarningMocks: ErrorWarningsMap<"F101" | "F201" | "F301" | "F204" | "W301" | "W302"> = { + F101: { + fields: ["data.recounted"], + code: "F101", + }, + F201: { + fields: [ + "data.voters_counts.poll_card_count", + "data.voters_counts.proxy_certificate_count", + "data.voters_counts.voter_card_count", + "data.voters_counts.total_admitted_voters_count", + ], + code: "F201", + }, + F204: { + fields: ["data.votes_counts.votes_candidates_count", "data.political_group_votes"], + code: "F204", + }, + F301: { + fields: ["data.differences_counts.more_ballots_count"], + code: "F301", + }, + W301: { + fields: [ + "data.differences_counts.more_ballots_count", + "data.differences_counts.too_many_ballots_handed_out_count", + "data.differences_counts.unreturned_ballots_count", + "data.differences_counts.too_few_ballots_handed_out_count", + "data.differences_counts.other_explanation_count", + "data.differences_counts.no_explanation_count", + ], + code: "W301", + }, + W302: { + fields: [ + "data.differences_counts.fewer_ballots_count", + "data.differences_counts.unreturned_ballots_count", + "data.differences_counts.too_few_ballots_handed_out_count", + "data.differences_counts.too_many_ballots_handed_out_count", + "data.differences_counts.other_explanation_count", + "data.differences_counts.no_explanation_count", + ], + code: "W302", + }, +}; + +export function getCandidateFullNamesFromMockData(politicalGroupMockData: PoliticalGroup): string[] { + const candidateNames = politicalGroupMockData.candidates.map((candidate) => { + return candidate.first_name + ? `${candidate.last_name}, ${candidate.initials} (${candidate.first_name})` + : `${candidate.last_name}, ${candidate.initials}`; + }); + return candidateNames; +} diff --git a/frontend/app/component/form/data_entry/testHelperFunctions.ts b/frontend/app/component/form/data_entry/testHelperFunctions.ts deleted file mode 100644 index 5afdb3cb9..000000000 --- a/frontend/app/component/form/data_entry/testHelperFunctions.ts +++ /dev/null @@ -1,137 +0,0 @@ -import { expect } from "vitest"; - -import { - PoliticalGroup, - POLLING_STATION_DATA_ENTRY_SAVE_REQUEST_BODY, - ValidationResult, - ValidationResultCode, -} from "@kiesraad/api"; -import { electionMockData } from "@kiesraad/api-mocks"; -import { screen, within } from "@kiesraad/test"; - -export function expectFieldsToBeInvalidAndToHaveAccessibleErrorMessage(fields: Array, feedbackMessage: string) { - fields.forEach((field) => { - const inputField = within(screen.getByTestId(`cell-${field}`)).getByRole("textbox"); - expect(inputField).toBeInvalid(); - expect(inputField).toHaveAccessibleErrorMessage(feedbackMessage); - }); -} - -export function expectFieldsToHaveIconAndToHaveAccessibleName(fields: Array, accessibleName: string) { - fields.forEach((field) => { - const icon = within(screen.getByTestId(`cell-${field}`)).getByRole("img"); - expect(icon).toHaveAccessibleName(accessibleName); - }); -} - -export function expectFieldsToBeValidAndToNotHaveAccessibleErrorMessage(fields: Array) { - fields.forEach((field) => { - const inputField = within(screen.getByTestId(`cell-${field}`)).getByRole("textbox"); - expect(inputField).toBeValid(); - expect(inputField).not.toHaveAccessibleErrorMessage(); - }); -} - -export function expectFieldsToNotHaveIcon(fields: Array) { - fields.forEach((field) => { - const icon = within(screen.getByTestId(`cell-${field}`)).queryByRole("img"); - expect(icon).toBeNull(); - }); -} - -export const emptyDataEntryRequest: POLLING_STATION_DATA_ENTRY_SAVE_REQUEST_BODY = { - progress: 0, - data: { - voters_counts: { - poll_card_count: 0, - proxy_certificate_count: 0, - voter_card_count: 0, - total_admitted_voters_count: 0, - }, - votes_counts: { - votes_candidates_count: 0, - blank_votes_count: 0, - invalid_votes_count: 0, - total_votes_cast_count: 0, - }, - differences_counts: { - more_ballots_count: 0, - fewer_ballots_count: 0, - unreturned_ballots_count: 0, - too_few_ballots_handed_out_count: 0, - too_many_ballots_handed_out_count: 0, - other_explanation_count: 0, - no_explanation_count: 0, - }, - political_group_votes: electionMockData.political_groups.map((group) => ({ - number: group.number, - total: 0, - candidate_votes: group.candidates.map((candidate) => ({ - number: candidate.number, - votes: 0, - })), - })), - }, - client_state: { - test: "test", - }, -}; - -type ErrorWarningsMap = { - [C in Code]: ValidationResult & { code: C }; -}; - -export const errorWarningMocks: ErrorWarningsMap<"F101" | "F201" | "F301" | "F204" | "W301" | "W302"> = { - F101: { - fields: ["data.recounted"], - code: "F101", - }, - F201: { - fields: [ - "data.voters_counts.poll_card_count", - "data.voters_counts.proxy_certificate_count", - "data.voters_counts.voter_card_count", - "data.voters_counts.total_admitted_voters_count", - ], - code: "F201", - }, - F204: { - fields: ["data.votes_counts.votes_candidates_count", "data.political_group_votes"], - code: "F204", - }, - F301: { - fields: ["data.differences_counts.more_ballots_count"], - code: "F301", - }, - W301: { - fields: [ - "data.differences_counts.more_ballots_count", - "data.differences_counts.too_many_ballots_handed_out_count", - "data.differences_counts.unreturned_ballots_count", - "data.differences_counts.too_few_ballots_handed_out_count", - "data.differences_counts.other_explanation_count", - "data.differences_counts.no_explanation_count", - ], - code: "W301", - }, - W302: { - fields: [ - "data.differences_counts.fewer_ballots_count", - "data.differences_counts.unreturned_ballots_count", - "data.differences_counts.too_few_ballots_handed_out_count", - "data.differences_counts.too_many_ballots_handed_out_count", - "data.differences_counts.other_explanation_count", - "data.differences_counts.no_explanation_count", - ], - code: "W302", - }, -}; - -export function getCandidateFullNamesFromMockData(politicalGroupMockData: PoliticalGroup): string[] { - const candidateNames = politicalGroupMockData.candidates.map((candidate) => { - return candidate.first_name - ? `${candidate.last_name}, ${candidate.initials} (${candidate.first_name})` - : `${candidate.last_name}, ${candidate.initials}`; - }); - return candidateNames; -} diff --git a/frontend/app/component/form/data_entry/voters_and_votes/VotersAndVotesForm.test.tsx b/frontend/app/component/form/data_entry/voters_and_votes/VotersAndVotesForm.test.tsx index f99766199..1db98358f 100644 --- a/frontend/app/component/form/data_entry/voters_and_votes/VotersAndVotesForm.test.tsx +++ b/frontend/app/component/form/data_entry/voters_and_votes/VotersAndVotesForm.test.tsx @@ -3,12 +3,14 @@ import { beforeEach, describe, expect, test, vi } from "vitest"; import { mockElection } from "app/component/election/status/mockData"; import { + defaultFormSection, emptyDataEntryRequest, expectFieldsToBeInvalidAndToHaveAccessibleErrorMessage, expectFieldsToBeValidAndToNotHaveAccessibleErrorMessage, expectFieldsToHaveIconAndToHaveAccessibleName, expectFieldsToNotHaveIcon, -} from "app/component/form/data_entry/testHelperFunctions"; + overrideServerGetDataEntryResponse, +} from "app/component/form/data_entry/test.util"; import { GetDataEntryResponse, @@ -25,7 +27,6 @@ import { getUrlMethodAndBody, overrideOnce, render, screen, server, userTypeInpu import { DataEntryProvider } from "../state/DataEntryProvider"; import { getClientState } from "../state/dataEntryUtils"; import { DataEntryState } from "../state/types"; -import { defaultFormSection, overrideServerGetDataEntryResponse } from "../test.util"; import { VotersAndVotesForm } from "./VotersAndVotesForm"; const initialValues: PollingStationResults = { diff --git a/frontend/app/module/data_entry/DataEntry.integration.test.tsx b/frontend/app/module/data_entry/DataEntry.integration.test.tsx index 1b096c8f9..92ecdeb6d 100644 --- a/frontend/app/module/data_entry/DataEntry.integration.test.tsx +++ b/frontend/app/module/data_entry/DataEntry.integration.test.tsx @@ -2,7 +2,7 @@ import { render as rtlRender, within } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { beforeEach, describe, expect, test, vi } from "vitest"; -import { errorWarningMocks } from "app/component/form/data_entry/testHelperFunctions"; +import { errorWarningMocks } from "app/component/form/data_entry/test.util"; import { routes } from "app/routes"; import { SaveDataEntryResponse } from "@kiesraad/api"; diff --git a/sigrid.yaml b/sigrid.yaml index 65582464d..fa5eee912 100644 --- a/sigrid.yaml +++ b/sigrid.yaml @@ -166,6 +166,7 @@ languages: - ".*[.]e2e[.]ts" - ".*.stories[.]tsx" - ".*/test-data/.*[.]ts" + - ".*/test[.]utils[.]ts" generated: include: - ".*/gen/.*[.]ts"