最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文教你學(xué)會(huì)Nodejs中puppeteer的簡單使用

 更新時(shí)間:2024年01月11日 10:37:39   作者:beckyye  
Puppeteer是一個(gè)控制headless Chrome的Node.js API ,是一個(gè) Node.js庫,在瀏覽器中手動(dòng)完成的大多數(shù)事情都可以通過使用 Puppeteer完成,本文主要介紹了Puppeteer的簡單使用,希望對(duì)大家有所幫助

引言

對(duì)于編寫應(yīng)用程序,尤其是要部署上線投入生產(chǎn)使用的應(yīng)用,QA是其中重要的一環(huán),在過去的工作經(jīng)歷中,我參與的項(xiàng)目開發(fā),大多是由測試同學(xué)主要來把控質(zhì)量的,我很少編寫前端方面的測試代碼,對(duì)于測試工具的使用,也基本停留在一個(gè)小玩具的樣子,所以接觸的也少,回憶上一次寫單元測試,還是在一個(gè)vue3的課程中使用jest實(shí)現(xiàn)TDD,記得之前有的時(shí)候面試,會(huì)被問到有沒有在項(xiàng)目中用單測,但是因?yàn)橐郧肮ぷ髦写蠖鄶?shù)時(shí)候需求排期都只考慮開發(fā)的時(shí)間,就很少考慮到這方面,然后就,面試中這方面也說不出什么東西,最近因?yàn)橐粋€(gè)偶然的機(jī)會(huì),我接觸了puppeteer用來做前端自動(dòng)化測試,用著還感覺蠻有點(diǎn)小意思。

puppeteer能做什么

puppeteer是一個(gè)Node.js庫,通過puppeteer的文檔,我們可以快速的了解我們能使用puppeteer來做些什么:

Most things that you can do manually in the browser can be done using Puppeteer! Here are a few examples to get you started:

  • Generate screenshots and PDFs of pages.
  • Crawl a SPA (Single-Page Application) and generate pre-rendered content (i.e. "SSR" (Server-Side Rendering)).
  • Automate form submission, UI testing, keyboard input, etc.
  • Create an automated testing environment using the latest JavaScript and browser features.
  • Capture a timeline trace of your site to help diagnose performance issues.
  • Test Chrome Extensions.

第一句作為總領(lǐng),點(diǎn)出了puppeteer可以模擬用戶與瀏覽器的交互。包括頁面截圖、生成SPA的預(yù)渲染內(nèi)容、觸發(fā)用戶交互事件等等,可以用于進(jìn)行UI和功能測試,另外可以看出除了普通的前端測試外,還可以作為爬蟲工具使用。本文針對(duì)簡單的用戶交互事件的模擬和頁面截圖,實(shí)現(xiàn)一個(gè)puppeteer的使用示例。

準(zhǔn)備工作

首先在使用之前,需要先安裝依賴

npm i puppeteer
# or using yarn
yarn add puppeteer
# or using pnpm
pnpm i puppeteer

我這里使用yarn global進(jìn)行了全局的安裝。

然后我們來準(zhǔn)備待測試的頁面

我這里準(zhǔn)備了一個(gè)簡單的頁面,直接預(yù)覽如下所示:

頁面分為兩部分,最上面是標(biāo)題,下面展示的是一個(gè)canvas。我們即將測試的內(nèi)容除了基本的請求頁面和獲取頁面元素外,主要有兩項(xiàng)功能,分別為:

  • 點(diǎn)擊canvas后展示一個(gè)彈窗,使用文字描述“土”與其他五行的關(guān)系,測試點(diǎn)擊事件的模擬和彈窗的展示
  • 點(diǎn)擊canvas后在canvas上繪制,使用圖像描述“土”與其他五行的關(guān)系,測試puppeteer的截圖功能并引入blink-diff模塊,用于圖像的對(duì)比

接下來我們就可以開始編寫測試代碼。

使用示例

因?yàn)槭悄M交互,所以會(huì)有許多異步的操作,我們可以通過await獲取結(jié)果,所以這個(gè)例子中的代碼會(huì)使用異步函數(shù)async來包裹。

