fix(test): MainWrapper tests

This commit is contained in:
Phan An 2022-07-10 17:17:48 +02:00
parent 3b0d5217d8
commit 31094fe283
No known key found for this signature in database
GPG key ID: A81E4477F0BB6FDC
9 changed files with 66 additions and 88 deletions

View file

@ -1,6 +1,6 @@
import isMobile from 'ismobilejs'
import { expect, it } from 'vitest'
import { fireEvent, queryAllByTestId } from '@testing-library/vue'
import { fireEvent, queryAllByTestId, waitFor } from '@testing-library/vue'
import { eventBus } from '@/utils'
import factory from '@/__tests__/factory'
import compareVersions from 'compare-versions'
@ -34,9 +34,7 @@ new class extends UnitTestCase {
expect(await queryByRole('search')).toBeNull()
await fireEvent.click(getByTitle('Show or hide the search form'))
await this.tick()
getByRole('search')
await waitFor(() => getByRole('search'))
})
it.each([[true, true, true], [false, true, false], [true, false, false], [false, false, false]])(
@ -46,7 +44,7 @@ new class extends UnitTestCase {
const { queryAllByTestId } = this.actingAs(factory<User>('user', { is_admin: isAdmin })).render(AppHeader)
expect(await queryAllByTestId('new-version')).toHaveLength(announcing ? 1 : 0)
expect(queryAllByTestId('new-version')).toHaveLength(announcing ? 1 : 0)
}
)
}

View file

