From ecfe54e99e31f2d43c923a77aa271978f90abc43 Mon Sep 17 00:00:00 2001 From: Kial Jinnah Date: Fri, 24 Jul 2026 16:22:28 -0400 Subject: [PATCH 1/7] 34225 - numbered incorp launcher implemented with placeholder help me choose dialog Signed-off-by: Kial Jinnah --- app/src/App.vue | 4 +- app/src/components/dialogs/index.ts | 1 + .../dialogs/numbered-company-help.vue | 51 ++++++ .../numbered-company-bullets.vue | 15 +- app/src/components/new-request/search.vue | 82 +++++++++ app/src/interfaces/new-request-interface.ts | 1 + app/src/mixins/common-mixin.ts | 5 + app/src/plugins/launchDarkly.ts | 1 + app/src/store/actions.ts | 4 + app/src/store/getters.ts | 4 + app/src/store/mutations.ts | 4 + app/src/store/state.ts | 1 + .../dialogs/numbered-company-help.spec.ts | 56 ++++++ .../unit/numbered-company-bullets.spec.ts | 45 +++++ app/tests/unit/search.spec.ts | 163 +++++++++++++++++- 15 files changed, 431 insertions(+), 6 deletions(-) create mode 100644 app/src/components/dialogs/numbered-company-help.vue create mode 100644 app/tests/unit/dialogs/numbered-company-help.spec.ts create mode 100644 app/tests/unit/numbered-company-bullets.spec.ts diff --git a/app/src/App.vue b/app/src/App.vue index 73ffbc930..4e7813ee6 100644 --- a/app/src/App.vue +++ b/app/src/App.vue @@ -95,6 +95,7 @@ /> + @@ -131,7 +132,7 @@ import { Breadcrumb } from '@/components/common' import GenesysWebMessage from '@bcrs-shared-components/genesys-web-message/GenesysWebMessage.vue' import { WebChat as ChatPopup } from '@bcrs-shared-components/web-chat' import { AffiliationErrorDialog, CancelDialog, ConditionsDialog, ErrorDialog, ExitDialog, - HelpMeChooseDialog, MrasSearchInfoDialog, NrNotRequiredDialog, CreateBusinessErrorDialog, + HelpMeChooseDialog, MrasSearchInfoDialog, NrNotRequiredDialog, NumberedCompanyHelpDialog, CreateBusinessErrorDialog, ConfirmNrDialog, PaymentCompleteDialog, PickEntityOrConversionDialog, RenewDialog, ReceiptsDialog, RefundDialog, ResubmitDialog, RetryDialog, StaffPaymentErrorDialog, UpgradeDialog, ExitIncompletePaymentDialog } from '@/components/dialogs' @@ -158,6 +159,7 @@ import { CorpTypeCd } from '@bcrs-shared-components/corp-type-module' HelpMeChooseDialog, MrasSearchInfoDialog, NrNotRequiredDialog, + NumberedCompanyHelpDialog, PaymentCompleteDialog, PickEntityOrConversionDialog, ReceiptsDialog, diff --git a/app/src/components/dialogs/index.ts b/app/src/components/dialogs/index.ts index 1601a9e38..d1eb3dc92 100644 --- a/app/src/components/dialogs/index.ts +++ b/app/src/components/dialogs/index.ts @@ -9,6 +9,7 @@ export { default as ExitIncompletePaymentDialog } from './exit-incomplete-paymen export { default as HelpMeChooseDialog } from './help-me-choose.vue' export { default as MrasSearchInfoDialog } from './mras-search-info.vue' export { default as NrNotRequiredDialog } from './nr-not-required.vue' +export { default as NumberedCompanyHelpDialog } from './numbered-company-help.vue' export { default as PaymentCompleteDialog } from './payment-complete.vue' export { default as PickEntityOrConversionDialog } from './pick-entity-or-conversion.vue' export { default as ReceiptsDialog } from './receipts.vue' diff --git a/app/src/components/dialogs/numbered-company-help.vue b/app/src/components/dialogs/numbered-company-help.vue new file mode 100644 index 000000000..df4395929 --- /dev/null +++ b/app/src/components/dialogs/numbered-company-help.vue @@ -0,0 +1,51 @@ + + + + + diff --git a/app/src/components/new-request/search-components/numbered-company-bullets.vue b/app/src/components/new-request/search-components/numbered-company-bullets.vue index 3782e28ad..39373db00 100644 --- a/app/src/components/new-request/search-components/numbered-company-bullets.vue +++ b/app/src/components/new-request/search-components/numbered-company-bullets.vue @@ -29,7 +29,20 @@ + + + diff --git a/app/src/components/new-request/search.vue b/app/src/components/new-request/search.vue index 969d6c6e5..af728489d 100644 --- a/app/src/components/new-request/search.vue +++ b/app/src/components/new-request/search.vue @@ -471,7 +471,6 @@ import SocietiesInfo from '@/components/dialogs/societies-info-dialog.vue' import { AuthorizedActions, EntityTypes } from '@/enums' import { CommonMixin, NrAffiliationMixin, SearchMixin } from '@/mixins' import { Designations, XproMapping } from '@/list-data' -import { Navigate } from '@/plugins' import { ActionBindingIF } from '@/interfaces/store-interfaces' import { Action, Getter } from 'pinia-class' import { useStore } from '@/store' @@ -832,30 +831,6 @@ export default class Search extends Mixins(CommonMixin, NrAffiliationMixin, Sear return (this.getHasNoCorpNum && !this.isValidXproName) || (!this.getHasNoCorpNum && !this.corpNumValid) } - /** - * If user is authenticated, create draft business and redirect to Dashboard. - * If restoration/reinstatement selected, go to business dashboard. - * If user is not authenticated, redirect to login screen then redirect back. - */ - async actionNowClicked () { - const legalType = this.entityTypeToCorpType(this.getEntityTypeCd) - if (this.isAuthenticated) { - if (this.isConversion || this.isRestoration || this.isChangeName) { - this.goToEntityDashboard(this.getSearchBusiness.identifier) - } else { - await this.actionNumberedEntity(legalType) - } - } else { - // persist legal type and request type of the action in session upon authentication via Signin component - sessionStorage.setItem('LEGAL_TYPE', legalType) - sessionStorage.setItem('REQUEST_ACTION_CD', this.getRequestActionCd) - // navigate to BC Registry login page with return parameter - const registryHomeUrl = sessionStorage.getItem('REGISTRY_HOME_URL') - const nameRequestUrl = `${window.location.origin}` - Navigate(`${registryHomeUrl}login?return=${nameRequestUrl}`) - } - } - async handleSubmit (doNameCheck = true) { this.setDoNameCheck(doNameCheck) if (this.isXproFlow) this.$root.$emit('showSpinner', true) diff --git a/app/src/mixins/nr-affiliation-mixin.ts b/app/src/mixins/nr-affiliation-mixin.ts index 272cbc8ed..17685cc05 100644 --- a/app/src/mixins/nr-affiliation-mixin.ts +++ b/app/src/mixins/nr-affiliation-mixin.ts @@ -7,7 +7,7 @@ import { BusinessRequest, NameRequestI } from '@/interfaces' import { ActionBindingIF } from '@/interfaces/store-interfaces' import { Navigate } from '@/plugins' import { CommonMixin } from '@/mixins' -import { NrAffiliationErrors } from '@/enums' +import { EntityTypes, NrAffiliationErrors } from '@/enums' import { CREATED, BAD_REQUEST } from 'http-status-codes' import { CorpTypeCd } from '@bcrs-shared-components/corp-type-module' import { AmalgamationTypes, CorrectNameOptions, FilingTypes, NrRequestActionCodes } @@ -19,6 +19,12 @@ export class NrAffiliationMixin extends Mixins(CommonMixin) { @Getter(useStore) isContinuationIn!: boolean @Getter(useStore) isNewBusiness!: boolean @Getter(useStore) getBusinessAccountId: string + @Getter(useStore) getEntityTypeCd!: EntityTypes + @Getter(useStore) getRequestActionCd!: NrRequestActionCodes + @Getter(useStore) isAuthenticated!: boolean + @Getter(useStore) isChangeName!: boolean + @Getter(useStore) isConversion!: boolean + @Getter(useStore) isRestoration!: boolean @Getter(useStore) isRoleStaff!: boolean @Action(useStore) setAffiliationErrorModalValue!: ActionBindingIF @@ -215,6 +221,30 @@ export class NrAffiliationMixin extends Mixins(CommonMixin) { } } + /** + * If user is authenticated, create draft business and redirect to Dashboard. + * If restoration/reinstatement selected, go to business dashboard. + * If user is not authenticated, redirect to login screen then redirect back. + */ + async actionNowClicked (): Promise { + const legalType = this.entityTypeToCorpType(this.getEntityTypeCd) + if (this.isAuthenticated) { + if (this.isConversion || this.isRestoration || this.isChangeName) { + this.goToEntityDashboard(this.getSearchBusiness.identifier) + } else { + await this.actionNumberedEntity(legalType) + } + } else { + // persist legal type and request type of the action in session upon authentication via Signin component + sessionStorage.setItem('LEGAL_TYPE', legalType) + sessionStorage.setItem('REQUEST_ACTION_CD', this.getRequestActionCd) + // navigate to BC Registry login page with return parameter + const registryHomeUrl = sessionStorage.getItem('REGISTRY_HOME_URL') + const nameRequestUrl = `${window.location.origin}` + Navigate(`${registryHomeUrl}login?return=${nameRequestUrl}`) + } + } + /** * 1. Handles the action buttons (numbered selection). * 2. Creates draft business depending on legal type. diff --git a/app/tests/unit/dialogs/numbered-company-help.spec.ts b/app/tests/unit/dialogs/numbered-company-help.spec.ts index 3179d071b..fcaa6013a 100644 --- a/app/tests/unit/dialogs/numbered-company-help.spec.ts +++ b/app/tests/unit/dialogs/numbered-company-help.spec.ts @@ -3,18 +3,43 @@ import { mount } from '@vue/test-utils' import { createPinia, setActivePinia } from 'pinia' import NumberedCompanyHelpDialog from '@/components/dialogs/numbered-company-help.vue' import { useStore } from '@/store' +import { EntityTypes } from '@/enums' const vuetify = new Vuetify() // Prevent the warning "[Vuetify] Unable to locate target [data-app]" document.body.setAttribute('data-app', 'true') +const mockFlags = vi.hoisted(() => ({ value: {} as Record })) + +vi.mock('@/plugins/launchDarkly', () => ({ + GetFeatureFlag: (name: string) => mockFlags.value[name], + InitLdClient: vi.fn(), + UpdateLdUser: vi.fn() +})) + +const mockNavigate = vi.hoisted(() => vi.fn()) + +vi.mock('@/plugins/navigate', () => ({ + Navigate: mockNavigate +})) + setActivePinia(createPinia()) const store = useStore() // NB: store state is set before mounting because pinia -> component reactivity // is not available in this test environment (pinia is externalized by vitest) describe('NumberedCompanyHelpDialog', () => { + beforeEach(() => { + sessionStorage.setItem('CORPORATE_ONLINE_URL', 'https://corporate-online-url/') + sessionStorage.setItem('REGISTRY_HOME_URL', 'https://registry-home-url/') + mockFlags.value = { + 'supported-incorporation-registration-entities': [EntityTypes.CR] + } + store.setEntityTypeCd(EntityTypes.CR) + mockNavigate.mockClear() + }) + afterEach(() => { store.setNumberedCompanyHelpModalVisible(false) }) @@ -28,16 +53,49 @@ describe('NumberedCompanyHelpDialog', () => { wrapper.destroy() }) - it('shows the modal when the state is set and displays the placeholder info', () => { + it('shows the modal when the state is set and displays both option cards', () => { store.setNumberedCompanyHelpModalVisible(true) const wrapper = mount(NumberedCompanyHelpDialog, { vuetify }) expect(wrapper.vm.showModal).toBe(true) - expect(wrapper.text()).toContain('Help me Choose') - expect(wrapper.text()).toContain( - 'Information to help you choose between Corporate Online and the new BC Business Registry' - ) - expect(wrapper.find('#numbered-company-help-close-btn').exists()).toBe(true) + expect(wrapper.text()).toContain('Choose the website you want to use') + + // Corporate Online card + const coCard = wrapper.find('#corporate-online-card') + expect(coCard.exists()).toBe(true) + expect(coCard.text()).toContain('Corporate Online') + expect(coCard.text()).toContain('For complex filings.') + expect(coCard.text()).toContain('combine or merge your business with another business (Amalgamation)') + expect(coCard.text()).toContain('reactivate a business (Restoration)') + expect(coCard.text()).toContain('move your business out of B.C. (Continuation-out)') + expect(coCard.text()).toContain('Note: all businesses in Corporate Online will be moved') + const coBtn = coCard.find('#help-corporate-online-btn') + expect(coBtn.text()).toContain('Continue to Corporate Online') + expect(coBtn.attributes('href')).toBe('https://corporate-online-url/') + expect(coBtn.attributes('target')).toBe('_blank') + + // BC Business Registry card + const brCard = wrapper.find('#business-registry-card') + expect(brCard.exists()).toBe(true) + expect(brCard.text()).toContain('BC Business Registry') + expect(brCard.text()).toContain('For everyday filings.') + expect(brCard.text()).toContain('file annual reports') + expect(brCard.text()).toContain('change your business address when you move') + expect(brCard.text()).toContain('change directors names or addresses') + expect(brCard.text()).toContain('change basic business information (Alteration)') + const brBtn = brCard.find('#help-business-registry-btn') + expect(brBtn.text()).toContain('Use the New BC Business Registry') + expect(brBtn.attributes('disabled')).toBeUndefined() + + wrapper.destroy() + }) + + it('disables the registry button when the entity is not supported', () => { + mockFlags.value['supported-incorporation-registration-entities'] = [] + store.setNumberedCompanyHelpModalVisible(true) + const wrapper = mount(NumberedCompanyHelpDialog, { vuetify }) + + expect(wrapper.find('#help-business-registry-btn').attributes('disabled')).toBe('disabled') wrapper.destroy() }) @@ -53,4 +111,17 @@ describe('NumberedCompanyHelpDialog', () => { wrapper.destroy() }) + + it('closes the modal and actions the NR when the registry button is pressed', async () => { + store.setNumberedCompanyHelpModalVisible(true) + const wrapper = mount(NumberedCompanyHelpDialog, { vuetify }) + + await wrapper.find('#help-business-registry-btn').trigger('click') + + expect(store.getNumberedCompanyHelpModalVisible).toBe(false) + // unauthenticated user is redirected to login with a return parameter + expect(mockNavigate).toHaveBeenCalledWith(`https://registry-home-url/login?return=${window.location.origin}`) + + wrapper.destroy() + }) }) From a9095b3d1ec3ace1c01a321d13defe7cc00a98b7 Mon Sep 17 00:00:00 2001 From: Kial Jinnah Date: Mon, 27 Jul 2026 10:35:02 -0400 Subject: [PATCH 3/7] Prevent numbered company launcher showing for benefit companies Signed-off-by: Kial Jinnah --- app/src/components/new-request/search.vue | 6 ++++-- app/tests/unit/search.spec.ts | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/app/src/components/new-request/search.vue b/app/src/components/new-request/search.vue index af728489d..3a2e720fd 100644 --- a/app/src/components/new-request/search.vue +++ b/app/src/components/new-request/search.vue @@ -595,13 +595,15 @@ export default class Search extends Mixins(CommonMixin, NrAffiliationMixin, Sear ) } - /** Whether to show the two-button numbered company launcher (new BC business flow only). */ + /** Whether to show the two-button numbered company launcher (new BC business flow only, not BEN). */ get showNumberedCompanyLauncher (): boolean { return ( this.isNumberedCompanyLauncherEnabled() && this.isNewBcBusiness && this.isNumberedCompany && - this.isNumberedEntityType + this.isNumberedEntityType && + // NB: EntityTypes.BC is the namex code for Benefit Company + this.getEntityTypeCd !== EntityTypes.BC ) } diff --git a/app/tests/unit/search.spec.ts b/app/tests/unit/search.spec.ts index 548fee266..ad042a98d 100644 --- a/app/tests/unit/search.spec.ts +++ b/app/tests/unit/search.spec.ts @@ -212,6 +212,22 @@ describe('Numbered Company Launcher', () => { wrapper.destroy() }) + it('does not show the launcher for a benefit company', () => { + mockFlags.value['enable-numbered-company-launcher'] = true + mockFlags.value['supported-incorporation-registration-entities'] = [EntityTypes.BC] + // NB: EntityTypes.BC is the namex code for Benefit Company + store.setEntityTypeCd(EntityTypes.BC) + const wrapper = wrapperFactory() + + expect(wrapper.find('#incorporate-colin-btn').exists()).toBe(false) + expect(wrapper.find('#incorporate-registry-btn').exists()).toBe(false) + expect(wrapper.find('#help-me-choose-launcher-btn').exists()).toBe(false) + // a supported benefit company still shows the Action Now button + expect(wrapper.find('#action-now-button').exists()).toBe(true) + + wrapper.destroy() + }) + it('does not show the launcher in a non-new-business flow', () => { mockFlags.value['enable-numbered-company-launcher'] = true store.setRequestAction(NrRequestActionCodes.AMALGAMATE) From 73fec2f68a74488ec2899a132d77aa920b4233d2 Mon Sep 17 00:00:00 2001 From: Kial Jinnah Date: Mon, 27 Jul 2026 14:59:59 -0400 Subject: [PATCH 4/7] Attempting CI fix - use pnpm version 10 Signed-off-by: Kial Jinnah --- .github/workflows/cd.yml | 1 + .github/workflows/ci.yml | 1 + app/package.json | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 7bce55a41..38f7ecfce 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -24,6 +24,7 @@ jobs: with: target: ${{ inputs.environment }} node_version: "24" + pnpm_version: 10.0.0 app_name: 'namerequest' working_directory: 'app' secrets: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ca8b90507..a7640e40d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,4 +16,5 @@ jobs: with: app_name: "namerequest" working_directory: "./app" + pnpm_version: 10.0.0 codecov_flag: "" diff --git a/app/package.json b/app/package.json index 9caffdbf4..c5669e491 100644 --- a/app/package.json +++ b/app/package.json @@ -1,6 +1,6 @@ { "name": "name-request", - "version": "5.10.0", + "version": "5.10.1", "private": true, "engines": { "node": ">=24" From 16ad5860deb2f919d6d5110536136d566fb72d22 Mon Sep 17 00:00:00 2001 From: Kial Jinnah Date: Mon, 27 Jul 2026 15:05:37 -0400 Subject: [PATCH 5/7] Attempting CI fix - revert to pnpm 9 / default Signed-off-by: Kial Jinnah --- .github/workflows/cd.yml | 1 - .github/workflows/ci.yml | 1 - 2 files changed, 2 deletions(-) diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 38f7ecfce..7bce55a41 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -24,7 +24,6 @@ jobs: with: target: ${{ inputs.environment }} node_version: "24" - pnpm_version: 10.0.0 app_name: 'namerequest' working_directory: 'app' secrets: diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a7640e40d..ca8b90507 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,5 +16,4 @@ jobs: with: app_name: "namerequest" working_directory: "./app" - pnpm_version: 10.0.0 codecov_flag: "" From fe0ef658986a8d4071a551cefc0d0a41e1282912 Mon Sep 17 00:00:00 2001 From: Kial Jinnah Date: Mon, 27 Jul 2026 15:25:41 -0400 Subject: [PATCH 6/7] Attempting CI fix - add vue-demi with pnpm 9 Signed-off-by: Kial Jinnah --- app/package.json | 1 + app/pnpm-lock.yaml | 3 +++ 2 files changed, 4 insertions(+) diff --git a/app/package.json b/app/package.json index c5669e491..31e41fc87 100644 --- a/app/package.json +++ b/app/package.json @@ -75,6 +75,7 @@ "vitest": "0.33.0", "volar-service-vetur": "^0.0.62", "vue-debounce-decorator": "^1.0.1", + "vue-demi": "^0.14.10", "vue-property-decorator": "^9.1.2", "vue-test-utils-helpers": "git+https://github.com/bcgov/vue-test-utils-helpers.git", "vuex-class": "^0.3.2", diff --git a/app/pnpm-lock.yaml b/app/pnpm-lock.yaml index b9c5a53c8..98dabb1be 100644 --- a/app/pnpm-lock.yaml +++ b/app/pnpm-lock.yaml @@ -176,6 +176,9 @@ importers: vue-debounce-decorator: specifier: ^1.0.1 version: 1.0.1 + vue-demi: + specifier: ^0.14.10 + version: 0.14.10(vue@2.7.16) vue-property-decorator: specifier: ^9.1.2 version: 9.1.2(vue-class-component@7.2.6(vue@2.7.16))(vue@2.7.16) From 1de184239c4bf3060f6f095c9efe3950415bd7ff Mon Sep 17 00:00:00 2001 From: Kial Jinnah Date: Mon, 27 Jul 2026 15:35:24 -0400 Subject: [PATCH 7/7] Attempting CI fix - run needed vue-demi 2.7 script before tests/build (required since CI prevents post install script) Signed-off-by: Kial Jinnah --- app/package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/package.json b/app/package.json index 31e41fc87..989cfbc18 100644 --- a/app/package.json +++ b/app/package.json @@ -9,14 +9,14 @@ "sbcName": "SBC Common Components", "scripts": { "dev": "vite", - "build": "vite build", - "build-check": "vite build", + "build": "vue-demi-fix && vite build", + "build-check": "vue-demi-fix && vite build", "preview": "vite preview --port 8080", "lint": "eslint . --ext js,ts,vue --no-fix", - "test": "vitest run", - "test:unit": "vitest run", + "test": "vue-demi-fix && vitest run", + "test:unit": "vue-demi-fix && vitest run", "test:watch": "vitest watch", - "test:coverage": "vitest run --coverage" + "test:coverage": "vue-demi-fix && vitest run --coverage" }, "dependencies": { "@babel/compat-data": "^7.24.4",