"@playwright/test": "1.37.0",
"playwright": "1.37.0",
"playwright-core": "1.37.0",
demo
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch();
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://example.com');
await page.screenshot({ path: 'example.png' });
await browser.close();
})();
创建Api.ts
'api.ts'
import type { Page } from 'playwright-core';
import * as config from './config'
const { chromium } = require('playwright');
const config.baseURL = process.env.baseURL;
const host = new URL(config.baseURL).host
export class Chromium{
static browser;
static async newChromium(
options?: {
clearCookies?: boolean,
baseURL?: string,
[key: string]: any
}): Promise<Page> {
options = options ?? { clearCookies: false }
if (Chromium.browser == undefined) {
Chromium.browser = await chromium.launch();
}
const context = await Chromium.browser.newContext({
baseURL: config.baseURL,
viewport: { width: 1920, height: 1080 },
ignoreHTTPSErrors: true,
locale: 'zh-CN',
headless: false,
permissions: ['clipboard-read']
});
if (options.clearCookies) {
await context.clearCookies();
}
const page = await context.newPage();
return page;
}
static async closeChromium() {
if (Chromium.browser == undefined) {
return;
}
await Chromium.browser.close();
Chromium.browser = undefined;
}
}
工具utils
'utils.ts'
import * as fs from 'fs';
import * as path from 'path';
import * as process from 'process';
import type { Page, Locator } from "playwright-core";
const workDir = process.cwd().replace('\\', '/')
function mkdirs(dirPath){
if (fs.existsSync(dirPath)) {
return;
}
const parent = path.dirname(dirPath);
if (!fs.existsSync(parent)) {
mkdirs(parent);
}
fs.mkdirSync(dirPath);
}
function getPathPath(page:Page, fileName?: string, fileType='.png'){
const uri = new URL(page.url());
const [hostname, pathname, hash] = [uri.hostname || '', uri.pathname || '', uri.hash || ''];
const endPath = (pathname + hash).replace('//', '/').split('?')[0].slice(1);
const paths = [workDir, hostname, endPath];
if (fileName) {
paths.push(fileName);
}
const filePath = paths.join('/');
return filePath.endsWith(fileType) ? filePath : filePath + fileType;
}
export async function waitForStabilize(
page: Page,
options?: {
path?: string
fullPage?: boolean,
selector?: string | Locator,
timeout?: number,
animations?: 'disabled' | 'allow',
retryTimes?: number,
}
) {
options = options ?? {fullPage: true}
options.fullPage = options.fullPage ?? true
options.fullPage = options.selector == null
options.timeout = options.timeout ?? 60000
options.animations = options.animations ?? 'disabled'
options.retryTimes = options.retryTimes ?? 120
options.path = getPathPath(page, options.path)
await page.waitForLoadState("networkidle");
let matchNum = 0;
let retryTimes = options.retryTimes;
let previous = await page.screenshot(options);
while (retryTimes > 0) {
retryTimes -= 1;
await page.waitForTimeout(1000);
let current = await page.screenshot(options);
if (current && current.equals(previous)) {
matchNum++;
if (matchNum > 1) {
break;
}
} else if (matchNum > 0) {
matchNum--;
}
previous = current;
}
}
使用
'main.ts'
import { API, Chromium } from '../tools/api';
import { waitForStabilize } from "../tools/utils";
const page = await Chromium.newChromium();
const api = new API(page);
await api.login(loginUser);
for (let task of urls) {
console.log('加载页面 ==> ' + task.url);
const retry = task['timeout'] ?? 120
await page.goto(task.url, { waitUntil: 'networkidle' });
await waitForStabilize(page, { retryTimes: retry});
console.log('加载完成 ==> ' + task.url);
}
await Chromium.closeChromium()
playwright.config.ts
import { PlaywrightTestConfig} from '@playwright/test';
import { devices } from 'playwright';
const storageState = cfg.getCookiesPath();
const config: PlaywrightTestConfig = {
testDir: './cunfangmulu',
snapshotDir: new URL(process.env.baseURL).hostname,
use: {
baseURL: new URL(process.env.baseURL),
locale: 'zh-CN',
trace: "off",
actionTimeout: 20 * 1000,
headless: true,
viewport: { width: 1920, height: 1080 },
contextOptions:{
viewport: { width: 1920, height: 1080 },
},
ignoreHTTPSErrors: true,
video: 'off',
screenshot: 'off'
},
updateSnapshots: 'missing',
fullyParallel: true,
outputDir: 'results/',
timeout: 600 * 1000,
expect: {
timeout: 5000
},
globalTimeout: 6 * 3600 * 1000,
forbidOnly: false,
retries: 0,
workers: 5,
projects: [
{
name: 'chromium',
use: {
viewport: { width: 1920, height: 1080 } ,
...devices['Desktop Chrome']
},
}
]
};
export default config;
了解更多