Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,098 changes: 524 additions & 574 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
"engines": {
"node": ">=10.15.0"
},
"bin": {
"playwright": "lib/cli/index.js"
},
"scripts": {
"ctest": "cross-env BROWSER=chromium node --unhandled-rejections=strict test/test.js",
"ftest": "cross-env BROWSER=firefox node --unhandled-rejections=strict test/test.js",
Expand Down Expand Up @@ -39,6 +42,7 @@
},
"license": "Apache-2.0",
"dependencies": {
"commander": "^5.1.0",
"debug": "^4.1.1",
"extract-zip": "^2.0.0",
"https-proxy-agent": "^3.0.0",
Expand Down Expand Up @@ -69,7 +73,6 @@
"eslint": "^6.6.0",
"esprima": "^4.0.0",
"formidable": "^1.2.1",
"minimist": "^1.2.5",
"ncp": "^2.0.0",
"node-stream-zip": "^1.8.2",
"pixelmatch": "^4.0.2",
Expand Down
101 changes: 101 additions & 0 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#!/usr/bin/env node

/**
* Copyright (c) Microsoft Corporation.
*
* 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.
*/

/* eslint-disable no-console */

import * as program from 'commander';
import { Playwright } from '../server/playwright';
import { BrowserType, LaunchOptions } from '../server/browserType';
import { DeviceDescriptors } from '../deviceDescriptors';
import { BrowserContextOptions } from '../browserContext';

const playwright = new Playwright(__dirname, require('../../browsers.json')['browsers']);

program
.version('Version ' + require('../../package.json').version)
.option('-b, --browser <browserType>', 'browser to use, one of cr, chromium, ff, firefox, wk, webkit', 'chromium')
.option('--headless', 'run in headless mode', false)
.option('--device <deviceName>', 'emulate device, for example "iPhone 11"');

program
.command('open [url]')
.description('open page in browser specified via -b, --browser')
.action(function(url, command) {
open(command.parent, url);
}).on('--help', function() {
console.log('');
console.log('Examples:');
console.log('');
console.log(' $ open');
console.log(' $ -b webkit open https://example.com');
});

const browsers = [
{ initial: 'cr', name: 'Chromium', type: 'chromium' },
{ initial: 'ff', name: 'Firefox', type: 'firefox' },
{ initial: 'wk', name: 'WebKit', type: 'webkit' },
];

for (const {initial, name, type} of browsers) {
program
.command(`${initial} [url]`)
.description(`open page in ${name} browser`)
.action(function(url, command) {
open({ ...command.parent, browser: type }, url);
}).on('--help', function() {
console.log('');
console.log('Examples:');
console.log('');
console.log(` $ ${initial} https://example.com`);
});
}

program.parse(process.argv);

type Options = {
browser: string,
device: string | undefined,
verbose: boolean,
headless: boolean,
};

async function open(options: Options, url: string | undefined) {
const browserType = lookupBrowserType(options.browser);
const launchOptions: LaunchOptions = { headless: options.headless };
const browser = await browserType.launch(launchOptions);
const contextOptions: BrowserContextOptions = options.device ? DeviceDescriptors[options.device] || {} : {};
const page = await browser.newPage(contextOptions);
if (url) {
if (!url.startsWith('http'))
url = 'http://' + url;
await page.goto(url);
}
return { browser, page };
}

function lookupBrowserType(name: string): BrowserType {
switch (name) {
case 'chromium': return playwright.chromium!;
case 'webkit': return playwright.webkit!;
case 'firefox': return playwright.firefox!;
case 'cr': return playwright.chromium!;
case 'wk': return playwright.webkit!;
case 'ff': return playwright.firefox!;
}
program.help();
}
4 changes: 2 additions & 2 deletions src/debug/injected/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ function prepareTemplate(strings: TemplateStringsArray) {
html += strings[strings.length - 1];
template.innerHTML = html;

const walker = template.ownerDocument!.createTreeWalker(
const walker = template.ownerDocument.createTreeWalker(
template.content, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, null, false);
const emptyTextNodes: Node[] = [];
const subs: Sub[] = [];
Expand Down Expand Up @@ -145,7 +145,7 @@ function shouldRemoveTextNode(node: Text) {
}

function renderTemplate(template: HTMLTemplateElement, subs: Sub[], values: (string | Node)[]): DocumentFragment | ChildNode {
const content = template.ownerDocument!.importNode(template.content, true)!;
const content = template.ownerDocument.importNode(template.content, true)!;
const boundElements = Array.from(content.querySelectorAll('[dom-template-marked]'));
for (const node of boundElements)
node.removeAttribute('dom-template-marked');
Expand Down
8 changes: 6 additions & 2 deletions src/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export type RegisteredListener = {

export type Listener = (...args: any[]) => void;

const isDebugModeEnv = !!getFromENV('PWDEBUG');
let isInDebugMode = !!getFromENV('PWDEBUG');

class Helper {
static evaluationString(fun: Function | string, ...args: any[]): string {
Expand Down Expand Up @@ -303,7 +303,11 @@ class Helper {
}

static isDebugMode(): boolean {
return isDebugModeEnv;
return isInDebugMode;
}

static setDebugMode() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Seem unused.

Copy link
Member Author

Choose a reason for hiding this comment

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

It will be!

isInDebugMode = true;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/injected/attributeSelectorEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function queryShadowInternal(root: SelectorRoot, attribute: string, value: strin
}

function queryShadowAllInternal(root: SelectorRoot, attribute: string, value: string, result: Element[]) {
const document = root instanceof Document ? root : root.ownerDocument!;
const document = root instanceof Document ? root : root.ownerDocument;
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
const shadowRoots = [];
while (walker.nextNode()) {
Expand Down
4 changes: 2 additions & 2 deletions src/injected/injectedScript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -315,9 +315,9 @@ export default class InjectedScript {
textarea.focus();
return { value: 'done' };
}
const range = element.ownerDocument!.createRange();
const range = element.ownerDocument.createRange();
range.selectNodeContents(element);
const selection = element.ownerDocument!.defaultView!.getSelection();
const selection = element.ownerDocument.defaultView!.getSelection();
if (!selection)
return { error: 'Element belongs to invisible iframe.' };
selection.removeAllRanges();
Expand Down
4 changes: 2 additions & 2 deletions src/injected/textSelectorEngine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ function isFilteredNode(root: SelectorRoot, document: Document) {
}

function queryInternal(root: SelectorRoot, matcher: Matcher, shadow: boolean): Element | undefined {
const document = root instanceof Document ? root : root.ownerDocument!;
const document = root instanceof Document ? root : root.ownerDocument;
if (isFilteredNode(root, document))
return;
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT, nodeFilter);
Expand Down Expand Up @@ -136,7 +136,7 @@ function queryInternal(root: SelectorRoot, matcher: Matcher, shadow: boolean): E
}

function queryAllInternal(root: SelectorRoot, matcher: Matcher, shadow: boolean, result: Element[]) {
const document = root instanceof Document ? root : root.ownerDocument!;
const document = root instanceof Document ? root : root.ownerDocument;
if (isFilteredNode(root, document))
return;
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT, nodeFilter);
Expand Down
Loading