Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { screen, within } from '@testing-library/react';
import { commonText } from '../../../localization/common';
import { statsText } from '../../../localization/stats';
import { requireContext } from '../../../tests/helpers';
import { defaultLayoutGenerated } from '../StatsSpec';
import { mockStatsRequests, renderEmptyStatsPage } from './statsPageTestUtils';

requireContext();
mockStatsRequests();

type User = Awaited<ReturnType<typeof renderEmptyStatsPage>>['user'];

const defaultPageName = defaultLayoutGenerated[0].label;
const newPageName = 'My Shared Page';

const getSection = (sectionName: string): HTMLElement =>
screen.getByRole('heading', { name: sectionName }).closest('li')!;

const getPageButtons = (sectionName: string) =>
within(getSection(sectionName))
.getAllByRole('listitem')
.map((item) => within(item).getAllByRole('button')[0]);

const getPageNames = (sectionName: string) =>
getPageButtons(sectionName).map(({ textContent }) => textContent);

const getAddPageButton = () =>
within(getSection(statsText.shared())).getByRole('button', {
name: commonText.add(),
});

const getEditButton = (): HTMLElement =>
screen
.getAllByRole('button', { name: commonText.edit() })
.find(({ textContent }) => textContent === commonText.edit())!;

async function openAddPageDialog(user: User): Promise<HTMLElement> {
await user.click(getEditButton());
await user.click(getAddPageButton());
return screen.getByRole('dialog', { name: statsText.addPage() });
}

async function addSharedPage(user: User): Promise<void> {
const dialog = await openAddPageDialog(user);
await user.type(within(dialog).getByRole('textbox'), newPageName);
await user.click(
within(dialog).getByRole('button', { name: commonText.add() })
);
}

