From c85564bf0a0950e9e12f8d24860d69a44bbf6621 Mon Sep 17 00:00:00 2001 From: Phan An Date: Fri, 6 May 2022 12:28:02 +0200 Subject: [PATCH] feat(test): add ExtraPanel component tests --- .../__snapshots__/extra-panel.spec.ts.snap | 61 ----------------- .../layout/main-wrapper/extra-panel.spec.ts | 54 --------------- .../components/song/edit-form.spec.ts | 4 +- .../layout/main-wrapper/ExtraPanel.spec.ts | 65 +++++++++++++++++++ .../layout/main-wrapper/ExtraPanel.vue | 8 ++- .../js/components/song/SongEditForm.vue | 18 ++--- .../js/services/info/songInfoService.ts | 17 +++-- 7 files changed, 93 insertions(+), 134 deletions(-) delete mode 100644 resources/assets/js/__tests__/components/layout/main-wrapper/__snapshots__/extra-panel.spec.ts.snap delete mode 100644 resources/assets/js/__tests__/components/layout/main-wrapper/extra-panel.spec.ts create mode 100644 resources/assets/js/components/layout/main-wrapper/ExtraPanel.spec.ts diff --git a/resources/assets/js/__tests__/components/layout/main-wrapper/__snapshots__/extra-panel.spec.ts.snap b/resources/assets/js/__tests__/components/layout/main-wrapper/__snapshots__/extra-panel.spec.ts.snap deleted file mode 100644 index 8d080f63..00000000 --- a/resources/assets/js/__tests__/components/layout/main-wrapper/__snapshots__/extra-panel.spec.ts.snap +++ /dev/null @@ -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`] = ` -
-
-
- -
-
-
- -
- - - -
-
-
-`; - -exports[`components/layout/ExtraPanel renders properly 1`] = ` -
-
-
- -
-
-
- -
- - - -
-
-
-`; diff --git a/resources/assets/js/__tests__/components/layout/main-wrapper/extra-panel.spec.ts b/resources/assets/js/__tests__/components/layout/main-wrapper/extra-panel.spec.ts deleted file mode 100644 index 8b300eda..00000000 --- a/resources/assets/js/__tests__/components/layout/main-wrapper/extra-panel.spec.ts +++ /dev/null @@ -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 = {}): 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) - }) -}) diff --git a/resources/assets/js/__tests__/components/song/edit-form.spec.ts b/resources/assets/js/__tests__/components/song/edit-form.spec.ts index 2d5eb7ef..01f475c3 100644 --- a/resources/assets/js/__tests__/components/song/edit-form.spec.ts +++ b/resources/assets/js/__tests__/components/song/edit-form.spec.ts @@ -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 } }) diff --git a/resources/assets/js/components/layout/main-wrapper/ExtraPanel.spec.ts b/resources/assets/js/components/layout/main-wrapper/ExtraPanel.spec.ts new file mode 100644 index 00000000..0ffcedd7 --- /dev/null +++ b/resources/assets/js/components/layout/main-wrapper/ExtraPanel.spec.ts @@ -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') + }, + 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') + const mock = mockHelper.mock(songInfoService, 'fetch', song) + + eventBus.emit('SONG_STARTED', song) + + expect(mock).toHaveBeenCalledWith(song) +}) diff --git a/resources/assets/js/components/layout/main-wrapper/ExtraPanel.vue b/resources/assets/js/components/layout/main-wrapper/ExtraPanel.vue index b2734a09..71b94862 100644 --- a/resources/assets/js/components/layout/main-wrapper/ExtraPanel.vue +++ b/resources/assets/js/components/layout/main-wrapper/ExtraPanel.vue @@ -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 diff --git a/resources/assets/js/components/song/SongEditForm.vue b/resources/assets/js/components/song/SongEditForm.vue index 845c2f0b..9ade410a 100644 --- a/resources/assets/js/components/song/SongEditForm.vue +++ b/resources/assets/js/components/song/SongEditForm.vue @@ -14,22 +14,22 @@
@@ -43,7 +43,7 @@ role="tabpanel" tabindex="0" > -
+
@@ -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) { diff --git a/resources/assets/js/services/info/songInfoService.ts b/resources/assets/js/services/info/songInfoService.ts index 874d2515..8181f980 100644 --- a/resources/assets/js/services/info/songInfoService.ts +++ b/resources/assets/js/services/info/songInfoService.ts @@ -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 => { +export const songInfoService = { + fetch: async (song: Song) => { if (!song.infoRetrieved) { - const { lyrics, artist_info, album_info, youtube } = await httpService.get(`song/${song.id}/info`) + const { + lyrics, + artist_info: artistInfo, + album_info: albumInfo, + youtube + } = await httpService.get(`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 }