Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions __mocks__/forms/rfe-forms/repeating-component-test-form.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
{
"name": "Repeating Component Test Form",
"pages": [
{
"label": "Emergency Contact",
"sections": [
{
"label": "Contacts",
"isExpanded": "true",
"questions": [
{
"label": "Contact",
"type": "obsGroup",
"required": true,
"id": "patientContact",
"questionOptions": {
"rendering": "repeating"
},
"questions": [
{
"label": "Contact relationship",
"type": "obs",
"required": true,
"id": "patientContactRelationship",
"questionOptions": {
"rendering": "radio",
"concept": "164352AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"conceptMappings": [
{
"relationship": "SAME-AS",
"type": "CIEL",
"value": "164352"
}
],
"answers": [
{
"concept": "1528AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"label": "Child"
},
{
"concept": "972AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"label": "Brother/Sister"
},
{
"concept": "1527AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"label": "Father/Mother"
},
{
"concept": "5617AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"label": "Partner/Spouse"
},
{
"concept": "5622AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"label": "Other"
}
]
}
},
{
"label": "Phone",
"type": "obs",
"required": true,
"id": "phoneNumber",
"questionOptions": {
"rendering": "text",
"concept": "1650AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"conceptMappings": [
{
"relationship": "SAME-AS",
"type": "CIEL",
"value": "1650"
}
]
}
}
]
}
]
}
]
}
],
"processor": "EncounterFormProcessor",
"encounterType": "dd528487-82a5-4082-9c72-ed246bd49591",
"referencedForms": [],
"uuid": "a8817ad2-ef92-46c8-bbf7-db336505027c",
"description": "test-repeating",
"version": "1.0"
}
29 changes: 0 additions & 29 deletions src/components/repeat/repeat.test.ts

This file was deleted.

152 changes: 152 additions & 0 deletions src/components/repeat/repeat.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { updateFieldIdInExpression } from './helpers';
import { render, screen, waitFor } from '@testing-library/react';
import repeatingComponentTestForm from '../../../__mocks__/forms/rfe-forms/repeating-component-test-form.json';
import { useFormProviderContext } from '../../provider/form-provider';
import { usePatient, useSession } from '@openmrs/esm-framework';
import { type FormSchema, type SessionMode } from '../../types';
import { FormEngine } from '../../..';
import { mockPatient } from '../../../__mocks__/patient.mock';
import { mockSessionDataResponse } from '../../../__mocks__/session.mock';
import userEvent from '@testing-library/user-event';
import React, { act } from 'react';

