feat(test): song list sorter tests

This commit is contained in:
Phan An 2024-06-03 19:42:21 +08:00
parent e33a29d583
commit 1cb1125183
6 changed files with 66 additions and 15 deletions

View file

@ -185,7 +185,7 @@ watch(playlistId, async id => {
if (playlist.value) {
await fetchDetails()
listConfig.collaborative = playlist.value.is_collaborative
listConfig.hasCustomSort = !playlist.value.is_smart
listConfig.hasCustomOrderSort = !playlist.value.is_smart
controlsConfig.deletePlaylist = playlist.value.user_id === currentUser.value?.id
} else {
await triggerNotFound()

View file

@ -75,7 +75,7 @@
<SongListSorter
v-if="config.sortable"
:field="sortField"
:has-custom-sort="config.hasCustomSort"
:has-custom-order-sort="config.hasCustomOrderSort"
:order="sortOrder"
:content-type="contentType"
@sort="sort"

View file

@ -0,0 +1,51 @@
import { screen } from '@testing-library/vue'
import { expect, it } from 'vitest'
import UnitTestCase from '@/__tests__/UnitTestCase'
import Component from './SongListSorter.vue'
new class extends UnitTestCase {
protected test () {
it('contains proper items for song-only lists', () => {
this.render(Component)
;['Title', 'Album', 'Artist', 'Track & Disc', 'Time', 'Date Added'].forEach(text => screen.getByText(text))
;['Podcast', 'Album or Podcast', 'Author', 'Artist or Author'].forEach(
text => expect(screen.queryByText(text)).toBeNull()
)
})
it('contains proper items for episode-only lists', () => {
this.render(Component, {
props: {
contentType: 'episodes'
}
})
;['Title', 'Podcast', 'Author', 'Time', 'Date Added'].forEach(text => screen.getByText(text))
;['Album', 'Album or Podcast', 'Artist', 'Artist or Author'].forEach(
text => expect(screen.queryByText(text)).toBeNull()
)
})
it('contains proper items for mixed-content lists', () => {
this.render(Component, {
props: {
contentType: 'mixed'
}
})
;['Title', 'Album or Podcast', 'Artist or Author', 'Date Added'].forEach(text => screen.getByText(text))
;['Album', 'Artist', 'Podcast', 'Author'].forEach(text => expect(screen.queryByText(text)).toBeNull())
})
it('has custom order sort if so configured', () => {
this.render(Component, {
props: {
hasCustomOrderSort: true
}
})
screen.getByText('Custom Order')
})
}
}

View file

@ -8,7 +8,7 @@
<li
v-for="item in menuItems"
:key="item.label"
:class="isCurrentField(item.field) && 'active'"
:class="currentlySortedBy(item.field) && 'active'"
class="cursor-pointer flex justify-between"
@click="sort(item.field)"
>
@ -30,28 +30,28 @@ import { faArrowDown, faArrowUp, faCheck, faSort } from '@fortawesome/free-solid
import { OnClickOutside } from '@vueuse/components'
import { computed, onBeforeUnmount, onMounted, ref, toRefs } from 'vue'
import { useFloatingUi } from '@/composables'
import { arrayify } from '@/utils'
import { arrayify, getPlayableCollectionContentType } from '@/utils'
const props = withDefaults(defineProps<{
field?: MaybeArray<PlayableListSortField>
field?: MaybeArray<PlayableListSortField> // the current field(s) being sorted by
order?: SortOrder
hasCustomSort?: boolean
contentType?: 'songs' | 'episodes' | 'mixed'
hasCustomOrderSort?: boolean // whether to provide "custom order" sort (like for playlists)
contentType?: ReturnType<typeof getPlayableCollectionContentType>
}>(), {
field: 'title',
order: 'asc',
hasCustomSort: false,
hasCustomOrderSort: false,
contentType: 'songs'
})
const { field, order, hasCustomSort, contentType } = toRefs(props)
const { field, order, hasCustomOrderSort, contentType } = toRefs(props)
const emit = defineEmits<{ (e: 'sort', field: MaybeArray<PlayableListSortField>): void }>()
const button = ref<HTMLButtonElement>()
const menu = ref<HTMLDivElement>()
const menuItems = computed<{ label: string, field: MaybeArray<PlayableListSortField> }[]>(() => {
const menuItems = computed(() => {
type MenuItems = { label: string, field: MaybeArray<PlayableListSortField> }
const title: MenuItems = { label: 'Title', field: 'title' }
@ -69,12 +69,12 @@ const menuItems = computed<{ label: string, field: MaybeArray<PlayableListSortFi
let items: MenuItems[] = [title, album, artist, track, time, dateAdded]
if (contentType.value === 'episodes') {
items = [title, author, podcast, time, dateAdded]
items = [title, podcast, author, time, dateAdded]
} else if (contentType.value === 'mixed') {
items = [title, albumOrPodcast, artistOrAuthor, time, dateAdded]
}
if (hasCustomSort.value) {
if (hasCustomOrderSort.value) {
items.push(customOrder)
}
@ -92,7 +92,7 @@ const sort = (field: MaybeArray<PlayableListSortField>) => {
hide()
}
const isCurrentField = (field: MaybeArray<PlayableListSortField>) => isEqual(arrayify(field), arrayify(props.field))
const currentlySortedBy = (field: MaybeArray<PlayableListSortField>) => isEqual(arrayify(field), arrayify(props.field))
onMounted(() => menu.value && setup())
onBeforeUnmount(() => teardown())

View file

@ -27,7 +27,7 @@ export const useSongList = (
sortable: true,
reorderable: false,
collaborative: false,
hasCustomSort: false
hasCustomOrderSort: false
}
) => {
const filterKeywords = ref('')

View file

@ -457,7 +457,7 @@ interface PlayableListConfig {
sortable: boolean
reorderable: boolean
collaborative: boolean
hasCustomSort: boolean
hasCustomOrderSort: boolean
}
type PlayableListContext = {