-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
117 lines (102 loc) · 3.16 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { readFile, unlink } from 'node:fs/promises';
import os from 'node:os';
import path from 'node:path';
import { chromium } from 'playwright'; // 'firefox' or 'webkit' or 'chromium'.
const tmpDir = os.tmpdir();
// https://gs.statcounter.com/screen-resolution-stats
const viewportSizes = {
'Mobile 360x800': { width: 360, height: 800 },
'Mobile 375x812': { width: 375, height: 812 },
'Mobile 390x844': { width: 390, height: 844 },
'Mobile 393x873': { width: 393, height: 873 },
'Mobile 412x915': { width: 412, height: 915 },
'Desktop 1280x720': { width: 1280, height: 720 },
'Desktop 1366x768': { width: 1366, height: 768 },
'Desktop 1440x900': { width: 1440, height: 900 },
'Desktop 1536x864': { width: 1536, height: 864 },
'Desktop 1920x1080': { width: 1920, height: 1080 },
'Tablet 768x1024': { width: 768, height: 1024 },
'Tablet 810x1080': { width: 810, height: 1080 },
'Tablet 820x1180': { width: 820, height: 1180 },
'Tablet 1280x800': { width: 1280, height: 800 },
'Tablet 800x1280': { width: 800, height: 1280 },
};
export const createHar = async (url, opts = {}) => {
const browser = await chromium.launch();
const harFile = path.join(tmpDir, btoa(url));
const context = await browser.newContext({
recordHar: {
path: harFile,
mode: 'full',
},
});
const page = await context.newPage();
context.setDefaultTimeout(2 * 60 * 1000);
page.setViewportSize({ width: 1920, height: 1080 });
if (typeof opts.routes === 'object') {
Object.keys(opts.routes).forEach((key) => {
page.route(key, async (route) => {
const handler = opts.routes[key];
if (typeof handler === 'function') {
await handler(route);
return;
}
await route.fulfill(handler);
});
});
}
await page.goto(url);
await page.waitForLoadState('load');
await page.waitForTimeout(opts.delay || 0);
const renderedHtml = await page.evaluate(
() => document.documentElement.outerHTML,
);
const links = await page.$$eval('a', as => as.map(a => ({
title: a.title,
href: a.href,
text: a.innerText,
target: a.target,
rel: a.rel,
download: a.download,
referrerpolicy: a.referrerPolicy,
type: a.type,
})));
const screenshots = (
!opts.screenshots
? null
: await Promise.all(Object.keys(viewportSizes).map(async (key) => {
const { width, height } = viewportSizes[key];
page.setViewportSize({ width, height });
return {
key,
value: (await page.screenshot()).toString('base64'),
};
}))
);
await context.close();
await page.close();
await browser.close();
const har = await readFile(harFile, 'utf8');
await unlink(harFile);
const harJson = JSON.parse(har);
return {
...harJson,
log: {
...harJson.log,
pages: [
{
...harJson.log.pages[0],
_url: url,
_renderedHtml: renderedHtml,
_links: links,
...(screenshots && {
_screenshots: screenshots.reduce(
(memo, { key, value }) => ({ ...memo, [key]: value }),
{},
),
}),
},
],
},
};
};