feat(test): some missing component tests

This commit is contained in:
Phan An 2024-04-22 23:56:56 +02:00
parent 6a1a874c23
commit 36e65145aa
13 changed files with 106 additions and 9 deletions

View file

@ -1,6 +1,6 @@
import isMobile from 'ismobilejs'
import { isObject, mergeWith } from 'lodash'
import { cleanup, render, RenderOptions } from '@testing-library/vue'
import { cleanup, createEvent, fireEvent, render, RenderOptions } from '@testing-library/vue'
import { afterEach, beforeEach, vi } from 'vitest'
import { defineComponent, nextTick } from 'vue'
import { commonStore, userStore } from '@/stores'
@ -12,6 +12,7 @@ import { routes } from '@/config'
import Router from '@/router'
import userEvent from '@testing-library/user-event'
import { UserEvent } from '@testing-library/user-event/dist/types/setup/setup'
import { EventType } from '@testing-library/dom/types/events'
// A deep-merge function that
// - supports symbols as keys (_.merge doesn't)
@ -184,5 +185,9 @@ export default abstract class UnitTestCase {
await this.user.type(element, value)
}
protected async trigger(element: HTMLElement, key: EventType | string, options?: {}) {
await fireEvent(element, createEvent[key](element, options))
}
protected abstract test ()
}

View file

@ -1,7 +1,7 @@
// Vitest Snapshot v1
exports[`renders 1`] = `
<article data-v-f01bdc56="" class="relative flex max-w-full md:max-w-[256px] border p-5 rounded-lg flex-col gap-5 transition border-color duration-200 full" draggable="true" tabindex="0" title="IV by Led Zeppelin">
<article data-v-f01bdc56="" class="relative flex max-w-full md:max-w-[256px] border p-5 rounded-lg flex-col gap-5 transition border-color duration-200 full" draggable="true" tabindex="0" data-testid="artist-album-card" title="IV by Led Zeppelin">
<div data-v-a14c1d10="" data-v-f01bdc56="" class="cover relative w-full aspect-square bg-no-repeat bg-cover bg-center overflow-hidden rounded-md after:block after:pt-[100%]" style="background-image: url(undefined/resources/assets/img/covers/default.svg);" data-testid="album-artist-thumbnail"><img data-v-a14c1d10="" alt="IV" src="http://loremflickr.com/640/480" class="w-full h-full object-cover absolute left-0 top-0 pointer-events-none before:absolute before:w-full before:h-full before:opacity-0 before:z-[1] before-top-0" loading="lazy"><a data-v-a14c1d10="" class="control control-play h-full w-full absolute flex justify-center items-center" role="button"><span data-v-a14c1d10="" class="hidden">Play all songs in the album IV</span><span data-v-a14c1d10="" class="icon opacity-0 w-1/2 h-1/2 flex justify-center items-center pointer-events-none pl-[4%] rounded-full after:w-full after:h-full"></span></a></div>
<footer data-v-f01bdc56="" class="flex flex-1 flex-col gap-1.5 overflow-hidden">
<div data-v-f01bdc56="" class="name flex flex-col gap-2 whitespace-nowrap"><a href="#/album/42" class="font-medium" data-testid="name">IV</a><a href="#/artist/17">Led Zeppelin</a></div>

View file

@ -1,7 +1,7 @@
// Vitest Snapshot v1
exports[`renders 1`] = `
<article data-v-f01bdc56="" class="relative flex max-w-full md:max-w-[256px] border p-5 rounded-lg flex-col gap-5 transition border-color duration-200 full" draggable="true" tabindex="0" title="Led Zeppelin">
<article data-v-f01bdc56="" class="relative flex max-w-full md:max-w-[256px] border p-5 rounded-lg flex-col gap-5 transition border-color duration-200 full" draggable="true" tabindex="0" data-testid="artist-album-card" title="Led Zeppelin">
<div data-v-a14c1d10="" data-v-f01bdc56="" class="cover relative w-full aspect-square bg-no-repeat bg-cover bg-center overflow-hidden rounded-md after:block after:pt-[100%]" style="background-image: url(undefined/resources/assets/img/covers/default.svg);" data-testid="album-artist-thumbnail"><img data-v-a14c1d10="" alt="Led Zeppelin" src="foo.jpg" class="w-full h-full object-cover absolute left-0 top-0 pointer-events-none before:absolute before:w-full before:h-full before:opacity-0 before:z-[1] before-top-0" loading="lazy"><a data-v-a14c1d10="" class="control control-play h-full w-full absolute flex justify-center items-center" role="button"><span data-v-a14c1d10="" class="hidden">Play all songs by Led Zeppelin</span><span data-v-a14c1d10="" class="icon opacity-0 w-1/2 h-1/2 flex justify-center items-center pointer-events-none pl-[4%] rounded-full after:w-full after:h-full"></span></a></div>
<footer data-v-f01bdc56="" class="flex flex-1 flex-col gap-1.5 overflow-hidden">
<div data-v-f01bdc56="" class="name flex flex-col gap-2 whitespace-nowrap"><a href="#/artist/42" class="font-medium" data-testid="name">Led Zeppelin</a></div>

