Skip to content

Commit

Permalink
18641 More unit tests (bcgov#618)
Browse files Browse the repository at this point in the history
* - app version = 5.6.32
- added Amalgamation Mixin unit tests
- updated some status messages (per Yui)
- updated some rules (per Yui)
- added more Business Table unit tests (disabled until future)
- misc updates

* - added missing rule to list

---------

Co-authored-by: Severin Beauvais <severin.beauvais@gov.bc.ca>
2 people authored and JazzarKarim committed Jan 26, 2024
1 parent d764048 commit 073ae7f
Showing 10 changed files with 360 additions and 22 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "business-create-ui",
"version": "5.6.31",
"version": "5.6.32",
"private": true,
"appName": "Create UI",
"sbcName": "SBC Common Components",
7 changes: 3 additions & 4 deletions src/components/Amalgamation/BusinessStatus.vue
Original file line number Diff line number Diff line change
@@ -58,16 +58,15 @@ export default class BusinessStatus extends Vue {
'Form Horizontal amalgamation. '
case AmlStatuses.ERROR_FOREIGN_UNLIMITED:
return 'A foreign corporation must not amalgamate with a limited company and continue as ' +
'an Unlimited Liability Company.'
return 'A foreign corporation must not amalgamate with a BC Company and continue as an ' +
'Unlimited Liability Company.'
case AmlStatuses.ERROR_FOREIGN_UNLIMITED2:
return 'A BC Company cannot amalgamate with an existing foreign corporation to form a BC ' +
'Unlimited Liability Company.'
case AmlStatuses.ERROR_FOREIGN_UNLIMITED3:
return 'A BC Company cannot amalgamate with a foreign company to form a BC Unlimited ' +
'Liability Company.'
return 'A BC Unlimited Liability Company cannot amalgamate with a foreign company.'
case AmlStatuses.ERROR_FUTURE_EFFECTIVE_FILING:
return 'This business has a future effective filing. It cannot be part of an amalgamation ' +
4 changes: 2 additions & 2 deletions src/mixin-tester.vue
Original file line number Diff line number Diff line change
@@ -4,10 +4,10 @@

<script lang="ts">
import { Component, Mixins } from 'vue-property-decorator'
import { DateMixin, FilingTemplateMixin } from '@/mixins'
import { AmalgamationMixin, DateMixin, FilingTemplateMixin } from '@/mixins'
@Component({})
export default class MixinTester extends Mixins(DateMixin, FilingTemplateMixin) {}
export default class MixinTester extends Mixins(AmalgamationMixin, DateMixin, FilingTemplateMixin) {}
</script>

<style>
18 changes: 12 additions & 6 deletions src/mixins/amalgamation-mixin.ts
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ export default class AmalgamationMixin extends Vue {

@Action(useStore) setAmalgamatingBusinesses!: (x: Array<any>) => void

/** Iterable array of rule functions, sorted by importance. */
/** Iterable array of rule functions, in order of processing. */
readonly rules = [
this.notAffiliated,
this.notHistorical,
@@ -33,6 +33,7 @@ export default class AmalgamationMixin extends Vue {
this.cccMismatch,
this.foreignUnlimited2,
this.xproUlcCcc,
this.foreignUnlimited3,
this.needBcCompany,
this.foreignHorizontal
]
@@ -91,9 +92,9 @@ export default class AmalgamationMixin extends Vue {
return null
}

/** Disallow if foreign into ULC if there is also a limited company. */
/** Disallow if foreign and there is also a BC company, into ULC. */
foreignUnlimited (business: AmalgamatingBusinessIF): AmlStatuses {
if (business.type === AmlTypes.FOREIGN && this.isTypeBcUlcCompany && this.isAnyLimited) {
if (business.type === AmlTypes.FOREIGN && this.isAnyBcCompany && this.isTypeBcUlcCompany) {
return AmlStatuses.ERROR_FOREIGN_UNLIMITED
}
return null
@@ -107,9 +108,14 @@ export default class AmalgamationMixin extends Vue {
return null
}

/** Disallow if foreign into ULC if there is also a limited company. */
/** Disallow if BC and there is also a foreign, into ULC. */
foreignUnlimited2 (business: AmalgamatingBusinessIF): AmlStatuses {
if (business.type === AmlTypes.FOREIGN && this.isTypeBcUlcCompany && this.isAnyLimited) {
if (
business.type === AmlTypes.LEAR &&
business.legalType === CorpTypeCd.BC_COMPANY &&
this.isAnyForeign &&
this.isTypeBcUlcCompany
) {
return AmlStatuses.ERROR_FOREIGN_UNLIMITED2
}
return null
@@ -138,7 +144,7 @@ export default class AmalgamationMixin extends Vue {
return null
}

/** Disallow if there are no BC Companies. */
/** Disallow if there are no BC companies. */
needBcCompany (): AmlStatuses {
if (!this.isAnyBcCompany) {
return AmlStatuses.ERROR_NEED_BC_COMPANY
4 changes: 2 additions & 2 deletions tests/unit/BusinessStatus.spec.ts
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@ describe('Business Status', () => {
{
label: 'Error Foreign Unlimited',
status: AmlStatuses.ERROR_FOREIGN_UNLIMITED,
tooltip: 'A foreign corporation must not amalgamate with a limited company and continue as'
tooltip: 'A foreign corporation must not amalgamate with a BC Company and continue as an'
},
{
label: 'Error Foreign Unlimited 2',
@@ -37,7 +37,7 @@ describe('Business Status', () => {
{
label: 'Error Foreign Unlimited 3',
status: AmlStatuses.ERROR_FOREIGN_UNLIMITED3,
tooltip: 'A BC Company cannot amalgamate with a foreign company to form a BC Unlimited'
tooltip: 'A BC Unlimited Liability Company cannot amalgamate with a foreign company.'
},
{
label: 'Error Future Effective Filing',
81 changes: 79 additions & 2 deletions tests/unit/BusinessTable.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { AmlRoles, AmlTypes } from '@/enums'
import { AmlRoles, AmlStatuses, AmlTypes } from '@/enums'
import { wrapperFactory } from '../vitest-wrapper-factory'
import BusinessTable from '@/components/Amalgamation/BusinessTable.vue'
import { CorpTypeCd } from '@bcrs-shared-components/corp-type-module'
import AmalgamationMixin from '@/mixins/amalgamation-mixin'

describe('Business Table', () => {
describe('Business Table - display', () => {
it('displays correctly when there are no amalgamating businesses', () => {
const wrapper = wrapperFactory(
BusinessTable,
@@ -167,3 +168,79 @@ describe('Business Table', () => {
})
}
})

// *** FUTURE: get this working
// ATM, local rules are mocked (eg, wrapper.vm.notAffiliated()), but not the actual rules in the mixin.
// It's probably this: https://vitest.dev/guide/mocking.html#mocking-pitfalls.
// Maybe try vi.mock() to mock the imported mixin?
describe.skip('Business Table - rule evaluation', () => {
let wrapper: any

const rules = [
{ methodName: 'notAffiliated', error: AmlStatuses.ERROR_NOT_AFFILIATED },
{ methodName: 'notHistorical', error: AmlStatuses.ERROR_HISTORICAL },
{ methodName: 'notInGoodStanding', error: AmlStatuses.ERROR_NOT_IN_GOOD_STANDING },
{ methodName: 'limitedRestoration', error: AmlStatuses.ERROR_LIMITED_RESTORATION },
{ methodName: 'futureEffectiveFiling', error: AmlStatuses.ERROR_FUTURE_EFFECTIVE_FILING },
{ methodName: 'foreign', error: AmlStatuses.ERROR_FOREIGN },
{ methodName: 'foreignUnlimited', error: AmlStatuses.ERROR_FOREIGN_UNLIMITED },
{ methodName: 'cccMismatch', error: AmlStatuses.ERROR_CCC_MISMATCH },
{ methodName: 'foreignUnlimited2', error: AmlStatuses.ERROR_FOREIGN_UNLIMITED2 },
{ methodName: 'xproUlcCcc', error: AmlStatuses.ERROR_XPRO_ULC_CCC },
{ methodName: 'needBcCompany', error: AmlStatuses.ERROR_NEED_BC_COMPANY },
{ methodName: 'foreignHorizontal', error: AmlStatuses.ERROR_FOREIGN_HORIZONTAL }
]

beforeAll(() => {
wrapper = wrapperFactory(
BusinessTable,
null,
{
amalgamation: {
amalgamatingBusinesses: [{ /* dummy business */ }]
},
tombstone: {
keycloakRoles: ['staff']
}
}
)

// mock all rules to return their error
for (let i = 0; i < rules.length; i++) {
vi.spyOn(wrapper.vm, rules[i].methodName).mockReturnValue(rules[i].error)
}
// *** these work
console.log('*** value1 = ', wrapper.vm.notAffiliated())
console.log('*** value2 = ', wrapper.vm.notHistorical())
console.log('*** value3 = ', wrapper.vm.notInGoodStanding())

// *** this doesn't work ("is not a function")
console.log('*** value4 = ', (AmalgamationMixin as any).notAffiliated())
})

it('has the expected number of rules', () => {
expect(wrapper.vm.rules.length).toBe(rules.length)
})

// check each rule sequentially
for (let i = 0; i < rules.length; i++) {
it.skip(`fails rule "${rules[i].methodName}"`, () => {
// first, verify that current rule fails
expect(wrapper.vm.businesses[0].status).toBe(rules[i].error)

// now override rule to return null
vi.spyOn(wrapper.vm, rules[i].methodName).mockReturnValue(null)

// if this is the last rule...
if (i === (rules.length - 1)) {
// verify that no rules have failed
expect(wrapper.vm.businesses[0].status).toBe(AmlStatuses.OK)
} else {
// verify that another rule has failed
expect(wrapper.vm.businesses[0].status).toBe(rules[i + 1].error)
}

wrapper.destroy()
})
}
})
251 changes: 251 additions & 0 deletions tests/unit/amalgamation-mixin.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,251 @@
/* eslint-disable max-len */
import { wrapperFactory } from '../vitest-wrapper-factory'
import MixinTester from '@/mixin-tester.vue'
import { createPinia, setActivePinia } from 'pinia'
import { useStore } from '@/store/store'
import { AmalgamationTypes, AmlStatuses, AmlTypes } from '@/enums'
import { CorpTypeCd } from '@bcrs-shared-components/corp-type-module'

setActivePinia(createPinia())
const store = useStore()

describe('Amalgamation Mixin - rules', () => {
let wrapper: any

beforeEach(() => {
wrapper = wrapperFactory(MixinTester)
})

afterEach(() => {
wrapper.destroy()
})

it('correctly evaluates "notAffiliated" rule', () => {
// init
store.setKeycloakRoles([])

// verify rule
expect(wrapper.vm.notAffiliated({ type: AmlTypes.LEAR, address: null })).toBe(AmlStatuses.ERROR_NOT_AFFILIATED)

// verify staff only
store.setKeycloakRoles(['staff'])
expect(wrapper.vm.notAffiliated({ type: AmlTypes.LEAR, address: null })).toBeNull()
store.setKeycloakRoles([])

// verify not LEAR only
expect(wrapper.vm.notAffiliated({ type: AmlTypes.FOREIGN, address: null })).toBeNull()

// verify address exists only
expect(wrapper.vm.notAffiliated({ type: AmlTypes.LEAR, address: {} })).toBeNull()
})

it('correctly evaluates "notHistorical" rule', () => {
// verify rule
expect(wrapper.vm.notHistorical({ type: AmlTypes.LEAR, isHistorical: true })).toBe(AmlStatuses.ERROR_HISTORICAL)

// verify not LEAR only
expect(wrapper.vm.notHistorical({ type: AmlTypes.FOREIGN, isHistorical: true })).toBeNull()

// verify not historical only
expect(wrapper.vm.notHistorical({ type: AmlTypes.LEAR, isHistorical: false })).toBeNull()
})

it('correctly evaluates "notInGoodStanding" rule', () => {
// init
store.setKeycloakRoles([])

// verify rule
expect(wrapper.vm.notInGoodStanding({ type: AmlTypes.LEAR, isNotInGoodStanding: true })).toBe(AmlStatuses.ERROR_NOT_IN_GOOD_STANDING)

// verify staff only
store.setKeycloakRoles(['staff'])
expect(wrapper.vm.notInGoodStanding({ type: AmlTypes.LEAR, isNotInGoodStanding: null })).toBeNull()
store.setKeycloakRoles([])

// verify not LEAR only
expect(wrapper.vm.notInGoodStanding({ type: AmlTypes.FOREIGN, isNotInGoodStanding: true })).toBeNull()

// verify not good standing only
expect(wrapper.vm.notInGoodStanding({ type: AmlTypes.LEAR, isNotInGoodStanding: false })).toBeNull()
})

it('correctly evaluates "limitedRestoration" rule', () => {
// init
store.setKeycloakRoles([])

// verify rule
expect(wrapper.vm.limitedRestoration({ type: AmlTypes.LEAR, isLimitedRestoration: true })).toBe(AmlStatuses.ERROR_LIMITED_RESTORATION)

// verify staff only
store.setKeycloakRoles(['staff'])
expect(wrapper.vm.limitedRestoration({ type: AmlTypes.LEAR, isLimitedRestoration: null })).toBeNull()
store.setKeycloakRoles([])

// verify not LEAR only
expect(wrapper.vm.limitedRestoration({ type: AmlTypes.FOREIGN, isLimitedRestoration: true })).toBeNull()

// verify not limited restoration only
expect(wrapper.vm.limitedRestoration({ type: AmlTypes.LEAR, isLimitedRestoration: false })).toBeNull()
})

it('correctly evaluates "futureEffectiveFiling" rule', () => {
// verify rule
expect(wrapper.vm.futureEffectiveFiling({ type: AmlTypes.LEAR, isFutureEffective: true })).toBe(AmlStatuses.ERROR_FUTURE_EFFECTIVE_FILING)

// verify not LEAR only
expect(wrapper.vm.futureEffectiveFiling({ type: AmlTypes.FOREIGN, isFutureEffective: true })).toBeNull()

// verify not future effective only
expect(wrapper.vm.futureEffectiveFiling({ type: AmlTypes.LEAR, isFutureEffective: false })).toBeNull()
})

it('correctly evaluates "foreign" rule', () => {
// init
store.setKeycloakRoles([])

// verify rule
expect(wrapper.vm.foreign({ type: AmlTypes.FOREIGN })).toBe(AmlStatuses.ERROR_FOREIGN)

// verify staff only
store.setKeycloakRoles(['staff'])
expect(wrapper.vm.foreign({ type: AmlTypes.FOREIGN })).toBeNull()
store.setKeycloakRoles([])

// verify not FOREIGN only
expect(wrapper.vm.foreign({ type: AmlTypes.LEAR })).toBeNull()
})

it('correctly evaluates "foreignUnlimited" rule', () => {
// init
vi.spyOn(wrapper.vm, 'isAnyBcCompany', 'get').mockReturnValue(true)
store.setEntityType(CorpTypeCd.BC_ULC_COMPANY)

// verify rule
expect(wrapper.vm.foreignUnlimited({ type: AmlTypes.FOREIGN })).toBe(AmlStatuses.ERROR_FOREIGN_UNLIMITED)

// verify not FOREIGN only
expect(wrapper.vm.foreignUnlimited({ type: AmlTypes.LEAR })).toBeNull()

// verify not any BC company only
vi.spyOn(wrapper.vm, 'isAnyBcCompany', 'get').mockReturnValue(false)
expect(wrapper.vm.foreignUnlimited({ type: AmlTypes.FOREIGN })).toBeNull()
vi.spyOn(wrapper.vm, 'isAnyBcCompany', 'get').mockReturnValue(true)

// verify not ULC only
store.setEntityType(null)
expect(wrapper.vm.foreignUnlimited({ type: AmlTypes.FOREIGN })).toBeNull()
store.setEntityType(CorpTypeCd.BC_ULC_COMPANY)
})

it('correctly evaluates "cccMismatch" rule', () => {
// init
store.setEntityType(null)

// verify rule
expect(wrapper.vm.cccMismatch({ type: AmlTypes.LEAR, legalType: CorpTypeCd.BC_CCC })).toBe(AmlStatuses.ERROR_CCC_MISMATCH)

// verify not LEAR only
expect(wrapper.vm.cccMismatch({ type: AmlTypes.FOREIGN, legalType: CorpTypeCd.BC_CCC })).toBeNull()

// verify not legalType only
expect(wrapper.vm.cccMismatch({ type: AmlTypes.LEAR, legalType: null })).toBeNull()

// verify not CCC only
store.setEntityType(CorpTypeCd.BC_CCC)
expect(wrapper.vm.cccMismatch({ type: AmlTypes.LEAR, legalType: CorpTypeCd.BC_CCC })).toBeNull()
})

it('correctly evaluates "foreignUnlimited2" rule', () => {
// init
vi.spyOn(wrapper.vm, 'isAnyForeign', 'get').mockReturnValue(true)
store.setEntityType(CorpTypeCd.BC_ULC_COMPANY)

// verify rule
expect(wrapper.vm.foreignUnlimited2({ type: AmlTypes.LEAR, legalType: CorpTypeCd.BC_COMPANY })).toBe(AmlStatuses.ERROR_FOREIGN_UNLIMITED2)

// verify not LEAR only
expect(wrapper.vm.foreignUnlimited2({ type: AmlTypes.FOREIGN, legalType: CorpTypeCd.BC_COMPANY })).toBeNull()

// verify not legalType only
expect(wrapper.vm.foreignUnlimited2({ type: AmlTypes.LEAR, legalType: null })).toBeNull()

// verify not ULC only
store.setEntityType(null)
expect(wrapper.vm.foreignUnlimited2({ type: AmlTypes.LEAR, legalType: CorpTypeCd.BC_COMPANY })).toBeNull()
})

it('correctly evaluates "xproUlcCcc" rule - for ULC', () => {
// init
store.setEntityType(CorpTypeCd.BC_ULC_COMPANY)

// verify rule
expect(wrapper.vm.xproUlcCcc({ type: AmlTypes.FOREIGN })).toBe(AmlStatuses.ERROR_XPRO_ULC_CCC)

// verify not FOREIGN only
expect(wrapper.vm.xproUlcCcc({ type: AmlTypes.LEAR })).toBeNull()

// verify not ULC or CCC only
store.setEntityType(null)
expect(wrapper.vm.xproUlcCcc({ type: AmlTypes.FOREIGN })).toBeNull()
})

it('correctly evaluates "xproUlcCcc" rule - for CCC', () => {
// init
store.setEntityType(CorpTypeCd.BC_CCC)

// verify rule
expect(wrapper.vm.xproUlcCcc({ type: AmlTypes.FOREIGN })).toBe(AmlStatuses.ERROR_XPRO_ULC_CCC)

// verify not FOREIGN only
expect(wrapper.vm.xproUlcCcc({ type: AmlTypes.LEAR })).toBeNull()

// verify not ULC or CCC only
store.setEntityType(null)
expect(wrapper.vm.xproUlcCcc({ type: AmlTypes.FOREIGN })).toBeNull()
})

it('correctly evaluates "foreignUnlimited3" rule', () => {
// init
vi.spyOn(wrapper.vm, 'isAnyForeign', 'get').mockReturnValue(true)

// verify rule
expect(wrapper.vm.foreignUnlimited3({ type: AmlTypes.LEAR, legalType: CorpTypeCd.BC_ULC_COMPANY })).toBe(AmlStatuses.ERROR_FOREIGN_UNLIMITED3)

// verify not LEAR only
expect(wrapper.vm.foreignUnlimited3({ type: AmlTypes.FOREIGN, legalType: CorpTypeCd.BC_ULC_COMPANY })).toBeNull()

// verify not legalType only
expect(wrapper.vm.foreignUnlimited3({ type: AmlTypes.LEAR, legalType: null })).toBeNull()

// verify not foreign only
vi.spyOn(wrapper.vm, 'isAnyForeign', 'get').mockReturnValue(false)
expect(wrapper.vm.foreignUnlimited3({ type: AmlTypes.LEAR, legalType: CorpTypeCd.BC_ULC_COMPANY })).toBeNull()
})

it('correctly evaluates "needBcCompany" rule', () => {
// init
vi.spyOn(wrapper.vm, 'isAnyBcCompany', 'get').mockReturnValue(false)

// verify rule
expect(wrapper.vm.needBcCompany()).toBe(AmlStatuses.ERROR_NEED_BC_COMPANY)

// verify not BC company only
vi.spyOn(wrapper.vm, 'isAnyBcCompany', 'get').mockReturnValue(true)
expect(wrapper.vm.needBcCompany()).toBeNull()
})

it('correctly evaluates "foreignHorizontal" rule', () => {
// init
store.setAmalgamationType(AmalgamationTypes.HORIZONTAL)

// verify rule
expect(wrapper.vm.foreignHorizontal({ type: AmlTypes.FOREIGN })).toBe(AmlStatuses.ERROR_FOREIGN_HORIZONTAL)

// verify not FOREIGN only
expect(wrapper.vm.foreignHorizontal({ type: AmlTypes.LEAR })).toBeNull()

// verify not horizontal only
store.setAmalgamationType(null)
expect(wrapper.vm.foreignHorizontal({ type: AmlTypes.FOREIGN })).toBeNull()
})
})
2 changes: 1 addition & 1 deletion tests/unit/filing-template-mixin.spec.ts
Original file line number Diff line number Diff line change
@@ -82,7 +82,7 @@ describe('Registration Filing', () => {
naicsDescription: 'Some NAICS Description'
}
store.stateModel.nameRequest = {
legalType: CorpTypeCd.SOLE_PROP,
legalType: CorpTypeCd.SOLE_PROP as any,
nrNum: 'NR 1234567'
} as NameRequestIF

9 changes: 7 additions & 2 deletions tests/vitest-wrapper-factory.ts
Original file line number Diff line number Diff line change
@@ -38,9 +38,11 @@ export const shallowWrapperFactory = (
) => {
setActivePinia(createPinia())
const store = useStore()

if (routeName) router.push({ name: routeName }).catch(() => {})

if (stateValues) applyStoreValues(store, stateValues, resource)

return shallowMount(component, {
propsData: {
...propsData
@@ -61,8 +63,11 @@ export const wrapperFactory = (
) => {
setActivePinia(createPinia())
const store = useStore()

if (routeName) router.push({ name: routeName }).catch(() => {})

if (stateValues) applyStoreValues(store, stateValues, resource)

return mount(component, {
propsData: {
...propsData
@@ -74,9 +79,9 @@ export const wrapperFactory = (
})
}

const applyStoreValues = (store, stateValues, resource = null) => {
const applyStoreValues = (store, stateValues, resource) => {
resource = resource || IncorporationResources
// Set Company Resources
// Set Company Resources (even if not needed)
store.resourceModel = resource.find(x => x.entityType === stateValues.entityType)

// Set individual state properties

0 comments on commit 073ae7f

Please sign in to comment.