diff --git a/src/components/Dashboard/FilingHistoryList.vue b/src/components/Dashboard/FilingHistoryList.vue index f558266c6..2a6ba065a 100644 --- a/src/components/Dashboard/FilingHistoryList.vue +++ b/src/components/Dashboard/FilingHistoryList.vue @@ -64,6 +64,7 @@ + mdi-file-document-edit-outline @@ -162,8 +163,8 @@ v-if="isRoleStaff" @click.stop="showCommentDialog(item.filingId)" > - Add Detail Comment - + Add Detail Comment +
@@ -344,7 +345,7 @@ export default { }], paperOnly: false, isCorrected: filing.header.isCorrected || false, - comments: this.flattenComments(filing.header.comments) + comments: this.flattenAndSortComments(filing.header.comments) } this.filedItems.push(item) } else { @@ -388,7 +389,7 @@ export default { status: filing.header.status, paperOnly: false, isCorrected: filing.header.isCorrected || false, - comments: this.flattenComments(filing.header.comments) + comments: this.flattenAndSortComments(filing.header.comments) } this.filedItems.push(item) } else { @@ -429,13 +430,20 @@ export default { }], paperOnly: true, isCorrected: filing.header.isCorrected || false, - comments: this.flattenComments(filing.header.comments) + comments: this.flattenAndSortComments(filing.header.comments) } this.filedItems.push(item) }, - flattenComments (comments: any): Array { - return (comments && comments.length > 0) ? comments.map(c => c.comment) : [] + flattenAndSortComments (comments: any): Array { + if (comments && comments.length > 0) { + // first use map to change comment.comment to comment + const mapped: Array = comments.map(c => c.comment) + // then sort newest to oldest + const sorted = mapped.sort((a, b) => new Date(a.timestamp) < new Date(b.timestamp) ? 1 : -1) + return sorted + } + return [] }, typeToTitle (type: string, agmYear: string = null): string { diff --git a/src/components/common/DetailComment.vue b/src/components/common/DetailComment.vue index d1c3b48a7..72ed4fb7e 100644 --- a/src/components/common/DetailComment.vue +++ b/src/components/common/DetailComment.vue @@ -5,11 +5,12 @@ outlined auto-grow rows="5" - id="detail-comment-textfield" + id="detail-comment-textarea" :counter="MAXLENGTH" :rules="rules" :value="value" :label="label" + :autofocus="autofocus" @input="emitInput($event)" /> @@ -46,6 +47,10 @@ export default class DetailComment extends Vue { @Prop({ default: '' }) private label: string + /** Autofocus passed into this component. */ + @Prop({ default: false }) + private autofocus: boolean + /** * Called when prop changes (ie, v-model is updated by parent). * This method is debounced to prevent excessive validation. diff --git a/src/components/dialogs/AddCommentDialog.vue b/src/components/dialogs/AddCommentDialog.vue index d03e06376..3bdc47373 100644 --- a/src/components/dialogs/AddCommentDialog.vue +++ b/src/components/dialogs/AddCommentDialog.vue @@ -7,6 +7,7 @@ @@ -53,7 +54,7 @@ export default class AddCommentDialog extends Vue { /** Prop to display the dialog. */ @Prop() private dialog: boolean - /** Prop to display the dialog. */ + /** Prop to provide the Filing ID. */ @Prop() private filingId: number /** Prop to provide attachment selector. */ @@ -92,6 +93,14 @@ export default class AddCommentDialog extends Vue { private async save (): Promise { // prevent double saving if (this.saving) return + + // ensure we have a Filing ID + if (!this.filingId) { + // eslint-disable-next-line no-console + console.error('save() error - missing filing ID') + return + } + this.saving = true const data = { diff --git a/src/utils/config-helper.ts b/src/utils/config-helper.ts index cd72d4824..1e5618e85 100644 --- a/src/utils/config-helper.ts +++ b/src/utils/config-helper.ts @@ -7,6 +7,9 @@ export default { * fetch config from environment and API */ fetchConfig () { + const { name, version } = require('../../package.json') + console.info(`This is ${name} v${version}`) + const origin = window.location.origin const vueAppPath = process.env.VUE_APP_PATH diff --git a/src/utils/sleep.ts b/src/utils/sleep.ts index fa1f8cbe5..caba91dc8 100644 --- a/src/utils/sleep.ts +++ b/src/utils/sleep.ts @@ -1,10 +1,8 @@ -export default { - /** - * Method that "sleeps" for specified timeout. Must be called from async method. - * @param ms Delay to sleep, in milliseconds. - * @returns A promise to await upon. - */ - sleep (ms: number): Promise { - return new Promise(resolve => setTimeout(resolve, ms)) - } +/** + * Function that "sleeps" for specified timeout. Must be called from async method. + * @param ms Delay to sleep, in milliseconds. + * @returns A promise to await upon. + */ +export function sleep (ms: number): Promise { + return new Promise(resolve => setTimeout(resolve, ms)) } diff --git a/src/views/AnnualReport.vue b/src/views/AnnualReport.vue index 43de5ec84..bc1531659 100644 --- a/src/views/AnnualReport.vue +++ b/src/views/AnnualReport.vue @@ -397,8 +397,7 @@ export default { if (this.agmDate) return this.agmDate // if filing is in past year then use last day in that year if (this.ARFilingYear < this.currentYear) return `${this.ARFilingYear}-12-31` - // otherwise use current date - // (should never happen because either we should have an AGM Date or filing should be in past year) + // otherwise use current date (BCOMP only - should never happen for COOP) return this.currentDate }, @@ -455,7 +454,7 @@ export default { } // NB: filing id of 0 means "new AR" // otherwise it's a draft AR filing id - this.filingId = this.$route.params.id + this.filingId = +this.$route.params.id // number // if tombstone data isn't set, route to home if (!this.entityIncNo || !this.ARFilingYear || (this.filingId === undefined)) { diff --git a/src/views/Correction.vue b/src/views/Correction.vue index 0a27d57ef..2c798793b 100644 --- a/src/views/Correction.vue +++ b/src/views/Correction.vue @@ -329,7 +329,7 @@ export default { } } // NB: this is the id of the filing to correct - const origFilingId = this.$route.params.id + const origFilingId = +this.$route.params.id // number // if required data isn't set, route to home if (!this.entityIncNo || (origFilingId === undefined) || (origFilingId <= 0)) { @@ -606,9 +606,7 @@ export default { } } if (setting === 'add' && !added) { - // TODO: remove hard-coded entity type when fee codes are available from Pay team - // this.filingData.push({ filingTypeCode: filing, entityType: this.entityType }) - this.filingData.push({ filingTypeCode: filing, entityType: EntityTypes.BCOMP }) + this.filingData.push({ filingTypeCode: filing, entityType: this.entityType }) } }, diff --git a/src/views/StandaloneDirectorsFiling.vue b/src/views/StandaloneDirectorsFiling.vue index d10063d0d..2665a7370 100644 --- a/src/views/StandaloneDirectorsFiling.vue +++ b/src/views/StandaloneDirectorsFiling.vue @@ -403,7 +403,7 @@ export default { // NB: filing id of 0 means "new" // otherwise it's a draft filing id - this.filingId = this.$route.params.id + this.filingId = +this.$route.params.id // number // if tombstone data isn't set, route to home if (!this.entityIncNo || (this.filingId === undefined)) { diff --git a/src/views/StandaloneOfficeAddressFiling.vue b/src/views/StandaloneOfficeAddressFiling.vue index a7b26fc77..6fb6110bf 100644 --- a/src/views/StandaloneOfficeAddressFiling.vue +++ b/src/views/StandaloneOfficeAddressFiling.vue @@ -274,7 +274,7 @@ export default { // NB: filing id of 0 means "new" // otherwise it's a draft filing id - this.filingId = this.$route.params.id + this.filingId = +this.$route.params.id // number // if tombstone data isn't set, route to home if (!this.entityIncNo || (this.filingId === undefined)) { diff --git a/tests/unit/AGMDate.spec.ts b/tests/unit/AGMDate.spec.ts index 8218d8aeb..b98e8f4ab 100644 --- a/tests/unit/AGMDate.spec.ts +++ b/tests/unit/AGMDate.spec.ts @@ -1,8 +1,7 @@ import Vue from 'vue' import Vuetify from 'vuetify' import Vuelidate from 'vuelidate' -import { mount } from '@vue/test-utils' -import flushPromises from 'flush-promises' +import { mount, Wrapper } from '@vue/test-utils' import store from '@/store/store' import AgmDate from '@/components/AnnualReport/AGMDate.vue' @@ -27,10 +26,10 @@ Vue.use(Vuelidate) const vuetify = new Vuetify({}) describe('AgmDate', () => { - let wrapper - let vm + let wrapper: Wrapper + let vm: any - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.currentDate = '2019-07-15' @@ -39,9 +38,7 @@ describe('AgmDate', () => { store.state.lastAnnualReportDate = '2018-07-15' wrapper = mount(AgmDate, { store, vuetify }) - vm = wrapper.vm as any - - await flushPromises() + vm = wrapper.vm }) afterEach(() => { diff --git a/tests/unit/AddressListSm.spec.ts b/tests/unit/AddressListSm.spec.ts index c80573760..919db9093 100644 --- a/tests/unit/AddressListSm.spec.ts +++ b/tests/unit/AddressListSm.spec.ts @@ -10,7 +10,7 @@ import { EntityTypes } from '@/enums' Vue.use(Vuetify) Vue.use(Vuelidate) -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) describe('AddressListSm', () => { it('handles empty data', done => { diff --git a/tests/unit/AnnualReport.spec.ts b/tests/unit/AnnualReport.spec.ts index bb8265e32..8be0a3f58 100644 --- a/tests/unit/AnnualReport.spec.ts +++ b/tests/unit/AnnualReport.spec.ts @@ -10,7 +10,7 @@ import store from '@/store/store' import mockRouter from './mockRouter' import flushPromises from 'flush-promises' import { BAD_REQUEST } from 'http-status-codes' -import { shallowMount, createLocalVue, mount } from '@vue/test-utils' +import { shallowMount, createLocalVue, mount, Wrapper } from '@vue/test-utils' // Components import AnnualReport from '@/views/AnnualReport.vue' @@ -31,7 +31,7 @@ Vue.use(Vuelidate) // ref: https://github.com/vuejs/vue-test-utils/issues/532 Vue.config.silent = true -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) describe('AnnualReport - Part 1 - UI', () => { beforeEach(() => { @@ -655,7 +655,7 @@ describe('AnnualReport - Part 1B - UI - BCOMP', () => { }) describe('AnnualReport - Part 2 - Resuming', () => { - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.entityName = 'Legal Name - CP0001191' @@ -746,7 +746,7 @@ describe('AnnualReport - Part 3 - Submitting', () => { window.location.assign = assign }) - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.entityType = EntityTypes.COOP @@ -754,9 +754,15 @@ describe('AnnualReport - Part 3 - Submitting', () => { store.state.ARFilingYear = 2017 store.state.currentFilingStatus = 'NEW' + const sinonAxiosGet = sinon.stub(axios, 'get') + + // mock "get tasks" endpoint - needed for hasTasks() + sinonAxiosGet + .withArgs('CP0001191/tasks') + .returns(new Promise(resolve => resolve({ data: { tasks: [] } }))) + // mock "fetch a draft filing" endpoint - sinon - .stub(axios, 'get') + sinonAxiosGet .withArgs('CP0001191/filings/123') .returns( new Promise(resolve => @@ -1019,7 +1025,7 @@ describe('AnnualReport - Part 3B - Submitting - BCOMP', () => { window.location.assign = assign }) - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'BC0007291' store.state.entityName = 'Legal Name - BC0007291' @@ -1030,6 +1036,12 @@ describe('AnnualReport - Part 3B - Submitting - BCOMP', () => { store.state.registeredAddress = {} store.state.recordsAddress = {} + // mock "get tasks" endpoint - needed for hasTasks() + sinon + .stub(axios, 'get') + .withArgs('BC0007291/tasks') + .returns(new Promise(resolve => resolve({ data: { tasks: [] } }))) + // mock "save and file" endpoint sinon .stub(axios, 'post') @@ -1128,10 +1140,10 @@ describe('AnnualReport - Part 3B - Submitting - BCOMP', () => { }) describe('AnnualReport - Part 4 - Saving', () => { - let wrapper - let vm + let wrapper: Wrapper + let vm: any - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.entityType = EntityTypes.COOP @@ -1139,6 +1151,12 @@ describe('AnnualReport - Part 4 - Saving', () => { store.state.ARFilingYear = 2017 store.state.currentFilingStatus = 'NEW' + // mock "get tasks" endpoint - needed for hasTasks() + sinon + .stub(axios, 'get') + .withArgs('CP0001191/tasks') + .returns(new Promise(resolve => resolve({ data: { tasks: [] } }))) + // mock "save draft" endpoint sinon .stub(axios, 'post') @@ -1180,7 +1198,7 @@ describe('AnnualReport - Part 4 - Saving', () => { router.push({ name: 'annual-report', params: { id: '0' } }) // new filing id wrapper = shallowMount(AnnualReport, { store, localVue, router, vuetify }) - vm = wrapper.vm as any + vm = wrapper.vm }) afterEach(() => { @@ -1265,13 +1283,13 @@ describe('AnnualReport - Part 4 - Saving', () => { }) describe('AnnualReport - Part 5 - Data', () => { - let wrapper - let vm + let wrapper: Wrapper + let vm: any let spy const currentFilingYear = 2017 - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.entityType = EntityTypes.COOP @@ -1279,6 +1297,12 @@ describe('AnnualReport - Part 5 - Data', () => { store.state.ARFilingYear = currentFilingYear store.state.currentFilingStatus = 'NEW' + // mock "get tasks" endpoint - needed for hasTasks() + sinon + .stub(axios, 'get') + .withArgs('CP0001191/tasks') + .returns(new Promise(resolve => resolve({ data: { tasks: [] } }))) + // mock "save draft" endpoint - garbage response data, we aren't testing that spy = sinon .stub(axios, 'post') @@ -1306,7 +1330,7 @@ describe('AnnualReport - Part 5 - Data', () => { router.push({ name: 'annual-report', params: { id: '0' } }) // new filing id wrapper = shallowMount(AnnualReport, { store, localVue, router, vuetify }) - vm = wrapper.vm as any + vm = wrapper.vm // set up director data vm.allDirectors = [ @@ -1398,6 +1422,7 @@ describe('AnnualReport - Part 5 - Data', () => { // - the first index (0) is to get the first call, where there could be many calls to the stubbed function // - the second index (1) is to get the second param - data - where the call is axios.post(url, data) const payload = spy.args[0][1] + // basic tests to pass ensuring structure of payload is as expected expect(payload.filing).toBeDefined() expect(payload.filing.annualReport).toBeDefined() @@ -1524,23 +1549,30 @@ describe('AnnualReport - Part 5 - Data', () => { }) describe('AnnualReport - Part 5B - Data - BCOMP', () => { - let wrapper - let vm - let spy + let wrapper: Wrapper + let vm: any + let spy: any const currentFilingYear = 2018 - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'BC0007291' store.state.entityName = 'Legal Name - BC0007291' store.state.entityType = EntityTypes.BCOMP store.state.ARFilingYear = 2018 + store.state.currentDate = '2018-09-26' store.state.nextARDate = '2019-09-26T00:00:00+00:00' store.state.currentFilingStatus = 'NEW' store.state.registeredAddress = {} store.state.recordsAddress = {} + // mock "get tasks" endpoint - needed for hasTasks() + sinon + .stub(axios, 'get') + .withArgs('BC0007291/tasks') + .returns(new Promise(resolve => resolve({ data: { tasks: [] } }))) + // mock "save" endpoint - garbage response data, we aren't testing that spy = sinon .stub(axios, 'post') @@ -1585,7 +1617,7 @@ describe('AnnualReport - Part 5B - Data - BCOMP', () => { }, vuetify }) - vm = wrapper.vm as any + vm = wrapper.vm // set up director data vm.allDirectors = [ @@ -1738,8 +1770,8 @@ describe('AnnualReport - Part 5B - Data - BCOMP', () => { }) describe('AnnualReport - Part 6 - Error/Warning dialogs', () => { - let wrapper - let vm + let wrapper: Wrapper + let vm: any const request = require('request') const { assign } = window.location @@ -1753,7 +1785,7 @@ describe('AnnualReport - Part 6 - Error/Warning dialogs', () => { window.location.assign = assign }) - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.entityType = EntityTypes.COOP @@ -1761,6 +1793,12 @@ describe('AnnualReport - Part 6 - Error/Warning dialogs', () => { store.state.ARFilingYear = 2017 store.state.currentFilingStatus = 'NEW' + // mock "get tasks" endpoint - needed for hasTasks() + sinon + .stub(axios, 'get') + .withArgs('CP0001191/tasks') + .returns(new Promise(resolve => resolve({ data: { tasks: [] } }))) + // mock "file post" endpoint const p1 = Promise.reject({ response: { @@ -1854,6 +1892,7 @@ describe('AnnualReport - Part 6 - Error/Warning dialogs', () => { .stub(axios, 'put') .withArgs('CP0001191/filings/123') .returns(p2) + const localVue = createLocalVue() localVue.use(VueRouter) const router = mockRouter.mock() @@ -1878,7 +1917,7 @@ describe('AnnualReport - Part 6 - Error/Warning dialogs', () => { }, vuetify }) - vm = wrapper.vm as any + vm = wrapper.vm }) afterEach(() => { @@ -1912,8 +1951,9 @@ describe('AnnualReport - Part 6 - Error/Warning dialogs', () => { wrapper.find('#ar-file-pay-btn').trigger('click') // work-around because click trigger isn't working await vm.onClickFilePay() - await flushPromises() + + // verify error dialog expect(vm.saveErrorDialog).toBe(true) expect(vm.saveErrors.length).toBe(1) expect(vm.saveErrors[0].error).toBe('err msg post') @@ -1952,6 +1992,7 @@ describe('AnnualReport - Part 6 - Error/Warning dialogs', () => { await vm.onClickFilePay() await flushPromises() + // verify error dialog expect(vm.saveErrorDialog).toBe(true) expect(vm.saveErrors.length).toBe(1) expect(vm.saveErrors[0].error).toBe('err msg put') @@ -1961,8 +2002,8 @@ describe('AnnualReport - Part 6 - Error/Warning dialogs', () => { }) describe('AnnualReport - Part 7 - Save through multiple tabs', () => { - let wrapper - let vm + let wrapper: Wrapper + let vm: any store.state.entityName = 'Legal Name - CP0001191' store.state.entityType = EntityTypes.COOP @@ -1970,7 +2011,7 @@ describe('AnnualReport - Part 7 - Save through multiple tabs', () => { store.state.currentFilingStatus = 'NEW' store.state.entityIncNo = 'CP0001191' - beforeEach(async () => { + beforeEach(() => { const localVue = createLocalVue() localVue.use(VueRouter) const router = mockRouter.mock() @@ -1994,9 +2035,9 @@ describe('AnnualReport - Part 7 - Save through multiple tabs', () => { }, vuetify }) - vm = wrapper.vm as any + vm = wrapper.vm - // mock "save draft" endpoint + // mock "get tasks" endpoint sinon .stub(axios, 'get') .withArgs('CP0001191/tasks') @@ -2004,19 +2045,19 @@ describe('AnnualReport - Part 7 - Save through multiple tabs', () => { new Promise(resolve => resolve({ data: { - 'tasks': [ + tasks: [ { - 'task': { - 'filing': { - 'header': { - 'name': 'annualReport', - 'ARFilingYear': 2017, - 'status': 'DRAFT' + task: { + filing: { + header: { + name: 'annualReport', + ARFilingYear: 2017, + status: 'DRAFT' } } }, - 'enabled': true, - 'order': 1 + enabled: true, + order: 1 } ] } @@ -2048,11 +2089,11 @@ describe('AnnualReport - Part 7 - Save through multiple tabs', () => { // click the Save button wrapper.find('#ar-file-pay-btn').trigger('click') await flushPromises() - setTimeout(() => { - expect(vm.saveErrorDialog).toBe(true) - expect(vm.saveErrors.length).toBe(1) - expect(vm.saveErrors[0].error) - .toBe('Another draft filing already exists. Please complete it before creating a new filing.') - }, 1000) + + // verify error dialog + expect(vm.saveErrorDialog).toBe(true) + expect(vm.saveErrors.length).toBe(1) + expect(vm.saveErrors[0].error) + .toBe('Another draft filing already exists. Please complete it before creating a new filing.') }) }) diff --git a/tests/unit/App.spec.ts b/tests/unit/App.spec.ts index 609d1dc59..aa3b8d80e 100644 --- a/tests/unit/App.spec.ts +++ b/tests/unit/App.spec.ts @@ -3,7 +3,7 @@ import Vuetify from 'vuetify' import Vuelidate from 'vuelidate' import VueRouter from 'vue-router' import sinon from 'sinon' -import { createLocalVue, shallowMount } from '@vue/test-utils' +import { createLocalVue, shallowMount, Wrapper } from '@vue/test-utils' import axios from '@/axios-auth' import store from '@/store/store' @@ -12,11 +12,11 @@ import App from '@/App.vue' Vue.use(Vuetify) Vue.use(Vuelidate) -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) describe('App as a COOP', () => { - let wrapper - let vm + let wrapper: Wrapper + let vm: any beforeEach(done => { // we need a token that can get parsed properly (will be expired but doesn't matter for tests) @@ -332,8 +332,8 @@ describe('App as a COOP', () => { describe('BCOMP APP', () => { // just need a token that can get parsed properly (will be expired but doesn't matter for tests) // must not include keycloakRoles=["staff"] - let wrapper - let vm + let wrapper: Wrapper + let vm: any beforeEach(done => { sessionStorage.setItem('KEYCLOAK_TOKEN', 'eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJUbWdtZUk0MnVsdUZ0N3F' + diff --git a/tests/unit/CODDate.spec.ts b/tests/unit/CODDate.spec.ts index a8c3d6ad2..96452d00a 100644 --- a/tests/unit/CODDate.spec.ts +++ b/tests/unit/CODDate.spec.ts @@ -1,7 +1,7 @@ import Vue from 'vue' import Vuetify from 'vuetify' import Vuelidate from 'vuelidate' -import { mount } from '@vue/test-utils' +import { mount, Wrapper } from '@vue/test-utils' import store from '@/store/store' import CodDate from '@/components/StandaloneDirectorChange/CODDate.vue' @@ -11,7 +11,7 @@ Vue.config.silent = true Vue.use(Vuetify) Vue.use(Vuelidate) -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) // get rid of "Download the Vue Devtools extension for a better development experience" console message Vue.config.devtools = false @@ -20,8 +20,8 @@ Vue.config.devtools = false Vue.config.productionTip = false describe('CodDate', () => { - let wrapper - let vm + let wrapper: Wrapper + let vm: any beforeEach(() => { // init store @@ -31,7 +31,7 @@ describe('CodDate', () => { store.state.entityFoundingDate = '2018-03-01T00:00:00' wrapper = mount(CodDate, { store, vuetify }) - vm = wrapper.vm as any + vm = wrapper.vm }) afterEach(() => { diff --git a/tests/unit/CancelPaymentErrorDialog.spec.ts b/tests/unit/CancelPaymentErrorDialog.spec.ts index 3e756eeb6..d10f2139b 100644 --- a/tests/unit/CancelPaymentErrorDialog.spec.ts +++ b/tests/unit/CancelPaymentErrorDialog.spec.ts @@ -6,7 +6,7 @@ import { CancelPaymentErrorDialog } from '@/components/dialogs' Vue.use(Vuetify) -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) describe('CancelPaymentErrorDialog - Displays Error/Warning messages', () => { it('displays generic message for normal users', () => { diff --git a/tests/unit/Dashboard.spec.ts b/tests/unit/Dashboard.spec.ts index 316eb1608..2d1605f44 100644 --- a/tests/unit/Dashboard.spec.ts +++ b/tests/unit/Dashboard.spec.ts @@ -2,7 +2,7 @@ import Vue from 'vue' import Vuetify from 'vuetify' import Vuelidate from 'vuelidate' import VueRouter from 'vue-router' -import { shallowMount, createLocalVue } from '@vue/test-utils' +import { shallowMount, createLocalVue, Wrapper } from '@vue/test-utils' import mockRouter from './mockRouter' import store from '@/store/store' @@ -28,7 +28,7 @@ Vue.config.silent = true Vue.use(Vuetify) Vue.use(Vuelidate) -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) // Boilerplate to prevent the complaint "[Vuetify] Unable to locate target [data-app]" const app: HTMLDivElement = document.createElement('div') @@ -36,12 +36,14 @@ app.setAttribute('data-app', 'true') document.body.append(app) describe('Dashboard - UI', () => { - let wrapper + let wrapper: Wrapper + let vm: any beforeEach(() => { // create wrapper for Dashboard // this stubs out the 5 sub-components wrapper = shallowMount(Dashboard, { store, vuetify }) + vm = wrapper.vm }) afterEach(() => { @@ -60,27 +62,27 @@ describe('Dashboard - UI', () => { wrapper.find(TodoList).vm.$emit('todo-count', 2) wrapper.find(FilingHistoryList).vm.$emit('filed-count', 3) - expect(wrapper.vm.todoCount).toEqual(2) - expect(wrapper.vm.filedCount).toEqual(3) + expect(vm.todoCount).toEqual(2) + expect(vm.filedCount).toEqual(3) }) it('enables standalone filing buttons when there are no blocker filings in the to-do list', () => { wrapper.find(TodoList).vm.$emit('has-blocker-filing', false) - expect(wrapper.vm.hasBlockerFiling).toEqual(false) - expect(wrapper.vm.$el.querySelector('#standalone-addresses-button') + expect(vm.hasBlockerFiling).toEqual(false) + expect(vm.$el.querySelector('#standalone-addresses-button') .getAttribute('disabled')).toBeNull() - expect(wrapper.vm.$el.querySelector('#standalone-directors-button') + expect(vm.$el.querySelector('#standalone-directors-button') .getAttribute('disabled')).toBeNull() }) it('disables standalone filing buttons when there is a blocker filing in the to-do list', () => { wrapper.find(TodoList).vm.$emit('has-blocker-filing', true) - expect(wrapper.vm.hasBlockerFiling).toEqual(true) - expect(wrapper.vm.$el.querySelector('#standalone-addresses-button') + expect(vm.hasBlockerFiling).toEqual(true) + expect(vm.$el.querySelector('#standalone-addresses-button') .getAttribute('disabled')).toBe('true') - expect(wrapper.vm.$el.querySelector('#standalone-directors-button') + expect(vm.$el.querySelector('#standalone-directors-button') .getAttribute('disabled')).toBe('true') }) @@ -91,11 +93,11 @@ describe('Dashboard - UI', () => { [{ 'name': 'Address Change', 'status': 'PAID' }]) wrapper.find(TodoList).vm.$emit('has-blocker-filing', true) - expect(wrapper.vm.hasBlockerFiling).toEqual(true) - expect(wrapper.vm.coaPending).toEqual(true) - expect(wrapper.vm.$el.querySelector('#standalone-addresses-button') + expect(vm.hasBlockerFiling).toEqual(true) + expect(vm.coaPending).toEqual(true) + expect(vm.$el.querySelector('#standalone-addresses-button') .getAttribute('disabled')).toBe('true') - expect(wrapper.vm.$el.querySelector('#standalone-directors-button') + expect(vm.$el.querySelector('#standalone-directors-button') .getAttribute('disabled')).toBe('true') }) diff --git a/tests/unit/DirectorListSm.spec.ts b/tests/unit/DirectorListSm.spec.ts index 590b9b1a9..9064ad28e 100644 --- a/tests/unit/DirectorListSm.spec.ts +++ b/tests/unit/DirectorListSm.spec.ts @@ -10,7 +10,7 @@ import { EntityTypes } from '@/enums' Vue.use(Vuetify) Vue.use(Vuelidate) -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) describe('DirectorListSm', () => { it('handles empty data as a coop', done => { diff --git a/tests/unit/Directors.spec.ts b/tests/unit/Directors.spec.ts index f6d01ad31..eff637503 100644 --- a/tests/unit/Directors.spec.ts +++ b/tests/unit/Directors.spec.ts @@ -1,6 +1,7 @@ import Vue from 'vue' import Vuetify from 'vuetify' import Vuelidate from 'vuelidate' +import { mount, Wrapper } from '@vue/test-utils' import sinon from 'sinon' import axios from '@/axios-auth' import store from '@/store/store' @@ -18,7 +19,7 @@ Vue.config.devtools = false // get rid of "You are running Vue in development mode" console message Vue.config.productionTip = false -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) // Boilerplate to prevent the complaint "[Vuetify] Unable to locate target [data-app]" const app: HTMLDivElement = document.createElement('div') @@ -720,6 +721,7 @@ describe('Directors as a BCOMP', () => { }) describe('Appoint New Director tests', () => { + let wrapper: Wrapper let vm: any beforeEach(() => { @@ -736,13 +738,16 @@ describe('Appoint New Director tests', () => { } }))) - const Constructor = Vue.extend(Directors) - const instance = new Constructor({ store, vuetify }) - vm = instance.$mount() - - // set props - vm.asOfDate = '2019-04-01' - vm.componentEnabled = true + wrapper = mount(Directors, { + sync: false, + store, + vuetify, + propsData: { + asOfDate: '2019-04-01', + componentEnabled: true + } + }) + vm = wrapper.vm // click Appoint New Director button click(vm, '.new-director-btn') @@ -750,138 +755,128 @@ describe('Appoint New Director tests', () => { afterEach(() => { sinon.restore() + wrapper.destroy() + wrapper = null }) - it('accepts valid First Name', done => { - setValue(vm, '#new-director__first-name', 'First First') + it('accepts valid First Name', async () => { + const inputElement = wrapper.find('#new-director__first-name') + inputElement.setValue('First First') expect(vm.director.officer.firstName).toBe('First First') // verify that there are no validation errors - setTimeout(() => { - expect(vm.$el.querySelectorAll('.v-messages')[0].textContent).toBe('') - done() - }, 250) + await Vue.nextTick() + expect(vm.$el.querySelectorAll('.v-messages')[0].textContent).toBe('') }) - it('displays error for invalid First Name - leading spaces', done => { - setValue(vm, '#new-director__first-name', ' First') + it('displays error for invalid First Name - leading spaces', async () => { + const inputElement = wrapper.find('#new-director__first-name') + inputElement.setValue(' First') expect(vm.director.officer.firstName).toBe(' First') // verify that validation error is displayed - setTimeout(() => { - expect(vm.$el.querySelectorAll('.v-messages')[0].textContent).toContain('Invalid spaces') - done() - }, 250) + await Vue.nextTick() + expect(vm.$el.querySelectorAll('.v-messages')[0].textContent).toContain('Invalid spaces') }) - it('displays error for invalid First Name - trailing spaces', done => { - setValue(vm, '#new-director__first-name', 'First ') + it('displays error for invalid First Name - trailing spaces', async () => { + const inputElement = wrapper.find('#new-director__first-name') + inputElement.setValue('First ') expect(vm.director.officer.firstName).toBe('First ') // verify that validation error is displayed - setTimeout(() => { - expect(vm.$el.querySelectorAll('.v-messages')[0].textContent).toContain('Invalid spaces') - done() - }, 250) + await Vue.nextTick() + expect(vm.$el.querySelectorAll('.v-messages')[0].textContent).toContain('Invalid spaces') }) - it('allows First Name with multiple inline spaces', done => { - setValue(vm, '#new-director__first-name', 'First First') + it('allows First Name with multiple inline spaces', async () => { + const inputElement = wrapper.find('#new-director__first-name') + inputElement.setValue('First First') expect(vm.director.officer.firstName).toBe('First First') // verify that validation error is not displayed - setTimeout(() => { - expect(vm.$el.querySelectorAll('.v-messages')[0].textContent).toBe('') - done() - }, 250) + await Vue.nextTick() + expect(vm.$el.querySelectorAll('.v-messages')[0].textContent).toBe('') }) - it('accepts valid Middle Initial', done => { - setValue(vm, '#new-director__middle-initial', 'M M') + it('accepts valid Middle Initial', async () => { + const inputElement = wrapper.find('#new-director__middle-initial') + inputElement.setValue('M M') expect(vm.director.officer.middleInitial).toBe('M M') // verify that there are no validation errors - setTimeout(() => { - expect(vm.$el.querySelectorAll('.v-messages')[1].textContent).toBe('') - done() - }, 250) + await Vue.nextTick() + expect(vm.$el.querySelectorAll('.v-messages')[1].textContent).toBe('') }) - it('displays error for invalid Middle Initial - leading spaces', done => { - setValue(vm, '#new-director__middle-initial', ' M') + it('displays error for invalid Middle Initial - leading spaces', async () => { + const inputElement = wrapper.find('#new-director__middle-initial') + inputElement.setValue(' M') expect(vm.director.officer.middleInitial).toBe(' M') // verify that validation error is displayed - setTimeout(() => { - expect(vm.$el.querySelectorAll('.v-messages')[1].textContent).toContain('Invalid spaces') - done() - }, 250) + await Vue.nextTick() + expect(vm.$el.querySelectorAll('.v-messages')[1].textContent).toContain('Invalid spaces') }) - it('displays error for invalid Middle Initial - trailing spaces', done => { - setValue(vm, '#new-director__middle-initial', 'M ') + it('displays error for invalid Middle Initial - trailing spaces', async () => { + const inputElement = wrapper.find('#new-director__middle-initial') + inputElement.setValue('M ') expect(vm.director.officer.middleInitial).toBe('M ') // verify that validation error is displayed - setTimeout(() => { - expect(vm.$el.querySelectorAll('.v-messages')[1].textContent).toContain('Invalid spaces') - done() - }, 250) + await Vue.nextTick() + expect(vm.$el.querySelectorAll('.v-messages')[1].textContent).toContain('Invalid spaces') }) - it('allows Middle Initial with multiple inline spaces', done => { - setValue(vm, '#new-director__middle-initial', 'M M') + it('allows Middle Initial with multiple inline spaces', async () => { + const inputElement = wrapper.find('#new-director__middle-initial') + inputElement.setValue('M M') expect(vm.director.officer.middleInitial).toBe('M M') // verify that validation error is displayed - setTimeout(() => { - expect(vm.$el.querySelectorAll('.v-messages')[1].textContent).toBe('') - done() - }, 250) + await Vue.nextTick() + expect(vm.$el.querySelectorAll('.v-messages')[1].textContent).toBe('') }) - it('accepts valid Last Name', done => { - setValue(vm, '#new-director__last-name', 'Last') + it('accepts valid Last Name', async () => { + const inputElement = wrapper.find('#new-director__last-name') + inputElement.setValue('Last') expect(vm.director.officer.lastName).toBe('Last') // verify that there are no validation errors - setTimeout(() => { - expect(vm.$el.querySelectorAll('.v-messages')[2].textContent).toBe('') - done() - }, 250) + await Vue.nextTick() + expect(vm.$el.querySelectorAll('.v-messages')[2].textContent).toBe('') }) - it('displays error for invalid Last Name - leading spaces', done => { - setValue(vm, '#new-director__last-name', ' Last') + it('displays error for invalid Last Name - leading spaces', async () => { + const inputElement = wrapper.find('#new-director__last-name') + inputElement.setValue(' Last') expect(vm.director.officer.lastName).toBe(' Last') // verify that validation error is displayed - setTimeout(() => { - expect(vm.$el.querySelectorAll('.v-messages')[2].textContent).toContain('Invalid spaces') - done() - }, 250) + await Vue.nextTick() + expect(vm.$el.querySelectorAll('.v-messages')[2].textContent).toContain('Invalid spaces') }) - it('displays error for invalid Last Name - trailing spaces', done => { - setValue(vm, '#new-director__last-name', 'Last ') + it('displays error for invalid Last Name - trailing spaces', async () => { + const inputElement = wrapper.find('#new-director__last-name') + inputElement.setValue('Last ') expect(vm.director.officer.lastName).toBe('Last ') // verify that validation error is displayed - setTimeout(() => { - expect(vm.$el.querySelectorAll('.v-messages')[2].textContent).toContain('Invalid spaces') - done() - }, 250) + await Vue.nextTick() + expect(vm.$el.querySelectorAll('.v-messages')[2].textContent).toContain('Invalid spaces') }) - it('allows Last Name with multiple inline spaces', done => { - setValue(vm, '#new-director__last-name', 'Last Last') + it('allows Last Name with multiple inline spaces', async () => { + const inputElement = wrapper.find('#new-director__last-name') + inputElement.setValue('Last Last') expect(vm.director.officer.lastName).toBe('Last Last') // verify that validation error is displayed - setTimeout(() => { - expect(vm.$el.querySelectorAll('.v-messages')[2].textContent).toBe('') - done() - }, 250) + await Vue.nextTick() + expect(vm.$el.querySelectorAll('.v-messages')[2].textContent).toBe('') }) // todo diff --git a/tests/unit/EntityInfo.spec.ts b/tests/unit/EntityInfo.spec.ts index d422355ed..7a4172b93 100644 --- a/tests/unit/EntityInfo.spec.ts +++ b/tests/unit/EntityInfo.spec.ts @@ -8,7 +8,7 @@ import EntityInfo from '@/components/EntityInfo.vue' Vue.use(Vuetify) Vue.use(Vuelidate) -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) // Boilerplate to prevent the complaint "[Vuetify] Unable to locate target [data-app]" const app: HTMLDivElement = document.createElement('div') @@ -16,7 +16,7 @@ app.setAttribute('data-app', 'true') document.body.append(app) describe('EntityInfo', () => { - let vm + let vm: any beforeEach(done => { const Constructor = Vue.extend(EntityInfo) diff --git a/tests/unit/FilingHistoryList.spec.ts b/tests/unit/FilingHistoryList.spec.ts index 11b6aa15b..974e55a47 100644 --- a/tests/unit/FilingHistoryList.spec.ts +++ b/tests/unit/FilingHistoryList.spec.ts @@ -9,7 +9,7 @@ import FilingHistoryList from '@/components/Dashboard/FilingHistoryList.vue' Vue.use(Vuetify) Vue.use(Vuelidate) -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) const sampleFilings = [ { @@ -110,7 +110,7 @@ const sampleFilings = [ ] describe('FilingHistoryList', () => { - it('handles empty data', done => { + it('handles empty data', async () => { const $route = { query: { 'filingId': null } } // init store @@ -120,19 +120,18 @@ describe('FilingHistoryList', () => { const wrapper = shallowMount(FilingHistoryList, { store, mocks: { $route }, vuetify }) const vm = wrapper.vm as any - Vue.nextTick(() => { - expect(vm.filedItems.length).toEqual(0) - expect(vm.$el.querySelectorAll('.filing-item').length).toEqual(0) - expect(wrapper.emitted('filed-count')).toEqual([[0]]) - expect(vm.panel).toBeNull() // no row is expanded - expect(vm.$el.querySelector('.no-results')).not.toBeNull() - expect(vm.$el.querySelector('.no-results').textContent).toContain('You have no filing history') - wrapper.destroy() - done() - }) + await Vue.nextTick() + expect(vm.filedItems.length).toEqual(0) + expect(vm.$el.querySelectorAll('.filing-history-item').length).toEqual(0) + expect(wrapper.emitted('filed-count')).toEqual([[0]]) + expect(vm.panel).toBeNull() // no row is expanded + expect(vm.$el.querySelector('.no-results')).not.toBeNull() + expect(vm.$el.querySelector('.no-results').textContent).toContain('You have no filing history') + + wrapper.destroy() }) - it('displays the Filed Items pre/post bob date', done => { + it('displays the Filed Items pre/post bob date', async () => { const $route = { query: { 'filingId': null } } // init store @@ -243,18 +242,17 @@ describe('FilingHistoryList', () => { const wrapper = shallowMount(FilingHistoryList, { store, mocks: { $route }, vuetify }) const vm = wrapper.vm as any - Vue.nextTick(() => { - expect(vm.filedItems.length).toEqual(store.state.filings.length) - expect(vm.$el.querySelectorAll('.filing-item').length).toEqual(store.state.filings.length) - expect(wrapper.emitted('filed-count')).toEqual([[store.state.filings.length]]) - expect(vm.panel).toBeNull() // no row is expanded - expect(vm.$el.querySelector('.no-results')).toBeNull() - wrapper.destroy() - done() - }) + await Vue.nextTick() + expect(vm.filedItems.length).toEqual(store.state.filings.length) + expect(vm.$el.querySelectorAll('.filing-history-item').length).toEqual(store.state.filings.length) + expect(wrapper.emitted('filed-count')).toEqual([[store.state.filings.length]]) + expect(vm.panel).toBeNull() // no row is expanded + expect(vm.$el.querySelector('.no-results')).toBeNull() + + wrapper.destroy() }) - it('expands the specified filing ID for pre/post bob date filings', done => { + it('expands the specified filing ID for pre/post bob date filings', async () => { const $route = { query: { 'filing_id': '654' } } // init store @@ -365,18 +363,17 @@ describe('FilingHistoryList', () => { const wrapper = shallowMount(FilingHistoryList, { store, mocks: { $route }, vuetify }) const vm = wrapper.vm as any - Vue.nextTick(() => { - expect(vm.filedItems.length).toEqual(store.state.filings.length) - expect(vm.$el.querySelectorAll('.filing-item').length).toEqual(store.state.filings.length) - expect(wrapper.emitted('filed-count')).toEqual([[store.state.filings.length]]) - expect(vm.panel).toEqual(1) // second row is expanded - expect(vm.$el.querySelector('.no-results')).toBeNull() - wrapper.destroy() - done() - }) + await Vue.nextTick() + expect(vm.filedItems.length).toEqual(store.state.filings.length) + expect(vm.$el.querySelectorAll('.filing-history-item').length).toEqual(store.state.filings.length) + expect(wrapper.emitted('filed-count')).toEqual([[store.state.filings.length]]) + expect(vm.panel).toEqual(1) // second row is expanded + expect(vm.$el.querySelector('.no-results')).toBeNull() + + wrapper.destroy() }) - it('shows the filing date in the correct format yyyy-mm-dd', done => { + it('shows the filing date in the correct format yyyy-mm-dd', async () => { const $route = { query: { 'filing_id': '654' } } // init store @@ -386,16 +383,15 @@ describe('FilingHistoryList', () => { const wrapper = shallowMount(FilingHistoryList, { store, mocks: { $route }, vuetify }) const vm = wrapper.vm as any - Vue.nextTick(() => { - expect(vm.$el.querySelectorAll('.filing-item')[0] - .querySelector('.list-item__subtitle').textContent) - .toContain('2019-06-02') - wrapper.destroy() - done() - }) + await Vue.nextTick() + expect(vm.$el.querySelectorAll('.filing-history-item')[0] + .querySelector('.list-item__subtitle').textContent) + .toContain('2019-06-02') + + wrapper.destroy() }) - it('displays the alert when the filing is future effective', done => { + it('displays the alert when the filing is future effective', async () => { const $route = { query: { 'filing_id': '9873' } } // init store @@ -406,10 +402,10 @@ describe('FilingHistoryList', () => { const wrapper = shallowMount(FilingHistoryList, { store, mocks: { $route }, vuetify }) const vm = wrapper.vm as any - expect(vm.$el.querySelectorAll('.filing-item')[5].textContent) + await Vue.nextTick() + expect(vm.$el.querySelectorAll('.filing-history-item')[5].textContent) .toContain('The updated office addresses will be legally effective on 2019-12-13') wrapper.destroy() - done() }) }) diff --git a/tests/unit/OfficeAddresses.spec.ts b/tests/unit/OfficeAddresses.spec.ts index 174124944..b9831ceaf 100644 --- a/tests/unit/OfficeAddresses.spec.ts +++ b/tests/unit/OfficeAddresses.spec.ts @@ -10,7 +10,7 @@ import { EntityTypes } from '@/enums' Vue.use(Vuetify) Vue.use(Vuelidate) -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) // Boilerplate to prevent the complaint "[Vuetify] Unable to locate target [data-app]" const app: HTMLDivElement = document.createElement('div') @@ -18,7 +18,7 @@ app.setAttribute('data-app', 'true') document.body.append(app) describe('OfficeAddresses as a COOP', () => { - let vm + let vm: any beforeAll(() => { // init store @@ -260,7 +260,7 @@ describe('OfficeAddresses as a COOP', () => { }) describe('OfficeAddresses as a BCOMP', () => { - let vm + let vm: any beforeAll(() => { // init store diff --git a/tests/unit/SaveErrorDialog.spec.ts b/tests/unit/SaveErrorDialog.spec.ts index 2bef2db68..34b33cff3 100644 --- a/tests/unit/SaveErrorDialog.spec.ts +++ b/tests/unit/SaveErrorDialog.spec.ts @@ -7,7 +7,7 @@ import { SaveErrorDialog } from '@/components/dialogs' Vue.use(Vuetify) -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) describe('SaveErrorDialog - Part 1 - Displays Error/Warning messages', () => { it('displays generic message for normal users', () => { diff --git a/tests/unit/StaffPayment.spec.ts b/tests/unit/StaffPayment.spec.ts index 97b5e76a4..75e76f8f8 100644 --- a/tests/unit/StaffPayment.spec.ts +++ b/tests/unit/StaffPayment.spec.ts @@ -8,21 +8,18 @@ Vue.use(Vuetify) // https://vue-test-utils.vuejs.org/api/config.html#silent Vue.config.silent = true -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) describe('StaffPayment', () => { it('initializes correctly with no prop', async () => { - const wrapper = mount(StaffPayment, - { - propsData: { value: null }, - vuetify - }) + const wrapper = mount(StaffPayment, { vuetify }) + await Vue.nextTick() // check that: - // 1. value is initially null - // 2. component is initially invalid - expect(wrapper.emitted('update:value')).toEqual([[null]]) - expect(wrapper.emitted('valid')).toEqual([[false]]) + // 1. routingSlipNumber is null + // 2. component is invalid + expect(wrapper.emitted('update:routingSlipNumber').pop()).toEqual([null]) + expect(wrapper.emitted('valid').pop()).toEqual([false]) wrapper.destroy() }) @@ -30,107 +27,86 @@ describe('StaffPayment', () => { it('initializes correctly with prop', async () => { const wrapper = mount(StaffPayment, { - propsData: { value: '123456789' }, - vuetify + vuetify, + propsData: { routingSlipNumber: '123456789' } }) + await Vue.nextTick() // check that: - // 1. value is initially set - // 2. component is initially valid - expect(wrapper.emitted('update:value')).toEqual([['123456789']]) - setTimeout(() => { - expect(wrapper.emitted('valid')).toEqual([[true]]) - }, 100) + // 1. routingSlipNumber is set + // 2. component is valid + expect(wrapper.emitted('update:routingSlipNumber').pop()).toEqual(['123456789']) + expect(wrapper.emitted('valid').pop()).toEqual([true]) wrapper.destroy() }) it('becomes valid when prop becomes valid', async () => { - const wrapper = mount(StaffPayment, - { - propsData: { value: null }, - vuetify - }) + const wrapper = mount(StaffPayment, { vuetify }) - wrapper.setProps({ value: '123456789' }) + wrapper.setProps({ routingSlipNumber: '123456789' }) + await Vue.nextTick() // check that: - // 1. value was initially null - // 2. value became set - // 3. component was initially invalid - // 4. component became valid - expect(wrapper.emitted('update:value')).toEqual([[null], ['123456789']]) - setTimeout(() => { - expect(wrapper.emitted('valid')).toEqual([[false], [true]]) - }, 100) + // 1. routingSlipNumber is set + // 2. component is valid + expect(wrapper.emitted('update:routingSlipNumber').pop()).toEqual(['123456789']) + expect(wrapper.emitted('valid').pop()).toEqual([true]) + wrapper.destroy() }) it('becomes invalid when prop becomes invalid', async () => { const wrapper = mount(StaffPayment, { - propsData: { value: '123456789' }, - vuetify + vuetify, + propsData: { routingSlipNumber: '123456789' } }) - wrapper.setProps({ value: null }) - - // NB: can't check error message because Vuetify renders it outside this component + wrapper.setProps({ routingSlipNumber: null }) + await Vue.nextTick() // check that: - // 1. value was initially set - // 2. value became null - // 3. component was initially valid - // 4. component became invalid - expect(wrapper.emitted('update:value')).toEqual([['123456789'], [null]]) - setTimeout(() => { - expect(wrapper.emitted('valid')).toEqual([[true], [false]]) - }, 100) + // 1. routingSlipNumber is null + // 2. component is invalid + expect(wrapper.emitted('update:routingSlipNumber').pop()).toEqual([null]) + expect(wrapper.emitted('valid').pop()).toEqual([false]) wrapper.destroy() }) it('becomes valid when input becomes valid', async () => { - const wrapper = mount(StaffPayment, - { - propsData: { value: null }, - vuetify - }) + const wrapper = mount(StaffPayment, { vuetify }) wrapper.setData({ routingSlipNumber: '123456789' }) + await Vue.nextTick() // check that: - // 1. value was initially null - // 2. value became set - // 3. component was initially invalid - // 4. component became valid - expect(wrapper.emitted('update:value')).toEqual([[null], ['123456789']]) - setTimeout(() => { - expect(wrapper.emitted('valid')).toEqual([[false], [true]]) - }, 100) + // 1. routingSlipNumber is set + // 2. component is valid + expect(wrapper.emitted('update:routingSlipNumber').pop()).toEqual(['123456789']) + expect(wrapper.emitted('valid').pop()).toEqual([true]) + wrapper.destroy() }) it('becomes invalid when input becomes invalid', async () => { const wrapper = mount(StaffPayment, { - propsData: { value: '123456789' }, - vuetify + vuetify, + propsData: { routingSlipNumber: '123456789' } }) wrapper.setData({ routingSlipNumber: null }) + await Vue.nextTick() // NB: can't check error message because Vuetify renders it outside this component // check that: - // 1. value was initially set - // 2. value became null - // 3. component was initially valid - // 4. component became invalid - expect(wrapper.emitted('update:value')).toEqual([['123456789'], [null]]) - setTimeout(() => { - expect(wrapper.emitted('valid')).toEqual([[true], [false]]) - }, 100) + // 1. routingSlipNumber is null + // 2. component is invalid + expect(wrapper.emitted('update:routingSlipNumber').pop()).toEqual([null]) + expect(wrapper.emitted('valid').pop()).toEqual([false]) wrapper.destroy() }) diff --git a/tests/unit/StandaloneDirectorsFiling.spec.ts b/tests/unit/StandaloneDirectorsFiling.spec.ts index 2c23697f8..4a5fd67a2 100644 --- a/tests/unit/StandaloneDirectorsFiling.spec.ts +++ b/tests/unit/StandaloneDirectorsFiling.spec.ts @@ -3,7 +3,7 @@ import Vue from 'vue' import Vuetify from 'vuetify' import Vuelidate from 'vuelidate' import sinon from 'sinon' -import { createLocalVue, shallowMount, mount } from '@vue/test-utils' +import { createLocalVue, shallowMount, mount, Wrapper } from '@vue/test-utils' import flushPromises from 'flush-promises' import CodDate from '@/components/StandaloneDirectorChange/CODDate.vue' import Directors from '@/components/AnnualReport/Directors.vue' @@ -24,7 +24,7 @@ Vue.use(Vuelidate) // ref: https://github.com/vuejs/vue-test-utils/issues/532 Vue.config.silent = true -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) const sampleDirectors = [ { @@ -73,7 +73,7 @@ describe('Standalone Directors Filing - Part 1 - UI', () => { beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' - store.state.currentDate = '2019/07/15' + store.state.currentDate = '2019-07-15' // set Last Filing Date and verify new Min Date store.state.entityFoundingDate = '2018-03-01T00:00:00' }) @@ -332,11 +332,11 @@ describe('Standalone Directors Filing - Part 1 - UI', () => { }) describe('Standalone Directors Filing - Part 2 - Resuming', () => { - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.entityName = 'Legal Name - CP0001191' - store.state.currentDate = '2019/07/15' + store.state.currentDate = '2019-07-15' // mock "fetch a draft filing" endpoint sinon.stub(axios, 'get').withArgs('CP0001191/filings/123') @@ -413,11 +413,11 @@ describe('Standalone Directors Filing - Part 3A - Submitting filing that needs t window.location.assign = assign }) - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.entityName = 'Legal Name - CP0001191' - store.state.currentDate = '2019/07/15' + store.state.currentDate = '2019-07-15' const get = sinon.stub(axios, 'get') @@ -738,11 +738,11 @@ describe('Standalone Directors Filing - Part 3A - Submitting filing that needs t }) describe('Standalone Directors Filing - Part 3B - Submitting filing that doesn\'t need to be paid', () => { - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.entityName = 'Legal Name - CP0001191' - store.state.currentDate = '2019/07/15' + store.state.currentDate = '2019-07-15' // mock "save and file" endpoint sinon.stub(axios, 'post').withArgs('CP0001191/filings') @@ -849,11 +849,11 @@ describe('Standalone Directors Filing - Part 4 - Saving', () => { window.location.assign = assign }) - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.entityName = 'Legal Name - CP0001191' - store.state.currentDate = '2019/07/15' + store.state.currentDate = '2019-07-15' // mock "save draft" endpoint sinon.stub(axios, 'post').withArgs('CP0001191/filings?draft=true') @@ -994,15 +994,21 @@ describe('Standalone Directors Filing - Part 4 - Saving', () => { }) describe('Standalone Directors Filing - Part 5 - Data', () => { - let wrapper - let vm + let wrapper: Wrapper + let vm: any let spy - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.entityName = 'Legal Name - CP0001191' - store.state.currentDate = '2019/07/15' + store.state.currentDate = '2019-07-15' + + // mock "get tasks" endpoint - needed for hasTasks() + sinon + .stub(axios, 'get') + .withArgs('CP0001191/tasks') + .returns(new Promise(resolve => resolve({ data: { tasks: [] } }))) // mock "save draft" endpoint - garbage response data, we aren't testing that spy = sinon.stub(axios, 'post').withArgs('CP0001191/filings?draft=true') @@ -1029,7 +1035,7 @@ describe('Standalone Directors Filing - Part 5 - Data', () => { router.push({ name: 'standalone-directors', params: { id: '0' } }) // new filing id wrapper = shallowMount(StandaloneDirectorsFiling, { store, localVue, router }) - vm = wrapper.vm as any + vm = wrapper.vm // set up director data vm.allDirectors = [ @@ -1151,11 +1157,11 @@ describe('Standalone Directors Filing - Part 6 - Error/Warning dialogs', () => { window.location.assign = assign }) - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.entityName = 'Legal Name - CP0001191' - store.state.currentDate = '2019/07/15' + store.state.currentDate = '2019-07-15' const get = sinon.stub(axios, 'get') diff --git a/tests/unit/StandaloneOfficeAddressFiling.spec.ts b/tests/unit/StandaloneOfficeAddressFiling.spec.ts index 6b99961e8..0689cd679 100644 --- a/tests/unit/StandaloneOfficeAddressFiling.spec.ts +++ b/tests/unit/StandaloneOfficeAddressFiling.spec.ts @@ -3,7 +3,7 @@ import Vue from 'vue' import Vuetify from 'vuetify' import Vuelidate from 'vuelidate' import sinon from 'sinon' -import { createLocalVue, shallowMount, mount } from '@vue/test-utils' +import { createLocalVue, shallowMount, mount, Wrapper } from '@vue/test-utils' import flushPromises from 'flush-promises' import axios from '@/axios-auth' import store from '@/store/store' @@ -25,7 +25,7 @@ Vue.use(Vuelidate) // ref: https://github.com/vuejs/vue-test-utils/issues/532 Vue.config.silent = true -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) const sampleDeliveryAddress = { 'streetAddress': 'delivery street address', @@ -470,10 +470,10 @@ describe('Standalone Office Address Filing - Part 3 - Submitting', () => { store.state.entityName = 'Legal Name - CP0001191' store.state.entityType = EntityTypes.COOP - let s = sinon.stub(axios, 'get') + let sinonAxiosGet = sinon.stub(axios, 'get') // mock "fetch a draft filing" endpoint - s.withArgs('CP0001191/filings/123') + sinonAxiosGet.withArgs('CP0001191/filings/123') .returns(new Promise((resolve) => resolve({ data: { @@ -507,7 +507,7 @@ describe('Standalone Office Address Filing - Part 3 - Submitting', () => { } }))) - s.withArgs('CP0001191/tasks') + sinonAxiosGet.withArgs('CP0001191/tasks') .returns(new Promise((resolve) => resolve({ data: { 'tasks': [ @@ -746,10 +746,10 @@ describe('Standalone Office Address Filing - Part 3B (BCOMP) - Submitting', () = store.state.entityName = 'Legal Name - BC0001191' store.state.entityType = EntityTypes.BCOMP - let s = sinon.stub(axios, 'get') + let sinonAxiosGet = sinon.stub(axios, 'get') // mock "fetch a draft filing" endpoint - s.withArgs('BC0001191/filings/123') + sinonAxiosGet.withArgs('BC0001191/filings/123') .returns(new Promise((resolve) => resolve({ data: { @@ -787,7 +787,7 @@ describe('Standalone Office Address Filing - Part 3B (BCOMP) - Submitting', () = } }))) - s.withArgs('BC0001191/tasks') + sinonAxiosGet.withArgs('BC0001191/tasks') .returns(new Promise((resolve) => resolve({ data: { 'tasks': [ @@ -1026,7 +1026,7 @@ describe('Standalone Office Address Filing - Part 4 - Saving', () => { window.location.assign = assign }) - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.entityName = 'Legal Name - CP0001191' @@ -1061,8 +1061,7 @@ describe('Standalone Office Address Filing - Part 4 - Saving', () => { } }))) - let s = sinon.stub(axios, 'get') - s.withArgs('CP0001191/tasks') + sinon.stub(axios, 'get').withArgs('CP0001191/tasks') .returns(new Promise((resolve) => resolve({ data: { 'tasks': [ @@ -1156,7 +1155,7 @@ describe('Standalone Office Address Filing - Part 4B (BCOMP) - Saving', () => { window.location.assign = assign }) - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'BC0001191' store.state.entityName = 'Legal Name - BC0001191' @@ -1200,8 +1199,7 @@ describe('Standalone Office Address Filing - Part 4B (BCOMP) - Saving', () => { } }))) - let s = sinon.stub(axios, 'get') - s.withArgs('BC0001191/tasks') + sinon.stub(axios, 'get').withArgs('BC0001191/tasks') .returns(new Promise((resolve) => resolve({ data: { 'tasks': [ @@ -1283,16 +1281,22 @@ describe('Standalone Office Address Filing - Part 4B (BCOMP) - Saving', () => { }) describe('Standalone Office Address Filing - Part 5 - Data', () => { - let wrapper - let vm + let wrapper: Wrapper + let vm: any let spy - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.entityName = 'Legal Name - CP0001191' - // mock "save draft" endpoint - garbage response data, we aren't testing that + // mock "get tasks" endpoint - needed for hasTasks() + sinon + .stub(axios, 'get') + .withArgs('CP0001191/tasks') + .returns(new Promise(resolve => resolve({ data: { tasks: [] } }))) + + // mock "save draft" endpoint spy = sinon.stub(axios, 'post').withArgs('CP0001191/filings?draft=true') .returns(new Promise((resolve) => resolve({ data: @@ -1322,7 +1326,7 @@ describe('Standalone Office Address Filing - Part 5 - Data', () => { router.push({ name: 'standalone-addresses', params: { id: '0' } }) // new filing id wrapper = shallowMount(StandaloneOfficeAddressFiling, { store, localVue, router, vuetify }) - vm = wrapper.vm as any + vm = wrapper.vm // stub address data vm.addresses = { @@ -1365,16 +1369,22 @@ describe('Standalone Office Address Filing - Part 5 - Data', () => { }) describe('Standalone Office Address Filing - Part 5B (BCOMP) - Data', () => { - let wrapper - let vm + let wrapper: Wrapper + let vm: any let spy - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'BC0001191' store.state.entityName = 'Legal Name - BC0001191' - // mock "save draft" endpoint - garbage response data, we aren't testing that + // mock "get tasks" endpoint - needed for hasTasks() + sinon + .stub(axios, 'get') + .withArgs('BC0001191/tasks') + .returns(new Promise(resolve => resolve({ data: { tasks: [] } }))) + + // mock "save draft" endpoint spy = sinon.stub(axios, 'post').withArgs('BC0001191/filings?draft=true') .returns(new Promise((resolve) => resolve({ data: @@ -1408,7 +1418,7 @@ describe('Standalone Office Address Filing - Part 5B (BCOMP) - Data', () => { router.push({ name: 'standalone-addresses', params: { id: '0' } }) // new filing id wrapper = shallowMount(StandaloneOfficeAddressFiling, { store, localVue, router, vuetify }) - vm = wrapper.vm as any + vm = wrapper.vm // stub address data vm.addresses = { @@ -1467,11 +1477,54 @@ describe('Standalone Office Address Filing - Part 6 - Error/Warning dialogs', () window.location.assign = assign }) - beforeEach(async () => { + beforeEach(() => { // init store store.state.entityIncNo = 'CP0001191' store.state.entityName = 'Legal Name - CP0001191' + const sinonAxiosGet = sinon.stub(axios, 'get') + + // mock "get tasks" endpoint - needed for hasTasks() + sinonAxiosGet + .withArgs('CP0001191/tasks') + .returns(new Promise(resolve => resolve({ data: { tasks: [] } }))) + + // mock "fetch a draft filing" endpoint + sinonAxiosGet + .withArgs('CP0001191/filings/123') + .returns(new Promise((resolve) => resolve({ + data: + { + 'filing': { + 'changeOfAddress': { + 'offices': { + 'registeredOffice': { + 'deliveryAddress': sampleDeliveryAddress, + 'mailingAddress': sampleMailingAddress + } + } + }, + 'business': { + 'cacheId': 1, + 'foundingDate': '2007-04-08', + 'identifier': 'CP0001191', + 'lastLedgerTimestamp': '2019-04-15T20:05:49.068272+00:00', + 'legalName': 'Legal Name - CP0001191' + }, + 'header': { + 'name': 'changeOfAddress', + 'date': '2017-06-06', + 'submitter': 'cp0001191', + 'status': 'DRAFT', + 'certifiedBy': 'Full Name', + 'email': 'no_one@never.get', + 'filingId': 123, + 'routingSlipNumber': '456' + } + } + } + }))) + // mock "file post" endpoint const p1 = Promise.reject({ response: { diff --git a/tests/unit/SummaryCertify.spec.ts b/tests/unit/SummaryCertify.spec.ts index eee0f89dd..e4c7af7f2 100644 --- a/tests/unit/SummaryCertify.spec.ts +++ b/tests/unit/SummaryCertify.spec.ts @@ -8,7 +8,7 @@ import { mount, Wrapper } from '@vue/test-utils' import { SummaryCertify } from '@/components/common' Vue.use(Vuetify) -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) const statementSelector: string = '.certify-content' const someCertifier = 'Some Certifier' diff --git a/tests/unit/SummaryDirectors.spec.ts b/tests/unit/SummaryDirectors.spec.ts index 0c42572c3..14eca936c 100644 --- a/tests/unit/SummaryDirectors.spec.ts +++ b/tests/unit/SummaryDirectors.spec.ts @@ -16,7 +16,7 @@ import { EntityTypes } from '@/enums' Vue.use(Vuetify) Vue.use(Vuelidate) -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) // Boilerplate to prevent the complaint "[Vuetify] Unable to locate target [data-app]" const app: HTMLDivElement = document.createElement('div') @@ -24,7 +24,7 @@ app.setAttribute('data-app', 'true') document.body.append(app) describe('Directors as a COOP', () => { - let vm + let vm: any beforeEach(done => { // init store @@ -161,7 +161,7 @@ describe('Directors as a COOP', () => { }) describe('Directors as a BCOMP', () => { - let vm + let vm: any beforeEach(done => { // init store diff --git a/tests/unit/SummaryOfficeAddresses.spec.ts b/tests/unit/SummaryOfficeAddresses.spec.ts index ac79c5ea1..3fa801f39 100644 --- a/tests/unit/SummaryOfficeAddresses.spec.ts +++ b/tests/unit/SummaryOfficeAddresses.spec.ts @@ -10,7 +10,7 @@ import { EntityTypes } from '@/enums' Vue.use(Vuetify) Vue.use(Vuelidate) -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) // Boilerplate to prevent the complaint "[Vuetify] Unable to locate target [data-app]" const app: HTMLDivElement = document.createElement('div') @@ -18,7 +18,7 @@ app.setAttribute('data-app', 'true') document.body.append(app) describe('OfficeAddresses as a BCOMP', () => { - let vm + let vm: any beforeAll(() => { // init store diff --git a/tests/unit/TodoList.spec.ts b/tests/unit/TodoList.spec.ts index 0c80829b6..e3e962030 100644 --- a/tests/unit/TodoList.spec.ts +++ b/tests/unit/TodoList.spec.ts @@ -24,7 +24,7 @@ Vue.config.silent = true Vue.use(Vuetify) Vue.use(Vuelidate) -let vuetify = new Vuetify({}) +const vuetify = new Vuetify({}) // Boilerplate to prevent the complaint "[Vuetify] Unable to locate target [data-app]" const app: HTMLDivElement = document.createElement('div') @@ -1388,7 +1388,7 @@ describe('TodoList - Delete Draft', () => { const { assign } = window.location let deleteCall - beforeEach(async () => { + beforeEach(() => { deleteCall = sinon.stub(axios, 'delete') }) @@ -1547,7 +1547,7 @@ describe('TodoList - Cancel Payment', () => { const { assign } = window.location let patchCall - beforeEach(async () => { + beforeEach(() => { patchCall = sinon.stub(axios, 'patch') })