mirror of
https://github.com/koel/koel
synced 2024-11-27 22:40:26 +00:00
chore(tests): better typings for factory
This commit is contained in:
parent
3d68b1b470
commit
bdc9f72368
94 changed files with 569 additions and 389 deletions
|
@ -71,12 +71,13 @@ export default abstract class UnitTestCase {
|
|||
}
|
||||
|
||||
protected be (user?: User) {
|
||||
userStore.state.current = user || factory<User>('user')
|
||||
userStore.state.current = user || factory('user')
|
||||
return this
|
||||
}
|
||||
|
||||
protected beAdmin () {
|
||||
return this.be(factory.states('admin')<User>('user'))
|
||||
factory.states('admin')('user')
|
||||
return this.be(factory.states('admin')('user'))
|
||||
}
|
||||
|
||||
protected mock<T, M extends MethodOf<Required<T>>> (obj: T, methodName: M, implementation?: any) {
|
||||
|
|
|
@ -7,6 +7,6 @@ export default (faker: Faker): AlbumInfo => ({
|
|||
summary: faker.lorem.sentence(),
|
||||
full: faker.lorem.sentences(4)
|
||||
},
|
||||
tracks: factory<AlbumTrack>('album-track', 8),
|
||||
tracks: factory('album-track', 8),
|
||||
url: faker.internet.url()
|
||||
})
|
||||
|
|
20
resources/assets/js/__tests__/factory/episodeFactory.ts
Normal file
20
resources/assets/js/__tests__/factory/episodeFactory.ts
Normal file
|
@ -0,0 +1,20 @@
|
|||
import { Faker } from '@faker-js/faker'
|
||||
|
||||
export default (faker: Faker): Episode => {
|
||||
return {
|
||||
type: 'episodes',
|
||||
id: faker.datatype.uuid(),
|
||||
title: faker.lorem.sentence(),
|
||||
length: faker.datatype.number(),
|
||||
created_at: faker.date.past().toISOString(),
|
||||
playback_state: 'Stopped',
|
||||
liked: false,
|
||||
play_count: 0,
|
||||
episode_link: faker.internet.url(),
|
||||
episode_description: faker.lorem.paragraph(),
|
||||
episode_image: faker.image.imageUrl(),
|
||||
podcast_id: faker.datatype.uuid(),
|
||||
podcast_title: faker.lorem.sentence(),
|
||||
podcast_author: faker.name.findName()
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
import factory from 'factoria'
|
||||
import factoria, { Factoria } from 'factoria'
|
||||
import artistFactory, { states as artistStates } from '@/__tests__/factory/artistFactory'
|
||||
import songFactory, { states as songStates } from '@/__tests__/factory/songFactory'
|
||||
import albumFactory, { states as albumStates } from '@/__tests__/factory/albumFactory'
|
||||
|
@ -14,20 +14,91 @@ import artistInfoFactory from '@/__tests__/factory/artistInfoFactory'
|
|||
import youTubeVideoFactory from '@/__tests__/factory/youTubeVideoFactory'
|
||||
import genreFactory from '@/__tests__/factory/genreFactory'
|
||||
import playlistCollaboratorFactory from '@/__tests__/factory/playlistCollaboratorFactory'
|
||||
import episodeFactory from '@/__tests__/factory/episodeFactory'
|
||||
import podcastFactory from '@/__tests__/factory/podcastFactory'
|
||||
import { Faker } from '@faker-js/faker'
|
||||
|
||||
export default factory
|
||||
.define('artist', faker => artistFactory(faker), artistStates)
|
||||
.define('artist-info', faker => artistInfoFactory(faker))
|
||||
.define('album', faker => albumFactory(faker), albumStates)
|
||||
.define('album-track', faker => albumTrackFactory(faker))
|
||||
.define('album-info', faker => albumInfoFactory(faker))
|
||||
.define('song', () => songFactory(), songStates)
|
||||
.define('interaction', faker => interactionFactory(faker))
|
||||
.define('genre', faker => genreFactory(faker))
|
||||
.define('video', faker => youTubeVideoFactory(faker))
|
||||
.define('smart-playlist-rule', faker => smartPlaylistRuleFactory(faker))
|
||||
.define('smart-playlist-rule-group', faker => smartPlaylistRuleGroupFactory(faker))
|
||||
.define('playlist', faker => playlistFactory(faker), playlistStates)
|
||||
.define('playlist-folder', faker => playlistFolderFactory(faker))
|
||||
.define('user', faker => userFactory(faker), userStates)
|
||||
.define('playlist-collaborator', faker => playlistCollaboratorFactory(faker))
|
||||
type ModelToTypeMap = {
|
||||
artist: Artist
|
||||
'artist-info': ArtistInfo
|
||||
album: Album
|
||||
'album-track': AlbumTrack
|
||||
'album-info': AlbumInfo
|
||||
song: Song
|
||||
interaction: Interaction
|
||||
genre: Genre
|
||||
video: YouTubeVideo
|
||||
'smart-playlist-rule': SmartPlaylistRule
|
||||
'smart-playlist-rule-group': SmartPlaylistRuleGroup
|
||||
playlist: Playlist
|
||||
'playlist-folder': PlaylistFolder
|
||||
user: User
|
||||
'playlist-collaborator': PlaylistCollaborator
|
||||
episode: Episode
|
||||
podcast: Podcast
|
||||
}
|
||||
|
||||
type Model = keyof ModelToTypeMap
|
||||
type Overrides<M extends Model> = Factoria.Overrides<ModelToTypeMap[M]>
|
||||
|
||||
const define = <M extends Model>(
|
||||
model: M,
|
||||
handle: (faker: Faker) => Overrides<M>,
|
||||
states?: Record<string, Factoria.StateDefinition>
|
||||
) => factoria.define(model, handle, states)
|
||||
|
||||
function factory <M extends Model>(
|
||||
model: M,
|
||||
overrides?: Overrides<M>
|
||||
): ModelToTypeMap[M]
|
||||
|
||||
function factory <M extends Model>(
|
||||
model: M,
|
||||
count: 1,
|
||||
overrides?: Overrides<M>
|
||||
): ModelToTypeMap[M]
|
||||
|
||||
function factory <M extends Model>(
|
||||
model: M,
|
||||
count: number,
|
||||
overrides?: Overrides<M>
|
||||
): ModelToTypeMap[M][]
|
||||
|
||||
function factory <M extends Model>(
|
||||
model: M,
|
||||
count: number|Overrides<M> = 1,
|
||||
overrides?: Overrides<M>
|
||||
) {
|
||||
return typeof count === 'number'
|
||||
? count === 1 ? factoria(model, overrides) : factoria(model, count, overrides)
|
||||
: factoria(model, count)
|
||||
}
|
||||
|
||||
const states = (...states: string[]): typeof factory => {
|
||||
factoria.states(...states)
|
||||
return factory
|
||||
}
|
||||
|
||||
factory.states = states
|
||||
|
||||
export default factory as typeof factory & {
|
||||
states: typeof states
|
||||
}
|
||||
|
||||
define('artist', artistFactory, artistStates)
|
||||
define('artist-info', artistInfoFactory)
|
||||
define('album', albumFactory, albumStates)
|
||||
define('album-track', albumTrackFactory)
|
||||
define('album-info', albumInfoFactory)
|
||||
define('song', songFactory, songStates)
|
||||
define('interaction', interactionFactory)
|
||||
define('genre', genreFactory)
|
||||
define('video', youTubeVideoFactory)
|
||||
define('smart-playlist-rule', smartPlaylistRuleFactory)
|
||||
define('smart-playlist-rule-group', smartPlaylistRuleGroupFactory)
|
||||
define('playlist', playlistFactory, playlistStates)
|
||||
define('playlist-folder', playlistFolderFactory)
|
||||
define('user', userFactory, userStates)
|
||||
define('playlist-collaborator', playlistCollaboratorFactory)
|
||||
define('episode', episodeFactory)
|
||||
define('podcast', podcastFactory)
|
||||
|
|
|
@ -18,7 +18,7 @@ export const states: Record<string, (faker: Faker) => Omit<Partial<Playlist>, 't
|
|||
smart: _ => ({
|
||||
is_smart: true,
|
||||
rules: [
|
||||
factory<SmartPlaylistRuleGroup>('smart-playlist-rule-group')
|
||||
factory('smart-playlist-rule-group')
|
||||
]
|
||||
}),
|
||||
orphan: _ => ({
|
||||
|
|
19
resources/assets/js/__tests__/factory/podcastFactory.ts
Normal file
19
resources/assets/js/__tests__/factory/podcastFactory.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { Faker } from '@faker-js/faker'
|
||||
|
||||
export default (faker: Faker): Podcast => {
|
||||
return {
|
||||
type: 'podcasts',
|
||||
id: faker.datatype.uuid(),
|
||||
title: faker.lorem.sentence(),
|
||||
url: faker.internet.url(),
|
||||
link: faker.internet.url(),
|
||||
image: faker.image.imageUrl(),
|
||||
description: faker.lorem.paragraph(),
|
||||
author: faker.name.findName(),
|
||||
subscribed_at: faker.date.past().toISOString(),
|
||||
state: {
|
||||
current_episode: null,
|
||||
progresses: {}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,5 +3,5 @@ import factory from 'factoria'
|
|||
|
||||
export default (faker: Faker): SmartPlaylistRuleGroup => ({
|
||||
id: faker.datatype.uuid(),
|
||||
rules: factory<SmartPlaylistRule>('smart-playlist-rule', 3)
|
||||
rules: factory('smart-playlist-rule', 3)
|
||||
})
|
||||
|
|
|
@ -30,7 +30,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('shuffles', async () => {
|
||||
const songs = factory<Song>('song', 10)
|
||||
const songs = factory('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(songs)
|
||||
const shuffleMock = this.mock(playbackService, 'queueAndPlay').mockResolvedValue(void 0)
|
||||
this.renderComponent()
|
||||
|
@ -52,7 +52,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private renderComponent () {
|
||||
album = factory<Album>('album', {
|
||||
album = factory('album', {
|
||||
id: 42,
|
||||
name: 'IV',
|
||||
artist_id: 17,
|
||||
|
|
|
@ -15,7 +15,7 @@ new class extends UnitTestCase {
|
|||
it('renders', async () => expect((await this.renderComponent()).html()).toMatchSnapshot())
|
||||
|
||||
it('plays all', async () => {
|
||||
const songs = factory<Song>('song', 10)
|
||||
const songs = factory('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
|
||||
|
@ -28,7 +28,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('shuffles all', async () => {
|
||||
const songs = factory<Song>('song', 10)
|
||||
const songs = factory('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
|
||||
|
@ -66,7 +66,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('does not have an option to download or go to Unknown Album and Artist', async () => {
|
||||
await this.renderComponent(factory.states('unknown')<Album>('album'))
|
||||
await this.renderComponent(factory.states('unknown')('album'))
|
||||
|
||||
expect(screen.queryByText('Go to Album')).toBeNull()
|
||||
expect(screen.queryByText('Go to Artist')).toBeNull()
|
||||
|
@ -84,7 +84,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private async renderComponent (_album?: Album) {
|
||||
album = _album || factory<Album>('album', {
|
||||
album = _album || factory('album', {
|
||||
name: 'IV'
|
||||
})
|
||||
|
||||
|
|
|
@ -29,10 +29,10 @@ new class extends UnitTestCase {
|
|||
commonStore.state.uses_last_fm = true
|
||||
|
||||
if (info === undefined) {
|
||||
info = factory<AlbumInfo>('album-info')
|
||||
info = factory('album-info')
|
||||
}
|
||||
|
||||
album = factory<Album>('album', { name: 'IV' })
|
||||
album = factory('album', { name: 'IV' })
|
||||
const fetchMock = this.mock(mediaInfoService, 'fetchForAlbum').mockResolvedValue(info)
|
||||
|
||||
const rendered = this.render(AlbumInfoComponent, {
|
||||
|
|
|
@ -8,13 +8,13 @@ import { songStore } from '@/stores'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('displays the tracks', async () => {
|
||||
const album = factory<Album>('album')
|
||||
const fetchMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(factory<Song>('song', 5))
|
||||
const album = factory('album')
|
||||
const fetchMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(factory('song', 5))
|
||||
|
||||
this.render(AlbumTrackList, {
|
||||
props: {
|
||||
album,
|
||||
tracks: factory<AlbumTrack>('album-track', 3)
|
||||
tracks: factory('album-track', 3)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ new class extends UnitTestCase {
|
|||
it('renders', () => expect(this.renderComponent().html()).toMatchSnapshot())
|
||||
|
||||
it('plays', async () => {
|
||||
const matchedSong = factory<Song>('song')
|
||||
const matchedSong = factory('song')
|
||||
const queueMock = this.mock(queueStore, 'queueIfNotQueued')
|
||||
const playMock = this.mock(playbackService, 'play')
|
||||
|
||||
|
@ -27,10 +27,10 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private renderComponent (matchedSong?: Song) {
|
||||
const songsToMatchAgainst = factory<Song>('song', 10)
|
||||
const album = factory<Album>('album')
|
||||
const songsToMatchAgainst = factory('song', 10)
|
||||
const album = factory('album')
|
||||
|
||||
const track = factory<AlbumTrack>('album-track', {
|
||||
const track = factory('album-track', {
|
||||
title: 'Fahrstuhl to Heaven',
|
||||
length: 280
|
||||
})
|
||||
|
|
|
@ -12,7 +12,7 @@ let artist: Artist
|
|||
new class extends UnitTestCase {
|
||||
protected beforeEach () {
|
||||
super.beforeEach(() => {
|
||||
artist = factory<Artist>('artist', {
|
||||
artist = factory('artist', {
|
||||
id: 42,
|
||||
name: 'Led Zeppelin'
|
||||
})
|
||||
|
@ -38,7 +38,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('shuffles', async () => {
|
||||
const songs = factory<Song>('song', 16)
|
||||
const songs = factory('song', 16)
|
||||
const fetchMock = this.mock(songStore, 'fetchForArtist').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ new class extends UnitTestCase {
|
|||
it('renders', async () => expect((await this.renderComponent()).html()).toMatchSnapshot())
|
||||
|
||||
it('plays all', async () => {
|
||||
const songs = factory<Song>('song', 10)
|
||||
const songs = factory('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForArtist').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
|
||||
|
@ -28,7 +28,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('shuffles all', async () => {
|
||||
const songs = factory<Song>('song', 10)
|
||||
const songs = factory('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForArtist').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
|
||||
|
@ -66,14 +66,14 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('does not have an option to download or go to Unknown Artist', async () => {
|
||||
await this.renderComponent(factory.states('unknown')<Artist>('artist'))
|
||||
await this.renderComponent(factory.states('unknown')('artist'))
|
||||
|
||||
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 () => {
|
||||
await this.renderComponent(factory.states('various')<Artist>('artist'))
|
||||
await this.renderComponent(factory.states('various')('artist'))
|
||||
|
||||
expect(screen.queryByText('Go to Artist')).toBeNull()
|
||||
expect(screen.queryByText('Download')).toBeNull()
|
||||
|
@ -81,7 +81,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private async renderComponent (_artist?: Artist) {
|
||||
artist = _artist || factory<Artist>('artist', {
|
||||
artist = _artist || factory('artist', {
|
||||
name: 'Accept'
|
||||
})
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@ new class extends UnitTestCase {
|
|||
|
||||
private async renderComponent (mode: MediaInfoDisplayMode = 'aside', info?: ArtistInfo) {
|
||||
commonStore.state.uses_last_fm = true
|
||||
info = info ?? factory<ArtistInfo>('artist-info')
|
||||
artist = factory<Artist>('artist', { name: 'Led Zeppelin' })
|
||||
info = info ?? factory('artist-info')
|
||||
artist = factory('artist', { name: 'Led Zeppelin' })
|
||||
|
||||
const fetchMock = this.mock(mediaInfoService, 'fetchForArtist').mockResolvedValue(info)
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('accepts invitation', async () => {
|
||||
const getProspectMock = this.mock(invitationService, 'getUserProspect')
|
||||
.mockResolvedValue(factory.states('prospect')<User>('user'))
|
||||
.mockResolvedValue(factory.states('prospect')('user'))
|
||||
|
||||
const acceptMock = this.mock(invitationService, 'accept').mockResolvedValue({
|
||||
token: 'my-api-token',
|
||||
|
|
|
@ -11,30 +11,38 @@ new class extends UnitTestCase {
|
|||
it.each<[string, keyof Events, User | Song[] | Playlist | PlaylistFolder | undefined]>([
|
||||
['add-user-form', 'MODAL_SHOW_ADD_USER_FORM', undefined],
|
||||
['invite-user-form', 'MODAL_SHOW_INVITE_USER_FORM', undefined],
|
||||
['edit-user-form', 'MODAL_SHOW_EDIT_USER_FORM', factory<User>('user')],
|
||||
['edit-song-form', 'MODAL_SHOW_EDIT_SONG_FORM', [factory<Song>('song')]],
|
||||
['create-playlist-form', 'MODAL_SHOW_CREATE_PLAYLIST_FORM', factory<PlaylistFolder>('playlist-folder')],
|
||||
['edit-user-form', 'MODAL_SHOW_EDIT_USER_FORM', factory('user')],
|
||||
['edit-song-form', 'MODAL_SHOW_EDIT_SONG_FORM', [factory('song')]],
|
||||
['create-playlist-form', 'MODAL_SHOW_CREATE_PLAYLIST_FORM', factory('playlist-folder')],
|
||||
['create-playlist-folder-form', 'MODAL_SHOW_CREATE_PLAYLIST_FOLDER_FORM', undefined],
|
||||
['edit-playlist-folder-form', 'MODAL_SHOW_EDIT_PLAYLIST_FOLDER_FORM', factory<PlaylistFolder>('playlist-folder')],
|
||||
['create-smart-playlist-form', 'MODAL_SHOW_CREATE_SMART_PLAYLIST_FORM', factory<PlaylistFolder>('playlist-folder')],
|
||||
['edit-playlist-form', 'MODAL_SHOW_EDIT_PLAYLIST_FORM', factory<Playlist>('playlist')],
|
||||
['edit-smart-playlist-form', 'MODAL_SHOW_EDIT_PLAYLIST_FORM', factory<Playlist>('playlist', { is_smart: true })],
|
||||
['about-koel', 'MODAL_SHOW_ABOUT_KOEL', undefined]
|
||||
['edit-playlist-folder-form', 'MODAL_SHOW_EDIT_PLAYLIST_FOLDER_FORM', factory('playlist-folder')],
|
||||
['playlist-collaboration', 'MODAL_SHOW_PLAYLIST_COLLABORATION', factory('playlist')],
|
||||
['create-smart-playlist-form', 'MODAL_SHOW_CREATE_SMART_PLAYLIST_FORM', factory('playlist-folder')],
|
||||
['edit-playlist-form', 'MODAL_SHOW_EDIT_PLAYLIST_FORM', factory('playlist')],
|
||||
['edit-smart-playlist-form', 'MODAL_SHOW_EDIT_PLAYLIST_FORM', factory('playlist', { is_smart: true })],
|
||||
['about-koel', 'MODAL_SHOW_ABOUT_KOEL', undefined],
|
||||
['koel-plus', 'MODAL_SHOW_KOEL_PLUS', undefined],
|
||||
['equalizer', 'MODAL_SHOW_EQUALIZER', undefined],
|
||||
['add-podcast-form', 'MODAL_SHOW_ADD_PODCAST_FORM', undefined]
|
||||
])('shows %s modal', async (modalName, eventName, eventParams?: any) => {
|
||||
this.render(ModalWrapper, {
|
||||
global: {
|
||||
stubs: {
|
||||
AboutKoelModal: this.stub('about-koel'),
|
||||
AddPodcastForm: this.stub('add-podcast-form'),
|
||||
AddUserForm: this.stub('add-user-form'),
|
||||
EditUserForm: this.stub('edit-user-form'),
|
||||
InviteUserForm: this.stub('invite-user-form'),
|
||||
EditSongForm: this.stub('edit-song-form'),
|
||||
CreatePlaylistForm: this.stub('create-playlist-form'),
|
||||
CreatePlaylistFolderForm: this.stub('create-playlist-folder-form'),
|
||||
EditPlaylistFolderForm: this.stub('edit-playlist-folder-form'),
|
||||
CreatePlaylistForm: this.stub('create-playlist-form'),
|
||||
CreateSmartPlaylistForm: this.stub('create-smart-playlist-form'),
|
||||
EditPlaylistFolderForm: this.stub('edit-playlist-folder-form'),
|
||||
EditPlaylistForm: this.stub('edit-playlist-form'),
|
||||
EditSmartPlaylistForm: this.stub('edit-smart-playlist-form'),
|
||||
AboutKoelModal: this.stub('about-koel')
|
||||
EditSongForm: this.stub('edit-song-form'),
|
||||
EditUserForm: this.stub('edit-user-form'),
|
||||
Equalizer: this.stub('equalizer'),
|
||||
InviteUserForm: this.stub('invite-user-form'),
|
||||
KoelPlus: this.stub('koel-plus'),
|
||||
PlaylistCollaborationModal: this.stub('playlist-collaboration')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -14,21 +14,21 @@ import { arrayify, eventBus, provideReadonly } from '@/utils'
|
|||
import { ModalContextKey } from '@/symbols'
|
||||
|
||||
const modalNameToComponentMap = {
|
||||
'create-playlist-form': defineAsyncComponent(() => import('@/components/playlist/CreatePlaylistForm.vue')),
|
||||
'edit-playlist-form': defineAsyncComponent(() => import('@/components/playlist/EditPlaylistForm.vue')),
|
||||
'create-smart-playlist-form': defineAsyncComponent(() => import('@/components/playlist/smart-playlist/CreateSmartPlaylistForm.vue')),
|
||||
'edit-smart-playlist-form': defineAsyncComponent(() => import('@/components/playlist/smart-playlist/EditSmartPlaylistForm.vue')),
|
||||
'add-user-form': defineAsyncComponent(() => import('@/components/user/AddUserForm.vue')),
|
||||
'edit-user-form': defineAsyncComponent(() => import('@/components/user/EditUserForm.vue')),
|
||||
'invite-user-form': defineAsyncComponent(() => import('@/components/user/InviteUserForm.vue')),
|
||||
'edit-song-form': defineAsyncComponent(() => import('@/components/song/EditSongForm.vue')),
|
||||
'create-playlist-folder-form': defineAsyncComponent(() => import('@/components/playlist/CreatePlaylistFolderForm.vue')),
|
||||
'edit-playlist-folder-form': defineAsyncComponent(() => import('@/components/playlist/EditPlaylistFolderForm.vue')),
|
||||
'playlist-collaboration': defineAsyncComponent(() => import('@/components/playlist/PlaylistCollaborationModal.vue')),
|
||||
'add-podcast-form': defineAsyncComponent(() => import('@/components/podcast/AddPodcastForm.vue')),
|
||||
'about-koel': defineAsyncComponent(() => import('@/components/meta/AboutKoelModal.vue')),
|
||||
'add-podcast-form': defineAsyncComponent(() => import('@/components/podcast/AddPodcastForm.vue')),
|
||||
'add-user-form': defineAsyncComponent(() => import('@/components/user/AddUserForm.vue')),
|
||||
'create-playlist-folder-form': defineAsyncComponent(() => import('@/components/playlist/CreatePlaylistFolderForm.vue')),
|
||||
'create-playlist-form': defineAsyncComponent(() => import('@/components/playlist/CreatePlaylistForm.vue')),
|
||||
'create-smart-playlist-form': defineAsyncComponent(() => import('@/components/playlist/smart-playlist/CreateSmartPlaylistForm.vue')),
|
||||
'edit-playlist-folder-form': defineAsyncComponent(() => import('@/components/playlist/EditPlaylistFolderForm.vue')),
|
||||
'edit-playlist-form': defineAsyncComponent(() => import('@/components/playlist/EditPlaylistForm.vue')),
|
||||
'edit-smart-playlist-form': defineAsyncComponent(() => import('@/components/playlist/smart-playlist/EditSmartPlaylistForm.vue')),
|
||||
'edit-song-form': defineAsyncComponent(() => import('@/components/song/EditSongForm.vue')),
|
||||
'edit-user-form': defineAsyncComponent(() => import('@/components/user/EditUserForm.vue')),
|
||||
'equalizer': defineAsyncComponent(() => import('@/components/ui/equalizer/Equalizer.vue')),
|
||||
'invite-user-form': defineAsyncComponent(() => import('@/components/user/InviteUserForm.vue')),
|
||||
'koel-plus': defineAsyncComponent(() => import('@/components/koel-plus/KoelPlusModal.vue')),
|
||||
'equalizer': defineAsyncComponent(() => import('@/components/ui/equalizer/Equalizer.vue'))
|
||||
'playlist-collaboration': defineAsyncComponent(() => import('@/components/playlist/PlaylistCollaborationModal.vue'))
|
||||
}
|
||||
|
||||
type ModalName = keyof typeof modalNameToComponentMap
|
||||
|
|
|
@ -33,7 +33,7 @@ new class extends UnitTestCase {
|
|||
|
||||
private renderComponent (song?: Song | null) {
|
||||
if (song === undefined) {
|
||||
song = factory<Song>('song', {
|
||||
song = factory('song', {
|
||||
id: '00000000-0000-0000-0000-000000000000',
|
||||
title: 'Fahrstuhl to Heaven',
|
||||
artist_name: 'Led Zeppelin',
|
||||
|
|
|
@ -10,7 +10,7 @@ new class extends UnitTestCase {
|
|||
it('renders with no current song', () => expect(this.render(FooterSongInfo).html()).toMatchSnapshot())
|
||||
|
||||
it('renders with current song', () => {
|
||||
const song = factory<Song>('song', {
|
||||
const song = factory('song', {
|
||||
title: 'Fahrstuhl zum Mond',
|
||||
album_cover: 'https://via.placeholder.com/150',
|
||||
playback_state: 'Playing',
|
||||
|
|
|
@ -31,7 +31,7 @@ new class extends UnitTestCase {
|
|||
return this.render(MainContent, {
|
||||
global: {
|
||||
provide: {
|
||||
[<symbol>CurrentPlayableKey]: ref(factory<Song>('song'))
|
||||
[<symbol>CurrentPlayableKey]: ref(factory('song'))
|
||||
},
|
||||
stubs: {
|
||||
AlbumArtOverlay,
|
||||
|
|
|
@ -14,7 +14,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('sets the active tab to the preference', async () => {
|
||||
preferenceStore.active_extra_panel_tab = 'YouTube'
|
||||
this.renderComponent(ref(factory<Song>('song')))
|
||||
this.renderComponent(ref(factory('song')))
|
||||
const tab = screen.getByTestId<HTMLElement>('extra-drawer-youtube')
|
||||
|
||||
expect(tab.style.display).toBe('none')
|
||||
|
@ -25,7 +25,7 @@ new class extends UnitTestCase {
|
|||
it('fetches info for the current song', async () => {
|
||||
commonStore.state.uses_you_tube = true
|
||||
|
||||
const song = factory<Song>('song')
|
||||
const song = factory('song')
|
||||
const songRef = ref<Song | null>(null)
|
||||
|
||||
const [, resolveArtistMock, resolveAlbumMock] = this.renderComponent(songRef)
|
||||
|
@ -66,10 +66,10 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private renderComponent (songRef: Ref<Song | null> = ref(null)): [RenderResult, Mock, Mock] {
|
||||
const artist = factory<Artist>('artist')
|
||||
const artist = factory('artist')
|
||||
const resolveArtistMock = this.mock(artistStore, 'resolve').mockResolvedValue(artist)
|
||||
|
||||
const album = factory<Album>('album')
|
||||
const album = factory('album')
|
||||
const resolveAlbumMock = this.mock(albumStore, 'resolve').mockResolvedValue(album)
|
||||
|
||||
const rendered = this.render(ExtraDrawer, {
|
||||
|
|
|
@ -17,7 +17,7 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('requests context menu if is playlist', async () => {
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const playlist = factory('playlist')
|
||||
this.renderComponent(playlist)
|
||||
|
||||
await fireEvent.contextMenu(screen.getByRole('listitem'))
|
||||
|
|
|
@ -11,9 +11,9 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('displays orphan playlists', () => {
|
||||
playlistStore.state.playlists = [
|
||||
factory.states('orphan')<Playlist>('playlist', { name: 'Foo Playlist' }),
|
||||
factory.states('orphan')<Playlist>('playlist', { name: 'Bar Playlist' }),
|
||||
factory.states('smart', 'orphan')<Playlist>('playlist', { name: 'Smart Playlist' })
|
||||
factory.states('orphan')('playlist', { name: 'Foo Playlist' }),
|
||||
factory.states('orphan')('playlist', { name: 'Bar Playlist' }),
|
||||
factory.states('smart', 'orphan')('playlist', { name: 'Smart Playlist' })
|
||||
]
|
||||
|
||||
this.renderComponent()
|
||||
|
@ -25,8 +25,8 @@ new class extends UnitTestCase {
|
|||
|
||||
it('displays playlist folders', () => {
|
||||
playlistFolderStore.state.folders = [
|
||||
factory<PlaylistFolder>('playlist-folder', { name: 'Foo Folder' }),
|
||||
factory<PlaylistFolder>('playlist-folder', { name: 'Bar Folder' })
|
||||
factory('playlist-folder', { name: 'Foo Folder' }),
|
||||
factory('playlist-folder', { name: 'Bar Folder' })
|
||||
]
|
||||
|
||||
this.renderComponent()
|
||||
|
|
|
@ -9,7 +9,7 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('submits', async () => {
|
||||
const storeMock = this.mock(playlistFolderStore, 'store')
|
||||
.mockResolvedValue(factory<PlaylistFolder>('playlist-folder'))
|
||||
.mockResolvedValue(factory('playlist-folder'))
|
||||
|
||||
this.render(CreatePlaylistFolderForm)
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ import CreatePlaylistForm from './CreatePlaylistForm.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('creates playlist with no songs', async () => {
|
||||
const folder = factory<PlaylistFolder>('playlist-folder')
|
||||
const storeMock = this.mock(playlistStore, 'store').mockResolvedValue(factory<Playlist>('playlist'))
|
||||
const folder = factory('playlist-folder')
|
||||
const storeMock = this.mock(playlistStore, 'store').mockResolvedValue(factory('playlist'))
|
||||
|
||||
this.render(CreatePlaylistForm, {
|
||||
global: {
|
||||
|
@ -32,9 +32,9 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('creates playlist with songs', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const folder = factory<PlaylistFolder>('playlist-folder')
|
||||
const storeMock = this.mock(playlistStore, 'store').mockResolvedValue(factory<Playlist>('playlist'))
|
||||
const songs = factory('song', 3)
|
||||
const folder = factory('playlist-folder')
|
||||
const storeMock = this.mock(playlistStore, 'store').mockResolvedValue(factory('playlist'))
|
||||
|
||||
this.render(CreatePlaylistForm, {
|
||||
global: {
|
||||
|
|
|
@ -10,7 +10,7 @@ import EditPlaylistFolderForm from './EditPlaylistFolderForm.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('submits', async () => {
|
||||
const folder = factory<PlaylistFolder>('playlist-folder', { name: 'My folder' })
|
||||
const folder = factory('playlist-folder', { name: 'My folder' })
|
||||
const renameMock = this.mock(playlistFolderStore, 'rename')
|
||||
this.render(EditPlaylistFolderForm, {
|
||||
global: {
|
||||
|
|
|
@ -10,9 +10,9 @@ import EditPlaylistForm from './EditPlaylistForm.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('submits', async () => {
|
||||
playlistFolderStore.state.folders = factory<PlaylistFolder>('playlist-folder', 3)
|
||||
playlistFolderStore.state.folders = factory('playlist-folder', 3)
|
||||
|
||||
const playlist = factory<Playlist>('playlist', {
|
||||
const playlist = factory('playlist', {
|
||||
name: 'My playlist',
|
||||
folder_id: playlistFolderStore.state.folders[0].id
|
||||
})
|
||||
|
|
|
@ -10,7 +10,7 @@ new class extends UnitTestCase {
|
|||
it('works', async () => {
|
||||
this.mock(playlistCollaborationService, 'createInviteLink').mockResolvedValue('http://localhost:3000/invite/1234')
|
||||
const writeTextMock = this.mock(navigator.clipboard, 'writeText')
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const playlist = factory('playlist')
|
||||
|
||||
this.render(Component, {
|
||||
props: {
|
||||
|
|
|
@ -11,7 +11,7 @@ new class extends UnitTestCase {
|
|||
const { html } = this.render(Modal, {
|
||||
global: {
|
||||
provide: {
|
||||
[<symbol>ModalContextKey]: [ref({ playlist: factory<Playlist>('playlist') })]
|
||||
[<symbol>ModalContextKey]: [ref({ playlist: factory('playlist') })]
|
||||
},
|
||||
stubs: {
|
||||
InviteCollaborators: this.stub('InviteCollaborators'),
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
<template>
|
||||
<div class="collaboration-modal max-w-[640px]" tabindex="0" @keydown.esc="close">
|
||||
<div
|
||||
class="collaboration-modal max-w-[640px]"
|
||||
tabindex="0"
|
||||
@keydown.esc="close"
|
||||
data-testid="playlist-collaboration"
|
||||
>
|
||||
<header>
|
||||
<h1>Playlist Collaboration</h1>
|
||||
</header>
|
||||
|
|
|
@ -7,12 +7,12 @@ import Component from './PlaylistCollaboratorList.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('renders', async () => {
|
||||
const playlist = factory<Playlist>('playlist', {
|
||||
const playlist = factory('playlist', {
|
||||
is_collaborative: true
|
||||
})
|
||||
|
||||
const fetchMock = this.mock(playlistCollaborationService, 'fetchCollaborators').mockResolvedValue(
|
||||
factory<PlaylistCollaborator>('playlist-collaborator', 5)
|
||||
factory('playlist-collaborator', 5)
|
||||
)
|
||||
|
||||
const { html } = await this.be().renderComponent(playlist)
|
||||
|
|
|
@ -7,9 +7,9 @@ import Component from './PlaylistCollaboratorListItem.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('does not show a badge when current user is not the collaborator', async () => {
|
||||
const currentUser = factory<User>('user')
|
||||
const currentUser = factory('user')
|
||||
this.be(currentUser).renderComponent({
|
||||
collaborator: factory<PlaylistCollaborator>('playlist-collaborator', { id: currentUser.id + 1 }),
|
||||
collaborator: factory('playlist-collaborator', { id: currentUser.id + 1 }),
|
||||
removable: true,
|
||||
manageable: true,
|
||||
role: 'owner'
|
||||
|
@ -19,9 +19,9 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('shows a badge when current user is the collaborator', async () => {
|
||||
const currentUser = factory<User>('user')
|
||||
const currentUser = factory('user')
|
||||
this.be(currentUser).renderComponent({
|
||||
collaborator: factory<PlaylistCollaborator>('playlist-collaborator',
|
||||
collaborator: factory('playlist-collaborator',
|
||||
{
|
||||
id: currentUser.id,
|
||||
name: currentUser.name,
|
||||
|
@ -37,7 +37,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('shows the role', async () => {
|
||||
const collaborator = factory<PlaylistCollaborator>('playlist-collaborator')
|
||||
const collaborator = factory('playlist-collaborator')
|
||||
|
||||
this.be().renderComponent({
|
||||
collaborator,
|
||||
|
@ -59,7 +59,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('emits the remove event when the remove button is clicked', async () => {
|
||||
const collaborator = factory<PlaylistCollaborator>('playlist-collaborator')
|
||||
const collaborator = factory('playlist-collaborator')
|
||||
const { emitted } = this.be().renderComponent({
|
||||
collaborator,
|
||||
removable: true,
|
||||
|
|
|
@ -12,7 +12,7 @@ import PlaylistContextMenu from './PlaylistContextMenu.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('edits a standard playlist', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const playlist = factory('playlist')
|
||||
await this.renderComponent(playlist)
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
|
||||
|
@ -22,7 +22,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('edits a smart playlist', async () => {
|
||||
const playlist = factory.states('smart')<Playlist>('playlist')
|
||||
const playlist = factory.states('smart')('playlist')
|
||||
await this.renderComponent(playlist)
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
|
||||
|
@ -32,7 +32,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('deletes a playlist', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const playlist = factory('playlist')
|
||||
await this.renderComponent(playlist)
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
|
||||
|
@ -42,8 +42,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('plays', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const songs = factory<Song>('song', 3)
|
||||
const playlist = factory('playlist')
|
||||
const songs = factory('song', 3)
|
||||
const fetchMock = this.mock(songStore, 'fetchForPlaylist').mockResolvedValue(songs)
|
||||
const queueMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const goMock = this.mock(Router, 'go')
|
||||
|
@ -59,7 +59,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('warns if attempting to play an empty playlist', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const playlist = factory('playlist')
|
||||
const fetchMock = this.mock(songStore, 'fetchForPlaylist').mockResolvedValue([])
|
||||
const queueMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const goMock = this.mock(Router, 'go')
|
||||
|
@ -78,8 +78,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('shuffles', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const songs = factory<Song>('song', 3)
|
||||
const playlist = factory('playlist')
|
||||
const songs = factory('song', 3)
|
||||
const fetchMock = this.mock(songStore, 'fetchForPlaylist').mockResolvedValue(songs)
|
||||
const queueMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const goMock = this.mock(Router, 'go')
|
||||
|
@ -95,7 +95,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('warns if attempting to shuffle an empty playlist', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const playlist = factory('playlist')
|
||||
const fetchMock = this.mock(songStore, 'fetchForPlaylist').mockResolvedValue([])
|
||||
const queueMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const goMock = this.mock(Router, 'go')
|
||||
|
@ -114,8 +114,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('queues', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const songs = factory<Song>('song', 3)
|
||||
const playlist = factory('playlist')
|
||||
const songs = factory('song', 3)
|
||||
const fetchMock = this.mock(songStore, 'fetchForPlaylist').mockResolvedValue(songs)
|
||||
const queueMock = this.mock(queueStore, 'queueAfterCurrent')
|
||||
const toastMock = this.mock(MessageToasterStub.value, 'success')
|
||||
|
@ -131,8 +131,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('does not have an option to edit or delete if the playlist is not owned by the current user', async () => {
|
||||
const user = factory<User>('user')
|
||||
const playlist = factory<Playlist>('playlist', {
|
||||
const user = factory('user')
|
||||
const playlist = factory('playlist', {
|
||||
user_id: user.id + 1
|
||||
})
|
||||
|
||||
|
@ -144,7 +144,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('opens collaboration form', async () => {
|
||||
this.enablePlusEdition()
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const playlist = factory('playlist')
|
||||
await this.renderComponent(playlist)
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
|
||||
|
@ -155,7 +155,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private async renderComponent (playlist: Playlist, user: User | null = null) {
|
||||
userStore.state.current = user || factory<User>('user', {
|
||||
userStore.state.current = user || factory('user', {
|
||||
id: playlist.user_id
|
||||
})
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import PlaylistFolderContextMenu from './PlaylistFolderContextMenu.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('renames', async () => {
|
||||
const folder = factory<PlaylistFolder>('playlist-folder')
|
||||
const folder = factory('playlist-folder')
|
||||
await this.renderComponent(folder)
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
|
||||
|
@ -22,7 +22,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('deletes', async () => {
|
||||
const folder = factory<PlaylistFolder>('playlist-folder')
|
||||
const folder = factory('playlist-folder')
|
||||
await this.renderComponent(folder)
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
|
||||
|
@ -33,7 +33,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('plays', async () => {
|
||||
const folder = this.createPlayableFolder()
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
const fetchMock = this.mock(songStore, 'fetchForPlaylistFolder').mockResolvedValue(songs)
|
||||
const queueMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const goMock = this.mock(Router, 'go')
|
||||
|
@ -70,7 +70,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('shuffles', async () => {
|
||||
const folder = this.createPlayableFolder()
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
const fetchMock = this.mock(songStore, 'fetchForPlaylistFolder').mockResolvedValue(songs)
|
||||
const queueMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const goMock = this.mock(Router, 'go')
|
||||
|
@ -86,7 +86,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('does not show shuffle option if folder is empty', async () => {
|
||||
const folder = factory<PlaylistFolder>('playlist-folder')
|
||||
const folder = factory('playlist-folder')
|
||||
await this.renderComponent(folder)
|
||||
|
||||
expect(screen.queryByText('Shuffle All')).toBeNull()
|
||||
|
@ -121,8 +121,8 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private createPlayableFolder () {
|
||||
const folder = factory<PlaylistFolder>('playlist-folder')
|
||||
this.mock(playlistStore, 'byFolder', factory<Playlist>('playlist', 3, { folder_id: folder.id }))
|
||||
const folder = factory('playlist-folder')
|
||||
this.mock(playlistStore, 'byFolder', factory('playlist', 3, { folder_id: folder.id }))
|
||||
return folder
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<FormBase>
|
||||
<FormBase data-testid="edit-smart-playlist-form">
|
||||
<form @submit.prevent="submit" @keydown.esc="maybeClose">
|
||||
<header>
|
||||
<h1>Edit Smart Playlist</h1>
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import { screen } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import { podcastStore } from '@/stores'
|
||||
import Component from './AddPodcastForm.vue'
|
||||
import factory from '@/__tests__/factory'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('adds a new podcast', async() => {
|
||||
const storeMock = this.mock(podcastStore, 'store').mockResolvedValue(factory('podcast'))
|
||||
this.render(Component)
|
||||
await this.type(screen.getByPlaceholderText('https://example.com/feed.xml'), 'https://foo.bar/feed.xml')
|
||||
await this.user.click(screen.getByRole('button', { name: 'Save' }))
|
||||
expect(storeMock).toHaveBeenCalledWith('https://foo.bar/feed.xml')
|
||||
})
|
||||
}
|
||||
}
|
38
resources/assets/js/components/podcast/EpisodeItem.spec.ts
Normal file
38
resources/assets/js/components/podcast/EpisodeItem.spec.ts
Normal file
|
@ -0,0 +1,38 @@
|
|||
import { screen } from '@testing-library/vue'
|
||||
import { expect, it } from 'vitest'
|
||||
import UnitTestCase from '@/__tests__/UnitTestCase'
|
||||
import Component from './EpisodeItem.vue'
|
||||
import factory from '@/__tests__/factory'
|
||||
import { playbackService } from '@/services'
|
||||
|
||||
new class extends UnitTestCase {
|
||||
private renderComponent (episode: Episode, podcast?: Podcast) {
|
||||
podcast = podcast || factory('podcast', {
|
||||
id: episode.id
|
||||
})
|
||||
|
||||
this.render(Component, {
|
||||
props: {
|
||||
episode,
|
||||
podcast
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
protected test () {
|
||||
it('pauses playback', async () => {
|
||||
const pauseMock = this.mock(playbackService, 'pause')
|
||||
|
||||
const episode = factory('episode', {
|
||||
id: 'foo',
|
||||
playback_state: 'Playing'
|
||||
})
|
||||
|
||||
this.renderComponent(episode)
|
||||
|
||||
await this.user.click(screen.getByRole('button'))
|
||||
|
||||
expect(pauseMock).toHaveBeenCalled()
|
||||
})
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ new class extends UnitTestCase {
|
|||
const updateMock = this.mock(authService, 'updateProfile')
|
||||
const alertMock = this.mock(MessageToasterStub.value, 'success')
|
||||
|
||||
this.renderComponent(factory<User>('user', {
|
||||
this.renderComponent(factory('user', {
|
||||
avatar: 'https://gravatar.com/foo'
|
||||
}))
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private async renderComponent () {
|
||||
albumStore.state.albums = factory<Album>('album', 9)
|
||||
albumStore.state.albums = factory('album', 9)
|
||||
|
||||
this.render(AlbumListScreen, {
|
||||
global: {
|
||||
|
|
|
@ -40,7 +40,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('shows other albums from the same artist', async () => {
|
||||
const albums = factory<Album>('album', 3)
|
||||
const albums = factory('album', 3)
|
||||
albums.push(album)
|
||||
const fetchMock = this.mock(albumStore, 'fetchForArtist').mockResolvedValue(albums)
|
||||
await this.renderComponent()
|
||||
|
@ -57,7 +57,7 @@ new class extends UnitTestCase {
|
|||
private async renderComponent () {
|
||||
commonStore.state.uses_last_fm = true
|
||||
|
||||
album = factory<Album>('album', {
|
||||
album = factory('album', {
|
||||
id: 42,
|
||||
name: 'Led Zeppelin IV',
|
||||
artist_id: 123,
|
||||
|
@ -66,7 +66,7 @@ new class extends UnitTestCase {
|
|||
|
||||
const resolveAlbumMock = this.mock(albumStore, 'resolve').mockResolvedValue(album)
|
||||
|
||||
const songs = factory<Song>('song', 13)
|
||||
const songs = factory('song', 13)
|
||||
const fetchSongsMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(songs)
|
||||
|
||||
await this.router.activateRoute({
|
||||
|
|
|
@ -12,7 +12,7 @@ new class extends UnitTestCase {
|
|||
super.beforeEach(cb)
|
||||
commonStore.state.song_count = 420
|
||||
commonStore.state.song_length = 123_456
|
||||
songStore.state.songs = factory<Song>('song', 20)
|
||||
songStore.state.songs = factory('song', 20)
|
||||
this.be()
|
||||
}
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private async renderComponent () {
|
||||
artistStore.state.artists = factory<Artist>('artist', 9)
|
||||
artistStore.state.artists = factory('artist', 9)
|
||||
|
||||
const rendered = this.render(ArtistListScreen, {
|
||||
global: {
|
||||
|
|
|
@ -14,14 +14,14 @@ new class extends UnitTestCase {
|
|||
protected async renderComponent () {
|
||||
commonStore.state.uses_last_fm = true
|
||||
|
||||
artist = factory<Artist>('artist', {
|
||||
artist = factory('artist', {
|
||||
id: 42,
|
||||
name: 'Led Zeppelin',
|
||||
})
|
||||
|
||||
const resolveArtistMock = this.mock(artistStore, 'resolve').mockResolvedValue(artist)
|
||||
|
||||
const songs = factory<Song>('song', 13)
|
||||
const songs = factory('song', 13)
|
||||
const fetchSongsMock = this.mock(songStore, 'fetchForArtist').mockResolvedValue(songs)
|
||||
|
||||
await this.router.activateRoute({
|
||||
|
|
|
@ -8,7 +8,7 @@ import FavoritesScreen from './FavoritesScreen.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('renders a list of favorites', async () => {
|
||||
favoriteStore.state.songs = factory<Song>('song', 13)
|
||||
favoriteStore.state.songs = factory('song', 13)
|
||||
await this.renderComponent()
|
||||
|
||||
await waitFor(() => {
|
||||
|
|
|
@ -10,9 +10,9 @@ new class extends UnitTestCase {
|
|||
it('renders the list of genres and their song counts', async () => {
|
||||
// ensure there's no duplicated names
|
||||
const genres = [
|
||||
factory<Genre>('genre', { name: 'Rock', song_count: 10 }),
|
||||
factory<Genre>('genre', { name: 'Pop', song_count: 20 }),
|
||||
factory<Genre>('genre', { name: 'Jazz', song_count: 30 })
|
||||
factory('genre', { name: 'Rock', song_count: 10 }),
|
||||
factory('genre', { name: 'Pop', song_count: 20 }),
|
||||
factory('genre', { name: 'Jazz', song_count: 30 })
|
||||
]
|
||||
|
||||
const fetchMock = this.mock(genreStore, 'fetchAll').mockResolvedValue(genres)
|
||||
|
|
|
@ -14,8 +14,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('shuffles all songs without fetching if genre has <= 500 songs', async () => {
|
||||
const genre = factory<Genre>('genre', { song_count: 10 })
|
||||
const songs = factory<Song>('song', 10)
|
||||
const genre = factory('genre', { song_count: 10 })
|
||||
const songs = factory('song', 10)
|
||||
const playbackMock = this.mock(playbackService, 'queueAndPlay')
|
||||
|
||||
await this.renderComponent(genre, songs)
|
||||
|
@ -26,8 +26,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('fetches and shuffles all songs if genre has > 500 songs', async () => {
|
||||
const genre = factory<Genre>('genre', { song_count: 501 })
|
||||
const songs = factory<Song>('song', 10) // we don't really need to generate 501 songs
|
||||
const genre = factory('genre', { song_count: 501 })
|
||||
const songs = factory('song', 10) // we don't really need to generate 501 songs
|
||||
const playbackMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const fetchMock = this.mock(songStore, 'fetchRandomForGenre').mockResolvedValue(songs)
|
||||
|
||||
|
@ -43,12 +43,12 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private async renderComponent (genre?: Genre, songs?: Song[]) {
|
||||
genre = genre || factory<Genre>('genre')
|
||||
genre = genre || factory('genre')
|
||||
|
||||
const fetchGenreMock = this.mock(genreStore, 'fetchOne').mockResolvedValue(genre)
|
||||
const paginateMock = this.mock(songStore, 'paginateForGenre').mockResolvedValue({
|
||||
nextPage: 2,
|
||||
songs: songs || factory<Song>('song', 13)
|
||||
songs: songs || factory('song', 13)
|
||||
})
|
||||
|
||||
await this.router.activateRoute({
|
||||
|
|
|
@ -12,7 +12,7 @@ let playlist: Playlist
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('renders the playlist', async () => {
|
||||
await this.renderComponent(factory<Song>('song', 10))
|
||||
await this.renderComponent(factory('song', 10))
|
||||
|
||||
await waitFor(() => {
|
||||
screen.getByTestId('song-list')
|
||||
|
@ -31,7 +31,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('downloads the playlist', async () => {
|
||||
const downloadMock = this.mock(downloadService, 'fromPlaylist')
|
||||
await this.renderComponent(factory<Song>('song', 10))
|
||||
await this.renderComponent(factory('song', 10))
|
||||
|
||||
await this.tick(2)
|
||||
await this.user.click(screen.getByRole('button', { name: 'Download All' }))
|
||||
|
@ -58,7 +58,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private async renderComponent (songs: Song[]) {
|
||||
playlist = playlist || factory<Playlist>('playlist')
|
||||
playlist = playlist || factory('playlist')
|
||||
playlistStore.init([playlist])
|
||||
playlist.songs = songs
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import QueueScreen from './QueueScreen.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('renders the queue', () => {
|
||||
this.renderComponent(factory<Song>('song', 3))
|
||||
this.renderComponent(factory('song', 3))
|
||||
|
||||
expect(screen.queryByTestId('song-list')).toBeTruthy()
|
||||
expect(screen.queryByTestId('screen-empty-state')).toBeNull()
|
||||
|
@ -37,7 +37,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('Shuffles all', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
this.renderComponent(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import RecentlyPlayedScreen from './RecentlyPlayedScreen.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('displays the songs', async () => {
|
||||
await this.renderComponent(factory<Song>('song', 3))
|
||||
await this.renderComponent(factory('song', 3))
|
||||
|
||||
screen.getByTestId('song-list')
|
||||
expect(screen.queryByTestId('screen-empty-state')).toBeNull()
|
||||
|
|
|
@ -24,7 +24,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('displays a list of user prospects', async () => {
|
||||
const users = [...factory.states('prospect')<User>('user', 2), ...factory<User>('user', 3)]
|
||||
const users = [...factory.states('prospect')('user', 2), ...factory('user', 3)]
|
||||
await this.renderComponent(users)
|
||||
|
||||
expect(screen.getAllByTestId('user-card')).toHaveLength(5)
|
||||
|
@ -52,7 +52,7 @@ new class extends UnitTestCase {
|
|||
|
||||
private async renderComponent (users: User[] = []) {
|
||||
if (users.length === 0) {
|
||||
users = factory<User>('user', 6)
|
||||
users = factory('user', 6)
|
||||
}
|
||||
|
||||
const fetchMock = this.mock(http, 'get').mockResolvedValue(users)
|
||||
|
|
|
@ -7,7 +7,7 @@ import MostPlayedAlbums from './MostPlayedAlbums.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('displays the albums', () => {
|
||||
overviewStore.state.mostPlayedAlbums = factory<Album>('album', 6)
|
||||
overviewStore.state.mostPlayedAlbums = factory('album', 6)
|
||||
expect(this.render(MostPlayedAlbums, {
|
||||
global: {
|
||||
stubs: {
|
||||
|
|
|
@ -7,7 +7,7 @@ import MostPlayedArtists from './MostPlayedArtists.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('displays the artists', () => {
|
||||
overviewStore.state.mostPlayedArtists = factory<Artist>('artist', 6)
|
||||
overviewStore.state.mostPlayedArtists = factory('artist', 6)
|
||||
expect(this.render(MostPlayedArtists, {
|
||||
global: {
|
||||
stubs: {
|
||||
|
|
|
@ -7,7 +7,7 @@ import MostPlayedSongs from './MostPlayedSongs.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('displays the songs', () => {
|
||||
overviewStore.state.mostPlayedSongs = factory<Song>('song', 6)
|
||||
overviewStore.state.mostPlayedSongs = factory('song', 6)
|
||||
expect(this.render(MostPlayedSongs, {
|
||||
global: {
|
||||
stubs: {
|
||||
|
|
|
@ -7,7 +7,7 @@ import RecentlyAddedAlbums from './RecentlyAddedAlbums.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('displays the albums', () => {
|
||||
overviewStore.state.recentlyAddedAlbums = factory<Album>('album', 6)
|
||||
overviewStore.state.recentlyAddedAlbums = factory('album', 6)
|
||||
expect(this.render(RecentlyAddedAlbums, {
|
||||
global: {
|
||||
stubs: {
|
||||
|
|
|
@ -7,7 +7,7 @@ import RecentlyAddedSongs from './RecentlyAddedSongs.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('displays the songs', () => {
|
||||
overviewStore.state.recentlyAddedSongs = factory<Song>('song', 6)
|
||||
overviewStore.state.recentlyAddedSongs = factory('song', 6)
|
||||
expect(this.render(RecentlyAddedSongs, {
|
||||
global: {
|
||||
stubs: {
|
||||
|
|
|
@ -9,7 +9,7 @@ import RecentlyPlayedSongs from './RecentlyPlayedSongs.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('displays the songs', () => {
|
||||
overviewStore.state.recentlyPlayed = factory<Song>('song', 6)
|
||||
overviewStore.state.recentlyPlayed = factory('song', 6)
|
||||
expect(this.render(RecentlyPlayedSongs, {
|
||||
global: {
|
||||
stubs: {
|
||||
|
|
|
@ -19,9 +19,9 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('renders', () => {
|
||||
playlistStore.state.playlists = [
|
||||
factory<Playlist>('playlist', { name: 'Foo' }),
|
||||
factory<Playlist>('playlist', { name: 'Bar' }),
|
||||
factory<Playlist>('playlist', { name: 'Baz' })
|
||||
factory('playlist', { name: 'Foo' }),
|
||||
factory('playlist', { name: 'Bar' }),
|
||||
factory('playlist', { name: 'Baz' })
|
||||
]
|
||||
|
||||
expect(this.renderComponent().html()).toMatchSnapshot()
|
||||
|
@ -40,7 +40,7 @@ new class extends UnitTestCase {
|
|||
['to top', 'queue-top', 'queueToTop'],
|
||||
['to bottom', 'queue-bottom', 'queue']
|
||||
])('queues songs %s', async (_: string, testId: string, queueMethod: MethodOf<typeof queueStore>) => {
|
||||
queueStore.state.playables = factory<Song>('song', 5)
|
||||
queueStore.state.playables = factory('song', 5)
|
||||
queueStore.state.playables[2].playback_state = 'Playing'
|
||||
|
||||
const mock = this.mock(queueStore, queueMethod)
|
||||
|
@ -62,7 +62,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('adds songs to existing playlist', async () => {
|
||||
const mock = this.mock(playlistStore, 'addContent')
|
||||
playlistStore.state.playlists = factory<Playlist>('playlist', 3)
|
||||
playlistStore.state.playlists = factory('playlist', 3)
|
||||
this.renderComponent()
|
||||
|
||||
await this.user.click(screen.getAllByTestId('add-to-playlist')[1])
|
||||
|
@ -81,7 +81,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private renderComponent (customConfig: Partial<AddToMenuConfig> = {}) {
|
||||
songs = factory<Song>('song', 5)
|
||||
songs = factory('song', 5)
|
||||
|
||||
return this.render(AddToMenu, {
|
||||
props: {
|
||||
|
|
|
@ -28,7 +28,7 @@ new class extends UnitTestCase {
|
|||
const emitMock = this.mock(eventBus, 'emit')
|
||||
const alertMock = this.mock(MessageToasterStub.value, 'success')
|
||||
|
||||
const { html } = await this.renderComponent(factory<Song>('song', {
|
||||
const { html } = await this.renderComponent(factory('song', {
|
||||
title: 'Rocket to Heaven',
|
||||
artist_name: 'Led Zeppelin',
|
||||
album_name: 'IV',
|
||||
|
@ -81,7 +81,7 @@ new class extends UnitTestCase {
|
|||
const emitMock = this.mock(eventBus, 'emit')
|
||||
const alertMock = this.mock(MessageToasterStub.value, 'success')
|
||||
|
||||
const { html } = await this.renderComponent(factory<Song>('song', 3))
|
||||
const { html } = await this.renderComponent(factory('song', 3))
|
||||
|
||||
expect(html()).toMatchSnapshot()
|
||||
expect(screen.queryByTestId('title-input')).toBeNull()
|
||||
|
@ -112,7 +112,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('displays artist name if all songs have the same artist', async () => {
|
||||
await this.renderComponent(factory<Song>('song', 4, {
|
||||
await this.renderComponent(factory('song', 4, {
|
||||
artist_id: 1000,
|
||||
artist_name: 'Led Zeppelin',
|
||||
album_id: 1001,
|
||||
|
|
|
@ -20,7 +20,7 @@ new class extends UnitTestCase {
|
|||
it('queues and plays', async () => {
|
||||
const queueMock = this.mock(queueStore, 'queueIfNotQueued')
|
||||
const playMock = this.mock(playbackService, 'play')
|
||||
const song = factory<Song>('song', { playback_state: 'Stopped' })
|
||||
const song = factory('song', { playback_state: 'Stopped' })
|
||||
await this.renderComponent(song)
|
||||
|
||||
await this.user.click(screen.getByText('Play'))
|
||||
|
@ -31,7 +31,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('pauses playback', async () => {
|
||||
const pauseMock = this.mock(playbackService, 'pause')
|
||||
await this.renderComponent(factory<Song>('song', { playback_state: 'Playing' }))
|
||||
await this.renderComponent(factory('song', { playback_state: 'Playing' }))
|
||||
|
||||
await this.user.click(screen.getByText('Pause'))
|
||||
|
||||
|
@ -40,7 +40,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('resumes playback', async () => {
|
||||
const resumeMock = this.mock(playbackService, 'resume')
|
||||
await this.renderComponent(factory<Song>('song', { playback_state: 'Paused' }))
|
||||
await this.renderComponent(factory('song', { playback_state: 'Paused' }))
|
||||
|
||||
await this.user.click(screen.getByText('Play'))
|
||||
|
||||
|
@ -49,7 +49,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('goes to album details screen', async () => {
|
||||
const goMock = this.mock(Router, 'go')
|
||||
await this.renderComponent(factory<Song>('song'))
|
||||
await this.renderComponent(factory('song'))
|
||||
|
||||
await this.user.click(screen.getByText('Go to Album'))
|
||||
|
||||
|
@ -58,7 +58,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('goes to artist details screen', async () => {
|
||||
const goMock = this.mock(Router, 'go')
|
||||
await this.renderComponent(factory<Song>('song'))
|
||||
await this.renderComponent(factory('song'))
|
||||
|
||||
await this.user.click(screen.getByText('Go to Artist'))
|
||||
|
||||
|
@ -178,7 +178,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('lists and adds to existing playlist', async () => {
|
||||
playlistStore.state.playlists = factory<Playlist>('playlist', 3)
|
||||
playlistStore.state.playlists = factory('playlist', 3)
|
||||
const addMock = this.mock(playlistStore, 'addContent')
|
||||
this.mock(MessageToasterStub.value, 'success')
|
||||
await this.renderComponent()
|
||||
|
@ -191,8 +191,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('does not list smart playlists', async () => {
|
||||
playlistStore.state.playlists = factory<Playlist>('playlist', 3)
|
||||
playlistStore.state.playlists.push(factory.states('smart')<Playlist>('playlist', { name: 'My Smart Playlist' }))
|
||||
playlistStore.state.playlists = factory('playlist', 3)
|
||||
playlistStore.state.playlists.push(factory.states('smart')('playlist', { name: 'My Smart Playlist' }))
|
||||
|
||||
await this.renderComponent()
|
||||
|
||||
|
@ -200,7 +200,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('removes from playlist', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const playlist = factory('playlist')
|
||||
playlistStore.state.playlists.push(playlist)
|
||||
|
||||
await this.router.activateRoute({
|
||||
|
@ -248,21 +248,21 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('has an option to copy shareable URL in Community edition', async () => {
|
||||
await this.renderComponent(factory<Song>('song'))
|
||||
await this.renderComponent(factory('song'))
|
||||
screen.getByText('Copy Shareable URL')
|
||||
})
|
||||
|
||||
it('has an option to copy shareable URL if song is public in Plus edition', async () => {
|
||||
this.enablePlusEdition()
|
||||
|
||||
await this.renderComponent(factory<Song>('song', { is_public: true }))
|
||||
await this.renderComponent(factory('song', { is_public: true }))
|
||||
screen.getByText('Copy Shareable URL')
|
||||
})
|
||||
|
||||
it('does not have an option to share if song is private in Plus edition', async () => {
|
||||
this.enablePlusEdition()
|
||||
|
||||
await this.renderComponent(factory<Song>('song', { is_public: false }))
|
||||
await this.renderComponent(factory('song', { is_public: false }))
|
||||
expect(screen.queryByText('Copy Shareable URL')).toBeNull()
|
||||
})
|
||||
|
||||
|
@ -303,8 +303,8 @@ new class extends UnitTestCase {
|
|||
it('makes songs private', async () => {
|
||||
this.enablePlusEdition()
|
||||
|
||||
const user = factory<User>('user')
|
||||
const songs = factory<Song>('song', 5, {
|
||||
const user = factory('user')
|
||||
const songs = factory('song', 5, {
|
||||
is_public: true,
|
||||
owner_id: user.id
|
||||
})
|
||||
|
@ -320,8 +320,8 @@ new class extends UnitTestCase {
|
|||
it('makes songs public', async () => {
|
||||
this.enablePlusEdition()
|
||||
|
||||
const user = factory<User>('user')
|
||||
const songs = factory<Song>('song', 5, {
|
||||
const user = factory('user')
|
||||
const songs = factory('song', 5, {
|
||||
is_public: false,
|
||||
owner_id: user.id
|
||||
})
|
||||
|
@ -337,9 +337,9 @@ new class extends UnitTestCase {
|
|||
it('does not have an option to make songs public or private if current user is not owner', async () => {
|
||||
this.enablePlusEdition()
|
||||
|
||||
const user = factory<User>('user')
|
||||
const owner = factory<User>('user')
|
||||
const songs = factory<Song>('song', 5, {
|
||||
const user = factory('user')
|
||||
const owner = factory('user')
|
||||
const songs = factory('song', 5, {
|
||||
is_public: false,
|
||||
owner_id: owner.id
|
||||
})
|
||||
|
@ -353,11 +353,11 @@ new class extends UnitTestCase {
|
|||
it('has both options to make public and private if songs have mixed visibilities', async () => {
|
||||
this.enablePlusEdition()
|
||||
|
||||
const owner = factory<User>('user')
|
||||
const songs = factory<Song>('song', 2, {
|
||||
const owner = factory('user')
|
||||
const songs = factory('song', 2, {
|
||||
is_public: false,
|
||||
owner_id: owner.id
|
||||
}).concat(...factory<Song>('song', 3, {
|
||||
}).concat(...factory('song', 3, {
|
||||
is_public: true,
|
||||
owner_id: owner.id
|
||||
}))
|
||||
|
@ -369,8 +369,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('does not have an option to make songs public or private or Community edition', async () => {
|
||||
const owner = factory<User>('user')
|
||||
const songs = factory<Song>('song', 5, {
|
||||
const owner = factory('user')
|
||||
const songs = factory('song', 5, {
|
||||
is_public: false,
|
||||
owner_id: owner.id
|
||||
})
|
||||
|
@ -383,7 +383,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private async renderComponent (_songs?: Song | Song[]) {
|
||||
songs = arrayify(_songs || factory<Song>('song', 5))
|
||||
songs = arrayify(_songs || factory('song', 5))
|
||||
|
||||
const rendered = this.render(PlayableContextMenu)
|
||||
eventBus.emit('PLAYABLE_CONTEXT_MENU_REQUESTED', { pageX: 420, pageY: 42 } as MouseEvent, songs)
|
||||
|
@ -393,7 +393,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private fillQueue () {
|
||||
queueStore.state.playables = factory<Song>('song', 5)
|
||||
queueStore.state.playables = factory('song', 5)
|
||||
queueStore.state.playables[2].playback_state = 'Playing'
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private renderComponent (playbackState: PlaybackState = 'Stopped') {
|
||||
song = factory<Song>('song', {
|
||||
song = factory('song', {
|
||||
playback_state: playbackState,
|
||||
play_count: 10,
|
||||
title: 'Foo bar'
|
||||
|
|
|
@ -12,7 +12,7 @@ new class extends UnitTestCase {
|
|||
['Like Foo by Bar', false]
|
||||
])('%s', async (name: string, liked: boolean) => {
|
||||
const mock = this.mock(favoriteStore, 'toggleOne')
|
||||
const song = factory<Song>('song', {
|
||||
const song = factory('song', {
|
||||
liked,
|
||||
title: 'Foo',
|
||||
artist_name: 'Bar'
|
||||
|
|
|
@ -19,7 +19,7 @@ let songs: Playable[]
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('renders', async () => {
|
||||
const { html } = await this.renderComponent(factory<Song>('song', 5))
|
||||
const { html } = await this.renderComponent(factory('song', 5))
|
||||
expect(html()).toMatchSnapshot()
|
||||
})
|
||||
|
||||
|
@ -29,7 +29,7 @@ new class extends UnitTestCase {
|
|||
['album_name', 'header-album'],
|
||||
['length', 'header-length']
|
||||
])('sorts by %s upon %s clicked', async (field, testId) => {
|
||||
const { emitted } = await this.renderComponent(factory<Song>('song', 5))
|
||||
const { emitted } = await this.renderComponent(factory('song', 5))
|
||||
|
||||
await this.user.click(screen.getByTestId(testId))
|
||||
expect(emitted().sort[0]).toEqual([field, 'desc'])
|
||||
|
@ -39,7 +39,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('cannot be sorted if configured so', async () => {
|
||||
const { emitted } = await this.renderComponent(factory<Song>('song', 5), {
|
||||
const { emitted } = await this.renderComponent(factory('song', 5), {
|
||||
sortable: false,
|
||||
reorderable: true
|
||||
})
|
||||
|
|
|
@ -63,7 +63,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private renderComponent (selectedSongCount = 1, configOverrides: Partial<SongListControlsConfig> = {}) {
|
||||
const songs = factory<Song>('song', 5)
|
||||
const songs = factory('song', 5)
|
||||
const config: SongListControlsConfig = merge({
|
||||
addTo: {
|
||||
queue: true,
|
||||
|
|
|
@ -9,7 +9,7 @@ let row: PlayableRow
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('renders', async () => {
|
||||
const song = factory<Song>('song', {
|
||||
const song = factory('song', {
|
||||
title: 'Test Song',
|
||||
album_name: 'Test Album',
|
||||
artist_name: 'Test Artist',
|
||||
|
@ -32,7 +32,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private renderComponent (song?: Song) {
|
||||
song = song ?? factory<Song>('song')
|
||||
song = song ?? factory('song')
|
||||
|
||||
row = {
|
||||
playable: song,
|
||||
|
|
|
@ -26,7 +26,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private renderComponent (playbackState: PlaybackState = 'Stopped') {
|
||||
song = factory<Song>('song', {
|
||||
song = factory('song', {
|
||||
playback_state: playbackState,
|
||||
play_count: 10,
|
||||
title: 'Foo bar'
|
||||
|
|
|
@ -13,7 +13,7 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('toggles the playback of current song', async () => {
|
||||
const toggleMock = this.mock(playbackService, 'toggle')
|
||||
this.renderComponent(factory<Song>('song'))
|
||||
this.renderComponent(factory('song'))
|
||||
|
||||
await this.user.click(screen.getByRole('button'))
|
||||
|
||||
|
@ -26,7 +26,7 @@ new class extends UnitTestCase {
|
|||
['Playlist', 'fetchForPlaylist', '71d8cd40-20d4-4b17-b460-d30fe5bb7b66']
|
||||
])('initiates playback for %s screen', async (screenName, fetchMethod, id) => {
|
||||
commonStore.state.song_count = 10
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
const fetchMock = this.mock(songStore, fetchMethod).mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const goMock = this.mock(Router, 'go')
|
||||
|
@ -55,7 +55,7 @@ new class extends UnitTestCase {
|
|||
['RecentlyPlayed', recentlyPlayedStore, 'fetch']
|
||||
])('initiates playback for %s screen', async (screenName, store, fetchMethod) => {
|
||||
commonStore.state.song_count = 10
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
const fetchMock = this.mock(store, fetchMethod).mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const goMock = this.mock(Router, 'go')
|
||||
|
@ -77,7 +77,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it.each<[ScreenName]>([['Queue'], ['Songs'], ['Albums']])('initiates playback %s screen', async screenName => {
|
||||
commonStore.state.song_count = 10
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
const fetchMock = this.mock(queueStore, 'fetchRandom').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
const goMock = this.mock(Router, 'go')
|
||||
|
|
|
@ -11,7 +11,7 @@ new class extends UnitTestCase {
|
|||
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', { lyrics: null })
|
||||
|
||||
const mock = this.mock(eventBus, 'emit')
|
||||
this.beAdmin().renderComponent(song)
|
||||
|
@ -22,13 +22,13 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('does not have a button to add lyrics if current user is not an admin', async () => {
|
||||
this.be().renderComponent(factory<Song>('song', { lyrics: null }))
|
||||
this.be().renderComponent(factory('song', { lyrics: null }))
|
||||
expect(screen.queryByRole('button', { name: 'Click here' })).toBeNull()
|
||||
})
|
||||
}
|
||||
|
||||
private renderComponent (song?: Song) {
|
||||
song = song || factory<Song>('song', {
|
||||
song = song || factory('song', {
|
||||
lyrics: 'Foo bar baz qux'
|
||||
})
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import ProfileAvatar from './ProfileAvatar.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('renders', () => {
|
||||
const user = factory<User>('user', {
|
||||
const user = factory('user', {
|
||||
name: 'John Doe',
|
||||
avatar: 'https://example.com/avatar.jpg'
|
||||
})
|
||||
|
|
|
@ -9,7 +9,7 @@ new class extends UnitTestCase {
|
|||
it('emits events on user actions', async () => {
|
||||
const { emitted } = this.render(ArtistAlbumCard, {
|
||||
props: {
|
||||
entity: factory<Album>('album')
|
||||
entity: factory('album')
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('plays album', async () => {
|
||||
const songs = factory<Song>('song', 10)
|
||||
const songs = factory('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
this.renderForAlbum()
|
||||
|
@ -35,7 +35,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('queues album', async () => {
|
||||
const songs = factory<Song>('song', 10)
|
||||
const songs = factory('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForAlbum').mockResolvedValue(songs)
|
||||
const queueMock = this.mock(queueStore, 'queue')
|
||||
this.renderForAlbum()
|
||||
|
@ -51,7 +51,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('plays artist', async () => {
|
||||
const songs = factory<Song>('song', 10)
|
||||
const songs = factory('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForArtist').mockResolvedValue(songs)
|
||||
const playMock = this.mock(playbackService, 'queueAndPlay')
|
||||
this.renderForArtist()
|
||||
|
@ -65,7 +65,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('queues artist', async () => {
|
||||
const songs = factory<Song>('song', 10)
|
||||
const songs = factory('song', 10)
|
||||
const fetchMock = this.mock(songStore, 'fetchForArtist').mockResolvedValue(songs)
|
||||
const queueMock = this.mock(queueStore, 'queue')
|
||||
this.renderForArtist()
|
||||
|
@ -82,7 +82,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private renderForAlbum () {
|
||||
album = factory<Album>('album', {
|
||||
album = factory('album', {
|
||||
name: 'IV',
|
||||
cover: 'https://test/album.jpg'
|
||||
})
|
||||
|
@ -95,7 +95,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private renderForArtist () {
|
||||
artist = factory<Artist>('artist', {
|
||||
artist = factory('artist', {
|
||||
name: 'Led Zeppelin',
|
||||
image: 'https://test/blimp.jpg'
|
||||
})
|
||||
|
|
|
@ -10,14 +10,14 @@ import YouTubeVideoList from './YouTubeVideoList.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('functions', async () => {
|
||||
const song = factory<Song>('song')
|
||||
const song = factory('song')
|
||||
|
||||
const searchMock = this.mock(youTubeService, 'searchVideosBySong').mockResolvedValueOnce({
|
||||
nextPageToken: 'foo',
|
||||
items: factory<YouTubeVideo>('video', 5)
|
||||
items: factory('video', 5)
|
||||
}).mockResolvedValueOnce({
|
||||
nextPageToken: 'bar',
|
||||
items: factory<YouTubeVideo>('video', 3)
|
||||
items: factory('video', 3)
|
||||
})
|
||||
|
||||
this.render(YouTubeVideoList, {
|
||||
|
|
|
@ -14,7 +14,7 @@ new class extends UnitTestCase {
|
|||
const updateMock = this.mock(userStore, 'update')
|
||||
const alertMock = this.mock(MessageToasterStub.value, 'success')
|
||||
|
||||
const user = ref(factory<User>('user', { name: 'John Doe' }))
|
||||
const user = ref(factory('user', { name: 'John Doe' }))
|
||||
|
||||
this.render(EditUserForm, {
|
||||
global: {
|
||||
|
|
|
@ -12,7 +12,7 @@ import UserCard from './UserCard.vue'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('has different behaviors for current user', () => {
|
||||
const user = factory<User>('user')
|
||||
const user = factory('user')
|
||||
this.be(user).renderComponent(user)
|
||||
|
||||
screen.getByTitle('This is you!')
|
||||
|
@ -20,7 +20,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('edits user', async () => {
|
||||
const user = factory<User>('user')
|
||||
const user = factory('user')
|
||||
const emitMock = this.mock(eventBus, 'emit')
|
||||
this.renderComponent(user)
|
||||
|
||||
|
@ -31,7 +31,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('redirects to Profile screen if edit current user', async () => {
|
||||
const mock = this.mock(Router, 'go')
|
||||
const user = factory<User>('user')
|
||||
const user = factory('user')
|
||||
this.be(user).renderComponent(user)
|
||||
|
||||
await this.user.click(screen.getByRole('button', { name: 'Your Profile' }))
|
||||
|
@ -41,7 +41,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('deletes user if confirmed', async () => {
|
||||
this.mock(DialogBoxStub.value, 'confirm').mockResolvedValue(true)
|
||||
const user = factory<User>('user')
|
||||
const user = factory('user')
|
||||
this.beAdmin().renderComponent(user)
|
||||
const destroyMock = this.mock(userStore, 'destroy')
|
||||
|
||||
|
@ -52,7 +52,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('does not delete user if not confirmed', async () => {
|
||||
this.mock(DialogBoxStub.value, 'confirm').mockResolvedValue(false)
|
||||
const user = factory<User>('user')
|
||||
const user = factory('user')
|
||||
this.beAdmin().renderComponent(user)
|
||||
const destroyMock = this.mock(userStore, 'destroy')
|
||||
|
||||
|
@ -63,7 +63,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('revokes invite for prospects', async () => {
|
||||
this.mock(DialogBoxStub.value, 'confirm').mockResolvedValue(true)
|
||||
const prospect = factory.states('prospect')<User>('user')
|
||||
const prospect = factory.states('prospect')('user')
|
||||
this.beAdmin().renderComponent(prospect)
|
||||
const revokeMock = this.mock(invitationService, 'revoke')
|
||||
|
||||
|
@ -74,7 +74,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('does not revoke invite for prospects if not confirmed', async () => {
|
||||
this.mock(DialogBoxStub.value, 'confirm').mockResolvedValue(false)
|
||||
const prospect = factory.states('prospect')<User>('user')
|
||||
const prospect = factory.states('prospect')('user')
|
||||
this.beAdmin().renderComponent(prospect)
|
||||
const revokeMock = this.mock(invitationService, 'revoke')
|
||||
|
||||
|
|
|
@ -56,13 +56,13 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('updates profile', async () => {
|
||||
userStore.state.current = factory<User>('user', {
|
||||
userStore.state.current = factory('user', {
|
||||
id: 1,
|
||||
name: 'John Doe',
|
||||
email: 'john@doe.com'
|
||||
})
|
||||
|
||||
const updated = factory<User>('user', {
|
||||
const updated = factory('user', {
|
||||
id: 1,
|
||||
name: 'Jane Doe',
|
||||
email: 'jane@doe.com'
|
||||
|
|
|
@ -8,35 +8,35 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('downloads songs', () => {
|
||||
const mock = this.mock(downloadService, 'trigger')
|
||||
downloadService.fromPlayables([factory<Song>('song', { id: 'foo' }), factory<Song>('song', { id: 'bar' })])
|
||||
downloadService.fromPlayables([factory('song', { id: 'bar' })])
|
||||
|
||||
expect(mock).toHaveBeenCalledWith('songs?songs[]=bar&songs[]=foo&')
|
||||
})
|
||||
|
||||
it('downloads all by artist', () => {
|
||||
const mock = this.mock(downloadService, 'trigger')
|
||||
downloadService.fromArtist(factory<Artist>('artist', { id: 42 }))
|
||||
downloadService.fromArtist(factory('artist', { id: 42 }))
|
||||
|
||||
expect(mock).toHaveBeenCalledWith('artist/42')
|
||||
})
|
||||
|
||||
it('downloads all in album', () => {
|
||||
const mock = this.mock(downloadService, 'trigger')
|
||||
downloadService.fromAlbum(factory<Album>('album', { id: 42 }))
|
||||
downloadService.fromAlbum(factory('album', { id: 42 }))
|
||||
|
||||
expect(mock).toHaveBeenCalledWith('album/42')
|
||||
})
|
||||
|
||||
it('downloads a playlist', () => {
|
||||
const mock = this.mock(downloadService, 'trigger')
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const playlist = factory('playlist')
|
||||
|
||||
downloadService.fromPlaylist(playlist)
|
||||
|
||||
expect(mock).toHaveBeenCalledWith(`playlist/${playlist.id}`)
|
||||
})
|
||||
|
||||
it.each<[Song[], boolean]>([[[], false], [factory<Song>('song', 5), true]])(
|
||||
it.each<[Song[], boolean]>([[[], false], [factory('song', 5), true]])(
|
||||
'downloads favorites if available',
|
||||
(songs, triggered) => {
|
||||
const mock = this.mock(downloadService, 'trigger')
|
||||
|
|
|
@ -29,7 +29,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('invites users', async () => {
|
||||
const prospects = factory.states('prospect')<User>('user', 2)
|
||||
const prospects = factory.states('prospect')('user', 2)
|
||||
const addMock = this.mock(userStore, 'add')
|
||||
const postMock = this.mock(http, 'post').mockResolvedValue(prospects)
|
||||
|
||||
|
@ -44,7 +44,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('revokes an invitation', async () => {
|
||||
const user = factory.states('prospect')<User>('user')
|
||||
const user = factory.states('prospect')('user')
|
||||
const removeMock = this.mock(userStore, 'remove')
|
||||
const deleteMock = this.mock(http, 'delete')
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ import { mediaInfoService } from './mediaInfoService'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('fetches the artist info', async () => {
|
||||
const artist = artistStore.syncWithVault(factory<Artist>('artist', { id: 42 }))[0]
|
||||
const artistInfo = factory<ArtistInfo>('artist-info')
|
||||
const artist = artistStore.syncWithVault(factory('artist', { id: 42 }))[0]
|
||||
const artistInfo = factory('artist-info')
|
||||
const getMock = this.mock(http, 'get').mockResolvedValue(artistInfo)
|
||||
const hasCacheMock = this.mock(cache, 'has', false)
|
||||
const setCacheMock = this.mock(cache, 'set')
|
||||
|
@ -23,20 +23,20 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('gets the artist info from cache', async () => {
|
||||
const artistInfo = factory<ArtistInfo>('artist-info')
|
||||
const artistInfo = factory('artist-info')
|
||||
const hasCacheMock = this.mock(cache, 'has', true)
|
||||
const getCacheMock = this.mock(cache, 'get', artistInfo)
|
||||
const getMock = this.mock(http, 'get')
|
||||
|
||||
expect(await mediaInfoService.fetchForArtist(factory<Artist>('artist', { id: 42 }))).toBe(artistInfo)
|
||||
expect(await mediaInfoService.fetchForArtist(factory('artist', { id: 42 }))).toBe(artistInfo)
|
||||
expect(hasCacheMock).toHaveBeenCalledWith(['artist.info', 42])
|
||||
expect(getCacheMock).toHaveBeenCalledWith(['artist.info', 42])
|
||||
expect(getMock).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('fetches the album info', async () => {
|
||||
const album = albumStore.syncWithVault(factory<Album>('album', { id: 42 }))[0]
|
||||
const albumInfo = factory<AlbumInfo>('album-info')
|
||||
const album = albumStore.syncWithVault(factory('album', { id: 42 }))[0]
|
||||
const albumInfo = factory('album-info')
|
||||
const getMock = this.mock(http, 'get').mockResolvedValue(albumInfo)
|
||||
const hasCacheMock = this.mock(cache, 'has', false)
|
||||
const setCacheMock = this.mock(cache, 'set')
|
||||
|
@ -50,12 +50,12 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('gets the album info from cache', async () => {
|
||||
const albumInfo = factory<AlbumInfo>('album-info')
|
||||
const albumInfo = factory('album-info')
|
||||
const hasCacheMock = this.mock(cache, 'has', true)
|
||||
const getCacheMock = this.mock(cache, 'get', albumInfo)
|
||||
const getMock = this.mock(http, 'get')
|
||||
|
||||
expect(await mediaInfoService.fetchForAlbum(factory<Album>('album', { id: 42 }))).toBe(albumInfo)
|
||||
expect(await mediaInfoService.fetchForAlbum(factory('album', { id: 42 }))).toBe(albumInfo)
|
||||
expect(hasCacheMock).toHaveBeenCalledWith(['album.info', 42])
|
||||
expect(getCacheMock).toHaveBeenCalledWith(['album.info', 42])
|
||||
expect(getMock).not.toHaveBeenCalled()
|
||||
|
|
|
@ -41,7 +41,7 @@ new class extends UnitTestCase {
|
|||
])(
|
||||
'when playCountRegistered is %s, isTranscoding is %s, current media time is %d, media duration is %d, then registerPlay() should be call %d times',
|
||||
(playCountRegistered, isTranscoding, currentTime, duration, numberOfCalls) => {
|
||||
const song = factory<Song>('song', {
|
||||
const song = factory('song', {
|
||||
play_count_registered: playCountRegistered,
|
||||
playback_state: 'Playing'
|
||||
})
|
||||
|
@ -78,7 +78,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('scrobbles if current song ends', () => {
|
||||
commonStore.state.uses_last_fm = true
|
||||
userStore.state.current = reactive(factory<User>('user', {
|
||||
userStore.state.current = reactive(factory('user', {
|
||||
preferences: {
|
||||
lastfm_session_key: 'foo'
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ new class extends UnitTestCase {
|
|||
(preloaded, isTranscoding, currentTime, duration, numberOfCalls) => {
|
||||
this.mock(playbackService, 'registerPlay')
|
||||
|
||||
this.setReadOnlyProperty(queueStore, 'next', factory<Song>('song', { preloaded }))
|
||||
this.setReadOnlyProperty(queueStore, 'next', factory('song', { preloaded }))
|
||||
this.setReadOnlyProperty(playbackService, 'isTranscoding', isTranscoding)
|
||||
playbackService.init(document.querySelector('.plyr')!)
|
||||
|
||||
|
@ -136,7 +136,7 @@ new class extends UnitTestCase {
|
|||
it('registers play', () => {
|
||||
const recentlyPlayedStoreAddMock = this.mock(recentlyPlayedStore, 'add')
|
||||
const registerPlayMock = this.mock(songStore, 'registerPlay')
|
||||
const song = factory<Song>('song')
|
||||
const song = factory('song')
|
||||
|
||||
playbackService.registerPlay(song)
|
||||
|
||||
|
@ -155,7 +155,7 @@ new class extends UnitTestCase {
|
|||
|
||||
const createElementMock = this.mock(document, 'createElement', audioElement)
|
||||
this.mock(songStore, 'getSourceUrl').mockReturnValue('/foo?token=o5afd')
|
||||
const song = factory<Song>('song')
|
||||
const song = factory('song')
|
||||
|
||||
playbackService.preload(song)
|
||||
|
||||
|
@ -298,7 +298,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('resumes playback', async () => {
|
||||
const song = this.setCurrentSong(factory<Song>('song', {
|
||||
const song = this.setCurrentSong(factory('song', {
|
||||
playback_state: 'Paused'
|
||||
}))
|
||||
|
||||
|
@ -329,7 +329,7 @@ new class extends UnitTestCase {
|
|||
])('%ss playback if toggled when current song playback state is %s', async (action, playbackState) => {
|
||||
playbackService.init(document.querySelector('.plyr')!)
|
||||
|
||||
this.setCurrentSong(factory<Song>('song', { playback_state: playbackState }))
|
||||
this.setCurrentSong(factory('song', { playback_state: playbackState }))
|
||||
const actionMock = this.mock(playbackService, action)
|
||||
await playbackService.toggle()
|
||||
|
||||
|
@ -339,7 +339,7 @@ new class extends UnitTestCase {
|
|||
it('queues and plays songs without shuffling', async () => {
|
||||
playbackService.init(document.querySelector('.plyr')!)
|
||||
|
||||
const songs = factory<Song>('song', 5)
|
||||
const songs = factory('song', 5)
|
||||
const replaceQueueMock = this.mock(queueStore, 'replaceQueueWith')
|
||||
const playMock = this.mock(playbackService, 'play')
|
||||
const firstSongInQueue = songs[0]
|
||||
|
@ -357,8 +357,8 @@ new class extends UnitTestCase {
|
|||
it('queues and plays songs with shuffling', async () => {
|
||||
playbackService.init(document.querySelector('.plyr')!)
|
||||
|
||||
const songs = factory<Song>('song', 5)
|
||||
const shuffledSongs = factory<Song>('song', 5)
|
||||
const songs = factory('song', 5)
|
||||
const shuffledSongs = factory('song', 5)
|
||||
const replaceQueueMock = this.mock(queueStore, 'replaceQueueWith')
|
||||
const playMock = this.mock(playbackService, 'play')
|
||||
const firstSongInQueue = songs[0]
|
||||
|
@ -376,7 +376,7 @@ new class extends UnitTestCase {
|
|||
it('plays first song in queue', async () => {
|
||||
playbackService.init(document.querySelector('.plyr')!)
|
||||
|
||||
const songs = factory<Song>('song', 5)
|
||||
const songs = factory('song', 5)
|
||||
queueStore.state.playables = songs
|
||||
this.setReadOnlyProperty(queueStore, 'first', songs[0])
|
||||
const playMock = this.mock(playbackService, 'play')
|
||||
|
@ -400,7 +400,7 @@ new class extends UnitTestCase {
|
|||
}
|
||||
|
||||
private setCurrentSong (song?: Song) {
|
||||
song = reactive(song || factory<Song>('song', {
|
||||
song = reactive(song || factory('song', {
|
||||
playback_state: 'Playing'
|
||||
}))
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import { playlistCollaborationService as service } from './playlistCollaboration
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('creates invite link', async () => {
|
||||
const playlist = factory<Playlist>('playlist', { is_smart: false })
|
||||
const playlist = factory('playlist', { is_smart: false })
|
||||
const postMock = this.mock(http, 'post').mockResolvedValue({ token: 'abc123' })
|
||||
|
||||
const link = await service.createInviteLink(playlist)
|
||||
|
@ -17,7 +17,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('throws if trying to create invite link for smart playlist', async () => {
|
||||
const playlist = factory<Playlist>('playlist', { is_smart: true })
|
||||
const playlist = factory('playlist', { is_smart: true })
|
||||
|
||||
await expect(service.createInviteLink(playlist)).rejects.toThrow('Smart playlists are not collaborative.')
|
||||
})
|
||||
|
@ -31,8 +31,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('fetches collaborators', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const collaborators = factory<PlaylistCollaborator[]>('playlist-collaborator', 2)
|
||||
const playlist = factory('playlist')
|
||||
const collaborators = factory('playlist-collaborator', 2)
|
||||
const getMock = this.mock(http, 'get').mockResolvedValue(collaborators)
|
||||
|
||||
const received = await service.fetchCollaborators(playlist)
|
||||
|
@ -42,8 +42,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('removes collaborator', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const collaborator = factory<PlaylistCollaborator>('playlist-collaborator')
|
||||
const playlist = factory('playlist')
|
||||
const collaborator = factory('playlist-collaborator')
|
||||
const deleteMock = this.mock(http, 'delete').mockResolvedValue({})
|
||||
const removeCacheMock = this.mock(cache, 'remove')
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import { youTubeService } from './youTubeService'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('plays a video', () => {
|
||||
const video = factory<YouTubeVideo>('video', {
|
||||
const video = factory('video', {
|
||||
id: {
|
||||
videoId: 'foo'
|
||||
},
|
||||
|
|
|
@ -14,13 +14,13 @@ new class extends UnitTestCase {
|
|||
|
||||
protected test () {
|
||||
it('gets an album by ID', () => {
|
||||
const album = factory<Album>('album')
|
||||
const album = factory('album')
|
||||
albumStore.vault.set(album.id, album)
|
||||
expect(albumStore.byId(album.id)).toEqual(album)
|
||||
})
|
||||
|
||||
it('removes albums by IDs', () => {
|
||||
const albums = factory<Album>('album', 3)
|
||||
const albums = factory('album', 3)
|
||||
albums.forEach(album => albumStore.vault.set(album.id, album))
|
||||
albumStore.state.albums = albums
|
||||
|
||||
|
@ -33,15 +33,15 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('identifies an unknown album', () => {
|
||||
const album = factory.states('unknown')<Album>('album')
|
||||
const album = factory.states('unknown')('album')
|
||||
|
||||
expect(albumStore.isUnknown(album)).toBe(true)
|
||||
expect(albumStore.isUnknown(album.id)).toBe(true)
|
||||
expect(albumStore.isUnknown(factory<Album>('album'))).toBe(false)
|
||||
expect(albumStore.isUnknown(factory('album'))).toBe(false)
|
||||
})
|
||||
|
||||
it('syncs albums with the vault', () => {
|
||||
const album = factory<Album>('album', { name: 'IV' })
|
||||
const album = factory('album', { name: 'IV' })
|
||||
|
||||
albumStore.syncWithVault(album)
|
||||
expect(albumStore.vault.get(album.id)).toEqual(album)
|
||||
|
@ -54,9 +54,9 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('uploads a cover for an album', async () => {
|
||||
const album = factory<Album>('album')
|
||||
const album = factory('album')
|
||||
albumStore.syncWithVault(album)
|
||||
const songsInAlbum = factory<Song>('song', 3, { album_id: album.id })
|
||||
const songsInAlbum = factory('song', 3, { album_id: album.id })
|
||||
const putMock = this.mock(http, 'put').mockResolvedValue({ cover_url: 'http://test/cover.jpg' })
|
||||
this.mock(songStore, 'byAlbum', songsInAlbum)
|
||||
|
||||
|
@ -70,7 +70,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('fetches an album thumbnail', async () => {
|
||||
const getMock = this.mock(http, 'get').mockResolvedValue({ thumbnailUrl: 'http://test/thumbnail.jpg' })
|
||||
const album = factory<Album>('album')
|
||||
const album = factory('album')
|
||||
|
||||
const url = await albumStore.fetchThumbnail(album.id)
|
||||
|
||||
|
@ -79,7 +79,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('resolves an album', async () => {
|
||||
const album = factory<Album>('album')
|
||||
const album = factory('album')
|
||||
const getMock = this.mock(http, 'get').mockResolvedValueOnce(album)
|
||||
|
||||
expect(await albumStore.resolve(album.id)).toEqual(album)
|
||||
|
@ -91,7 +91,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('paginates', async () => {
|
||||
const albums = factory<Album>('album', 3)
|
||||
const albums = factory('album', 3)
|
||||
|
||||
this.mock(http, 'get').mockResolvedValueOnce({
|
||||
data: albums,
|
||||
|
|
|
@ -14,13 +14,13 @@ new class extends UnitTestCase {
|
|||
|
||||
protected test () {
|
||||
it('gets an artist by ID', () => {
|
||||
const artist = factory<Artist>('artist')
|
||||
const artist = factory('artist')
|
||||
artistStore.vault.set(artist.id, artist)
|
||||
expect(artistStore.byId(artist.id)).toEqual(artist)
|
||||
})
|
||||
|
||||
it('removes artists by IDs', () => {
|
||||
const artists = factory<Artist>('artist', 3)
|
||||
const artists = factory('artist', 3)
|
||||
artists.forEach(artist => artistStore.vault.set(artist.id, artist))
|
||||
artistStore.state.artists = artists
|
||||
|
||||
|
@ -33,29 +33,29 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('identifies an unknown artist', () => {
|
||||
const artist = factory.states('unknown')<Artist>('artist')
|
||||
const artist = factory.states('unknown')('artist')
|
||||
|
||||
expect(artistStore.isUnknown(artist)).toBe(true)
|
||||
expect(artistStore.isUnknown(artist.id)).toBe(true)
|
||||
expect(artistStore.isUnknown(factory<Artist>('artist'))).toBe(false)
|
||||
expect(artistStore.isUnknown(factory('artist'))).toBe(false)
|
||||
})
|
||||
|
||||
it('identifies the various artist', () => {
|
||||
const artist = factory.states('various')<Artist>('artist')
|
||||
const artist = factory.states('various')('artist')
|
||||
|
||||
expect(artistStore.isVarious(artist)).toBe(true)
|
||||
expect(artistStore.isVarious(artist.id)).toBe(true)
|
||||
expect(artistStore.isVarious(factory<Artist>('artist'))).toBe(false)
|
||||
expect(artistStore.isVarious(factory('artist'))).toBe(false)
|
||||
})
|
||||
|
||||
it('identifies a standard artist', () => {
|
||||
expect(artistStore.isStandard(factory.states('unknown')<Artist>('artist'))).toBe(false)
|
||||
expect(artistStore.isStandard(factory.states('various')<Artist>('artist'))).toBe(false)
|
||||
expect(artistStore.isStandard(factory<Artist>('artist'))).toBe(true)
|
||||
expect(artistStore.isStandard(factory.states('unknown')('artist'))).toBe(false)
|
||||
expect(artistStore.isStandard(factory.states('various')('artist'))).toBe(false)
|
||||
expect(artistStore.isStandard(factory('artist'))).toBe(true)
|
||||
})
|
||||
|
||||
it('syncs artists with the vault', () => {
|
||||
const artist = factory<Artist>('artist', { name: 'Led Zeppelin' })
|
||||
const artist = factory('artist', { name: 'Led Zeppelin' })
|
||||
|
||||
artistStore.syncWithVault(artist)
|
||||
expect(artistStore.vault.get(artist.id)).toEqual(artist)
|
||||
|
@ -68,7 +68,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('uploads an image for an artist', async () => {
|
||||
const artist = factory<Artist>('artist')
|
||||
const artist = factory('artist')
|
||||
artistStore.syncWithVault(artist)
|
||||
const putMock = this.mock(http, 'put').mockResolvedValue({ image_url: 'http://test/img.jpg' })
|
||||
|
||||
|
@ -80,7 +80,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('resolves an artist', async () => {
|
||||
const artist = factory<Artist>('artist')
|
||||
const artist = factory('artist')
|
||||
const getMock = this.mock(http, 'get').mockResolvedValueOnce(artist)
|
||||
|
||||
expect(await artistStore.resolve(artist.id)).toEqual(artist)
|
||||
|
@ -92,7 +92,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('paginates', async () => {
|
||||
const artists = factory<Artist>('artist', 3)
|
||||
const artists = factory('artist', 3)
|
||||
|
||||
this.mock(http, 'get').mockResolvedValueOnce({
|
||||
data: artists,
|
||||
|
|
|
@ -14,7 +14,7 @@ new class extends UnitTestCase {
|
|||
const addMock = this.mock(favoriteStore, 'add')
|
||||
const removeMock = this.mock(favoriteStore, 'remove')
|
||||
const postMock = this.mock(http, 'post')
|
||||
const song = factory<Song>('song', { liked: false })
|
||||
const song = factory('song', { liked: false })
|
||||
|
||||
await favoriteStore.toggleOne(song)
|
||||
|
||||
|
@ -29,7 +29,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('adds songs', () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
favoriteStore.add(songs)
|
||||
expect(favoriteStore.state.songs).toEqual(songs)
|
||||
|
||||
|
@ -39,14 +39,14 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('removes songs', () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
favoriteStore.state.songs = songs
|
||||
favoriteStore.remove(songs)
|
||||
expect(favoriteStore.state.songs).toEqual([])
|
||||
})
|
||||
|
||||
it('likes several songs', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
const addMock = this.mock(favoriteStore, 'add')
|
||||
const postMock = this.mock(http, 'post')
|
||||
|
||||
|
@ -57,7 +57,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('unlikes several songs', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
const removeMock = this.mock(favoriteStore, 'remove')
|
||||
const postMock = this.mock(http, 'post')
|
||||
|
||||
|
@ -68,7 +68,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('fetches favorites', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
const getMock = this.mock(http, 'get').mockResolvedValue(songs)
|
||||
|
||||
await favoriteStore.fetch()
|
||||
|
|
|
@ -7,14 +7,14 @@ import { genreStore } from '@/stores/genreStore'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('fetches all genres', async () => {
|
||||
const genres = factory<Genre>('genre', 3)
|
||||
const genres = factory('genre', 3)
|
||||
this.mock(http, 'get').mockResolvedValue(genres)
|
||||
|
||||
expect(await genreStore.fetchAll()).toEqual(genres)
|
||||
})
|
||||
|
||||
it('fetches a single genre', async () => {
|
||||
const genre = factory<Genre>('genre')
|
||||
const genre = factory('genre')
|
||||
this.mock(http, 'get').mockResolvedValue(genre)
|
||||
|
||||
expect(await genreStore.fetchOne(genre.name)).toEqual(genre)
|
||||
|
|
|
@ -25,12 +25,12 @@ new class extends UnitTestCase {
|
|||
const artistSyncMock = this.mock(artistStore, 'syncWithVault')
|
||||
const refreshMock = this.mock(overviewStore, 'refreshPlayStats')
|
||||
|
||||
const mostPlayedSongs = factory<Song>('song', 7)
|
||||
const mostPlayedAlbums = factory<Album>('album', 6)
|
||||
const mostPlayedArtists = factory<Artist>('artist', 6)
|
||||
const recentlyAddedSongs = factory<Song>('song', 9)
|
||||
const recentlyAddedAlbums = factory<Album>('album', 6)
|
||||
const recentlyPlayedSongs = factory<Song>('song', 9)
|
||||
const mostPlayedSongs = factory('song', 7)
|
||||
const mostPlayedAlbums = factory('album', 6)
|
||||
const mostPlayedArtists = factory('artist', 6)
|
||||
const recentlyAddedSongs = factory('song', 9)
|
||||
const recentlyAddedAlbums = factory('album', 6)
|
||||
const recentlyPlayedSongs = factory('song', 9)
|
||||
|
||||
const getMock = this.mock(http, 'get').mockResolvedValueOnce({
|
||||
most_played_songs: mostPlayedSongs,
|
||||
|
@ -54,8 +54,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('refreshes the store', () => {
|
||||
const mostPlayedSongs = factory<Song>('song', 7)
|
||||
const recentlyPlayedSongs = factory<Song>('song', 9)
|
||||
const mostPlayedSongs = factory('song', 7)
|
||||
const recentlyPlayedSongs = factory('song', 9)
|
||||
|
||||
const mostPlayedSongsMock = this.mock(songStore, 'getMostPlayed', mostPlayedSongs)
|
||||
recentlyPlayedStore.excerptState.playables = recentlyPlayedSongs
|
||||
|
|
|
@ -69,7 +69,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('sets up a smart playlist with properly unserialized rules', () => {
|
||||
const playlist = factory<Playlist>('playlist', {
|
||||
const playlist = factory('playlist', {
|
||||
is_smart: true,
|
||||
rules: serializedRuleGroups as unknown as SmartPlaylistRuleGroup[]
|
||||
})
|
||||
|
@ -80,9 +80,9 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('stores a playlist', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const folder = factory<PlaylistFolder>('playlist-folder')
|
||||
const songs = factory('song', 3)
|
||||
const playlist = factory('playlist')
|
||||
const folder = factory('playlist-folder')
|
||||
const postMock = this.mock(http, 'post').mockResolvedValue(playlist)
|
||||
this.mock(playlistStore, 'serializeSmartPlaylistRulesForStorage', null)
|
||||
|
||||
|
@ -99,9 +99,9 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('deletes a playlist', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const playlist = factory('playlist')
|
||||
const deleteMock = this.mock(http, 'delete')
|
||||
playlistStore.state.playlists = [factory<Playlist>('playlist'), playlist]
|
||||
playlistStore.state.playlists = [factory('playlist'), playlist]
|
||||
|
||||
await playlistStore.delete(playlist)
|
||||
|
||||
|
@ -111,8 +111,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('adds songs to a playlist', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const songs = factory<Song>('song', 3)
|
||||
const playlist = factory('playlist')
|
||||
const songs = factory('song', 3)
|
||||
const postMock = this.mock(http, 'post').mockResolvedValue(playlist)
|
||||
const removeMock = this.mock(cache, 'remove')
|
||||
|
||||
|
@ -126,8 +126,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('removes songs from a playlist', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const songs = factory<Song>('song', 3)
|
||||
const playlist = factory('playlist')
|
||||
const songs = factory('song', 3)
|
||||
const deleteMock = this.mock(http, 'delete').mockResolvedValue(playlist)
|
||||
const removeMock = this.mock(cache, 'remove')
|
||||
|
||||
|
@ -141,20 +141,20 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('does not modify a smart playlist content', async () => {
|
||||
const playlist = factory.states('smart')<Playlist>('playlist')
|
||||
const playlist = factory.states('smart')('playlist')
|
||||
const postMock = this.mock(http, 'post')
|
||||
|
||||
await playlistStore.addContent(playlist, factory<Song>('song', 3))
|
||||
await playlistStore.addContent(playlist, factory('song', 3))
|
||||
expect(postMock).not.toHaveBeenCalled()
|
||||
|
||||
await playlistStore.removeContent(playlist, factory<Song>('song', 3))
|
||||
await playlistStore.removeContent(playlist, factory('song', 3))
|
||||
expect(postMock).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('updates a standard playlist', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const playlist = factory('playlist')
|
||||
playlistStore.state.playlists = [playlist]
|
||||
const folder = factory<PlaylistFolder>('playlist-folder')
|
||||
const folder = factory('playlist-folder')
|
||||
|
||||
const putMock = this.mock(http, 'put').mockResolvedValue(playlist)
|
||||
|
||||
|
@ -170,9 +170,9 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('updates a smart playlist', async () => {
|
||||
const playlist = factory.states('smart')<Playlist>('playlist')
|
||||
const playlist = factory.states('smart')('playlist')
|
||||
playlistStore.state.playlists = [playlist]
|
||||
const rules = factory<SmartPlaylistRuleGroup>('smart-playlist-rule-group', 2)
|
||||
const rules = factory('smart-playlist-rule-group', 2)
|
||||
const serializeMock = this.mock(playlistStore, 'serializeSmartPlaylistRulesForStorage', ['Whatever'])
|
||||
const putMock = this.mock(http, 'put').mockResolvedValue(playlist)
|
||||
const removeMock = this.mock(cache, 'remove')
|
||||
|
@ -191,7 +191,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('uploads a cover for a playlist', async () => {
|
||||
const playlist = factory<Playlist>('playlist')
|
||||
const playlist = factory('playlist')
|
||||
playlistStore.state.playlists = [playlist]
|
||||
const putMock = this.mock(http, 'put').mockResolvedValue({ cover_url: 'http://test/cover.jpg' })
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ new class extends UnitTestCase {
|
|||
|
||||
protected test () {
|
||||
it('sets preferences and saves the state', () => {
|
||||
const user = factory<User>('user')
|
||||
const user = factory('user')
|
||||
user.preferences = defaultPreferences
|
||||
const mock = this.mock(http, 'patch')
|
||||
preferenceStore.set('volume', 5)
|
||||
|
|
|
@ -10,7 +10,7 @@ let songs: Song[]
|
|||
new class extends UnitTestCase {
|
||||
protected beforeEach () {
|
||||
super.beforeEach(() => {
|
||||
songs = factory<Song>('song', 3)
|
||||
songs = factory('song', 3)
|
||||
queueStore.state.playables = reactive(songs)
|
||||
})
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ new class extends UnitTestCase {
|
|||
it('returns the last queued song', () => expect(queueStore.last).toEqual(songs[2]))
|
||||
|
||||
it('queues to bottom', () => {
|
||||
const song = factory<Song>('song')
|
||||
const song = factory('song')
|
||||
const putMock = this.mock(http, 'put')
|
||||
queueStore.queue(song)
|
||||
|
||||
|
@ -33,7 +33,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('queues to top', () => {
|
||||
const song = factory<Song>('song')
|
||||
const song = factory('song')
|
||||
const putMock = this.mock(http, 'put')
|
||||
queueStore.queueToTop(song)
|
||||
|
||||
|
@ -43,7 +43,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('replaces the whole queue', () => {
|
||||
const newSongs = factory<Song>('song', 2)
|
||||
const newSongs = factory('song', 2)
|
||||
const putMock = this.mock(http, 'put')
|
||||
queueStore.replaceQueueWith(newSongs)
|
||||
|
||||
|
@ -101,7 +101,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('fetches random songs to queue', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
const getMock = this.mock(http, 'get').mockResolvedValue(songs)
|
||||
const syncMock = this.mock(songStore, 'syncWithVault', songs)
|
||||
const putMock = this.mock(http, 'put')
|
||||
|
@ -115,7 +115,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('fetches random songs to queue with a custom order', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
const getMock = this.mock(http, 'get').mockResolvedValue(songs)
|
||||
const syncMock = this.mock(songStore, 'syncWithVault', songs)
|
||||
const putMock = this.mock(http, 'put')
|
||||
|
|
|
@ -7,7 +7,7 @@ import { recentlyPlayedStore, songStore } from '.'
|
|||
new class extends UnitTestCase {
|
||||
protected test () {
|
||||
it('fetches the recently played songs', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
const getMock = this.mock(http, 'get').mockResolvedValue(songs)
|
||||
const syncMock = this.mock(songStore, 'syncWithVault', songs)
|
||||
|
||||
|
@ -20,17 +20,17 @@ new class extends UnitTestCase {
|
|||
|
||||
it('fetches when attempting to add a new song and the state is empty', async () => {
|
||||
recentlyPlayedStore.state.playables = []
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
const fetchMock = this.mock(recentlyPlayedStore, 'fetch').mockResolvedValue(songs)
|
||||
|
||||
await recentlyPlayedStore.add(factory<Song>('song'))
|
||||
await recentlyPlayedStore.add(factory('song'))
|
||||
|
||||
expect(fetchMock).toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('adds a song to the state', async () => {
|
||||
const newSong = factory<Song>('song')
|
||||
const songs = factory<Song>('song', 10)
|
||||
const newSong = factory('song')
|
||||
const songs = factory('song', 10)
|
||||
const exceptSongs = songs.slice(0, 7)
|
||||
|
||||
// We don't want to keep the reference to the original songs
|
||||
|
@ -44,7 +44,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('deduplicates when adding a song to the state', async () => {
|
||||
const songs = factory<Song>('song', 10)
|
||||
const songs = factory('song', 10)
|
||||
const newSong = songs[1]
|
||||
const exceptSongs = songs.slice(0, 7)
|
||||
|
||||
|
|
|
@ -22,9 +22,9 @@ new class extends UnitTestCase {
|
|||
protected test () {
|
||||
it('performs an excerpt search', async () => {
|
||||
const result: ExcerptSearchResult = {
|
||||
playables: factory<Song>('song', 3),
|
||||
albums: factory<Album>('album', 3),
|
||||
artists: factory<Artist>('artist', 3)
|
||||
playables: factory('song', 3),
|
||||
albums: factory('album', 3),
|
||||
artists: factory('artist', 3)
|
||||
}
|
||||
|
||||
const getMock = this.mock(http, 'get').mockResolvedValue(result)
|
||||
|
@ -45,7 +45,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('performs a song search', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
|
||||
const getMock = this.mock(http, 'get').mockResolvedValue(songs)
|
||||
const syncMock = this.mock(songStore, 'syncWithVault', songs)
|
||||
|
@ -59,7 +59,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('resets the song result state', () => {
|
||||
searchStore.state.songs = factory<Song>('song', 3)
|
||||
searchStore.state.songs = factory('song', 3)
|
||||
searchStore.resetSongResultState()
|
||||
expect(searchStore.state.songs).toEqual([])
|
||||
})
|
||||
|
|
|
@ -25,42 +25,42 @@ new class extends UnitTestCase {
|
|||
|
||||
protected test () {
|
||||
it('gets a song by ID', () => {
|
||||
const song = reactive(factory<Song>('song', { id: 'foo' }))
|
||||
const song = reactive(factory('song', { id: 'foo' }))
|
||||
songStore.vault.set('foo', reactive(song))
|
||||
songStore.vault.set('bar', reactive(factory<Song>('song', { id: 'bar' })))
|
||||
songStore.vault.set('bar', reactive(factory('song', { id: 'bar' })))
|
||||
|
||||
expect(songStore.byId('foo')).toBe(song)
|
||||
})
|
||||
|
||||
it('gets songs by IDs', () => {
|
||||
const foo = reactive(factory<Song>('song', { id: 'foo' }))
|
||||
const bar = reactive(factory<Song>('song', { id: 'bar' }))
|
||||
const foo = reactive(factory('song', { id: 'foo' }))
|
||||
const bar = reactive(factory('song', { id: 'bar' }))
|
||||
songStore.vault.set('foo', foo)
|
||||
songStore.vault.set('bar', bar)
|
||||
songStore.vault.set('baz', reactive(factory<Song>('song', { id: 'baz' })))
|
||||
songStore.vault.set('baz', reactive(factory('song', { id: 'baz' })))
|
||||
|
||||
expect(songStore.byIds(['foo', 'bar'])).toEqual([foo, bar])
|
||||
})
|
||||
|
||||
it('gets formatted length', () => {
|
||||
expect(songStore.getFormattedLength(factory<Song>('song', { length: 123 }))).toBe('2 min 3 sec')
|
||||
expect(songStore.getFormattedLength(factory('song', { length: 123 }))).toBe('2 min 3 sec')
|
||||
expect(songStore.getFormattedLength([
|
||||
factory<Song>('song', { length: 122 }),
|
||||
factory<Song>('song', { length: 123 })
|
||||
factory('song', { length: 122 }),
|
||||
factory('song', { length: 123 })
|
||||
])).toBe('4 min 5 sec')
|
||||
})
|
||||
|
||||
it('gets songs by album', () => {
|
||||
const songs = reactive(factory<Song>('song', 2, { album_id: 3 }))
|
||||
const songs = reactive(factory('song', 2, { album_id: 3 }))
|
||||
songStore.vault.set(songs[0].id, songs[0])
|
||||
songStore.vault.set(songs[1].id, songs[1])
|
||||
const album = factory<Album>('album', { id: 3 })
|
||||
const album = factory('album', { id: 3 })
|
||||
|
||||
expect(songStore.byAlbum(album)).toEqual(songs)
|
||||
})
|
||||
|
||||
it('resolves a song', async () => {
|
||||
const song = factory<Song>('song')
|
||||
const song = factory('song')
|
||||
const getMock = this.mock(http, 'get').mockResolvedValueOnce(song)
|
||||
|
||||
expect(await songStore.resolve(song.id)).toEqual(song)
|
||||
|
@ -72,17 +72,17 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('matches a song', () => {
|
||||
const song = factory<Song>('song', { title: 'An amazing song' })
|
||||
const songs = [song, ...factory<Song>('song', 3)]
|
||||
const song = factory('song', { title: 'An amazing song' })
|
||||
const songs = [song, ...factory('song', 3)]
|
||||
|
||||
expect(songStore.match('An amazing song', songs)).toEqual(song)
|
||||
expect(songStore.match('An Amazing Song', songs)).toEqual(song)
|
||||
})
|
||||
|
||||
it('registers a play', async () => {
|
||||
const song = factory<Song>('song', { play_count: 42 })
|
||||
const song = factory('song', { play_count: 42 })
|
||||
|
||||
const postMock = this.mock(http, 'post').mockResolvedValueOnce(factory<Interaction>('interaction', {
|
||||
const postMock = this.mock(http, 'post').mockResolvedValueOnce(factory('interaction', {
|
||||
song_id: song.id,
|
||||
play_count: 50
|
||||
}))
|
||||
|
@ -93,7 +93,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('scrobbles', async () => {
|
||||
const song = factory<Song>('song')
|
||||
const song = factory('song')
|
||||
song.play_start_time = 123456789
|
||||
const postMock = this.mock(http, 'post')
|
||||
|
||||
|
@ -103,12 +103,12 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('updates songs', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
|
||||
const result: SongUpdateResult = {
|
||||
playables: factory<Song>('song', 3),
|
||||
albums: factory<Album>('album', 2),
|
||||
artists: factory<Artist>('artist', 2),
|
||||
playables: factory('song', 3),
|
||||
albums: factory('album', 2),
|
||||
artists: factory('artist', 2),
|
||||
removed: {
|
||||
albums: [{
|
||||
id: 10,
|
||||
|
@ -155,7 +155,7 @@ new class extends UnitTestCase {
|
|||
|
||||
it('gets source URL', () => {
|
||||
commonStore.state.cdn_url = 'http://test/'
|
||||
const song = factory<Song>('song', { id: 'foo' })
|
||||
const song = factory('song', { id: 'foo' })
|
||||
this.mock(authService, 'getAudioToken', 'hadouken')
|
||||
|
||||
expect(songStore.getSourceUrl(song)).toBe('http://test/play/foo?t=hadouken')
|
||||
|
@ -166,12 +166,12 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('gets shareable URL', () => {
|
||||
const song = factory<Song>('song', { id: 'foo' })
|
||||
const song = factory('song', { id: 'foo' })
|
||||
expect(songStore.getShareableUrl(song)).toBe('http://test/#/song/foo')
|
||||
})
|
||||
|
||||
it('syncs with the vault', () => {
|
||||
const song = factory<Song>('song', {
|
||||
const song = factory('song', {
|
||||
playback_state: null
|
||||
})
|
||||
|
||||
|
@ -190,7 +190,7 @@ new class extends UnitTestCase {
|
|||
it('watches play count tracking', async () => {
|
||||
const refreshMock = this.mock(overviewStore, 'refreshPlayStats')
|
||||
|
||||
const song = reactive(factory<Song>('song', {
|
||||
const song = reactive(factory('song', {
|
||||
album_id: 10,
|
||||
artist_id: 42,
|
||||
album_artist_id: 43,
|
||||
|
@ -206,8 +206,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('fetches for album', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const album = factory<Album>('album', { id: 42 })
|
||||
const songs = factory('song', 3)
|
||||
const album = factory('album', { id: 42 })
|
||||
const getMock = this.mock(http, 'get').mockResolvedValueOnce(songs)
|
||||
const syncMock = this.mock(songStore, 'syncWithVault', songs)
|
||||
|
||||
|
@ -218,8 +218,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('fetches for artist', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const artist = factory<Artist>('artist', { id: 42 })
|
||||
const songs = factory('song', 3)
|
||||
const artist = factory('artist', { id: 42 })
|
||||
const getMock = this.mock(http, 'get').mockResolvedValueOnce(songs)
|
||||
const syncMock = this.mock(songStore, 'syncWithVault', songs)
|
||||
|
||||
|
@ -230,8 +230,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('fetches for playlist', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const playlist = factory<Playlist>('playlist', { id: '966268ea-935d-4f63-a84e-180385376a78' })
|
||||
const songs = factory('song', 3)
|
||||
const playlist = factory('playlist', { id: '966268ea-935d-4f63-a84e-180385376a78' })
|
||||
this.mock(playlistStore, 'byId').mockReturnValueOnce(playlist)
|
||||
const getMock = this.mock(http, 'get').mockResolvedValueOnce(songs)
|
||||
const syncMock = this.mock(songStore, 'syncWithVault', songs)
|
||||
|
@ -245,8 +245,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('fetches for playlist with cache', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const playlist = factory<Playlist>('playlist', { id: '966268ea-935d-4f63-a84e-180385376a78' })
|
||||
const songs = factory('song', 3)
|
||||
const playlist = factory('playlist', { id: '966268ea-935d-4f63-a84e-180385376a78' })
|
||||
this.mock(playlistStore, 'byId').mockReturnValueOnce(playlist)
|
||||
cache.set(['playlist.songs', playlist.id], songs)
|
||||
|
||||
|
@ -260,8 +260,8 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('fetches for playlist discarding cache', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const playlist = factory<Playlist>('playlist', { id: '966268ea-935d-4f63-a84e-180385376a78' })
|
||||
const songs = factory('song', 3)
|
||||
const playlist = factory('playlist', { id: '966268ea-935d-4f63-a84e-180385376a78' })
|
||||
this.mock(playlistStore, 'byId').mockReturnValueOnce(playlist)
|
||||
cache.set(['playlist.songs', playlist.id], songs)
|
||||
|
||||
|
@ -275,7 +275,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('paginates', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
|
||||
const getMock = this.mock(http, 'get').mockResolvedValueOnce({
|
||||
data: songs,
|
||||
|
@ -302,7 +302,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('paginates for genre', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
const reactiveSongs = reactive(songs)
|
||||
|
||||
const getMock = this.mock(http, 'get').mockResolvedValueOnce({
|
||||
|
@ -331,7 +331,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('fetches random songs for genre', async () => {
|
||||
const songs = factory<Song>('song', 3)
|
||||
const songs = factory('song', 3)
|
||||
const reactiveSongs = reactive(songs)
|
||||
|
||||
const getMock = this.mock(http, 'get').mockResolvedValueOnce(songs)
|
||||
|
|
|
@ -4,7 +4,7 @@ import factory from '@/__tests__/factory'
|
|||
import { http } from '@/services'
|
||||
import { CreateUserData, UpdateUserData, userStore } from '.'
|
||||
|
||||
const currentUser = factory<User>('user', {
|
||||
const currentUser = factory('user', {
|
||||
id: 1,
|
||||
name: 'John Doe',
|
||||
email: 'john@doe.com',
|
||||
|
@ -26,7 +26,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('syncs with vault', () => {
|
||||
const user = factory<User>('user')
|
||||
const user = factory('user')
|
||||
|
||||
expect(userStore.syncWithVault(user)).toEqual([user])
|
||||
expect(userStore.vault.size).toBe(2)
|
||||
|
@ -34,7 +34,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('fetches users', async () => {
|
||||
const users = factory<User>('user', 3)
|
||||
const users = factory('user', 3)
|
||||
const getMock = this.mock(http, 'get').mockResolvedValue(users)
|
||||
|
||||
await userStore.fetch()
|
||||
|
@ -44,7 +44,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('gets user by id', () => {
|
||||
const user = factory<User>('user', { id: 2 })
|
||||
const user = factory('user', { id: 2 })
|
||||
userStore.syncWithVault(user)
|
||||
|
||||
expect(userStore.byId(2)).toEqual(user)
|
||||
|
@ -58,7 +58,7 @@ new class extends UnitTestCase {
|
|||
email: 'jane@doe.com'
|
||||
}
|
||||
|
||||
const user = factory<User>('user', data)
|
||||
const user = factory('user', data)
|
||||
const postMock = this.mock(http, 'post').mockResolvedValue(user)
|
||||
|
||||
expect(await userStore.store(data)).toEqual(user)
|
||||
|
@ -68,7 +68,7 @@ new class extends UnitTestCase {
|
|||
})
|
||||
|
||||
it('updates a user', async () => {
|
||||
const user = factory<User>('user', { id: 2 })
|
||||
const user = factory('user', { id: 2 })
|
||||
userStore.state.users.push(...userStore.syncWithVault(user))
|
||||
|
||||
const data: UpdateUserData = {
|
||||
|
@ -90,7 +90,7 @@ new class extends UnitTestCase {
|
|||
it('deletes a user', async () => {
|
||||
const deleteMock = this.mock(http, 'delete')
|
||||
|
||||
const user = factory<User>('user', { id: 2 })
|
||||
const user = factory('user', { id: 2 })
|
||||
userStore.state.users.push(...userStore.syncWithVault(user))
|
||||
expect(userStore.vault.has(2)).toBe(true)
|
||||
|
||||
|
|
2
resources/assets/js/types.d.ts
vendored
2
resources/assets/js/types.d.ts
vendored
|
@ -154,7 +154,6 @@ interface Playable {
|
|||
play_count_registered?: boolean
|
||||
play_count: number
|
||||
play_start_time?: number
|
||||
genre: string
|
||||
preloaded?: boolean
|
||||
playback_state?: PlaybackState
|
||||
liked: boolean
|
||||
|
@ -172,6 +171,7 @@ interface Song extends Playable {
|
|||
artist_name: Artist['name']
|
||||
album_artist_id: Artist['id']
|
||||
album_artist_name: Artist['name']
|
||||
genre: string
|
||||
track: number | null
|
||||
disc: number | null
|
||||
year: number | null
|
||||
|
|
Loading…
Reference in a new issue