Skip to content

Commit 5df6300

Browse files
authored
Merge pull request #10944 from opencrvs/ocrvs-10875
fix: ommit fields from hidden pages early on
2 parents 70bf3be + bb3af66 commit 5df6300

File tree

5 files changed

+122
-22
lines changed

5 files changed

+122
-22
lines changed

packages/client/src/v2-events/features/events/actions/declare/Pages.interaction.stories.tsx

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
ActionStatus,
1818
ActionType,
1919
Draft,
20+
generateEventDocument,
2021
generateWorkqueues,
2122
getCurrentEventState,
2223
tennisClubMembershipEvent,
@@ -437,7 +438,10 @@ export const CanSubmitValidlyFilledForm: Story = {
437438
'Verify that register button is enabled and that no validation errors are shown',
438439
async () => {
439440
await expect(canvas.queryByText('Required')).not.toBeInTheDocument()
440-
await expect(await canvas.findByText('Register')).toBeEnabled()
441+
const registerButton = await canvas.findByText('Register')
442+
await expect(registerButton).toBeEnabled()
443+
await userEvent.click(registerButton)
444+
await userEvent.click(await canvas.findByTestId('confirm_Declare'))
441445
}
442446
)
443447
},
@@ -454,6 +458,64 @@ export const CanSubmitValidlyFilledForm: Story = {
454458
event: [
455459
tRPCMsw.event.get.query(() => {
456460
return undeclaredDraftEvent
461+
}),
462+
tRPCMsw.event.actions.declare.request.mutation(async (payload) => {
463+
await expect(payload.declaration).not.toHaveProperty(
464+
'recommender.name'
465+
)
466+
return generateEventDocument({
467+
configuration: tennisClubMembershipEvent,
468+
actions: [
469+
{ type: ActionType.CREATE },
470+
{ type: ActionType.DECLARE }
471+
]
472+
})
473+
}),
474+
tRPCMsw.event.actions.validate.request.mutation(async (payload) => {
475+
await expect(payload.declaration).not.toHaveProperty(
476+
'recommender.name'
477+
)
478+
return generateEventDocument({
479+
configuration: tennisClubMembershipEvent,
480+
actions: [
481+
{ type: ActionType.CREATE },
482+
{ type: ActionType.DECLARE },
483+
{ type: ActionType.VALIDATE }
484+
]
485+
})
486+
}),
487+
tRPCMsw.event.actions.register.request.mutation(async (payload) => {
488+
await expect(payload.declaration).not.toHaveProperty(
489+
'recommender.name'
490+
)
491+
return generateEventDocument({
492+
configuration: tennisClubMembershipEvent,
493+
actions: [
494+
{ type: ActionType.CREATE },
495+
{ type: ActionType.DECLARE },
496+
{ type: ActionType.VALIDATE },
497+
{ type: ActionType.REGISTER }
498+
]
499+
})
500+
}),
501+
tRPCMsw.event.search.query((input) => {
502+
return {
503+
results: [
504+
getCurrentEventState(
505+
generateEventDocument({
506+
configuration: tennisClubMembershipEvent,
507+
actions: [
508+
{ type: ActionType.CREATE },
509+
{ type: ActionType.DECLARE },
510+
{ type: ActionType.VALIDATE },
511+
{ type: ActionType.REGISTER }
512+
]
513+
}),
514+
tennisClubMembershipEvent
515+
)
516+
],
517+
total: 1
518+
}
457519
})
458520
]
459521
}

packages/commons/src/events/test.utils.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ function mapFieldTypeToMockValue(
254254
}
255255
}
256256