另外由于要模擬操作,所以選擇器也是核心功能,類似于document.querySelectordocument.querySelectorAll的作用,puppeteer使用css選擇器語法的超集進(jìn)行查詢,也就是說我們可以使用.class、#id等css選擇器來進(jìn)行元素查詢。

基本功能

以下是基本的代碼:

/*
 * check.js
*/
const puppeteer = require('puppeteer');

(async () => {
    // Launch the browser and open a new blank page
    const browser = await puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] });
    const page = await browser.newPage();
  
    // Set screen size
    await page.setViewport({width: 1920, height: 1080});
  
    // Navigate the page to a URL
    await page.goto('http://0.0.0.0:8080');

    // 關(guān)閉puppeteer
    browser.close();

    // ...
})()

在模擬交互前,我們需要先啟動(dòng)瀏覽器并打開頁面,以上代碼就可以完成這些操作:

puppeteer.launch:啟動(dòng)瀏覽器

在啟動(dòng)瀏覽器時(shí),我們可以設(shè)置一些啟動(dòng)參數(shù),這里的'--no-sandbox'代表取消沙盒模式,放開權(quán)限,--disable-setuid-sandbox也是類似的作用,此兩者的區(qū)別可以參考這個(gè)discuss

browser.newPage:可以理解為打開一個(gè)瀏覽器tab

page.setViewport:設(shè)置視窗尺寸

page.goto:跳轉(zhuǎn)頁面到指定地址,這里跳轉(zhuǎn)到了我們本地啟動(dòng)的8080服務(wù)頁面

browser.close:關(guān)閉瀏覽器。我們可以在獲取到數(shù)據(jù)后就進(jìn)行關(guān)閉操作,再在后續(xù)中使用抓取到的數(shù)據(jù)

可以看到在每步操作之前,我們都使用了await來等待操作完成,每一步都需要等待上一步操作完畢才能開始。

接下來我們就可以開始獲取頁面上的元素,比如示例頁面上的h3標(biāo)簽。

const elm = await page.waitForSelector('h3');
// OR
const elm = await page.$('h3');

console.log(elm);
// CdpElementHandle {
//   handle: CdpJSHandle {},
//   [Symbol(_isElementHandle)]: true
// }
console.log(elm.innerText); // undefined

可以通過.waitForSelector或簡寫的.$方法獲取元素,可以看到打印出來的并不是DOM對(duì)象,而是一個(gè)經(jīng)過封裝的CdpElementHandle類型的對(duì)象,因此我們無法通過elm.innerText的方式來獲取h3標(biāo)簽內(nèi)的文本內(nèi)容,似乎這個(gè)選擇器方法只能用于判斷頁面上是否存在某個(gè)或某類匹配的元素。

如果想獲取元素對(duì)應(yīng)的DOM屬性,可以使用Page.$eval()來實(shí)現(xiàn),用法如下所示:

const elmText = await page.$eval('h3', h3 => h3.innerText);
console.log(elmText); // "土"與其他五行的關(guān)系

判斷DOM屬性

在本文的測試頁面中,實(shí)現(xiàn)了點(diǎn)擊canvas顯示彈窗的功能,彈窗的顯示是通過js代碼添加樣式類實(shí)現(xiàn)的,并且會(huì)在2s后關(guān)閉彈窗的顯示,所以我們需要測試樣式類的添加和移除。

同樣的,我們需要先獲取到canvas元素。

const canvas = await page.$('canvas');

接著模擬點(diǎn)擊,并獲取彈窗對(duì)應(yīng)div的classList。

await canvas.click();
const popupClassList = await page.$eval('.popup-dialog', popup => popup.classList);
console.log(popupClassList); // { '0': 'popup-dialog', '1': 'visible' }

可以看到彈窗的classList中按照預(yù)期出現(xiàn)了代表顯示的樣式類visible。

接著我們繼續(xù)測試2s后彈窗關(guān)閉。

await new Promise(r => setTimeout(r, 2000));
const postPopupClassList = await page.$eval('.popup-dialog', popup => popup.classList);
console.log(postPopupClassList); // { '0': 'popup-dialog' }

