Skip to content

Commit 001bce1

Browse files
committed
Premium Analytics: Share the CSV capture helper with the Top posts tests
1 parent e33a3e5 commit 001bce1

3 files changed

Lines changed: 15 additions & 36 deletions

File tree

‎projects/packages/premium-analytics/widgets/clicks/__tests__/clicks.test.tsx‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*/
44
import { getDefaultQueryParams, queryClient } from '@jetpack-premium-analytics/data';
55
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
6+
import userEvent from '@testing-library/user-event';
67
import apiFetch from '@wordpress/api-fetch';
78
/**
89
* Internal dependencies
@@ -405,15 +406,14 @@ describe( 'ClicksWidget CSV export', () => {
405406
<ClicksWidget attributes={ { reportParams: { from: '2026-03-01', to: '2026-03-10' } } } />
406407
);
407408

408-
// eslint-disable-next-line testing-library/prefer-user-event -- @testing-library/user-event is not a direct dep of this package.
409-
fireEvent.click(
409+
const user = userEvent.setup( { advanceTimers: jest.advanceTimersByTime } );
410+
await user.click(
410411
await screen.findByRole( 'button', { name: /view clicked links for wordpress\.org/i } )
411412
);
412413
await expect(
413414
screen.findByRole( 'button', { name: /view all clicks/i } )
414415
).resolves.toBeInTheDocument();
415-
// eslint-disable-next-line testing-library/prefer-user-event -- @testing-library/user-event is not a direct dep of this package.
416-
fireEvent.click( screen.getByRole( 'button', { name: /Download CSV/ } ) );
416+
await user.click( screen.getByRole( 'button', { name: /Download CSV/ } ) );
417417
await waitFor( () => expect( downloads.files ).toHaveLength( 1 ) );
418418

419419
const lines = await downloads.lines();

‎projects/packages/premium-analytics/widgets/test-utils.tsx‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export function queryClientWrapper( { children }: { children: ReactNode } ) {
1515
/**
1616
* Capture the files the CSV helpers save; jsdom can neither create object URLs nor navigate.
1717
*
18-
* @return The saved files, a reader for one file's lines, and a restore for `afterEach`.
18+
* @return The saved files, a reader for the first file's lines, and a restore for `afterEach`.
1919
*/
2020
export function captureCsvDownloads() {
2121
const files: { filename: string; blob: Blob }[] = [];
@@ -41,8 +41,7 @@ export function captureCsvDownloads() {
4141

4242
return {
4343
files,
44-
lines: async ( index = 0 ) =>
45-
( await files[ index ].blob.text() ).replace( '', '' ).split( '\n' ),
44+
lines: async () => ( await files[ 0 ].blob.text() ).replace( '\ufeff', '' ).split( '\n' ),
4645
restore: () => {
4746
clickSpy.mockRestore();
4847
window.URL.createObjectURL = originalCreateObjectURL;

‎projects/packages/premium-analytics/widgets/top-posts/__tests__/top-posts.test.tsx‎

Lines changed: 9 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type { ReactNode } from 'react';
1111
/**
1212
* Internal dependencies
1313
*/
14+
import { captureCsvDownloads } from '../../test-utils';
1415
import TopPostsWidget from '../render';
1516

1617
jest.mock( '@automattic/jetpack-script-data', () => ( {
@@ -276,43 +277,25 @@ describe( 'TopPostsWidget', () => {
276277
} );
277278

278279
describe( 'CSV export', () => {
279-
let blobs: Blob[];
280-
let clickSpy: jest.SpyInstance;
281-
let originalCreateObjectURL: typeof window.URL.createObjectURL;
282-
let originalRevokeObjectURL: typeof window.URL.revokeObjectURL;
280+
let downloads: ReturnType< typeof captureCsvDownloads >;
283281

284282
beforeEach( () => {
285283
jest.useFakeTimers();
286-
blobs = [];
287-
originalCreateObjectURL = window.URL.createObjectURL;
288-
originalRevokeObjectURL = window.URL.revokeObjectURL;
289-
// jsdom defines neither, so `jest.spyOn` has nothing to wrap.
290-
const createObjectURL = jest.fn( ( blob: Blob ) => {
291-
blobs.push( blob );
292-
return 'blob:mock';
293-
} );
294-
const revokeObjectURL = jest.fn();
295-
window.URL.createObjectURL = createObjectURL;
296-
window.URL.revokeObjectURL = revokeObjectURL;
297-
// An anchor click would reach jsdom's unimplemented navigation.
298-
clickSpy = jest.spyOn( HTMLAnchorElement.prototype, 'click' ).mockImplementation( () => {} );
284+
downloads = captureCsvDownloads();
299285
} );
300286

301287
afterEach( () => {
302288
jest.useRealTimers();
303-
clickSpy.mockRestore();
304-
window.URL.createObjectURL = originalCreateObjectURL;
305-
window.URL.revokeObjectURL = originalRevokeObjectURL;
289+
downloads.restore();
306290
} );
307291

308292
async function downloadCsvLines() {
309-
// This package does not depend on @testing-library/user-event.
310-
// eslint-disable-next-line testing-library/prefer-user-event
311-
fireEvent.click( await screen.findByRole( 'button', { name: /Download CSV/ } ) );
293+
const user = userEvent.setup( { advanceTimers: jest.advanceTimersByTime } );
294+
await user.click( await screen.findByRole( 'button', { name: /Download CSV/ } ) );
312295

313-
await waitFor( () => expect( blobs ).toHaveLength( 1 ) );
296+
await waitFor( () => expect( downloads.files ).toHaveLength( 1 ) );
314297

315-
return ( await blobs[ 0 ].text() ).replace( '\ufeff', '' ).split( '\n' );
298+
return downloads.lines();
316299
}
317300

318301
it( 'downloads the full Posts & pages report instead of the rows on screen', async () => {
@@ -404,10 +387,7 @@ describe( 'TopPostsWidget', () => {
404387
'"Tags","80",""',
405388
'"Tags > video","80","https://example.com/tag/video/"',
406389
] );
407-
expect( clickSpy.mock.contexts[ 0 ] ).toHaveProperty(
408-
'download',
409-
'archives-2026-03-01_2026-03-10.csv'
410-
);
390+
expect( downloads.files[ 0 ].filename ).toBe( 'archives-2026-03-01_2026-03-10.csv' );
411391
} );
412392
} );
413393

0 commit comments

Comments
 (0)