View file

@ -8,7 +8,7 @@ exports[`renders 1`] = `
<!--v-if-->
</label><label data-v-0b0f87ea="" class="flex flex-col gap-2 text-[1.1rem]">
<!--v-if-->
<div data-v-0b0f87ea="" class="relative"><input class="block text-base w-full px-4 py-2.5 rounded bg-k-bg-input text-k-text-input read-only:bg-gray-400 read-only:text-gray-900 disabled:bg-gray-400 disabled:text-gray-900 w-full" type="password" placeholder="Password" required=""><button class="absolute p-2.5 right-0 top-0 text-k-bg-primary" type="button"><br data-testid="Icon" icon="[object Object]"></button></div>
<div data-v-0b0f87ea="" class="relative"><input class="block text-base w-full px-4 py-2.5 rounded bg-k-bg-input text-k-text-input read-only:bg-gray-400 read-only:text-gray-900 disabled:bg-gray-400 disabled:text-gray-900 w-full" type="password" data-testid="input" placeholder="Password" required=""><button class="absolute p-2.5 right-0 top-0 text-k-bg-primary" type="button" data-testid="toggle"><br data-testid="Icon" icon="[object Object]"></button></div>
<!--v-if-->
</label><label data-v-0b0f87ea="" class="flex flex-col gap-2 text-[1.1rem]">
<!--v-if--><button data-v-8943c846="" data-v-0b0f87ea="" class="text-base text-k-text-primary bg-k-primary px-4 py-2.5 rounded cursor-pointer" type="submit" data-testid="submit">Log In</button>
@ -31,7 +31,7 @@ exports[`shows Google login button 1`] = `
<!--v-if-->
</label><label data-v-0b0f87ea="" class="flex flex-col gap-2 text-[1.1rem]">
<!--v-if-->
<div data-v-0b0f87ea="" class="relative"><input class="block text-base w-full px-4 py-2.5 rounded bg-k-bg-input text-k-text-input read-only:bg-gray-400 read-only:text-gray-900 disabled:bg-gray-400 disabled:text-gray-900 w-full" type="password" placeholder="Password" required=""><button class="absolute p-2.5 right-0 top-0 text-k-bg-primary" type="button"><br data-testid="Icon" icon="[object Object]"></button></div>
<div data-v-0b0f87ea="" class="relative"><input class="block text-base w-full px-4 py-2.5 rounded bg-k-bg-input text-k-text-input read-only:bg-gray-400 read-only:text-gray-900 disabled:bg-gray-400 disabled:text-gray-900 w-full" type="password" data-testid="input" placeholder="Password" required=""><button class="absolute p-2.5 right-0 top-0 text-k-bg-primary" type="button" data-testid="toggle"><br data-testid="Icon" icon="[object Object]"></button></div>
<!--v-if-->
</label><label data-v-0b0f87ea="" class="flex flex-col gap-2 text-[1.1rem]">
<!--v-if--><button data-v-8943c846="" data-v-0b0f87ea="" class="text-base text-k-text-primary bg-k-primary px-4 py-2.5 rounded cursor-pointer" type="submit" data-testid="submit">Log In</button>

View file

