playwright 简单使用

版本号(官网地址

"@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;
    /**
    * 启动一个浏览器,默认会清除cookies
    * @returns 
    */
    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) { // 清除cookies 消除登录信息(如果需要登录才能进入的网址
            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); // 业务代码 执行页面登录存放cookies

for (let task of urls) { // 多个地址快照
  console.log('加载页面 ==> ' + task.url);
  const retry = task['timeout'] ?? 120 
  await page.goto(task.url, { waitUntil: 'networkidle' }); // goto 执行地址访问
  await waitForStabilize(page, { retryTimes: retry}); // 执行快照生成
  console.log('加载完成 ==> ' + task.url);
}
// 关闭chromium
await Chromium.closeChromium()

playwright.config.ts

import { PlaywrightTestConfig} from '@playwright/test';
import { devices } from 'playwright';
const storageState = cfg.getCookiesPath(); //业务代码 浏览器cookies

// 默认配置信息
const config: PlaywrightTestConfig = {
    testDir: './cunfangmulu', // 存放目录
    snapshotDir: new URL(process.env.baseURL).hostname,
    // globalSetup: require.resolve('./global-setup'),
    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'
        // storageState: storageState
    },
    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;

了解更多

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值