feat(test): add LyricsPane component tests

This commit is contained in:
Phan An 2022-05-11 11:12:26 +02:00
parent 9805ad1e44
commit e3145d2a97
No known key found for this signature in database
GPG key ID: A81E4477F0BB6FDC
7 changed files with 92 additions and 22 deletions

View file

@ -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<T> = { [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>('user'))
}
protected mock<T, M extends Methods<Required<T>>> (obj: T, methodName: M, implementation?: any) {
const mock = vi.fn()

View file

@ -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>('user', { is_admin: isAdmin })
const { queryAllByTestId } = this.render(AppHeader)
const { queryAllByTestId } = this.actingAsAdmin().render(AppHeader)
expect(await queryAllByTestId('new-version')).toHaveLength(announcing ? 1 : 0)
}

View file

@ -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>('user')
const { findByTestId } = this.render(AboutKoelModel)
const { findByTestId } = this.actingAsAdmin().render(AboutKoelModel)
findByTestId('new-version-about')
})

View file

@ -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>('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>('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>('user')).renderComponent(factory<Song>('song', {
lyrics: null
}))
expect(await queryByTestId('add-lyrics-btn')).toBeNull()
})
}
}

View file

@ -4,7 +4,7 @@
<template v-if="song">
<div v-show="song.lyrics">
<div ref="lyricsContainer" v-html="song.lyrics"></div>
<Magnifier :target="lyricsContainer"/>
<TextMagnifier :target="lyricsContainer" class="magnifier"/>
</div>
<p v-if="song.id && !song.lyrics" class="none text-secondary">
<template v-if="isAdmin">
@ -26,7 +26,7 @@ import { defineAsyncComponent, ref, toRefs } from 'vue'
import { eventBus } from '@/utils'
import { useAuthorization } from '@/composables'
const Magnifier = defineAsyncComponent(() => import('@/components/ui/TextMagnifier.vue'))
const TextMagnifier = defineAsyncComponent(() => import('@/components/ui/TextMagnifier.vue'))
const props = defineProps<{ song: Song }>()
const { song } = toRefs(props)
@ -43,7 +43,7 @@ const showEditSongForm = () => eventBus.emit('MODAL_SHOW_EDIT_SONG_FORM', song.v
line-height: 1.6;
position: relative;
.text-zoomer {
.magnifier {
opacity: 0;
position: absolute;
top: 0;
@ -54,7 +54,7 @@ const showEditSongForm = () => eventBus.emit('MODAL_SHOW_EDIT_SONG_FORM', song.v
}
}
&:hover .text-zoomer {
&:hover .magnifier {
opacity: .5;
&:hover {

View file

@ -1,12 +1,12 @@
<template>
<div class="text-zoomer">
<button title="Zoom out" @click.prevent="zoom(-1)">
<i class="fa fa-search-minus"></i>
<span>
<button title="Zoom out" type="button" @click.prevent="zoom(-1)">
<i class="fa fa-search-minus"/>
</button>
<button title="Zoom in" @click.prevent="zoom(1)">
<i class="fa fa-search-plus"></i>
<button title="Zoom in" type="button" @click.prevent="zoom(1)">
<i class="fa fa-search-plus"/>
</button>
</div>
</span>
</template>
<script lang="ts" setup>
@ -33,7 +33,7 @@ const zoom = (level: number) => {
</script>
<style lang="scss" scoped>
.text-zoomer {
span {
display: flex;
transition: .2s;
@ -53,12 +53,12 @@ const zoom = (level: number) => {
color: var(--color-text-primary);
}
&:first-of-type {
&:first-child {
border-radius: 4px 0 0 4px;
border-right: 0;
}
&:last-of-type {
&:last-child {
border-radius: 0 4px 4px 0;
}
}

View file

@ -0,0 +1,12 @@
// Vitest Snapshot v1
exports[`renders 1`] = `
"<article id=\\"lyrics\\" data-v-502c43f0=\\"\\">
<div class=\\"content\\" data-v-502c43f0=\\"\\">
<div data-v-502c43f0=\\"\\">
<div data-v-502c43f0=\\"\\">Foo bar baz qux</div><span class=\\"magnifier\\" data-v-4cadbfe6=\\"\\" data-v-502c43f0=\\"\\"><button title=\\"Zoom out\\" type=\\"button\\" data-v-4cadbfe6=\\"\\"><i class=\\"fa fa-search-minus\\" data-v-4cadbfe6=\\"\\"></i></button><button title=\\"Zoom in\\" type=\\"button\\" data-v-4cadbfe6=\\"\\"><i class=\\"fa fa-search-plus\\" data-v-4cadbfe6=\\"\\"></i></button></span>
</div>
<!--v-if-->
</div>
</article>"
`;