[[oktatas:web|< Web]]
====== Puppeteer ======
* **Szerző:** Sallai András
* Copyright (c) 2024, Sallai András
* Szerkesztve: 2024, 2025
* Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC BY-SA 4.0]]
* Web: https://szit.hu
===== Bevezetés =====
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
* https://pptr.dev/
===== Telepítés =====
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épernyőkép =====
{
"type": "module"
}
import puppeteer from 'puppeteer';
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto('https://szit.hu');
await page.screenshot({ path: 'example.png' });
await browser.close();
})();
Futtatás:
node test/barmi.js
===== Keresés példa =====
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
===== Indítás böngésző fejjel =====
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
===== Képernyőkép PDF-fel =====
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();
})();
===== Használat Mocha mellett =====
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
===== Triangle =====
Ebben a példában ES modulokat használunk (import a requiure helyett), ezért a package.json
fájlban:
{
"type": "module"
}
A teszt ezek után:
import puppeteer from "puppeteer";
import assert from "assert";
describe("Triangle", function () {
let browser;
let page;
before(async function () {
browser = await puppeteer.launch();
page = await browser.newPage();
});
/* Minden teszt előtt újra betölti a weboldalot. */
this.beforeEach(async function () {
await page.goto("https://szit.hu/m/triangle_ts");
})
after(async function () {
await browser.close();
});
it("A title ellenőrzése", async function () {
const actual = await page.title();
const expected = "Háromszög";
assert.strictEqual(actual, expected);
});
it("A h1 elem ellenőrzése", async function () {
const actual = await page.$eval("h1", el => el.textContent);
const expected = "Háromszög területe";
assert.strictEqual(actual, expected);
});
it("Háromszög területe 30, 35 bemenetre 525", async function () {
await page.type("#base", "30");
await page.type("#height", "35");
await page.click("#calcButton");
const actual = await page.$eval("#area", el => Number(el.value));
const expected = 525;
assert.strictEqual(actual.toFixed(1), expected.toFixed(1));
});
it("Háromszög területe 123, 99 bemenetre 6088.5", async function () {
await page.type("#base", "123");
await page.type("#height", "99");
await page.click("#calcButton");
const actual = await page.$eval("#area", el => Number(el.value));
const expected = 6088.5;
assert.strictEqual(actual.toFixed(1), expected.toFixed(1));
});
})
===== Szelektorok =====
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);
===== Háromszög területszámítás =====
Háromszög
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();
}
==== Teszt ====
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')
})
})