|
@@ -2,13 +2,14 @@
|
|
|
* Tests for the ArchivesPage component.
|
|
* Tests for the ArchivesPage component.
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
-import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
|
|
|
|
|
+import { describe, it, expect, beforeEach, afterEach, beforeAll, afterAll } from 'vitest';
|
|
|
import { screen, waitFor, fireEvent } from '@testing-library/react';
|
|
import { screen, waitFor, fireEvent } from '@testing-library/react';
|
|
|
import { render } from '../utils';
|
|
import { render } from '../utils';
|
|
|
import { ArchivesPage } from '../../pages/ArchivesPage';
|
|
import { ArchivesPage } from '../../pages/ArchivesPage';
|
|
|
import { http, HttpResponse } from 'msw';
|
|
import { http, HttpResponse } from 'msw';
|
|
|
import { server } from '../mocks/server';
|
|
import { server } from '../mocks/server';
|
|
|
import { setAuthToken } from '../../api/client';
|
|
import { setAuthToken } from '../../api/client';
|
|
|
|
|
+import { useNavigate } from 'react-router-dom';
|
|
|
|
|
|
|
|
const mockArchives = [
|
|
const mockArchives = [
|
|
|
{
|
|
{
|
|
@@ -655,6 +656,16 @@ describe('ArchivesPage', () => {
|
|
|
// Archive redesign P2: merging changes and removes whole archives, so the
|
|
// Archive redesign P2: merging changes and removes whole archives, so the
|
|
|
// button is there only for those the merge API lets through.
|
|
// button is there only for those the merge API lets through.
|
|
|
describe('merge duplicates button', () => {
|
|
describe('merge duplicates button', () => {
|
|
|
|
|
+ // jsdom has no scrolling, and following an archive link scrolls to its
|
|
|
|
|
+ // card, later than the test that followed it may run.
|
|
|
|
|
+ const scrollIntoView = Element.prototype.scrollIntoView;
|
|
|
|
|
+ beforeAll(() => {
|
|
|
|
|
+ Element.prototype.scrollIntoView = vi.fn();
|
|
|
|
|
+ });
|
|
|
|
|
+ afterAll(() => {
|
|
|
|
|
+ Element.prototype.scrollIntoView = scrollIntoView;
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
const signInWith = (permissions: string[]) => {
|
|
const signInWith = (permissions: string[]) => {
|
|
|
setAuthToken('merge-token', 'session');
|
|
setAuthToken('merge-token', 'session');
|
|
|
server.use(
|
|
server.use(
|
|
@@ -680,6 +691,89 @@ describe('ArchivesPage', () => {
|
|
|
expect(await screen.findByText('No duplicates to merge.')).toBeInTheDocument();
|
|
expect(await screen.findByText('No duplicates to merge.')).toBeInTheDocument();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ it('offers the merge while duplicates exist, until dismissed', async () => {
|
|
|
|
|
+ signInWith(['archives:read_all', 'archives:update_all', 'archives:delete_all']);
|
|
|
|
|
+ server.use(http.get('*/api/v1/archives/merge-count', () => HttpResponse.json({ groups: 3 })));
|
|
|
|
|
+ render(<ArchivesPage />);
|
|
|
|
|
+
|
|
|
|
|
+ const banner = await screen.findByTestId('merge-banner');
|
|
|
|
|
+ expect(banner).toHaveTextContent('3 group(s) of archives hold the same file');
|
|
|
|
|
+ fireEvent.click(screen.getByRole('button', { name: 'Dismiss' }));
|
|
|
|
|
+
|
|
|
|
|
+ await waitFor(() => expect(screen.queryByTestId('merge-banner')).toBeNull());
|
|
|
|
|
+ expect(window.localStorage.setItem).toHaveBeenCalledWith('archiveMergeBannerDismissed', '3');
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('offers it again once the count has changed since it was dismissed', async () => {
|
|
|
|
|
+ vi.mocked(window.localStorage.getItem).mockImplementation((key: string) =>
|
|
|
|
|
+ key === 'archiveMergeBannerDismissed' ? '3' : null,
|
|
|
|
|
+ );
|
|
|
|
|
+ signInWith(['archives:read_all', 'archives:update_all', 'archives:delete_all']);
|
|
|
|
|
+ server.use(http.get('*/api/v1/archives/merge-count', () => HttpResponse.json({ groups: 4 })));
|
|
|
|
|
+ render(<ArchivesPage />);
|
|
|
|
|
+
|
|
|
|
|
+ expect(await screen.findByTestId('merge-banner')).toBeInTheDocument();
|
|
|
|
|
+ vi.mocked(window.localStorage.getItem).mockReset();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('counts again when the archives change', async () => {
|
|
|
|
|
+ signInWith(['archives:read_all', 'archives:update_all', 'archives:delete_all']);
|
|
|
|
|
+ let groups = 1;
|
|
|
|
|
+ server.use(http.get('*/api/v1/archives/merge-count', () => HttpResponse.json({ groups })));
|
|
|
|
|
+ // Following an archive link reloads the list, as a delete or a new print does.
|
|
|
|
|
+ function GoTo() {
|
|
|
|
|
+ const navigate = useNavigate();
|
|
|
|
|
+ return <button onClick={() => navigate('/archives?highlight=1')}>go</button>;
|
|
|
|
|
+ }
|
|
|
|
|
+ render(<><ArchivesPage /><GoTo /></>);
|
|
|
|
|
+ await screen.findByTestId('merge-banner');
|
|
|
|
|
+
|
|
|
|
|
+ groups = 0;
|
|
|
|
|
+ fireEvent.click(screen.getByText('go'));
|
|
|
|
|
+
|
|
|
|
|
+ await waitFor(() => expect(screen.queryByTestId('merge-banner')).toBeNull());
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('stays dismissed when merging some left fewer', async () => {
|
|
|
|
|
+ vi.mocked(window.localStorage.getItem).mockImplementation((key: string) =>
|
|
|
|
|
+ key === 'archiveMergeBannerDismissed' ? '3' : null,
|
|
|
|
|
+ );
|
|
|
|
|
+ signInWith(['archives:read_all', 'archives:update_all', 'archives:delete_all']);
|
|
|
|
|
+ let counted = false;
|
|
|
|
|
+ server.use(
|
|
|
|
|
+ http.get('*/api/v1/archives/merge-count', () => {
|
|
|
|
|
+ counted = true;
|
|
|
|
|
+ return HttpResponse.json({ groups: 2 });
|
|
|
|
|
+ }),
|
|
|
|
|
+ );
|
|
|
|
|
+ render(<ArchivesPage />);
|
|
|
|
|
+
|
|
|
|
|
+ await waitFor(() => expect(counted).toBe(true));
|
|
|
|
|
+ await screen.findByRole('button', { name: 'Merge duplicates' });
|
|
|
|
|
+ expect(screen.queryByTestId('merge-banner')).toBeNull();
|
|
|
|
|
+ vi.mocked(window.localStorage.getItem).mockReset();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ it('stays dismissed while the count is the same', async () => {
|
|
|
|
|
+ vi.mocked(window.localStorage.getItem).mockImplementation((key: string) =>
|
|
|
|
|
+ key === 'archiveMergeBannerDismissed' ? '3' : null,
|
|
|
|
|
+ );
|
|
|
|
|
+ signInWith(['archives:read_all', 'archives:update_all', 'archives:delete_all']);
|
|
|
|
|
+ let counted = false;
|
|
|
|
|
+ server.use(
|
|
|
|
|
+ http.get('*/api/v1/archives/merge-count', () => {
|
|
|
|
|
+ counted = true;
|
|
|
|
|
+ return HttpResponse.json({ groups: 3 });
|
|
|
|
|
+ }),
|
|
|
|
|
+ );
|
|
|
|
|
+ render(<ArchivesPage />);
|
|
|
|
|
+
|
|
|
|
|
+ await waitFor(() => expect(counted).toBe(true));
|
|
|
|
|
+ await screen.findByRole('button', { name: 'Merge duplicates' });
|
|
|
|
|
+ expect(screen.queryByTestId('merge-banner')).toBeNull();
|
|
|
|
|
+ vi.mocked(window.localStorage.getItem).mockReset();
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
it('is offered in the Duplicates collection', async () => {
|
|
it('is offered in the Duplicates collection', async () => {
|
|
|
signInWith(['archives:read_all', 'archives:update_all', 'archives:delete_all']);
|
|
signInWith(['archives:read_all', 'archives:update_all', 'archives:delete_all']);
|
|
|
render(<ArchivesPage />);
|
|
render(<ArchivesPage />);
|