From e3145d2a971a08ace938cb338fbfc65bdb92946e Mon Sep 17 00:00:00 2001 From: Phan An Date: Wed, 11 May 2022 11:12:26 +0200 Subject: [PATCH] feat(test): add LyricsPane component tests --- .../assets/js/__tests__/ComponentTestCase.ts | 12 ++++- .../js/components/layout/AppHeader.spec.ts | 5 +- .../js/components/meta/AboutKoelModal.spec.ts | 6 +-- .../js/components/ui/LyricsPane.spec.ts | 53 +++++++++++++++++++ .../assets/js/components/ui/LyricsPane.vue | 8 +-- .../assets/js/components/ui/TextMagnifier.vue | 18 +++---- .../ui/__snapshots__/LyricsPane.spec.ts.snap | 12 +++++ 7 files changed, 92 insertions(+), 22 deletions(-) create mode 100644 resources/assets/js/components/ui/LyricsPane.spec.ts create mode 100644 resources/assets/js/components/ui/__snapshots__/LyricsPane.spec.ts.snap diff --git a/resources/assets/js/__tests__/ComponentTestCase.ts b/resources/assets/js/__tests__/ComponentTestCase.ts index af6c0c0f..d5c02d15 100644 --- a/resources/assets/js/__tests__/ComponentTestCase.ts +++ b/resources/assets/js/__tests__/ComponentTestCase.ts @@ -4,7 +4,8 @@ import { cleanup, render, RenderOptions } from '@testing-library/vue' import { afterEach, beforeEach, vi } from 'vitest' import { clickaway, droppable, focus } from '@/directives' import { defineComponent, nextTick } from 'vue' -import { commonStore } from '@/stores' +import { commonStore, userStore } from '@/stores' +import factory from '@/__tests__/factory' declare type Methods = { [K in keyof T]: T[K] extends Closure ? K : never; }[keyof T] & (string | symbol); @@ -34,6 +35,15 @@ export default abstract class ComponentTestCase { }) } + protected actingAs (user: User) { + userStore.state.current = user + return this + } + + protected actingAsAdmin () { + return this.actingAs(factory.states('admin')('user')) + } + protected mock>> (obj: T, methodName: M, implementation?: any) { const mock = vi.fn() diff --git a/resources/assets/js/components/layout/AppHeader.spec.ts b/resources/assets/js/components/layout/AppHeader.spec.ts index 8accc94e..6902d639 100644 --- a/resources/assets/js/components/layout/AppHeader.spec.ts +++ b/resources/assets/js/components/layout/AppHeader.spec.ts @@ -3,8 +3,6 @@ import { fireEvent, queryAllByTestId } from '@testing-library/vue' import { eventBus } from '@/utils' import isMobile from 'ismobilejs' import compareVersions from 'compare-versions' -import { userStore } from '@/stores' -import factory from '@/__tests__/factory' import ComponentTestCase from '@/__tests__/ComponentTestCase' import AppHeader from './AppHeader.vue' import SearchForm from '@/components/ui/SearchForm.vue' @@ -44,9 +42,8 @@ new class extends ComponentTestCase { 'announces a new version if applicable', async (hasNewVersion, isAdmin, announcing) => { this.mock(compareVersions, 'compare', hasNewVersion) - userStore.state.current = factory('user', { is_admin: isAdmin }) - const { queryAllByTestId } = this.render(AppHeader) + const { queryAllByTestId } = this.actingAsAdmin().render(AppHeader) expect(await queryAllByTestId('new-version')).toHaveLength(announcing ? 1 : 0) } diff --git a/resources/assets/js/components/meta/AboutKoelModal.spec.ts b/resources/assets/js/components/meta/AboutKoelModal.spec.ts index 1e047c4a..4d4d9555 100644 --- a/resources/assets/js/components/meta/AboutKoelModal.spec.ts +++ b/resources/assets/js/components/meta/AboutKoelModal.spec.ts @@ -1,6 +1,5 @@ import { expect, it } from 'vitest' -import { commonStore, userStore } from '@/stores' -import factory from '@/__tests__/factory' +import { commonStore } from '@/stores' import ComponentTestCase from '@/__tests__/ComponentTestCase' import AboutKoelModel from './AboutKoelModal.vue' import Btn from '@/components/ui/Btn.vue' @@ -29,8 +28,7 @@ new class extends ComponentTestCase { it('shows new version', () => { commonStore.state.currentVersion = 'v1.0.0' commonStore.state.latestVersion = 'v1.0.1' - userStore.state.current = factory.states('admin')('user') - const { findByTestId } = this.render(AboutKoelModel) + const { findByTestId } = this.actingAsAdmin().render(AboutKoelModel) findByTestId('new-version-about') }) diff --git a/resources/assets/js/components/ui/LyricsPane.spec.ts b/resources/assets/js/components/ui/LyricsPane.spec.ts new file mode 100644 index 00000000..a98788dc --- /dev/null +++ b/resources/assets/js/components/ui/LyricsPane.spec.ts @@ -0,0 +1,53 @@ +import { expect, it } from 'vitest' +import ComponentTestCase from '@/__tests__/ComponentTestCase' +import factory from '@/__tests__/factory' +import { eventBus } from '@/utils' +import { fireEvent } from '@testing-library/vue' +import LyricsPane from './LyricsPane.vue' +import TextMagnifier from '@/components/ui/TextMagnifier.vue' + +new class extends ComponentTestCase { + private renderComponent (song?: Song) { + song = song || factory('song', { + lyrics: 'Foo bar baz qux' + }) + + return this.render(LyricsPane, { + props: { + song + }, + global: { + stubs: { + TextMagnifier + } + } + }) + } + + protected test () { + it('renders', () => { + expect(this.renderComponent().html()).toMatchSnapshot() + }) + + it('provides a button to add lyrics if current user is admin', async () => { + const song = factory('song', { + lyrics: null + }) + + const mock = this.mock(eventBus, 'emit') + const { getByTestId } = this.actingAsAdmin().renderComponent(song) + + await fireEvent.click(getByTestId('add-lyrics-btn')) + + expect(mock).toHaveBeenCalledWith('MODAL_SHOW_EDIT_SONG_FORM', song, 'lyrics') + }) + + it('does not have a button to add lyrics if current user is not an admin', async () => { + const { queryByTestId } = this.actingAs(factory('user')).renderComponent(factory('song', { + lyrics: null + })) + + expect(await queryByTestId('add-lyrics-btn')).toBeNull() + }) + } +} diff --git a/resources/assets/js/components/ui/LyricsPane.vue b/resources/assets/js/components/ui/LyricsPane.vue index d1c67472..326c110e 100644 --- a/resources/assets/js/components/ui/LyricsPane.vue +++ b/resources/assets/js/components/ui/LyricsPane.vue @@ -4,7 +4,7 @@