nukeop/nuclear

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

Summary

Maintainability
F
5 days
Test Coverage
import { waitFor } from '@testing-library/react';
import { mountedComponentFactory, setupI18Next } from '../../../test/testUtils';
import { buildStoreState } from '../../../test/storeBuilders';
import PlayerBarContainer from '../PlayerBarContainer';
import userEvent from '@testing-library/user-event';

describe('Album view container', () => {
  beforeAll(() => {
    setupI18Next();
  });

  beforeEach(() => {
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    const { store } = require('@nuclear/core');
    store.clear();
  });

  it('should display an album', () => {
    const { component } = mountComponent();
    expect(component.asFragment()).toMatchSnapshot();
  });

  it('should show that an album is still loading', () => {
    const { component } = mountComponent(
      buildStoreState()
        .withPlugins()
        .withAlbumDetails({ ['test-album-id']: { loading: true } })
        .build()
    );

    expect(component.asFragment()).toMatchSnapshot();
  });

  it('should search for artist after clicking his name', async () => {
    const { component, history } = mountComponent();
    expect(history.location.pathname).toBe('/album/test-album-id');
    await waitFor(() => component.getByText(/test artist/i).click());
    expect(history.location.pathname).toBe('/artist/test-artist-id');
  });

  it('should add a single track to queue after clicking the button in the popup', async () => {
    const { component, store } = mountComponent();

    await waitFor(() => component.getAllByTestId('track-popup-trigger')[0].click());
    await waitFor(() => component.getByText(/add to queue/i).click());

    const state = store.getState();
    expect(state.queue.queueItems).toEqual([
      expect.objectContaining({
        artist: 'test artist',
        name: 'test track 1'
      })
    ]);
  });

  it('should start playing a single track after clicking the button in the popup', async () => {
    const { component, store } = mountComponent();

    await waitFor(() => component.getAllByTestId('track-popup-trigger')[0].click());
    await waitFor(() => component.getByText(/play now/i).click());

    const state = store.getState();
    expect(state.queue.queueItems).toEqual([
      expect.objectContaining({
        artist: 'test artist',
        name: 'test track 1'
      })
    ]);
    expect(state.player.playbackStatus).toEqual('PLAYING');
  });

  it('should queue a single track to be played next after clicking the button in the popup', async () => {
    const { component, store } = mountComponent();

    await waitFor(() => component.getAllByTestId('track-popup-trigger')[1].click());
    await waitFor(() => component.getByText(/play now/i).click());
    await waitFor(() => component.getAllByTestId('track-popup-trigger')[0].click());
    await waitFor(() => component.getByText(/play next/i).click());

    const state = store.getState();
    expect(state.queue.queueItems).toEqual([
      expect.objectContaining({
        artist: 'test artist',
        name: 'test track 2'
      }),
      expect.objectContaining({
        artist: 'test artist',
        name: 'test track 1'
      })
    ]);
    expect(state.player.playbackStatus).toEqual('PLAYING');
  });

  it('should add a single track to downloads after clicking the button in the popup', async () => {
    const { component, store } = mountComponent();

    await waitFor(() => component.getAllByTestId('track-popup-trigger')[0].click());
    await waitFor(() => component.getByText(/download/i).click());

    const state = store.getState();
    expect(state.downloads).toEqual([
      {
        completion: 0,
        status: 'Waiting',
        track: expect.objectContaining({
          artist: 'test artist',
          name: 'test track 1'
        })
      }
    ]);
  });

  it('should add album to favorites after clicking the star', async () => {
    const { component, store } = mountComponent();
    let state = store.getState();
    expect(state.favorites.albums).toEqual([]);

    await waitFor(() => component.getByTestId(/add-remove-favorite/i).click());
    state = store.getState();
    expect(state.favorites.albums).toEqual([
      expect.objectContaining({
        artist: 'test artist',
        title: 'test album'
      })
    ]);
  });

  it('should remove album from favorites after clicking the star if already in favorites', async () => {
    const { component, store } = mountComponent();
    let state = store.getState();
    expect(state.favorites.albums).toEqual([]);

    await waitFor(() => component.getByTestId(/add-remove-favorite/i).click());
    state = store.getState();
    expect(state.favorites.albums).toEqual([
      expect.objectContaining({
        artist: 'test artist',
        title: 'test album'
      })
    ]);

    await waitFor(() => component.getByTestId(/add-remove-favorite/i).click());
    state = store.getState();
    expect(state.favorites.albums).toEqual([]);
  });

  it('should play all tracks in the album after clicking play all', async () => {
    const { component, store } = mountComponent();
    await waitFor(() => component.getByText(/Play/i).click());

    const state = store.getState();
    expect(state?.queue?.queueItems).toEqual([
      expect.objectContaining({
        artist: 'test artist',
        name: 'test track 1'
      }),
      expect.objectContaining({
        artist: 'test artist',
        name: 'test track 2'
      }),
      expect.objectContaining({
        artist: 'test artist',
        name: 'test track 3'
      })
    ]);
    expect(state.player.playbackStatus).toEqual('PLAYING');
  });

  it('should add album to queue after clicking the button', async () => {
    const { component, store } = mountComponent();
    await waitFor(() => component.getByTestId('more-button').click());
    await waitFor(() => component.getByText(/Add album to queue/i).click());
    const state = store.getState();

    expect(state?.queue?.queueItems).toEqual([
      expect.objectContaining({
        artist: 'test artist',
        name: 'test track 1'
      }),
      expect.objectContaining({
        artist: 'test artist',
        name: 'test track 2'
      }),
      expect.objectContaining({
        artist: 'test artist',
        name: 'test track 3'
      })
    ]);
  });

  it('should load the stream sources one by one', async () => {
    const { component, store } = mountComponent();
    await waitFor(() => component.getByTestId('more-button').click());
    component.getByText(/Add album to queue/i).click();
    const state = store.getState();

    expect(state?.queue?.queueItems[1].streams).toEqual([]);
    expect(state?.queue?.queueItems[2].streams).toEqual([]);
    await waitFor(() => {
      const currentState = store.getState();
      return expect(currentState?.queue?.queueItems).toEqual([
        expect.objectContaining({
          artist: 'test artist',
          name: 'test track 1',
          streams: [{
            stream: 'test-stream-url',
            author: {
              name: 'test author'
            }
          }]
        }),
        expect.objectContaining({
          artist: 'test artist',
          name: 'test track 2'
        }),
        expect.objectContaining({
          artist: 'test artist',
          name: 'test track 3'
        })
      ]);
    });
  });

  it('should add album to downloads after clicking the button', async () => {
    const { component, store } = mountComponent();
    await waitFor(() => component.getByTestId('more-button').click());
    await waitFor(() => component.getByText(/Download/i).click());
    const state = store.getState();
    expect(state.downloads).toEqual([
      {
        completion: 0,
        status: 'Waiting',
        track: expect.objectContaining({
          artist: 'test artist',
          name: 'test track 1',
          uuid: 'track-1-id'
        })
      },
      {
        completion: 0,
        status: 'Waiting',
        track: expect.objectContaining({
          uuid: 'track-2-id',
          artist: 'test artist',
          name: 'test track 2'
        })
      },
      {
        completion: 0,
        status: 'Waiting',
        track: expect.objectContaining({
          uuid: 'track-3-id',
          artist: 'test artist',
          name: 'test track 3'
        })
      }
    ]);
  });

  it('should add album tracks to an existing playlist using the album menu popup', async () => {
    const { component, store } = mountComponent(
      buildStoreState()
        .withAlbumDetails()
        .withPlaylists([{
          id: 'test playlist id',
          name: 'test playlist',
          tracks: []
        }])
        .build()
    );
    userEvent.click(component.getByTestId('more-button'));
    userEvent.click(component.getByTestId('add-album-to-playlist'));
    userEvent.click(component.getByText('test playlist'));

    const state = store.getState();
    expect(state.playlists.localPlaylists.data[0].tracks).toEqual([
      expect.objectContaining({ uuid: 'track-1-id' }),
      expect.objectContaining({ uuid: 'track-2-id' }),
      expect.objectContaining({ uuid: 'track-3-id' })
    ]);
  });

  it('should add album tracks to a new playlist using the album menu popup', async () => {
    const { component, store } = mountComponent();
    userEvent.click(component.getByTestId('more-button'));
    userEvent.click(component.getByTestId('add-album-to-playlist'));
    userEvent.click(component.getByTestId('playlist-popup-create-playlist'));
    
    expect(component.getByTestId('create-playlist-dialog-input')).toBeVisible();
    expect(component.getByTestId('create-playlist-dialog-accept')).toBeVisible();
    expect(component.getByTestId('create-playlist-dialog-cancel')).toBeVisible();

    userEvent.click(component.getByTestId('create-playlist-dialog-accept'));

    const state = store.getState();
    expect(state.playlists.localPlaylists.data).toHaveLength(1);

    const firstPlaylist = state.playlists.localPlaylists.data[0];
    expect(firstPlaylist.name).toBe('test artist - test album');
    expect(firstPlaylist.tracks).toEqual([
      expect.objectContaining({ uuid: 'track-1-id' }),
      expect.objectContaining({ uuid: 'track-2-id' }),
      expect.objectContaining({ uuid: 'track-3-id' })
    ]);
  });

  const mountComponent = mountedComponentFactory(
    ['/album/test-album-id'],
    buildStoreState()
      .withAlbumDetails()
      .withArtistDetails()
      .withPlugins()
      .withConnectivity()
      .withSettings({ useStreamVerification: false})
      .build(),
    PlayerBarContainer
  );
});