Skip to content

Commit 3c0e337

Browse files
committed
feature(webpage-impact): add support for custom user interactions
Signed-off-by: alexzurbonsen <[email protected]>
1 parent 75ab7b6 commit 3c0e337

File tree

3 files changed

+68
-5
lines changed

3 files changed

+68
-5
lines changed

example-manifests/measure-webpage.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ initialize:
1414
config:
1515
url: https://www.tngtech.com
1616
scrollToBottom: true
17-
computeReloadRati: true
17+
computeReloadRatio: true
18+
customUserInteraction: '/absolute/path/to/your/script.js'
1819
'co2js':
1920
method: Co2js
2021
path: '@tngtech/if-webpage-plugins'

src/lib/webpage-impact/README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ The follwing config parameters are optional:
2525
- `accept`: string https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept
2626
- `accept-encoding`: array of allowed encodings (a single encoding can also be passed as a string) https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding
2727

28+
Experimental:
29+
30+
- `customUserInteraction`: absolute path to a Javascript Common JS module, that exports a function with the signature `userInteraction: (page: Page) => Promise<void>`. For an example see below. Setting `customUserInteraction` cannot be set together with `scrollToBottom`.
31+
2832
### Returns
2933

3034
- `network/data/bytes`: page weight in bytes
@@ -81,3 +85,26 @@ tree:
8185
- webpage-impact
8286
inputs:
8387
```
88+
89+
## Experimental: Custom user interactions
90+
91+
Example script:
92+
93+
```js
94+
const userInteraction = async page => {
95+
// on tngtech.com click on the "Leistungen" link
96+
await page.locator('#menu > ul > li:nth-child(1) > a').click();
97+
await page.waitForNavigation();
98+
99+
// for debugging purposes
100+
await page.screenshot({
101+
path: '/absolute/path/image.png',
102+
});
103+
};
104+
105+
exports.userInteraction = userInteraction;
106+
```
107+
108+
Puppeteer docs on page interactions: https://pptr.dev/guides/page-interactions
109+
110+
TODO: How to deal with the reload option?

src/lib/webpage-impact/index.ts

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type WebpageImpactOptions = {
2424
reload: boolean;
2525
cacheEnabled: boolean;
2626
scrollToBottom?: boolean;
27+
customUserInteraction?: string;
2728
};
2829

2930
type ResourceBase = {
@@ -36,6 +37,10 @@ type Resource = ResourceBase & {transferSize: number};
3637

3738
type Device = keyof typeof KnownDevices;
3839

40+
interface CustomUserInteraction {
41+
userInteraction: (page: Page) => Promise<void>;
42+
}
43+
3944
const LOGGER_PREFIX = 'WebpageImpact';
4045

4146
const ALLOWED_ENCODINGS = [
@@ -176,6 +181,7 @@ const WebpageImpactUtils = () => {
176181
reload: false,
177182
cacheEnabled: false,
178183
scrollToBottom: config?.scrollToBottom,
184+
customUserInteraction: config?.customUserInteraction,
179185
});
180186

181187
let reloadedResources: Resource[] | undefined;
@@ -203,7 +209,12 @@ const WebpageImpactUtils = () => {
203209
const loadPageResources = async (
204210
page: Page,
205211
url: string,
206-
{reload, cacheEnabled, scrollToBottom}: WebpageImpactOptions
212+
{
213+
reload,
214+
cacheEnabled,
215+
scrollToBottom,
216+
customUserInteraction,
217+
}: WebpageImpactOptions
207218
): Promise<Resource[]> => {
208219
try {
209220
await page.setCacheEnabled(cacheEnabled);
@@ -254,14 +265,19 @@ const WebpageImpactUtils = () => {
254265

255266
if (!reload) {
256267
await page.goto(url, {waitUntil: 'networkidle0'});
268+
if (customUserInteraction) {
269+
const module = await import(customUserInteraction);
270+
if (iscustomUserInteraction(module)) {
271+
await module.userInteraction(page);
272+
}
273+
}
257274
} else {
275+
console.log('before reload');
258276
await page.reload({waitUntil: 'networkidle0'});
259277
}
260278

261-
if (scrollToBottom) {
262-
// await page.screenshot({path: './TOP.png'});
279+
if (!customUserInteraction && scrollToBottom) {
263280
await page.evaluate(scrollToBottomOfPage);
264-
// await page.screenshot({path: './BOTTOM.png'});
265281
}
266282

267283
await cdpSession.detach();
@@ -274,6 +290,15 @@ const WebpageImpactUtils = () => {
274290
}
275291
};
276292

293+
const iscustomUserInteraction = (
294+
customUserInteraction: any
295+
): customUserInteraction is CustomUserInteraction => {
296+
return (
297+
'userInteraction' in customUserInteraction &&
298+
typeof customUserInteraction['userInteraction'] === 'function'
299+
);
300+
};
301+
277302
const mergeCdpData = (
278303
cdpResponses: Record<string, ResourceBase>,
279304
cdpTransferSizes: Record<string, {transferSize: number}>
@@ -375,6 +400,7 @@ const WebpageImpactUtils = () => {
375400
mobileDevice: z.string().optional(),
376401
emulateNetworkConditions: z.string().optional(),
377402
scrollToBottom: z.boolean().optional(),
403+
customUserInteraction: z.string().optional(),
378404
headers: z
379405
.object({
380406
accept: z.string().optional(),
@@ -417,6 +443,15 @@ const WebpageImpactUtils = () => {
417443
PredefinedNetworkConditions
418444
).join(', ')}.`,
419445
}
446+
)
447+
.refine(
448+
data => {
449+
return !(data?.scrollToBottom && data?.customUserInteraction);
450+
},
451+
{
452+
message:
453+
'`scrollToBottom: true` and `customUserInteraction` cannot be provided together.',
454+
}
420455
);
421456

422457
return validate<z.infer<typeof configSchema>>(configSchema, config);

0 commit comments

Comments
 (0)