{"_id":"nodecg-screenshot-tester","_rev":"33-47f54c8a88d45935ab664f2d07302b20","time":{"0.0.1":"2020-12-07T15:38:08.056Z","0.1.0":"2020-12-07T15:38:08.056Z","0.1.1":"2020-12-07T15:38:08.056Z","1.0.0":"2020-12-07T15:38:08.056Z","2.0.0":"2020-12-07T15:38:08.056Z","2.1.0":"2020-12-07T15:38:08.056Z","2.1.1":"2020-12-07T15:38:08.056Z","2.1.2":"2020-12-07T15:38:08.056Z","2.2.0":"2020-12-07T15:38:08.056Z","2.2.1":"2020-12-07T15:38:08.056Z","2.2.2":"2020-12-07T15:38:08.056Z","3.0.0":"2020-12-07T15:38:08.056Z","4.0.0":"2020-12-07T15:38:08.056Z","4.1.0":"2020-12-07T15:38:08.056Z","5.0.0":"2020-12-07T15:38:08.056Z","5.0.1":"2020-12-07T15:38:08.056Z","5.0.2":"2020-12-07T15:38:08.056Z","5.1.0":"2020-12-07T15:38:08.056Z","6.0.0":"2020-12-07T15:38:08.056Z","7.0.0":"2020-12-07T15:38:08.056Z","8.0.0":"2020-12-07T15:38:08.056Z","8.0.1":"2020-12-07T15:38:08.056Z","8.0.2":"2020-12-07T15:38:08.056Z","8.0.3":"2020-12-07T15:38:08.056Z","8.0.4":"2020-12-07T15:38:08.056Z","8.0.5":"2020-12-07T15:38:08.056Z","created":"2020-12-11T01:42:14.708Z","9.0.0":"2020-12-11T01:42:14.893Z","modified":"2022-05-11T07:10:40.771Z","8.0.6":"2020-12-11T20:11:24.845Z","5.0.3":"2021-03-08T18:03:57.369Z"},"name":"nodecg-screenshot-tester","dist-tags":{"latest":"5.0.3","legacy-8":"8.0.6"},"versions":{"9.0.0":{"name":"nodecg-screenshot-tester","version":"9.0.0","description":"Automated visual regression testing of NodeCG graphics.","scripts":{"test":"npm run static","format":"pretty-quick","static":"eslint --parser-options=project:tsconfig.json \"src/**/*.ts\"","prebuild":"npm run test","build":"trash dist && tsc -p tsconfig.json","prerelease":"npm t","release":"standard-version","postrelease":"npm publish && git push --follow-tags"},"author":{"name":"Alex Van Camp","email":"email@alexvan.camp"},"license":"MIT","dependencies":{"cheerio":"^1.0.0-rc.2","express":"^4.16.4","express-transform-bare-module-specifiers":"^1.0.4","is-ci":"^2.0.0","log-symbols":"^3.0.0","mkdirp":"^0.5.1","mock-nodecg":"^1.8.1","ora":"^2.1.0","p-each-series":"^1.0.0","p-limit":"^2.2.2","p-map":"^3.0.0","physical-cpu-count":"^2.0.0","pixelmatch":"^4.0.2","pngjs":"^3.4.0","progress":"^2.0.3","table":"^5.4.6","tmp":"0.0.33","tslib":"^1.9.1","yargs":"^11.0.0"},"devDependencies":{"@commitlint/cli":"^7.5.2","@commitlint/config-conventional":"^7.5.0","@gamesdonequick/eslint-config":"^2.2.1","@gamesdonequick/prettier-config":"^2.2.1","@types/cheerio":"^0.22.7","@types/express":"^4.16.0","@types/is-ci":"^2.0.0","@types/mkdirp":"^0.5.2","@types/node":"^10.1.1","@types/p-each-series":"^1.0.0","@types/pixelmatch":"^4.0.0","@types/pngjs":"^3.3.1","@types/progress":"^2.0.3","@types/puppeteer":"^1.3.2","@types/table":"^4.0.7","@types/tmp":"0.0.33","@types/yargs":"^11.0.0","ava":"^1.4.1","eslint":"^6.8.0","prettier":"^1.19.1","pretty-quick":"^2.0.1","trash-cli":"^1.4.0","ts-node":"^8.6.2","typescript":"^3.7.5"},"peerDependencies":{"puppeteer":"1 - 2"},"bin":{"nodecg-screenshot-tester":"dist/bin/main.js"},"repository":{"type":"git","url":"git+https://github.com/nodecg/nodecg-screenshot-tester.git"},"types":"dist/index.d.ts","husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"pretty-quick --staged"}},"engines":{"node":">=10"},"gitHead":"9b1b86984e9108ceaff923dff911b5cf024aa81f","bugs":{"url":"https://github.com/nodecg/nodecg-screenshot-tester/issues"},"homepage":"https://github.com/nodecg/nodecg-screenshot-tester#readme","_id":"nodecg-screenshot-tester@9.0.0","_nodeVersion":"12.20.0","_npmVersion":"6.14.8","dist":{"integrity":"sha512-TorBs+L5F4L2SXUlRogCUkZOlICse+UHMs+3sBQuxBPsPX6lPtOFfrgSDDqID/QHhDgud36icRsaSXnHdZwF0w==","shasum":"8cf053f0da34b999bde20a8fbb496f792b2372e4","tarball":"https://registry.npmjs.org/nodecg-screenshot-tester/-/nodecg-screenshot-tester-9.0.0.tgz","fileCount":47,"unpackedSize":74974,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf0s53CRA9TVsSAnZWagAAYeoP/iEDzxFQAso0B1FX7jPg\n1KF5lo16s4pw9EfpAlgbkDxPR7DIsYmCYwAXKN6PCA3b2n2be4jrFpjRmsat\nH6AkFYjVyhxM1qdScUX1C0GswkpRgUjTN2LEQLS6TyIUYp84/tc+lLcwfbe/\nxxCSEEaSHT9sArn357isQAimwmpdTtzyoFOdqzSGpgohdvS1FJtnpiHxLol0\nfwiiad+WlFbz234Yw9/vqtdOl8STHNtIeu6sVKMkr5hC/5U6F6h+iEHbSr7x\nRGYiENjkEQLtGZKpKM9dceMRzi8P7LJb7VbvCgDpI//ydUUKzm+AZKVhaiJs\nid48OgN2aFo2xZyJkc12iUcb7RR+KVoJLh65TEUu6clfsvqmAY/jyT8z8+/M\nbD9Hf1IL2DSIMqvI0+wKsxeI3UBk6hYRnRmiKvLxqhGQl0G7ayG+gMsE0axr\nLqZJ6/gNteUTo6kpVeHpa4RYfN9x9POutp64VjFXCQSLmVCflswKnpz5ItyU\nTztOpycozw8f8o1rnwE5Y8R44WqxdZv9yEeBjuMFIlZBm/eD0ieKk0Sj1LVU\nDnut4xotZimmNFOjiwdshKbTtz4FsuF+EXkRljv+Ym6bljs1oSZBWdiMMz0o\ngfLQGTvTVRX2m+V1dnnICJkpNvMgW/RKmQdWPyG1PO5tMkumHuiVUP6DXaYE\nG5/i\r\n=+K+s\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIBZFyn2wOvIkUhaDkN+I7Niyg5mV+ljThL1qTmBcJRDCAiBlkJRHh8pJ64g9ri6hHwvXYRq/2OXqwYIRiS7Zbr2Nkw=="}]},"_npmUser":{"name":"hoishin","email":"hoishinxii@gmail.com"},"directories":{},"maintainers":[{"name":"hoishin","email":"hoishinxii@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/nodecg-screenshot-tester_9.0.0_1607650934709_0.40226978452304407"},"_hasShrinkwrap":false},"8.0.6":{"name":"nodecg-screenshot-tester","version":"8.0.6","description":"Automated visual regression testing of NodeCG graphics.","scripts":{"test":"npm run static","format":"pretty-quick","static":"eslint --parser-options=project:tsconfig.json \"src/**/*.ts\"","prebuild":"npm run test","build":"trash dist && tsc -p tsconfig.json","prerelease":"npm t","release":"standard-version","postrelease":"npm publish && git push --follow-tags"},"author":{"name":"Alex Van Camp","email":"email@alexvan.camp"},"license":"MIT","dependencies":{"cheerio":"^1.0.0-rc.2","express":"^4.16.4","express-transform-bare-module-specifiers":"^1.0.4","is-ci":"^2.0.0","log-symbols":"^3.0.0","mkdirp":"^0.5.1","mock-nodecg":"^1.8.1","ora":"^2.1.0","p-each-series":"^1.0.0","p-limit":"^2.2.2","p-map":"^3.0.0","physical-cpu-count":"^2.0.0","pixelmatch":"^4.0.2","pngjs":"^3.4.0","progress":"^2.0.3","puppeteer":"^1.15.0","table":"^5.4.6","tmp":"0.0.33","tslib":"^1.9.1","yargs":"^11.0.0"},"devDependencies":{"@commitlint/cli":"^7.5.2","@commitlint/config-conventional":"^7.5.0","@gamesdonequick/eslint-config":"^2.2.1","@gamesdonequick/prettier-config":"^2.2.1","@types/cheerio":"^0.22.7","@types/express":"^4.16.0","@types/is-ci":"^2.0.0","@types/mkdirp":"^0.5.2","@types/node":"^10.1.1","@types/p-each-series":"^1.0.0","@types/pixelmatch":"^4.0.0","@types/pngjs":"^3.3.1","@types/progress":"^2.0.3","@types/puppeteer":"^1.3.2","@types/table":"^4.0.7","@types/tmp":"0.0.33","@types/yargs":"^11.0.0","ava":"^1.4.1","eslint":"^6.8.0","prettier":"^1.19.1","pretty-quick":"^2.0.1","trash-cli":"^1.4.0","ts-node":"^8.6.2","typescript":"^3.7.5"},"bin":{"nodecg-screenshot-tester":"dist/bin/main.js"},"repository":{"type":"git","url":"git+https://github.com/nodecg/nodecg-screenshot-tester.git"},"types":"dist/index.d.ts","husky":{"hooks":{"commit-msg":"commitlint -E HUSKY_GIT_PARAMS","pre-commit":"pretty-quick --staged"}},"engines":{"node":">=10"},"gitHead":"d10ccbea4dfc153555daddf3e35403869795d934","bugs":{"url":"https://github.com/nodecg/nodecg-screenshot-tester/issues"},"homepage":"https://github.com/nodecg/nodecg-screenshot-tester#readme","_id":"nodecg-screenshot-tester@8.0.6","_nodeVersion":"10.23.0","_npmVersion":"6.14.9","dist":{"integrity":"sha512-u9uRHF5Gd6buqppxWW/C1ZaTwuCq8greP7l+eZiEhmQU6yWFByS4DCXa8DrKBKpbf4o7H5L/RMQtG718KYWqXg==","shasum":"1b3aa981d09d39a00a7441e65111587d9ed9241b","tarball":"https://registry.npmjs.org/nodecg-screenshot-tester/-/nodecg-screenshot-tester-8.0.6.tgz","fileCount":47,"unpackedSize":77704,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJf09JtCRA9TVsSAnZWagAAfs8QAKKpNJUAOw5CY9xs5JVe\n3EGSm5RpwhQBo5OqFjkNOH1l16XwSGyzt6l9VujhjPVg4P22eMZiwyqxmIZd\nJ4oavwZFJxGO7srzGswt5QcdZDFhrKYw0fOpaxm403MwQ93CsAYkbIrMPCWj\nGTrC0SB4qtOntMyCUrpeRzR+9pM9Qpb0ECoCqeaUtKm/j81ylNT5nks76cWE\nITFvmS+8EsfAHuROCOQuKshIez4jQHXRVYIvkbrgpgRggtq5mP8nvOMI2n7y\nozu4tzN0WxeDPnWd3nC/xEoKOPsTKir0B/RStZ/+GVwgSq4B2nBnkRZ12uGF\n28dnLoaEA1VJxmKrXh4/t2QAGIugbxkLbn+dSzCvk/83Nl8AlgTm+2Zk8jjv\n0jLUH9MW0LjyY+pcbNuukvE73VxkbXoGOYG1T+v/2qI7gGwhQyo7fFTXzV3D\nXpYo8RBIb9gzaCxEhUacEO8WHa6WRbM83MxBOZVyMOiQkuJ+SpyaVoucWRTN\n3rqTwLf5EKXf6qPtvfzGCatAmYuTMyZMgD4PvXIdmeOCjpJqrgfDyEwQaTKB\njPXmBlri+nMCiBS1HwsqJxPx1DOJn8Czhx+Xp1wmyi5ftOH80LM/j7dWvHFB\nc0IUxX7WXsEoFoNSeVdXNNwPE6Iye1G55jBI3nlWM7JgPCMiMiSEYhMAFJ5Q\nB4kW\r\n=ZXO7\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIA+TsGPYxZDDAqOmAVp6HogrG6Lg10kazL6R3BR0hXLyAiAo5mjdIaQLhDNTPEmwmzW8/sJZciKKkJUFmHBo+bMBbw=="}]},"_npmUser":{"name":"hoishin","email":"hoishinxii@gmail.com"},"directories":{},"maintainers":[{"name":"hoishin","email":"hoishinxii@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/nodecg-screenshot-tester_8.0.6_1607717484721_0.12981181831727673"},"_hasShrinkwrap":false},"5.0.3":{"name":"nodecg-screenshot-tester","version":"5.0.3","description":"Automated visual regression testing of NodeCG graphics.","main":"dist/index.js","scripts":{"test":"npm run static","static":"tslint -c tslint.json 'src/**/*.ts'","prebuild":"npm run test","build":"trash dist && tsc -p tsconfig.json","prerelease":"npm t","release":"standard-version","postrelease":"npm publish && git push --follow-tags"},"author":{"name":"Alex Van Camp","email":"email@alexvan.camp"},"license":"MIT","dependencies":{"cheerio":"^1.0.0-rc.2","express":"^4.16.4","express-transform-bare-module-specifiers":"^1.0.4","mkdirp":"^0.5.1","mock-nodecg":"^1.8.1","ora":"^2.1.0","p-each-series":"^1.0.0","pixelmatch":"^4.0.2","pngjs":"^3.4.0","puppeteer":"^1.15.0","tmp":"0.0.33","tslib":"^1.9.1","yargs":"^11.0.0"},"devDependencies":{"@types/cheerio":"^0.22.7","@types/express":"^4.16.0","@types/mkdirp":"^0.5.2","@types/node":"^10.1.1","@types/ora":"^1.3.4","@types/p-each-series":"^1.0.0","@types/pixelmatch":"^4.0.0","@types/pngjs":"^3.3.1","@types/puppeteer":"^1.3.2","@types/tmp":"0.0.33","@types/yargs":"^11.0.0","ava":"^1.4.1","trash-cli":"^1.4.0","ts-node":"^6.0.3","tslint":"^5.10.0","tslint-xo":"^0.7.2","typescript":"^2.8.3"},"peerDependencies":{"ava":"^1.2.0"},"bin":{"generate-fixture-screenshots":"dist/bin/generate-fixture-screenshots.js"},"repository":{"type":"git","url":"git+https://github.com/nodecg/nodecg-screenshot-tester.git"},"types":"dist/index.d.ts","gitHead":"380e342183ccfc340adbd21d4cbca91e8ca6a3dd","bugs":{"url":"https://github.com/nodecg/nodecg-screenshot-tester/issues"},"homepage":"https://github.com/nodecg/nodecg-screenshot-tester#readme","_id":"nodecg-screenshot-tester@5.0.3","_nodeVersion":"12.21.0","_npmVersion":"6.14.11","dist":{"integrity":"sha512-Kc5jlSUkERFOioW9V3BpH7n2ucBqmmA5XaV1Z8d9vePSf6+YyuzZZK5g5XfWqHTASGJcLc3Dt9ayIvmohyrb4A==","shasum":"7e888e841448f44f33b1ee3f1ffe0ae1fb0ea926","tarball":"https://registry.npmjs.org/nodecg-screenshot-tester/-/nodecg-screenshot-tester-5.0.3.tgz","fileCount":39,"unpackedSize":82923,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgRmcNCRA9TVsSAnZWagAAm2wP/R1boK0bHTN+eXNv+Z/R\nj8XRrZt1bokatQlvLLAVyPD9G0orJquFqhU1I6rlf1KPWSnnm64JsAL3U3k2\nVrJS1CO9PpifatNFgESx0e+n85R5sKTGKSBvaZQDtkeU5KyfJ+ZLfx3+4XPK\nYYrmmNJUA/rsL8gboRD1OaHwyQnWGzzy64aabLsFNZsE6GU2jRWtqWxSOq4c\nPy6rtKGVZC6PI891rGW3rB0veVKbRLJ3UywryaOBqB663hnfwuY3SzTpjBxf\nGCZpa9SC2CPnGtMI5QgncjX169XQpXVnZYFrCr3Z60tTBgKz/m9IR/4cgGdC\n9b0QU1nJduzQzunUE6ll80pNcem1mHSpNsUSPiDGoDDoMpf2W1v3gzXPHY+/\na7bNO2ezouDaDBdeiXSc0vzH7yk/28MFZYz+9Ils6G81Dy2rFIiYYoo0kAQh\nxqA8YtGLM/jTqOEWFv0uKV28jAQ6Y0724Okf1yjl22F9PRaQcE0zrh5mfWNX\nzC2TR2jwmWE2hbjjmNHmo1Yq3uXhu2h8VTnDHYCSL/ljeypEaedxc7bL0er1\nHSePqNoDu/gxDAUIYWBZS4UDPDbYTCFCFeTxbIHlCq8M8+5VALNMvyLCR1L9\nrkPYkz+Jjwo8btW2RnTqBGWn1OXkxAn6YDMG4FSRLLW5dgsu+9Oo4WE09Ive\nedRf\r\n=5Pme\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQC0TdGY1Jh3N2cMMkQxAO4UV/feXgr6dI0dLEiEQrqnWAIhAOx5iLEx1yLzK9SaSMQTdFYIQ/jR9GxANTVAuQ33onFn"}]},"_npmUser":{"name":"hoishin","email":"hoishinxii@gmail.com"},"directories":{},"maintainers":[{"name":"mattmcnam","email":"matt@mattmcn.com"},{"name":"hoishin","email":"hoishinxii@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/nodecg-screenshot-tester_5.0.3_1615226637174_0.7603725583845757"},"_hasShrinkwrap":false}},"maintainers":[{"name":"mattmcnam","email":"matt@mattmcn.com"},{"name":"hoishin","email":"hoishinxii@gmail.com"}],"description":"Automated visual regression testing of NodeCG graphics.","homepage":"https://github.com/nodecg/nodecg-screenshot-tester#readme","repository":{"type":"git","url":"git+https://github.com/nodecg/nodecg-screenshot-tester.git"},"author":{"name":"Alex Van Camp","email":"email@alexvan.camp"},"bugs":{"url":"https://github.com/nodecg/nodecg-screenshot-tester/issues"},"license":"MIT","readme":"# nodecg-screenshot-tester [![npm version](https://img.shields.io/npm/v/nodecg-screenshot-tester.svg)](https://npm.im/nodecg-screenshot-tester) [![license](https://img.shields.io/npm/l/nodecg-screenshot-tester.svg)](https://npm.im/nodecg-screenshot-tester) [![Build Status](https://travis-ci.com/nodecg/nodecg-screenshot-tester.svg?branch=master)](https://travis-ci.com/nodecg/nodecg-screenshot-tester)\n\n> Automated visual regression testing of NodeCG graphics.\n\n## Motivation\nIt's difficult to write tests for NodeCG graphics, or really any broadcast graphics in general. With `nodecg-screenshot-tester`, screenshot tests can often be made very quickly, and for a wide variety of cases for each of your bundle's graphics.\n\nScreenshot tests aren't a complete solution, but they're pretty useful and are better than nothing. Ideally, you'd use them alongside traditional unit and integration tests.\n\n## Can you show me an example?\nYes, [`sgdq18-layouts`](https://github.com/GamesDoneQuick/sgdq18-layouts/tree/master/test) makes full use of `nodecg-screenshot-tester`. These links may help explain what `nodecg-screenshot-tester` is, and how it works:\n\n- [`sgdq18-layouts`'s `package.json`](https://github.com/GamesDoneQuick/sgdq18-layouts/blob/master/package.json)\n- [`sgdq18-layouts`'s tests](https://github.com/GamesDoneQuick/sgdq18-layouts/tree/master/test)\n- [`sgdq18-layouts`'s reference screenshots](https://github.com/GamesDoneQuick/sgdq18-layouts/tree/master/test/fixtures/screenshots), used to validate the tests\n\n## Table of Contents\n* [How do I use it in my bundle?](#bundle-usage)\n* [How do I test my animations?](#animation-testing)\n* [Can I delay the screenshot?](#delay)\n* [How do I populate Replicants for testing?](#populating-replicants)\n* [What if my graphic relies on HTTP routes not provided by `nodecg-screenshot-tester`?](#custom-routes)\n* [Can I run arbitrary code as part of my test?](#arbitrary-code)\n* [How do I run only a subset of my test cases?](#filter-cases)\n* [Are there other things I can do in my test cases?](#other)\n\n## <a name=\"bundle-usage\"></a> How do I use it in my bundle?\nTo be completely blunt, the API for this is quirky and probably could be improved. But, it does work and has been successfully used for major broadcasts.\n\n`nodecg-screenshot-tester` is hardcoded to use the [ava](https://github.com/avajs/ava) test runner. If you use another test runner such as [Mocha](https://mochajs.org/), you are out of luck.\n\n1. Add `nodecg-screenshot-tester` and `ava` as devDependencies in your bundle:\n\n\t```bash\n\tnpm i -D nodecg-screenshot-tester ava\n\t```\n2. Add these scripts to the `scripts` stanza in your bundle's `package.json` :\n\n\t```json\n\t{\n\t\t\"scripts\": {\n\t\t\t\"test\": \"ava test\",\n\t\t\t\"generate-fixture-screenshots\": \"generate-fixture-screenshots\",\n\t\t\t\"debug-fixture-screenshots\": \"generate-fixture-screenshots --debug\"\n\t\t}\n\t}\n\t```\n\n\tIf you want to run a linter or other static analysis, the `pretest` script is a good place to do so. `npm` will automatically run it before executing your `test` script.\n3. Create a dummy test which passes an `ava` instance to `nodecg-screenshot-tester`:\n\n\t```js\n\t// nodecg/bundles/your-bundle/test/screenshot-comparison.js\n    const test = require('ava');\n    const {comparisonTests} = require('nodecg-screenshot-tester');\n    comparisonTests(test);\n\t```\n4. Create a `screenshot-consts.js` file, which is where your test cases will be defined:\n\n\t```js\n\t// nodecg/bundles/your-bundle/test/helpers/screenshot-costs.js\n\tmodule.exports = {\n\t\tTEST_CASES: [{\n\t\t\troute: 'bundles/your-bundle/graphics/example.html'\n\t\t}]\n\t}\n\t```\n\t\n\tThis is the most simple possible example. All it will do is load `example.html` and take a screenshot of it. It won't try to run any of your animations or set values in any of your replicants. Those things require extra configuration, which we will cover later.\n5. Generate the \"fixture\" screenshots. These are the references used to determine if a test passes or fails:\n\n\t```bash\n\tnpm run generate-fixture-screenshots\n\t```\n\n\tIf you're having troubles with this step, you can run `npm run debug-fixture-screenshots`, which will disable headless mode in Puppeteer, allowing you to see and interact with the Chromium instance being used to take the screenshots.\n\t\n\t> ❗ Note that your graphics may render differently when using `debug-fixture-screenshots`. Only use this command for debugging, and always use the normal `generate-fixture-screenshots` to create your final, completed fixtures. Do not commit screenshots generated by `debug-fixture-screenshots`.\n6. Review your fixture screenshots, to ensure that they show what you want and don't have any issues.\n\n\t> ❗ This library doesn't know if your screenshots are good or not. All it knows is if the screenshots it takes during `npm test` match the screesnhots in your `test/fixtures/screenshots` folder. It is up to you to ensure that your fixtures are actually correct.\n7. Run the actual tests:\n\n\t```bash\n\tnpm test\n\t```\n8. With any luck, you will now have one passing screenshot test! 🙌\n\n## <a name=\"animation-testing\"></a> How do I test my animations?\nYou can provide a `selector`, `entranceMethodName` and optional `entranceMethodArgs` in your test cases. `nodecg-screenshot-tester` will find `selector` on your page and invoke that method on it with the provided args. This works with graphics made with a component framework, such as [React](https://reactjs.org/), [Polymer](https://www.polymer-project.org/), [Vue.js](https://vuejs.org/), etc.\n\nIf your element's entrance method returns a Promise, `nodecg-screenshot-tester` will wait for that Promise to resolve before taking the screesnhot.\n\nLikewise, if your element's entrance method returns a [GreenSock](https://greensock.com/gsap) tween or timeline, `nodecg-screenshot-tester` will wait for that animation to complete before taking the screenshot.\n\n##### Example: \n```js\n// nodecg/bundles/your-bundle/test/helpers/screenshot-costs.js\nmodule.exports = {\n\tTEST_CASES: [{\n\t\troute: 'bundles/your-bundle/graphics/example.html',\n\t\tselector: 'my-root-element',\n\t\tentranceMethodName: 'enter',\n\t\tentranceMethodArgs: ['foo', 123, {bar: 'baz'}]\n\t}]\n}\n```\n\n## <a name=\"delay\"></a> Can I delay the screenshot?\nYes! Just add an `additionalDelay` key to your test case.\n\nIt might feel like this is a hack, but you'll probably find yourself needing to add at least a few hundred milliseconds of additional delay to _most_ of your tests. Graphics are hard.\n\n##### Example:\n```js\n// nodecg/bundles/your-bundle/test/helpers/screenshot-costs.js\nmodule.exports = {\n\tTEST_CASES: [{\n\t\troute: 'bundles/your-bundle/graphics/example.html',\n\t\tadditionalDelay: 1000 // Delays for 1000 milliseconds after the page has finished loading.\n\t}, {\n\t\troute: 'bundles/your-bundle/graphics/example2.html',\n\t\tentranceMethodName: 'enter',\n\t\tadditionalDelay: 1000 // Delays for 1000 milliseconds after entranceMethod has resolved.\n\t}]\n}\n```\n\n## <a name=\"populating-replicants\"></a> How do I populate Replicants for testing?\nIf your test case specifies a `replicantPrefills` object, it will populate those Replicants with the specified values before running your entrance method (if defined) and taking the screenshot.\n\nYou can even put your Replicant values in a file on disk and have `nodecg-screenshot-tester` load them for you.\n\n##### Example:\n```js\n// nodecg/bundles/your-bundle/test/helpers/screenshot-costs.js\nmodule.exports = {\n\tTEST_CASES: [{\n\t\troute: 'bundles/your-bundle/graphics/example.html',\n\t\treplicantPrefills: {\n\t\t\texampleReplicant: 'The \"exampleReplicant\" replicant will be given a string value',\n\t\t\tarrayExample: ['this', 'one', 'will', 'have', 'an', 'array', 'value'],\n\t\t\tobjectExample: {objects: 'are', okay: 'too!'},\n\t\t\t\n\t\t\tfixtureExample: undefined // <- \"undefined\" is a special value!\n\t\t\t// This special value tells `nodecg-screenshot-tester` to load the value from the \t\n\t\t\t// nodecg/bundles/your-bundle/test/fixtures/replicants/fixtureExample.rep file on disk.\n\t\t}\n\t}]\n}\n```\n\n## <a name=\"custom-routes\"></a> What if my graphic relies on HTTP routes not provided by `nodecg-screenshot-tester`?\nYou can provide a `CUSTOM_ROUTES` key in your `screenshot-consts.js` export. Routes are handled by [`express`](https://expressjs.com/), so refer to its docs for more details on how to write a route.\n\n##### Example:\n```js\n// nodecg/bundles/your-bundle/test/helpers/screenshot-costs.js\nmodule.exports = {\n\tCUSTOM_ROUTES: [{\n\t\tmethod: 'get',\n\t\troute: `/your-bundle/cache/:digest`,\n\t\thandler: (req, res, next) => {\n\t\t\t// Lange: This is a real example from a super secret bundle I made for a client! \n\t\t\tlet fileName = req.params.digest;\n   \n\t\t\tconst variant = req.query.variant;\n\t\t\tif (variant) {\n\t\t\t\tfileName += `_${variant}`;\n\t\t\t}\n   \n\t\t\tconst fileLocation = path.join(BUNDLE_ROOT, 'test/fixtures/images', `${fileName}.png`);\n\t\t\tres.sendFile(fileLocation, err => {\n\t\t\t\tif (!err) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n   \n\t\t\t\tif (err.code === 'ENOENT') {\n\t\t\t\t\treturn res.sendStatus(404);\n\t\t\t\t}\n   \n\t\t\t\treturn next();\n\t\t\t});\n\t\t}\n\t}, {\n\t\tmethod: 'post',\n\t\troute: `/your-bundle/example-post-route`,\n\t\thandler: async (req, res) => {\n\t\t\t// Logic goes here.\n\t\t\t// Note that we made this one an async method! Anything goes. :)\n\t\t}\n\t}],\n\tTEST_CASES: [{\n\t\troute: 'bundles/your-bundle/graphics/example.html'\n\t}]\n}\n```\n\n## <a name=\"arbitrary-code\"></a> Can I run arbitrary code as part of my test?\nYes! You can provide a `before` method in your test case, which will be run before the screenshot is taken. It will also be run before the entrance method, if you provided a `selector` and `entranceMethodName`.\n\n`before` methods have two arguments: `page` and `element`. Your `before` method runs in the Node.js server context, but you can easily run code in the Chromium browser context via methods such as [`page.evaluate`](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#pageevaluatepagefunction-args).\n\n`page` is the [Puppeteer Page](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-page) instance for this particular test case. This gives you full access to the Puppeteer API to do whatever you need to do on your page to get it ready for a screenshot. Every test case is run on its own page. Things you do in one page will not affect other test cases.\n\n`element` is an optional argument which will only be defined if your test case specified a `selector`. If your selector was found on the page, `element` will be the [Puppeteer ElementHandle](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-elementhandle) for your element.\n\nYour `before` method can return a Promise, which also means it can be an `async` method!\n\n##### Example:\n```js\n// nodecg/bundles/your-bundle/test/helpers/screenshot-costs.js\nmodule.exports = {\n\t\tTEST_CASES: [{\n\t\t\troute: 'bundles/your-bundle/graphics/sync-before-example.html',\n\t\t\tbefore(page, element) {\n\t\t\t\tconsole.log('Just some simple synchronous code.');\n\t\t\t\tconsole.log('You can put anything in here that you need to!');\n\t\t\t}\n\t\t}, {\n\t\t\troute: 'bundles/your-bundle/graphics/async-before-example.html',\n\t\t\tbefore: async (page, element) => {\n\t\t\t\tconsole.log('But you can also use async code in you `before` method if you need to!');\n\t\t\t\tawait page.evaluate(() => {\n\t\t\t\t\tconsole.log('This will print in the browser console! Cool!');\n\t\t\t\t});\n\t\t\t}\n\t\t}]\n\t}\n```\n\n## <a name=\"filter-cases\"></a> How do I run only a subset of my test cases?\nThe `--filter` option is what you're looking for. The value you enter will be interpreted as a RegExp.\n\nFiltering your actual ava tests requires `ava@^1.0.0` (currently in beta).\n\n##### Example:\n```bash\nnpm run generate-fixture-screenshots -- --filter=example\nnpm test -- -- --filter=example\nava test -- --filter=example\n```\n\n## <a name=\"other\"></a> Are there other things I can do in my test cases?\nThere might be! I'm not always the greatest at updating documentation. 🙇‍♂️\n\nYou can look at the `TestCase` interface in [screenshot-consts.ts](https://github.com/nodecg/nodecg-screenshot-tester/blob/master/src/screenshot-consts.ts) to see all the supported properties.\n","readmeFilename":"README.md"}