Skip to content
Merged
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
42 changes: 2 additions & 40 deletions apps/ssr-tests-v9/src/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,14 @@ import * as fs from 'fs';
import * as path from 'path';
import type { Browser } from 'puppeteer';

import { PROVIDER_ID } from './utils/constants';
import { hrToSeconds } from './utils/helpers';
import { launchBrowser } from './utils/launchBrowser';
import { visitPage } from './utils/visitPage';

class RenderError extends Error {
public name = 'RangeError';
}

export async function runTest(browser: Browser, url: string): Promise<void> {
const page = await browser.newPage();
await page.setRequestInterception(true);

let error: Error | undefined;

page.on('console', message => {
if (message.type() === 'error') {
// Ignoring network errors as we have an interceptor that prevents loading everything except our JS bundle
if (!message.text().includes('net::ERR_FAILED')) {
error = new RenderError(message.text());
}
}
});

page.on('request', request => {
// Our interceptor allows only our HTML and JS output
if (request.url() === url || request.url().endsWith('/out-esm.js')) {
return request.continue();
}

return request.abort();
});

page.on('pageerror', err => {
error = err;
});

await page.goto(url);
await page.waitForSelector(`#${PROVIDER_ID}`);

await page.close();

if (error) {
throw error;
}
}

async function test(): Promise<void> {
const startTime = process.hrtime();
console.log('Starting a browser...');
Expand All @@ -68,7 +30,7 @@ async function test(): Promise<void> {
const url = `file://${htmlPath}`;
console.log(`Using "${url}"`);

await runTest(browser, url);
await visitPage(browser, url);
console.log(`Test finished successfully in ${hrToSeconds(process.hrtime(startTime))}`);
} finally {
if (browser) {
Expand Down
34 changes: 34 additions & 0 deletions apps/ssr-tests-v9/src/utils/visitPage.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type { Page } from 'puppeteer';
import { visitUrl } from './visitPage';

// eslint-disable-next-line @typescript-eslint/no-empty-function
const noop = () => {};

describe('visitUrl', () => {
it('calls .goto() 5 times before a failure', async () => {
expect.assertions(2);

jest.spyOn(console, 'warn').mockImplementation(noop);
jest.spyOn(console, 'error').mockImplementation(noop);

const pageMock: Partial<Page> = {
goto: jest.fn().mockImplementation(() => Promise.reject(new Error('page wont open - mock'))),
};

await expect(visitUrl(pageMock as Page, 'https://localhost:8080')).rejects.toMatchInlineSnapshot(
`[Error: page wont open - mock]`,
);
expect(pageMock.goto).toHaveBeenCalledTimes(5);
});

it('calls .goto once if successful', async () => {
expect.assertions(2);

const pageMock: Partial<Page> = {
goto: jest.fn(),
};

await expect(visitUrl(pageMock as Page, 'https://localhost:8080')).resolves.toBeUndefined();
expect(pageMock.goto).toHaveBeenCalledTimes(1);
});
});
65 changes: 65 additions & 0 deletions apps/ssr-tests-v9/src/utils/visitPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import type { Browser, Page } from 'puppeteer';
import { PROVIDER_ID } from './constants';

class RenderError extends Error {
public name = 'RangeError';
}

export async function visitUrl(page: Page, url: string) {
let attempt = 1;

while (attempt <= 5) {
try {
await page.goto(url, { timeout: 10 * 1000 /* 10 seconds */ });
break;
} catch (err) {
if (attempt === 5) {
console.error(`Failed to navigate to a page after 5 attempts...`);
throw err;
}

console.warn('A browser failed to navigate to a page, retrying...');
console.warn(err);

attempt++;
}
}
}

export async function visitPage(browser: Browser, url: string) {
const page = await browser.newPage();
await page.setRequestInterception(true);

let error: Error | undefined;

page.on('console', message => {
if (message.type() === 'error') {
// Ignoring network errors as we have an interceptor that prevents loading everything except our JS bundle
if (!message.text().includes('net::ERR_FAILED')) {
error = new RenderError(message.text());
}
}
});

page.on('request', request => {
// Our interceptor allows only our HTML and JS output
if (request.url() === url || request.url().endsWith('/out-esm.js')) {
return request.continue();
}

return request.abort();
});

page.on('pageerror', err => {
error = err;
});

await visitUrl(page, url);

await page.waitForSelector(`#${PROVIDER_ID}`);
await page.close();

if (error) {
throw error;
}
}