可以看到在2s后,樣式類visible按照預(yù)期被移除了。這里我們使用一個(gè)promise來計(jì)時(shí)。

截圖功能

最后我們來使用puppeteer的截圖功能。在使用之前,先把測試頁面的點(diǎn)擊canvas顯示彈窗改為繪制圖像,然后我們來測試。

在截圖之前,我們需要先指定一個(gè)目錄用于存放截圖,這里我直接創(chuàng)建一個(gè)imgs文件夾,然后編寫以下代碼:

const imgDir = './imgs/';
canvas.screenshot({ path: `${imgDir}canvas.png` });

執(zhí)行node check.js后,我們就可以看到imgs目錄下生成了一張圖片,和我們在瀏覽器中看到的是一樣的。

如果這是一個(gè)UI效果圖,我們可以把他重命名為target.png,然后使用代碼實(shí)現(xiàn)后,配合使用blink-diff模塊,對(duì)比UI設(shè)計(jì)圖與實(shí)際代碼實(shí)現(xiàn)所存在的差異大小;blink-diff模塊也可以通過NPM來安裝。blink-diff是一個(gè)輕量級(jí)的圖片對(duì)比工具,以下是一個(gè)簡單的使用展示:

const puppeteer = require("puppeteer"),
    BlinkDiff = require('blink-diff');

// ...

// 關(guān)閉puppeteer
browser.close();

const diff = new BlinkDiff({
	imageAPath: imgDir + 'target.png', // ui
	imageBPath: imgDir + 'canvas.png', // 頁面截圖
	imageOutputPath: imgDir + 'Diff.png', // 差異對(duì)比圖
	threshold: 0.02
});

因?yàn)橐呀?jīng)得到截圖,所以此時(shí)已經(jīng)不需要瀏覽器了,new BlinkDiff可以在puppeteer關(guān)閉后執(zhí)行。

imageAPath和imageBPath分別是設(shè)計(jì)圖和頁面截圖的存放路徑,imageOutputPath輸出兩張圖片的差異對(duì)比圖,threshold是一個(gè)百分比閾值,當(dāng)差異比例低于該值時(shí)忽略差異,在這里這就是說,當(dāng)差異比例低于2%,就認(rèn)為兩張圖是相同的。

接下來就通過調(diào)用diff.run()方法來執(zhí)行對(duì)比:

diff.run(function (error, result) {
    if (error) {
        throw error;
    } else {
        let rel = Math.round((result.differences /
            result.dimension) * 100);
        console.log(result.code);
        console.log(diff.hasPassed(result.code));
        console.log(diff.hasPassed(result.code) ? 'Passed' : 'Failed');
        console.log('總像素:' + result.dimension);
        console.log('發(fā)現(xiàn):' + result.differences + ' 差異,差異占?'
            + rel + "%");
    }
});

當(dāng)正常執(zhí)行后,會(huì)返回一個(gè)result對(duì)象包含對(duì)比結(jié)果的信息。

result.differences表示存在不同的像素?cái)?shù)量,result.dimension表示像素的總數(shù)量,因此這里rel計(jì)算得到的就是像素的差異比例。

result.code就是一個(gè)結(jié)果狀態(tài)碼,調(diào)用diff.hasPassed方法會(huì)根據(jù)diff的配置對(duì)狀態(tài)碼進(jìn)行解析,從而得出通過或失敗的判斷。

到這里為止就是一個(gè)截圖功能和圖像對(duì)比的簡單示例,看上去使用起來挺不錯(cuò)的樣子,但實(shí)際還是存在一些問題,比如我最近遇到的,使用漸變函數(shù)設(shè)置樣式,得到的截圖會(huì)存在問題,并沒有得到應(yīng)用漸變后的樣式截圖,不知道是兼容上的問題還是我的使用方式問題,所以暫時(shí)我使用了getComputedStyle作為替代方案。