257-
function fieldConfigsToActionPayload(
257+
export function fieldConfigsToActionPayload(
258258
fields: FieldConfig[],
259259
rng: () => number
260260
): EventState {

packages/commons/src/events/utils.test.ts

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,23 @@
1010
*/
1111

1212
import { UUID } from '../uuid'
13-
import { cloneDeep } from 'lodash'
13+
import { cloneDeep, difference } from 'lodash'
1414
import { Action } from './ActionDocument'
1515
import { ActionType } from './ActionType'
1616
import {
1717
findLastAssignmentAction,
18+
getDeclaration,
19+
getDeclarationFields,
1820
getMixedPath,
19-
getPendingAction
21+
getPendingAction,
22+
omitHiddenPaginatedFields
2023
} from './utils'
2124
import { TokenUserType } from '../authentication'
25+
import {
26+
createPrng,
27+
fieldConfigsToActionPayload,
28+
tennisClubMembershipEvent
29+
} from '../client'
2230

2331
const commonAction = {
2432
status: 'Requested' as const,
@@ -517,3 +525,34 @@ describe('getPendingAction', () => {
517525
)
518526
})
519527
})
528+
529+
describe('omitHiddenPaginatedFields', () => {
530+
it('removes fields that are hidden by field conditionals when page conditional is true', () => {
531+
const rng = createPrng(101)
532+
533+
const fields = getDeclarationFields(tennisClubMembershipEvent)
534+
535+
const declarationConfig = getDeclaration(tennisClubMembershipEvent)
536+
537+
const declaration = fieldConfigsToActionPayload(fields, rng)
538+
const declarationWithoutHiddenFields = omitHiddenPaginatedFields(
539+
declarationConfig,
540+
declaration,
541+
{}
542+
)
543+
544+
const missingKeys = difference(
545+
Object.keys(declaration),
546+
Object.keys(declarationWithoutHiddenFields)
547+
)
548+
549+
expect(missingKeys).toEqual([
550+
'applicant.dob', // dobUnknown is true
551+
'applicant.isRecommendedByFieldAgent', // user is not field agent
552+
'senior-pass.id', // dob is not before the threshhold
553+
'senior-pass.recommender', // dob is not before threshhold
554+
'recommender.name', // recommender.none is true
555+
'recommender.id' // recommender.none is true
556+
])
557+
})
558+
})

packages/commons/src/events/utils.ts

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ import { getOrThrow } from '../utils'
5454
import { TokenUserType } from '../authentication'
5555
import { DateValue, SelectDateRangeValue } from './FieldValue'
5656
import { subDays, subYears, format } from 'date-fns'
57-
import { ConditionalType } from './Conditional'
5857

5958
export function ageToDate(age: number, asOfDate: DateValue) {
6059
const date = new Date(asOfDate)
@@ -222,24 +221,23 @@ export function omitHiddenPaginatedFields(
222221
values: EventState,
223222
validatorContext: ValidatorContext
224223
) {
225-
// If a page has a conditional, we set it as one of the field's conditionals with ConditionalType.SHOW
226-
const fields = formConfig.pages.flatMap((p) =>
227-
p.fields.map((f) => {
228-
if (!p.conditional) {
229-
return f
230-
}
224+
const visibleFields = formConfig.pages
225+
.filter((p) => isPageVisible(p, values, validatorContext))
226+
.flatMap((p) => p.fields)
231227

232-
return {
233-
...f,
234-
conditionals: [
235-
...(f.conditionals ?? []),
236-
{ type: ConditionalType.SHOW, conditional: p.conditional }
237-
]
238-
}
239-
})
240-
)
228+
const hiddenFields = formConfig.pages
229+
.filter((p) => !isPageVisible(p, values, validatorContext))
230+
.flatMap((p) => p.fields)
241231

242-
return omitHiddenFields(fields, values, validatorContext)
232+
const valuesExceptHiddenPage = omitBy(values, (_, fieldId) => {
233+
return hiddenFields.some((f) => f.id === fieldId)
234+
})
235+
236+
return omitHiddenFields(
237+
visibleFields,
238+
valuesExceptHiddenPage,
239+
validatorContext
240+
)
243241
}
244242

245243
/**

packages/commons/src/fixtures/forms.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1224,7 +1224,8 @@ export const TENNIS_CLUB_DECLARATION_FORM = defineDeclarationForm({
12241224
id: 'event.tennis-club-membership.action.declare.form.section.recommender.field.id.label'
12251225
}
12261226
}
1227-
]
1227+
],
1228+
conditional: not(never()) // Intentional always-true page conditional to exercise interactions between page-level and field-level conditionals in tests
12281229
}
12291230
]
12301231
})

0 commit comments

Comments
 (0)