@ -1,5 +1,4 @@
import factory from '@/__tests__/factory'
import { httpService } from '@/services'
import { eventBus } from '@/utils'
import { it } from 'vitest'
import { EventName } from '@/config'
@ -8,7 +7,7 @@ import ModalWrapper from './ModalWrapper.vue'
new class extends UnitTestCase {
protected test () {
it.each<[string, EventName, User | Song | any]>([
it.each<[string, EventName, User | Song | Playlist | any]>([
['add-user-form', 'MODAL_SHOW_ADD_USER_FORM', undefined],
['edit-user-form', 'MODAL_SHOW_EDIT_USER_FORM', factory('user')],
['edit-song-form', 'MODAL_SHOW_EDIT_SONG_FORM', [factory('song')]],
@ -16,23 +15,7 @@ new class extends UnitTestCase {
['edit-smart-playlist-form', 'MODAL_SHOW_EDIT_SMART_PLAYLIST_FORM', factory('playlist')],
['about-koel', 'MODAL_SHOW_ABOUT_KOEL', undefined]
])('shows %s modal', async (modalName: string, eventName: EventName, eventParams?: any) => {
if (modalName === 'edit-song-form') {
// mocking the songInfoService.fetch() request made during edit-form modal opening
this.mock(httpService, 'request').mockReturnValue(Promise.resolve({ data: {} }))
}
const { findByTestId } = this.render(ModalWrapper, {
global: {
stubs: {
CreateSmartPlaylistForm: this.stub('create-smart-playlist-form'),
EditSmartPlaylistForm: this.stub('edit-smart-playlist-form'),
AddUserForm: this.stub('add-user-form'),
EditUserForm: this.stub('edit-user-form'),
EditSongForm: this.stub('edit-song-form'),
AboutKoel: this.stub('about-koel')
}
}
})
const { findByTestId } = this.render(ModalWrapper)
eventBus.emit(eventName, eventParams)

View file

@ -1,33 +1,18 @@
<template>
<div class="modal-wrapper" :class="{ overlay: showingModalName }">
<CreateSmartPlaylistForm v-if="showingModalName === 'create-smart-playlist-form'" @close="close"/>
<EditSmartPlaylistForm
v-if="showingModalName === 'edit-smart-playlist-form'"
:playlist="boundData.playlist"
@close="close"
/>
<EditSmartPlaylistForm v-if="showingModalName === 'edit-smart-playlist-form'" @close="close"/>
<AddUserForm v-if="showingModalName === 'add-user-form'" @close="close"/>
<EditUserForm v-if="showingModalName === 'edit-user-form'" :user="boundData.user" @close="close"/>
<EditSongForm
v-if="showingModalName === 'edit-song-form'"
:initialTab="boundData.initialTab"
:songs="boundData.songs"
@close="close"
/>
<EditUserForm v-if="showingModalName === 'edit-user-form'" @close="close"/>
<EditSongForm v-if="showingModalName === 'edit-song-form'" @close="close"/>
<AboutKoel v-if="showingModalName === 'about-koel'" @close="close"/>
</div>
</template>
<script lang="ts" setup>
import { defineAsyncComponent, ref } from 'vue'
import { eventBus, arrayify } from '@/utils'
interface ModalWrapperBoundData {
playlist?: Playlist
user?: User
songs?: Song[]
initialTab?: string
}
import { defineAsyncComponent, provide, ref } from 'vue'
import { arrayify, eventBus } from '@/utils'
import { EditSongFormInitialTabKey, PlaylistKey, SongsKey, UserKey } from '@/symbols'
declare type ModalName =
| 'create-smart-playlist-form'
@ -45,31 +30,37 @@ const EditSongForm = defineAsyncComponent(() => import('@/components/song/SongEd
const AboutKoel = defineAsyncComponent(() => import('@/components/meta/AboutKoelModal.vue'))
const showingModalName = ref<ModalName | null>(null)
const boundData = ref<ModalWrapperBoundData>({})
const close = () => {
showingModalName.value = null
boundData.value = {}
}
const close = () => (showingModalName.value = null)
const playlistToEdit = ref<Playlist>()
const userToEdit = ref<User>()
const songsToEdit = ref<Song[]>()
const editSongFormInitialTab = ref<EditSongFormTabName>('details')
provide(PlaylistKey, playlistToEdit)
provide(UserKey, userToEdit)
provide(SongsKey, songsToEdit)
provide(EditSongFormInitialTabKey, editSongFormInitialTab)
eventBus.on({
'MODAL_SHOW_ABOUT_KOEL': () => (showingModalName.value = 'about-koel'),
'MODAL_SHOW_ADD_USER_FORM': () => (showingModalName.value = 'add-user-form'),
'MODAL_SHOW_CREATE_SMART_PLAYLIST_FORM': () => (showingModalName.value = 'create-smart-playlist-form'),
MODAL_SHOW_EDIT_SMART_PLAYLIST_FORM (playlist: Playlist) {
boundData.value.playlist = playlist
'MODAL_SHOW_EDIT_SMART_PLAYLIST_FORM': (playlist: Playlist) => {
playlistToEdit.value = playlist
showingModalName.value = 'edit-smart-playlist-form'
},
MODAL_SHOW_EDIT_USER_FORM (user: User) {
boundData.value.user = user
'MODAL_SHOW_EDIT_USER_FORM': (user: User) => {
userToEdit.value = user
showingModalName.value = 'edit-user-form'
},
MODAL_SHOW_EDIT_SONG_FORM (songs: Song | Song[], initialTab = 'details') {
boundData.value.songs = arrayify(songs)
boundData.value.initialTab = initialTab
'MODAL_SHOW_EDIT_SONG_FORM': (songs: Song | Song[], initialTab: EditSongFormTabName = 'details') => {
songsToEdit.value = arrayify(songs)
editSongFormInitialTab.value = initialTab
showingModalName.value = 'edit-song-form'
}
})

View file

@ -25,16 +25,12 @@ new class extends UnitTestCase {
protected test () {
it('has a YouTube tab if using YouTube ', () => {
commonStore.state.use_you_tube = true
const { getByTestId } = this.renderComponent()
getByTestId('extra-tab-youtube')
this.renderComponent().getByTestId('extra-tab-youtube')
})
it('does not have a YouTube tab if not using YouTube', async () => {
it('does not have a YouTube tab if not using YouTube', () => {
commonStore.state.use_you_tube = false
const { queryByTestId } = this.renderComponent()
expect(await queryByTestId('extra-tab-youtube')).toBeNull()
expect(this.renderComponent().queryByTestId('extra-tab-youtube')).toBeNull()
})
it.each([['extra-tab-lyrics'], ['extra-tab-album'], ['extra-tab-artist']])('switches to "%s" tab', async (id) => {

View file

@ -37,16 +37,17 @@
</template>
<script lang="ts" setup>
import { computed, reactive, toRefs } from 'vue'
import { computed, inject, reactive, ref, watch } from 'vue'
import { cloneDeep, isEqual } from 'lodash'
import { playlistStore } from '@/stores'
import { alerts, eventBus } from '@/utils'
import { useSmartPlaylistForm } from '@/components/playlist/smart-playlist/useSmartPlaylistForm'
import { PlaylistKey } from '@/symbols'
const props = defineProps<{ playlist: Playlist }>()
const { playlist } = toRefs(props)
const playlist = inject(PlaylistKey, ref<Playlist>())
let mutatedPlaylist: Playlist
const mutatedPlaylist = reactive<Playlist>(cloneDeep(playlist.value))
watch(playlist, () => (mutatedPlaylist = reactive(cloneDeep(playlist.value))), { immediate: true })
const isPristine = computed(() => {
return isEqual(mutatedPlaylist.rules, playlist.value.rules) && mutatedPlaylist.name.trim() === playlist.value.name

View file

@ -132,23 +132,21 @@
</template>
<script lang="ts" setup>
import { computed, reactive, ref, toRefs } from 'vue'
import { computed, inject, onMounted, reactive, ref } from 'vue'
import { isEqual } from 'lodash'
import { alerts, arrayify, defaultCover, pluralize } from '@/utils'
import { alerts, defaultCover, pluralize } from '@/utils'
import { songStore } from '@/stores'
import Btn from '@/components/ui/Btn.vue'
import SoundBar from '@/components/ui/SoundBar.vue'
import { EditSongFormInitialTabKey, SongsKey } from '@/symbols'
type EditFormData = Pick<Song, 'title' | 'album_name' | 'artist_name' | 'album_artist_name' | 'lyrics' | 'track' | 'disc'>
type TabName = 'details' | 'lyrics'
const props = withDefaults(defineProps<{ songs: Song[], initialTab: TabName }>(), { initialTab: 'details' })
const { songs, initialTab } = toRefs(props)
const mutatedSongs = ref<Song[]>([])
const currentView = ref<TabName>()
const initialTab = inject(EditSongFormInitialTabKey, ref<EditSongFormTabName>('details'))
const songs = inject(SongsKey, ref<Song[]>([]))
const mutatedSongs = computed(() => songs.value)
const currentView = ref<EditSongFormTabName>('details')
const loading = ref(false)
/**
@ -197,7 +195,6 @@ const displayedAlbumName = computed(() => {
const isPristine = computed(() => isEqual(formData, initialFormData))
const open = async () => {
mutatedSongs.value = arrayify(songs.value)
currentView.value = initialTab.value
const firstSong = mutatedSongs.value[0]
@ -244,7 +241,7 @@ const submit = async () => {
}
}
open()
onMounted(async () => await open())
</script>
<style lang="scss" scoped>

View file

@ -44,24 +44,29 @@
<script lang="ts" setup>
import { isEqual } from 'lodash'
import { reactive, ref, toRefs } from 'vue'
import { inject, reactive, ref, watch } from 'vue'
import { alerts, parseValidationError } from '@/utils'
import { UpdateUserData, userStore } from '@/stores'
import Btn from '@/components/ui/Btn.vue'
import SoundBar from '@/components/ui/SoundBar.vue'
import TooltipIcon from '@/components/ui/TooltipIcon.vue'
import { UserKey } from '@/symbols'
const props = defineProps<{ user: User }>()
const { user } = toRefs(props)
const user = inject(UserKey, ref<User>())
const originalData: UpdateUserData = {
name: user.value.name,
email: user.value.email,
is_admin: user.value.is_admin
}
let originalData: UpdateUserData
let updateData: UpdateUserData
const updateData = reactive<UpdateUserData>(Object.assign({}, originalData))
watch(user, () => {
originalData = {
name: user.value.name,
email: user.value.email,
is_admin: user.value.is_admin
}
updateData = reactive(Object.assign({}, originalData))
}, { immediate: true })
const loading = ref(false)

View file

@ -6,3 +6,8 @@ export const SelectedSongsKey: InjectionKey<Ref<Song[]>> = Symbol('SelectedSongs
export const SongListConfigKey: InjectionKey<Partial<SongListConfig>> = Symbol('SongListConfig')
export const SongListSortFieldKey: InjectionKey<Ref<SongListSortField>> = Symbol('SongListSortField')
export const SongListSortOrderKey: InjectionKey<Ref<SortOrder>> = Symbol('SongListSortOrder')
export const EditSongFormInitialTabKey: InjectionKey<Ref<EditSongFormTabName>> = Symbol('EditSongFormInitialTab')
export const PlaylistKey: InjectionKey<Ref<Playlist>> = Symbol('Playlist')
export const UserKey: InjectionKey<Ref<User>> = Symbol('User')

View file

@ -402,3 +402,5 @@ interface PaginatorResource {
current_page: number
}
}
type EditSongFormTabName = 'details' | 'lyrics'