到此這篇關(guān)于一文教你學(xué)會(huì)Nodejs中puppeteer的簡單使用的文章就介紹到這了,更多相關(guān)Nodejs puppeteer內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 微信小程序搭載node.js服務(wù)器的簡單教程

    微信小程序搭載node.js服務(wù)器的簡單教程

    小程序是一種全新的連接用戶與服務(wù)的方式,它可以在微信內(nèi)被便捷地獲取和傳播,同時(shí)具有出色的使用體驗(yàn),下面這篇文章主要給大家介紹了關(guān)于微信小程序搭載node.js服務(wù)器的簡單教程,需要的朋友可以參考下
    2022-12-12
  • 解決node終端下運(yùn)行js文件不支持ES6語法

    解決node終端下運(yùn)行js文件不支持ES6語法

    這篇文章主要介紹了解決node終端下運(yùn)行js文件不支持ES6語法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-04-04
  • 使用NodeJs 開發(fā)微信公眾號(hào)(三)微信事件交互實(shí)例

    使用NodeJs 開發(fā)微信公眾號(hào)(三)微信事件交互實(shí)例

    這篇文章主要介紹了使用NodeJs 開發(fā)微信公眾號(hào)(三)微信事件交互實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2016-03-03
  • Node.js的HTTP模塊、URL模塊與supervisor工具介紹

    Node.js的HTTP模塊、URL模塊與supervisor工具介紹

    這篇文章介紹了Node.js的HTTP模塊、URL模塊與supervisor工具,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • 使用Jasmine和Karma對(duì)AngularJS頁面程序進(jìn)行測試

    使用Jasmine和Karma對(duì)AngularJS頁面程序進(jìn)行測試

    這篇文章主要介紹了使用Jasmine和Karma對(duì)AngularJS頁面程序進(jìn)行測試的方法,以Node.js為環(huán)境,非常適合JavaScript的全棧開發(fā)時(shí)使用,需要的朋友可以參考下
    2016-03-03
  • Node.js?中的?module.exports?與?exports區(qū)別介紹

    Node.js?中的?module.exports?與?exports區(qū)別介紹

    這篇文章主要介紹了Node.js中的module.exports與exports區(qū)別介紹,每個(gè)模塊中都有module對(duì)象,存放了當(dāng)前模塊相關(guān)的信息,更多相關(guān)內(nèi)容需要的朋友可以參考一下
    2022-09-09
  • node.js將MongoDB數(shù)據(jù)同步到MySQL的步驟

    node.js將MongoDB數(shù)據(jù)同步到MySQL的步驟

    這篇文章主要給大家介紹了關(guān)于node.js將MongoDB數(shù)據(jù)同步到MySQL的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-12-12
  • 用nodejs實(shí)現(xiàn)json和jsonp服務(wù)的方法

    用nodejs實(shí)現(xiàn)json和jsonp服務(wù)的方法

    本篇文章主要介紹了用nodejs實(shí)現(xiàn)json和jsonp服務(wù)的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • nodejs同步調(diào)用獲取mysql數(shù)據(jù)時(shí)遇到的大坑

    nodejs同步調(diào)用獲取mysql數(shù)據(jù)時(shí)遇到的大坑

    今天小編就為大家分享一篇關(guān)于nodejs同步調(diào)用獲取mysql數(shù)據(jù)時(shí)遇到的大坑,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • node.js中的require使用詳解

    node.js中的require使用詳解

    本文通過幾個(gè)具體實(shí)例來分析講解了node.js中require的使用方法,非常的詳盡,這里推薦給大家
    2014-12-12

最新評(píng)論

镇赉县| 永清县| 香格里拉县| 南乐县| 平泉县| 天长市| 东宁县| 高平市| 拉萨市| 祁东县| 静安区| 嘉祥县| 霍林郭勒市| 阜南县| 山阳县| 荥阳市| 武川县| 西充县| 临颍县| 通许县| 拜城县| 峨眉山市| 渝中区| 新野县| 伊宁市| 会理县| 安达市| 临高县| 车致| 五华县| 鄄城县| 砚山县| 邳州市| 贵州省| 青海省| 修武县| 乃东县| 抚顺市| 福州市| 涟源市| 天柱县|