diff --git a/resources/assets/js/components/playlist/PlaylistContextMenu.spec.ts b/resources/assets/js/components/playlist/PlaylistContextMenu.spec.ts index b41827f8..45e99494 100644 --- a/resources/assets/js/components/playlist/PlaylistContextMenu.spec.ts +++ b/resources/assets/js/components/playlist/PlaylistContextMenu.spec.ts @@ -2,7 +2,10 @@ import { expect, it } from 'vitest' import UnitTestCase from '@/__tests__/UnitTestCase' import { eventBus } from '@/utils' import factory from '@/__tests__/factory' -import { screen } from '@testing-library/vue' +import { screen, waitFor } from '@testing-library/vue' +import { songStore } from '@/stores' +import { playbackService } from '@/services' +import { MessageToasterStub } from '@/__tests__/stubs' import PlaylistContextMenu from './PlaylistContextMenu.vue' new class extends UnitTestCase { @@ -42,5 +45,77 @@ new class extends UnitTestCase { expect(emitMock).toHaveBeenCalledWith('PLAYLIST_DELETE', playlist) }) + + it('plays', async () => { + 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(this.router, 'go') + await this.renderComponent(playlist) + + await this.user.click(screen.getByText('Play')) + + await waitFor(() => { + expect(fetchMock).toHaveBeenCalledWith(playlist) + expect(queueMock).toHaveBeenCalledWith(songs) + expect(goMock).toHaveBeenCalledWith('queue') + }) + }) + + it('warns if attempting to play an empty playlist', async () => { + const playlist = factory('playlist') + const fetchMock = this.mock(songStore, 'fetchForPlaylist').mockResolvedValue([]) + const queueMock = this.mock(playbackService, 'queueAndPlay') + const goMock = this.mock(this.router, 'go') + const warnMock = this.mock(MessageToasterStub.value, 'warning') + + await this.renderComponent(playlist) + + await this.user.click(screen.getByText('Play')) + + await waitFor(() => { + expect(fetchMock).toHaveBeenCalledWith(playlist) + expect(queueMock).not.toHaveBeenCalled() + expect(goMock).not.toHaveBeenCalled() + expect(warnMock).toHaveBeenCalledWith('The playlist is empty.') + }) + }) + + it('shuffles', async () => { + 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(this.router, 'go') + await this.renderComponent(playlist) + + await this.user.click(screen.getByText('Shuffle')) + + await waitFor(() => { + expect(fetchMock).toHaveBeenCalledWith(playlist) + expect(queueMock).toHaveBeenCalledWith(songs, true) + expect(goMock).toHaveBeenCalledWith('queue') + }) + }) + + it('warns if attempting to shuffle an empty playlist', async () => { + const playlist = factory('playlist') + const fetchMock = this.mock(songStore, 'fetchForPlaylist').mockResolvedValue([]) + const queueMock = this.mock(playbackService, 'queueAndPlay') + const goMock = this.mock(this.router, 'go') + const warnMock = this.mock(MessageToasterStub.value, 'warning') + + await this.renderComponent(playlist) + + await this.user.click(screen.getByText('Shuffle')) + + await waitFor(() => { + expect(fetchMock).toHaveBeenCalledWith(playlist) + expect(queueMock).not.toHaveBeenCalled() + expect(goMock).not.toHaveBeenCalled() + expect(warnMock).toHaveBeenCalledWith('The playlist is empty.') + }) + }) } } diff --git a/resources/assets/js/components/playlist/PlaylistContextMenu.vue b/resources/assets/js/components/playlist/PlaylistContextMenu.vue index ce579e60..f2265b32 100644 --- a/resources/assets/js/components/playlist/PlaylistContextMenu.vue +++ b/resources/assets/js/components/playlist/PlaylistContextMenu.vue @@ -1,20 +1,50 @@