Update @puppeteer/replay to 2.9.0

Bug: none
Change-Id: I0372a04e8714f11338d7df7c2b2ce21b24f3048a
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/4226464
Commit-Queue: Simon Zünd <szuend@chromium.org>
Reviewed-by: Simon Zünd <szuend@chromium.org>
Auto-Submit: Randolf Jung <jrandolf@chromium.org>
This commit is contained in:
Randolf
2023-02-07 04:50:44 +00:00
committed by Devtools-frontend LUCI CQ
parent 12f3d686cc
commit 51ffdadc72
16 changed files with 384 additions and 27 deletions
+1
View File
@@ -0,0 +1 @@
../@puppeteer/replay/lib/extension-test.js
+5 -4
View File
@@ -525,9 +525,9 @@
}
},
"node_modules/@puppeteer/replay": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/@puppeteer/replay/-/replay-2.7.1.tgz",
"integrity": "sha512-w5lghKKto24XB7PGAyflkf1lSuFC+V4+UU5upJJkmWD+O0Q82H2PlHl/Wqwi9aQrngEkKSiK2xMK8Ycs5NddPA==",
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/@puppeteer/replay/-/replay-2.9.0.tgz",
"integrity": "sha512-nVxGZ6+UNQD7ALGndLThhZHRRiBb0Bw0ViFz64RVHU4Cch8gpGXMbN7xZl79q9xInnvRPaqeKZzdb1316jc25A==",
"dev": true,
"dependencies": {
"cli-table3": "0.6.3",
@@ -535,7 +535,8 @@
"yargs": "17.6.2"
},
"bin": {
"replay": "lib/cli.js"
"replay": "lib/cli.js",
"replay-extension-test": "lib/extension-test.js"
},
"engines": {
"node": ">=14"
+13
View File
@@ -246,6 +246,19 @@ console.log(
## Others
### Test your extensions using the replay lib
The replay lib offers a canonical recording and a test page that allows to
verify that your extension produces all expected side effects on a page.
The test command supports both stringify and runner extensions. The stringify
extension will be tested by running the stringified script using node. Run the
test using the following command.
```
npx -p @puppeteer/replay replay-extension-test --ext path-to-your-extension-js
```
### Create a Chrome extension for Recorder (Available from Chrome 104 onwards)
You can create a Chrome extension for [Recorder](https://goo.gle/devtools-recorder). Refer to the [Chrome Extensions documentation](https://developer.chrome.com/docs/extensions/mv3/devtools/) for more details on how to extend DevTools.
+1
View File
@@ -21,6 +21,7 @@ exports.SelectorType = void 0;
SelectorType["ARIA"] = "aria";
SelectorType["Text"] = "text";
SelectorType["XPath"] = "xpath";
SelectorType["Pierce"] = "pierce";
})(exports.SelectorType = exports.SelectorType || (exports.SelectorType = {}));
exports.StepType = void 0;
(function (StepType) {
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -35,7 +35,8 @@ declare enum SelectorType {
CSS = "css",
ARIA = "aria",
Text = "text",
XPath = "xpath"
XPath = "xpath",
Pierce = "pierce"
}
declare enum StepType {
Change = "change",
+6 -5
View File
@@ -3,7 +3,7 @@ import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { parse, createRunner, PuppeteerRunnerOwningBrowserExtension } from '../lib/main.js';
import { lstatSync, readFileSync, readdirSync } from 'fs';
import { isAbsolute, join, extname, relative } from 'path';
import { extname, join, relative, isAbsolute } from 'path';
import { pathToFileURL } from 'url';
import { cwd } from 'process';
import Table from 'cli-table3';
@@ -108,6 +108,10 @@ function createStatusReport(results) {
}
return table;
}
async function importExtensionFromPath(path) {
const module = await import(pathToFileURL(isAbsolute(path) ? path : join(cwd(), path)).toString());
return module.default;
}
async function runFiles(files, opts = {
log: true,
headless: true,
@@ -115,10 +119,7 @@ async function runFiles(files, opts = {
let Extension = PuppeteerRunnerOwningBrowserExtension;
let browser;
if (opts.extension) {
const module = await import(pathToFileURL(isAbsolute(opts.extension)
? opts.extension
: join(cwd(), opts.extension)).toString());
Extension = module.default;
Extension = await importExtensionFromPath(opts.extension);
}
const results = [];
for (const file of files) {
+1 -1
View File
File diff suppressed because one or more lines are too long
+332
View File
@@ -0,0 +1,332 @@
#!/usr/bin/env node
import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import { RunnerExtension, createRunner, parse, stringify } from '../lib/main.js';
import 'fs';
import { isAbsolute, join } from 'path';
import { pathToFileURL } from 'url';
import { cwd } from 'process';
import 'cli-table3';
import 'colorette';
import http from 'http';
import assert from 'assert/strict';
import { spawn } from 'child_process';
/**
Copyright 2022 Google LLC
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
https://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.
*/
async function importExtensionFromPath(path) {
const module = await import(pathToFileURL(isAbsolute(path) ? path : join(cwd(), path)).toString());
return module.default;
}
const recording = {
title: 'spec',
steps: [
{
type: 'setViewport',
width: 900,
height: 700,
deviceScaleFactor: 1,
isMobile: false,
hasTouch: false,
isLandscape: false,
},
{
type: 'navigate',
url: 'http://localhost:8907/spec.html',
assertedEvents: [
{
type: 'navigation',
url: 'http://localhost:8907/spec.html',
title: '',
},
],
},
{
type: 'click',
target: 'main',
selectors: [
['aria/Click'],
['#button'],
['xpath///*[@id="button"]'],
['text/Click'],
],
offsetY: 18,
offsetX: 36,
},
{
type: 'doubleClick',
target: 'main',
selectors: [
['aria/Click'],
['#button'],
['xpath///*[@id="button"]'],
['text/Click'],
],
offsetY: 18,
offsetX: 36,
},
{
type: 'keyDown',
target: 'main',
key: 'Tab',
},
{
type: 'keyUp',
key: 'Tab',
target: 'main',
},
{
type: 'change',
value: 'test',
selectors: [['#input'], ['xpath///*[@id="input"]']],
target: 'main',
},
{
type: 'change',
value: 'testSuffix',
selectors: [['#input-prefilled']],
target: 'main',
},
{
type: 'keyDown',
target: 'main',
key: 'Enter',
},
{
type: 'keyUp',
key: 'Enter',
target: 'main',
},
{
type: 'click',
selectors: [['#input'], ['xpath///*[@id="input"]']],
target: 'main',
button: 'secondary',
offsetX: 1,
offsetY: 1,
},
{
type: 'hover',
target: 'main',
selectors: [
['aria/Hover'],
['#button'],
['xpath///*[@id="hover"]'],
['text/Hover'],
],
},
{
type: 'waitForExpression',
expression: 'new Promise(resolve => setTimeout(() => resolve(true), 500))',
},
{
type: 'waitForElement',
target: 'main',
selectors: ['#button'],
count: 1,
visible: true,
properties: {
id: 'button',
},
attributes: {
id: 'button',
},
},
{
type: 'change',
value: 'optionB',
selectors: [['#select']],
target: 'main',
},
],
};
const expectedLog = `window dimensions 900x700
click targetId=button button=0 value=
click targetId=button button=0 value=
dblclick targetId=button button=0 value=
change targetId=input button=undefined value=test
change targetId=input-prefilled button=undefined value=testSuffix
contextmenu targetId=input button=2 value=test
mouseenter targetId=hover button=0 value=
change targetId=select button=undefined value=optionB
`.trim();
const files = new Map([
[
'spec.html',
`<!DOCTYPE html>
<button id="button" onclick="logEvent(event)" ondblclick="logEvent(event)">
Click
</button>
<button
id="hover"
onmouseenter="logEvent(event)"
onmouseleave="logEvent(event)"
>
Hover
</button>
<input id="input" oncontextmenu="logEvent(event)" onchange="logEvent(event)" />
<input id="input-prefilled" onchange="logEvent(event)" value="test" />
<select id="select" onchange="logEvent(event)">
<option value=""></option>
<option value="optionA">Option A</option>
<option value="optionB">Option B</option>
</select>
<pre id="log"></pre>
<script>
function logStr(str) {
log.innerText += str;
const data = { username: 'example' };
fetch('/log', {
method: 'POST',
headers: {
'Content-Type': 'application/text',
},
body: str,
})
.catch((error) => {
console.error(error);
});
}
function logEvent(event) {
logStr(
'\\n' +
event.type +
' targetId=' +
event.target.id +
' button=' +
event.button +
' value=' +
event.target.value
);
}
logStr(\`window dimensions \${window.innerWidth}x\${window.innerHeight}\`);
input.addEventListener('contextmenu', (e) => e.preventDefault(), false);
</script>`,
],
]);
/**
Copyright 2023 Google LLC
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
https://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.
*/
async function startServer() {
const log = {
contents: '',
};
const server = http.createServer(async (req, res) => {
var _a;
if (req.method === 'GET') {
for (const [file, content] of files.entries()) {
if ((_a = req.url) === null || _a === void 0 ? void 0 : _a.endsWith(file)) {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(content);
return;
}
}
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('Not found');
return;
}
if (req.method === 'POST') {
const body = await new Promise((resolve) => {
const body = [];
req
.on('data', (chunk) => {
body.push(chunk);
})
.on('end', () => {
resolve(Buffer.concat(body).toString());
});
});
res.writeHead(200);
res.end();
log.contents += body;
return;
}
res.writeHead(400);
res.end();
});
return new Promise((resolve) => {
server.listen(8907, 'localhost', () => {
resolve({ server, log });
});
});
}
yargs(hideBin(process.argv))
.command('$0', 'Test an extension implementation', () => { }, async (argv) => {
const args = argv;
const Extension = await importExtensionFromPath(args.extension);
const ext = new Extension();
let run = async () => { };
if (ext instanceof RunnerExtension) {
console.log('runner');
run = async () => {
const extension = new Extension();
const runner = await createRunner(parse(recording), extension);
await runner.run();
};
}
else {
run = async () => {
const exported = await stringify(parse(recording), {
extension: new Extension(),
});
const childProcess = spawn('node', {
stdio: ['pipe', 'pipe', 'inherit'],
shell: true,
});
childProcess.stdin.write(exported);
childProcess.stdin.end();
await new Promise((resolve, reject) => {
childProcess.on('close', (code) => code
? reject(new Error(`Running node failed with code ${code}`))
: resolve());
});
};
}
const { server, log } = await startServer();
try {
await run();
}
catch (err) {
console.error(err);
}
finally {
server.close();
}
assert.equal(log.contents, expectedLog);
console.log('Run matches the expectations');
})
.option('extension', {
alias: 'ext',
type: 'string',
description: 'The path to the extension module. The default export will be used as a Stringify or Runner extension based on instanceOf checks.',
demandOption: true,
})
.parse();
//# sourceMappingURL=extension-test.js.map
File diff suppressed because one or more lines are too long
+2 -1
View File
@@ -35,7 +35,8 @@ declare enum SelectorType {
CSS = "css",
ARIA = "aria",
Text = "text",
XPath = "xpath"
XPath = "xpath",
Pierce = "pierce"
}
declare enum StepType {
Change = "change",
+1
View File
@@ -19,6 +19,7 @@ var SelectorType;
SelectorType["ARIA"] = "aria";
SelectorType["Text"] = "text";
SelectorType["XPath"] = "xpath";
SelectorType["Pierce"] = "pierce";
})(SelectorType = SelectorType || (SelectorType = {}));
var StepType;
(function (StepType) {
+1 -1
View File
File diff suppressed because one or more lines are too long
+7 -4
View File
@@ -1,10 +1,13 @@
{
"name": "@puppeteer/replay",
"version": "2.7.1",
"version": "2.9.0",
"description": "Replay is a library which provides an API to replay and stringify recordings created using Chrome DevTools Recorder](https://developer.chrome.com/docs/devtools/recorder/)",
"main": "lib/cjs/main.cjs",
"types": "lib/main.d.ts",
"bin": "lib/cli.js",
"bin": {
"@puppeteer/replay": "lib/cli.js",
"replay-extension-test": "lib/extension-test.js"
},
"exports": {
".": {
"import": {
@@ -70,8 +73,8 @@
"mime": "3.0.0",
"mocha": "10.1.0",
"prettier": "2.7.1",
"puppeteer": "19.4.1",
"puppeteer-core": "19.4.1",
"puppeteer": "19.6.2",
"puppeteer-core": "19.6.2",
"rimraf": "3.0.2",
"rollup": "3.2.2",
"rollup-plugin-dts": "5.0.0",
+9 -8
View File
@@ -8,7 +8,7 @@
"license": "BSD-3-Clause",
"devDependencies": {
"@istanbuljs/schema": "0.1.3",
"@puppeteer/replay": "^2.7.1",
"@puppeteer/replay": "^2.9.0",
"@types/chai": "4.3.0",
"@types/codemirror": "0.0.108",
"@types/estree": "0.0.50",
@@ -597,9 +597,9 @@
}
},
"node_modules/@puppeteer/replay": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/@puppeteer/replay/-/replay-2.7.1.tgz",
"integrity": "sha512-w5lghKKto24XB7PGAyflkf1lSuFC+V4+UU5upJJkmWD+O0Q82H2PlHl/Wqwi9aQrngEkKSiK2xMK8Ycs5NddPA==",
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/@puppeteer/replay/-/replay-2.9.0.tgz",
"integrity": "sha512-nVxGZ6+UNQD7ALGndLThhZHRRiBb0Bw0ViFz64RVHU4Cch8gpGXMbN7xZl79q9xInnvRPaqeKZzdb1316jc25A==",
"dev": true,
"dependencies": {
"cli-table3": "0.6.3",
@@ -607,7 +607,8 @@
"yargs": "17.6.2"
},
"bin": {
"replay": "lib/cli.js"
"replay": "lib/cli.js",
"replay-extension-test": "lib/extension-test.js"
},
"engines": {
"node": ">=14"
@@ -9240,9 +9241,9 @@
}
},
"@puppeteer/replay": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/@puppeteer/replay/-/replay-2.7.1.tgz",
"integrity": "sha512-w5lghKKto24XB7PGAyflkf1lSuFC+V4+UU5upJJkmWD+O0Q82H2PlHl/Wqwi9aQrngEkKSiK2xMK8Ycs5NddPA==",
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/@puppeteer/replay/-/replay-2.9.0.tgz",
"integrity": "sha512-nVxGZ6+UNQD7ALGndLThhZHRRiBb0Bw0ViFz64RVHU4Cch8gpGXMbN7xZl79q9xInnvRPaqeKZzdb1316jc25A==",
"dev": true,
"requires": {
"cli-table3": "0.6.3",
+1 -1
View File
@@ -41,7 +41,7 @@ LICENSES = [
# List all DEPS here.
DEPS = {
"@istanbuljs/schema": "0.1.3",
"@puppeteer/replay": "2.7.1",
"@puppeteer/replay": "2.9.0",
"@types/chai": "4.3.0",
"@types/codemirror": "0.0.108",
"@types/estree": "0.0.50",