Skip to content

Commit

Permalink
core(replay): @puppeteer/replay stringify extension (#14146)
Browse files Browse the repository at this point in the history
  • Loading branch information
adamraine authored Aug 16, 2022
1 parent 6c04777 commit 5250b82
Show file tree
Hide file tree
Showing 13 changed files with 1,336 additions and 5 deletions.
1 change: 1 addition & 0 deletions .github/workflows/unit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ jobs:
- run: yarn install --frozen-lockfile --network-timeout 1000000
- run: yarn build-report
- run: yarn reset-link

# Run pptr tests using ToT Chrome instead of stable default.
- name: Define ToT chrome path
Expand Down
22 changes: 22 additions & 0 deletions cli/test/fixtures/flow/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!--
* Copyright 2022 The Lighthouse Authors. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-->
<html>
<body>
<div id="list"></div>
<h1>Landing page for our user flows!</h1>
<button id="add-item">Add item</button>
<a id="link" href="/flow/next.html">Link to new page!</a>
</body>
<script>
const button = document.getElementById('add-item');
button.onclick = async () => {
const list = document.getElementById('list');
const item = document.createElement('h3');
item.textContent = 'New item!';
list.append(item);
}
</script>
</html>
15 changes: 15 additions & 0 deletions cli/test/fixtures/flow/next.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<!--
* Copyright 2022 The Lighthouse Authors. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
-->
<html>
<body>
<h1>New page after clicking the link!</h1>
<details id="content">
<summary>Hidden content here:</summary>
Hello there!
</details>
</body>
</html>

107 changes: 107 additions & 0 deletions core/fraggle-rock/replay/stringify-extension.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* @license Copyright 2022 The Lighthouse Authors. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/
'use strict';

import * as PuppeteerReplay from '@puppeteer/replay';

/**
* @param {PuppeteerReplay.Schema.Step} step
* @return {boolean}
*/
function isNavigationStep(step) {
return Boolean(
step.type === 'navigate' ||
step.assertedEvents?.some(event => event.type === 'navigation')
);
}

class LighthouseStringifyExtension extends PuppeteerReplay.PuppeteerStringifyExtension {
#isProcessingTimespan = false;

/**
* @override
* @param {PuppeteerReplay.LineWriter} out
* @param {PuppeteerReplay.Schema.UserFlow} flow
*/
async beforeAllSteps(out, flow) {
out.appendLine(`const fs = require('fs');`);

let isMobile = true;
for (const step of flow.steps) {
if (step.type !== 'setViewport') continue;
isMobile = step.isMobile;
}

await super.beforeAllSteps(out, flow);

const configContext = {
settingsOverrides: {
screenEmulation: {
disabled: true,
},
},
};
out.appendLine(`const configContext = ${JSON.stringify(configContext)}`);
if (isMobile) {
out.appendLine(`const config = undefined;`);
} else {
// eslint-disable-next-line max-len
out.appendLine(`const config = (await import('lighthouse/core/config/desktop-config.js')).default;`);
}

out.appendLine(`const lhApi = await import('lighthouse/core/fraggle-rock/api.js');`);
// eslint-disable-next-line max-len
out.appendLine(`const lhFlow = await lhApi.startFlow(page, {name: ${JSON.stringify(flow.title)}, config, configContext});`);
}

/**
* @override
* @param {PuppeteerReplay.LineWriter} out
* @param {PuppeteerReplay.Schema.Step} step
* @param {PuppeteerReplay.Schema.UserFlow} flow
*/
async stringifyStep(out, step, flow) {
if (step.type === 'setViewport') {
await super.stringifyStep(out, step, flow);
return;
}

const isNavigation = isNavigationStep(step);

if (isNavigation) {
if (this.#isProcessingTimespan) {
out.appendLine(`await lhFlow.endTimespan();`);
this.#isProcessingTimespan = false;
}
out.appendLine(`await lhFlow.startNavigation();`);
} else if (!this.#isProcessingTimespan) {
out.appendLine(`await lhFlow.startTimespan();`);
this.#isProcessingTimespan = true;
}

await super.stringifyStep(out, step, flow);

if (isNavigation) {
out.appendLine(`await lhFlow.endNavigation();`);
}
}

/**
* @override
* @param {PuppeteerReplay.LineWriter} out
* @param {PuppeteerReplay.Schema.UserFlow} flow
*/
async afterAllSteps(out, flow) {
if (this.#isProcessingTimespan) {
out.appendLine(`await lhFlow.endTimespan();`);
}
out.appendLine(`const lhFlowReport = await lhFlow.generateReport();`);
out.appendLine(`fs.writeFileSync(__dirname + '/flow.report.html', lhFlowReport)`);
await super.afterAllSteps(out, flow);
}
}

export default LighthouseStringifyExtension;
102 changes: 102 additions & 0 deletions core/test/fixtures/fraggle-rock/replay/desktop-test-flow.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
{
"title": "Test Flow on Desktop",
"steps": [
{
"type": "setViewport",
"width": 757,
"height": 988,
"deviceScaleFactor": 1,
"isMobile": false,
"hasTouch": false,
"isLandscape": false
},
{
"type": "navigate",
"url": "http://localhost:10200/flow/index.html",
"assertedEvents": [
{
"type": "navigation",
"url": "http://localhost:10200/flow/index.html",
"title": ""
}
]
},
{
"type": "click",
"target": "main",
"selectors": [
[
"aria/Add item"
],
[
"#add-item"
]
],
"offsetY": 13.5625,
"offsetX": 61
},
{
"type": "click",
"target": "main",
"selectors": [
[
"aria/Add item"
],
[
"#add-item"
]
],
"offsetY": 4.125,
"offsetX": 42
},
{
"type": "click",
"target": "main",
"selectors": [
[
"aria/Add item"
],
[
"#add-item"
]
],
"offsetY": 8.40625,
"offsetX": 50
},
{
"type": "click",
"target": "main",
"selectors": [
[
"aria/Link to new page!"
],
[
"#link"
]
],
"offsetY": 3.6875,
"offsetX": 53.390625,
"assertedEvents": [
{
"type": "navigation",
"url": "http://localhost:10200/flow/next.html",
"title": ""
}
]
},
{
"type": "click",
"target": "main",
"selectors": [
[
"aria/Hidden content here:"
],
[
"#content > summary"
]
],
"offsetY": 10.5625,
"offsetX": 6
}
]
}
102 changes: 102 additions & 0 deletions core/test/fixtures/fraggle-rock/replay/mobile-test-flow.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
{
"title": "Test Flow on Mobile",
"steps": [
{
"type": "setViewport",
"width": 300,
"height": 600,
"deviceScaleFactor": 3,
"isMobile": true,
"hasTouch": true,
"isLandscape": false
},
{
"type": "navigate",
"url": "http://localhost:10200/flow/index.html",
"assertedEvents": [
{
"type": "navigation",
"url": "http://localhost:10200/flow/index.html",
"title": ""
}
]
},
{
"type": "click",
"target": "main",
"selectors": [
[
"aria/Add item"
],
[
"#add-item"
]
],
"offsetY": 13.5625,
"offsetX": 61
},
{
"type": "click",
"target": "main",
"selectors": [
[
"aria/Add item"
],
[
"#add-item"
]
],
"offsetY": 4.125,
"offsetX": 42
},
{
"type": "click",
"target": "main",
"selectors": [
[
"aria/Add item"
],
[
"#add-item"
]
],
"offsetY": 8.40625,
"offsetX": 50
},
{
"type": "click",
"target": "main",
"selectors": [
[
"aria/Link to new page!"
],
[
"#link"
]
],
"offsetY": 3.6875,
"offsetX": 53.390625,
"assertedEvents": [
{
"type": "navigation",
"url": "http://localhost:10200/flow/next.html",
"title": ""
}
]
},
{
"type": "click",
"target": "main",
"selectors": [
[
"aria/Hidden content here:"
],
[
"#content > summary"
]
],
"offsetY": 10.5625,
"offsetX": 6
}
]
}
Loading

1 comment on commit 5250b82

@Mayarezai
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well done my friends

Please sign in to comment.