cypress/integration/song-context-menu.spec.ts

Summary

Maintainability
D
2 days
Test Coverage
context('Song Context Menu', { scrollBehavior: false }, () => {
  it('plays a song via double-clicking', () => {
    cy.$mockPlayback()
    cy.$login()
    cy.$clickSidebarItem('All Songs')

    cy.get('#songsWrapper').within(() => cy.get('.song-item:first-child').dblclick().should('have.class', 'playing'))
    cy.$assertPlaying()
  })

  it('plays and pauses a song via context menu', () => {
    cy.$mockPlayback()
    cy.$login()
    cy.$clickSidebarItem('All Songs')

    cy.get('#songsWrapper').within(() => cy.get('.song-item:first-child').as('item').rightclick())

    cy.findByTestId('song-context-menu').within(() => cy.findByText('Play').click())
    cy.get('@item').should('have.class', 'playing')
    cy.$assertPlaying()

    cy.get('@item').rightclick()
    cy.findByTestId('song-context-menu').within(() => cy.findByText('Pause').click())
    cy.$assertNotPlaying()
  })

  it('invokes album screen', () => {
    cy.$login()
    cy.$clickSidebarItem('All Songs')

    cy.get('#songsWrapper').within(() => cy.get('.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('.song-item').should('have.length.at.least', 1)
    })
  })

  it('invokes artist screen', () => {
    cy.$login()
    cy.$clickSidebarItem('All Songs')

    cy.get('#songsWrapper').within(() => cy.get('.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('.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.$login()
      cy.$shuffleSeveralSongs()
      cy.$clickSidebarItem('All Songs')

      let songTitle
      cy.get('#songsWrapper').within(() => {
        cy.get('.song-item:nth-child(4) .title').invoke('text').then(text => (songTitle = text))
        cy.get('.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('.song-item').should('have.length', 4)
        cy.get(`.song-item:nth-child(${config.queuedPosition}) .title`).should('have.text', songTitle)
      })
    })
  })

  ;[
    { name: 'one song', songCount: 1 },
    { name: 'several songs', songCount: 2 }
  ].forEach((config) => {
    it(`adds ${config.name} into a simple playlist`, () => {
      cy.intercept('/api/playlist/1/songs', {
        fixture: 'playlist-songs.get.200.json'
      })

      cy.intercept('PUT', '/api/playlist/1/sync', {})

      cy.$login()
      cy.$clickSidebarItem('All Songs')

      cy.$assertPlaylistSongCount('Simple Playlist', 3)
      cy.get('#songsWrapper').within(() => {
        if (config.songCount > 1) {
          cy.$selectSongRange(0, config.songCount - 1).rightclick()
        } else {
          cy.get('.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.$login()
    cy.$clickSidebarItem('All Songs')
    cy.get('#songsWrapper').within(() => cy.get('.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/batch/like', {
      fixture: 'batch-like.post.200.json'
    })

    cy.$login()
    cy.$clickSidebarItem('All Songs')
    cy.$assertFavoriteSongCount(3)

    cy.get('#songsWrapper').within(() => cy.get('.song-item:first-child').rightclick())
    cy.findByTestId('song-context-menu').within(() => {
      cy.findByText('Add To').click()
      cy.findByText('Favorites').click()
    })

    cy.$assertFavoriteSongCount(4)
  })

  it('initiates editing a song', () => {
    cy.intercept('/api/**/info', {
      fixture: 'song-info.get.200.json'
    })

    cy.get('#songsWrapper').within(() => cy.get('.song-item:first-child').rightclick())
    cy.findByTestId('song-context-menu').within(() => cy.findByText('Edit').click())
    cy.findByTestId('edit-song-form').should('be.visible')
  })

  it('downloads a song', () => {
    cy.intercept('/download/songs?*').as('download')

    cy.$login()
    cy.$clickSidebarItem('All Songs')

    cy.get('#songsWrapper').within(() => cy.get('.song-item:first-child').rightclick())
    cy.findByTestId('song-context-menu').within(() => cy.findByText('Download').click())

    cy.wait('@download')
  })

  it('does not have a Download item if download is not allowed', () => {
    cy.$login({ allowDownload: false })
    cy.$clickSidebarItem('All Songs')

    cy.get('#songsWrapper').within(() => cy.get('.song-item:first-child').rightclick())
    cy.findByTestId('song-context-menu').within(() => cy.findByText('Download').should('not.exist'))
  })

  it('does not have an Edit item if user is not an admin', () => {
    cy.$loginAsNonAdmin()
    cy.$clickSidebarItem('All Songs')

    cy.get('#songsWrapper').within(() => cy.get('.song-item:first-child').rightclick())
    cy.findByTestId('song-context-menu').within(() => cy.findByText('Edit').should('not.exist'))
  })

  it('copies a song\'s URL', () => {
    cy.$login()
    cy.$clickSidebarItem('All Songs')

    cy.window().then(window => cy.spy(window.document, 'execCommand').as('copy'))
    cy.get('#songsWrapper').within(() => cy.get('.song-item:first-child').rightclick())
    cy.findByTestId('song-context-menu').within(() => cy.findByText('Copy Shareable URL').click())
    cy.get('@copy').should('be.calledWithExactly', 'copy')
  })
})