describe('Adding a new Shared page', () => {
test('"+" opens an empty "Add Page" dialog', async () => {
const { user } = await renderEmptyStatsPage();
const dialog = await openAddPageDialog(user);
expect(within(dialog).getByRole('textbox')).toHaveValue('');
});

test('adds an empty page to the end of Shared and opens it', async () => {
const { user, getSharedLayout, getPersonalLayout } =
await renderEmptyStatsPage();
const personalLayout = getPersonalLayout();
await addSharedPage(user);

expect(
screen.queryByRole('dialog', { name: statsText.addPage() })
).not.toBeInTheDocument();
expect(getPageNames(statsText.shared())).toEqual([
defaultPageName,
newPageName,
]);
expect(getPageButtons(statsText.shared())[1]).toHaveAttribute(
'aria-current',
'page'
);

expect(getSharedLayout()?.[1]).toMatchObject({
label: newPageName,
categories: [],
});
defaultLayoutGenerated[0].categories.forEach(({ label }) =>
expect(
screen.queryByRole('heading', { name: label })
).not.toBeInTheDocument()
);
expect(
screen.getByRole('button', { name: statsText.addACategory() })
).toBeInTheDocument();

expect(getPersonalLayout()).toEqual(personalLayout);
});

test('Cancel discards the new page and reopens the last existing page', async () => {
const { user, getSharedLayout } = await renderEmptyStatsPage();
await addSharedPage(user);
await user.click(screen.getByRole('button', { name: commonText.cancel() }));

expect(getSharedLayout()?.map(({ label }) => label)).toEqual([
defaultPageName,
]);
expect(getPageNames(statsText.shared())).toEqual([defaultPageName]);
expect(getPageButtons(statsText.shared())[0]).toHaveAttribute(
'aria-current',
'page'
);
});

test('closing the dialog does not add a page', async () => {
const { user, getSharedLayout } = await renderEmptyStatsPage();
const dialog = await openAddPageDialog(user);
await user.type(within(dialog).getByRole('textbox'), newPageName);
await user.click(
within(dialog).getByRole('button', { name: commonText.close() })
);

expect(getSharedLayout()).toHaveLength(1);
expect(getPageNames(statsText.shared())).toEqual([defaultPageName]);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { screen } from '@testing-library/react';
import { statsText } from '../../../localization/stats';
import { requireContext } from '../../../tests/helpers';
import type { RA } from '../../../utils/types';
import { defaultLayoutGenerated } from '../StatsSpec';
import type { StatLayout } from '../types';
import { mockStatsRequests, renderEmptyStatsPage } from './statsPageTestUtils';
requireContext();
mockStatsRequests();

const findCategory = (layout: RA<StatLayout>, label: string) =>
layout[0].categories.find((category) => category.label === label);

describe('Statistics initial load with no saved layout', () => {
test('saves the default shared page to collection preferences', async () => {
const { sharedLayout } = await renderEmptyStatsPage();
expect(sharedLayout).toHaveLength(1);
expect(sharedLayout[0].label).toBe(defaultLayoutGenerated[0].label);
expect(sharedLayout[0].categories.map(({ label }) => label)).toEqual(
defaultLayoutGenerated[0].categories.map(({ label }) => label)
);
});

test('saves the default personal page to user preferences without loading it', async () => {
const { getPersonalLayout } = await renderEmptyStatsPage();
expect(getPersonalLayout()).toEqual([defaultLayoutGenerated[1]]);
});

test('marks the active page as refreshed', async () => {
const { sharedLayout } = await renderEmptyStatsPage();
expect(
Number.isNaN(new Date(sharedLayout[0].lastUpdated!).valueOf())
).toBe(false);
expect(
screen.getByText(statsText.lastRefreshed(), { exact: false })
).toBeInTheDocument();
});

test('renders the Shared and Private sections with their default pages', async () => {
await renderEmptyStatsPage();
expect(
screen.getByRole('heading', { name: statsText.shared() })
).toBeInTheDocument();
expect(
screen.getByRole('heading', { name: statsText.private() })
).toBeInTheDocument();
expect(
screen.getByRole('button', { name: defaultLayoutGenerated[0].label })
).toBeInTheDocument();
expect(
screen.getByRole('button', { name: defaultLayoutGenerated[1].label })
).toBeInTheDocument();
});

test('renders every default category of the shared page', async () => {
await renderEmptyStatsPage();
defaultLayoutGenerated[0].categories.forEach(({ label }) =>
expect(screen.getByRole('heading', { name: label })).toBeInTheDocument()
);
});

test('fills backend categories from the backend response', async () => {
const { sharedLayout } = await renderEmptyStatsPage();
const preparations = findCategory(
sharedLayout,
defaultLayoutGenerated[0].categories[1].label
);
expect(
preparations?.items.map(({ label, itemValue }) => [label, itemValue])
).toEqual([
['C&S', '826 / 430'],
['EtOH', '176 / 985'],
]);
expect(screen.getByText('C&S')).toBeInTheDocument();
expect(screen.getByText('826 / 430')).toBeInTheDocument();
});

test('fills backend percentage stats from the backend response', async () => {
const { sharedLayout } = await renderEmptyStatsPage();
const values = Object.fromEntries(
sharedLayout[0].categories
.flatMap(({ items }) => items)
.map((item) => [item.label, item.itemValue])
);
expect(values[statsText.percentGeoReferenced()]).toBe('42%');
expect(values[statsText.percentImaged()]).toBe('17%');
expect(screen.getByText('42%')).toBeInTheDocument();
expect(screen.getByText('17%')).toBeInTheDocument();
});

test('fills dynamic categories from the query results', async () => {
const { sharedLayout } = await renderEmptyStatsPage();
const typeSpecimens = findCategory(
sharedLayout,
statsText.typeSpecimens()
);
expect(typeSpecimens?.items.map(({ label }) => label)).toEqual([
'Holotype',
'Neotype',
]);
typeSpecimens?.items.forEach((item) =>
expect(item.itemValue).toBeDefined()
);
});
});
Loading
Loading