@ -0,0 +1,27 @@
import { screen } from '@testing-library/vue'
import { expect, it } from 'vitest'
import UnitTestCase from '@/__tests__/UnitTestCase'
import ArtistAlbumCard from './ArtistAlbumCard.vue'
import factory from '@/__tests__/factory'
new class extends UnitTestCase {
protected test () {
it('emits events on user actions', async () => {
const { emitted } = this.render(ArtistAlbumCard, {
props: {
entity: factory<Album>('album')
}
})
const component = screen.getByTestId('artist-album-card')
await this.trigger(component, 'dblClick')
expect(emitted().dblclick).toBeTruthy()
await this.trigger(component, 'dragStart')
expect(emitted().dragstart).toBeTruthy()
await this.trigger(component, 'contextMenu')
expect(emitted().contextmenu).toBeTruthy()
})
}
}

View file

@ -4,6 +4,7 @@
:class="layout"
draggable="true"
tabindex="0"
data-testid="artist-album-card"
@dblclick="onDblClick"
@dragstart="onDragStart"
@contextmenu.prevent="onContextMenu"

View file

@ -32,7 +32,7 @@ const value = computed({
})
/**
* Since watching the value and update the slider UI proves to be not performant,
* Since watching the value and updating the slider UI proves to be not performant,
* we defined an explicit method to update the UI and expose it so that the
* parent component (Equalizer) can call it when resetting the preset.
*/

View file

@ -16,7 +16,7 @@ new class extends UnitTestCase {
it('emits the input event', async () => {
const { emitted } = this.render(CheckBox)
await this.user.click(screen.getByRole('checkbox'))
await this.trigger(screen.getByRole('checkbox'), 'click')
expect(emitted()['update:modelValue']).toBeTruthy()
})

View file

@ -0,0 +1,20 @@
import { screen } from '@testing-library/vue'
import { expect, it } from 'vitest'
import UnitTestCase from '@/__tests__/UnitTestCase'
import PasswordField from './PasswordField.vue'
new class extends UnitTestCase {
protected test () {
it('renders plain text', async () => {
this.render(PasswordField)
const input = screen.getByTestId('input')
const toggle = screen.getByTestId('toggle')
await this.trigger(toggle, 'click')
expect(input.getAttribute('type')).toBe('text')
await this.trigger(toggle, 'click')
expect(input.getAttribute('type')).toBe('password')
})
}
}

View file

@ -1,7 +1,12 @@
<template>
<div class="relative">
<TextInput v-model="value" :type="type" class="w-full" v-bind="$attrs" />
<button class="absolute p-2.5 right-0 top-0 text-k-bg-primary" type="button" @click.prevent="toggleReveal">
<TextInput v-model="value" :type="type" class="w-full" data-testid="input" v-bind="$attrs" />
<button
class="absolute p-2.5 right-0 top-0 text-k-bg-primary"
type="button"
data-testid="toggle"
@click.prevent="toggleReveal"
>
<Icon v-if="type === 'password'" :icon="faEye" />
<Icon v-else :icon="faEyeSlash" />
</button>

View file

@ -0,0 +1,19 @@
import { screen } from '@testing-library/vue'
import { expect, it } from 'vitest'
import UnitTestCase from '@/__tests__/UnitTestCase'
import TextArea from './TextArea.vue'
new class extends UnitTestCase {
protected test () {
it('emits value', async () => {
const { emitted } = this.render(TextArea)
await this.type(screen.getByRole('textbox'), 'Hi')
expect(emitted()['update:modelValue']).toStrictEqual([
['H'],
['Hi']
])
})
}
}

View file

@ -0,0 +1,19 @@
import { screen } from '@testing-library/vue'
import { expect, it } from 'vitest'
import UnitTestCase from '@/__tests__/UnitTestCase'
import TextInput from './TextInput.vue'
new class extends UnitTestCase {
protected test () {
it('emits value', async () => {
const { emitted } = this.render(TextInput)
await this.type(screen.getByRole('textbox'), 'Hi')
expect(emitted()['update:modelValue']).toStrictEqual([
['H'],
['Hi']
])
})
}
}

View file

@ -9,6 +9,7 @@
<script lang="ts" setup>
import { ref } from 'vue'
import { uuid } from '@/utils'
import MessageToast from '@/components/ui/message-toaster/MessageToast.vue'
const messages = ref<ToastMessage[]>([])