From 559d31ad284863ae15fc550666eee871276b36e3 Mon Sep 17 00:00:00 2001 From: Dima K Date: Tue, 17 Oct 2023 16:39:27 -0400 Subject: [PATCH] Fix Home Owners error handling (#1585) * Fix Home Owners error handling * Fix validation for Sale Gift Transfer --- .../HomeOwners/HomeOwnersTable.vue | 9 +- .../mhrInformation/useTransferOwners.ts | 16 +++ .../views/newMhrRegistration/HomeOwners.vue | 4 +- ppr-ui/tests/unit/MhrInformation.spec.ts | 122 ++++++++++++------ .../tests/unit/MhrTransferHomeOwners.spec.ts | 7 +- 5 files changed, 116 insertions(+), 42 deletions(-) diff --git a/ppr-ui/src/components/mhrRegistration/HomeOwners/HomeOwnersTable.vue b/ppr-ui/src/components/mhrRegistration/HomeOwners/HomeOwnersTable.vue index 19edc85e3..9c816447b 100644 --- a/ppr-ui/src/components/mhrRegistration/HomeOwners/HomeOwnersTable.vue +++ b/ppr-ui/src/components/mhrRegistration/HomeOwners/HomeOwnersTable.vue @@ -630,8 +630,11 @@ export default defineComponent({ if (!props.validateTransfer || !localState.isValidAllocation) return false // check if group is not valid due to mixed owners or all removed owners - if (TransSaleOrGift.hasMixedOwnersInGroup(groupId) || - TransSaleOrGift.hasAllCurrentOwnersRemoved(groupId)) return true + if (isTransferDueToSaleOrGift.value && + (TransSaleOrGift.hasMixedOwnersInGroup(groupId) || + TransSaleOrGift.hasPartlyRemovedEATOwners(groupId) || + (TransSaleOrGift.hasAllCurrentOwnersRemoved(groupId) && !TransSaleOrGift.hasAddedOwners(groupId)) + )) return true if ((isTransferToExecutorProbateWill.value || isTransferToExecutorUnder25Will.value || @@ -833,7 +836,7 @@ export default defineComponent({ hasMinimumGroups() && localState.isValidAllocation && !localState.hasGroupsWithNoOwners && - (isTransferDueToSaleOrGift.value ? !TransSaleOrGift.hasMixedOwners.value : true) && + (isTransferDueToSaleOrGift.value ? TransSaleOrGift.isValidTransfer.value : true) && (isTransferToSurvivingJointTenant.value ? TransJointTenants.isValidTransfer.value : true) && ((isTransferToExecutorProbateWill.value || isTransferToExecutorUnder25Will.value) ? TransToExec.isValidTransfer.value : true) diff --git a/ppr-ui/src/composables/mhrInformation/useTransferOwners.ts b/ppr-ui/src/composables/mhrInformation/useTransferOwners.ts index 2661ed0e2..bab18fde4 100644 --- a/ppr-ui/src/composables/mhrInformation/useTransferOwners.ts +++ b/ppr-ui/src/composables/mhrInformation/useTransferOwners.ts @@ -318,6 +318,17 @@ export const useTransferOwners = (enableAllActions: boolean = false) => { // Transfer Due to Sale or Gift flow and all the related conditions/logic const TransSaleOrGift: any = { + isValidTransfer: computed((): boolean => { + const allGroupsValid = getMhrTransferHomeOwnerGroups.value.every(group => + TransSaleOrGift.isGroupValid(group.groupId)) + + return !TransSaleOrGift.hasMixedOwners && allGroupsValid + }), + isGroupValid: (groupId): boolean => { + return !(TransSaleOrGift.hasMixedOwnersInGroup(groupId) || + TransSaleOrGift.hasPartlyRemovedEATOwners(groupId) || + (TransSaleOrGift.hasAllCurrentOwnersRemoved(groupId) && !TransSaleOrGift.hasAddedOwners(groupId))) + }, hasMixedOwners: computed((): boolean => { return !getMhrTransferHomeOwnerGroups.value .every((group: MhrRegistrationHomeOwnerGroupIF) => @@ -356,6 +367,11 @@ export const useTransferOwners = (enableAllActions: boolean = false) => { .every(owner => isCurrentOwner(owner) ? owner.action === ActionTypes.REMOVED : owner.action === ActionTypes.ADDED) + }, + hasAddedOwners: (groupId): boolean => { + return getMhrTransferHomeOwnerGroups.value + .find(group => group.groupId === groupId) + .owners.some(owner => owner.action === ActionTypes.ADDED) } } diff --git a/ppr-ui/src/views/newMhrRegistration/HomeOwners.vue b/ppr-ui/src/views/newMhrRegistration/HomeOwners.vue index 94e9c7c74..b0ff5d222 100644 --- a/ppr-ui/src/views/newMhrRegistration/HomeOwners.vue +++ b/ppr-ui/src/views/newMhrRegistration/HomeOwners.vue @@ -129,7 +129,7 @@ - Nothing to delete + Nothing to delete @@ -153,7 +153,7 @@ Home Tenancy Type: {{ homeTenancyType }} Must include more than one group of owners diff --git a/ppr-ui/tests/unit/MhrInformation.spec.ts b/ppr-ui/tests/unit/MhrInformation.spec.ts index da0f2483f..339897647 100644 --- a/ppr-ui/tests/unit/MhrInformation.spec.ts +++ b/ppr-ui/tests/unit/MhrInformation.spec.ts @@ -38,9 +38,17 @@ import { mockedRegisteringParty1, mockedAccountInfo, mockedLockedMhRegistration, - mockedUnitNotes5 + mockedUnitNotes5, + mockedPerson2, + mockedExecutor, + mockedAdministrator } from './test-data' -import { CertifyIF, MhrRegistrationHomeOwnerGroupIF, MhrRegistrationHomeOwnerIF } from '@/interfaces' +import { + CertifyIF, + MhrRegistrationHomeOwnerGroupIF, + MhrRegistrationHomeOwnerIF, + TransferTypeSelectIF +} from '@/interfaces' import { TransferDetails, TransferDetailsReview, TransferType } from '@/components/mhrTransfers' import { defaultFlagSet, toDisplayPhone } from '@/utils' @@ -67,7 +75,7 @@ function createComponent (): Wrapper { }) document.body.setAttribute('data-app', 'true') - return mount((MhrInformation as any), { + return mount(MhrInformation as any, { localVue, store, propsData: { @@ -264,11 +272,13 @@ describe('Mhr Information', () => { }) it('should show correct Home Tenancy Type for MHR Transfers', async () => { - await store.setMhrTransferHomeOwnerGroups([{ - ...mockMhrTransferCurrentHomeOwner, - interestNumerator: null, - interestDenominator: null - }]) + await store.setMhrTransferHomeOwnerGroups([ + { + ...mockMhrTransferCurrentHomeOwner, + interestNumerator: null, + interestDenominator: null + } + ]) wrapper.vm.dataLoaded = true await nextTick() @@ -277,12 +287,9 @@ describe('Mhr Information', () => { const homeOwnersComponent = wrapper.findComponent(HomeOwners) as Wrapper expect(homeOwnersComponent.vm.getHomeOwners.length).toBe(1) - expect( - wrapper - .findComponent(HomeOwners) - .find(getTestId('home-owner-tenancy-type')) - .text() - ).toBe(HomeTenancyTypes.SOLE) + expect(wrapper.findComponent(HomeOwners).find(getTestId('home-owner-tenancy-type')).text()).toBe( + HomeTenancyTypes.SOLE + ) // Add a second Owner to the existing group homeOwnerGroup[0].owners.push(mockedOrganization) @@ -291,23 +298,17 @@ describe('Mhr Information', () => { await nextTick() expect(homeOwnersComponent.vm.getHomeOwners.length).toBe(2) - expect( - wrapper - .findComponent(HomeOwners) - .find(getTestId('home-owner-tenancy-type')) - .text() - ).toBe(HomeTenancyTypes.JOINT) + expect(wrapper.findComponent(HomeOwners).find(getTestId('home-owner-tenancy-type')).text()).toBe( + HomeTenancyTypes.JOINT + ) // Enable Groups homeOwnerGroup.push({ groupId: 2, owners: [mockedPerson], type: '' }) await nextTick() - expect( - wrapper - .findComponent(HomeOwners) - .find(getTestId('home-owner-tenancy-type')) - .text() - ).toBe(HomeTenancyTypes.COMMON) + expect(wrapper.findComponent(HomeOwners).find(getTestId('home-owner-tenancy-type')).text()).toBe( + HomeTenancyTypes.COMMON + ) }) it('should correctly show current and newly added Owner Groups', async () => { @@ -486,12 +487,7 @@ describe('Mhr Information', () => { await nextTick() // Check if Authorization renders in review mode - expect( - wrapper - .findComponent(MhrInformation) - .findComponent(CertifyInformation) - .exists() - ).toBe(true) + expect(wrapper.findComponent(MhrInformation).findComponent(CertifyInformation).exists()).toBe(true) // Check for component's attributes const authorizationComponent = wrapper.findComponent(CertifyInformation) @@ -721,7 +717,7 @@ describe('Mhr Information', () => { await store.setMhrTransferType({ transferType: ApiTransferTypes.SALE_OR_GIFT, textLabel: UITransferTypes.SALE_OR_GIFT - }) + } as TransferTypeSelectIF) await wrapper.find('#btn-stacked-submit').trigger('click') await nextTick() @@ -753,6 +749,61 @@ describe('Mhr Information', () => { await store.setAuthRoles([AuthRoles.MHR]) }) + it('SALE OR GIFT Flow: should correctly validate all fields', async () => { + const homeOwnerGroups: MhrRegistrationHomeOwnerGroupIF[] = [ + { + groupId: 1, + interest: 'Undivided', + interestNumerator: 1, + interestDenominator: 2, + owners: [mockedExecutor, mockedAdministrator], + type: '' + }, + { + groupId: 2, + interest: 'Undivided', + interestNumerator: 1, + interestDenominator: 2, + owners: [mockedPerson2, mockedOrganization], + type: '' + } + ] + + await store.setMhrTransferCurrentHomeOwnerGroups(homeOwnerGroups) + await store.setMhrTransferHomeOwnerGroups(homeOwnerGroups) + await store.setMhrTransferType({ transferType: ApiTransferTypes.SALE_OR_GIFT } as TransferTypeSelectIF) + await store.setMhrTransferDocumentId('12345678') + + wrapper.vm.dataLoaded = true + wrapper.vm.showTransferType = true + await nextTick() + + // should be no errors on the page + expect(wrapper.findAll('.error-text')).toHaveLength(0) + expect(wrapper.findAll('.border-left-error')).toHaveLength(0) + + expect(wrapper.findComponent(TransferDetails).exists()).toBeFalsy() + + await enterTransferTypeFields(wrapper.findComponent(TransferType)) + + await wrapper.find(HomeOwners).findAll(getTestId('table-delete-btn')).at(0).trigger('click') + await nextTick() + + // should show group error because we removed one Executor + expect(wrapper.findAll('.error-text')).toHaveLength(1) + expect(wrapper.find(getTestId('invalid-group-msg')).exists()).toBeTruthy() + + await enterTransferDetailsFields(wrapper.findComponent(TransferDetails)) + await wrapper.find('#btn-stacked-submit').trigger('click') + await nextTick() + + // make sure we are still on Mhr Information page due to the error in the table + expect(wrapper.find('#mhr-information-header').text()).toContain('Manufactured Home Information') + expect(wrapper.find(HomeOwners).props().isReadonlyTable).toBe(false) + // should be three border errors, for: error message itself, owner 1 and owner 2 + expect(wrapper.findAll('.border-error-left').length).toBe(3) + }) + it('SURVIVING JOINT TENANT Flow: display correct Confirm Completion sections', async () => { setupCurrentHomeOwners() wrapper.vm.dataLoaded = true @@ -773,7 +824,7 @@ describe('Mhr Information', () => { await store.setMhrTransferType({ transferType: ApiTransferTypes.SURVIVING_JOINT_TENANT, textLabel: UITransferTypes.SURVIVING_JOINT_TENANT - }) + } as TransferTypeSelectIF) await wrapper.find('#btn-stacked-submit').trigger('click') await nextTick() @@ -815,7 +866,7 @@ describe('Mhr Information', () => { await store.setMhrTransferType({ transferType: ApiTransferTypes.TO_EXECUTOR_PROBATE_WILL, textLabel: UITransferTypes.TO_EXECUTOR_PROBATE_WILL - }) + } as TransferTypeSelectIF) await wrapper.find('#btn-stacked-submit').trigger('click') await nextTick() @@ -854,7 +905,6 @@ describe('Mhr Information', () => { const homeOwnersComponent: Wrapper = wrapper.findComponent(HomeOwners) await store.setMhrTransferHomeOwnerGroups(homeOwnerGroup) expect(homeOwnersComponent.findComponent(HomeOwnersTable).exists()).toBeTruthy() - const ownersTable = homeOwnersComponent.findComponent(HomeOwnersTable) // check owners are in table expect(homeOwnersComponent.vm.getHomeOwners.length).toBe(2) diff --git a/ppr-ui/tests/unit/MhrTransferHomeOwners.spec.ts b/ppr-ui/tests/unit/MhrTransferHomeOwners.spec.ts index a3e240cfd..e1d6cadea 100644 --- a/ppr-ui/tests/unit/MhrTransferHomeOwners.spec.ts +++ b/ppr-ui/tests/unit/MhrTransferHomeOwners.spec.ts @@ -494,7 +494,7 @@ describe('Home Owners', () => { expect(homeOwnersTable.find(getTestId('invalid-group-msg')).exists()).toBeFalsy() // should show all Delete buttons in the table const allDeleteButtons = homeOwnersTable.findAll(getTestId('table-delete-btn')) - expect(allDeleteButtons).toHaveLength(homeOwnerGroup[0].owners.length) + expect(allDeleteButtons).toHaveLength(homeOwnerGroup[0].owners.length) // should be two Delete buttons // delete first owner which is Executor allDeleteButtons.at(0).trigger('click') @@ -503,6 +503,11 @@ describe('Home Owners', () => { expect(homeOwnersTable.find(getTestId('invalid-group-msg')).exists()).toBeTruthy() expect(homeOwnersTable.find(getTestId('invalid-group-msg')).text()) .toContain(transfersErrors.eatOwnersMustBeDeleted) + + expect(homeOwnersTable.findAll('.border-error-left')).toHaveLength(0) + await wrapper.setProps({ validateTransfer: true }) + // should be three border errors, for: error message itself, owner 1 and owner 2 + expect(homeOwnersTable.findAll('.border-error-left')).toHaveLength(3) }) it('TRANS SALE GIFT + Unit Note: renders Home Owners table buttons when Confidential Note filed', async () => {