Skip to content

Commit 8755661

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

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
@@ -13,7 +13,8 @@ initialize:
1313
path: '@tngtech/if-webpage-plugins'
1414
config:
1515
scrollToBottom: true
16-
url: https://www.tngtech.com
16+
url: https://www.sueddeutsche.de
17+
customUserInteraction: '/absolute/path/to/your/script.js'
1718
'co2js':
1819
method: Co2js
1920
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
@@ -24,6 +24,10 @@ The follwing config parameters are optional:
2424
- `accept`: string https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept
2525
- `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
2626

27+
Experimental:
28+
29+
- `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`.
30+
2731
### Returns
2832

2933
- `network/data/bytes`: page weight in bytes
@@ -80,3 +84,26 @@ tree:
8084
- webpage-impact
8185
inputs:
8286
```
87+
88+
## Experimental: Custom user interactions
89+
90+
Example script:
91+
92+
```js
93+
const userInteraction = async page => {
94+
// on tngtech.com click on the "Leistungen" link
95+
await page.locator('#menu > ul > li:nth-child(1) > a').click();
96+
await page.waitForNavigation();
97+
98+
// for debugging purposes
99+
await page.screenshot({
100+
path: '/absolute/path/image.png',
101+
});
102+
};
103+
104+
exports.userInteraction = userInteraction;
105+
```
106+
107+
Puppeteer docs on page interactions: https://pptr.dev/guides/page-interactions
108+
109+
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 = [
@@ -183,6 +188,7 @@ const WebpageImpactUtils = () => {
183188
reload: false,
184189
cacheEnabled: false,
185190
scrollToBottom: config?.scrollToBottom,
191+
customUserInteraction: config?.customUserInteraction,
186192
});
187193

188194
let reloadedResources: Resource[] | undefined;
@@ -210,7 +216,12 @@ const WebpageImpactUtils = () => {
210216
const loadPageResources = async (
211217
page: Page,
212218
url: string,
213-
{reload, cacheEnabled, scrollToBottom}: WebpageImpactOptions
219+
{
220+
reload,
221+
cacheEnabled,
222+
scrollToBottom,
223+
customUserInteraction,
224+
}: WebpageImpactOptions
214225
): Promise<Resource[]> => {
215226
try {
216227
await page.setCacheEnabled(cacheEnabled);
@@ -261,14 +272,19 @@ const WebpageImpactUtils = () => {
261272

262273
if (!reload) {
263274
await page.goto(url, {waitUntil: 'networkidle0'});
275+
if (customUserInteraction) {
276+
const module = await import(customUserInteraction);
277+
if (iscustomUserInteraction(module)) {
278+
await module.userInteraction(page);
279+
}
280+
}
264281
} else {
282+
console.log('before reload');
265283
await page.reload({waitUntil: 'networkidle0'});
266284
}
267285

268-
if (scrollToBottom) {
269-
// await page.screenshot({path: './TOP.png'});
286+
if (!customUserInteraction && scrollToBottom) {
270287
await page.evaluate(scrollToBottomOfPage);
271-
// await page.screenshot({path: './BOTTOM.png'});
272288
}
273289

274290
await cdpSession.detach();
@@ -281,6 +297,15 @@ const WebpageImpactUtils = () => {
281297
}
282298
};
283299

300+
const iscustomUserInteraction = (
301+
customUserInteraction: any
302+
): customUserInteraction is CustomUserInteraction => {
303+
return (
304+
'userInteraction' in customUserInteraction &&
305+
typeof customUserInteraction['userInteraction'] === 'function'
306+
);
307+
};
308+
284309
const mergeCdpData = (
285310
cdpResponses: Record<string, ResourceBase>,
286311
cdpTransferSizes: Record<string, {transferSize: number}>
@@ -381,6 +406,7 @@ const WebpageImpactUtils = () => {
381406
mobileDevice: z.string().optional(),
382407
emulateNetworkConditions: z.string().optional(),
383408
scrollToBottom: z.boolean().optional(),
409+
customUserInteraction: z.string().optional(),
384410
headers: z
385411
.object({
386412
accept: z.string().optional(),
@@ -428,6 +454,15 @@ const WebpageImpactUtils = () => {
428454
PredefinedNetworkConditions
429455
).join(', ')}.`,
430456
}
457+
)
458+
.refine(
459+
data => {
460+
return !(data?.scrollToBottom && data?.customUserInteraction);
461+
},
462+
{
463+
message:
464+
'`scrollToBottom: true` and `customUserInteraction` cannot be provided together.',
465+
}
431466
);
432467

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

0 commit comments

Comments
 (0)