Files
immich/web/src/lib/components/album-page/__tests__/album-card.spec.ts
T
Michel Heusschen 9c6a26de9f chore(web): add asset store unit tests (#8077)
chore(web): asset store unit tests
2024-03-19 23:41:31 -05:00

134 lines
4.8 KiB
TypeScript

import { createObjectURLMock } from '$lib/__mocks__/jsdom-url.mock';
import { sdkMock } from '$lib/__mocks__/sdk.mock';
import { ThumbnailFormat } from '@immich/sdk';
import { albumFactory } from '@test-data';
import '@testing-library/jest-dom';
import { fireEvent, render, waitFor, type RenderResult } from '@testing-library/svelte';
import AlbumCard from '../album-card.svelte';
const onShowContextMenu = vi.fn();
describe('AlbumCard component', () => {
let sut: RenderResult<AlbumCard>;
it.each([
{
album: albumFactory.build({ albumThumbnailAssetId: null, shared: false, assetCount: 0 }),
count: 0,
shared: false,
},
{
album: albumFactory.build({ albumThumbnailAssetId: null, shared: true, assetCount: 0 }),
count: 0,
shared: true,
},
{
album: albumFactory.build({ albumThumbnailAssetId: null, shared: false, assetCount: 5 }),
count: 5,
shared: false,
},
{
album: albumFactory.build({ albumThumbnailAssetId: null, shared: true, assetCount: 2 }),
count: 2,
shared: true,
},
])('shows album data without thumbnail with count $count - shared: $shared', async ({ album, count, shared }) => {
sut = render(AlbumCard, { album });
const albumImgElement = sut.getByTestId('album-image');
const albumNameElement = sut.getByTestId('album-name');
const albumDetailsElement = sut.getByTestId('album-details');
const detailsText = `${count} items` + (shared ? ' . Shared' : '');
expect(albumImgElement).toHaveAttribute('src');
expect(albumImgElement).toHaveAttribute('alt', album.albumName);
await waitFor(() => expect(albumImgElement).toHaveAttribute('src'));
expect(albumImgElement).toHaveAttribute('alt', album.albumName);
expect(sdkMock.getAssetThumbnail).not.toHaveBeenCalled();
expect(albumNameElement).toHaveTextContent(album.albumName);
expect(albumDetailsElement).toHaveTextContent(new RegExp(detailsText));
});
it('shows album data and loads the thumbnail image when available', async () => {
const thumbnailFile = new File([new Blob()], 'fileThumbnail');
const thumbnailUrl = 'blob:thumbnailUrlOne';
sdkMock.getAssetThumbnail.mockResolvedValue(thumbnailFile);
createObjectURLMock.mockReturnValueOnce(thumbnailUrl);
const album = albumFactory.build({
albumThumbnailAssetId: 'thumbnailIdOne',
shared: false,
albumName: 'some album name',
});
sut = render(AlbumCard, { album });
const albumImgElement = sut.getByTestId('album-image');
const albumNameElement = sut.getByTestId('album-name');
const albumDetailsElement = sut.getByTestId('album-details');
expect(albumImgElement).toHaveAttribute('alt', album.albumName);
await waitFor(() => expect(albumImgElement).toHaveAttribute('src', thumbnailUrl));
expect(albumImgElement).toHaveAttribute('alt', album.albumName);
expect(sdkMock.getAssetThumbnail).toHaveBeenCalledTimes(1);
expect(sdkMock.getAssetThumbnail).toHaveBeenCalledWith({
id: 'thumbnailIdOne',
format: ThumbnailFormat.Jpeg,
});
expect(createObjectURLMock).toHaveBeenCalledWith(thumbnailFile);
expect(albumNameElement).toHaveTextContent('some album name');
expect(albumDetailsElement).toHaveTextContent('0 items');
});
it('hides context menu when "onShowContextMenu" is undefined', () => {
const album = Object.freeze(albumFactory.build({ albumThumbnailAssetId: null }));
sut = render(AlbumCard, { album });
const contextButtonParent = sut.queryByTestId('context-button-parent');
expect(contextButtonParent).not.toBeInTheDocument();
});
describe('with rendered component - no thumbnail', () => {
const album = Object.freeze(albumFactory.build({ albumThumbnailAssetId: null }));
beforeEach(async () => {
sut = render(AlbumCard, { album, onShowContextMenu });
const albumImgElement = sut.getByTestId('album-image');
await waitFor(() => expect(albumImgElement).toHaveAttribute('src'));
});
it('dispatches "onShowContextMenu" event on context menu click with mouse coordinates', async () => {
const contextMenuButton = sut.getByTestId('context-button-parent').children[0];
expect(contextMenuButton).toBeDefined();
// Mock getBoundingClientRect to return a bounding rectangle that will result in the expected position
contextMenuButton.getBoundingClientRect = () => ({
x: 123,
y: 456,
width: 0,
height: 0,
top: 0,
right: 0,
bottom: 0,
left: 0,
toJSON: () => ({}),
});
await fireEvent(
contextMenuButton,
new MouseEvent('click', {
clientX: 123,
clientY: 456,
}),
);
expect(onShowContextMenu).toHaveBeenCalledTimes(1);
expect(onShowContextMenu).toHaveBeenCalledWith(expect.objectContaining({ x: 123, y: 456 }));
});
});
});