mirror of
https://github.com/koel/koel
synced 2024-11-10 06:34:14 +00:00
chore(test): improve client unit tests with user-event and screen (#1606)
This commit is contained in:
parent
7e327f5a0e
commit
20bded3bca
105 changed files with 904 additions and 679 deletions
|
@ -43,8 +43,8 @@
|
|||
"@babel/preset-env": "^7.9.6",
|
||||
"@faker-js/faker": "^6.2.0",
|
||||
"@floating-ui/dom": "^1.0.3",
|
||||
"@testing-library/cypress": "^8.0.2",
|
||||
"@testing-library/vue": "^6.5.1",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@testing-library/vue": "^6.6.1",
|
||||
"@types/axios": "^0.14.0",
|
||||
"@types/blueimp-md5": "^2.7.0",
|
||||
"@types/local-storage": "^1.4.0",
|
||||
|
|
|
@ -10,6 +10,8 @@ import { DialogBoxKey, MessageToasterKey, OverlayKey, RouterKey } from '@/symbol
|
|||
import { DialogBoxStub, MessageToasterStub, OverlayStub } from '@/__tests__/stubs'
|
||||
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'
|
||||
|
||||
// A deep-merge function that
|
||||
// - supports symbols as keys (_.merge doesn't)
|
||||
|
@ -27,10 +29,13 @@ const deepMerge = (first: object, second: object) => {
|
|||
export default abstract class UnitTestCase {
|
||||
private backupMethods = new Map()
|
||||
protected router: Router
|
||||
protected user: UserEvent
|
||||
|
||||
public constructor () {
|
||||
this.router = new Router(routes)
|
||||
this.mock(http, 'request') // prevent actual HTTP requests from being made
|
||||
this.user = userEvent.setup({ delay: null }) // @see https://github.com/testing-library/user-event/issues/833
|
||||
|
||||
this.beforeEach()
|
||||
this.afterEach()
|
||||
this.test()
|
||||
|
@ -150,5 +155,10 @@ export default abstract class UnitTestCase {
|
|||
})
|
||||
}
|
||||
|
||||
protected async type (element: HTMLElement, value: string) {
|
||||
await this.user.clear(element)
|
||||
await this.user.type(element, value)
|
||||
}
|
||||
|
||||
protected abstract test ()
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import { downloadService, playbackService } from '@/services'
|
||||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import AlbumCard from './AlbumCard.vue'
|
||||
import { songStore } from '@/stores'
|
||||
import { commonStore, songStore } from '@/stores'
|
||||
|
||||
let album: Album
|
||||
|
||||
|
@ -34,20 +34,27 @@ new class extends UnitTestCase {
|
|||
|
||||
it('downloads', async () => {
|
||||
const mock = this.mock(downloadService, 'fromAlbum')
|
||||
const { getByTestId } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTestId('download-album'))
|
||||
await this.user.click(screen.getByTitle('Download all songs in the album IV'))
|
||||
|
||||
expect(mock).toHaveBeenCalledTimes(1)
|
||||
})
|
||||
|
||||
it('does not have an option to download if downloading is disabled', async () => {
|
||||
commonStore.state.allow_download = false
|
||||
this.renderComponent()
|
||||
|
||||
expect(screen.queryByText('Download')).toBeNull()
|
||||
})
|
||||
|
||||
it('shuffles', async () => {
|
||||
const songs = factory<Song>('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(songs)
|
||||
const shuffleMock = this.mock(playbackService, 'queueAndPlay').mockResolvedValue(void 0)
|
||||
const { getByTestId } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTestId('shuffle-album'))
|
||||
await this.user.click(screen.getByTitle('Shuffle all songs in the album IV'))
|
||||
await this.tick()
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(album)
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
<a
|
||||
:title="`Shuffle all songs in the album ${album.name}`"
|
||||
class="shuffle-album"
|
||||
data-testid="shuffle-album"
|
||||
href
|
||||
role="button"
|
||||
@click.prevent="shuffle"
|
||||
|
@ -29,7 +28,6 @@
|
|||
v-if="allowDownload"
|
||||
:title="`Download all songs in the album ${album.name}`"
|
||||
class="download-album"
|
||||
data-testid="download-album"
|
||||
href
|
||||
role="button"
|
||||
@click.prevent="download"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { eventBus } from '@/utils'
|
||||
|
@ -15,25 +16,22 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
const rendered = this.render(AlbumContextMenu)
|
||||
eventBus.emit('ALBUM_CONTEXT_MENU_REQUESTED', { pageX: 420, pageY: 42 }, album)
|
||||
eventBus.emit('ALBUM_CONTEXT_MENU_REQUESTED', { pageX: 420, pageY: 42 } as MouseEvent, album)
|
||||
await this.tick(2)
|
||||
|
||||
return rendered
|
||||
}
|
||||
|
||||
protected test () {
|
||||
it('renders', async () => {
|
||||
const { html } = await this.renderComponent()
|
||||
expect(html()).toMatchSnapshot()
|
||||
})
|
||||
it('renders', async () => expect((await this.renderComponent()).html()).toMatchSnapshot())
|
||||
|
||||
it('plays all', async () => {
|
||||
const songs = factory<Song>('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
|
||||
const { getByText } = await this.renderComponent()
|
||||
await getByText('Play All').click()
|
||||
await this.renderComponent()
|
||||
await this.user.click(screen.getByText('Play All'))
|
||||
await this.tick()
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(album)
|
||||
|
@ -45,8 +43,8 @@ new class extends UnitTestCase {
|
|||
const fetchMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
|
||||
const { getByText } = await this.renderComponent()
|
||||
await getByText('Shuffle All').click()
|
||||
await this.renderComponent()
|
||||
await this.user.click(screen.getByText('Shuffle All'))
|
||||
await this.tick()
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(album)
|
||||
|
@ -55,42 +53,42 @@ new class extends UnitTestCase {
|
|||
|
||||
it('downloads', async () => {
|
||||
const downloadMock = this.mock(downloadService, 'fromAlbum')
|
||||
await this.renderComponent()
|
||||
|
||||
const { getByText } = await this.renderComponent()
|
||||
await getByText('Download').click()
|
||||
await this.user.click(screen.getByText('Download'))
|
||||
|
||||
expect(downloadMock).toHaveBeenCalledWith(album)
|
||||
})
|
||||
|
||||
it('does not have an option to download if downloading is disabled', async () => {
|
||||
commonStore.state.allow_download = false
|
||||
const { queryByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
expect(queryByText('Download')).toBeNull()
|
||||
expect(screen.queryByText('Download')).toBeNull()
|
||||
})
|
||||
|
||||
it('goes to album', async () => {
|
||||
const mock = this.mock(this.router, 'go')
|
||||
const { getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await getByText('Go to Album').click()
|
||||
await this.user.click(screen.getByText('Go to Album'))
|
||||
|
||||
expect(mock).toHaveBeenCalledWith(`album/${album.id}`)
|
||||
})
|
||||
|
||||
it('does not have an option to download or go to Unknown Album and Artist', async () => {
|
||||
const { queryByTestId } = await this.renderComponent(factory.states('unknown')<Album>('album'))
|
||||
await this.renderComponent(factory.states('unknown')<Album>('album'))
|
||||
|
||||
expect(queryByTestId('view-album')).toBeNull()
|
||||
expect(queryByTestId('view-artist')).toBeNull()
|
||||
expect(queryByTestId('download')).toBeNull()
|
||||
expect(screen.queryByText('Go to Album')).toBeNull()
|
||||
expect(screen.queryByText('Go to Artist')).toBeNull()
|
||||
expect(screen.queryByText('Download')).toBeNull()
|
||||
})
|
||||
|
||||
it('goes to artist', async () => {
|
||||
const mock = this.mock(this.router, 'go')
|
||||
const { getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await getByText('Go to Artist').click()
|
||||
await this.user.click(screen.getByText('Go to Artist'))
|
||||
|
||||
expect(mock).toHaveBeenCalledWith(`artist/${album.artist_id}`)
|
||||
})
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<ContextMenuBase ref="base" data-testid="album-context-menu" extra-class="album-menu">
|
||||
<template v-if="album">
|
||||
<li data-testid="play" @click="play">Play All</li>
|
||||
<li data-testid="shuffle" @click="shuffle">Shuffle All</li>
|
||||
<li @click="play">Play All</li>
|
||||
<li @click="shuffle">Shuffle All</li>
|
||||
<li class="separator"></li>
|
||||
<li v-if="isStandardAlbum" data-testid="view-album" @click="viewAlbumDetails">Go to Album</li>
|
||||
<li v-if="isStandardArtist" data-testid="view-artist" @click="viewArtistDetails">Go to Artist</li>
|
||||
<li v-if="isStandardAlbum" @click="viewAlbumDetails">Go to Album</li>
|
||||
<li v-if="isStandardArtist" @click="viewArtistDetails">Go to Artist</li>
|
||||
<template v-if="isStandardAlbum && allowDownload">
|
||||
<li class="separator"></li>
|
||||
<li data-testid="download" @click="download">Download</li>
|
||||
<li @click="download">Download</li>
|
||||
</template>
|
||||
</template>
|
||||
</ContextMenuBase>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { screen } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { commonStore, songStore } from '@/stores'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { mediaInfoService, playbackService } from '@/services'
|
||||
import AlbumInfoComponent from './AlbumInfo.vue'
|
||||
|
||||
|
@ -40,44 +40,44 @@ new class extends UnitTestCase {
|
|||
|
||||
protected test () {
|
||||
it.each<[MediaInfoDisplayMode]>([['aside'], ['full']])('renders in %s mode', async (mode) => {
|
||||
const { getByTestId, queryByTestId } = await this.renderComponent(mode)
|
||||
await this.renderComponent(mode)
|
||||
|
||||
getByTestId('album-info-tracks')
|
||||
screen.getByTestId('album-info-tracks')
|
||||
|
||||
if (mode === 'aside') {
|
||||
getByTestId('thumbnail')
|
||||
screen.getByTestId('thumbnail')
|
||||
} else {
|
||||
expect(queryByTestId('thumbnail')).toBeNull()
|
||||
expect(screen.queryByTestId('thumbnail')).toBeNull()
|
||||
}
|
||||
|
||||
expect(getByTestId('album-info').classList.contains(mode)).toBe(true)
|
||||
expect(screen.getByTestId('album-info').classList.contains(mode)).toBe(true)
|
||||
})
|
||||
|
||||
it('triggers showing full wiki for aside mode', async () => {
|
||||
const { getByTestId, queryByTestId } = await this.renderComponent('aside')
|
||||
expect(queryByTestId('full')).toBeNull()
|
||||
await this.renderComponent('aside')
|
||||
expect(screen.queryByTestId('full')).toBeNull()
|
||||
|
||||
await fireEvent.click(getByTestId('more-btn'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Full Wiki' }))
|
||||
|
||||
expect(queryByTestId('summary')).toBeNull()
|
||||
expect(queryByTestId('full')).not.toBeNull()
|
||||
expect(screen.queryByTestId('summary')).toBeNull()
|
||||
screen.getByTestId('full')
|
||||
})
|
||||
|
||||
it('shows full wiki for full mode', async () => {
|
||||
const { queryByTestId } = await this.renderComponent('full')
|
||||
await this.renderComponent('full')
|
||||
|
||||
expect(queryByTestId('full')).not.toBeNull()
|
||||
expect(queryByTestId('summary')).toBeNull()
|
||||
expect(queryByTestId('more-btn')).toBeNull()
|
||||
screen.getByTestId('full')
|
||||
expect(screen.queryByTestId('summary')).toBeNull()
|
||||
expect(screen.queryByRole('button', { name: 'Full Wiki' })).toBeNull()
|
||||
})
|
||||
|
||||
it('plays', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const fetchMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const { getByTitle } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTitle('Play all songs in IV'))
|
||||
await this.user.click(screen.getByTitle('Play all songs in IV'))
|
||||
await this.tick(2)
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(album)
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<div v-if="showSummary" class="summary" data-testid="summary" v-html="info.wiki.summary"/>
|
||||
<div v-if="showFull" class="full" data-testid="full" v-html="info.wiki.full"/>
|
||||
|
||||
<button v-if="showSummary" class="more" data-testid="more-btn" @click.prevent="showingFullWiki = true">
|
||||
<button v-if="showSummary" class="more" @click.prevent="showingFullWiki = true">
|
||||
Full Wiki
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { screen } from '@testing-library/vue'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
|
@ -10,7 +11,7 @@ new class extends UnitTestCase {
|
|||
const album = factory<Album>('album')
|
||||
const fetchMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(factory<Song>('song', 5))
|
||||
|
||||
const { queryAllByTestId } = this.render(AlbumTrackList, {
|
||||
this.render(AlbumTrackList, {
|
||||
props: {
|
||||
album,
|
||||
tracks: factory<AlbumTrack>('album-track', 3)
|
||||
|
@ -20,7 +21,7 @@ new class extends UnitTestCase {
|
|||
await this.tick()
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(album)
|
||||
expect(queryAllByTestId('album-track-item')).toHaveLength(3)
|
||||
expect(screen.queryAllByTestId('album-track-item')).toHaveLength(3)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { queueStore, songStore } from '@/stores'
|
||||
|
@ -45,9 +45,9 @@ new class extends UnitTestCase {
|
|||
const queueMock = this.mock(queueStore, 'queueIfNotQueued')
|
||||
const playMock = this.mock(playbackService, 'play')
|
||||
|
||||
const { getByTitle } = this.renderComponent(matchedSong)
|
||||
this.renderComponent(matchedSong)
|
||||
|
||||
await fireEvent.click(getByTitle('Click to play'))
|
||||
await this.user.click(screen.getByTitle('Click to play'))
|
||||
|
||||
expect(queueMock).toHaveBeenNthCalledWith(1, matchedSong)
|
||||
expect(playMock).toHaveBeenNthCalledWith(1, matchedSong)
|
||||
|
|
|
@ -4,7 +4,7 @@ exports[`renders 1`] = `
|
|||
<article class="item full" draggable="true" tabindex="0" title="IV by Led Zeppelin" data-v-f01bdc56=""><br data-testid="thumbnail" entity="[object Object]" data-v-f01bdc56="">
|
||||
<footer data-v-f01bdc56="">
|
||||
<div class="name" data-v-f01bdc56=""><a href="#/album/42" class="text-normal" data-testid="name">IV</a><a href="#/artist/17">Led Zeppelin</a></div>
|
||||
<p class="meta" data-v-f01bdc56=""><a title="Shuffle all songs in the album IV" class="shuffle-album" data-testid="shuffle-album" href="" role="button"> Shuffle </a><a title="Download all songs in the album IV" class="download-album" data-testid="download-album" href="" role="button"> Download </a></p>
|
||||
<p class="meta" data-v-f01bdc56=""><a title="Shuffle all songs in the album IV" class="shuffle-album" href="" role="button"> Shuffle </a><a title="Download all songs in the album IV" class="download-album" href="" role="button"> Download </a></p>
|
||||
</footer>
|
||||
</article>
|
||||
`;
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
exports[`renders 1`] = `
|
||||
<nav class="album-menu menu context-menu" style="top: 42px; left: 420px;" tabindex="0" data-testid="album-context-menu" data-v-0408531a="">
|
||||
<ul data-v-0408531a="">
|
||||
<li data-testid="play">Play All</li>
|
||||
<li data-testid="shuffle">Shuffle All</li>
|
||||
<li>Play All</li>
|
||||
<li>Shuffle All</li>
|
||||
<li class="separator"></li>
|
||||
<li data-testid="view-album">Go to Album</li>
|
||||
<li data-testid="view-artist">Go to Artist</li>
|
||||
<li>Go to Album</li>
|
||||
<li>Go to Artist</li>
|
||||
<li class="separator"></li>
|
||||
<li data-testid="download">Download</li>
|
||||
<li>Download</li>
|
||||
</ul>
|
||||
</nav>
|
||||
`;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { downloadService, playbackService } from '@/services'
|
||||
|
@ -36,19 +36,17 @@ new class extends UnitTestCase {
|
|||
|
||||
it('downloads', async () => {
|
||||
const mock = this.mock(downloadService, 'fromArtist')
|
||||
this.renderComponent()
|
||||
|
||||
const { getByTestId } = this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTestId('download-artist'))
|
||||
await this.user.click(screen.getByTitle('Download all songs by Led Zeppelin'))
|
||||
expect(mock).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('does not have an option to download if downloading is disabled', async () => {
|
||||
commonStore.state.allow_download = false
|
||||
this.renderComponent()
|
||||
|
||||
const { queryByTestId } = this.renderComponent()
|
||||
|
||||
expect(queryByTestId('download-artist')).toBeNull()
|
||||
expect(screen.queryByText('Download')).toBeNull()
|
||||
})
|
||||
|
||||
it('shuffles', async () => {
|
||||
|
@ -56,9 +54,9 @@ new class extends UnitTestCase {
|
|||
const fetchMock = this.mock(songStore, 'fetchForArtist').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
|
||||
const { getByTestId } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTestId('shuffle-artist'))
|
||||
await this.user.click(screen.getByTitle('Shuffle all songs by Led Zeppelin'))
|
||||
await this.tick()
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(artist)
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
<a
|
||||
:title="`Shuffle all songs by ${artist.name}`"
|
||||
class="shuffle-artist"
|
||||
data-testid="shuffle-artist"
|
||||
href
|
||||
role="button"
|
||||
@click.prevent="shuffle"
|
||||
|
@ -26,7 +25,6 @@
|
|||
v-if="allowDownload"
|
||||
:title="`Download all songs by ${artist.name}`"
|
||||
class="download-artist"
|
||||
data-testid="download-artist"
|
||||
href
|
||||
role="button"
|
||||
@click.prevent="download"
|
||||
|
|
|
@ -5,6 +5,7 @@ import { eventBus } from '@/utils'
|
|||
import { downloadService, playbackService } from '@/services'
|
||||
import { commonStore, songStore } from '@/stores'
|
||||
import ArtistContextMenu from './ArtistContextMenu.vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
|
||||
let artist: Artist
|
||||
|
||||
|
@ -22,18 +23,15 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
protected test () {
|
||||
it('renders', async () => {
|
||||
const { html } = await this.renderComponent()
|
||||
expect(html()).toMatchSnapshot()
|
||||
})
|
||||
it('renders', async () => expect((await this.renderComponent()).html()).toMatchSnapshot())
|
||||
|
||||
it('plays all', async () => {
|
||||
const songs = factory<Song>('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForArtist').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
|
||||
const { getByText } = await this.renderComponent()
|
||||
await getByText('Play All').click()
|
||||
await this.renderComponent()
|
||||
await screen.getByText('Play All').click()
|
||||
await this.tick()
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(artist)
|
||||
|
@ -45,8 +43,8 @@ new class extends UnitTestCase {
|
|||
const fetchMock = this.mock(songStore, 'fetchForArtist').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
|
||||
const { getByText } = await this.renderComponent()
|
||||
await getByText('Shuffle All').click()
|
||||
await this.renderComponent()
|
||||
await screen.getByText('Shuffle All').click()
|
||||
await this.tick()
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(artist)
|
||||
|
@ -56,40 +54,40 @@ new class extends UnitTestCase {
|
|||
it('downloads', async () => {
|
||||
const mock = this.mock(downloadService, 'fromArtist')
|
||||
|
||||
const { getByText } = await this.renderComponent()
|
||||
await getByText('Download').click()
|
||||
await this.renderComponent()
|
||||
await screen.getByText('Download').click()
|
||||
|
||||
expect(mock).toHaveBeenCalledWith(artist)
|
||||
})
|
||||
|
||||
it('does not have an option to download if downloading is disabled', async () => {
|
||||
commonStore.state.allow_download = false
|
||||
const { queryByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
expect(queryByText('Download')).toBeNull()
|
||||
expect(screen.queryByText('Download')).toBeNull()
|
||||
})
|
||||
|
||||
it('goes to artist', async () => {
|
||||
const mock = this.mock(this.router, 'go')
|
||||
const { getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await getByText('Go to Artist').click()
|
||||
await screen.getByText('Go to Artist').click()
|
||||
|
||||
expect(mock).toHaveBeenCalledWith(`artist/${artist.id}`)
|
||||
})
|
||||
|
||||
it('does not have an option to download or go to Unknown Artist', async () => {
|
||||
const { queryByTestId } = await this.renderComponent(factory.states('unknown')<Artist>('artist'))
|
||||
await this.renderComponent(factory.states('unknown')<Artist>('artist'))
|
||||
|
||||
expect(queryByTestId('view-artist')).toBeNull()
|
||||
expect(queryByTestId('download')).toBeNull()
|
||||
expect(screen.queryByText('Go to Artist')).toBeNull()
|
||||
expect(screen.queryByText('Download')).toBeNull()
|
||||
})
|
||||
|
||||
it('does not have an option to download or go to Various Artist', async () => {
|
||||
const { queryByTestId } = await this.renderComponent(factory.states('various')<Artist>('artist'))
|
||||
await this.renderComponent(factory.states('various')<Artist>('artist'))
|
||||
|
||||
expect(queryByTestId('view-artist')).toBeNull()
|
||||
expect(queryByTestId('download')).toBeNull()
|
||||
expect(screen.queryByText('Go to Artist')).toBeNull()
|
||||
expect(screen.queryByText('Download')).toBeNull()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
<template>
|
||||
<ContextMenuBase ref="base" data-testid="artist-context-menu" extra-class="artist-menu">
|
||||
<template v-if="artist">
|
||||
<li data-testid="play" @click="play">Play All</li>
|
||||
<li data-testid="shuffle" @click="shuffle">Shuffle All</li>
|
||||
<li @click="play">Play All</li>
|
||||
<li @click="shuffle">Shuffle All</li>
|
||||
<template v-if="isStandardArtist">
|
||||
<li class="separator"></li>
|
||||
<li data-testid="view-artist" @click="viewArtistDetails">Go to Artist</li>
|
||||
<li @click="viewArtistDetails">Go to Artist</li>
|
||||
</template>
|
||||
<template v-if="isStandardArtist && allowDownload">
|
||||
<li class="separator"></li>
|
||||
<li data-testid="download" @click="download">Download</li>
|
||||
<li @click="download">Download</li>
|
||||
</template>
|
||||
</template>
|
||||
</ContextMenuBase>
|
||||
|
|
|
@ -2,7 +2,7 @@ import { expect, it } from 'vitest'
|
|||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { commonStore, songStore } from '@/stores'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { mediaInfoService, playbackService } from '@/services'
|
||||
import ArtistInfoComponent from './ArtistInfo.vue'
|
||||
|
||||
|
@ -11,12 +11,9 @@ let artist: Artist
|
|||
new class extends UnitTestCase {
|
||||
private async renderComponent (mode: MediaInfoDisplayMode = 'aside', info?: ArtistInfo) {
|
||||
commonStore.state.use_last_fm = true
|
||||
|
||||
if (info === undefined) {
|
||||
info = factory<ArtistInfo>('artist-info')
|
||||
}
|
||||
|
||||
info ??= factory<ArtistInfo>('artist-info')
|
||||
artist = factory<Artist>('artist', { name: 'Led Zeppelin' })
|
||||
|
||||
const fetchMock = this.mock(mediaInfoService, 'fetchForArtist').mockResolvedValue(info)
|
||||
|
||||
const rendered = this.render(ArtistInfoComponent, {
|
||||
|
@ -39,42 +36,42 @@ new class extends UnitTestCase {
|
|||
|
||||
protected test () {
|
||||
it.each<[MediaInfoDisplayMode]>([['aside'], ['full']])('renders in %s mode', async (mode) => {
|
||||
const { getByTestId, queryByTestId } = await this.renderComponent(mode)
|
||||
await this.renderComponent(mode)
|
||||
|
||||
if (mode === 'aside') {
|
||||
getByTestId('thumbnail')
|
||||
screen.getByTestId('thumbnail')
|
||||
} else {
|
||||
expect(queryByTestId('thumbnail'))
|
||||
expect(screen.queryByTestId('thumbnail')).toBeNull()
|
||||
}
|
||||
|
||||
expect(getByTestId('artist-info').classList.contains(mode)).toBe(true)
|
||||
expect(screen.getByTestId('artist-info').classList.contains(mode)).toBe(true)
|
||||
})
|
||||
|
||||
it('triggers showing full bio for aside mode', async () => {
|
||||
const { queryByTestId, getByTestId } = await this.renderComponent('aside')
|
||||
expect(queryByTestId('full')).toBeNull()
|
||||
await this.renderComponent('aside')
|
||||
expect(screen.queryByTestId('full')).toBeNull()
|
||||
|
||||
await fireEvent.click(getByTestId('more-btn'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Full Bio' }))
|
||||
|
||||
expect(queryByTestId('summary')).toBeNull()
|
||||
expect(queryByTestId('full')).not.toBeNull()
|
||||
expect(screen.queryByTestId('summary')).toBeNull()
|
||||
screen.getByTestId('full')
|
||||
})
|
||||
|
||||
it('shows full bio for full mode', async () => {
|
||||
const { queryByTestId } = await this.renderComponent('full')
|
||||
await this.renderComponent('full')
|
||||
|
||||
expect(queryByTestId('full')).not.toBeNull()
|
||||
expect(queryByTestId('summary')).toBeNull()
|
||||
expect(queryByTestId('more-btn')).toBeNull()
|
||||
screen.getByTestId('full')
|
||||
expect(screen.queryByTestId('summary')).toBeNull()
|
||||
expect(screen.queryByRole('button', { name: 'Full Bio' })).toBeNull()
|
||||
})
|
||||
|
||||
it('plays', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const fetchMock = this.mock(songStore, 'fetchForArtist').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const { getByTitle } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTitle('Play all songs by Led Zeppelin'))
|
||||
await this.user.click(screen.getByTitle('Play all songs by Led Zeppelin'))
|
||||
await this.tick(2)
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(artist)
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<div v-if="showSummary" class="summary" data-testid="summary" v-html="info.bio.summary"/>
|
||||
<div v-if="showFull" class="full" data-testid="full" v-html="info.bio.full"/>
|
||||
|
||||
<button v-if="showSummary" class="more" data-testid="more-btn" @click.prevent="showingFullBio = true">
|
||||
<button v-if="showSummary" class="more" @click.prevent="showingFullBio = true">
|
||||
Full Bio
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -4,7 +4,7 @@ exports[`renders 1`] = `
|
|||
<article class="item full" draggable="true" tabindex="0" title="Led Zeppelin" data-v-f01bdc56=""><br data-testid="thumbnail" entity="[object Object]" data-v-f01bdc56="">
|
||||
<footer data-v-f01bdc56="">
|
||||
<div class="name" data-v-f01bdc56=""><a href="#/artist/42" class="text-normal" data-testid="name">Led Zeppelin</a></div>
|
||||
<p class="meta" data-v-f01bdc56=""><a title="Shuffle all songs by Led Zeppelin" class="shuffle-artist" data-testid="shuffle-artist" href="" role="button"> Shuffle </a><a title="Download all songs by Led Zeppelin" class="download-artist" data-testid="download-artist" href="" role="button"> Download </a></p>
|
||||
<p class="meta" data-v-f01bdc56=""><a title="Shuffle all songs by Led Zeppelin" class="shuffle-artist" href="" role="button"> Shuffle </a><a title="Download all songs by Led Zeppelin" class="download-artist" href="" role="button"> Download </a></p>
|
||||
</footer>
|
||||
</article>
|
||||
`;
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
exports[`renders 1`] = `
|
||||
<nav class="artist-menu menu context-menu" style="top: 42px; left: 420px;" tabindex="0" data-testid="artist-context-menu" data-v-0408531a="">
|
||||
<ul data-v-0408531a="">
|
||||
<li data-testid="play">Play All</li>
|
||||
<li data-testid="shuffle">Shuffle All</li>
|
||||
<li>Play All</li>
|
||||
<li>Shuffle All</li>
|
||||
<li class="separator"></li>
|
||||
<li data-testid="view-artist">Go to Artist</li>
|
||||
<li>Go to Artist</li>
|
||||
<li class="separator"></li>
|
||||
<li data-testid="download">Download</li>
|
||||
<li>Download</li>
|
||||
</ul>
|
||||
</nav>
|
||||
`;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { fireEvent } from '@testing-library/vue'
|
||||
import { expect, it, SpyInstanceFn } from 'vitest'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import { userStore } from '@/stores'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import LoginFrom from './LoginForm.vue'
|
||||
|
@ -8,9 +8,9 @@ new class extends UnitTestCase {
|
|||
private async submitForm (loginMock: SpyInstanceFn) {
|
||||
const rendered = this.render(LoginFrom)
|
||||
|
||||
await fireEvent.update(rendered.getByPlaceholderText('Email Address'), 'john@doe.com')
|
||||
await fireEvent.update(rendered.getByPlaceholderText('Password'), 'secret')
|
||||
await fireEvent.submit(rendered.getByTestId('login-form'))
|
||||
await this.type(screen.getByPlaceholderText('Email Address'), 'john@doe.com')
|
||||
await this.type(screen.getByPlaceholderText('Password'), 'secret')
|
||||
await this.user.click(screen.getByRole('button', { name: 'Log In' }))
|
||||
|
||||
expect(loginMock).toHaveBeenCalledWith('john@doe.com', 'secret')
|
||||
|
||||
|
@ -26,11 +26,11 @@ new class extends UnitTestCase {
|
|||
|
||||
it('fails to log in', async () => {
|
||||
const mock = this.mock(userStore, 'login').mockRejectedValue(new Error('Unauthenticated'))
|
||||
const { getByTestId, emitted } = await this.submitForm(mock)
|
||||
const { emitted } = await this.submitForm(mock)
|
||||
await this.tick()
|
||||
|
||||
expect(emitted().loggedin).toBeFalsy()
|
||||
expect(getByTestId('login-form').classList.contains('error')).toBe(true)
|
||||
expect(screen.getByTestId('login-form').classList.contains('error')).toBe(true)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { it } from 'vitest'
|
||||
import { waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { eventBus } from '@/utils'
|
||||
import { Events } from '@/config'
|
||||
|
@ -20,7 +20,7 @@ new class extends UnitTestCase {
|
|||
['edit-smart-playlist-form', 'MODAL_SHOW_EDIT_PLAYLIST_FORM', factory<Playlist>('playlist', { is_smart: true })],
|
||||
['about-koel', 'MODAL_SHOW_ABOUT_KOEL', undefined]
|
||||
])('shows %s modal', async (modalName, eventName, eventParams?: any) => {
|
||||
const { getByTestId } = this.render(ModalWrapper, {
|
||||
this.render(ModalWrapper, {
|
||||
global: {
|
||||
stubs: {
|
||||
AddUserForm: this.stub('add-user-form'),
|
||||
|
@ -39,7 +39,7 @@ new class extends UnitTestCase {
|
|||
|
||||
eventBus.emit(eventName, eventParams)
|
||||
|
||||
await waitFor(() => getByTestId(modalName))
|
||||
await waitFor(() => screen.getByTestId(modalName))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ import { expect, it } from 'vitest'
|
|||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { CurrentSongKey } from '@/symbols'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { playbackService } from '@/services'
|
||||
import FooterPlaybackControls from './FooterPlaybackControls.vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
private renderComponent (song?: Song | null) {
|
||||
|
@ -27,7 +27,7 @@ new class extends UnitTestCase {
|
|||
PlayButton: this.stub('PlayButton')
|
||||
},
|
||||
provide: {
|
||||
[CurrentSongKey]: ref(song)
|
||||
[<symbol>CurrentSongKey]: ref(song)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -39,18 +39,18 @@ new class extends UnitTestCase {
|
|||
|
||||
it('plays the previous song', async () => {
|
||||
const playMock = this.mock(playbackService, 'playPrev')
|
||||
const { getByTitle } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTitle('Play previous song'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Play previous song' }))
|
||||
|
||||
expect(playMock).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('plays the next song', async () => {
|
||||
const playMock = this.mock(playbackService, 'playNext')
|
||||
const { getByTitle } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTitle('Play next song'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Play next song' }))
|
||||
|
||||
expect(playMock).toHaveBeenCalled()
|
||||
})
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
exports[`renders with a current song 1`] = `
|
||||
<div class="playback-controls" data-testid="footer-middle-pane" data-v-2e8b419d="">
|
||||
<div class="buttons" data-v-2e8b419d=""><button title="Unlike Fahrstuhl to Heaven by Led Zeppelin" data-testid="like-btn" type="button" class="like-btn" data-v-2e8b419d=""><br data-testid="btn-like-liked" icon="[object Object]"></button><!-- a placeholder to maintain the flex layout --><button type="button" title="Play previous song" data-v-2e8b419d=""><br data-testid="icon" icon="[object Object]" data-v-2e8b419d=""></button><br data-testid="PlayButton" data-v-2e8b419d=""><button type="button" title="Play next song" data-v-2e8b419d=""><br data-testid="icon" icon="[object Object]" data-v-2e8b419d=""></button><button class="repeat-mode-btn" title="Change repeat mode (current: No Repeat)" data-testid="repeat-mode-switch" type="button" data-v-cab48a7c="" data-v-2e8b419d="">
|
||||
<div class="buttons" data-v-2e8b419d=""><button title="Unlike Fahrstuhl to Heaven by Led Zeppelin" type="button" class="like-btn" data-v-2e8b419d=""><br data-testid="icon" icon="[object Object]"></button><!-- a placeholder to maintain the flex layout --><button type="button" title="Play previous song" data-v-2e8b419d=""><br data-testid="icon" icon="[object Object]" data-v-2e8b419d=""></button><br data-testid="PlayButton" data-v-2e8b419d=""><button type="button" title="Play next song" data-v-2e8b419d=""><br data-testid="icon" icon="[object Object]" data-v-2e8b419d=""></button><button class="repeat-mode-btn" title="Change repeat mode (current: No Repeat)" data-testid="repeat-mode-switch" type="button" data-v-cab48a7c="" data-v-2e8b419d="">
|
||||
<div class="fa-layers" data-v-cab48a7c=""><br data-testid="icon" icon="[object Object]" data-v-cab48a7c="">
|
||||
<!--v-if-->
|
||||
</div>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { ref, Ref } from 'vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { albumStore, artistStore, commonStore, preferenceStore } from '@/stores'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { CurrentSongKey } from '@/symbols'
|
||||
import ExtraPanel from './ExtraPanel.vue'
|
||||
import { eventBus } from '@/utils'
|
||||
import ExtraPanel from './ExtraPanel.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
private renderComponent (songRef: Ref<Song | null> = ref(null)) {
|
||||
|
@ -32,8 +32,8 @@ new class extends UnitTestCase {
|
|||
|
||||
it('sets the active tab to the preference', async () => {
|
||||
preferenceStore.activeExtraPanelTab = 'YouTube'
|
||||
const { getByTestId } = this.renderComponent(ref(factory<Song>('song')))
|
||||
const tab = getByTestId<HTMLElement>('extra-panel-youtube')
|
||||
this.renderComponent(ref(factory<Song>('song')))
|
||||
const tab = screen.getByTestId<HTMLElement>('extra-panel-youtube')
|
||||
|
||||
expect(tab.style.display).toBe('none')
|
||||
await this.tick()
|
||||
|
@ -52,21 +52,21 @@ new class extends UnitTestCase {
|
|||
|
||||
const songRef = ref<Song | null>(null)
|
||||
|
||||
const { getByTestId } = this.renderComponent(songRef)
|
||||
this.renderComponent(songRef)
|
||||
songRef.value = song
|
||||
|
||||
await waitFor(() => {
|
||||
expect(resolveArtistMock).toHaveBeenCalledWith(song.artist_id)
|
||||
expect(resolveAlbumMock).toHaveBeenCalledWith(song.album_id)
|
||||
;['lyrics', 'album-info', 'artist-info', 'youtube-video-list'].forEach(id => getByTestId(id))
|
||||
;['lyrics', 'album-info', 'artist-info', 'youtube-video-list'].forEach(id => screen.getByTestId(id))
|
||||
})
|
||||
})
|
||||
|
||||
it('shows About Koel model', async () => {
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
const { getByTitle } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTitle('About Koel'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'About Koel' }))
|
||||
|
||||
expect(emitMock).toHaveBeenCalledWith('MODAL_SHOW_ABOUT_KOEL')
|
||||
})
|
||||
|
@ -75,15 +75,15 @@ new class extends UnitTestCase {
|
|||
it('shows new version', () => {
|
||||
commonStore.state.current_version = 'v1.0.0'
|
||||
commonStore.state.latest_version = 'v1.0.1'
|
||||
this.actingAsAdmin().renderComponent().getByTitle('New version available!')
|
||||
this.actingAsAdmin().renderComponent().getByRole('button', { name: 'New version available!' })
|
||||
})
|
||||
})
|
||||
|
||||
it('logs out', async () => {
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
const { getByTitle } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTitle('Log out'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Log out' }))
|
||||
|
||||
expect(emitMock).toHaveBeenCalledWith('LOG_OUT')
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { ref } from 'vue'
|
||||
import { waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { albumStore, preferenceStore } from '@/stores'
|
||||
|
@ -28,17 +28,17 @@ new class extends UnitTestCase {
|
|||
it('has a translucent overlay per album', async () => {
|
||||
this.mock(albumStore, 'fetchThumbnail').mockResolvedValue('http://test/foo.jpg')
|
||||
|
||||
const { getByTestId } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await waitFor(() => getByTestId('album-art-overlay'))
|
||||
await waitFor(() => screen.getByTestId('album-art-overlay'))
|
||||
})
|
||||
|
||||
it('does not have a translucent over if configured not so', async () => {
|
||||
preferenceStore.state.showAlbumArtOverlay = false
|
||||
|
||||
const { queryByTestId } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await waitFor(() => expect(queryByTestId('album-art-overlay')).toBeNull())
|
||||
await waitFor(() => expect(screen.queryByTestId('album-art-overlay')).toBeNull())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { expect, it } from 'vitest'
|
|||
import { commonStore } from '@/stores'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { http } from '@/services'
|
||||
import { waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import AboutKoelModel from './AboutKoelModal.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
|
@ -35,10 +35,10 @@ new class extends UnitTestCase {
|
|||
// @ts-ignore
|
||||
import.meta.env.VITE_KOEL_ENV = 'demo'
|
||||
|
||||
const { getByTestId } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await waitFor(() => {
|
||||
getByTestId('demo-credits')
|
||||
screen.getByTestId('demo-credits')
|
||||
expect(getMock).toHaveBeenCalledWith('demo/credits')
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { expect, it, vi } from 'vitest'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { preferenceStore } from '@/stores'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import SupportKoel from './SupportKoel.vue'
|
||||
|
@ -27,9 +27,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
protected test () {
|
||||
it('shows after a delay', async () => {
|
||||
expect((await this.renderComponent()).html()).toMatchSnapshot()
|
||||
})
|
||||
it('shows after a delay', async () => expect((await this.renderComponent()).html()).toMatchSnapshot())
|
||||
|
||||
it('does not show if user so demands', async () => {
|
||||
preferenceStore.state.supportBarNoBugging = true
|
||||
|
@ -38,19 +36,17 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('hides', async () => {
|
||||
const { getByTestId, queryByTestId } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
await this.user.click(screen.getByRole('button', { name: 'Hide' }))
|
||||
|
||||
await fireEvent.click(getByTestId('hide-support-koel'))
|
||||
|
||||
expect(await queryByTestId('support-bar')).toBeNull()
|
||||
expect(screen.queryByTestId('support-bar')).toBeNull()
|
||||
})
|
||||
|
||||
it('hides and does not bug again', async () => {
|
||||
const { getByTestId, queryByTestId } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
await this.user.click(screen.getByRole('button', { name: 'Don\'t bug me again' }))
|
||||
|
||||
await fireEvent.click(getByTestId('stop-support-koel-bugging'))
|
||||
|
||||
expect(await queryByTestId('btn-stop-support-koel-bugging')).toBeNull()
|
||||
expect(await screen.queryByTestId('support-bar')).toBeNull()
|
||||
expect(preferenceStore.state.supportBarNoBugging).toBe(true)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
and/or
|
||||
<a href="https://opencollective.com/koel" rel="noopener" target="_blank">OpenCollective</a>.
|
||||
</p>
|
||||
<button data-testid="hide-support-koel" type="button" @click.prevent="close">Hide</button>
|
||||
<button type="button" @click.prevent="close">Hide</button>
|
||||
<span class="sep"></span>
|
||||
<button data-testid="stop-support-koel-bugging" type="button" @click.prevent="stopBugging">
|
||||
<button type="button" @click.prevent="stopBugging">
|
||||
Don't bug me again
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
exports[`shows after a delay 1`] = `
|
||||
<div class="support-bar" data-testid="support-bar" data-v-c8ee2518="">
|
||||
<p data-v-c8ee2518=""> Loving Koel? Please consider supporting its development via <a href="https://github.com/users/phanan/sponsorship" rel="noopener" target="_blank" data-v-c8ee2518="">GitHub Sponsors</a> and/or <a href="https://opencollective.com/koel" rel="noopener" target="_blank" data-v-c8ee2518="">OpenCollective</a>. </p><button data-testid="hide-support-koel" type="button" data-v-c8ee2518="">Hide</button><span class="sep" data-v-c8ee2518=""></span><button data-testid="stop-support-koel-bugging" type="button" data-v-c8ee2518=""> Don't bug me again </button>
|
||||
<p data-v-c8ee2518=""> Loving Koel? Please consider supporting its development via <a href="https://github.com/users/phanan/sponsorship" rel="noopener" target="_blank" data-v-c8ee2518="">GitHub Sponsors</a> and/or <a href="https://opencollective.com/koel" rel="noopener" target="_blank" data-v-c8ee2518="">OpenCollective</a>. </p><button type="button" data-v-c8ee2518="">Hide</button><span class="sep" data-v-c8ee2518=""></span><button type="button" data-v-c8ee2518=""> Don't bug me again </button>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { eventBus } from '@/utils'
|
||||
import { Events } from '@/config'
|
||||
|
@ -7,10 +7,9 @@ import CreateNewPlaylistContextMenu from './CreateNewPlaylistContextMenu.vue'
|
|||
|
||||
new class extends UnitTestCase {
|
||||
private async renderComponent () {
|
||||
const rendered = await this.render(CreateNewPlaylistContextMenu)
|
||||
eventBus.emit('CREATE_NEW_PLAYLIST_CONTEXT_MENU_REQUESTED', { pageX: 420, pageY: 42 })
|
||||
await this.render(CreateNewPlaylistContextMenu)
|
||||
eventBus.emit('CREATE_NEW_PLAYLIST_CONTEXT_MENU_REQUESTED', { pageX: 420, pageY: 42 } as MouseEvent)
|
||||
await this.tick(2)
|
||||
return rendered
|
||||
}
|
||||
|
||||
protected test () {
|
||||
|
@ -19,9 +18,9 @@ new class extends UnitTestCase {
|
|||
['playlist-context-menu-create-smart', 'MODAL_SHOW_CREATE_SMART_PLAYLIST_FORM'],
|
||||
['playlist-context-menu-create-folder', 'MODAL_SHOW_CREATE_PLAYLIST_FOLDER_FORM']
|
||||
])('when clicking on %s, should emit %s', async (id, eventName) => {
|
||||
const { getByTestId } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
await fireEvent.click(getByTestId(id))
|
||||
await this.user.click(screen.getByTestId(id))
|
||||
await waitFor(() => expect(emitMock).toHaveBeenCalledWith(eventName))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { playlistFolderStore } from '@/stores'
|
||||
import factory from '@/__tests__/factory'
|
||||
|
@ -11,10 +11,10 @@ new class extends UnitTestCase {
|
|||
const storeMock = this.mock(playlistFolderStore, 'store')
|
||||
.mockResolvedValue(factory<PlaylistFolder>('playlist-folder'))
|
||||
|
||||
const { getByPlaceholderText, getByRole } = await this.render(CreatePlaylistFolderForm)
|
||||
await this.render(CreatePlaylistFolderForm)
|
||||
|
||||
await fireEvent.update(getByPlaceholderText('Folder name'), 'My folder')
|
||||
await fireEvent.click(getByRole('button', { name: 'Save' }))
|
||||
await this.type(screen.getByPlaceholderText('Folder name'), 'My folder')
|
||||
await this.user.click(screen.getByRole('button', { name: 'Save' }))
|
||||
|
||||
expect(storeMock).toHaveBeenCalledWith('My folder')
|
||||
})
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { playlistStore } from '@/stores'
|
||||
import factory from '@/__tests__/factory'
|
||||
import CreatePlaylistForm from './CreatePlaylistForm.vue'
|
||||
import { ref } from 'vue'
|
||||
import { ModalContextKey } from '@/symbols'
|
||||
import CreatePlaylistForm from './CreatePlaylistForm.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('submits', async () => {
|
||||
const folder = factory<PlaylistFolder>('playlist-folder')
|
||||
const storeMock = this.mock(playlistStore, 'store').mockResolvedValue(factory<Playlist>('playlist'))
|
||||
const { getByPlaceholderText, getByRole } = await this.render(CreatePlaylistForm, {
|
||||
this.render(CreatePlaylistForm, {
|
||||
global: {
|
||||
provide: {
|
||||
[<symbol>ModalContextKey]: [ref({ folder })]
|
||||
|
@ -20,8 +20,8 @@ new class extends UnitTestCase {
|
|||
}
|
||||
})
|
||||
|
||||
await fireEvent.update(getByPlaceholderText('Playlist name'), 'My playlist')
|
||||
await fireEvent.click(getByRole('button', { name: 'Save' }))
|
||||
await this.type(screen.getByPlaceholderText('Playlist name'), 'My playlist')
|
||||
await this.user.click(screen.getByRole('button', { name: 'Save' }))
|
||||
|
||||
expect(storeMock).toHaveBeenCalledWith('My playlist', {
|
||||
folder_id: folder.id
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { ref } from 'vue'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { expect, it, vi } from 'vitest'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { playlistFolderStore } from '@/stores'
|
||||
|
@ -11,9 +11,8 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('submits', async () => {
|
||||
const folder = factory<PlaylistFolder>('playlist-folder', { name: 'My folder' })
|
||||
const updateFolderNameMock = vi.fn()
|
||||
const renameMock = this.mock(playlistFolderStore, 'rename')
|
||||
const { getByPlaceholderText, getByRole } = this.render(EditPlaylistFolderForm, {
|
||||
this.render(EditPlaylistFolderForm, {
|
||||
global: {
|
||||
provide: {
|
||||
[<symbol>ModalContextKey]: [ref({ folder })]
|
||||
|
@ -21,8 +20,8 @@ new class extends UnitTestCase {
|
|||
}
|
||||
})
|
||||
|
||||
await fireEvent.update(getByPlaceholderText('Folder name'), 'Your folder')
|
||||
await fireEvent.click(getByRole('button', { name: 'Save' }))
|
||||
await this.type(screen.getByPlaceholderText('Folder name'), 'Your folder')
|
||||
await this.user.click(screen.getByRole('button', { name: 'Save' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(renameMock).toHaveBeenCalledWith(folder, 'Your folder')
|
||||
|
|
|
@ -3,7 +3,7 @@ import factory from '@/__tests__/factory'
|
|||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { playlistFolderStore, playlistStore } from '@/stores'
|
||||
import { ref } from 'vue'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { ModalContextKey } from '@/symbols'
|
||||
import EditPlaylistForm from './EditPlaylistForm.vue'
|
||||
|
||||
|
@ -21,7 +21,7 @@ new class extends UnitTestCase {
|
|||
|
||||
const updateMock = this.mock(playlistStore, 'update')
|
||||
|
||||
const { getByPlaceholderText, getByRole } = this.render(EditPlaylistForm, {
|
||||
this.render(EditPlaylistForm, {
|
||||
global: {
|
||||
provide: {
|
||||
[<symbol>ModalContextKey]: [ref({ playlist })]
|
||||
|
@ -29,8 +29,8 @@ new class extends UnitTestCase {
|
|||
}
|
||||
})
|
||||
|
||||
await fireEvent.update(getByPlaceholderText('Playlist name'), 'Your playlist')
|
||||
await fireEvent.click(getByRole('button', { name: 'Save' }))
|
||||
await this.type(screen.getByPlaceholderText('Playlist name'), 'Your playlist')
|
||||
await this.user.click(screen.getByRole('button', { name: 'Save' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(updateMock).toHaveBeenCalledWith(playlist, {
|
||||
|
|
|
@ -2,44 +2,43 @@ import { expect, it } from 'vitest'
|
|||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { eventBus } from '@/utils'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import PlaylistContextMenu from './PlaylistContextMenu.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
private async renderComponent (playlist: Playlist) {
|
||||
const rendered = await this.render(PlaylistContextMenu)
|
||||
await this.render(PlaylistContextMenu)
|
||||
eventBus.emit('PLAYLIST_CONTEXT_MENU_REQUESTED', { pageX: 420, pageY: 42 }, playlist)
|
||||
await this.tick(2)
|
||||
return rendered
|
||||
}
|
||||
|
||||
protected test () {
|
||||
it('edits a standard playlist', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const { getByText } = await this.renderComponent(playlist)
|
||||
await this.renderComponent(playlist)
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
|
||||
await fireEvent.click(getByText('Edit'))
|
||||
await this.user.click(screen.getByText('Edit'))
|
||||
|
||||
expect(emitMock).toHaveBeenCalledWith('MODAL_SHOW_EDIT_PLAYLIST_FORM', playlist)
|
||||
})
|
||||
|
||||
it('edits a smart playlist', async () => {
|
||||
const playlist = factory.states('smart')<Playlist>('playlist')
|
||||
const { getByText } = await this.renderComponent(playlist)
|
||||
await this.renderComponent(playlist)
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
|
||||
await fireEvent.click(getByText('Edit'))
|
||||
await this.user.click(screen.getByText('Edit'))
|
||||
|
||||
expect(emitMock).toHaveBeenCalledWith('MODAL_SHOW_EDIT_PLAYLIST_FORM', playlist)
|
||||
})
|
||||
|
||||
it('deletes a playlist', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const { getByText } = await this.renderComponent(playlist)
|
||||
await this.renderComponent(playlist)
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
|
||||
await fireEvent.click(getByText('Delete'))
|
||||
await this.user.click(screen.getByText('Delete'))
|
||||
|
||||
expect(emitMock).toHaveBeenCalledWith('PLAYLIST_DELETE', playlist)
|
||||
})
|
||||
|
|
|
@ -2,36 +2,35 @@ import { expect, it } from 'vitest'
|
|||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { eventBus } from '@/utils'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { playlistStore, songStore } from '@/stores'
|
||||
import { playbackService } from '@/services'
|
||||
import PlaylistFolderContextMenu from './PlaylistFolderContextMenu.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
private async renderComponent (folder: PlaylistFolder) {
|
||||
const rendered = await this.render(PlaylistFolderContextMenu)
|
||||
await this.render(PlaylistFolderContextMenu)
|
||||
eventBus.emit('PLAYLIST_FOLDER_CONTEXT_MENU_REQUESTED', { pageX: 420, pageY: 42 }, folder)
|
||||
await this.tick(2)
|
||||
return rendered
|
||||
}
|
||||
|
||||
protected test () {
|
||||
it('renames', async () => {
|
||||
const folder = factory<PlaylistFolder>('playlist-folder')
|
||||
const { getByText } = await this.renderComponent(folder)
|
||||
await this.renderComponent(folder)
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
|
||||
await fireEvent.click(getByText('Rename'))
|
||||
await this.user.click(screen.getByText('Rename'))
|
||||
|
||||
expect(emitMock).toHaveBeenCalledWith('MODAL_SHOW_EDIT_PLAYLIST_FOLDER_FORM', folder)
|
||||
})
|
||||
|
||||
it('deletes', async () => {
|
||||
const folder = factory<PlaylistFolder>('playlist-folder')
|
||||
const { getByText } = await this.renderComponent(folder)
|
||||
await this.renderComponent(folder)
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
|
||||
await fireEvent.click(getByText('Delete'))
|
||||
await this.user.click(screen.getByText('Delete'))
|
||||
|
||||
expect(emitMock).toHaveBeenCalledWith('PLAYLIST_FOLDER_DELETE', folder)
|
||||
})
|
||||
|
@ -42,9 +41,9 @@ new class extends UnitTestCase {
|
|||
const fetchMock = this.mock(songStore, 'fetchForPlaylistFolder').mockResolvedValue(songs)
|
||||
const queueMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const goMock = this.mock(this.router, 'go')
|
||||
const { getByText } = await this.renderComponent(folder)
|
||||
await this.renderComponent(folder)
|
||||
|
||||
await fireEvent.click(getByText('Play All'))
|
||||
await this.user.click(screen.getByText('Play All'))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalledWith(folder)
|
||||
|
@ -59,9 +58,9 @@ new class extends UnitTestCase {
|
|||
const fetchMock = this.mock(songStore, 'fetchForPlaylistFolder').mockResolvedValue(songs)
|
||||
const queueMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const goMock = this.mock(this.router, 'go')
|
||||
const { getByText } = await this.renderComponent(folder)
|
||||
await this.renderComponent(folder)
|
||||
|
||||
await fireEvent.click(getByText('Shuffle All'))
|
||||
await this.user.click(screen.getByText('Shuffle All'))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalledWith(folder)
|
||||
|
@ -72,10 +71,10 @@ new class extends UnitTestCase {
|
|||
|
||||
it('does not show shuffle option if folder is empty', async () => {
|
||||
const folder = factory<PlaylistFolder>('playlist-folder')
|
||||
const { queryByText } = await this.renderComponent(folder)
|
||||
await this.renderComponent(folder)
|
||||
|
||||
expect(queryByText('Shuffle All')).toBeNull()
|
||||
expect(queryByText('Play All')).toBeNull()
|
||||
expect(screen.queryByText('Shuffle All')).toBeNull()
|
||||
expect(screen.queryByText('Play All')).toBeNull()
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { fireEvent, screen } from '@testing-library/vue'
|
||||
import { eventBus } from '@/utils'
|
||||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
|
@ -7,7 +7,7 @@ import PlaylistSidebarItem from './PlaylistSidebarItem.vue'
|
|||
|
||||
new class extends UnitTestCase {
|
||||
renderComponent (list: PlaylistLike) {
|
||||
return this.render(PlaylistSidebarItem, {
|
||||
this.render(PlaylistSidebarItem, {
|
||||
props: {
|
||||
list
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ new class extends UnitTestCase {
|
|||
it('requests context menu if is playlist', async () => {
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const { getByTestId } = this.renderComponent(playlist)
|
||||
this.renderComponent(playlist)
|
||||
|
||||
await fireEvent.contextMenu(getByTestId('playlist-sidebar-item'))
|
||||
await fireEvent.contextMenu(screen.getByRole('listitem'))
|
||||
|
||||
expect(emitMock).toHaveBeenCalledWith('PLAYLIST_CONTEXT_MENU_REQUESTED', expect.anything(), playlist)
|
||||
})
|
||||
|
@ -33,9 +33,9 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
const { getByTestId } = this.renderComponent(list)
|
||||
this.renderComponent(list)
|
||||
|
||||
await fireEvent.contextMenu(getByTestId('playlist-sidebar-item'))
|
||||
await fireEvent.contextMenu(screen.getByRole('listitem'))
|
||||
|
||||
expect(emitMock).not.toHaveBeenCalledWith('PLAYLIST_CONTEXT_MENU_REQUESTED', list)
|
||||
})
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
ref="el"
|
||||
:class="{ droppable }"
|
||||
class="playlist"
|
||||
data-testid="playlist-sidebar-item"
|
||||
draggable="true"
|
||||
@contextmenu="onContextMenu"
|
||||
@dragleave="onDragLeave"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { screen } from '@testing-library/vue'
|
||||
import { it } from 'vitest'
|
||||
import { playlistFolderStore, playlistStore } from '@/stores'
|
||||
import factory from '@/__tests__/factory'
|
||||
|
@ -8,7 +9,7 @@ import PlaylistFolderSidebarItem from './PlaylistFolderSidebarItem.vue'
|
|||
|
||||
new class extends UnitTestCase {
|
||||
private renderComponent () {
|
||||
return this.render(PlaylistSidebarList, {
|
||||
this.render(PlaylistSidebarList, {
|
||||
global: {
|
||||
stubs: {
|
||||
PlaylistSidebarItem,
|
||||
|
@ -26,9 +27,11 @@ new class extends UnitTestCase {
|
|||
factory.states('smart', 'orphan')<Playlist>('playlist', { name: 'Smart Playlist' })
|
||||
]
|
||||
|
||||
const { getByText } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
;['Favorites', 'Recently Played', 'Foo Playlist', 'Bar Playlist', 'Smart Playlist'].forEach(t => getByText(t))
|
||||
;['Favorites', 'Recently Played', 'Foo Playlist', 'Bar Playlist', 'Smart Playlist'].forEach(text => {
|
||||
screen.getByText(text)
|
||||
})
|
||||
})
|
||||
|
||||
it('displays playlist folders', () => {
|
||||
|
@ -37,8 +40,8 @@ new class extends UnitTestCase {
|
|||
factory<PlaylistFolder>('playlist-folder', { name: 'Bar Folder' })
|
||||
]
|
||||
|
||||
const { getByText } = this.renderComponent()
|
||||
;['Foo Folder', 'Bar Folder'].forEach(t => getByText(t))
|
||||
this.renderComponent()
|
||||
;['Foo Folder', 'Bar Folder'].forEach(text => screen.getByText(text))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import isMobile from 'ismobilejs'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import PreferencesForm from './PreferencesForm.vue'
|
||||
|
@ -7,14 +8,14 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('has "Transcode on mobile" option for mobile users', () => {
|
||||
isMobile.phone = true
|
||||
const { getByLabelText } = this.render(PreferencesForm)
|
||||
getByLabelText('Convert and play media at 128kbps on mobile')
|
||||
this.render(PreferencesForm)
|
||||
screen.getByRole('checkbox', { name: 'Convert and play media at 128kbps on mobile' })
|
||||
})
|
||||
|
||||
it('does not have "Transcode on mobile" option for non-mobile users', async () => {
|
||||
isMobile.phone = false
|
||||
const { queryByLabelText } = this.render(PreferencesForm)
|
||||
expect(await queryByLabelText('Convert and play media at 128kbps on mobile')).toBeNull()
|
||||
this.render(PreferencesForm)
|
||||
expect(screen.queryByRole('checkbox', { name: 'Convert and play media at 128kbps on mobile' })).toBeNull()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { expect, it } from 'vitest'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import ThemeCard from './ThemeCard.vue'
|
||||
|
||||
const theme: Theme = {
|
||||
|
@ -18,13 +18,13 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
protected test () {
|
||||
it('renders', () => {
|
||||
expect(this.renderComponent().html()).toMatchSnapshot()
|
||||
})
|
||||
it('renders', () => expect(this.renderComponent().html()).toMatchSnapshot())
|
||||
|
||||
it('emits an event when selected', async () => {
|
||||
const { emitted, getByTestId } = this.renderComponent()
|
||||
await fireEvent.click(getByTestId('theme-card-sample'))
|
||||
const { emitted } = this.renderComponent()
|
||||
|
||||
await this.user.click(screen.getByRole('button', { name: 'Sample' }))
|
||||
|
||||
expect(emitted().selected[0]).toEqual([theme])
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
<template>
|
||||
<div
|
||||
:class="{ selected: theme.selected }"
|
||||
:data-testid="`theme-card-${theme.id}`"
|
||||
:style="thumbnailStyles"
|
||||
:title="`Set current them to ${name}`"
|
||||
:title="`Set current theme to ${name}`"
|
||||
class="theme"
|
||||
role="button"
|
||||
@click="$emit('selected', theme)"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// Vitest Snapshot v1
|
||||
|
||||
exports[`renders 1`] = `
|
||||
<div class="theme" data-testid="theme-card-sample" style="background-color: rgb(255, 0, 0);" title="Set current them to Sample" role="button" data-v-1467c50f="">
|
||||
<div class="theme" style="background-color: rgb(255, 0, 0);" title="Set current theme to Sample" role="button" data-v-1467c50f="">
|
||||
<div class="name" data-v-1467c50f="">Sample</div>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
@ -2,7 +2,7 @@ import { expect, it } from 'vitest'
|
|||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { albumStore, preferenceStore } from '@/stores'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import AlbumListScreen from './AlbumListScreen.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
|
@ -13,7 +13,7 @@ new class extends UnitTestCase {
|
|||
private async renderComponent () {
|
||||
albumStore.state.albums = factory<Album>('album', 9)
|
||||
|
||||
const rendered = this.render(AlbumListScreen, {
|
||||
this.render(AlbumListScreen, {
|
||||
global: {
|
||||
stubs: {
|
||||
AlbumCard: this.stub('album-card')
|
||||
|
@ -22,31 +22,30 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
await this.router.activateRoute({ path: 'albums', screen: 'Albums' })
|
||||
return rendered
|
||||
}
|
||||
|
||||
protected test () {
|
||||
it('renders', async () => {
|
||||
const { getAllByTestId } = await this.renderComponent()
|
||||
expect(getAllByTestId('album-card')).toHaveLength(9)
|
||||
await this.renderComponent()
|
||||
expect(screen.getAllByTestId('album-card')).toHaveLength(9)
|
||||
})
|
||||
|
||||
it.each<[ArtistAlbumViewMode]>([['list'], ['thumbnails']])('sets layout from preferences', async (mode) => {
|
||||
preferenceStore.albumsViewMode = mode
|
||||
|
||||
const { getByTestId } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await waitFor(() => expect(getByTestId('album-list').classList.contains(`as-${mode}`)).toBe(true))
|
||||
await waitFor(() => expect(screen.getByTestId('album-list').classList.contains(`as-${mode}`)).toBe(true))
|
||||
})
|
||||
|
||||
it('switches layout', async () => {
|
||||
const { getByTestId, getByTitle } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTitle('View as list'))
|
||||
await waitFor(() => expect(getByTestId('album-list').classList.contains(`as-list`)).toBe(true))
|
||||
await this.user.click(screen.getByRole('radio', { name: 'View as list' }))
|
||||
await waitFor(() => expect(screen.getByTestId('album-list').classList.contains(`as-list`)).toBe(true))
|
||||
|
||||
await fireEvent.click(getByTitle('View as thumbnails'))
|
||||
await waitFor(() => expect(getByTestId('album-list').classList.contains(`as-thumbnails`)).toBe(true))
|
||||
await this.user.click(screen.getByRole('radio', { name: 'View as thumbnails' }))
|
||||
await waitFor(() => expect(screen.getByTestId('album-list').classList.contains(`as-thumbnails`)).toBe(true))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { fireEvent, getByTestId, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
|
@ -32,7 +32,7 @@ new class extends UnitTestCase {
|
|||
screen: 'Album'
|
||||
}, { id: '42' })
|
||||
|
||||
const rendered = this.render(AlbumScreen, {
|
||||
this.render(AlbumScreen, {
|
||||
global: {
|
||||
stubs: {
|
||||
SongList: this.stub('song-list'),
|
||||
|
@ -48,16 +48,14 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
await this.tick(2)
|
||||
|
||||
return rendered
|
||||
}
|
||||
|
||||
protected test () {
|
||||
it('downloads', async () => {
|
||||
const downloadMock = this.mock(downloadService, 'fromAlbum')
|
||||
const { getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByText('Download All'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Download All' }))
|
||||
|
||||
expect(downloadMock).toHaveBeenCalledWith(album)
|
||||
})
|
||||
|
@ -76,21 +74,21 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('shows the song list', async () => {
|
||||
const { getByTestId } = await this.renderComponent()
|
||||
getByTestId('song-list')
|
||||
await this.renderComponent()
|
||||
screen.getByTestId('song-list')
|
||||
})
|
||||
|
||||
it('shows other albums from the same artist', async () => {
|
||||
const albums = factory<Album>('album', 3)
|
||||
albums.push(album)
|
||||
const fetchMock = this.mock(albumStore, 'fetchForArtist').mockResolvedValue(albums)
|
||||
const { getByLabelText, getAllByTestId } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByLabelText('Other Albums'))
|
||||
await this.user.click(screen.getByRole('radio', { name: 'Other Albums' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalledWith(album.artist_id)
|
||||
expect(getAllByTestId('album-card')).toHaveLength(3) // current album is excluded
|
||||
expect(screen.getAllByTestId('album-card')).toHaveLength(3) // current album is excluded
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
<a
|
||||
v-if="allowDownload"
|
||||
class="download"
|
||||
href role="button"
|
||||
href
|
||||
role="button"
|
||||
title="Download all songs in album"
|
||||
@click.prevent="download"
|
||||
>
|
||||
|
|
|
@ -2,7 +2,7 @@ import { expect, it } from 'vitest'
|
|||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { commonStore, queueStore, songStore } from '@/stores'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { playbackService } from '@/services'
|
||||
import AllSongsScreen from './AllSongsScreen.vue'
|
||||
|
||||
|
@ -40,9 +40,9 @@ new class extends UnitTestCase {
|
|||
const queueMock = this.mock(queueStore, 'fetchRandom')
|
||||
const playMock = this.mock(playbackService, 'playFirstInQueue')
|
||||
const goMock = this.mock(this.router, 'go')
|
||||
const { getByTitle } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTitle('Shuffle all songs'))
|
||||
await this.user.click(screen.getByTitle('Shuffle all songs'))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(queueMock).toHaveBeenCalled()
|
||||
|
|
|
@ -2,7 +2,7 @@ import { expect, it } from 'vitest'
|
|||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { artistStore, preferenceStore } from '@/stores'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import ArtistListScreen from './ArtistListScreen.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
|
@ -27,26 +27,26 @@ new class extends UnitTestCase {
|
|||
|
||||
protected test () {
|
||||
it('renders', async () => {
|
||||
const { getAllByTestId } = await this.renderComponent()
|
||||
expect(getAllByTestId('artist-card')).toHaveLength(9)
|
||||
await this.renderComponent()
|
||||
expect(screen.getAllByTestId('artist-card')).toHaveLength(9)
|
||||
})
|
||||
|
||||
it.each<[ArtistAlbumViewMode]>([['list'], ['thumbnails']])('sets layout:%s from preferences', async (mode) => {
|
||||
preferenceStore.artistsViewMode = mode
|
||||
|
||||
const { getByTestId } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await waitFor(() => expect(getByTestId('artist-list').classList.contains(`as-${mode}`)).toBe(true))
|
||||
await waitFor(() => expect(screen.getByTestId('artist-list').classList.contains(`as-${mode}`)).toBe(true))
|
||||
})
|
||||
|
||||
it('switches layout', async () => {
|
||||
const { getByTestId, getByTitle } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTitle('View as list'))
|
||||
await waitFor(() => expect(getByTestId('artist-list').classList.contains(`as-list`)).toBe(true))
|
||||
await this.user.click(screen.getByRole('radio', { name: 'View as list' }))
|
||||
await waitFor(() => expect(screen.getByTestId('artist-list').classList.contains(`as-list`)).toBe(true))
|
||||
|
||||
await fireEvent.click(getByTitle('View as thumbnails'))
|
||||
await waitFor(() => expect(getByTestId('artist-list').classList.contains(`as-thumbnails`)).toBe(true))
|
||||
await this.user.click(screen.getByRole('radio', { name: 'View as thumbnails' }))
|
||||
await waitFor(() => expect(screen.getByTestId('artist-list').classList.contains(`as-thumbnails`)).toBe(true))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
|
@ -31,7 +31,7 @@ new class extends UnitTestCase {
|
|||
screen: 'Artist'
|
||||
}, { id: '42' })
|
||||
|
||||
const rendered = this.render(ArtistScreen, {
|
||||
this.render(ArtistScreen, {
|
||||
global: {
|
||||
stubs: {
|
||||
ArtistInfo: this.stub('artist-info'),
|
||||
|
@ -47,16 +47,14 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
await this.tick(2)
|
||||
|
||||
return rendered
|
||||
}
|
||||
|
||||
protected test () {
|
||||
it('downloads', async () => {
|
||||
const downloadMock = this.mock(downloadService, 'fromArtist')
|
||||
const { getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByText('Download All'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Download All' }))
|
||||
|
||||
expect(downloadMock).toHaveBeenCalledWith(artist)
|
||||
})
|
||||
|
@ -75,8 +73,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('shows the song list', async () => {
|
||||
const { getByTestId } = await this.renderComponent()
|
||||
getByTestId('song-list')
|
||||
await this.renderComponent()
|
||||
screen.getByTestId('song-list')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
|
@ -8,32 +8,30 @@ import FavoritesScreen from './FavoritesScreen.vue'
|
|||
new class extends UnitTestCase {
|
||||
private async renderComponent () {
|
||||
const fetchMock = this.mock(favoriteStore, 'fetch')
|
||||
const rendered = this.render(FavoritesScreen)
|
||||
this.render(FavoritesScreen)
|
||||
|
||||
await this.router.activateRoute({ path: 'favorites', screen: 'Favorites' })
|
||||
|
||||
await waitFor(() => expect(fetchMock).toHaveBeenCalled())
|
||||
|
||||
return rendered
|
||||
}
|
||||
|
||||
protected test () {
|
||||
it('renders a list of favorites', async () => {
|
||||
favoriteStore.state.songs = factory<Song>('song', 13)
|
||||
const { queryByTestId } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await waitFor(() => {
|
||||
expect(queryByTestId('screen-empty-state')).toBeNull()
|
||||
expect(queryByTestId('song-list')).not.toBeNull()
|
||||
expect(screen.queryByTestId('screen-empty-state')).toBeNull()
|
||||
screen.getByTestId('song-list')
|
||||
})
|
||||
})
|
||||
|
||||
it('shows empty state', async () => {
|
||||
favoriteStore.state.songs = []
|
||||
const { queryByTestId } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
expect(queryByTestId('screen-empty-state')).not.toBeNull()
|
||||
expect(queryByTestId('song-list')).toBeNull()
|
||||
screen.getByTestId('screen-empty-state')
|
||||
expect(screen.queryByTestId('song-list')).toBeNull()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,8 @@ import { expect, it } from 'vitest'
|
|||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { genreStore } from '@/stores'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import GenreListScreen from './GenreListScreen.vue'
|
||||
import { waitFor } from '@testing-library/vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
|
@ -17,11 +17,11 @@ new class extends UnitTestCase {
|
|||
|
||||
const fetchMock = this.mock(genreStore, 'fetchAll').mockResolvedValue(genres)
|
||||
|
||||
const { getByTitle } = this.render(GenreListScreen)
|
||||
this.render(GenreListScreen)
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalled()
|
||||
genres.forEach(genre => getByTitle(`${genre.name}: ${genre.song_count} songs`))
|
||||
genres.forEach(genre => screen.getByTitle(`${genre.name}: ${genre.song_count} songs`))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { genreStore, songStore } from '@/stores'
|
||||
|
@ -41,9 +41,8 @@ new class extends UnitTestCase {
|
|||
|
||||
protected test () {
|
||||
it('renders the song list', async () => {
|
||||
const { getByTestId } = await this.renderComponent()
|
||||
|
||||
expect(getByTestId('song-list')).toBeTruthy()
|
||||
await this.renderComponent()
|
||||
expect(screen.getByTestId('song-list')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('shuffles all songs without fetching if genre has <= 500 songs', async () => {
|
||||
|
@ -51,9 +50,9 @@ new class extends UnitTestCase {
|
|||
const songs = factory<Song>('song', 10)
|
||||
const playbackMock = this.mock(playbackService, 'queueAndPlay')
|
||||
|
||||
const { getByTitle } = await this.renderComponent(genre, songs)
|
||||
await this.renderComponent(genre, songs)
|
||||
|
||||
await fireEvent.click(getByTitle('Shuffle all songs'))
|
||||
await this.user.click(screen.getByTitle('Shuffle all songs'))
|
||||
|
||||
expect(playbackMock).toHaveBeenCalledWith(songs, true)
|
||||
})
|
||||
|
@ -64,9 +63,9 @@ new class extends UnitTestCase {
|
|||
const playbackMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const fetchMock = this.mock(songStore, 'fetchRandomForGenre').mockResolvedValue(songs)
|
||||
|
||||
const { getByTitle } = await this.renderComponent(genre, songs)
|
||||
await this.renderComponent(genre, songs)
|
||||
|
||||
await fireEvent.click(getByTitle('Shuffle all songs'))
|
||||
await this.user.click(screen.getByTitle('Shuffle all songs'))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalledWith(genre, 500)
|
||||
|
|
|
@ -3,13 +3,13 @@ import UnitTestCase from '@/__tests__/UnitTestCase'
|
|||
import { commonStore, overviewStore } from '@/stores'
|
||||
import { Events } from '@/config'
|
||||
import { eventBus } from '@/utils'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import HomeScreen from './HomeScreen.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
private async renderComponent () {
|
||||
const rendered = this.render(HomeScreen)
|
||||
this.render(HomeScreen)
|
||||
await this.router.activateRoute({ path: 'home', screen: 'Home' })
|
||||
return rendered
|
||||
}
|
||||
|
||||
protected test () {
|
||||
|
@ -17,16 +17,16 @@ new class extends UnitTestCase {
|
|||
commonStore.state.song_length = 0
|
||||
this.mock(overviewStore, 'init')
|
||||
|
||||
const { getByTestId } = await this.render(HomeScreen)
|
||||
await this.render(HomeScreen)
|
||||
|
||||
getByTestId('screen-empty-state')
|
||||
screen.getByTestId('screen-empty-state')
|
||||
})
|
||||
|
||||
it('renders overview components if applicable', async () => {
|
||||
commonStore.state.song_length = 100
|
||||
const initMock = this.mock(overviewStore, 'init')
|
||||
|
||||
const { getByTestId, queryByTestId } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
expect(initMock).toHaveBeenCalled()
|
||||
|
||||
|
@ -37,13 +37,13 @@ new class extends UnitTestCase {
|
|||
'recently-added-songs',
|
||||
'most-played-artists',
|
||||
'most-played-albums'
|
||||
].forEach(id => getByTestId(id))
|
||||
].forEach(id => screen.getByTestId(id))
|
||||
|
||||
expect(queryByTestId('screen-empty-state')).toBeNull()
|
||||
expect(screen.queryByTestId('screen-empty-state')).toBeNull()
|
||||
})
|
||||
|
||||
it.each<[keyof Events]>([['SONGS_UPDATED'], ['SONGS_DELETED']])
|
||||
('refreshes the overviews on %s event', async (eventName) => {
|
||||
('refreshes the overviews on %s event', async eventName => {
|
||||
const initMock = this.mock(overviewStore, 'init')
|
||||
const refreshMock = this.mock(overviewStore, 'refresh')
|
||||
await this.renderComponent()
|
||||
|
|
|
@ -2,7 +2,7 @@ import { expect, it } from 'vitest'
|
|||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { eventBus } from '@/utils'
|
||||
import { fireEvent, getByTestId, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { playlistStore, songStore } from '@/stores'
|
||||
import { downloadService } from '@/services'
|
||||
import PlaylistScreen from './PlaylistScreen.vue'
|
||||
|
@ -11,7 +11,7 @@ let playlist: Playlist
|
|||
|
||||
new class extends UnitTestCase {
|
||||
private async renderComponent (songs: Song[]) {
|
||||
playlist = playlist || factory<Playlist>('playlist')
|
||||
playlist ||= factory<Playlist>('playlist')
|
||||
playlistStore.init([playlist])
|
||||
|
||||
const fetchMock = this.mock(songStore, 'fetchForPlaylist').mockResolvedValue(songs)
|
||||
|
@ -25,51 +25,51 @@ new class extends UnitTestCase {
|
|||
|
||||
await waitFor(() => expect(fetchMock).toHaveBeenCalledWith(playlist, false))
|
||||
|
||||
return { rendered, fetchMock }
|
||||
return { fetchMock }
|
||||
}
|
||||
|
||||
protected test () {
|
||||
it('renders the playlist', async () => {
|
||||
const { rendered: { getByTestId, queryByTestId } } = (await this.renderComponent(factory<Song>('song', 10)))
|
||||
await this.renderComponent(factory<Song>('song', 10))
|
||||
|
||||
await waitFor(() => {
|
||||
getByTestId('song-list')
|
||||
expect(queryByTestId('screen-empty-state')).toBeNull()
|
||||
screen.getByTestId('song-list')
|
||||
expect(screen.queryByTestId('screen-empty-state')).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
it('displays the empty state if playlist is empty', async () => {
|
||||
const { rendered: { getByTestId, queryByTestId } } = (await this.renderComponent([]))
|
||||
await this.renderComponent([])
|
||||
|
||||
await waitFor(() => {
|
||||
getByTestId('screen-empty-state')
|
||||
expect(queryByTestId('song-list')).toBeNull()
|
||||
screen.getByTestId('screen-empty-state')
|
||||
expect(screen.queryByTestId('song-list')).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
it('downloads the playlist', async () => {
|
||||
const downloadMock = this.mock(downloadService, 'fromPlaylist')
|
||||
const { rendered: { getByText } } = (await this.renderComponent(factory<Song>('song', 10)))
|
||||
await this.renderComponent(factory<Song>('song', 10))
|
||||
|
||||
await this.tick()
|
||||
await fireEvent.click(getByText('Download All'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Download All' }))
|
||||
|
||||
await waitFor(() => expect(downloadMock).toHaveBeenCalledWith(playlist))
|
||||
})
|
||||
|
||||
it('deletes the playlist', async () => {
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
const { rendered: { getByTitle } } = (await this.renderComponent([]))
|
||||
await this.renderComponent([])
|
||||
|
||||
await fireEvent.click(getByTitle('Delete this playlist'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Delete this playlist' }))
|
||||
|
||||
await waitFor(() => expect(emitMock).toHaveBeenCalledWith('PLAYLIST_DELETE', playlist))
|
||||
})
|
||||
|
||||
it('refreshes the playlist', async () => {
|
||||
const { rendered: { getByTitle }, fetchMock } = (await this.renderComponent([]))
|
||||
const { fetchMock } = await this.renderComponent([])
|
||||
|
||||
await fireEvent.click(getByTitle('Refresh'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Refresh' }))
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith(playlist, true)
|
||||
})
|
||||
|
|
|
@ -2,7 +2,7 @@ import { expect, it } from 'vitest'
|
|||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { commonStore, queueStore } from '@/stores'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { playbackService } from '@/services'
|
||||
import QueueScreen from './QueueScreen.vue'
|
||||
|
||||
|
@ -10,7 +10,7 @@ new class extends UnitTestCase {
|
|||
private renderComponent (songs: Song[]) {
|
||||
queueStore.state.songs = songs
|
||||
|
||||
return this.render(QueueScreen, {
|
||||
this.render(QueueScreen, {
|
||||
global: {
|
||||
stubs: {
|
||||
SongList: this.stub('song-list')
|
||||
|
@ -21,17 +21,17 @@ new class extends UnitTestCase {
|
|||
|
||||
protected test () {
|
||||
it('renders the queue', () => {
|
||||
const { queryByTestId } = this.renderComponent(factory<Song>('song', 3))
|
||||
this.renderComponent(factory<Song>('song', 3))
|
||||
|
||||
expect(queryByTestId('song-list')).toBeTruthy()
|
||||
expect(queryByTestId('screen-empty-state')).toBeNull()
|
||||
expect(screen.queryByTestId('song-list')).toBeTruthy()
|
||||
expect(screen.queryByTestId('screen-empty-state')).toBeNull()
|
||||
})
|
||||
|
||||
it('renders an empty state if no songs queued', () => {
|
||||
const { queryByTestId } = this.renderComponent([])
|
||||
this.renderComponent([])
|
||||
|
||||
expect(queryByTestId('song-list')).toBeNull()
|
||||
expect(queryByTestId('screen-empty-state')).toBeTruthy()
|
||||
expect(screen.queryByTestId('song-list')).toBeNull()
|
||||
expect(screen.queryByTestId('screen-empty-state')).toBeTruthy()
|
||||
})
|
||||
|
||||
it('has an option to plays some random songs if the library is not empty', async () => {
|
||||
|
@ -39,8 +39,8 @@ new class extends UnitTestCase {
|
|||
const fetchRandomMock = this.mock(queueStore, 'fetchRandom')
|
||||
const playMock = this.mock(playbackService, 'playFirstInQueue')
|
||||
|
||||
const { getByText } = this.renderComponent([])
|
||||
await fireEvent.click(getByText('playing some random songs'))
|
||||
this.renderComponent([])
|
||||
await this.user.click(screen.getByText('playing some random songs'))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchRandomMock).toHaveBeenCalled()
|
||||
|
@ -50,10 +50,10 @@ new class extends UnitTestCase {
|
|||
|
||||
it('Shuffles all', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const { getByTitle } = this.renderComponent(songs)
|
||||
this.renderComponent(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
|
||||
await fireEvent.click(getByTitle('Shuffle all songs'))
|
||||
await this.user.click(screen.getByTitle('Shuffle all songs'))
|
||||
await waitFor(() => expect(playMock).toHaveBeenCalledWith(songs, true))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
No songs queued.
|
||||
<span v-if="libraryNotEmpty" class="d-block secondary">
|
||||
How about
|
||||
<a class="start" data-testid="shuffle-library" @click.prevent="shuffleSome">playing some random songs</a>?
|
||||
<a class="start" @click.prevent="shuffleSome">playing some random songs</a>?
|
||||
</span>
|
||||
</ScreenEmptyState>
|
||||
</section>
|
||||
|
|
|
@ -2,7 +2,7 @@ import { expect, it } from 'vitest'
|
|||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { recentlyPlayedStore } from '@/stores'
|
||||
import { waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import RecentlyPlayedScreen from './RecentlyPlayedScreen.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
|
@ -10,7 +10,7 @@ new class extends UnitTestCase {
|
|||
recentlyPlayedStore.state.songs = songs
|
||||
const fetchMock = this.mock(recentlyPlayedStore, 'fetch')
|
||||
|
||||
const rendered = this.render(RecentlyPlayedScreen, {
|
||||
this.render(RecentlyPlayedScreen, {
|
||||
global: {
|
||||
stubs: {
|
||||
SongList: this.stub('song-list')
|
||||
|
@ -21,23 +21,21 @@ new class extends UnitTestCase {
|
|||
await this.router.activateRoute({ path: 'recently-played', screen: 'RecentlyPlayed' })
|
||||
|
||||
await waitFor(() => expect(fetchMock).toHaveBeenCalled())
|
||||
|
||||
return rendered
|
||||
}
|
||||
|
||||
protected test () {
|
||||
it('displays the songs', async () => {
|
||||
const { queryByTestId } = await this.renderComponent(factory<Song>('song', 3))
|
||||
await this.renderComponent(factory<Song>('song', 3))
|
||||
|
||||
expect(queryByTestId('song-list')).toBeTruthy()
|
||||
expect(queryByTestId('screen-empty-state')).toBeNull()
|
||||
screen.getByTestId('song-list')
|
||||
expect(screen.queryByTestId('screen-empty-state')).toBeNull()
|
||||
})
|
||||
|
||||
it('displays the empty state', async () => {
|
||||
const { queryByTestId } = await this.renderComponent([])
|
||||
await this.renderComponent([])
|
||||
|
||||
expect(queryByTestId('song-list')).toBeNull()
|
||||
expect(queryByTestId('screen-empty-state')).toBeTruthy()
|
||||
expect(screen.queryByTestId('song-list')).toBeNull()
|
||||
screen.getByTestId('screen-empty-state')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import SettingsScreen from './SettingsScreen.vue'
|
||||
import { settingStore } from '@/stores'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { DialogBoxStub } from '@/__tests__/stubs'
|
||||
import SettingsScreen from './SettingsScreen.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
|
@ -14,10 +14,10 @@ new class extends UnitTestCase {
|
|||
const goMock = this.mock(this.router, 'go')
|
||||
|
||||
settingStore.state.media_path = ''
|
||||
const { getByLabelText, getByText } = this.render(SettingsScreen)
|
||||
this.render(SettingsScreen)
|
||||
|
||||
await fireEvent.update(getByLabelText('Media Path'), '/media')
|
||||
await fireEvent.click(getByText('Scan'))
|
||||
await this.type(screen.getByLabelText('Media Path'), '/media')
|
||||
await this.user.click(screen.getByRole('button', { name: 'Scan' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(updateMock).toHaveBeenCalledWith({ media_path: '/media' })
|
||||
|
@ -31,10 +31,10 @@ new class extends UnitTestCase {
|
|||
const confirmMock = this.mock(DialogBoxStub.value, 'confirm')
|
||||
|
||||
settingStore.state.media_path = '/old'
|
||||
const { getByLabelText, getByText } = this.render(SettingsScreen)
|
||||
this.render(SettingsScreen)
|
||||
|
||||
await fireEvent.update(getByLabelText('Media Path'), '/new')
|
||||
await fireEvent.click(getByText('Scan'))
|
||||
await this.type(screen.getByLabelText('Media Path'), '/new')
|
||||
await this.user.click(screen.getByRole('button', { name: 'Scan' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(updateMock).not.toHaveBeenCalled()
|
||||
|
|
|
@ -1,10 +1,45 @@
|
|||
import { it } from 'vitest'
|
||||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { http } from '@/services'
|
||||
import { eventBus } from '@/utils'
|
||||
import Btn from '@/components/ui/Btn.vue'
|
||||
import BtnGroup from '@/components/ui/BtnGroup.vue'
|
||||
import UserListScreen from './UserListScreen.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('displays a list of users', () => {
|
||||
private async renderComponent () {
|
||||
const fetchMock = this.mock(http, 'get').mockResolvedValue(factory<User>('user', 6))
|
||||
|
||||
this.render(UserListScreen, {
|
||||
global: {
|
||||
stubs: {
|
||||
Btn,
|
||||
BtnGroup,
|
||||
UserCard: this.stub('user-card')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
expect(fetchMock).toHaveBeenCalledWith('users')
|
||||
|
||||
await this.tick(2)
|
||||
}
|
||||
|
||||
protected test () {
|
||||
it('displays a list of users', async () => {
|
||||
await this.renderComponent()
|
||||
expect(screen.getAllByTestId('user-card')).toHaveLength(6)
|
||||
})
|
||||
|
||||
it('triggers create user modal', async () => {
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
await this.renderComponent()
|
||||
|
||||
await this.user.click(screen.getByRole('button', { name: 'Add' }))
|
||||
|
||||
expect(emitMock).toHaveBeenCalledWith('MODAL_SHOW_ADD_USER_FORM')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
<template v-slot:controls>
|
||||
<BtnGroup uppercased v-if="showingControls || !isPhone">
|
||||
<Btn class="btn-add" data-testid="add-user-btn" green @click="showAddUserForm">
|
||||
<Btn class="btn-add" green @click="showAddUserForm">
|
||||
<icon :icon="faPlus"/>
|
||||
Add
|
||||
</Btn>
|
||||
|
|
|
@ -8,7 +8,13 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('displays the songs', () => {
|
||||
overviewStore.state.mostPlayedSongs = factory<Song>('song', 6)
|
||||
expect(this.render(MostPlayedSongs).getAllByTestId('song-card')).toHaveLength(6)
|
||||
expect(this.render(MostPlayedSongs, {
|
||||
global: {
|
||||
stubs: {
|
||||
SongCard: this.stub('song-card')
|
||||
}
|
||||
}
|
||||
}).getAllByTestId('song-card')).toHaveLength(6)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,13 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('displays the songs', () => {
|
||||
overviewStore.state.recentlyAddedSongs = factory<Song>('song', 6)
|
||||
expect(this.render(RecentlyAddedSongs).getAllByTestId('song-card')).toHaveLength(6)
|
||||
expect(this.render(RecentlyAddedSongs, {
|
||||
global: {
|
||||
stubs: {
|
||||
SongCard: this.stub('song-card')
|
||||
}
|
||||
}
|
||||
}).getAllByTestId('song-card')).toHaveLength(6)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,22 +1,28 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { overviewStore } from '@/stores'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import RecentlyPlayedSongs from './RecentlyPlayedSongs.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('displays the songs', () => {
|
||||
overviewStore.state.recentlyPlayed = factory<Song>('song', 6)
|
||||
expect(this.render(RecentlyPlayedSongs).getAllByTestId('song-card')).toHaveLength(6)
|
||||
expect(this.render(RecentlyPlayedSongs, {
|
||||
global: {
|
||||
stubs: {
|
||||
SongCard: this.stub('song-card')
|
||||
}
|
||||
}
|
||||
}).getAllByTestId('song-card')).toHaveLength(6)
|
||||
})
|
||||
|
||||
it('goes to dedicated screen', async () => {
|
||||
const mock = this.mock(this.router, 'go')
|
||||
const { getByTestId } = this.render(RecentlyPlayedSongs)
|
||||
this.render(RecentlyPlayedSongs)
|
||||
|
||||
await fireEvent.click(getByTestId('home-view-all-recently-played-btn'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'View All' }))
|
||||
|
||||
expect(mock).toHaveBeenCalledWith('recently-played')
|
||||
})
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
Recently Played
|
||||
<Btn
|
||||
v-if="songs.length"
|
||||
data-testid="home-view-all-recently-played-btn"
|
||||
orange
|
||||
rounded
|
||||
small
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { clone } from 'lodash'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { favoriteStore, playlistStore, queueStore } from '@/stores'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { arrayify } from '@/utils'
|
||||
import Btn from '@/components/ui/Btn.vue'
|
||||
import AddToMenu from './AddToMenu.vue'
|
||||
import { arrayify } from '@/utils'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
|
||||
let songs: Song[]
|
||||
|
||||
|
@ -52,8 +52,8 @@ new class extends UnitTestCase {
|
|||
['playlists', 'add-to-playlist'],
|
||||
['newPlaylist', 'new-playlist']
|
||||
])('renders disabling %s config', (configKey: keyof AddToMenuConfig, testIds: string | string[]) => {
|
||||
const { queryByTestId } = this.renderComponent({ [configKey]: false })
|
||||
arrayify(testIds).forEach(async (id) => expect(await queryByTestId(id)).toBeNull())
|
||||
this.renderComponent({ [configKey]: false })
|
||||
arrayify(testIds).forEach(id => expect(screen.queryByTestId(id)).toBeNull())
|
||||
})
|
||||
|
||||
it.each<[string, string, MethodOf<typeof queueStore>]>([
|
||||
|
@ -65,18 +65,18 @@ new class extends UnitTestCase {
|
|||
queueStore.state.songs[2].playback_state = 'Playing'
|
||||
|
||||
const mock = this.mock(queueStore, queueMethod)
|
||||
const { getByTestId } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTestId(testId))
|
||||
await this.user.click(screen.getByTestId(testId))
|
||||
|
||||
expect(mock).toHaveBeenCalledWith(songs)
|
||||
})
|
||||
|
||||
it('adds songs to Favorites', async () => {
|
||||
const mock = this.mock(favoriteStore, 'like')
|
||||
const { getByTestId } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTestId('add-to-favorites'))
|
||||
await this.user.click(screen.getByTestId('add-to-favorites'))
|
||||
|
||||
expect(mock).toHaveBeenCalledWith(songs)
|
||||
})
|
||||
|
@ -84,9 +84,9 @@ new class extends UnitTestCase {
|
|||
it('adds songs to existing playlist', async () => {
|
||||
const mock = this.mock(playlistStore, 'addSongs')
|
||||
playlistStore.state.playlists = factory<Playlist>('playlist', 3)
|
||||
const { getAllByTestId } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getAllByTestId('add-to-playlist')[1])
|
||||
await this.user.click(screen.getAllByTestId('add-to-playlist')[1])
|
||||
|
||||
expect(mock).toHaveBeenCalledWith(playlistStore.state.playlists[1], songs)
|
||||
})
|
||||
|
|
|
@ -4,7 +4,7 @@ import UnitTestCase from '@/__tests__/UnitTestCase'
|
|||
import { arrayify, eventBus } from '@/utils'
|
||||
import { ModalContextKey } from '@/symbols'
|
||||
import { ref } from 'vue'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { songStore } from '@/stores'
|
||||
import { MessageToasterStub } from '@/__tests__/stubs'
|
||||
import EditSongForm from './EditSongForm.vue'
|
||||
|
@ -37,7 +37,7 @@ new class extends UnitTestCase {
|
|||
const emitMock = this.mock(eventBus, 'emit')
|
||||
const alertMock = this.mock(MessageToasterStub.value, 'success')
|
||||
|
||||
const { html, getByTestId, getByRole } = await this.renderComponent(factory<Song>('song', {
|
||||
const { html } = await this.renderComponent(factory<Song>('song', {
|
||||
title: 'Rocket to Heaven',
|
||||
artist_name: 'Led Zeppelin',
|
||||
album_name: 'IV',
|
||||
|
@ -47,17 +47,17 @@ new class extends UnitTestCase {
|
|||
|
||||
expect(html()).toMatchSnapshot()
|
||||
|
||||
await fireEvent.update(getByTestId('title-input'), 'Highway to Hell')
|
||||
await fireEvent.update(getByTestId('artist-input'), 'AC/DC')
|
||||
await fireEvent.update(getByTestId('albumArtist-input'), 'AC/DC')
|
||||
await fireEvent.update(getByTestId('album-input'), 'Back in Black')
|
||||
await fireEvent.update(getByTestId('disc-input'), '1')
|
||||
await fireEvent.update(getByTestId('track-input'), '10')
|
||||
await fireEvent.update(getByTestId('genre-input'), 'Rock & Roll')
|
||||
await fireEvent.update(getByTestId('year-input'), '1971')
|
||||
await fireEvent.update(getByTestId('lyrics-input'), 'I\'m gonna make him an offer he can\'t refuse')
|
||||
await this.type(screen.getByTestId('title-input'), 'Highway to Hell')
|
||||
await this.type(screen.getByTestId('artist-input'), 'AC/DC')
|
||||
await this.type(screen.getByTestId('albumArtist-input'), 'AC/DC')
|
||||
await this.type(screen.getByTestId('album-input'), 'Back in Black')
|
||||
await this.type(screen.getByTestId('disc-input'), '1')
|
||||
await this.type(screen.getByTestId('track-input'), '10')
|
||||
await this.type(screen.getByTestId('genre-input'), 'Rock & Roll')
|
||||
await this.type(screen.getByTestId('year-input'), '1971')
|
||||
await this.type(screen.getByTestId('lyrics-input'), 'I\'m gonna make him an offer he can\'t refuse')
|
||||
|
||||
await fireEvent.click(getByRole('button', { name: 'Update' }))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Update' }))
|
||||
|
||||
expect(updateMock).toHaveBeenCalledWith(songs, {
|
||||
title: 'Highway to Hell',
|
||||
|
@ -80,21 +80,21 @@ new class extends UnitTestCase {
|
|||
const emitMock = this.mock(eventBus, 'emit')
|
||||
const alertMock = this.mock(MessageToasterStub.value, 'success')
|
||||
|
||||
const { html, getByTestId, getByRole, queryByTestId } = await this.renderComponent(factory<Song>('song', 3))
|
||||
const { html } = await this.renderComponent(factory<Song>('song', 3))
|
||||
|
||||
expect(html()).toMatchSnapshot()
|
||||
expect(queryByTestId('title-input')).toBeNull()
|
||||
expect(queryByTestId('lyrics-input')).toBeNull()
|
||||
expect(screen.queryByTestId('title-input')).toBeNull()
|
||||
expect(screen.queryByTestId('lyrics-input')).toBeNull()
|
||||
|
||||
await fireEvent.update(getByTestId('artist-input'), 'AC/DC')
|
||||
await fireEvent.update(getByTestId('albumArtist-input'), 'AC/DC')
|
||||
await fireEvent.update(getByTestId('album-input'), 'Back in Black')
|
||||
await fireEvent.update(getByTestId('disc-input'), '1')
|
||||
await fireEvent.update(getByTestId('track-input'), '10')
|
||||
await fireEvent.update(getByTestId('year-input'), '1990')
|
||||
await fireEvent.update(getByTestId('genre-input'), 'Pop')
|
||||
await this.type(screen.getByTestId('artist-input'), 'AC/DC')
|
||||
await this.type(screen.getByTestId('albumArtist-input'), 'AC/DC')
|
||||
await this.type(screen.getByTestId('album-input'), 'Back in Black')
|
||||
await this.type(screen.getByTestId('disc-input'), '1')
|
||||
await this.type(screen.getByTestId('track-input'), '10')
|
||||
await this.type(screen.getByTestId('year-input'), '1990')
|
||||
await this.type(screen.getByTestId('genre-input'), 'Pop')
|
||||
|
||||
await fireEvent.click(getByRole('button', { name: 'Update' }))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Update' }))
|
||||
|
||||
expect(updateMock).toHaveBeenCalledWith(songs, {
|
||||
album_name: 'Back in Black',
|
||||
|
@ -111,15 +111,15 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('displays artist name if all songs have the same artist', async () => {
|
||||
const { getByTestId } = await this.renderComponent(factory<Song>('song', 4, {
|
||||
await this.renderComponent(factory<Song>('song', 4, {
|
||||
artist_id: 1000,
|
||||
artist_name: 'Led Zeppelin',
|
||||
album_id: 1001,
|
||||
album_name: 'IV'
|
||||
}))
|
||||
|
||||
expect(getByTestId('displayed-artist-name').textContent).toBe('Led Zeppelin')
|
||||
expect(getByTestId('displayed-album-name').textContent).toBe('IV')
|
||||
expect(screen.getByTestId('displayed-artist-name').textContent).toBe('Led Zeppelin')
|
||||
expect(screen.getByTestId('displayed-album-name').textContent).toBe('IV')
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ import factory from '@/__tests__/factory'
|
|||
import { queueStore } from '@/stores'
|
||||
import { playbackService } from '@/services'
|
||||
import { expect, it } from 'vitest'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import SongCard from './SongCard.vue'
|
||||
|
||||
|
@ -32,17 +32,17 @@ new class extends UnitTestCase {
|
|||
|
||||
protected test () {
|
||||
it('has a thumbnail and a like button', () => {
|
||||
const { getByTestId } = this.renderComponent()
|
||||
getByTestId('thumbnail')
|
||||
getByTestId('like-button')
|
||||
this.renderComponent()
|
||||
screen.getByTestId('thumbnail')
|
||||
screen.getByTestId('like-button')
|
||||
})
|
||||
|
||||
it('queues and plays on double-click', async () => {
|
||||
const queueMock = this.mock(queueStore, 'queueIfNotQueued')
|
||||
const playMock = this.mock(playbackService, 'play')
|
||||
const { getByTestId } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.dblClick(getByTestId('song-card'))
|
||||
await this.user.dblClick(screen.getByRole('article'))
|
||||
|
||||
expect(queueMock).toHaveBeenCalledWith(song)
|
||||
expect(playMock).toHaveBeenCalledWith(song)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<template>
|
||||
<article
|
||||
:class="{ playing: song.playback_state === 'Playing' || song.playback_state === 'Paused' }"
|
||||
data-testid="song-card"
|
||||
draggable="true"
|
||||
tabindex="0"
|
||||
@dragstart="onDragStart"
|
||||
|
|
|
@ -2,7 +2,7 @@ import { expect, it } from 'vitest'
|
|||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { arrayify, eventBus } from '@/utils'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { downloadService, playbackService } from '@/services'
|
||||
import { favoriteStore, playlistStore, queueStore, songStore } from '@/stores'
|
||||
import { DialogBoxStub, MessageToasterStub } from '@/__tests__/stubs'
|
||||
|
@ -19,7 +19,7 @@ new class extends UnitTestCase {
|
|||
songs = arrayify(_songs || factory<Song>('song', 5))
|
||||
|
||||
const rendered = this.render(SongContextMenu)
|
||||
eventBus.emit('SONG_CONTEXT_MENU_REQUESTED', { pageX: 420, pageY: 42 }, songs)
|
||||
eventBus.emit('SONG_CONTEXT_MENU_REQUESTED', { pageX: 420, pageY: 42 } as MouseEvent, songs)
|
||||
await this.tick(2)
|
||||
|
||||
return rendered
|
||||
|
@ -35,9 +35,9 @@ new class extends UnitTestCase {
|
|||
const queueMock = this.mock(queueStore, 'queueIfNotQueued')
|
||||
const playMock = this.mock(playbackService, 'play')
|
||||
const song = factory<Song>('song', { playback_state: 'Stopped' })
|
||||
const { getByText } = await this.renderComponent(song)
|
||||
await this.renderComponent(song)
|
||||
|
||||
await fireEvent.click(getByText('Play'))
|
||||
await this.user.click(screen.getByText('Play'))
|
||||
|
||||
expect(queueMock).toHaveBeenCalledWith(song)
|
||||
expect(playMock).toHaveBeenCalledWith(song)
|
||||
|
@ -45,54 +45,54 @@ new class extends UnitTestCase {
|
|||
|
||||
it('pauses playback', async () => {
|
||||
const pauseMock = this.mock(playbackService, 'pause')
|
||||
const { getByText } = await this.renderComponent(factory<Song>('song', { playback_state: 'Playing' }))
|
||||
await this.renderComponent(factory<Song>('song', { playback_state: 'Playing' }))
|
||||
|
||||
await fireEvent.click(getByText('Pause'))
|
||||
await this.user.click(screen.getByText('Pause'))
|
||||
|
||||
expect(pauseMock).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('resumes playback', async () => {
|
||||
const resumeMock = this.mock(playbackService, 'resume')
|
||||
const { getByText } = await this.renderComponent(factory<Song>('song', { playback_state: 'Paused' }))
|
||||
await this.renderComponent(factory<Song>('song', { playback_state: 'Paused' }))
|
||||
|
||||
await fireEvent.click(getByText('Play'))
|
||||
await this.user.click(screen.getByText('Play'))
|
||||
|
||||
expect(resumeMock).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('goes to album details screen', async () => {
|
||||
const goMock = this.mock(this.router, 'go')
|
||||
const { getByText } = await this.renderComponent(factory<Song>('song'))
|
||||
await this.renderComponent(factory<Song>('song'))
|
||||
|
||||
await fireEvent.click(getByText('Go to Album'))
|
||||
await this.user.click(screen.getByText('Go to Album'))
|
||||
|
||||
expect(goMock).toHaveBeenCalledWith(`album/${songs[0].album_id}`)
|
||||
})
|
||||
|
||||
it('goes to artist details screen', async () => {
|
||||
const goMock = this.mock(this.router, 'go')
|
||||
const { getByText } = await this.renderComponent(factory<Song>('song'))
|
||||
await this.renderComponent(factory<Song>('song'))
|
||||
|
||||
await fireEvent.click(getByText('Go to Artist'))
|
||||
await this.user.click(screen.getByText('Go to Artist'))
|
||||
|
||||
expect(goMock).toHaveBeenCalledWith(`artist/${songs[0].artist_id}`)
|
||||
})
|
||||
|
||||
it('downloads', async () => {
|
||||
const downloadMock = this.mock(downloadService, 'fromSongs')
|
||||
const { getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByText('Download'))
|
||||
await this.user.click(screen.getByText('Download'))
|
||||
|
||||
expect(downloadMock).toHaveBeenCalledWith(songs)
|
||||
})
|
||||
|
||||
it('queues', async () => {
|
||||
const queueMock = this.mock(queueStore, 'queue')
|
||||
const { getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByText('Queue'))
|
||||
await this.user.click(screen.getByText('Queue'))
|
||||
|
||||
expect(queueMock).toHaveBeenCalledWith(songs)
|
||||
})
|
||||
|
@ -100,9 +100,9 @@ new class extends UnitTestCase {
|
|||
it('queues after current song', async () => {
|
||||
this.fillQueue()
|
||||
const queueMock = this.mock(queueStore, 'queueAfterCurrent')
|
||||
const { getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByText('After Current Song'))
|
||||
await this.user.click(screen.getByText('After Current Song'))
|
||||
|
||||
expect(queueMock).toHaveBeenCalledWith(songs)
|
||||
})
|
||||
|
@ -110,9 +110,9 @@ new class extends UnitTestCase {
|
|||
it('queues to bottom', async () => {
|
||||
this.fillQueue()
|
||||
const queueMock = this.mock(queueStore, 'queue')
|
||||
const { getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByText('Bottom of Queue'))
|
||||
await this.user.click(screen.getByText('Bottom of Queue'))
|
||||
|
||||
expect(queueMock).toHaveBeenCalledWith(songs)
|
||||
})
|
||||
|
@ -120,9 +120,9 @@ new class extends UnitTestCase {
|
|||
it('queues to top', async () => {
|
||||
this.fillQueue()
|
||||
const queueMock = this.mock(queueStore, 'queueToTop')
|
||||
const { getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByText('Top of Queue'))
|
||||
await this.user.click(screen.getByText('Top of Queue'))
|
||||
|
||||
expect(queueMock).toHaveBeenCalledWith(songs)
|
||||
})
|
||||
|
@ -136,9 +136,9 @@ new class extends UnitTestCase {
|
|||
screen: 'Queue'
|
||||
})
|
||||
|
||||
const { getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByText('Remove from Queue'))
|
||||
await this.user.click(screen.getByText('Remove from Queue'))
|
||||
|
||||
expect(removeMock).toHaveBeenCalledWith(songs)
|
||||
})
|
||||
|
@ -151,16 +151,16 @@ new class extends UnitTestCase {
|
|||
screen: 'Songs'
|
||||
})
|
||||
|
||||
const { queryByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
expect(queryByText('Remove from Queue')).toBeNull()
|
||||
expect(screen.queryByText('Remove from Queue')).toBeNull()
|
||||
})
|
||||
|
||||
it('adds to favorites', async () => {
|
||||
const likeMock = this.mock(favoriteStore, 'like')
|
||||
const { getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByText('Favorites'))
|
||||
await this.user.click(screen.getByText('Favorites'))
|
||||
|
||||
expect(likeMock).toHaveBeenCalledWith(songs)
|
||||
})
|
||||
|
@ -171,9 +171,9 @@ new class extends UnitTestCase {
|
|||
screen: 'Favorites'
|
||||
})
|
||||
|
||||
const { queryByText } = await this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
expect(queryByText('Favorites')).toBeNull()
|
||||
expect(screen.queryByText('Favorites')).toBeNull()
|
||||
})
|
||||
|
||||
it('removes from favorites', async () => {
|
||||
|
@ -184,9 +184,9 @@ new class extends UnitTestCase {
|
|||
screen: 'Favorites'
|
||||
})
|
||||
|
||||
const { getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByText('Remove from Favorites'))
|
||||
await this.user.click(screen.getByText('Remove from Favorites'))
|
||||
|
||||
expect(unlikeMock).toHaveBeenCalledWith(songs)
|
||||
})
|
||||
|
@ -195,11 +195,11 @@ new class extends UnitTestCase {
|
|||
playlistStore.state.playlists = factory<Playlist>('playlist', 3)
|
||||
const addMock = this.mock(playlistStore, 'addSongs')
|
||||
this.mock(MessageToasterStub.value, 'success')
|
||||
const { queryByText, getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
playlistStore.state.playlists.forEach(playlist => queryByText(playlist.name))
|
||||
playlistStore.state.playlists.forEach(playlist => screen.queryByText(playlist.name))
|
||||
|
||||
await fireEvent.click(getByText(playlistStore.state.playlists[0].name))
|
||||
await this.user.click(screen.getByText(playlistStore.state.playlists[0].name))
|
||||
|
||||
expect(addMock).toHaveBeenCalledWith(playlistStore.state.playlists[0], songs)
|
||||
})
|
||||
|
@ -208,9 +208,9 @@ new class extends UnitTestCase {
|
|||
playlistStore.state.playlists = factory<Playlist>('playlist', 3)
|
||||
playlistStore.state.playlists.push(factory.states('smart')<Playlist>('playlist', { name: 'My Smart Playlist' }))
|
||||
|
||||
const { queryByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
expect(queryByText('My Smart Playlist')).toBeNull()
|
||||
expect(screen.queryByText('My Smart Playlist')).toBeNull()
|
||||
})
|
||||
|
||||
it('removes from playlist', async () => {
|
||||
|
@ -222,12 +222,12 @@ new class extends UnitTestCase {
|
|||
screen: 'Playlist'
|
||||
}, { id: String(playlist.id) })
|
||||
|
||||
const { getByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
const removeSongsMock = this.mock(playlistStore, 'removeSongs')
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
|
||||
await fireEvent.click(getByText('Remove from Playlist'))
|
||||
await this.user.click(screen.getByText('Remove from Playlist'))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(removeSongsMock).toHaveBeenCalledWith(playlist, songs)
|
||||
|
@ -241,41 +241,40 @@ new class extends UnitTestCase {
|
|||
screen: 'Songs'
|
||||
})
|
||||
|
||||
const { queryByText } = await this.renderComponent()
|
||||
await this.renderComponent()
|
||||
|
||||
expect(queryByText('Remove from Playlist')).toBeNull()
|
||||
expect(screen.queryByText('Remove from Playlist')).toBeNull()
|
||||
})
|
||||
|
||||
it('allows edit songs if current user is admin', async () => {
|
||||
const { getByText } = await this.actingAsAdmin().renderComponent()
|
||||
await this.actingAsAdmin().renderComponent()
|
||||
|
||||
// mock after render to ensure that the component is mounted properly
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
await fireEvent.click(getByText('Edit'))
|
||||
await this.user.click(screen.getByText('Edit'))
|
||||
|
||||
expect(emitMock).toHaveBeenCalledWith('MODAL_SHOW_EDIT_SONG_FORM', songs)
|
||||
})
|
||||
|
||||
it('does not allow edit songs if current user is not admin', async () => {
|
||||
const { queryByText } = await this.actingAs().renderComponent()
|
||||
expect(queryByText('Edit')).toBeNull()
|
||||
await this.actingAs().renderComponent()
|
||||
expect(screen.queryByText('Edit')).toBeNull()
|
||||
})
|
||||
|
||||
it('has an option to copy shareable URL', async () => {
|
||||
const { getByText } = await this.renderComponent(factory<Song>('song'))
|
||||
|
||||
getByText('Copy Shareable URL')
|
||||
await this.renderComponent(factory<Song>('song'))
|
||||
screen.getByText('Copy Shareable URL')
|
||||
})
|
||||
|
||||
it('deletes song', async () => {
|
||||
const confirmMock = this.mock(DialogBoxStub.value, 'confirm', true)
|
||||
const toasterMock = this.mock(MessageToasterStub.value, 'success')
|
||||
const deleteMock = this.mock(songStore, 'deleteFromFilesystem')
|
||||
const { getByText } = await this.actingAsAdmin().renderComponent()
|
||||
await this.actingAsAdmin().renderComponent()
|
||||
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
|
||||
await fireEvent.click(getByText('Delete from Filesystem'))
|
||||
await this.user.click(screen.getByText('Delete from Filesystem'))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(confirmMock).toHaveBeenCalled()
|
||||
|
@ -286,8 +285,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('does not have an option to delete songs if current user is not admin', async () => {
|
||||
const { queryByText } = await this.actingAs().renderComponent()
|
||||
expect(queryByText('Delete from Filesystem')).toBeNull()
|
||||
await this.actingAs().renderComponent()
|
||||
expect(screen.queryByText('Delete from Filesystem')).toBeNull()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,26 +1,30 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { favoriteStore } from '@/stores'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import SongLikeButton from './SongLikeButton.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it.each<[boolean, string]>([
|
||||
[true, 'btn-like-liked'],
|
||||
[false, 'btn-like-unliked']
|
||||
])('likes or unlikes', async (liked: boolean, testId: string) => {
|
||||
it.each<[string, boolean]>([
|
||||
['Unlike Foo by Bar', true],
|
||||
['Like Foo by Bar', false]
|
||||
])('%s', async (name: string, liked: boolean) => {
|
||||
const mock = this.mock(favoriteStore, 'toggleOne')
|
||||
const song = factory<Song>('song', { liked })
|
||||
const song = factory<Song>('song', {
|
||||
liked,
|
||||
title: 'Foo',
|
||||
artist_name: 'Bar'
|
||||
})
|
||||
|
||||
const { getByTestId } = this.render(SongLikeButton, {
|
||||
this.render(SongLikeButton, {
|
||||
props: {
|
||||
song
|
||||
}
|
||||
})
|
||||
|
||||
await fireEvent.click(getByTestId(testId))
|
||||
await this.user.click(screen.getByRole('button', { name }))
|
||||
|
||||
expect(mock).toHaveBeenCalledWith(song)
|
||||
})
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<button :title="title" data-testid="like-btn" type="button" @click.stop="toggleLike">
|
||||
<icon v-if="song.liked" :icon="faHeart" data-testid="btn-like-liked"/>
|
||||
<icon v-else :icon="faEmptyHeart" data-testid="btn-like-unliked"/>
|
||||
<button :title="title" type="button" @click.stop="toggleLike">
|
||||
<icon v-if="song.liked" :icon="faHeart"/>
|
||||
<icon v-else :icon="faEmptyHeart"/>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { ref } from 'vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { arrayify } from '@/utils'
|
||||
import { SelectedSongsKey, SongListConfigKey, SongListSortFieldKey, SongListSortOrderKey, SongsKey } from '@/symbols'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import SongList from './SongList.vue'
|
||||
|
||||
let songs: Song[]
|
||||
|
@ -59,22 +59,22 @@ new class extends UnitTestCase {
|
|||
['album_name', 'header-album'],
|
||||
['length', 'header-length']
|
||||
])('sorts by %s upon %s clicked', async (field, testId) => {
|
||||
const { getByTestId, emitted } = await this.renderComponent(factory<Song>('song', 5))
|
||||
const { emitted } = await this.renderComponent(factory<Song>('song', 5))
|
||||
|
||||
await fireEvent.click(getByTestId(testId))
|
||||
await this.user.click(screen.getByTestId(testId))
|
||||
expect(emitted().sort[0]).toEqual([field, 'desc'])
|
||||
|
||||
await fireEvent.click(getByTestId(testId))
|
||||
await this.user.click(screen.getByTestId(testId))
|
||||
expect(emitted().sort[1]).toEqual([field, 'asc'])
|
||||
})
|
||||
|
||||
it('cannot be sorted if configured so', async () => {
|
||||
const { getByTestId, emitted } = await this.renderComponent(factory<Song>('song', 5), {
|
||||
const { emitted } = await this.renderComponent(factory<Song>('song', 5), {
|
||||
sortable: false,
|
||||
reorderable: true
|
||||
})
|
||||
|
||||
await fireEvent.click(getByTestId('header-track-number'))
|
||||
await this.user.click(screen.getByTestId('header-track-number'))
|
||||
expect(emitted().sort).toBeUndefined()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ import { take } from 'lodash'
|
|||
import { ref } from 'vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { SelectedSongsKey, SongsKey } from '@/symbols'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import SongListControls from './SongListControls.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
|
@ -26,51 +26,53 @@ new class extends UnitTestCase {
|
|||
|
||||
protected test () {
|
||||
it.each([[0], [1]])('shuffles all if %s songs are selected', async (selectedCount: number) => {
|
||||
const { emitted, getByTitle } = this.renderComponent(selectedCount)
|
||||
const { emitted } = this.renderComponent(selectedCount)
|
||||
|
||||
await fireEvent.click(getByTitle('Shuffle all songs'))
|
||||
await this.user.click(screen.getByTitle('Shuffle all songs'))
|
||||
|
||||
expect(emitted().playAll[0]).toEqual([true])
|
||||
})
|
||||
|
||||
it.each([[0], [1]])('plays all if %s songs are selected with Alt pressed', async (selectedCount: number) => {
|
||||
const { emitted, getByTitle } = this.renderComponent(selectedCount)
|
||||
const { emitted } = this.renderComponent(selectedCount)
|
||||
|
||||
await fireEvent.keyDown(window, { key: 'Alt' })
|
||||
await fireEvent.click(getByTitle('Play all songs'))
|
||||
await this.user.keyboard('{Alt>}')
|
||||
await this.user.click(screen.getByTitle('Play all songs'))
|
||||
await this.user.keyboard('{/Alt}')
|
||||
|
||||
expect(emitted().playAll[0]).toEqual([false])
|
||||
})
|
||||
|
||||
it('shuffles selected if more than one song are selected', async () => {
|
||||
const { emitted, getByTitle } = this.renderComponent(2)
|
||||
const { emitted } = this.renderComponent(2)
|
||||
|
||||
await fireEvent.click(getByTitle('Shuffle selected songs'))
|
||||
await this.user.click(screen.getByTitle('Shuffle selected songs'))
|
||||
|
||||
expect(emitted().playSelected[0]).toEqual([true])
|
||||
})
|
||||
|
||||
it('plays selected if more than one song are selected with Alt pressed', async () => {
|
||||
const { emitted, getByTitle } = this.renderComponent(2)
|
||||
const { emitted } = this.renderComponent(2)
|
||||
|
||||
await fireEvent.keyDown(window, { key: 'Alt' })
|
||||
await fireEvent.click(getByTitle('Play selected songs'))
|
||||
await this.user.keyboard('{Alt>}')
|
||||
await this.user.click(screen.getByTitle('Play selected songs'))
|
||||
await this.user.keyboard('{/Alt}')
|
||||
|
||||
expect(emitted().playSelected[0]).toEqual([false])
|
||||
})
|
||||
|
||||
it('clears queue', async () => {
|
||||
const { emitted, getByTitle } = this.renderComponent(0, { clearQueue: true })
|
||||
const { emitted } = this.renderComponent(0, { clearQueue: true })
|
||||
|
||||
await fireEvent.click(getByTitle('Clear current queue'))
|
||||
await this.user.click(screen.getByTitle('Clear current queue'))
|
||||
|
||||
expect(emitted().clearQueue).toBeTruthy()
|
||||
})
|
||||
|
||||
it('deletes current playlist', async () => {
|
||||
const { emitted, getByTitle } = this.renderComponent(0, { deletePlaylist: true })
|
||||
const { emitted } = this.renderComponent(0, { deletePlaylist: true })
|
||||
|
||||
await fireEvent.click(getByTitle('Delete this playlist'))
|
||||
await this.user.click(screen.getByTitle('Delete this playlist'))
|
||||
|
||||
expect(emitted().deletePlaylist).toBeTruthy()
|
||||
})
|
||||
|
|
|
@ -2,7 +2,7 @@ import { expect, it } from 'vitest'
|
|||
import factory from '@/__tests__/factory'
|
||||
import { queueStore } from '@/stores'
|
||||
import { playbackService } from '@/services'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import SongListItem from './SongListItem.vue'
|
||||
|
||||
|
@ -44,9 +44,9 @@ new class extends UnitTestCase {
|
|||
it('plays on double click', async () => {
|
||||
const queueMock = this.mock(queueStore, 'queueIfNotQueued')
|
||||
const playMock = this.mock(playbackService, 'play')
|
||||
const { getByTestId } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.dblClick(getByTestId('song-item'))
|
||||
await this.user.dblClick(screen.getByTestId('song-item'))
|
||||
|
||||
expect(queueMock).toHaveBeenCalledWith(row.song)
|
||||
expect(playMock).toHaveBeenCalledWith(row.song)
|
||||
|
|
|
@ -2,8 +2,8 @@ import { expect, it } from 'vitest'
|
|||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { playbackService } from '@/services'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import SongThumbnail from '@/components/song/SongThumbnail.vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
|
||||
let song: Song
|
||||
|
||||
|
@ -23,15 +23,15 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
protected test () {
|
||||
it.each<[PlaybackState, MethodOf<typeof playbackService>]>([
|
||||
['Stopped', 'play'],
|
||||
['Playing', 'pause'],
|
||||
['Paused', 'resume']
|
||||
])('if state is currently "%s", %ss', async (state: PlaybackState, method: MethodOf<typeof playbackService>) => {
|
||||
it.each<[PlaybackState, string, MethodOf<typeof playbackService>]>([
|
||||
['Stopped', 'Play', 'play'],
|
||||
['Playing', 'Pause', 'pause'],
|
||||
['Paused', 'Resume', 'resume']
|
||||
])('if state is currently "%s", %ss', async (state, name, method) => {
|
||||
const mock = this.mock(playbackService, method)
|
||||
const { getByTestId } = this.renderComponent(state)
|
||||
this.renderComponent(state)
|
||||
|
||||
await fireEvent.click(getByTestId('play-control'))
|
||||
await this.user.click(screen.getByRole('button', { name }))
|
||||
|
||||
expect(mock).toHaveBeenCalled()
|
||||
})
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<div :style="{ backgroundImage: `url(${defaultCover})` }" class="cover">
|
||||
<img v-koel-hide-broken-icon :alt="song.album_name" :src="song.album_cover" loading="lazy"/>
|
||||
<a class="control" @click.prevent="changeSongState" data-testid="play-control">
|
||||
<a :title="title" class="control" role="button" @click.prevent="changeSongState">
|
||||
<icon :icon="song.playback_state === 'Playing' ? faPause : faPlay" class="text-highlight"/>
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { toRefs } from 'vue'
|
||||
import { computed, toRefs } from 'vue'
|
||||
import { faPause, faPlay } from '@fortawesome/free-solid-svg-icons'
|
||||
import { defaultCover } from '@/utils'
|
||||
import { playbackService } from '@/services'
|
||||
|
@ -22,6 +22,18 @@ const play = () => {
|
|||
playbackService.play(song.value)
|
||||
}
|
||||
|
||||
const title = computed(() => {
|
||||
if (song.value.playback_state === 'Playing') {
|
||||
return 'Pause'
|
||||
}
|
||||
|
||||
if (song.value.playback_state === 'Paused') {
|
||||
return 'Resume'
|
||||
}
|
||||
|
||||
return 'Play'
|
||||
})
|
||||
|
||||
const changeSongState = () => {
|
||||
if (song.value.playback_state === 'Stopped') {
|
||||
play()
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
// Vitest Snapshot v1
|
||||
|
||||
exports[`renders 1`] = `<div class="playing song-item" data-testid="song-item" tabindex="0"><span class="track-number"><i data-v-47e95701=""><span data-v-47e95701=""></span><span data-v-47e95701=""></span><span data-v-47e95701=""></span></i></span><span class="thumbnail"><div style="background-image: url(undefined/resources/assets/img/covers/default.svg);" class="cover" data-v-a2b2e00f=""><img alt="Test Album" src="https://example.com/cover.jpg" loading="lazy" data-v-a2b2e00f=""><a class="control" data-testid="play-control" data-v-a2b2e00f=""><br data-testid="icon" icon="[object Object]" class="text-highlight" data-v-a2b2e00f=""></a></div></span><span class="title-artist"><span class="title text-primary">Test Song</span><span class="artist">Test Artist</span></span><span class="album">Test Album</span><span class="time">16:40</span><span class="extra"><button title="Unlike Test Song by Test Artist" data-testid="like-btn" type="button"><br data-testid="btn-like-liked" icon="[object Object]"></button></span></div>`;
|
||||
exports[`renders 1`] = `<div class="playing song-item" data-testid="song-item" tabindex="0"><span class="track-number"><i data-v-47e95701=""><span data-v-47e95701=""></span><span data-v-47e95701=""></span><span data-v-47e95701=""></span></i></span><span class="thumbnail"><div style="background-image: url(undefined/resources/assets/img/covers/default.svg);" class="cover" data-v-a2b2e00f=""><img alt="Test Album" src="https://example.com/cover.jpg" loading="lazy" data-v-a2b2e00f=""><a title="Pause" class="control" role="button" data-v-a2b2e00f=""><br data-testid="icon" icon="[object Object]" class="text-highlight" data-v-a2b2e00f=""></a></div></span><span class="title-artist"><span class="title text-primary">Test Song</span><span class="artist">Test Artist</span></span><span class="album">Test Album</span><span class="time">16:40</span><span class="extra"><button title="Unlike Test Song by Test Artist" type="button"><br data-testid="icon" icon="[object Object]"></button></span></div>`;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { waitFor } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import { albumStore } from '@/stores'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import AlbumArtOverlay from './AlbumArtOverlay.vue'
|
||||
import { waitFor } from '@testing-library/vue'
|
||||
|
||||
let albumId: number
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ import { orderBy } from 'lodash'
|
|||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { expect, it } from 'vitest'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { queueStore, songStore } from '@/stores'
|
||||
import { playbackService } from '@/services'
|
||||
import Thumbnail from './AlbumArtistThumbnail.vue'
|
||||
|
@ -50,9 +50,9 @@ new class extends UnitTestCase {
|
|||
const songs = factory<Song>('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const { getByRole } = this.renderForAlbum()
|
||||
this.renderForAlbum()
|
||||
|
||||
await fireEvent.click(getByRole('button'))
|
||||
await this.user.click(screen.getByRole('button'))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalledWith(album)
|
||||
|
@ -64,9 +64,11 @@ new class extends UnitTestCase {
|
|||
const songs = factory<Song>('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(songs)
|
||||
const queueMock = this.mock(queueStore, 'queue')
|
||||
const { getByRole } = this.renderForAlbum()
|
||||
this.renderForAlbum()
|
||||
|
||||
await fireEvent.click(getByRole('button'), { altKey: true })
|
||||
await this.user.keyboard('{Alt>}')
|
||||
await this.user.click(screen.getByRole('button'))
|
||||
await this.user.keyboard('{/Alt}')
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalledWith(album)
|
||||
|
@ -78,9 +80,9 @@ new class extends UnitTestCase {
|
|||
const songs = factory<Song>('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForArtist').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const { getByRole } = this.renderForArtist()
|
||||
this.renderForArtist()
|
||||
|
||||
await fireEvent.click(getByRole('button'))
|
||||
await this.user.click(screen.getByRole('button'))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalledWith(artist)
|
||||
|
@ -92,9 +94,11 @@ new class extends UnitTestCase {
|
|||
const songs = factory<Song>('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForArtist').mockResolvedValue(songs)
|
||||
const queueMock = this.mock(queueStore, 'queue')
|
||||
const { getByRole } = this.renderForArtist()
|
||||
this.renderForArtist()
|
||||
|
||||
await fireEvent.click(getByRole('button'), { altKey: true })
|
||||
await this.user.keyboard('{Alt>}')
|
||||
await this.user.click(screen.getByRole('button'))
|
||||
await this.user.keyboard('{/Alt}')
|
||||
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalledWith(artist)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import BtnCloseModal from './BtnCloseModal.vue'
|
||||
|
||||
|
@ -8,9 +8,9 @@ new class extends UnitTestCase {
|
|||
it('renders', () => expect(this.render(BtnCloseModal).html()).toMatchSnapshot())
|
||||
|
||||
it('emits the event', async () => {
|
||||
const { emitted, getByRole } = this.render(BtnCloseModal)
|
||||
const { emitted } = this.render(BtnCloseModal)
|
||||
|
||||
await fireEvent.click(getByRole('button'))
|
||||
await this.user.click(screen.getByRole('button'))
|
||||
|
||||
expect(emitted().click).toBeTruthy()
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { $ } from '@/utils'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import BtnScrollToTop from './BtnScrollToTop.vue'
|
||||
|
@ -12,9 +12,9 @@ new class extends UnitTestCase {
|
|||
|
||||
it('scrolls to top', async () => {
|
||||
const mock = this.mock($, 'scrollTo')
|
||||
const { getByTitle } = this.render(BtnScrollToTop)
|
||||
this.render(BtnScrollToTop)
|
||||
|
||||
await fireEvent.click(getByTitle('Scroll to top'))
|
||||
await this.user.click(screen.getByTitle('Scroll to top'))
|
||||
|
||||
expect(mock).toHaveBeenCalled()
|
||||
})
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import CheckBox from './CheckBox.vue'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
|
@ -14,9 +14,9 @@ new class extends UnitTestCase {
|
|||
}).html()).toMatchSnapshot())
|
||||
|
||||
it('emits the input event', async () => {
|
||||
const { getByRole, emitted } = this.render(CheckBox)
|
||||
const { emitted } = this.render(CheckBox)
|
||||
|
||||
await fireEvent.input(getByRole('checkbox'))
|
||||
await this.user.click(screen.getByRole('checkbox'))
|
||||
|
||||
expect(emitted()['update:modelValue']).toBeTruthy()
|
||||
})
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import ExtraPanelTabHeader from './ExtraPanelTabHeader.vue'
|
||||
import { commonStore } from '@/stores'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import ExtraPanelTabHeader from './ExtraPanelTabHeader.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('renders tab headers', () => {
|
||||
commonStore.state.use_you_tube = false
|
||||
const { getByTitle, queryByTitle } = this.render(ExtraPanelTabHeader)
|
||||
this.render(ExtraPanelTabHeader)
|
||||
|
||||
;['Lyrics', 'Artist information', 'Album information'].forEach(title => getByTitle(title))
|
||||
expect(queryByTitle('Related YouTube videos')).toBeNull()
|
||||
;['Lyrics', 'Artist information', 'Album information'].forEach(name => screen.getByRole('button', { name }))
|
||||
expect(screen.queryByRole('button', { name: 'Related YouTube videos' })).toBeNull()
|
||||
})
|
||||
|
||||
it('has a YouTube tab header if using YouTube', () => {
|
||||
commonStore.state.use_you_tube = true
|
||||
const { getByTitle } = this.render(ExtraPanelTabHeader)
|
||||
this.render(ExtraPanelTabHeader)
|
||||
|
||||
getByTitle('Related YouTube videos')
|
||||
screen.getByRole('button', { name: 'Related YouTube videos' })
|
||||
})
|
||||
|
||||
it('emits the selected tab value', async () => {
|
||||
const { getByTitle, emitted } = this.render(ExtraPanelTabHeader)
|
||||
const { emitted } = this.render(ExtraPanelTabHeader)
|
||||
|
||||
await fireEvent.click(getByTitle('Lyrics'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Lyrics' }))
|
||||
|
||||
expect(emitted()['update:modelValue']).toEqual([['Lyrics']])
|
||||
})
|
||||
|
|
|
@ -3,7 +3,7 @@ import { ref } from 'vue'
|
|||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { playbackService } from '@/services'
|
||||
import { fireEvent, getByRole, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { CurrentSongKey } from '@/symbols'
|
||||
import { commonStore, favoriteStore, queueStore, recentlyPlayedStore, songStore } from '@/stores'
|
||||
import FooterPlayButton from './FooterPlayButton.vue'
|
||||
|
@ -22,9 +22,9 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('toggles the playback of current song', async () => {
|
||||
const toggleMock = this.mock(playbackService, 'toggle')
|
||||
const { getByRole } = this.renderComponent(factory<Song>('song'))
|
||||
this.renderComponent(factory<Song>('song'))
|
||||
|
||||
await fireEvent.click(getByRole('button'))
|
||||
await this.user.click(screen.getByRole('button'))
|
||||
|
||||
expect(toggleMock).toHaveBeenCalled()
|
||||
})
|
||||
|
@ -33,7 +33,7 @@ new class extends UnitTestCase {
|
|||
['Album', 'fetchForAlbum'],
|
||||
['Artist', 'fetchForArtist'],
|
||||
['Playlist', 'fetchForPlaylist']
|
||||
])('initiates playback for %s screen', async (screen, fetchMethod) => {
|
||||
])('initiates playback for %s screen', async (screenName, fetchMethod) => {
|
||||
commonStore.state.song_count = 10
|
||||
const songs = factory<Song>('song', 3)
|
||||
const fetchMock = this.mock(songStore, fetchMethod).mockResolvedValue(songs)
|
||||
|
@ -41,13 +41,13 @@ new class extends UnitTestCase {
|
|||
const goMock = this.mock(this.router, 'go')
|
||||
|
||||
await this.router.activateRoute({
|
||||
screen,
|
||||
screen: screenName,
|
||||
path: '_'
|
||||
}, { id: '42' })
|
||||
|
||||
const { getByRole } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByRole('button'))
|
||||
await this.user.click(screen.getByRole('button'))
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalledWith(42)
|
||||
expect(playMock).toHaveBeenCalledWith(songs)
|
||||
|
@ -58,7 +58,7 @@ new class extends UnitTestCase {
|
|||
it.each<[ScreenName, object, string]>([
|
||||
['Favorites', favoriteStore, 'fetch'],
|
||||
['RecentlyPlayed', recentlyPlayedStore, 'fetch']
|
||||
])('initiates playback for %s screen', async (screen, store, fetchMethod) => {
|
||||
])('initiates playback for %s screen', async (screenName, store, fetchMethod) => {
|
||||
commonStore.state.song_count = 10
|
||||
const songs = factory<Song>('song', 3)
|
||||
const fetchMock = this.mock(store, fetchMethod).mockResolvedValue(songs)
|
||||
|
@ -66,13 +66,13 @@ new class extends UnitTestCase {
|
|||
const goMock = this.mock(this.router, 'go')
|
||||
|
||||
await this.router.activateRoute({
|
||||
screen,
|
||||
screen: screenName,
|
||||
path: '_'
|
||||
})
|
||||
|
||||
const { getByRole } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByRole('button'))
|
||||
await this.user.click(screen.getByRole('button'))
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalled()
|
||||
expect(playMock).toHaveBeenCalledWith(songs)
|
||||
|
@ -80,7 +80,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
})
|
||||
|
||||
it.each<[ScreenName]>([['Queue'], ['Songs'], ['Albums']])('initiates playback %s screen', async (screen) => {
|
||||
it.each<[ScreenName]>([['Queue'], ['Songs'], ['Albums']])('initiates playback %s screen', async screenName => {
|
||||
commonStore.state.song_count = 10
|
||||
const songs = factory<Song>('song', 3)
|
||||
const fetchMock = this.mock(queueStore, 'fetchRandom').mockResolvedValue(songs)
|
||||
|
@ -88,13 +88,13 @@ new class extends UnitTestCase {
|
|||
const goMock = this.mock(this.router, 'go')
|
||||
|
||||
await this.router.activateRoute({
|
||||
screen,
|
||||
screen: screenName,
|
||||
path: '_'
|
||||
})
|
||||
|
||||
const { getByRole } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByRole('button'))
|
||||
await this.user.click(screen.getByRole('button'))
|
||||
await waitFor(() => {
|
||||
expect(fetchMock).toHaveBeenCalled()
|
||||
expect(playMock).toHaveBeenCalledWith(songs)
|
||||
|
@ -113,9 +113,9 @@ new class extends UnitTestCase {
|
|||
path: '_'
|
||||
})
|
||||
|
||||
const { getByRole } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByRole('button'))
|
||||
await this.user.click(screen.getByRole('button'))
|
||||
await waitFor(() => {
|
||||
expect(playMock).not.toHaveBeenCalled()
|
||||
expect(goMock).not.toHaveBeenCalled()
|
||||
|
|
|
@ -2,7 +2,7 @@ import { expect, it } from 'vitest'
|
|||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { eventBus } from '@/utils'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import LyricsPane from './LyricsPane.vue'
|
||||
import Magnifier from '@/components/ui/Magnifier.vue'
|
||||
|
||||
|
@ -25,29 +25,22 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
protected test () {
|
||||
it('renders', () => {
|
||||
expect(this.renderComponent().html()).toMatchSnapshot()
|
||||
})
|
||||
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 song = factory<Song>('song', { lyrics: null })
|
||||
|
||||
const mock = this.mock(eventBus, 'emit')
|
||||
const { getByTestId } = this.actingAsAdmin().renderComponent(song)
|
||||
this.actingAsAdmin().renderComponent(song)
|
||||
|
||||
await fireEvent.click(getByTestId('add-lyrics-btn'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Click here' }))
|
||||
|
||||
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().renderComponent(factory<Song>('song', {
|
||||
lyrics: null
|
||||
}))
|
||||
|
||||
expect(await queryByTestId('add-lyrics-btn')).toBeNull()
|
||||
this.actingAs().renderComponent(factory<Song>('song', { lyrics: null }))
|
||||
expect(screen.queryByRole('button', { name: 'Click here' })).toBeNull()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<p v-if="song.id && !song.lyrics" class="none text-secondary">
|
||||
<template v-if="isAdmin">
|
||||
No lyrics found.
|
||||
<button class="text-highlight" data-testid="add-lyrics-btn" type="button" @click.prevent="showEditSongForm">
|
||||
<button class="text-highlight" type="button" @click.prevent="showEditSongForm">
|
||||
Click here
|
||||
</button>
|
||||
to add lyrics.
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import Magnifier from './Magnifier.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('renders and functions', async () => {
|
||||
const { getByTitle, html, emitted } = this.render(Magnifier)
|
||||
const { html, emitted } = this.render(Magnifier)
|
||||
|
||||
await fireEvent.click(getByTitle('Zoom in'))
|
||||
expect(emitted()['in']).toBeTruthy()
|
||||
await this.user.click(screen.getByRole('button', { name: 'Zoom in' }))
|
||||
expect(emitted().in).toBeTruthy()
|
||||
|
||||
await fireEvent.click(getByTitle('Zoom out'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Zoom out' }))
|
||||
expect(emitted().out).toBeTruthy()
|
||||
|
||||
expect(html()).toMatchSnapshot()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { expect, it, vi } from 'vitest'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import MessageToast from './MessageToast.vue'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
private renderComponent () {
|
||||
|
@ -21,8 +21,8 @@ new class extends UnitTestCase {
|
|||
it('renders', () => expect(this.renderComponent().html()).toMatchSnapshot())
|
||||
|
||||
it('dismisses upon click', async () => {
|
||||
const { emitted, getByTitle } = this.renderComponent()
|
||||
await fireEvent.click(getByTitle('Click to dismiss'))
|
||||
const { emitted } = this.renderComponent()
|
||||
await this.user.click(screen.getByTitle('Click to dismiss'))
|
||||
|
||||
expect(emitted().dismiss).toBeTruthy()
|
||||
})
|
||||
|
|
|
@ -12,14 +12,14 @@ import MessageToast from '@/components/ui/MessageToast.vue'
|
|||
|
||||
const messages = ref<ToastMessage[]>([])
|
||||
|
||||
const addMessage = (type: 'info' | 'success' | 'warning' | 'danger', content: string, timeout?: number) => {
|
||||
const addMessage = (type: 'info' | 'success' | 'warning' | 'danger', content: string, timeout = 5) => {
|
||||
const id = `${Date.now().toString(36)}.${Math.random().toString(36)}`
|
||||
|
||||
messages.value.push({
|
||||
id,
|
||||
type,
|
||||
content,
|
||||
timeout: timeout || 5
|
||||
timeout
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import { preferenceStore } from '@/stores'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { playbackService } from '@/services'
|
||||
import RepeatModeSwitch from './RepeatModeSwitch.vue'
|
||||
|
||||
|
@ -10,9 +10,9 @@ new class extends UnitTestCase {
|
|||
it('changes mode', async () => {
|
||||
const mock = this.mock(playbackService, 'changeRepeatMode')
|
||||
preferenceStore.state.repeatMode = 'NO_REPEAT'
|
||||
const { getByRole } = this.render(RepeatModeSwitch)
|
||||
this.render(RepeatModeSwitch)
|
||||
|
||||
await fireEvent.click(getByRole('button'))
|
||||
await this.user.click(screen.getByRole('button'))
|
||||
|
||||
expect(mock).toHaveBeenCalledOnce()
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import isMobile from 'ismobilejs'
|
||||
import { expect, it } from 'vitest'
|
||||
import { fireEvent, getByRole } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import ScreenControlsToggle from './ScreenControlsToggle.vue'
|
||||
|
||||
|
@ -8,9 +8,9 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('renders and emits an event on mobile', async () => {
|
||||
isMobile.phone = true
|
||||
const { emitted, getByRole } = this.render(ScreenControlsToggle)
|
||||
const { emitted } = this.render(ScreenControlsToggle)
|
||||
|
||||
await fireEvent.click(getByRole('checkbox'))
|
||||
await this.user.click(screen.getByRole('checkbox'))
|
||||
|
||||
expect(emitted()['update:modelValue']).toBeTruthy()
|
||||
})
|
||||
|
|
|
@ -1,43 +1,43 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { eventBus } from '@/utils'
|
||||
import SearchForm from './SearchForm.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('sets focus into search box when requested', async () => {
|
||||
const { getByRole } = this.render(SearchForm)
|
||||
this.render(SearchForm)
|
||||
|
||||
eventBus.emit('FOCUS_SEARCH_FIELD')
|
||||
|
||||
expect(getByRole('searchbox')).toBe(document.activeElement)
|
||||
expect(screen.getByRole('searchbox')).toBe(document.activeElement)
|
||||
})
|
||||
|
||||
it('goes to search screen when search box is focused', async () => {
|
||||
const mock = this.mock(this.router, 'go')
|
||||
const { getByRole } = this.render(SearchForm)
|
||||
this.render(SearchForm)
|
||||
|
||||
await fireEvent.focus(getByRole('searchbox'))
|
||||
await this.user.click(screen.getByRole('searchbox'))
|
||||
|
||||
expect(mock).toHaveBeenCalledWith('search')
|
||||
})
|
||||
|
||||
it('emits an event when search query is changed', async () => {
|
||||
const mock = this.mock(eventBus, 'emit')
|
||||
const { getByRole } = this.render(SearchForm)
|
||||
this.render(SearchForm)
|
||||
|
||||
await fireEvent.update(getByRole('searchbox'), 'hey')
|
||||
await this.type(screen.getByRole('searchbox'), 'hey')
|
||||
|
||||
expect(mock).toHaveBeenCalledWith('SEARCH_KEYWORDS_CHANGED', 'hey')
|
||||
})
|
||||
|
||||
it('goes to the search screen if the form is submitted', async () => {
|
||||
const goMock = this.mock(this.router, 'go')
|
||||
const { getByRole } = this.render(SearchForm)
|
||||
this.render(SearchForm)
|
||||
|
||||
await fireEvent.update(getByRole('searchbox'), 'hey')
|
||||
await fireEvent.submit(getByRole('search'))
|
||||
await this.type(screen.getByRole('searchbox'), 'hey')
|
||||
await this.user.click(screen.getByRole('button', { name: 'Search' }))
|
||||
|
||||
expect(goMock).toHaveBeenCalledWith('search')
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { fireEvent, screen } from '@testing-library/vue'
|
||||
import { socketService, volumeManager } from '@/services'
|
||||
import { preferenceStore } from '@/stores'
|
||||
import Volume from './Volume.vue'
|
||||
|
@ -15,15 +15,15 @@ new class extends UnitTestCase {
|
|||
|
||||
protected test () {
|
||||
it('mutes and unmutes', async () => {
|
||||
const { getByTitle, html } = this.render(Volume)
|
||||
const { html } = this.render(Volume)
|
||||
expect(html()).toMatchSnapshot()
|
||||
expect(volumeManager.volume.value).toEqual(5)
|
||||
|
||||
await fireEvent.click(getByTitle('Mute'))
|
||||
await this.user.click(screen.getByTitle('Mute'))
|
||||
expect(html()).toMatchSnapshot()
|
||||
expect(volumeManager.volume.value).toEqual(0)
|
||||
|
||||
await fireEvent.click(getByTitle('Unmute'))
|
||||
await this.user.click(screen.getByTitle('Unmute'))
|
||||
expect(html()).toMatchSnapshot()
|
||||
expect(volumeManager.volume.value).toEqual(5)
|
||||
})
|
||||
|
@ -31,10 +31,10 @@ new class extends UnitTestCase {
|
|||
it('sets and broadcasts volume', async () => {
|
||||
const setMock = this.mock(volumeManager, 'set')
|
||||
const broadCastMock = this.mock(socketService, 'broadcast')
|
||||
const { getByRole } = this.render(Volume)
|
||||
this.render(Volume)
|
||||
|
||||
await fireEvent.update(getByRole('slider'), '4.2')
|
||||
await fireEvent.change(getByRole('slider'))
|
||||
await fireEvent.update(screen.getByRole('slider'), '4.2')
|
||||
await fireEvent.change(screen.getByRole('slider'))
|
||||
|
||||
expect(setMock).toHaveBeenCalledWith(4.2)
|
||||
expect(broadCastMock).toHaveBeenCalledWith('SOCKET_VOLUME_CHANGED', 4.2)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { youTubeService } from '@/services'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import YouTubeVideoItem from './YouTubeVideoItem.vue'
|
||||
|
@ -34,9 +34,9 @@ new class extends UnitTestCase {
|
|||
|
||||
it('plays', async () => {
|
||||
const mock = this.mock(youTubeService, 'play')
|
||||
const { getByRole } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByRole('button'))
|
||||
await this.user.click(screen.getByRole('button'))
|
||||
|
||||
expect(mock).toHaveBeenCalledWith(video)
|
||||
})
|
||||
|
|
|
@ -2,7 +2,7 @@ import { expect, it } from 'vitest'
|
|||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { youTubeService } from '@/services'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import Btn from '@/components/ui/Btn.vue'
|
||||
import YouTubeVideo from '@/components/ui/YouTubeVideoItem.vue'
|
||||
import YouTubeVideoList from './YouTubeVideoList.vue'
|
||||
|
@ -20,7 +20,7 @@ new class extends UnitTestCase {
|
|||
items: factory<YouTubeVideo>('video', 3)
|
||||
})
|
||||
|
||||
const { getAllByTestId, getByRole } = this.render(YouTubeVideoList, {
|
||||
this.render(YouTubeVideoList, {
|
||||
props: {
|
||||
song
|
||||
},
|
||||
|
@ -34,14 +34,14 @@ new class extends UnitTestCase {
|
|||
|
||||
await waitFor(() => {
|
||||
expect(searchMock).toHaveBeenNthCalledWith(1, song, '')
|
||||
expect(getAllByTestId('youtube-video')).toHaveLength(5)
|
||||
expect(screen.getAllByRole('listitem')).toHaveLength(5)
|
||||
})
|
||||
|
||||
await fireEvent.click(getByRole('button', { name: 'Load More' }))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Load More' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(searchMock).toHaveBeenNthCalledWith(2, song, 'foo')
|
||||
expect(getAllByTestId('youtube-video')).toHaveLength(8)
|
||||
expect(screen.getAllByRole('listitem')).toHaveLength(8)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import { UploadFile, uploadService, UploadStatus } from '@/services'
|
||||
import Btn from '@/components/ui/Btn.vue'
|
||||
import UploadItem from './UploadItem.vue'
|
||||
|
@ -33,11 +33,11 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('renders', () => expect(this.renderComponent('Canceled').html()).toMatchSnapshot())
|
||||
|
||||
it.each<[UploadStatus]>([['Canceled'], ['Errored']])('allows retrying when %s', async (status) => {
|
||||
it.each<[UploadStatus]>([['Canceled'], ['Errored']])('allows retrying when %s', async status => {
|
||||
const mock = this.mock(uploadService, 'retry')
|
||||
const { getByTitle } = this.renderComponent(status)
|
||||
this.renderComponent(status)
|
||||
|
||||
await fireEvent.click(getByTitle('Retry'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Retry' }))
|
||||
|
||||
expect(mock).toHaveBeenCalled()
|
||||
})
|
||||
|
@ -46,11 +46,11 @@ new class extends UnitTestCase {
|
|||
['Uploaded'],
|
||||
['Errored'],
|
||||
['Canceled']]
|
||||
)('allows removal if not uploading', async (status) => {
|
||||
)('allows removal if not uploading', async status => {
|
||||
const mock = this.mock(uploadService, 'remove')
|
||||
const { getByTitle } = this.renderComponent(status)
|
||||
this.renderComponent(status)
|
||||
|
||||
await fireEvent.click(getByTitle('Remove'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Remove' }))
|
||||
|
||||
expect(mock).toHaveBeenCalled()
|
||||
})
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { userStore } from '@/stores'
|
||||
import { MessageToasterStub } from '@/__tests__/stubs'
|
||||
import AddUserForm from './AddUserForm.vue'
|
||||
|
@ -11,13 +11,13 @@ new class extends UnitTestCase {
|
|||
const storeMock = this.mock(userStore, 'store')
|
||||
const alertMock = this.mock(MessageToasterStub.value, 'success')
|
||||
|
||||
const { getByLabelText, getByRole } = this.render(AddUserForm)
|
||||
this.render(AddUserForm)
|
||||
|
||||
await fireEvent.update(getByLabelText('Name'), 'John Doe')
|
||||
await fireEvent.update(getByLabelText('Email'), 'john@doe.com')
|
||||
await fireEvent.update(getByLabelText('Password'), 'secret-password')
|
||||
await fireEvent.click(getByRole('checkbox'))
|
||||
await fireEvent.click(getByRole('button', { name: 'Save' }))
|
||||
await this.type(screen.getByRole('textbox', { name: 'Name' }), 'John Doe')
|
||||
await this.type(screen.getByRole('textbox', { name: 'Email' }), 'john@doe.com')
|
||||
await this.type(screen.getByLabelText('Password'), 'secret-password')
|
||||
await this.user.click(screen.getByRole('checkbox'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Save' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(storeMock).toHaveBeenCalledWith({
|
||||
|
|
|
@ -3,7 +3,7 @@ import { expect, it } from 'vitest'
|
|||
import factory from '@/__tests__/factory'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { ModalContextKey } from '@/symbols'
|
||||
import { fireEvent, waitFor } from '@testing-library/vue'
|
||||
import { screen, waitFor } from '@testing-library/vue'
|
||||
import { userStore } from '@/stores'
|
||||
import { MessageToasterStub } from '@/__tests__/stubs'
|
||||
import EditUserForm from './EditUserForm.vue'
|
||||
|
@ -16,7 +16,7 @@ new class extends UnitTestCase {
|
|||
|
||||
const user = ref(factory<User>('user', { name: 'John Doe' }))
|
||||
|
||||
const { getByLabelText, getByRole } = this.render(EditUserForm, {
|
||||
this.render(EditUserForm, {
|
||||
global: {
|
||||
provide: {
|
||||
[<symbol>ModalContextKey]: [ref({ user })]
|
||||
|
@ -24,9 +24,9 @@ new class extends UnitTestCase {
|
|||
}
|
||||
})
|
||||
|
||||
await fireEvent.update(getByLabelText('Name'), 'Jane Doe')
|
||||
await fireEvent.update(getByLabelText('Password'), 'new-password-duck')
|
||||
await fireEvent.click(getByRole('button', { name: 'Update' }))
|
||||
await this.type(screen.getByRole('textbox', { name: 'Name' }), 'Jane Doe')
|
||||
await this.type(screen.getByLabelText('Password'), 'new-password-duck')
|
||||
await this.user.click(screen.getByRole('button', { name: 'Update' }))
|
||||
|
||||
await waitFor(() => {
|
||||
expect(updateMock).toHaveBeenCalledWith(user.value, {
|
||||
|
|
|
@ -2,7 +2,7 @@ import UnitTestCase from '@/__tests__/UnitTestCase'
|
|||
import factory from '@/__tests__/factory'
|
||||
import { expect, it } from 'vitest'
|
||||
import { eventBus } from '@/utils'
|
||||
import { fireEvent } from '@testing-library/vue'
|
||||
import { screen } from '@testing-library/vue'
|
||||
import UserBadge from './UserBadge.vue'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
|
@ -17,9 +17,9 @@ new class extends UnitTestCase {
|
|||
|
||||
it('logs out', async () => {
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
const { getByTestId } = this.renderComponent()
|
||||
this.renderComponent()
|
||||
|
||||
await fireEvent.click(getByTestId('btn-logout'))
|
||||
await this.user.click(screen.getByRole('button', { name: 'Log out' }))
|
||||
|
||||
expect(emitMock).toHaveBeenCalledWith('LOG_OUT')
|
||||
})
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue