Skip to content

Commit

Permalink
PLU-393: Variables: keys with . may be single key or nested path (#831)
Browse files Browse the repository at this point in the history
### TL;DR
New MyInfo Child fields from FormSG returns data with `.` as part of the
key (e.g., `child.birthdate`).

Libraries like `lodash.get` treat `.` as a path separator for nested
properties (e.g., accessing `child.birthdate`), leading to incorrect
value retrieval or failure.

### What changed?
- Replaced the `.` in keys with `_` to avoid issues with obtaining
values.

### How to test?
1. Run the test suite to verify all scenarios pass
2. Test with actual FormSG fields from MyInfo Child

### Why make this change?
The standard lodash.get function doesn't properly handle cases where
object keys contain dots, leading to incorrect property access. This
implementation provides more accurate property resolution.
  • Loading branch information
kevinkim-ogp authored Dec 24, 2024
1 parent 35f179f commit d3b6611
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,98 @@ describe('decrypt form response', () => {
}),
)
})

it('should parse form fields and replace dots with underscores in keys', async () => {
mockDecryptedSubmission({
responses: [
{
_id: 'question1.field.answer',
fieldType: 'textarea',
question: 'What do you eat for breakfast?',
answer: 'i eat lorem dimsum for breakfast',
},
{
_id: 'question2.field.answer',
fieldType: 'mobile',
question: 'What is your mobile number?',
answer: '+6591234567',
},
],
})
await expect(decryptFormResponse($)).resolves.toEqual(true)
expect($.request.body).toEqual(
expect.objectContaining({
fields: {
question1_field_answer: {
fieldType: 'textarea',
question: 'What do you eat for breakfast?',
answer: 'i eat lorem dimsum for breakfast',
order: 1,
},
question2_field_answer: {
fieldType: 'mobile',
question: 'What is your mobile number?',
answer: '+6591234567',
order: 2,
},
},
}),
)
expect($.request.headers).toBeUndefined()
expect($.request.query).toBeUndefined()
})

it('should parse form fields and replace dots with underscores in keys', async () => {
mockDecryptedSubmission({
responses: [
{
_id: 'childrenbirthrecords.abc.childdateofbirth.0',
fieldType: 'children',
question: 'Child Date of birth',
answer: '31/03/2017',
},
{
_id: 'childrenbirthrecords.abc.childname.0',
fieldType: 'children',
question: 'Child Name',
answer: 'John Doe',
},
{
_id: 'question2.field.answer',
fieldType: 'mobile',
question: 'What is your mobile number?',
answer: '+6591234567',
},
],
})
await expect(decryptFormResponse($)).resolves.toEqual(true)
expect($.request.body).toEqual(
expect.objectContaining({
fields: {
childrenbirthrecords_abc_childdateofbirth_0: {
fieldType: 'children',
question: 'Child Date of birth',
answer: '31/03/2017',
order: 1,
},
childrenbirthrecords_abc_childname_0: {
fieldType: 'children',
question: 'Child Name',
answer: 'John Doe',
order: 2,
},
question2_field_answer: {
fieldType: 'mobile',
question: 'What is your mobile number?',
answer: '+6591234567',
order: 3,
},
},
}),
)
expect($.request.headers).toBeUndefined()
expect($.request.query).toBeUndefined()
})
})

describe('attachments', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ export async function decryptFormResponse(

// Note: the order may not be sequential; fields (e.g. NRIC) can be
// omitted from the output.
parsedData[_id] = {
// Note: FormSG uses dot notation for field ids for MyInfo children
// we replace with underscore to avoid issues when using lodash get.
parsedData[_id.replaceAll('.', '_')] = {
order: index + 1,
...rest,
}
Expand Down
30 changes: 30 additions & 0 deletions packages/backend/src/helpers/__tests__/compute-parameters.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -319,4 +319,34 @@ describe('compute parameters', () => {
const result = computeParameters(params, executionStep)
expect(result).toEqual(expected)
})

it('should process parameters with underscores in keys', () => {
const executionStep = [
{
stepId: randomStepID,
dataOut: {
childrenbirthrecords_abc_childdateofbirth_0: {
fieldType: 'children',
question: 'Child Date of birth',
answer: '31/03/2017',
order: 1,
},
childrenbirthrecords_abc_childname_0: {
fieldType: 'children',
question: 'Child Name',
answer: 'John Doe',
order: 2,
},
},
} as unknown as ExecutionStep,
]
const params = {
toSubstitute: `{{step.${randomStepID}.childrenbirthrecords_abc_childdateofbirth_0.answer}} {{step.${randomStepID}.childrenbirthrecords_abc_childname_0.answer}}`,
}
const expected = {
toSubstitute: `31/03/2017 John Doe`,
}
const result = computeParameters(params, executionStep)
expect(result).toEqual(expected)
})
})

0 comments on commit d3b6611

Please sign in to comment.