Last active
August 1, 2020 15:49
-
-
Save philmander/29eb95e7992eb360ed7f537ea29db17b to your computer and use it in GitHub Desktop.
Simple Preact Unit Testing with Jest (with shallow rendering)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { options as preactOptions, render } from 'preact'; | |
let shouldRenderShallow; | |
let previousVNodeHook; | |
// wrap the Preact.render() to make it render shallow with a vnode hook | |
// adapted from https://gist.github.com/robertknight/88e9d10cff9269c55d453e5fb8364f47 | |
export function createShallowRenderer({ prefix = 'h-', context = {} } = {}) { | |
shouldRenderShallow = 2; | |
const vnodeHook = node => { | |
if (previousVNodeHook) { | |
previousVNodeHook(node); | |
} | |
if (typeof node.nodeName === 'string') { | |
return; | |
} | |
if(shouldRenderShallow <= 0) { | |
node.nodeName = prefix + node.nodeName.name; | |
} | |
shouldRenderShallow--; | |
}; | |
preactOptions.vnode = vnodeHook; | |
return (vnode, parent, merge) => { | |
const vnodeWithContext = h(ContextWrapper, { context }, vnode); | |
render(vnodeWithContext, parent, merge); | |
preactOptions.vnode = previousVNodeHook; | |
}; | |
} | |
// handy function to dispatch events and return a promise which is resolved after next tick | |
export function simulate(node, event) { | |
// pass a selector or a dom node | |
if(typeof node === 'string') { | |
node = document.querySelector(node); | |
} | |
// pass an event object or an event name | |
event = event instanceof window.Event ? event : new window.Event(event); | |
node.dispatchEvent(event); | |
// return a promise that resolves on next tick so the invoking code see the update | |
return new Promise(resolve => { | |
process.nextTick(() => { resolve() }); | |
}); | |
} | |
// wraps the node under test so a test context can be injected | |
function ContextWrapper({ context, children }) { | |
this.context = Object.assign(this.context, context); | |
return <div> { children } </div>; | |
} |
For comparing snapshots, (e.g. renderer.create(<Nav />).toJSON()
) see preact-render-to-json
wow.
@philmander is there not a package released for this? I think having the simulate
function or a way to fire events is very helpful.
Didn't seem worth it, but feel free to do so if it helps
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This example uses just Jest and Babel (using the standard Preact setup).
preact-test-helper.js
exports two functions:createShallowRenderer()
wraps `Preact.render() with a hook to support shallow rendering.simulate()
is a helper function to dispatch reguler dom events on the jsdom supplied by Jest.