Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c45cabc
[test]: undergo initial load
kwhuber Oct 6, 2026
ff11df1
Merge branch 'main' into issue-8582
kwhuber Oct 15, 2026
db015dd
(test): component test for StatsPage with no saved layout
kwhuber Oct 15, 2026
789a27e
(refactor): some deletions to make tests more modular
kwhuber Oct 16, 2026
32e8953
(refactor): utils file for shared functionality
kwhuber Oct 16, 2026
9ff8715
(test): add new Shared page
kwhuber Oct 16, 2026
ecc4941
(fix): changes from coderabbit suggestion
kwhuber Oct 16, 2026
849d535
Merge branch 'main' into issue-8582
kwhuber Oct 22, 2026
1e82e49
(test): add new and multiple Shared pages
kwhuber Oct 22, 2026
451afa6
(test): delete Shared pages
kwhuber Oct 22, 2026
d1daedb
(test): rename page with pencil icon
kwhuber Oct 22, 2026
4fa2579
(test): can't save a page without a name
kwhuber Oct 22, 2026
ea34beb
(test): verify adding long names looks okay
kwhuber Oct 22, 2026
c07908e
(test): add new private page
kwhuber Oct 23, 2026
c199552
(test): add multiple Private pages
kwhuber Oct 23, 2026
77e4f20
(test): delete Private pages
kwhuber Oct 23, 2026
304681c
(test): edit an existing category
kwhuber Oct 23, 2026
49e3539
(test): create a new category
kwhuber Oct 23, 2026
463edd7
(test): add several statistics
kwhuber Oct 23, 2026
c71a726
(test): create a new statistic
kwhuber Oct 23, 2026
bb5a657
(test): add stat item with same name; rename stat item
kwhuber Oct 23, 2026
e71bde9
(test): save new statistic
kwhuber Oct 23, 2026
d403cfd
(test): delete new statistic item
kwhuber Oct 23, 2026
13519c7
(test): delete existing statistics item
kwhuber Oct 23, 2026
6022b31
(test): download as TSV; skip empty categories
kwhuber Oct 30, 2026
891e493
(test): items with no permission are skipped on TSV download
kwhuber Oct 30, 2026
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,122 @@
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 {
addPage,
getCurrentPageName,
getPageNames,
mockStatsRequests,
openAddPageDialog,
renderEmptyStatsPage,
waitForInitialLoad,
} from './statsPageTestUtils';

requireContext();
mockStatsRequests();

const privateSection = statsText.private();
const defaultPrivatePageName = defaultLayoutGenerated[1].label;
const newPageName = 'My Private Page';

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

test('adds an empty page to the end of Private and opens it', async () => {
const { user, getSharedLayout, getPersonalLayout } =
await renderEmptyStatsPage();
const sharedLayout = getSharedLayout();
await addPage(user, newPageName, privateSection);

expect(
screen.queryByRole('dialog', { name: statsText.addPage() })
).not.toBeInTheDocument();
expect(getPageNames(privateSection)).toEqual([
defaultPrivatePageName,
newPageName,
]);
expect(getCurrentPageName(privateSection)).toBe(newPageName);
expect(getCurrentPageName()).toBeUndefined();

expect(getPersonalLayout()?.[1]).toMatchObject({
label: newPageName,
categories: [],
});
expect(
screen.getByRole('button', { name: statsText.addACategory() })
).toBeInTheDocument();

expect(getSharedLayout()).toEqual(sharedLayout);
});

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

const personalLayout = await waitForInitialLoad(getPersonalLayout);
expect(personalLayout.map(({ label }) => label)).toEqual([
defaultPrivatePageName,
]);
expect(getPageNames(privateSection)).toEqual([defaultPrivatePageName]);
expect(getCurrentPageName(privateSection)).toBe(defaultPrivatePageName);
});

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

expect(getPersonalLayout()).toHaveLength(1);
expect(getPageNames(privateSection)).toEqual([defaultPrivatePageName]);
});
});

