diff --git a/packages/fhir-keycloak-user-management/src/components/UserList/Viewdetails/ViewDetailResources/tests/fixtures.ts b/packages/fhir-keycloak-user-management/src/components/UserList/Viewdetails/ViewDetailResources/tests/fixtures.ts index 1d543f159..d4b5bb55e 100644 --- a/packages/fhir-keycloak-user-management/src/components/UserList/Viewdetails/ViewDetailResources/tests/fixtures.ts +++ b/packages/fhir-keycloak-user-management/src/components/UserList/Viewdetails/ViewDetailResources/tests/fixtures.ts @@ -206,6 +206,33 @@ export const user1147 = { }, }; +export const user1147ExtraFields = { + id: '9f72c646-dc1e-4f24-98df-6f04373b9ec6', + createdTimestamp: 1675179889477, + username: '1147', + enabled: true, + totp: false, + emailVerified: false, + firstName: 'test1147', + lastName: '1147', + email: 'mejay2303@gmail.com', + attributes: { + fhir_core_app_id: ['giz'], + nationalId: ['1234567891011121'], + phoneNumber: ['0101345678'], + }, + disableableCredentialTypes: [], + requiredActions: [], + notBefore: 1681810919, + access: { + manageGroupMembership: true, + view: true, + mapRoles: true, + impersonate: true, + manage: true, + }, +}; + export const user1147Groups = [ { id: 'b68e2590-c2ee-4b3c-9184-c4b35a69a271', diff --git a/packages/fhir-keycloak-user-management/src/components/UserList/Viewdetails/tests/index.test.tsx b/packages/fhir-keycloak-user-management/src/components/UserList/Viewdetails/tests/index.test.tsx index 8d5f7469d..271a854a2 100644 --- a/packages/fhir-keycloak-user-management/src/components/UserList/Viewdetails/tests/index.test.tsx +++ b/packages/fhir-keycloak-user-management/src/components/UserList/Viewdetails/tests/index.test.tsx @@ -25,6 +25,7 @@ import { import { practitionerDetailsBundle, user1147, + user1147ExtraFields, user1147Groups, user1147Roles, } from '../ViewDetailResources/tests/fixtures'; @@ -308,3 +309,166 @@ test('Edit button works correctly', async () => { expect(history.location.pathname).toEqual('/admin/users/edit/userId'); }); + +test('Renders extra user fields correctly', async () => { + const history = createMemoryHistory(); + history.push(`${URL_USER}/${userId}`); + + const successMock = jest + .spyOn(notifications, 'sendSuccessNotification') + .mockImplementation(() => { + return; + }); + + nock(props.fhirBaseURL) + .get(`/${practitionerDetailsResourceType}/_search`) + .query({ 'keycloak-uuid': userId }) + .reply(200, practitionerDetailsBundle); + + nock(props.keycloakBaseURL) + .get(`${KEYCLOAK_URL_USERS}/${userId}`) + .reply(200, user1147ExtraFields); + + nock(props.keycloakBaseURL) + .get(`${KEYCLOAK_URL_USERS}/${userId}${KEYCLOAK_URL_USER_GROUPS}`) + .reply(200, user1147Groups); + + render( + + + + ); + + // this only await the first call to get the users. + await waitForElementToBeRemoved(document.querySelector('.ant-spin')); + + expect(screen.queryByTitle(/View details/i)).toBeInTheDocument(); + + // second page header details. + const userProfile = screen.getByTestId('user-profile'); + const textContent = userProfile.textContent; + expect(textContent).toEqual( + '1147EnabledDeleteEditId9f72c646-dc1e-4f24-98df-6f04373b9ec6First Nametest1147Last Name1147National ID1234567891011121Phone Number0101345678Username1147Emailmejay2303@gmail.comVerifiedFalseAttributesfhir_core_app_id["giz"]' + ); + + // have a look at the tabs + + // start with group + const groupTab = screen.getByText('User groups'); + fireEvent.click(groupTab); + + await waitForElementToBeRemoved(document.querySelector('.ant-spin')); + + // check table has correct number of rows. and try removing user from one group + let detailsTabSection = document.querySelector('.details-tab'); + const groupsTable = detailsTabSection?.querySelector('table'); + + const tableData = [...(groupsTable?.querySelectorAll('tr') ?? [])].map((tr) => tr.textContent); + expect(tableData).toEqual(['NamePathActions', 'SuperUser/SuperUserLeave']); + + const leaveBtn = screen.getByText('Leave'); + expect(leaveBtn).toMatchInlineSnapshot(` + + Leave + + `); + + nock(props.keycloakBaseURL) + .delete(`${KEYCLOAK_URL_USERS}/${userId}${KEYCLOAK_URL_USER_GROUPS}/${user1147Groups[0].id}`) + .reply(200, user1147Groups); + + fireEvent.click(leaveBtn); + + await waitFor(() => { + expect(successMock).toHaveBeenCalledWith( + 'User has been successfully removed from the keycloak group' + ); + }); + + // go to practitioners + const practTab = screen.getByText('Practitioners'); + fireEvent.click(practTab); + + // Check that practitioner-details has finished loading. + await waitFor(() => { + expect(screen.getByText('3a801d6e-7bd3-4a5f-bc9c-64758fbb3dad')).toBeInTheDocument(); + }); + + // practitioner records + detailsTabSection = document.querySelector('div.ant-tabs-tabpane-active'); + const practitionerTable = detailsTabSection?.querySelector('table'); + + const practitionerData = [...(practitionerTable?.querySelectorAll('tr') ?? [])].map( + (tr) => tr.textContent + ); + expect(practitionerData).toEqual([ + 'IdNameActiveUser TypePractitioner Role Coding', + '3a801d6e-7bd3-4a5f-bc9c-64758fbb3dadtest1147 1147ActivepractitionerAssigned practitioner(http://snomed.info/sct|405623001), ', + ]); + + // go to roles + nock(props.keycloakBaseURL) + .get(`${KEYCLOAK_URL_USERS}/${userId}/${keycloakRoleMappingsEndpoint}`) + .reply(200, user1147Roles); + + const rolesTab = screen.getByText('User roles'); + fireEvent.click(rolesTab); + + // Check that practitioner-details has finished loading. + await waitFor(() => { + expect(screen.getByText('GET_LOCATION')).toBeInTheDocument(); + }); + + // practitioner records + detailsTabSection = document.querySelector('div.ant-tabs-tabpane-active'); + const realmRolesTable = detailsTabSection?.querySelectorAll('table')[0]; + const clientRolesTable = detailsTabSection?.querySelectorAll('table')[1]; + const realmRolesData = [...(realmRolesTable?.querySelectorAll('tr') ?? [])].map( + (tr) => tr.textContent + ); + const clientRolesData = [...(clientRolesTable?.querySelectorAll('tr') ?? [])].map( + (tr) => tr.textContent + ); + expect(realmRolesData).toEqual([ + 'NameDescription', + 'POST_LOCATION', + 'GET_LOCATION', + 'offline_access${role_offline-access}', + ]); + + expect(clientRolesData).toEqual([ + 'ClientNameDescription', + 'realm-managementmanage-realm${role_manage-realm}', + 'realm-managementmanage-users${role_manage-users}', + 'accountmanage-account${role_manage-account}', + ]); + + // go to careTeams + const careTeamsTab = screen.getByText('CareTeams'); + fireEvent.click(careTeamsTab); + + // practitioner records + detailsTabSection = document.querySelector('div.ant-tabs-tabpane-active'); + const careTeamsTable = detailsTabSection?.querySelector('table'); + + const careTeamsData = [...(careTeamsTable?.querySelectorAll('tr') ?? [])].map( + (tr) => tr.textContent + ); + expect(careTeamsData).toEqual(['IdNameStatusCategory', 'No data']); + + // go to organization + const organizationsTab = screen.getByText('Organizations'); + fireEvent.click(organizationsTab); + + // practitioner records + detailsTabSection = document.querySelector('div.ant-tabs-tabpane-active'); + const organizationsTable = detailsTabSection?.querySelector('table'); + + const organizationsData = [...(organizationsTable?.querySelectorAll('tr') ?? [])].map( + (tr) => tr.textContent + ); + expect(organizationsData).toEqual([ + 'IdNameActiveType', + '0d7ae048-9b84-4f0c-ba37-8d6c0b97dc84e2e-corporationActive(http://terminology.hl7.org/CodeSystem/organization-type|team), ', + ]); +}); diff --git a/packages/keycloak-user-management/src/components/forms/UserForm/utils.tsx b/packages/keycloak-user-management/src/components/forms/UserForm/utils.tsx index 6d5d778d8..de2811be1 100644 --- a/packages/keycloak-user-management/src/components/forms/UserForm/utils.tsx +++ b/packages/keycloak-user-management/src/components/forms/UserForm/utils.tsx @@ -100,16 +100,8 @@ const createEditKeycloakUser = async ( keycloakBaseURL ); - keycloakUserPayload.attributes = { - ...keycloakUserPayload.attributes, - nationalId: keycloakUserPayload.nationalId, - phoneNumber: keycloakUserPayload.phoneNumber, - }; - - const { nationalId, phoneNumber, ...coreUserPayload } = keycloakUserPayload; - return serve - .update(coreUserPayload) + .update(keycloakUserPayload) .then(() => { sendSuccessNotification(t('User edited successfully')); updateGroupsAndPractitionerCallback(keycloakUserPayload.id).catch(() => @@ -120,18 +112,10 @@ const createEditKeycloakUser = async ( throw error; }); } else { - keycloakUserPayload.attributes = { - ...keycloakUserPayload.attributes, - nationalId: keycloakUserPayload.nationalId, - phoneNumber: keycloakUserPayload.phoneNumber, - }; - - const { nationalId, phoneNumber, ...coreUserPayload } = keycloakUserPayload; - // create new keycloak user const serve = new KeycloakService(KEYCLOAK_URL_USERS, keycloakBaseURL); return serve - .create(coreUserPayload) + .create(keycloakUserPayload) .then((res) => { sendSuccessNotification(t('User created successfully')); const keycloakUserId = getUserId(res); @@ -337,6 +321,8 @@ export const getUserAndGroupsPayload = (values: FormFields) => { const preUserAttributes = { ...(contact ? { contact: [contact] } : {}), ...(fhirCoreAppId ? { fhir_core_app_id: [fhirCoreAppId] } : {}), + ...(nationalId ? { nationalId: [nationalId] } : {}), + ...(phoneNumber ? { phoneNumber: [phoneNumber] } : {}), }; const cleanedAttributes = pickBy( @@ -350,8 +336,6 @@ export const getUserAndGroupsPayload = (values: FormFields) => { firstName, id: isEditMode ? id : '', // id is generated by keycloak for after POST new user lastName, - nationalId, - phoneNumber, username, ...(email ? { email } : {}), enabled, diff --git a/packages/keycloak-user-management/src/ducks/user.ts b/packages/keycloak-user-management/src/ducks/user.ts index 0d5c1a8fb..4c0bf4cd4 100644 --- a/packages/keycloak-user-management/src/ducks/user.ts +++ b/packages/keycloak-user-management/src/ducks/user.ts @@ -62,8 +62,8 @@ export interface KeycloakUser { firstName: string; id: string; lastName: string; - nationalId: string; - phoneNumber: string; + nationalId?: string; + phoneNumber?: string; notBefore?: number; requiredActions?: string[]; totp?: boolean;