Tartalomjegyzék

< Web

Puppeteer

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

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

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ó.

test/test01.js
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:

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 new Promise(resolve => setTimeout(resolve, 5000));
    await browser.close();
})();

A teszt indítás:

node test/valami.js

Képernyőkép

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();
})();

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.

test/valami.js
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

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

index.html
<!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>
app.js
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.

test/apptest.js
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')
    })
})