A Puppeteer egy Node.js könyvtár, amely magas szintű API-t biztosít a Chrome vagy a Firefox vezérléséhez. DevTools protokollt vagy WebDriver BiDi-t használ.
Alapértelmezetten fej nélkül (nem indul el láthatóan a böngésző) fut, de beállítható, hogy látható legyen.
Webhely
A teszt elhelyezhető egy kész projektben, vagy létrehozható külön tesztelő projekt. A használathoz szükség van egy Node.js projektre.
Ha meg van a Node.js projekt, telepítsük a puppeteer csomagot:
npm install --save-dev puppeteer
Ha használjuk a pnpm parancsot:
pnpm add --save-dev puppeteer
Készítsünk egy test könyvtárat, ebbe helyezzük el az első tesztünket. Az első példában a a https://szit.hu webhely keresőjét fogjuk tesztelni. Megnézzük a „Programozás” szót ha beírjuk kapunk-e olyan találatot, amiben szerepel a „programozas” kulcsszó.
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://szit.hu/'); await page.type('#qsearch__in', 'Programozás'); await page.click('button[type="submit"]'); await page.waitForSelector('body'); const content = await page.content(); const containsProgramming = content.includes('programozas'); if (containsProgramming) { console.log('Az oldal tartalmazza a "programozas" szót.'); } else { console.log('Az oldal nem tartalmazza a "programozas" szót.'); } await browser.close(); })();
A teszt indítás:
node test/test01.js
Szeretnénk látni a böngészőt 5 másodpercig. Letiltjuk a fej nélküli indítást:
puppeteer.launch({headless: false});
Majd indítunk egy 5 másodperces várakozhást:
await new Promise(resolve => setTimeout(resolve, 5000));
A teljes kód:
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch({headless: false}); const page = await browser.newPage(); await page.goto('https://szit.hu/'); await new Promise(resolve => setTimeout(resolve, 5000)); await browser.close(); })();
A teszt indítás:
node test/valami.js
const puppeteer = require('puppeteer'); (async () => { const browser = await puppeteer.launch({headless: false}); const page = await browser.newPage(); await page.goto('https://szit.hu/'); await page.screenshot({ path: 'szit.png', fullPage: true}); await page.pdf({ path: 'szit.pdf', format: 'A4'}); await browser.close(); })();
A Puppeteer csak a böngészőt automatizálja. A teszt automatizálásához a Mocha-t fogjuk használni.
Telepítsük:
npm install --save-dev mocha
Lássunk egy példát, hogy használjuk a Puppeteer-t és a Mocha-t együtt.
const puppeteer = require('puppeteer'); const assert = require('assert'); describe('Teszt', function() { let browser; let page; before(async function() { browser = await puppeteer.launch({headless: true}); page = await browser.newPage(); }); after(async function() { await browser.close(); }); it('Az oldalra navigálunk', async function() { await page.goto('https://szit.hu'); const title = await page.title(); assert.strictEqual(title, 'start [szit]') }); it('Oktatás link a főoldalon', async function() { await page.goto('https://szit.hu'); const linkExists = await page.waitForSelector('a[href="/doku.php?id=oktatas"]'); assert.ok(linkExists, 'Az Oktatás link nem található a főoldalon.'); }); it('Kattintunk az Oktatás linkre', async function() { await page.goto('https://szit.hu'); await page.click('a[href="/doku.php?id=oktatas"]'); await page.waitForSelector('body') const currentUrl = await page.url(); assert.strictEqual(currentUrl, 'https://szit.hu/doku.php?id=oktatas'); }); });
Futtatás ha a Mocha a projektbe van telepítve:
npx mocha
A tesztekben változatos szelektorokra van szükségünk. Nézzünk néhány példát.
const content = await page.$eval('.form .input:nth-child(2) .form-label', element => element.textContent.trim())
it('Az alap label tartalma', async function() { const content = await page.$eval('.form .input:first-child .form-label', element => element.textContent.trim()) assert.strictEqual(content, 'Alap') })
it('A magasság label tartalma', async function() { const content = await page.$eval('label[for="height"]', element => element.textContent.trim()) assert.strictEqual(content, 'Magasság') })
Az id alapján hivatkozás:
const inputValue = await page.$eval('#height', element => element.value);
<!DOCTYPE html> <html lang="hu"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Háromszög</title> <link rel="stylesheet" href="bootstrap.css"> <link rel="stylesheet" href="style.css"> </head> <body> <div class="container"> <h1>Háromszög területe</h1> <div class="form"> <div class="input"> <label for="base" class="form-label"> Alap </label> <input type="text" id="base" class="form-control"> </div> <div class="input"> <label for="height" class="form-label"> Magasság </label> <input type="text" id="height" class="form-control"> </div> <div> <button id="calcButton" class="btn btn-primary mt-2"> Számít </button> </div> <div class="input"> <label for="area" class="form-label"> Terület </label> <input type="text" id="area" class="form-control" readonly> </div> </div> </div> <script type="module" src="app.js"></script> </body> </html>
const doc = { baseInput: document.querySelector('#base'), heightInput: document.querySelector('#height'), areaInput: document.querySelector('#area'), calcButton: document.querySelector('#calcButton') } const state = { base: 0, height: 0, area: 0 } doc.calcButton.addEventListener('click', () => { startCalc() }) function startCalc() { state.base = doc.baseInput.value state.height = doc.heightInput.value state.area = calcArea(state.base, state.height) renderResult() } function calcArea(base, height) { return base * height / 2 } function renderResult() { doc.baseInput.value = '' doc.heightInput.value = '' doc.areaInput.value = state.area doc.baseInput.focus(); }
Ebben a példában ECMASCriptet használunk, így import kulcsszavakkal importálunk.
import puppeteer from 'puppeteer' import assert from 'assert' describe('Területszámítás tesztje', () => { let browser; let page; before(async function () { browser = await puppeteer.launch({headless: true}) page = await browser.newPage() await page.goto('http://localhost:3000') }) after(async function() { await browser.close() }) it('Böngésző címsora', async function() { const title = await page.title() assert.strictEqual(title, 'Háromszög') }) it('h1 tartalma', async function() { const content = await page.$eval('h1', element => element.textContent) assert.strictEqual(content, 'Háromszög területe') }) it('Az alap label tartalma', async function() { const content = await page.$eval('label[for="base"]', element => element.textContent.trim()) assert.strictEqual(content, 'Alap') }) it('A magasság label tartalma', async function() { const content = await page.$eval('label[for="height"]', element => element.textContent.trim()) assert.strictEqual(content, 'Magasság') }) it('Az alap input', async function() { const element = await page.$('#base') assert.ok(element, 'A base input elemnek léteznie kell') }) it('A magasság input', async function() { const element = await page.$('#height') assert.ok(element, 'A height input elemnek léteznie kell') }) it('Input 30 35 és kattintás', async function() { await page.type('#base', '30') await page.type('#height', '35') await page.click('#calcButton') const actual = await page.$eval('#area', elem => elem.value) assert.strictEqual(actual, '525') }) })