UNPKG

riot-test-utils

Version:
420 lines (269 loc) 9.03 kB
Riot-test-utils =============== This provides lightweight testing of `Riot` tags. It is highly inspired by [`React-test-utils`](https://reactjs.org/docs/test-utils.html) [`Enzyme`](https://github.com/airbnb/enzyme), great testing utility for [`React`](https://reactjs.org/). Shallow-rendering is provided by [`Riot-shallowize`](https://www.npmjs.com/package/riot-shallowize) including the limitation about transclusions. Features: - Shorter way to setup unit-testing of tags. - Wrapper API of an instance of tags to inspect easily - DOM Traversing API similar to jQuery - jQuery integration - *Shallow-rendering*. - Snapshot testing This library is being developing and have **breaking changes** even if minor update. Any contributions are welcome! Installation ------------ Install via `npm`: ```bash npm install -D riot-test-utils ``` UMD module is also available. For example loading from CDN like jsdelivr is like: ```html <script src="https://cdn.jsdelivr.net/npm/riot@3.9/riot.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/riot-test-utils@1.1.0/dist/index.umd.min.js"></script> ``` Dependent packages `riot-shallowize`, `simulate-event` and other utilities are bundled in UMD. Usage ----- Import as: ```js // es5/commonjs var mount = require('riot-test-utils').mount; // es6 import { mount } from 'riot-test-utils'; ``` Create wrapper for the tag to test as: ```js var wrapper = mount('tag'); var wrapperWithOpts = mount('tag-with-opts', { title: 'RiotJS' }); ``` and look outerHTML: ```js assert(wrapper.html() === '<tag data-is="tag"><p>Hello, world!</p></tag>'); ``` Templating also works. ```js var wrapper = mount('<tag><p>{opts.greeting}</p></tag>', { greeting: 'Hello, world!' }); assert(wrapper.html() === '<tag data-is="tag"><p>Hello, world!</p></tag>'); ``` ### Embedding style We can write single tag source in the following style: ```js var wrapper = mount('<tag><p>Hello, world!</p></tag>'); ``` Specify the name to test when you have multiple tags: ```js var wrapper = mount( [ '<tag1><tag2 /></tag1>', '<tag2><p>Hello, world!</p></tag2>', ].join('\n'), 'tag1' ); ``` ### Shallow rendering This library provides great **shallow-rendering** feature as `React-test-utils`. It truly separates your tests of one tag from the others. For example: ```js var shallow = require('react-test-utils').shallow; var wrapper = shallow( [ '<inner><p>{opts.data}</p></inner>', '<outer><inner data={ opts.innerData }/></outer>' ].join('\n'), 'outer', { innerData: 'Hello!' } ); ``` This is *shallow* rendered as: ```js assert(wrapper.html() === '<outer data-is="outer"><inner data="Hello!"></inner></outer>'); ``` Of course, you can mount by name being registered. ```js var wrapper = shallow('outer', { innerData: 'Hello!' }); ``` DOM testing ----------- You can get DOM Element by `root`. Then, you can inspect by DOM API or some utility like jQuery. ```js var wrapper = mount('tag', { greeting: 'Hellow, world' }); // find by DOM API assert(wrapper.root.querySelector('p').textContent === 'Hellow, world' ); // find by jQuery assert($(wrapper.root).find('p').text() === 'Hello, world'); ``` And gather internal elements by `find()` method and inspect them. ```js const itemsWrapper = wrapper.find('ul.todo-list > li'); assert(itemsWrapper.length === 5); assert(itemsWrapper.get(0).text() === 'Buy a car'); ``` Snapshot testing ---------------- You can use `toJSON()` to use **[snapshot-testing](https://facebook.github.io/jest/docs/en/snapshot-testing.html)** to keep your tags. With `jest` for example: ```js it('should match snapshot', function () { var wrapper = shallow('<tag><h1>Example:</h1><p>Hello, world!</p></tag>'); expect(wrapper.toJSON()).toMatchSnapshot(); }); ``` Then, you will see the following result if different: ```diff <tag data-is={ Array [ "tag" ] } > - Hello, world! + <h1> + Example: + </h1> + <p> + Hello, world! + </p> </tag> ``` Public API ---------- ### Module #### mount(tagName, [opts], [mountOptions]) #### mount(singleTagSource, [opts], [mountOptions]) #### mount(multipleTagSource, tagName, [opts], [mountOptions]) Mount a tag with full-rendering. #### shallow(tagName, [opts], [mountOptions]) #### shallow(singleTagSource, [opts], [mountOptions]) #### shallow(multipleTagSource, tagName, [opts], [mountOptions]) Mount a tag with shallow-rendering. They return `RiotWrapper`. #### Parameters of mount/shallow | Parameter | Type | Description | | ----------------- | ------ | ------------------------------------------------------------ | | tagName | String | name of tag to test. You need to have loaded the tag somewhere without `singleTagSource` or `multipleTagSource`. | | singleTagSource | String | content of one tag to test. | | multipleTagSource | String | content of tags including one to test. It requires `tagName` too. | | opts | Object | tag interface | | mountOptions | Object | Options to mount. It has one optional property `attachTo`. See below. | ##### mountOptions.attachedTo An option to specify the element to mount on. ###### Example ```html <div> <span id="app"></span> </div> <script> var span = document.getElementById('id'); var wrapper = mount('my-tag', { attachTo: span }); </script> ``` ### RiotWrapper Wrapper of tag instance to be mounted or shallow-mounted. #### instance Get `TagInstance` of root. #### root Get root DOM Element. It is equivalent to `instance.root`. #### opts Get opts, including "data-is" attribute added during rendering. It is equivalent to `instance.opts`. #### parent Get the parent tag instance. It is equivalent to `instance.parent` and always `null`. #### tags Get nested tags. It is equivalent to `instance.tags`. #### refs Get refs. It is equivalent to `instance.refs`. #### on(event, callback) #### one(event, callback) #### trigger(event, ...args) #### off(event, [callback]) All the observable methods. It is equivalent to `instance,on()` and the others but returns the wrapper itself. Note: `this` is always the unwrapped instance in callbacks. #### isMounted Get the flag if the tag is mounted or not. It is equivalent to `instance.isMounted`. #### mount() Mount the tag. Note it is already mounted initially. It is equivalent to `instance.mount()`. #### unmount([keepTheParent]) Unmount the tag. It is equivalent to `instance.unmount()`. #### update([data]) Update the tag and its children. It is equivalent to `instance.update()`. #### mixin(mixin) Apply mixin to the tag. It is equivalent to `instance.mixin()`. #### find(selector) Find internal elements by CSS selector. This returns `WeakWrapper` #### html() Get outer HTML by string. #### text() Get internal concatenated text. #### toJSON() Get json form to create snapshot #### simulate(eventType, [options]) Fire event. For example: ```js wrapper.simulate('click'); ``` ```js wrapper.simulate('keyup', { key: 'a', keyCode: 97, metaKey: true }); ``` All the events are listed in [source](./src/lib/Simulate/eventTypes.ts). ### WeakWrapper Wrapper of DOM elements to be found. #### instance Tag instance. This always returns `null`. #### root **Throws** unless wrapped elements are single. #### length Get number of wrapped elements. #### get([index]) Get wrapped element(s) as `Element` or array of `Element`. #### find(selector) Find more under the wrapped element(s) by CSS selector. #### text() #### html() #### toJSON() Contents APIs above are supported as well as `RiotWrapper`, but first two methods **throws** unless single. #### simulate(eventType, [options]) Fire event. If wrapper has multiple elements, it fires each element in the order of appearance. ## jQuery integration You can use some methods to inspect DOM of [jQuery](https://jquery.com/) integrated with `RiotWrapper` and `ShallowWrapper`. Check [Riot-test-utils-jquery](https://www.npmjs.com/package/riot-test-utils-jquery) out. Enzyme integration ------------------ Check [Riot-enzyme](https://www.npmjs.com/package/riot-enzyme) out, but nearly archived. Requirement ----------- - JavaScript runtime, ES5 compatible at least and supports: - `Symbol` for snapshot testing. - DOM Environment like real browsers or `jsdom` and supports: - `querySelectorAll` and `compareDocumentPosition` for finding(IE9 is dropped!). TODO ---- - [x] Event simulated - [x] Deep rendering - [ ] Compiler options to set parsers - [x] Implement update. - [ ] To test the attributes of root opts - [ ] Full-featured finding API. - [x] More efficient API for multiple tags to compile once shared and use anywhere. - [ ] Other testing utility. - [x] Finding API on `querySelctorAll` similar to jQuery or Cheerio like Enzyme - [ ] *To promote* results of find() if they are actually tag instances.