describe('RepeatingFieldComponent - handleExpressionFieldIdUpdate', () => {
it('Should handle update of expression with ids in repeat group', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
it('Should handle update of expression with ids in repeat group', () => {
it('Should update field IDs when repeat index is greater than 1', () => {

const expression =
"infantStatus !== '151849AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' && infantStatus !== '154223AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'";
const fieldIds = ['birthDate', 'infantStatus', 'deathDate'];
const index = 2;

const updatedExpression = updateFieldIdInExpression(expression, index, fieldIds);

expect(updatedExpression).toEqual(
"infantStatus_2 !== '151849AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' && infantStatus_2 !== '154223AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'",
);
});

it('Should handle update of expression with ids not in repeat group', () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
it('Should handle update of expression with ids not in repeat group', () => {
it('Should not update field IDs when repeat index equals 1', () => {

const expression =
"myValue > today() || myValue <= '1/1/1890' || myValue > useFieldValue('visit_date') || myValue < useFieldValue('visit_date')";
const fieldIds = ['birthDate', 'infantStatus', 'deathDate'];
const index = 1;

const updatedExpression = updateFieldIdInExpression(expression, index, fieldIds);

expect(updatedExpression).toEqual(
"myValue > today() || myValue <= '1/1/1890' || myValue > useFieldValue('visit_date') || myValue < useFieldValue('visit_date')",
);
});
});

describe('Repeat Component Tests', () => {
const mockUsePatient = jest.mocked(usePatient);
const mockUseSession = jest.mocked(useSession);

global.ResizeObserver = require('resize-observer-polyfill');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is currently configured here.


jest.mock('@openmrs/esm-framework', () => {
const originalModule = jest.requireActual('@openmrs/esm-framework');
return {
...originalModule,
usePatient: jest.fn(),
useSession: jest.fn(),
createGlobalStore: jest.fn(),
ActionMenu: jest.fn(() => <div />),
};
});

jest.mock('../../provider/form-provider', () => {
const originalModule = jest.requireActual('../../provider/form-provider');
return {
...originalModule,
useFormProviderContext: jest.fn(),
};
});

jest.mock('../../api', () => ({}));

const renderForm = async (mode: SessionMode = 'enter') => {
await act(async () => {
render(
<FormEngine
formJson={repeatingComponentTestForm as FormSchema}
patientUUID="8673ee4f-e2ab-4077-ba55-4980f408773e"
mode={mode}
encounterUUID={mode === 'edit' ? 'a8817ad2-ef92-46c8-bbf7-db336505027c' : null}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@WodPachua, Do you have any test cases covering the "edit mode"? If not, can we define some?

/>,
);
});
};

const user = userEvent.setup();

const mockContext = {
patient: {},
sessionMode: 'enter',
formFields: repeatingComponentTestForm.pages[0].sections[0].questions,
methods: { getValues: jest.fn(), setValue: jest.fn() },
addFormField: jest.fn(),
formFieldAdapters: { obsGroup: { transformFieldValue: jest.fn() } },
};

beforeEach(() => {
Object.defineProperty(window, 'i18next', {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is currently configured here.

writable: true,
configurable: true,
value: {
language: 'en',
t: jest.fn(),
},
});

mockUsePatient.mockImplementation(() => ({
patient: mockPatient,
isLoading: false,
error: undefined,
patientUuid: mockPatient.id,
}));

mockUseSession.mockImplementation(() => mockSessionDataResponse.data);
(useFormProviderContext as jest.Mock).mockReturnValue(mockContext);
});

it('Should add a repeatable field instance on clicking "Add"', async () => {
await renderForm();
const addButton = screen.getByText(/add/i);
await user.click(addButton);

expect(mockContext.addFormField).toHaveBeenCalledTimes(1);
expect(mockContext.addFormField).toHaveBeenCalledWith(expect.objectContaining({ id: 'patientContact_1' }));
});

it('Should clone the field at origin on clicking "Add"', async () => {
await renderForm();
const addButton = screen.getByText(/add/i);
await user.click(addButton);

const clonedField = screen.getByLabelText(/Contact relationship/i);
expect(clonedField).toBeInTheDocument();
Comment on lines +127 to +128
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you confirm that there are two fields with the label "Contact relationship" that never existed on the initial render?

});

it('Should submit both the origin and its instances\' values successfully', async () => {
await renderForm();
const addButton = screen.getByText(/add/i);
await user.click(addButton);

const contactRelationshipField = screen.getByLabelText(/Contact relationship/i);
const phoneNumberField = screen.getByLabelText(/Phone/i);

await user.type(contactRelationshipField, 'Child');
await user.type(phoneNumberField, '123456789');

const submitButton = screen.getByText(/save/i);
await user.click(submitButton);

await waitFor(() => {
expect(mockContext.methods.getValues).toHaveBeenCalledWith(expect.objectContaining({
patientContactRelationship: 'Child',
phoneNumber: '123456789',
}));
Comment on lines +145 to +149
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also provide values for the instances so that we end up with a submission like:

     {
        patientContactRelationship: 'Child',
        patientContactRelationship_2: 'foo',
        phoneNumber: '123456789',
        phoneNumber_2: 'bar'
      }

});
});
});