Видели ли вы подход к интеграционному тестированию, который не вызывает у вас рвоты? по крайней мере, для планеты JS, потому что я думаю, что за эти годы я пересекся с фантомом и кармой, с селеном и Nightwatch, у меня были некоторые надежды на CasperJS и slimerJS, даже иногда я притворяюсь, что jsdom надежен, а затем я понимаю, что я сделал и плакал, чтобы спать; до субботы я обнаружил, что кукловод не новичок, я говорю вам это как отказ от ответственности, но совсем недавно у меня была возможность попробовать это.

В один прекрасный день все так хорошо

Насколько сложно может быть, когда запуск yarn add -D ava puppeteer уже приносит в вашу страну безголовый браузер. Первой задачей было запустить браузер ... const browser = await puppeteer.launch({ headless:false }) поверьте мне, это не так уж сложно, как насчет новой страницы, переходящей на localhost, тоже совсем не сложно, так что позвольте мне подвести итог

import test from 'ava'
import puppeteer from 'puppeteer'
let browser, page
test.beforeEach(async () => {
  browser = await puppeteer.launch({ headless: false, slowMo: 300 })
  page = await browser.newPage()
  await page.goto('http://localhost:3000')
})
test.afterEach(async () => {
  await browser.close()
})

В примере, который я использовал headless: false и slowMo: 300, просто чтобы увидеть, что в итоге происходит, я был поражен простотой процесса, но без опций он работает без каких-либо различий.

Время тестирования

Моя основная цель состояла в том, чтобы протестировать модальное окно cookie, одно из тех обычных модальных окон, которые создают cookie, если пользователь принимает политику cookie, ничего особенного, но было ненадежно тестировать только ложные срабатывания от phantomJS или фиктивные реализации jsdom.

Вот тогда в игру вступает кукольник. Во-первых, тест настолько прост, что почти так же легко, как и модульный тест, поэтому вы можете получить доступ к HTML-элементу.

test('Link to policy', async (t) => {
  const anchorText = await page.$eval('.terms', el => el.innerHTML)
  t.is(anchorText, 'Cookies policy', 'policy anchor text')
})

$ eval - это своего рода «оценка селектора», которая возвращает элемент при обратном вызове, что довольно полезно для запуска, но иногда вам нужно выполнить больше, чем это в браузере, для тех более сложных случаев, когда у вас все еще есть theevaluate, и я сделал это для случайного теста CSS, чтобы проверить zIndex и положение

test('Cookie banner is on top of everything', async (t) => {
  const banner = await page.evaluate(() => {
    const dialog = document.querySelector('.js_banner')
    return JSON.parse(JSON.stringify(getComputedStyle(dialog)))
  })
  t.is(banner.position, 'fixed', 'position is fixed')
  t.is(banner.zIndex, '6000001', 'z index is on top')
})

И последнее, но не менее важное: я рад, что API так похож на браузер, и вы можете проверить, что происходит внутри. Моя основная цель, как я уже говорил вам, заключалась в том, чтобы протестировать файл cookie, и вот результат.

test('Cookie banner is not visible after reload', async (t) => {
  await page.waitForSelector('button.js_accept')
  await page.click('button.js_accept')
  await page.reload()
  await page.waitForSelector('.ck_cookie_unrendered')
  const classes = await page.$eval('.ck_hidden', el => el.className)
  t.true(classes.indexOf('ck_hidden') !== -1, 'span without banner')
  const [ returnedCookie ] = await page.cookies()
  t.is(returnedCookie.name, 'Cookie_Consent', 'name is ok')
  t.is(returnedCookie.value, 'Accepted', 'value is ok')
})

Я не только смог перезагрузить страницу без каких-либо проблем после нажатия кнопки, но и возможность проверить имя файла cookie, значение, дату истечения срока действия и все другие важные свойства файла cookie было реальным делом, чтобы начать использовать кукольник все больше и больше. внутри моих проектов.