From 3d9a14711ea4dfa5b2e83edc7e1c4c9a2acff93a Mon Sep 17 00:00:00 2001 From: Rachel Schneiderman Date: Tue, 12 Mar 2024 09:41:40 -0700 Subject: [PATCH] 10007: Refactor and simplify creating practitioner user --- .../createPractitionerUserInteractor.ts | 45 --------------- .../utilities/createPractitionerUser.ts | 16 ++---- .../createPractitionerUserProxy.ts | 10 +--- .../createPractitionerUserInteractor.test.ts | 57 +++++++++---------- .../createPractitionerUserInteractor.ts | 35 ++++++++++++ .../useCases/user/createUserInteractor.ts | 4 +- web-api/src/getUseCases.ts | 2 +- .../createPractitionerUserAction.test.ts | 26 +++------ .../actions/createPractitionerUserAction.ts | 9 +-- 9 files changed, 84 insertions(+), 120 deletions(-) delete mode 100644 shared/src/business/useCases/practitioners/createPractitionerUserInteractor.ts rename {shared/src/business/useCases/practitioners => web-api/src/business/useCases/practitioner}/createPractitionerUserInteractor.test.ts (55%) create mode 100644 web-api/src/business/useCases/practitioner/createPractitionerUserInteractor.ts diff --git a/shared/src/business/useCases/practitioners/createPractitionerUserInteractor.ts b/shared/src/business/useCases/practitioners/createPractitionerUserInteractor.ts deleted file mode 100644 index f3d9653a250..00000000000 --- a/shared/src/business/useCases/practitioners/createPractitionerUserInteractor.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { Practitioner, RawPractitioner } from '../../entities/Practitioner'; -import { - ROLE_PERMISSIONS, - isAuthorized, -} from '../../../authorization/authorizationClientService'; -import { UnauthorizedError } from '@web-api/errors/errors'; -import { createPractitionerUser } from '../../utilities/createPractitionerUser'; - -/** - * createPractitionerUserInteractor - * - * @param {object} applicationContext the application context - * @param {object} providers the providers object - * @param {object} providers.user the user data - * @returns {Promise} the promise of the createUser call - */ -export const createPractitionerUserInteractor = async ( - applicationContext: IApplicationContext, - { user }: { user: RawPractitioner }, -) => { - const requestUser = applicationContext.getCurrentUser(); - - if (!isAuthorized(requestUser, ROLE_PERMISSIONS.ADD_EDIT_PRACTITIONER_USER)) { - throw new UnauthorizedError('Unauthorized for creating practitioner user'); - } - - user.pendingEmail = user.email; - user.email = undefined; - - const practitioner = await createPractitionerUser({ - applicationContext, - user, - }); - - const createdUser = await applicationContext - .getPersistenceGateway() - .createOrUpdatePractitionerUser({ - applicationContext, - user: practitioner, - }); - - return new Practitioner(createdUser, { applicationContext }) - .validate() - .toRawObject(); -}; diff --git a/shared/src/business/utilities/createPractitionerUser.ts b/shared/src/business/utilities/createPractitionerUser.ts index 66d4569c845..174e41a577d 100644 --- a/shared/src/business/utilities/createPractitionerUser.ts +++ b/shared/src/business/utilities/createPractitionerUser.ts @@ -1,14 +1,10 @@ -import { Practitioner } from '../entities/Practitioner'; +import { Practitioner, RawPractitioner } from '../entities/Practitioner'; +import { ServerApplicationContext } from '@web-api/applicationContext'; -/** - * Create a new practitioner - * - * @param {object} providers the providers object - * @param {object} providers.applicationContext the application context - * @param {object} providers.user the user data - * @returns {object} new practitioner user - */ -export const createPractitionerUser = async ({ applicationContext, user }) => { +export const createPractitionerUser = async ( + applicationContext: ServerApplicationContext, + { user }: { user: RawPractitioner }, +): Promise => { const barNumber = user.barNumber || (await applicationContext.barNumberGenerator.createBarNumber({ diff --git a/shared/src/proxies/practitioners/createPractitionerUserProxy.ts b/shared/src/proxies/practitioners/createPractitionerUserProxy.ts index a5890811a3b..456a77d4658 100644 --- a/shared/src/proxies/practitioners/createPractitionerUserProxy.ts +++ b/shared/src/proxies/practitioners/createPractitionerUserProxy.ts @@ -1,17 +1,9 @@ import { post } from '../requests'; -/** - * createPractitionerUserInteractor - * - * @param {object} applicationContext the application context - * @param {object} providers the providers object - * @param {string} providers.user the user data - * @returns {Promise} the created user data - */ export const createPractitionerUserInteractor = ( applicationContext, { user }, -) => { +): Promise<{ barNumber: string }> => { return post({ applicationContext, body: { user }, diff --git a/shared/src/business/useCases/practitioners/createPractitionerUserInteractor.test.ts b/web-api/src/business/useCases/practitioner/createPractitionerUserInteractor.test.ts similarity index 55% rename from shared/src/business/useCases/practitioners/createPractitionerUserInteractor.test.ts rename to web-api/src/business/useCases/practitioner/createPractitionerUserInteractor.test.ts index eec9a09372d..4a581b0146d 100644 --- a/shared/src/business/useCases/practitioners/createPractitionerUserInteractor.test.ts +++ b/web-api/src/business/useCases/practitioner/createPractitionerUserInteractor.test.ts @@ -1,15 +1,21 @@ -import { ROLES, SERVICE_INDICATOR_TYPES } from '../../entities/EntityConstants'; +import { + ROLES, + SERVICE_INDICATOR_TYPES, +} from '../../../../../shared/src/business/entities/EntityConstants'; +import { RawPractitioner } from '@shared/business/entities/Practitioner'; import { UnauthorizedError } from '@web-api/errors/errors'; -import { applicationContext } from '../../test/createTestApplicationContext'; +import { admissionsClerkUser, petitionerUser } from '@shared/test/mockUsers'; +import { applicationContext } from '../../../../../shared/src/business/test/createTestApplicationContext'; import { createPractitionerUserInteractor } from './createPractitionerUserInteractor'; -describe('create practitioner user', () => { - const mockUser = { +describe('createPractitionerUserInteractor', () => { + const mockUser: RawPractitioner = { admissionsDate: '2019-03-01', admissionsStatus: 'Active', barNumber: 'AT5678', - birthYear: 2019, + birthYear: '2019', employer: 'Private', + entityName: 'Practitioner', firmName: 'GW Law Offices', firstName: 'bob', lastName: 'sagot', @@ -17,36 +23,19 @@ describe('create practitioner user', () => { originalBarState: 'IL', practitionerType: 'Attorney', role: ROLES.privatePractitioner, + serviceIndicator: SERVICE_INDICATOR_TYPES.SI_PAPER, userId: '07044afe-641b-4d75-a84f-0698870b7650', - } as any; - - let testUser; + }; beforeEach(() => { - testUser = { - role: ROLES.admissionsClerk, - userId: 'admissionsclerk', - }; - - applicationContext.environment.stage = 'local'; - applicationContext.getCurrentUser.mockImplementation(() => testUser); + applicationContext.getCurrentUser.mockReturnValue(admissionsClerkUser); applicationContext .getPersistenceGateway() - .createOrUpdatePractitionerUser.mockResolvedValue(mockUser); - }); - - it('creates the practitioner user', async () => { - const user = await createPractitionerUserInteractor(applicationContext, { - user: mockUser, - }); - expect(user).not.toBeUndefined(); + .createOrUpdatePractitionerUser.mockResolvedValue(({ user }) => user); }); - it('throws unauthorized for a non-internal user', async () => { - testUser = { - role: ROLES.petitioner, - userId: '6a2a8f95-0223-442e-8e55-5f094c6bca15', - }; + it('should throw an error when the user is unauthorized to create a practitioner user', async () => { + applicationContext.getCurrentUser.mockReturnValue(petitionerUser); await expect( createPractitionerUserInteractor(applicationContext, { @@ -55,6 +44,17 @@ describe('create practitioner user', () => { ).rejects.toThrow(UnauthorizedError); }); + it('should return the practitioner`s bar number', async () => { + const { barNumber } = await createPractitionerUserInteractor( + applicationContext, + { + user: mockUser, + }, + ); + + expect(barNumber).toEqual(mockUser.barNumber); + }); + it('should set practitioner.pendingEmail to practitioner.email and set practitioner.email to undefined', async () => { const mockEmail = 'testing@example.com'; @@ -68,7 +68,6 @@ describe('create practitioner user', () => { const mockUserCall = applicationContext.getPersistenceGateway().createOrUpdatePractitionerUser .mock.calls[0][0].user; - expect(mockUserCall.email).toBeUndefined(); expect(mockUserCall.pendingEmail).toEqual(mockEmail); expect(mockUserCall.serviceIndicator).toEqual( diff --git a/web-api/src/business/useCases/practitioner/createPractitionerUserInteractor.ts b/web-api/src/business/useCases/practitioner/createPractitionerUserInteractor.ts new file mode 100644 index 00000000000..42bda73d028 --- /dev/null +++ b/web-api/src/business/useCases/practitioner/createPractitionerUserInteractor.ts @@ -0,0 +1,35 @@ +import { + ROLE_PERMISSIONS, + isAuthorized, +} from '../../../../../shared/src/authorization/authorizationClientService'; +import { RawPractitioner } from '../../../../../shared/src/business/entities/Practitioner'; +import { ServerApplicationContext } from '@web-api/applicationContext'; +import { UnauthorizedError } from '@web-api/errors/errors'; +import { createPractitionerUser } from '../../../../../shared/src/business/utilities/createPractitionerUser'; + +export const createPractitionerUserInteractor = async ( + applicationContext: ServerApplicationContext, + { user }: { user: RawPractitioner }, +): Promise<{ barNumber: string }> => { + const requestUser = applicationContext.getCurrentUser(); + + if (!isAuthorized(requestUser, ROLE_PERMISSIONS.ADD_EDIT_PRACTITIONER_USER)) { + throw new UnauthorizedError('Unauthorized for creating practitioner user'); + } + + user.pendingEmail = user.email; + user.email = undefined; + + const practitioner = await createPractitionerUser(applicationContext, { + user, + }); + + const createdUser = await applicationContext + .getPersistenceGateway() + .createOrUpdatePractitionerUser({ + applicationContext, + user: practitioner, + }); + + return { barNumber: createdUser.barNumber }; +}; diff --git a/web-api/src/business/useCases/user/createUserInteractor.ts b/web-api/src/business/useCases/user/createUserInteractor.ts index 1739f3acd6c..ed1502de9ca 100644 --- a/web-api/src/business/useCases/user/createUserInteractor.ts +++ b/web-api/src/business/useCases/user/createUserInteractor.ts @@ -40,7 +40,9 @@ export const createUserInteractor = async ( user.role === ROLES.inactivePractitioner ) { userEntity = new Practitioner( - await createPractitionerUser({ applicationContext, user }), + await createPractitionerUser(applicationContext, { + user: user as RawPractitioner, + }), ); } else { if (user.barNumber === '') { diff --git a/web-api/src/getUseCases.ts b/web-api/src/getUseCases.ts index 2a67f325902..0919a758456 100644 --- a/web-api/src/getUseCases.ts +++ b/web-api/src/getUseCases.ts @@ -30,7 +30,7 @@ import { createCaseInteractor } from '../../shared/src/business/useCases/createC import { createCourtIssuedOrderPdfFromHtmlInteractor } from '../../shared/src/business/useCases/courtIssuedOrder/createCourtIssuedOrderPdfFromHtmlInteractor'; import { createMessageInteractor } from '../../shared/src/business/useCases/messages/createMessageInteractor'; import { createPractitionerDocumentInteractor } from '../../shared/src/business/useCases/practitioners/createPractitionerDocumentInteractor'; -import { createPractitionerUserInteractor } from '../../shared/src/business/useCases/practitioners/createPractitionerUserInteractor'; +import { createPractitionerUserInteractor } from './business/useCases/practitioner/createPractitionerUserInteractor'; import { createTrialSessionInteractor } from '../../shared/src/business/useCases/trialSessions/createTrialSessionInteractor'; import { createUserInteractor } from './business/useCases/user/createUserInteractor'; import { deleteCaseDeadlineInteractor } from '../../shared/src/business/useCases/caseDeadline/deleteCaseDeadlineInteractor'; diff --git a/web-client/src/presenter/actions/createPractitionerUserAction.test.ts b/web-client/src/presenter/actions/createPractitionerUserAction.test.ts index b48f7ca8f77..660122d8781 100644 --- a/web-client/src/presenter/actions/createPractitionerUserAction.test.ts +++ b/web-client/src/presenter/actions/createPractitionerUserAction.test.ts @@ -4,13 +4,10 @@ import { presenter } from '../presenter-mock'; import { runAction } from '@web-client/presenter/test.cerebral'; describe('createPractitionerUserAction', () => { - let successMock; - let errorMock; - - beforeAll(() => { - successMock = jest.fn(); - errorMock = jest.fn(); + const successMock = jest.fn(); + const errorMock = jest.fn(); + beforeEach(() => { presenter.providers.applicationContext = applicationContext; presenter.providers.path = { @@ -24,9 +21,6 @@ describe('createPractitionerUserAction', () => { modules: { presenter, }, - props: { - computedDate: '2019-03-01T21:40:46.415Z', - }, state: { form: { confirmEmail: 'something@example.com', @@ -42,7 +36,7 @@ describe('createPractitionerUserAction', () => { }); }); - it('should return path.success with a success message and practitioner information when the practitioner user was successfully created', async () => { + it('should return path.success with a success message and practitioner bar number when the practitioner user was successfully created', async () => { const mockPractitioner = { barNumber: 'AB1234', name: 'Donna Harking', @@ -56,9 +50,7 @@ describe('createPractitionerUserAction', () => { presenter, }, state: { - form: { - user: {}, - }, + form: {}, }, }); @@ -67,11 +59,10 @@ describe('createPractitionerUserAction', () => { message: 'Practitioner added.', }, barNumber: mockPractitioner.barNumber, - practitionerUser: mockPractitioner, }); }); - it('should return path.error when the practitioner to create is invalid', async () => { + it('should return path.error when an error occurred while creating the practitioner', async () => { applicationContext .getUseCases() .createPractitionerUserInteractor.mockImplementation(() => { @@ -83,13 +74,10 @@ describe('createPractitionerUserAction', () => { presenter, }, state: { - form: { - user: {}, - }, + form: {}, }, }); - expect(errorMock).toHaveBeenCalled(); expect(errorMock).toHaveBeenCalledWith({ alertError: { message: 'Please try again.', diff --git a/web-client/src/presenter/actions/createPractitionerUserAction.ts b/web-client/src/presenter/actions/createPractitionerUserAction.ts index 39d7bca666c..148b7a5021a 100644 --- a/web-client/src/presenter/actions/createPractitionerUserAction.ts +++ b/web-client/src/presenter/actions/createPractitionerUserAction.ts @@ -7,21 +7,18 @@ export const createPractitionerUserAction = async ({ }: ActionProps) => { const practitioner = get(state.form); - practitioner.confirmEmail = undefined; - try { - const practitionerUser = await applicationContext + const { barNumber } = await applicationContext .getUseCases() .createPractitionerUserInteractor(applicationContext, { - user: practitioner, + user: { ...practitioner, confirmEmail: undefined }, }); return path.success({ alertSuccess: { message: 'Practitioner added.', }, - barNumber: practitionerUser.barNumber, - practitionerUser, + barNumber, }); } catch (err) { return path.error({