isolateComponent API
isolateComponent() and isolateComponentTree()​
isolateComponent
and isolateComponentTree
each accept React elements, usually rendered with JSX, and return an IsolatedComponent
Import isolateComponent:
import { isolateComponent } from 'isolate-react'
Isolate a component:
const Hello = (props) => <div>Hello {props.name}</div>
const isolated = isolateComponent(<Hello name="Arthur" />)
IsolatedComponent
IsolatedComponent
is the return type of isolateComponent. It provides methods for exploring and manipulating the isolated component.
IsolatedComponent: inspect content​
content()​
returns the component's inner content.
toString()​
returns the component's outer content.
const Answer = ({ answer }: { answer: number }) => (
<span>The answer is {answer}</span>
)
const answer = isolateComponent(<Answer answer={42} />)
console.log(answer.content()) // => 'The answer is 42'
console.log(answer.toString()) // => '<span>The answer is 42</span>'
IsolatedComponent: wait for next render​
waitForRender()​
Returns a promise that resolves after the next render.
Useful for testing components with asynchronous behavior.
const DelayedAnswer = () => {
// initial value
const [answer, setAnswer] = useState("unknown")
// update the value 100 milliseconds later
useEffect(() => {
setTimeout(() => { setAnswer("forty-two") }, 100)
}, [])
return (
<span>The answer is {answer}</span>
)
}
const answer = isolateComponent(<DelayedAnswer />)
console.log(answer.content()) // => 'The answer is unknown'
// wait for the next render
await answer.waitForRender()
console.log(answer.content()) // => 'The answer is forty-two'
IsolatedComponent: find child nodes​
findAll(selector)​
Find all nodes that match the given Selector.
Returns an array of ComponentNodes.
findOne(selector)​
Find a single child node that matches the given Selector.
Returns a ComponentNode if and only if there is a single matching node.
Throws an Error if there are zero or multiple matching nodes.
exists(selector)​
Check for the existence of any html elements or react components matching the selector. Returns true if any found, false if none found.
IsolatedComponent: inline child components​
inline(selector)​
Finds all elements rendered by the isolated component that match the given Selector and inlines them, incorporating them into the rendered output. Allows for testing some or all of the child components rendered by the isolated component together.
Use the '' wildcard to inline all child elements `inline('')`.
Important things to know:
- Inlining is recursive. The same inlining rules are
- An isolated component remembers all inlined selectors for the duration of its existence. If a new element is created that matches any inlined selector, it will also be inlined.
IsolatedComponent: Update props​
These methods both update the props of the component under test. The difference is that mergeProps preserves the props that are not set, while setProps replaces all of the props.
mergeProps(newProps)​
Set a subset of props, and re-render the component under test.
const FirstLast = (props) => <div>{props.first} {props.last}</div>
const isolated = isolateComponent(<FirstLast first="Ford" last="Prefect" />)
console.log(isolated.toString()) // => <div>Ford Prefect</div>
isolated.mergeProps({last: Focus})
console.log(isolated.toString()) // => <div>Ford Focus</div>
setProps(newProps)​
Replace all props, and re-render the component under test
const FirstLast = (props) => <div>{props.first} {props.last}</div>
const isolated = isolateComponent(<FirstLast first="Ford" last="Prefect" />)
console.log(isolated.toString()()) // => <div>Ford Prefect</div>
isolated.setProps({first: 'Arthur', last: 'Dent'})
console.log(isolated.toString()()) // => <div>Arthur Dent</div>
cleanup()​
Cleans up the component and runs all effect cleanups (functions returned by useEffect or useLayoutEffect handlers).
This is equivalent to unmounting a component/removing it from the tree.
// component that logs 'Goodbye' on unmount:
const Goodbye = () => {
useEffect(() => {
return () => { console.log('Goodbye') }
}, [])
return <div />
}
const isolated = isolateComponent(<Goodbye />)
isolated.cleanup() // Logs 'Goodbye'
setContext​
Set a context value.
Useful when testing a component that uses values from useContext:
const NameContext = createContext('Zaphod')
const HelloFromContext = () => {
const name = useContext(NameContext)
return <div>Hello ${name}</div>
}
const isolated = isolateComponent(<Hello />)
console.log(isolated.toString()()) // => <div>Zaphod</div>
isolated.setContext(NameContext, 'Trillian')
console.log(isolated.toString()()) // => <div>Trillian</div>
Selector​
Selectors
are used with the methods findOne
, findAll
, exists
, and inline
to match child nodes.
Selector
can be either a string or a component function.
Selector strings​
Selector strings support a subset of css-like matching, including matching id or class names and some matching of arbitrary properties.
- Find by tag:
button
will match any <button>
tags
- Find by id:
div#awesome-id
and #awesome-id
will find <div id='awesome' />
- Find by className:
span.cool
and .cool
will each find <span className='cool' />
m
- Find by a matching prop:
[data-test-id=foobar]
will find the react element or html element with a data-test-id
prop with the value foobar
- Find a react component by name:
MyComponent
will match a react component with a displayName of "MyComponent"
React component as selector​
You can use a react component function as a selector
ComponentNode​
The methods findOne
and findAll
on an isolated component return ComponentNodes
.
A ComponentNode
is a single node that was found within the rendered elements of an isolated component. It offers methods for inspecting its content and props.
content()​
Returns the inner content of the node.
toString()​
Returns the outer content of the node.
props​
Provides access to the props that were used on the latest render.
findAll, findOne, exists​
These methods work the same as the equivalent methods on IsolatedComponent, scoped to the children of the ComponentNode.
Typescript note​
Depending on the Selector that was used, access to props
may be typesafe.
If a component function was used as a selector, the type of props
will match the props of that component. If a string selector was used, the props willl be untyped (any).