describe('Adding multiple Private pages', () => {
const newPageNames = ['First Page', 'Second Page', 'Third Page'];

test('adds each page to the end of Private and opens the newest one', async () => {
const { user, getSharedLayout, getPersonalLayout } =
await renderEmptyStatsPage();
const sharedLayout = getSharedLayout();

for (const [index, name] of newPageNames.entries()) {
await addPage(user, name, privateSection);
const expectedNames = [
defaultPrivatePageName,
...newPageNames.slice(0, index + 1),
];
expect(getPageNames(privateSection)).toEqual(expectedNames);
expect(getPersonalLayout()?.map(({ label }) => label)).toEqual(
expectedNames
);
expect(getCurrentPageName(privateSection)).toBe(name);
}

getPersonalLayout()!
.slice(1)
.forEach((page) => expect(page.categories).toEqual([]));
expect(getSharedLayout()).toEqual(sharedLayout);
});

test('Cancel discards every page added in the edit session', async () => {
const { user, getPersonalLayout } = await renderEmptyStatsPage();
for (const name of newPageNames) await addPage(user, name, privateSection);
await user.click(screen.getByRole('button', { name: commonText.cancel() }));

const personalLayout = await waitForInitialLoad(getPersonalLayout);
expect(personalLayout.map(({ label }) => label)).toEqual([
defaultPrivatePageName,
]);
expect(getPageNames(privateSection)).toEqual([defaultPrivatePageName]);
expect(getCurrentPageName(privateSection)).toBe(defaultPrivatePageName);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
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 {
addSharedPage,
getPageButtons,
getPageNames,
mockStatsRequests,
openAddPageDialog,
renderEmptyStatsPage,
} from './statsPageTestUtils';

requireContext();
mockStatsRequests();

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

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, newPageName);

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, newPageName);
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]);
});
});

describe('Adding multiple Shared pages', () => {
const newPageNames = ['First Page', 'Second Page', 'Third Page'];

test('adds each page to the end of Shared and opens the newest one', async () => {
const { user, getSharedLayout } = await renderEmptyStatsPage();

for (const [index, name] of newPageNames.entries()) {
await addSharedPage(user, name);
const expectedNames = [
defaultPageName,
...newPageNames.slice(0, index + 1),
];
expect(getPageNames(statsText.shared())).toEqual(expectedNames);
expect(getSharedLayout()?.map(({ label }) => label)).toEqual(
expectedNames
);

const pages = getPageButtons(statsText.shared());
expect(pages.at(-1)).toHaveAttribute('aria-current', 'page');
pages
.slice(0, -1)
.forEach((page) => expect(page).not.toHaveAttribute('aria-current'));
}

getSharedLayout()!
.slice(1)
.forEach((page) => expect(page.categories).toEqual([]));
});

test('Cancel discards every page added in the edit session', async () => {
const { user, getSharedLayout } = await renderEmptyStatsPage();
for (const name of newPageNames) await addSharedPage(user, name);
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'
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { screen } from '@testing-library/react';
import { statsText } from '../../../localization/stats';
import { requireContext } from '../../../tests/helpers';
import {
addPageWithCategory,
addStat,
findDefaultStat,
getCategoryItems,
mockSavedQueries,
mockStatsRequests,
openChooseStatisticsDialog,
queryStatButton,
renderEmptyStatsPage,
} from './statsPageTestUtils';

requireContext();
mockStatsRequests();
mockSavedQueries();

const statsToAdd = [
findDefaultStat('holdings', 'specimens'),
findDefaultStat('loans', 'openLoansCount'),
findDefaultStat('locality_geography', 'localityCount'),
];

describe('Adding several statistics', () => {
test('"Add" opens the "Choose Statistics" dialog with the default statistics', async () => {
const { user } = await renderEmptyStatsPage();
await addPageWithCategory(user);
const dialog = await openChooseStatisticsDialog(user);

statsToAdd.forEach(({ label }) =>
expect(queryStatButton(dialog, label)).toBeDefined()
);
});

test('adds each chosen statistic to the end of the category', async () => {
const { user, getSharedLayout } = await renderEmptyStatsPage();
await addPageWithCategory(user);

for (const [index, stat] of statsToAdd.entries()) {
await addStat(user, stat);
expect(
screen.queryByRole('dialog', { name: statsText.chooseStatistics() })
).not.toBeInTheDocument();
expect(
getCategoryItems(getSharedLayout).map(
(item) =>
item.type === 'DefaultStat' && [item.categoryName, item.itemName]
)
).toEqual(
statsToAdd
.slice(0, index + 1)
.map(({ categoryName, itemName }) => [categoryName, itemName])
);
}
});

test('a statistic already on the page is no longer offered', async () => {
const { user } = await renderEmptyStatsPage();
await addPageWithCategory(user);
await addStat(user, statsToAdd[0]);

const dialog = await openChooseStatisticsDialog(user);
expect(queryStatButton(dialog, statsToAdd[0].label)).toBeUndefined();
expect(queryStatButton(dialog, statsToAdd[1].label)).toBeDefined();
});
});
Loading
Loading