mirror of
https://github.com/koel/koel
synced 2024-11-28 06:50:27 +00:00
feat(test): add ExtraPanel component tests
This commit is contained in:
parent
e51d8de337
commit
c85564bf0a
7 changed files with 93 additions and 134 deletions
|
@ -1,61 +0,0 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`components/layout/ExtraPanel does not have a YouTube tab if not using YouTube 1`] = `
|
||||
<section id="extra" data-testid="extra-panel" class="text-secondary showing">
|
||||
<div class="tabs">
|
||||
<div role="tablist" class="clear"><button aria-selected="true" aria-controls="extraPanelLyrics" id="extraTabLyrics" role="tab">
|
||||
Lyrics
|
||||
</button> <button aria-controls="extraPanelArtist" id="extraTabArtist" role="tab">
|
||||
Artist
|
||||
</button> <button aria-controls="extraPanelAlbum" id="extraTabAlbum" role="tab">
|
||||
Album
|
||||
</button>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="panes">
|
||||
<div aria-labelledby="extraTabLyrics" id="extraPanelLyrics" role="tabpanel" tabindex="0">
|
||||
<lyricspane-stub></lyricspane-stub>
|
||||
</div>
|
||||
<div aria-labelledby="extraTabArtist" id="extraPanelArtist" role="tabpanel" tabindex="0" style="display: none;">
|
||||
<!---->
|
||||
</div>
|
||||
<div aria-labelledby="extraTabAlbum" id="extraPanelAlbum" role="tabpanel" tabindex="0" style="display: none;">
|
||||
<!---->
|
||||
</div>
|
||||
<div aria-labelledby="extraTabYouTube" id="extraPanelYouTube" role="tabpanel" tabindex="0" style="display: none;">
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
`;
|
||||
|
||||
exports[`components/layout/ExtraPanel renders properly 1`] = `
|
||||
<section id="extra" data-testid="extra-panel" class="text-secondary showing">
|
||||
<div class="tabs">
|
||||
<div role="tablist" class="clear"><button aria-selected="true" aria-controls="extraPanelLyrics" id="extraTabLyrics" role="tab">
|
||||
Lyrics
|
||||
</button> <button aria-controls="extraPanelArtist" id="extraTabArtist" role="tab">
|
||||
Artist
|
||||
</button> <button aria-controls="extraPanelAlbum" id="extraTabAlbum" role="tab">
|
||||
Album
|
||||
</button>
|
||||
<!---->
|
||||
</div>
|
||||
<div class="panes">
|
||||
<div aria-labelledby="extraTabLyrics" id="extraPanelLyrics" role="tabpanel" tabindex="0">
|
||||
<lyrics-pane-stub></lyrics-pane-stub>
|
||||
</div>
|
||||
<div aria-labelledby="extraTabArtist" id="extraPanelArtist" role="tabpanel" tabindex="0" style="display: none;">
|
||||
<!---->
|
||||
</div>
|
||||
<div aria-labelledby="extraTabAlbum" id="extraPanelAlbum" role="tabpanel" tabindex="0" style="display: none;">
|
||||
<!---->
|
||||
</div>
|
||||
<div aria-labelledby="extraTabYouTube" id="extraPanelYouTube" role="tabpanel" tabindex="0" style="display: none;">
|
||||
<!---->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
`;
|
|
@ -1,54 +0,0 @@
|
|||
import Component from '@/components/layout/main-wrapper/ExtraPanel.vue'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { eventBus } from '@/utils'
|
||||
import { songInfo } from '@/services'
|
||||
import { mock } from '@/__tests__/__helpers__'
|
||||
import { shallow, Wrapper } from '@/__tests__/adapter'
|
||||
|
||||
const shallowComponent = (data: Record<string, any> = {}): Wrapper => shallow(Component, {
|
||||
stubs: ['lyrics-pane', 'artist-info', 'album-info', 'you-tube-video-list'],
|
||||
data: () => data
|
||||
})
|
||||
|
||||
describe('components/layout/ExtraPanel', () => {
|
||||
afterEach(() => {
|
||||
jest.resetModules()
|
||||
jest.clearAllMocks()
|
||||
})
|
||||
|
||||
it('renders properly', () => {
|
||||
expect(shallowComponent()).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('does not have a YouTube tab if not using YouTube', async () => {
|
||||
const wrapper = shallowComponent({
|
||||
sharedState: {
|
||||
useYouTube: false
|
||||
}
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
expect(shallow(Component)).toMatchSnapshot()
|
||||
})
|
||||
|
||||
it('has a YouTube tab if using YouTube', async () => {
|
||||
const wrapper = shallowComponent({
|
||||
sharedState: {
|
||||
useYouTube: true
|
||||
}
|
||||
})
|
||||
await wrapper.vm.$nextTick()
|
||||
expect(wrapper.has('#extraTabYouTube')).toBe(true)
|
||||
})
|
||||
|
||||
it.each<[string]>([['#extraTabLyrics'], ['#extraTabAlbum'], ['#extraTabArtist']])('switches to "%s" tab', selector => {
|
||||
expect(shallowComponent().click(selector).find('[aria-selected=true]').is(selector)).toBe(true)
|
||||
})
|
||||
|
||||
it('fetch song info when a new song is played', () => {
|
||||
shallowComponent()
|
||||
const song = factory('song')
|
||||
const m = mock(songInfo, 'fetch', song)
|
||||
eventBus.emit('SONG_STARTED', song)
|
||||
expect(m).toHaveBeenCalledWith(song)
|
||||
})
|
||||
})
|
|
@ -2,7 +2,7 @@ import Component from '@/components/song/SongEditForm.vue'
|
|||
import Typeahead from '@/components/ui/typeahead.vue'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { songStore } from '@/stores'
|
||||
import { songInfo } from '@/services/info'
|
||||
import { songInfoService } from '@/services/info'
|
||||
import { mock } from '@/__tests__/__helpers__'
|
||||
import { mount } from '@/__tests__/adapter'
|
||||
|
||||
|
@ -37,7 +37,7 @@ describe('components/song/edit-form', () => {
|
|||
|
||||
it('fetches song information on demand', () => {
|
||||
const song = factory('song', { infoRetrieved: false })
|
||||
const fetchMock = mock(songInfo, 'fetch')
|
||||
const fetchMock = mock(songInfoService, 'fetch')
|
||||
mount(Component, {
|
||||
propsData: { songs: song }
|
||||
})
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
import { beforeEach, expect, it } from 'vitest'
|
||||
import { cleanup, fireEvent } from '@testing-library/vue'
|
||||
import { mockHelper, render } from '@/__tests__/__helpers__'
|
||||
import ExtraPanel from './ExtraPanel.vue'
|
||||
import LyricsPane from '@/__tests__/Stub.vue'
|
||||
import AlbumInfo from '@/__tests__/Stub.vue'
|
||||
import ArtistInfo from '@/__tests__/Stub.vue'
|
||||
import YouTubeVideoList from '@/__tests__/Stub.vue'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { commonStore } from '@/stores'
|
||||
import { songInfoService } from '@/services'
|
||||
import { eventBus } from '@/utils'
|
||||
|
||||
const renderComponent = () => {
|
||||
return render(ExtraPanel, {
|
||||
props: {
|
||||
song: factory<Song>('song')
|
||||
},
|
||||
global: {
|
||||
stubs: {
|
||||
LyricsPane,
|
||||
AlbumInfo,
|
||||
ArtistInfo,
|
||||
YouTubeVideoList
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
cleanup()
|
||||
mockHelper.restoreAllMocks()
|
||||
})
|
||||
|
||||
it('has a YouTube tab if using YouTube ', () => {
|
||||
commonStore.state.useYouTube = true
|
||||
const { getByTestId } = renderComponent()
|
||||
|
||||
getByTestId('extra-tab-youtube')
|
||||
})
|
||||
|
||||
it('does not have a YouTube tab if not using YouTube', async () => {
|
||||
commonStore.state.useYouTube = false
|
||||
const { queryByTestId } = renderComponent()
|
||||
|
||||
expect(await queryByTestId('extra-tab-youtube')).toBe(null)
|
||||
})
|
||||
|
||||
it.each([['extra-tab-lyrics'], ['extra-tab-album'], ['extra-tab-artist']])('switches to "%s" tab', async (testId) => {
|
||||
const { getByTestId, container } = renderComponent()
|
||||
|
||||
await fireEvent.click(getByTestId(testId))
|
||||
|
||||
expect(container.querySelector('[aria-selected=true]')).toBe(getByTestId(testId))
|
||||
})
|
||||
|
||||
it('fetches song info when a new song is played', () => {
|
||||
renderComponent()
|
||||
const song = factory<Song>('song')
|
||||
const mock = mockHelper.mock(songInfoService, 'fetch', song)
|
||||
|
||||
eventBus.emit('SONG_STARTED', song)
|
||||
|
||||
expect(mock).toHaveBeenCalledWith(song)
|
||||
})
|
|
@ -6,6 +6,7 @@
|
|||
id="extraTabLyrics"
|
||||
:aria-selected="currentTab === 'Lyrics'"
|
||||
aria-controls="extraPanelLyrics"
|
||||
data-testid="extra-tab-lyrics"
|
||||
role="tab"
|
||||
@click.prevent="currentTab = 'Lyrics'"
|
||||
>
|
||||
|
@ -15,6 +16,7 @@
|
|||
id="extraTabArtist"
|
||||
:aria-selected="currentTab === 'Artist'"
|
||||
aria-controls="extraPanelArtist"
|
||||
data-testid="extra-tab-artist"
|
||||
role="tab"
|
||||
@click.prevent="currentTab = 'Artist'"
|
||||
>
|
||||
|
@ -24,6 +26,7 @@
|
|||
id="extraTabAlbum"
|
||||
:aria-selected="currentTab === 'Album'"
|
||||
aria-controls="extraPanelAlbum"
|
||||
data-testid="extra-tab-album"
|
||||
role="tab"
|
||||
@click.prevent="currentTab = 'Album'"
|
||||
>
|
||||
|
@ -34,6 +37,7 @@
|
|||
id="extraTabYouTube"
|
||||
:aria-selected="currentTab === 'YouTube'"
|
||||
aria-controls="extraPanelYouTube"
|
||||
data-testid="extra-tab-youtube"
|
||||
role="tab"
|
||||
title="YouTube"
|
||||
@click.prevent="currentTab = 'YouTube'"
|
||||
|
@ -92,7 +96,7 @@ import isMobile from 'ismobilejs'
|
|||
import { computed, defineAsyncComponent, ref, toRef, watch } from 'vue'
|
||||
import { $, eventBus } from '@/utils'
|
||||
import { preferenceStore as preferences } from '@/stores'
|
||||
import { songInfo } from '@/services'
|
||||
import { songInfoService } from '@/services'
|
||||
import { useThirdPartyServices } from '@/composables'
|
||||
|
||||
type Tab = 'Lyrics' | 'Artist' | 'Album' | 'YouTube'
|
||||
|
@ -122,7 +126,7 @@ watch(showing, (showingExtraPanel) => {
|
|||
|
||||
const fetchSongInfo = async (_song: Song) => {
|
||||
try {
|
||||
song.value = await songInfo.fetch(_song)
|
||||
song.value = await songInfoService.fetch(_song)
|
||||
} catch (err) {
|
||||
song.value = _song
|
||||
throw err
|
||||
|
|
|
@ -14,22 +14,22 @@
|
|||
<div class="tabs">
|
||||
<div class="clear" role="tablist">
|
||||
<button
|
||||
:aria-selected="currentView === 'details'"
|
||||
@click.prevent="currentView = 'details'"
|
||||
aria-controls="editSongPanelDetails"
|
||||
id="editSongTabDetails"
|
||||
:aria-selected="currentView === 'details'"
|
||||
aria-controls="editSongPanelDetails"
|
||||
role="tab"
|
||||
@click.prevent="currentView = 'details'"
|
||||
>
|
||||
Details
|
||||
</button>
|
||||
<button
|
||||
@click.prevent="currentView = 'lyrics'"
|
||||
v-if="editingOnlyOneSong"
|
||||
id="editSongTabLyrics"
|
||||
:aria-selected="currentView === 'lyrics'"
|
||||
aria-controls="editSongPanelLyrics"
|
||||
id="editSongTabLyrics"
|
||||
role="tab"
|
||||
data-testid="edit-song-lyrics-tab"
|
||||
role="tab"
|
||||
@click.prevent="currentView = 'lyrics'"
|
||||
>
|
||||
Lyrics
|
||||
</button>
|
||||
|
@ -43,7 +43,7 @@
|
|||
role="tabpanel"
|
||||
tabindex="0"
|
||||
>
|
||||
<div class="form-row" v-if="editingOnlyOneSong">
|
||||
<div v-if="editingOnlyOneSong" class="form-row">
|
||||
<label>Title</label>
|
||||
<input v-model="formData.title" v-koel-focus name="title" title="Title" type="text">
|
||||
</div>
|
||||
|
@ -122,7 +122,7 @@ import { computed, defineAsyncComponent, nextTick, reactive, ref, toRef, toRefs
|
|||
import { isEqual, union } from 'lodash'
|
||||
|
||||
import { alerts, arrayify, br2nl, defaultCover, pluralize } from '@/utils'
|
||||
import { songInfo } from '@/services/info'
|
||||
import { songInfoService } from '@/services/info'
|
||||
import { albumStore, artistStore, songStore } from '@/stores'
|
||||
|
||||
interface EditFormData {
|
||||
|
@ -235,7 +235,7 @@ const open = async () => {
|
|||
loading.value = true
|
||||
|
||||
try {
|
||||
await songInfo.fetch(firstSong)
|
||||
await songInfoService.fetch(firstSong)
|
||||
formData.lyrics = br2nl(firstSong.lyrics)
|
||||
formData.track = firstSong.track || null
|
||||
} catch (e) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { httpService, albumInfoService, artistInfoService } from '..'
|
||||
import { albumInfoService, artistInfoService, httpService } from '..'
|
||||
|
||||
interface SongInfoResponse {
|
||||
artist_info: ArtistInfo,
|
||||
|
@ -10,14 +10,19 @@ interface SongInfoResponse {
|
|||
lyrics: string
|
||||
}
|
||||
|
||||
export const songInfo = {
|
||||
fetch: async (song: Song): Promise<Song> => {
|
||||
export const songInfoService = {
|
||||
fetch: async (song: Song) => {
|
||||
if (!song.infoRetrieved) {
|
||||
const { lyrics, artist_info, album_info, youtube } = await httpService.get<SongInfoResponse>(`song/${song.id}/info`)
|
||||
const {
|
||||
lyrics,
|
||||
artist_info: artistInfo,
|
||||
album_info: albumInfo,
|
||||
youtube
|
||||
} = await httpService.get<SongInfoResponse>(`song/${song.id}/info`)
|
||||
|
||||
song.lyrics = lyrics
|
||||
artist_info && artistInfoService.merge(song.artist, artist_info)
|
||||
album_info && albumInfoService.merge(song.album, album_info)
|
||||
artistInfo && artistInfoService.merge(song.artist, artistInfo)
|
||||
albumInfo && albumInfoService.merge(song.album, albumInfo)
|
||||
song.youtube = youtube
|
||||
song.infoRetrieved = true
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue