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
74 changes: 73 additions & 1 deletion node/playwright-wrapper/__tests__/network.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ jest.mock('uuid', () => ({
}));

import { logger } from '../browser_logger';
import { waitForRequest } from '../network';
import { _waitForDownload, waitForRequest } from '../network';

const mockLogger = jest.mocked(logger);

Expand Down Expand Up @@ -222,3 +222,75 @@ describe('waitForRequest', () => {
expect(result.log).toContain('10000ms');
});
});

function makeMockDownload(
overrides: Partial<{
suggestedFilename: jest.Mock;
createReadStream: jest.Mock;
cancel: jest.Mock;
saveAs: jest.Mock;
path: jest.Mock;
}> = {},
) {
return {
suggestedFilename: jest.fn().mockReturnValue('downloaded.txt'),
createReadStream: jest.fn().mockResolvedValue({}),
cancel: jest.fn().mockResolvedValue(undefined),
saveAs: jest.fn().mockResolvedValue(undefined),
path: jest.fn().mockResolvedValue('/tmp/downloaded.txt'),
...overrides,
} as any;
}

function makeMockDownloadPage(waitForEvent: jest.Mock) {
return { waitForEvent } as any;
}

function makeMockDownloadState() {
return {
activeBrowser: {
browser: { _options: {} },
page: { activeDownloads: new Map() },
},
} as any;
}

describe('_waitForDownload', () => {
beforeEach(() => {
jest.clearAllMocks();
});

it('passes the download_timeout to waitForEvent so it is not bound by the page default timeout', async () => {
const downloadObject = makeMockDownload();
const waitForEvent = jest.fn().mockResolvedValue(downloadObject);
const mockPage = makeMockDownloadPage(waitForEvent);

await _waitForDownload(mockPage, makeMockDownloadState(), '', 30000, true);

expect(waitForEvent).toHaveBeenCalledWith('download', { timeout: 30000 });
});

it('disables the waitForEvent timeout when no download_timeout is given', async () => {
const downloadObject = makeMockDownload();
const waitForEvent = jest.fn().mockResolvedValue(downloadObject);
const mockPage = makeMockDownloadPage(waitForEvent);

await _waitForDownload(mockPage, makeMockDownloadState(), '', 0, true);

expect(waitForEvent).toHaveBeenCalledWith('download', { timeout: 0 });
});

it('cancels the download and throws when it does not finish within download_timeout', async () => {
expect.assertions(2);
const downloadObject = makeMockDownload({
createReadStream: jest.fn().mockImplementation(() => new Promise(() => {})),
});
const waitForEvent = jest.fn().mockResolvedValue(downloadObject);
const mockPage = makeMockDownloadPage(waitForEvent);

await expect(_waitForDownload(mockPage, makeMockDownloadState(), '', 1, true)).rejects.toThrow(
'Download failed, Timeout exceeded.',
);
expect(downloadObject.cancel).toHaveBeenCalledTimes(1);
});
});
6 changes: 4 additions & 2 deletions node/playwright-wrapper/network.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ export async function _waitForDownload(
downloadTimeout: number,
waitForFinished: boolean,
): Promise<pb.Response_Json> {
const downloadObject = await page.waitForEvent('download');
const downloadWaitStarted = Date.now();
const downloadObject = await page.waitForEvent('download', { timeout: downloadTimeout });

// @ts-ignore
const downloadsPath = state.activeBrowser.browser?._options?.downloadsPath;
Expand Down Expand Up @@ -203,9 +204,10 @@ export async function _waitForDownload(
}
}
if (downloadTimeout > 0) {
const remainingTimeout = Math.max(downloadTimeout - (Date.now() - downloadWaitStarted), 0);
const readStream = await Promise.race([
downloadObject.createReadStream(),
new Promise((resolve) => setTimeout(resolve, downloadTimeout)),
new Promise((resolve) => setTimeout(resolve, remainingTimeout)),
]);
if (!readStream) {
await downloadObject.cancel();
Expand Down