|  | 
| 1 | 1 | # Setting up AVA for browser testing | 
| 2 | 2 | 
 | 
| 3 |  | -Translations: [Español](https://github.com/avajs/ava-docs/blob/main/es_ES/docs/recipes/browser-testing.md), [Français](https://github.com/avajs/ava-docs/blob/main/fr_FR/docs/recipes/browser-testing.md), [Italiano](https://github.com/avajs/ava-docs/blob/main/it_IT/docs/recipes/browser-testing.md), [Русский](https://github.com/avajs/ava-docs/blob/main/ru_RU/docs/recipes/browser-testing.md), [简体中文](https://github.com/avajs/ava-docs/blob/main/zh_CN/docs/recipes/browser-testing.md) | 
|  | 3 | +AVA is running in a __Node.js__ environment. JavaScript that runs in a browser will likely expect the browser DOM globals to be in place. | 
|  | 4 | +With help from a package called [jsdom](https://github.com/jsdom/jsdom), | 
|  | 5 | +you can write unit tests with `ava` also for JavaScript that will run in a browser | 
|  | 6 | +and relying on browser specific globals such as `window`, `document` and `navigator`. | 
| 4 | 7 | 
 | 
| 5 |  | -AVA does not support running tests in browsers [yet](https://github.com/avajs/ava/issues/24). However JavaScript libraries that require browser specific globals (`window`, `document`, `navigator`, etc) can still be tested with AVA by mocking these globals. | 
|  | 8 | +## Install jsdom | 
| 6 | 9 | 
 | 
| 7 |  | -This recipe works for any library that needs a mocked browser environment. | 
| 8 |  | - | 
| 9 |  | -## Install browser-env | 
| 10 |  | - | 
| 11 |  | -> **❗️ Important note** | 
| 12 |  | -> | 
| 13 |  | ->`browser-env` adds properties from the `jsdom` window namespace to the Node.js global namespace. This is explicitly [recommended against](https://github.com/tmpvar/jsdom/wiki/Don't-stuff-jsdom-globals-onto-the-Node-global) by `jsdom`. Please read through the linked wiki page and make sure you understand the caveats. If you don't have lots of dependencies that also require a browser environment then [`window`](https://github.com/lukechilds/window#universal-testing-pattern) may be a better solution. | 
| 14 |  | -
 | 
| 15 |  | -Install [browser-env](https://github.com/lukechilds/browser-env). | 
| 16 |  | - | 
| 17 |  | -> Simulates a global browser environment using jsdom. | 
| 18 |  | -
 | 
| 19 |  | -``` | 
| 20 |  | -$ npm install --save-dev browser-env | 
|  | 10 | +```bash | 
|  | 11 | +npm install --save-dev jsdom | 
| 21 | 12 | ``` | 
| 22 | 13 | 
 | 
| 23 |  | -## Setup browser-env | 
| 24 |  | - | 
| 25 |  | -Create a helper file, prefixed with an underscore. This ensures AVA does not treat it as a test. | 
|  | 14 | +## Writing unit tests | 
| 26 | 15 | 
 | 
| 27 |  | -`test/_setup-browser-env.js`: | 
|  | 16 | +Use `jsdom` to set the globals and the DOM elements that the test target is expecting. | 
| 28 | 17 | 
 | 
| 29 |  | -```js | 
| 30 |  | -import browserEnv from 'browser-env'; | 
| 31 |  | -browserEnv(); | 
| 32 |  | -``` | 
| 33 | 18 | 
 | 
| 34 |  | -By default, `browser-env` will add all global browser variables to the Node.js global scope, creating a full browser environment. This should have good compatibility with most front-end libraries, however, it's generally not a good idea to create lots of global variables if you don't need to. If you know exactly which browser globals you need, you can pass an array of them. | 
|  | 19 | +### An example Unit Test | 
|  | 20 | +The JavaScript code to be tested is doing a DOM query, such as: `document.querySelector('#my-element-id')`. | 
| 35 | 21 | 
 | 
| 36 |  | -```js | 
| 37 |  | -import browserEnv from 'browser-env'; | 
| 38 |  | -browserEnv(['window', 'document', 'navigator']); | 
| 39 |  | -``` | 
| 40 |  | - | 
| 41 |  | -You can expose more global variables by assigning them to the `global` object. For instance, jQuery is typically available through the `$` variable: | 
| 42 |  | - | 
| 43 |  | -```js | 
| 44 |  | -import browserEnv from 'browser-env'; | 
| 45 |  | -import jQuery from 'jquery'; | 
| 46 |  | - | 
| 47 |  | -browserEnv(); | 
| 48 |  | -global.$ = jQuery(window); | 
| 49 |  | -``` | 
| 50 |  | - | 
| 51 |  | -## Configure tests to use browser-env | 
| 52 |  | - | 
| 53 |  | -Configure AVA to `require` the helper before every test file. | 
| 54 |  | - | 
| 55 |  | -**`package.json`:** | 
| 56 |  | - | 
| 57 |  | -```json | 
| 58 |  | -{ | 
| 59 |  | -	"ava": { | 
| 60 |  | -		"require": [ | 
| 61 |  | -			"./test/_setup-browser-env.js" | 
| 62 |  | -		] | 
| 63 |  | -	} | 
| 64 |  | -} | 
| 65 |  | -``` | 
| 66 |  | - | 
| 67 |  | -## Enjoy! | 
| 68 |  | - | 
| 69 |  | -Write your tests and enjoy a mocked browser environment. | 
| 70 |  | - | 
| 71 |  | -`test.js`: | 
|  | 22 | +To make the code testable with `ava`, add the element to `jsdom` and set the global object. | 
| 72 | 23 | 
 | 
| 73 | 24 | ```js | 
| 74 | 25 | import test from 'ava'; | 
|  | 26 | +import { JSDOM } from 'jsdom'; | 
| 75 | 27 | 
 | 
| 76 |  | -test('Insert to DOM', t => { | 
| 77 |  | -	const div = document.createElement('div'); | 
| 78 |  | -	document.body.appendChild(div); | 
|  | 28 | +test.before(() => { | 
|  | 29 | +  const dom = new JSDOM('<div id="my-element-id" />');  // insert any html needed for the unit test suite here | 
|  | 30 | +  global.document = dom.window.document; // add the globals needed for the unit tests in this suite. | 
|  | 31 | +}); | 
|  | 32 | + | 
|  | 33 | +test('this is an example', (t) => { | 
|  | 34 | +    const res = myTarget.runFunctionThatExpectsTheDocumentGlobalAndElement(); | 
| 79 | 35 | 
 | 
| 80 |  | -	t.is(document.querySelector('div'), div); | 
|  | 36 | +    t.truthy(res); | 
| 81 | 37 | }); | 
| 82 | 38 | ``` | 
|  | 39 | + | 
|  | 40 | +## Important note | 
|  | 41 | +In general, adding globals to the `Node.js` environment is [recommended against](https://github.com/jsdom/jsdom/wiki/Don't-stuff-jsdom-globals-onto-the-Node-global) by `jsdom`. | 
|  | 42 | +Please read through the linked wiki page and make sure you understand why. | 
0 commit comments