nukeop/nuclear

View on GitHub
packages/app/app/containers/TrackPopupContainer/TrackPopupContainer.test.tsx

Summary

Maintainability
A
35 mins
Test Coverage
import React from 'react';
import userEvent from '@testing-library/user-event';
import TrackPopupContainer from './index';
import { buildStoreState } from '../../../test/storeBuilders';
import { AnyProps, mountComponent, setupI18Next } from '../../../test/testUtils';
import { RenderResult } from '@testing-library/react';

const TRACK_TITLE = 'Track title';
const TEST_IDS = {
  TRIGGER_BUTTON: 'trigger-button',
  ADD_TO_QUEUE_BUTTON: 'track-popup-add-queue',
  PLAY_NEXT_BUTTON: 'track-popup-play-next',
  PLAY_NOW_BUTTON: 'track-popup-play-now',
  ADD_TO_FAVORITES_BUTTON: 'track-popup-add-favorites',
  ADD_TO_PLAYLIST_BUTTON: 'track-popup-add-playlist',
  CREATE_PLAYIST_BUTTON: 'track-popup-create-playlist',
  DOWNLOAD_BUTTON: 'track-popup-download',
  CREATE_PLAYLIST_DIALOG_INPUT: 'track-popup-create-playlist-dialog-input',
  CREATE_PLAYLIST_DIALOG_ACCEPT: 'track-popup-create-playlist-dialog-accept',
  CREATE_PLAYLIST_DIALOG_CANCEL: 'track-popup-create-playlist-dialog-cancel'
};

const openTrackPopup = (component: RenderResult) => {
  userEvent.click(component.getByTestId(TEST_IDS.TRIGGER_BUTTON));
};

const openCreatePlaylistInputDialog = (component: RenderResult) => {
  userEvent.click(component.getByTestId(TEST_IDS.ADD_TO_PLAYLIST_BUTTON));
  const createPlaylistComponent = component.getByTestId(TEST_IDS.CREATE_PLAYIST_BUTTON);
  expect(createPlaylistComponent).toBeVisible();
  userEvent.click(createPlaylistComponent);
  expect(component.getByTestId(TEST_IDS.CREATE_PLAYLIST_DIALOG_INPUT)).toBeVisible();
};

describe('Track Popup container', () => {
  beforeAll(() => {
    setupI18Next();
  });

  beforeEach(() => {
    jest.useFakeTimers();
  });

  afterEach(() => {
    jest.runOnlyPendingTimers();
    jest.useRealTimers();
  });

  it('should render the Track Popup container', () => {
    const { component } = mountTrackPopupContainer();
    openTrackPopup(component);
    expect(component.getByText(TRACK_TITLE)).toBeVisible();
    const popupButtonIds = [
      TEST_IDS.ADD_TO_QUEUE_BUTTON,
      TEST_IDS.PLAY_NEXT_BUTTON,
      TEST_IDS.PLAY_NOW_BUTTON,
      TEST_IDS.ADD_TO_FAVORITES_BUTTON,
      TEST_IDS.ADD_TO_PLAYLIST_BUTTON,
      TEST_IDS.DOWNLOAD_BUTTON
    ];
    popupButtonIds.forEach((id) => {
      expect(component.getByTestId(id)).toBeVisible();
    });
    expect(document.body).toMatchSnapshot(); // we need to use document.body because the popup is rendered outside the component
  });

  describe('creating new playlist', () => {
    it('should open Input Dialog', () => {
      const { component } = mountTrackPopupContainer();
      openTrackPopup(component);
      openCreatePlaylistInputDialog(component);
      expect(document.body).toMatchSnapshot();
    });

    it('should create new playlist with selected track', () => {
      const { component, store } = mountTrackPopupContainer();
      openTrackPopup(component);
      openCreatePlaylistInputDialog(component);
      const input = component.getByTestId(TEST_IDS.CREATE_PLAYLIST_DIALOG_INPUT).firstElementChild;
      expect(input).toHaveValue(TRACK_TITLE);
      const playlistName = 'New playlist name';
      userEvent.clear(input);
      userEvent.type(input, playlistName);
      expect(input).toHaveValue(playlistName);
      userEvent.click(component.getByTestId(TEST_IDS.CREATE_PLAYLIST_DIALOG_ACCEPT));

      const state = store.getState();      
      expect(state.playlists.localPlaylists.data).toEqual(
        expect.arrayContaining([
          expect.objectContaining({
            name: playlistName,
            tracks: [expect.objectContaining({ name: TRACK_TITLE })]
          })]));
    });

    it('should not create playlist with an empty name', async () => {
      const { component, store } = mountTrackPopupContainer();
      openTrackPopup(component);
      openCreatePlaylistInputDialog(component);
      const input = component.getByTestId(TEST_IDS.CREATE_PLAYLIST_DIALOG_INPUT).firstElementChild;
      userEvent.clear(input);
      expect(input).toHaveValue('');
      userEvent.click(component.getByTestId(TEST_IDS.CREATE_PLAYLIST_DIALOG_ACCEPT));

      const state = store.getState();
      expect(state.playlists.localPlaylists.data).not.toEqual([
        expect.objectContaining({
          name: ''
        })
      ]);
    });

    it('should add the song to next of current song when clicking PlayNext', async () => {
      const { component, store } = mountTrackPopupContainer({
        queue: {
          currentSong: 1,
          queueItems: [{
            artist: 'test artist 1',
            name: 'test track 1',
            streams: [{
              duration: 300,
              title: 'test track 1',
              skipSegments: []
            }]
          }, {
            artist: 'test artist 2',
            name: 'test track 2',
            streams: [{
              duration: 300,
              title: 'test track 2',
              skipSegments: []
            }]
          }]
        },
        player: {
          seek: 10
        }
      });
      
      openTrackPopup(component);
      userEvent.click(component.getByTestId(TEST_IDS.PLAY_NEXT_BUTTON));

      const state = store.getState();
      expect(state.player.seek).toBe(10);
      expect(state.queue.currentSong).toBe(1); 
      expect(state.queue.queueItems[state.queue.currentSong + 1]).toMatchObject({
        artist: 'Artist',
        name: TRACK_TITLE
      });
    });

  });


  const mountTrackPopupContainer = (initialStore?: AnyProps) => {
    return mountComponent(
      <TrackPopupContainer  
        title={TRACK_TITLE}
        track={{
          artist: {
            name: 'Artist'
          },
          title: TRACK_TITLE
        }}
        trigger={<button data-testid={TEST_IDS.TRIGGER_BUTTON}>Trigger</button>}
      />,
      ['/'],
      initialStore,
      buildStoreState()
        .build()
    );
  };
});