mirror of
https://github.com/koel/koel
synced 2025-02-26 04:07:18 +00:00
feat(test): add e2e tests for song context menu
This commit is contained in:
parent
1c39a59449
commit
67703be7ca
11 changed files with 208 additions and 96 deletions
|
@ -69,17 +69,17 @@
|
||||||
{
|
{
|
||||||
"id": 3,
|
"id": 3,
|
||||||
"name": "The Band",
|
"name": "The Band",
|
||||||
"image": null
|
"image": "http://localhost:8088/test/images/sample.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"name": "Unknown Artist",
|
"name": "Unknown Artist",
|
||||||
"image": null
|
"image": "http://localhost:8088/test/images/sample.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"name": "Various Artists",
|
"name": "Various Artists",
|
||||||
"image": null
|
"image": "http://localhost:8088/test/images/sample.png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"songs": [
|
"songs": [
|
||||||
|
|
|
@ -69,17 +69,17 @@
|
||||||
{
|
{
|
||||||
"id": 3,
|
"id": 3,
|
||||||
"name": "The Band",
|
"name": "The Band",
|
||||||
"image": null
|
"image": "http://localhost:8088/test/images/sample.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 1,
|
"id": 1,
|
||||||
"name": "Unknown Artist",
|
"name": "Unknown Artist",
|
||||||
"image": null
|
"image": "http://localhost:8088/test/images/sample.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": 2,
|
"id": 2,
|
||||||
"name": "Various Artists",
|
"name": "Various Artists",
|
||||||
"image": null
|
"image": "http://localhost:8088/test/images/sample.png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"songs": [
|
"songs": [
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
context('Favorites', { scrollBehavior: false }, () => {
|
context('Favorites', { scrollBehavior: false }, () => {
|
||||||
beforeEach(() => cy.$login())
|
beforeEach(() => cy.$login())
|
||||||
|
|
||||||
function assertFavoriteCount (count: number) {
|
|
||||||
cy.$clickSidebarItem('Favorites')
|
|
||||||
cy.get('#favoritesWrapper').within(() => cy.get('tr.song-item').should('have.length', count))
|
|
||||||
}
|
|
||||||
|
|
||||||
it('loads the list of favorites', () => {
|
it('loads the list of favorites', () => {
|
||||||
cy.$clickSidebarItem('Favorites')
|
cy.$clickSidebarItem('Favorites')
|
||||||
|
|
||||||
|
@ -37,7 +32,7 @@ context('Favorites', { scrollBehavior: false }, () => {
|
||||||
.within(() => cy.get('[data-test=btn-like-liked]').should('be.visible'))
|
.within(() => cy.get('[data-test=btn-like-liked]').should('be.visible'))
|
||||||
})
|
})
|
||||||
|
|
||||||
assertFavoriteCount(4)
|
cy.$assertFavoriteSongCount(4)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('adds a favorite song from Add To dropdown', () => {
|
it('adds a favorite song from Add To dropdown', () => {
|
||||||
|
@ -57,24 +52,9 @@ context('Favorites', { scrollBehavior: false }, () => {
|
||||||
.should('not.be.visible')
|
.should('not.be.visible')
|
||||||
})
|
})
|
||||||
|
|
||||||
assertFavoriteCount(4)
|
cy.$assertFavoriteSongCount(4)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('adds a favorite song from context menu', () => {
|
|
||||||
cy.intercept('POST', '/api/interaction/like', {
|
|
||||||
fixture: 'like.post.200.json'
|
|
||||||
})
|
|
||||||
|
|
||||||
cy.$clickSidebarItem('All Songs')
|
|
||||||
|
|
||||||
cy.get('#songsWrapper').within(() => cy.get('tr.song-item:first-child').rightclick())
|
|
||||||
cy.findByTestId('song-context-menu').within(() => {
|
|
||||||
cy.findByText('Add To').click()
|
|
||||||
cy.findByText('Favorites').click()
|
|
||||||
})
|
|
||||||
|
|
||||||
assertFavoriteCount(4)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('deletes a favorite with Unlike button', () => {
|
it('deletes a favorite with Unlike button', () => {
|
||||||
cy.intercept('POST', '/api/interaction/like', {})
|
cy.intercept('POST', '/api/interaction/like', {})
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
context('Playlists', () => {
|
context('Playlists', () => {
|
||||||
beforeEach(() => cy.$login())
|
beforeEach(() => cy.$login())
|
||||||
|
|
||||||
const assertPlaylistSongCount = (name: string, count: number) => {
|
|
||||||
cy.$clickSidebarItem(name)
|
|
||||||
cy.get('#playlistWrapper tr.song-item').should('have.length', count)
|
|
||||||
}
|
|
||||||
|
|
||||||
it('displays a playlist when sidebar menu item is clicked', () => {
|
it('displays a playlist when sidebar menu item is clicked', () => {
|
||||||
cy.intercept('GET', '/api/playlist/1/songs', {
|
cy.intercept('GET', '/api/playlist/1/songs', {
|
||||||
fixture: 'playlist-songs.get.200.json'
|
fixture: 'playlist-songs.get.200.json'
|
||||||
|
@ -102,11 +97,9 @@ context('Playlists', () => {
|
||||||
fixture: 'playlist-songs.get.200.json'
|
fixture: 'playlist-songs.get.200.json'
|
||||||
})
|
})
|
||||||
|
|
||||||
cy.intercept('PUT', '/api/playlist/1/sync', {
|
cy.intercept('PUT', '/api/playlist/1/sync', {})
|
||||||
fixture: 'playlist.post.200.json'
|
|
||||||
})
|
|
||||||
|
|
||||||
assertPlaylistSongCount('Simple Playlist', 3)
|
cy.$assertPlaylistSongCount('Simple Playlist', 3)
|
||||||
|
|
||||||
cy.$clickSidebarItem('All Songs')
|
cy.$clickSidebarItem('All Songs')
|
||||||
|
|
||||||
|
@ -121,7 +114,7 @@ context('Playlists', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
cy.findByText('Added 2 songs into "Simple Playlist".').should('be.visible')
|
cy.findByText('Added 2 songs into "Simple Playlist".').should('be.visible')
|
||||||
assertPlaylistSongCount('Simple Playlist', 5)
|
cy.$assertPlaylistSongCount('Simple Playlist', 5)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('creates a playlist directly from songs', () => {
|
it('creates a playlist directly from songs', () => {
|
||||||
|
@ -148,7 +141,7 @@ context('Playlists', () => {
|
||||||
.and('have.class', 'active')
|
.and('have.class', 'active')
|
||||||
|
|
||||||
cy.findByText('Created playlist "A New Playlist".').should('be.visible')
|
cy.findByText('Created playlist "A New Playlist".').should('be.visible')
|
||||||
assertPlaylistSongCount('A New Playlist', 3)
|
cy.$assertPlaylistSongCount('A New Playlist', 3)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('updates a simple playlist from the sidebar', () => {
|
it('updates a simple playlist from the sidebar', () => {
|
||||||
|
@ -245,7 +238,7 @@ context('Playlists', () => {
|
||||||
.findByText('My Smart Playlist')
|
.findByText('My Smart Playlist')
|
||||||
.should('have.class', 'active')
|
.should('have.class', 'active')
|
||||||
|
|
||||||
assertPlaylistSongCount('My Smart Playlist', 3)
|
cy.$assertPlaylistSongCount('My Smart Playlist', 3)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('updates a smart playlist', () => {
|
it('updates a smart playlist', () => {
|
||||||
|
|
|
@ -47,21 +47,8 @@ context('Queuing', { scrollBehavior: false }, () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
function queueSomeFromSongList (count = 3) {
|
|
||||||
cy.$clickSidebarItem('All Songs')
|
|
||||||
|
|
||||||
cy.get('#songsWrapper').within(() => {
|
|
||||||
cy.get('tr.song-item:nth-child(1)').click()
|
|
||||||
cy.get(`tr.song-item:nth-child(${count})`).click({
|
|
||||||
shiftKey: true
|
|
||||||
})
|
|
||||||
|
|
||||||
cy.get('.screen-header [data-test=btn-shuffle-selected]').click()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
it('creates a queue from selected songs', () => {
|
it('creates a queue from selected songs', () => {
|
||||||
queueSomeFromSongList()
|
cy.$queueSeveralSongs()
|
||||||
|
|
||||||
cy.get('#queueWrapper').within(() => {
|
cy.get('#queueWrapper').within(() => {
|
||||||
cy.get('tr.song-item').should('have.length', 3)
|
cy.get('tr.song-item').should('have.length', 3)
|
||||||
|
@ -70,7 +57,7 @@ context('Queuing', { scrollBehavior: false }, () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
it('deletes a song from queue', () => {
|
it('deletes a song from queue', () => {
|
||||||
queueSomeFromSongList()
|
cy.$queueSeveralSongs()
|
||||||
|
|
||||||
cy.get('#queueWrapper').within(() => {
|
cy.get('#queueWrapper').within(() => {
|
||||||
cy.get('tr.song-item').should('have.length', 3)
|
cy.get('tr.song-item').should('have.length', 3)
|
||||||
|
@ -79,44 +66,8 @@ context('Queuing', { scrollBehavior: false }, () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
;([
|
|
||||||
{ menuItem: 'After Current Song', queuedPosition: 2 },
|
|
||||||
{ menuItem: 'Bottom of Queue', queuedPosition: 4 },
|
|
||||||
{ menuItem: 'Top of Queue', queuedPosition: 1 }
|
|
||||||
]).forEach(config => {
|
|
||||||
it(`queues a song to ${config.menuItem}`, () => {
|
|
||||||
queueSomeFromSongList()
|
|
||||||
|
|
||||||
cy.$clickSidebarItem('All Songs')
|
|
||||||
|
|
||||||
let songTitle
|
|
||||||
cy.get('#songsWrapper').within(() => {
|
|
||||||
cy.get('tr.song-item:nth-child(4) .title')
|
|
||||||
.invoke('text')
|
|
||||||
.then(text => {
|
|
||||||
songTitle = text
|
|
||||||
})
|
|
||||||
|
|
||||||
cy.get('tr.song-item:nth-child(4)').rightclick()
|
|
||||||
})
|
|
||||||
|
|
||||||
cy.findByTestId('song-context-menu').should('be.visible')
|
|
||||||
.within(() => {
|
|
||||||
cy.findByText('Add To').click()
|
|
||||||
cy.findByText(config.menuItem).click()
|
|
||||||
})
|
|
||||||
|
|
||||||
cy.$clickSidebarItem('Current Queue')
|
|
||||||
cy.get('#queueWrapper').within(() => {
|
|
||||||
cy.get('tr.song-item').should('have.length', 4)
|
|
||||||
cy.get(`tr.song-item:nth-child(${config.queuedPosition}) .title`).should('have.text', songTitle)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
it('queues a song when plays it', () => {
|
it('queues a song when plays it', () => {
|
||||||
queueSomeFromSongList()
|
cy.$queueSeveralSongs()
|
||||||
|
|
||||||
cy.$clickSidebarItem('All Songs')
|
cy.$clickSidebarItem('All Songs')
|
||||||
|
|
||||||
let songTitle
|
let songTitle
|
||||||
|
|
153
cypress/integration/song-context-menu.spec.ts
Normal file
153
cypress/integration/song-context-menu.spec.ts
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
context('Song Context Menu', { scrollBehavior: false }, () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cy.$login()
|
||||||
|
cy.$clickSidebarItem('All Songs')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('plays a song via double-clicking', () => {
|
||||||
|
cy.$mockPlayback()
|
||||||
|
|
||||||
|
cy.get('#songsWrapper').within(() => {
|
||||||
|
cy.get('tr.song-item:first-child').dblclick()
|
||||||
|
cy.get('tr.song-item:first-child').should('have.class', 'playing')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('plays a song via context menu', () => {
|
||||||
|
cy.$mockPlayback()
|
||||||
|
|
||||||
|
cy.get('#songsWrapper').within(() => {
|
||||||
|
cy.get('tr.song-item:first-child')
|
||||||
|
.as('item')
|
||||||
|
.rightclick()
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.findByTestId('song-context-menu').within(() => cy.findByText('Play').click())
|
||||||
|
cy.get('@item').should('have.class', 'playing')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('goes to album', () => {
|
||||||
|
cy.get('#songsWrapper').within(() => cy.get('tr.song-item:first-child').rightclick())
|
||||||
|
cy.findByTestId('song-context-menu').within(() => cy.findByText('Go to Album').click())
|
||||||
|
|
||||||
|
cy.get('#albumWrapper')
|
||||||
|
.should('be.visible')
|
||||||
|
.within(() => {
|
||||||
|
cy.get('.screen-header').should('be.visible')
|
||||||
|
cy.get('tr.song-item').should('have.length.at.least', 1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('goes to artist', () => {
|
||||||
|
cy.get('#songsWrapper').within(() => cy.get('tr.song-item:first-child').rightclick())
|
||||||
|
cy.findByTestId('song-context-menu').within(() => cy.findByText('Go to Artist').click())
|
||||||
|
|
||||||
|
cy.get('#artistWrapper')
|
||||||
|
.should('be.visible')
|
||||||
|
.within(() => {
|
||||||
|
cy.get('.screen-header').should('be.visible')
|
||||||
|
cy.get('tr.song-item').should('have.length.at.least', 1)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
;([
|
||||||
|
{ menuItem: 'After Current Song', queuedPosition: 2 },
|
||||||
|
{ menuItem: 'Bottom of Queue', queuedPosition: 4 },
|
||||||
|
{ menuItem: 'Top of Queue', queuedPosition: 1 }
|
||||||
|
]).forEach(config => {
|
||||||
|
it(`queues a song to ${config.menuItem}`, () => {
|
||||||
|
cy.$queueSeveralSongs()
|
||||||
|
cy.$clickSidebarItem('All Songs')
|
||||||
|
|
||||||
|
let songTitle
|
||||||
|
cy.get('#songsWrapper').within(() => {
|
||||||
|
cy.get('tr.song-item:nth-child(4) .title')
|
||||||
|
.invoke('text')
|
||||||
|
.then(text => {
|
||||||
|
songTitle = text
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.get('tr.song-item:nth-child(4)').rightclick()
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.findByTestId('song-context-menu').within(() => {
|
||||||
|
cy.findByText('Add To').click()
|
||||||
|
cy.findByText(config.menuItem).click()
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.$clickSidebarItem('Current Queue')
|
||||||
|
cy.get('#queueWrapper').within(() => {
|
||||||
|
cy.get('tr.song-item').should('have.length', 4)
|
||||||
|
cy.get(`tr.song-item:nth-child(${config.queuedPosition}) .title`).should('have.text', songTitle)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
;[
|
||||||
|
{ name: 'one song', songCount: 1 },
|
||||||
|
{ name: 'several songs', songCount: 2 }
|
||||||
|
].forEach((config) => {
|
||||||
|
it(`add ${config.name} into a simple playlist`, () => {
|
||||||
|
cy.intercept('GET', '/api/playlist/1/songs', {
|
||||||
|
fixture: 'playlist-songs.get.200.json'
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.intercept('PUT', '/api/playlist/1/sync', {})
|
||||||
|
|
||||||
|
cy.$assertPlaylistSongCount('Simple Playlist', 3)
|
||||||
|
cy.get('#songsWrapper').within(() => {
|
||||||
|
cy.get('tr.song-item:first-child').click()
|
||||||
|
|
||||||
|
if (config.songCount > 1) {
|
||||||
|
cy.get(`tr.song-item:nth-child(${config.songCount})`).click({ shiftKey: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
cy.get('tr.song-item:first-child').rightclick()
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.findByTestId('song-context-menu')
|
||||||
|
.within(() => {
|
||||||
|
cy.findByText('Add To').click()
|
||||||
|
cy.findByText('Simple Playlist').click()
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.$assertPlaylistSongCount('Simple Playlist', 3 + config.songCount)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not have smart playlists as target for adding songs', () => {
|
||||||
|
cy.get('#songsWrapper').within(() => cy.get('tr.song-item:first-child').rightclick())
|
||||||
|
|
||||||
|
cy.findByTestId('song-context-menu')
|
||||||
|
.within(() => {
|
||||||
|
cy.findByText('Add To').click()
|
||||||
|
cy.findByText('Smart Playlist').should('not.exist')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it('adds a favorite song from context menu', () => {
|
||||||
|
cy.intercept('POST', '/api/interaction/like', {
|
||||||
|
fixture: 'like.post.200.json'
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.$assertFavoriteSongCount(3)
|
||||||
|
|
||||||
|
cy.get('#songsWrapper').within(() => cy.get('tr.song-item:first-child').rightclick())
|
||||||
|
cy.findByTestId('song-context-menu').within(() => {
|
||||||
|
cy.findByText('Add To').click()
|
||||||
|
cy.findByText('Favorites').click()
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.$assertFavoriteSongCount(4)
|
||||||
|
})
|
||||||
|
|
||||||
|
it.only('initiates editing a song', () => {
|
||||||
|
cy.intercept('GET', '/api/**/info', {
|
||||||
|
fixture: 'info.get.200.json'
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.get('#songsWrapper').within(() => cy.get('tr.song-item:first-child').rightclick())
|
||||||
|
cy.findByTestId('song-context-menu').within(() => cy.findByText('Edit').click())
|
||||||
|
cy.findByTestId('edit-song-form').should('be.visible')
|
||||||
|
})
|
||||||
|
})
|
3
cypress/integration/song-editing.spec.ts
Normal file
3
cypress/integration/song-editing.spec.ts
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
context.skip('Song Editing', () => {
|
||||||
|
// @todo Write tests for song editing
|
||||||
|
})
|
|
@ -1,3 +0,0 @@
|
||||||
context('Queuing', { scrollBehavior: false }, () => {
|
|
||||||
|
|
||||||
})
|
|
|
@ -50,3 +50,29 @@ Cypress.Commands.add('$mockPlayback', () => {
|
||||||
fixture: 'info.get.200.json'
|
fixture: 'info.get.200.json'
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Cypress.Commands.add('$queueSeveralSongs', (count = 3) => {
|
||||||
|
cy.$mockPlayback()
|
||||||
|
cy.$clickSidebarItem('All Songs')
|
||||||
|
|
||||||
|
cy.get('#songsWrapper').within(() => {
|
||||||
|
cy.get('tr.song-item:nth-child(1)').click()
|
||||||
|
cy.get(`tr.song-item:nth-child(${count})`).click({
|
||||||
|
shiftKey: true
|
||||||
|
})
|
||||||
|
|
||||||
|
cy.get('.screen-header [data-test=btn-shuffle-selected]').click()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Cypress.Commands.add('$assertPlaylistSongCount', (name: string, count: number) => {
|
||||||
|
cy.$clickSidebarItem(name)
|
||||||
|
cy.get('#playlistWrapper tr.song-item').should('have.length', count)
|
||||||
|
cy.go('back')
|
||||||
|
})
|
||||||
|
|
||||||
|
Cypress.Commands.add('$assertFavoriteSongCount', (count: number) => {
|
||||||
|
cy.$clickSidebarItem('Favorites')
|
||||||
|
cy.get('#favoritesWrapper').within(() => cy.get('tr.song-item').should('have.length', count))
|
||||||
|
cy.go('back')
|
||||||
|
})
|
||||||
|
|
9
cypress/types.d.ts
vendored
9
cypress/types.d.ts
vendored
|
@ -11,6 +11,15 @@ declare namespace Cypress {
|
||||||
*/
|
*/
|
||||||
$mockPlayback(): void
|
$mockPlayback(): void
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queue several songs from the All Song screen.
|
||||||
|
* @param count
|
||||||
|
*/
|
||||||
|
$queueSeveralSongs(count?: number): void
|
||||||
|
|
||||||
|
$assertPlaylistSongCount(name: string, count: number): void
|
||||||
|
$assertFavoriteSongCount(count: number): void
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support finding an element within an element identified with a test ID.
|
* Support finding an element within an element identified with a test ID.
|
||||||
* For example, given a DOM like this:
|
* For example, given a DOM like this:
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 9e72452c39d09a275ebbcb5aa25531e7f66525a1
|
Subproject commit 925ebc48432a3fa401ea21a35508a8d48e42079c
|
Loading…
Add table
Reference in a new issue