{"id":1282,"date":"2018-02-06T15:10:19","date_gmt":"2018-02-06T15:10:19","guid":{"rendered":"https:\/\/loadfocus.com\/blog\/?p=1282"},"modified":"2023-05-09T15:14:25","modified_gmt":"2023-05-09T15:14:25","slug":"visual-ui-regression-testing-with-jest-puppeteer-and-headless-chrome","status":"publish","type":"post","link":"https:\/\/loadfocus.com\/blog\/2018\/02\/visual-ui-regression-testing-with-jest-puppeteer-and-headless-chrome","title":{"rendered":"Visual UI Regression Testing with Jest, Puppeteer and Headless Chrome"},"content":{"rendered":"<span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\"><\/span> <span class=\"rt-time\"> 2<\/span> <span class=\"rt-label rt-postfix\">minutes read<\/span><\/span><p class=\"lead\"><!-- pn-tldr --><\/p>\n<h2>Key takeaways<\/h2>\n<ul>\n<li>Image comparison catches visual breakage that assertions never check for.<\/li>\n<li>Set a difference threshold, or font rendering will fail the suite on every machine.<\/li>\n<li>Run in a consistent environment; a different OS produces different pixels.<\/li>\n<\/ul>\n<p><!-- \/pn-tldr -->Jest is a complete and easy to set-up JavaScript testing solution which also provide a Snapshot Testing built-in mechanism.<\/p>\n<p>With the Snapshot Testing functionality you can capture snapshots of React trees or other serializable values to simplify testing and to analyze how state changes over time.<\/p>\n<p>In this article we are going to take advantage of Jest functionality to take screenshots of web pages using <a href=\"https:\/\/github.com\/GoogleChrome\/puppeteer\">Puppeteer<\/a> and compare generated screenshots with screenshots baseline in order to find regressions in the UI of any web page.<\/p>\n<p>Jest is very easy to use with <a href=\"https:\/\/github.com\/GoogleChrome\/puppeteer\">Puppeteer<\/a> due to its&nbsp;Global Setup\/Teardown and Async Test Environment APIs. More details on <a href=\"https:\/\/loadfocus.com\/blog\/tech\/2017\/12\/how-to-take-screenshots-with-puppeteer-using-headless-chrome-browser\/\">using Puppeteer to do visual regression testing<\/a> can be found here.<\/p>\n<p>With Puppeteer you can choose whether to launch Chromium in headless mode or not (tests run faster in headless mode, but it&#8217;s useful to be able to see the browser and run the test in slow motion for debugging purposes).<\/p>\n<h3>Prerequisites for your test to be able to run Jest tests with Puppeteer in order to take and compare screenshots of your web pages:<\/h3>\n<ul>\n<li>Install Jest:<\/li>\n<\/ul>\n<pre class=\"lang-js\"><code>\nnpm install --save-dev jest jest-cli\n<\/code><\/pre>\n<ul>\n<li>Install <a href=\"https:\/\/github.com\/GoogleChrome\/puppeteer\">Puppeteer<\/a>:<\/li>\n<\/ul>\n<pre class=\"lang-js\"><code>\nnpm install --save-dev puppeteer\n<\/code><\/pre>\n<ul>\n<li>Install <a href=\"https:\/\/github.com\/americanexpress\/jest-image-snapshot\/\">Jest Image Snapshot<\/a>:<\/li>\n<\/ul>\n<pre class=\"lang-js\"><code>\nnpm i --save-dev jest-image-snapshot\n<\/code><\/pre>\n<h3>Here is an example on how to use Jest Image Snapshot:<\/h3>\n<ul>\n<li>Extend Jest&#8217;s expect assertion mechanism:<\/li>\n<\/ul>\n<h3>Example: Jest screenshot test<\/h3>\n<pre class=\"lang-js\"><code>\nconst { toMatchImageSnapshot } = require('jest-image-snapshot');\n\nexpect.extend({ toMatchImageSnapshot });\n<\/code><\/pre>\n<h3>Example: Jest screenshot test with Puppeteer and Jest Image Snapshot with Headless Chrome<\/h3>\n<pre class=\"lang-java\"><code>\n\nexport const browserConfig = {\nignoreHTTPSErrors: true,\nheadless: true,\nargs: ['--no-sandbox', '--disable-setuid-sandbox'],\n};\n\n\/\/ jest-image-snapshot custom configuration in order to save screenshots and compare the with the baseline\nexport function setConfig (filename) {\nreturn {\nfailureThreshold: '0.01',\nfailureThresholdType: 'percent',\ncustomSnapshotsDir: `${__dirname}\/..\/snapshots\/`,\ncustomSnapshotIdentifier: filename,\nnoColors: true\n}\n}\n\ndescribe('screenshot', () =&amp;amp;gt; {\nlet browser;\n\nbeforeAll(async () =&amp;amp;gt; {\n\/\/ start Puppeteer with a custom configuration, see above the setup\nbrowser = await puppeteer.launch(browserConfig);\n});\n\nit('dummy application page', async () =&amp;amp;gt; {\nconst page = await browser.newPage();\n\nexpect.extend({ toMatchImageSnapshot });\nawait page.goto('http:\/\/localhost:3000');\nawait page.setViewport({ width: 1280, height: 1400 });\n\nconst image = await page.screenshot({ fullPage: true });\nexpect(image).toMatchImageSnapshot(setConfig('image-name'));\n}, 15000);\n\nafterAll(async () =&amp;amp;gt; {\nawait browser.close();\n});\n});\n<\/code><\/pre>\n<p>Also, you can automate your visual regression testing by using our built-in <a href=\"https:\/\/loadfocus.com\/visual-regression-testing\">visual regression testing service<\/a>.<!-- pn-faq --><\/p>\n<h2>Frequently Asked Questions<\/h2>\n<h3>What does image comparison add to a test suite?<\/h3>\n<p>It catches visual breakage nothing else checks. Assertions confirm elements exist; they say nothing about whether the page looks right.<\/p>\n<h3>Why does the suite fail on every machine?<\/h3>\n<p>Font rendering. Without a difference threshold, antialiasing alone is enough to fail comparisons, particularly across operating systems.<\/p>\n<h3>How do I keep it stable?<\/h3>\n<p>Run in a consistent environment, ideally the same container everywhere. A different OS produces different pixels for identical markup.<\/p>\n<p><!-- \/pn-faq --><!-- pn-related-reading --><\/p>\n<h2>Related reading<\/h2>\n<ul>\n<li><a href=\"https:\/\/loadfocus.com\/blog\/2024\/02\/what-is-puppeteer-a-tutorial-on-how-to-use-puppeteer\">What Is Puppeteer?, A Tutorial on How to Use Puppeteer<\/a><\/li>\n<li><a href=\"https:\/\/loadfocus.com\/blog\/2024\/10\/how-to-improve-user-experience-using-synthetic-monitoring\">How To Improve User Experience Using Synthetic Monitoring<\/a><\/li>\n<li><a href=\"https:\/\/loadfocus.com\/blog\/2014\/06\/how-to-take-snapshots-of-the-browser-using-selenium-webdriver\">How to take screenshots with Selenium WebDriver<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p><span class=\"span-reading-time rt-reading-time\" style=\"display: block;\"><span class=\"rt-label rt-prefix\"><\/span> <span class=\"rt-time\"> 2<\/span> <span class=\"rt-label rt-postfix\">minutes read<\/span><\/span>Key takeaways Image comparison catches visual breakage that assertions never check for. Set a difference threshold, or font rendering will fail the suite on every machine. Run in a consistent environment; a different OS produces different pixels. Jest is a complete and easy to set-up JavaScript testing solution which also provide a Snapshot Testing built-in&#8230;  <a href=\"https:\/\/loadfocus.com\/blog\/2018\/02\/visual-ui-regression-testing-with-jest-puppeteer-and-headless-chrome\" class=\"more-link\" title=\"Read Visual UI Regression Testing with Jest, Puppeteer and Headless Chrome\">Read more &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":3737,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[48],"tags":[247,246,248],"class_list":["post-1282","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-test-automation","tag-image-comparison-with-jest-and-puppeteer","tag-jest-screenshot-testing","tag-screenshot-testing-using-headless-chrome-and-jest"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/loadfocus.com\/blog\/wp-json\/wp\/v2\/posts\/1282","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/loadfocus.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/loadfocus.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/loadfocus.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/loadfocus.com\/blog\/wp-json\/wp\/v2\/comments?post=1282"}],"version-history":[{"count":1,"href":"https:\/\/loadfocus.com\/blog\/wp-json\/wp\/v2\/posts\/1282\/revisions"}],"predecessor-version":[{"id":2574,"href":"https:\/\/loadfocus.com\/blog\/wp-json\/wp\/v2\/posts\/1282\/revisions\/2574"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/loadfocus.com\/blog\/wp-json\/wp\/v2\/media\/3737"}],"wp:attachment":[{"href":"https:\/\/loadfocus.com\/blog\/wp-json\/wp\/v2\/media?parent=1282"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/loadfocus.com\/blog\/wp-json\/wp\/v2\/categories?post=1282"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/loadfocus.com\/blog\/wp-json\/wp\/v2\/tags?post=1282"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}