From 258d1f034c11fbd005da224d9cd91a6e3a96f98c Mon Sep 17 00:00:00 2001 From: Jordan Welch Date: Fri, 4 Oct 2024 21:19:00 -0500 Subject: [PATCH 1/2] add `byTestId` helper --- client/src/__tests__/setup.ts | 7 +++++++ client/src/__tests__/test-extensions.d.ts | 7 +++++++ .../__tests__/Notifications.spec.ts | 20 +++++++++---------- .../__tests__/ReminderSubscribe.spec.ts | 17 +++++++--------- .../components/__tests__/RsvpModal.spec.ts | 16 +++++++-------- .../components/week/__tests__/Theme.spec.ts | 4 ++-- 6 files changed, 41 insertions(+), 30 deletions(-) create mode 100644 client/src/__tests__/test-extensions.d.ts diff --git a/client/src/__tests__/setup.ts b/client/src/__tests__/setup.ts index 6ecf842..6f5ee35 100644 --- a/client/src/__tests__/setup.ts +++ b/client/src/__tests__/setup.ts @@ -1,9 +1,16 @@ import createFetchMock from 'vitest-fetch-mock' import { vi } from 'vitest' const fetchMocker = createFetchMock(vi) +import { VueWrapper } from '@vue/test-utils' fetchMocker.enableMocks() HTMLCanvasElement.prototype.getContext = () => { // return whatever getContext has to return } + +// Vue Wrapper helpers + +VueWrapper.prototype.byTestId = function (this: VueWrapper, id: string) { + return this.find(`[data-testid="${id}"]`) +} diff --git a/client/src/__tests__/test-extensions.d.ts b/client/src/__tests__/test-extensions.d.ts new file mode 100644 index 0000000..dd50043 --- /dev/null +++ b/client/src/__tests__/test-extensions.d.ts @@ -0,0 +1,7 @@ +import { VueWrapper } from '@vue/test-utils' + +declare module '@vue/test-utils' { + interface VueWrapper { + byTestId(id: string): VueWrapper; + } +} diff --git a/client/src/components/__tests__/Notifications.spec.ts b/client/src/components/__tests__/Notifications.spec.ts index c2678f0..4e907be 100644 --- a/client/src/components/__tests__/Notifications.spec.ts +++ b/client/src/components/__tests__/Notifications.spec.ts @@ -8,12 +8,12 @@ import { nextTick } from 'vue' import { CheckCircleIcon, ExclamationTriangleIcon, InformationCircleIcon, XCircleIcon } from '@heroicons/vue/24/solid' let wrapper: VueWrapper -let notification: DOMWrapper +let notification: VueWrapper describe('default', () => { beforeEach(() => { wrapper = mount(Notifications) - notification = wrapper.find('[data-testid="notifications"]') + notification = wrapper.byTestId('notifications') }) it('does not display message by default', () => { @@ -26,7 +26,7 @@ describe('show message with default type', () => { wrapper = mount(Notifications) notifications.open('Hello World') await nextTick() - notification = wrapper.find('[data-testid="notifications"]') + notification = wrapper.byTestId('notifications') }) it('should show notifications', () => { @@ -51,7 +51,7 @@ describe('show message with success type', () => { wrapper = mount(Notifications) notifications.open('Hello World', 'success') await nextTick() - notification = wrapper.find('[data-testid="notifications"]') + notification = wrapper.byTestId('notifications') }) it('should display message with correct style', () => { @@ -68,7 +68,7 @@ describe('show message with warning type', () => { wrapper = mount(Notifications) notifications.open('Hello World', 'warning') await nextTick() - notification = wrapper.find('[data-testid="notifications"]') + notification = wrapper.byTestId('notifications') }) it('should display message with correct style', () => { @@ -85,7 +85,7 @@ describe('show message with error type', () => { wrapper = mount(Notifications) notifications.open('Hello World', 'error') await nextTick() - notification = wrapper.find('[data-testid="notifications"]') + notification = wrapper.byTestId('notifications') }) it('should display message with correct style', () => { @@ -106,12 +106,12 @@ describe('message open', () => { it('should close message', async () => { const wrapper = mount(Notifications) - const close = wrapper.find('[data-testid="notifications-close"]') + const close = wrapper.byTestId('notifications-close') close.trigger('click') await nextTick() - expect(wrapper.find('[data-testid="notifications"]').exists()).toBe(false) + expect(wrapper.byTestId('notifications').exists()).toBe(false) }) }) }) @@ -124,7 +124,7 @@ describe('Message called via query param', () => { wrapper = mount(Notifications) await nextTick() - notification = wrapper.find('[data-testid="notifications"]') + notification = wrapper.byTestId('notifications') }) it('should display info message', async () => { @@ -142,7 +142,7 @@ describe('Message called via query param with type', () => { wrapper = mount(Notifications) await nextTick() - notification = wrapper.find('[data-testid="notifications"]') + notification = wrapper.byTestId('notifications') }) it('should display success message', async () => { diff --git a/client/src/components/__tests__/ReminderSubscribe.spec.ts b/client/src/components/__tests__/ReminderSubscribe.spec.ts index 12ea850..f7d5c2c 100644 --- a/client/src/components/__tests__/ReminderSubscribe.spec.ts +++ b/client/src/components/__tests__/ReminderSubscribe.spec.ts @@ -7,9 +7,6 @@ import { nextTick } from 'vue' let wrapper: VueWrapper -const subscribeSelector = '[data-testid="subscribe-button"]' -const getRemindersSelector = '[data-testid="get-reminders-button"]' - globalThis.fetch = vi.fn() beforeAll(() => { @@ -25,7 +22,7 @@ beforeEach(() => { }) it('renders "Get Reminders" button with unopened style', () => { - const button = wrapper.find(getRemindersSelector) + const button = wrapper.byTestId('get-reminders-button') expect(button.text()).toBe('Get Reminders!') expect(button.classes()).toContain('text-white') @@ -38,7 +35,7 @@ describe('press the "Get Reminders" button', () => { }) it('renders "Get Reminders" button with opened style', () => { - const button = wrapper.find(getRemindersSelector) + const button = wrapper.byTestId('get-reminders-button') expect(button.text()).toBe('Get Reminders!') expect(button.classes()).toContain('text-mint') @@ -50,7 +47,7 @@ describe('press the "Get Reminders" button', () => { }) it('shows a "Subscribe" button', () => { - expect(wrapper.find(subscribeSelector).exists()).toBe(true) + expect(wrapper.byTestId('subscribe-button').exists()).toBe(true) }) describe('enter email and subscribe with success', () => { @@ -63,7 +60,7 @@ describe('press the "Get Reminders" button', () => { }) await wrapper.find('input').setValue('test@example.com') - await wrapper.find(subscribeSelector).trigger('click') + await wrapper.byTestId('subscribe-button').trigger('click') await nextTick() }) @@ -77,7 +74,7 @@ describe('press the "Get Reminders" button', () => { it('closes the input', async () => { expect(wrapper.find('input').exists()).toBe(false) - expect(wrapper.find(subscribeSelector).exists()).toBe(false) + expect(wrapper.byTestId('subscribe-button').exists()).toBe(false) }) }) @@ -92,12 +89,12 @@ describe('press the "Get Reminders" button', () => { }) await wrapper.find('input').setValue('test@example.com') - await wrapper.find(subscribeSelector).trigger('click') + await wrapper.byTestId('subscribe-button').trigger('click') }) it('does not close the input', async () => { expect(wrapper.find('input').exists()).toBe(true) - expect(wrapper.find(subscribeSelector).exists()).toBe(true) + expect(wrapper.byTestId('subscribe-button').exists()).toBe(true) }) }) }) diff --git a/client/src/components/__tests__/RsvpModal.spec.ts b/client/src/components/__tests__/RsvpModal.spec.ts index 479f294..f9a05b2 100644 --- a/client/src/components/__tests__/RsvpModal.spec.ts +++ b/client/src/components/__tests__/RsvpModal.spec.ts @@ -23,8 +23,8 @@ describe('name and email already set', () => { rsvpModal.open(week) const wrapper = mount(RsvpModal) - expect(wrapper.find('[data-testid="input-name"]').element.value).toEqual('John Doe') - expect(wrapper.find('[data-testid="input-email"]').element.value).toEqual('jdoe@example.com') + expect(wrapper.byTestId('input-name').element.value).toEqual('John Doe') + expect(wrapper.byTestId('input-email').element.value).toEqual('jdoe@example.com') }) }) @@ -34,7 +34,7 @@ describe('nothing input', () => { rsvpModal.open(week) const wrapper = mount(RsvpModal) - expect(wrapper.find('[data-testid="rsvp-button"]').attributes('disabled')).toBe('') + expect(wrapper.byTestId('rsvp-button').attributes('disabled')).toBe('') }) }) @@ -44,9 +44,9 @@ describe('only name input', () => { rsvpModal.open(week) const wrapper = mount(RsvpModal) - await wrapper.find('[data-testid="input-name"]').setValue('John Doe') + await wrapper.byTestId('input-name').setValue('John Doe') - expect(wrapper.find('[data-testid="rsvp-button"]').attributes('disabled')).toBe(undefined) + expect(wrapper.byTestId('rsvp-button').attributes('disabled')).toBe(undefined) }) }) @@ -62,10 +62,10 @@ describe('rsvp submit', () => { }) rsvpModal.open(week) const wrapper = mount(RsvpModal) - await wrapper.find('[data-testid="input-name"]').setValue('John Doe') - await wrapper.find('[data-testid="input-email"]').setValue('jdoe@example.com') + await wrapper.byTestId('input-name').setValue('John Doe') + await wrapper.byTestId('input-email').setValue('jdoe@example.com') - await wrapper.find('[data-testid="rsvp-button"]').trigger('click') + await wrapper.byTestId('rsvp-button').trigger('click') }) it('calls api with the correct data', async () => { diff --git a/client/src/components/week/__tests__/Theme.spec.ts b/client/src/components/week/__tests__/Theme.spec.ts index 1e05540..6640ad1 100644 --- a/client/src/components/week/__tests__/Theme.spec.ts +++ b/client/src/components/week/__tests__/Theme.spec.ts @@ -42,7 +42,7 @@ describe('Styled theme', () => { props: { week }, }) - const component = wrapper.find('[data-testid="theme"]') + const component = wrapper.byTestId('theme') expect(component.exists()).toBe(true) expect(component.element.children[0].innerHTML).toBe('The') expect(component.element.children[0].classList).toContain('font-bold') @@ -83,7 +83,7 @@ describe('Week skipped', () => { props: { week }, }) - const component = wrapper.find('[data-testid="theme"]') + const component = wrapper.byTestId('theme') expect(component.exists()).toBe(true) expect(component.element.children[0].innerHTML).toBe('The') expect(component.element.children[0].classList).toContain('font-bold') From d4bb01161191ddae3d3e38533b44993ecd32e3a8 Mon Sep 17 00:00:00 2001 From: Jordan Welch Date: Fri, 4 Oct 2024 21:28:04 -0500 Subject: [PATCH 2/2] Fix lint problems --- client/src/__tests__/test-extensions.d.ts | 2 +- client/src/components/__tests__/Notifications.spec.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/__tests__/test-extensions.d.ts b/client/src/__tests__/test-extensions.d.ts index dd50043..a1490d4 100644 --- a/client/src/__tests__/test-extensions.d.ts +++ b/client/src/__tests__/test-extensions.d.ts @@ -1,4 +1,4 @@ -import { VueWrapper } from '@vue/test-utils' +import { VueWrapper } from '@vue/test-utils' // eslint-disable-line declare module '@vue/test-utils' { interface VueWrapper { diff --git a/client/src/components/__tests__/Notifications.spec.ts b/client/src/components/__tests__/Notifications.spec.ts index 4e907be..ed4fb79 100644 --- a/client/src/components/__tests__/Notifications.spec.ts +++ b/client/src/components/__tests__/Notifications.spec.ts @@ -1,7 +1,7 @@ /** @vitest-environment jsdom */ import { beforeEach, describe, expect, it } from 'vitest' -import { DOMWrapper, VueWrapper, mount } from '@vue/test-utils' +import { VueWrapper, mount } from '@vue/test-utils' import Notifications from '@components/Notifications.vue' import { notifications } from '@client/state/notificationState' import { nextTick } from 'vue'