react-ioc-widgets-test-renderer

Test harness for widgets

Usage no npm install needed!

<script type="module">
  import reactIocWidgetsTestRenderer from 'https://cdn.skypack.dev/react-ioc-widgets-test-renderer';
</script>

README

React IoC Widgets Test Renderer

This library works alongside React IoC Widgets to create an easy to use renderer based on react-testing-library that makes writing unit tests for your components straightforward.

Installation

npm install --save-dev react-ioc-widgets-test-renderer

Writing a test

You’ll have built a module or two that add editors or layouts perhaps something like this:

example-module.js

import React from "react"
import {useLayout, useDesign, useTabs} from "react-ioc-widgets"

function TestRender() {
    const [design] = useDesign()
    return <div>{design.title}</div>
}

function TestEditor() {
    const [design, update] = useDesign()
    return <input data-testid="input" value={design.title} onChange={e=>update({title: e.target.value})}/>
}

export default function (widgets) {
    widgets.configure("test", ()=>{
        useLayout({content: [TestRender]})
    })
    widgets.editor("test", ()=>{
        useTabs(TestEditor)
    })
}

Now you want to write a unit test to make sure that the renderer renders and the editor updates.

The React IoC Widgets Test Renderer makes this simple by providing a single call that will render a Widgets component and editor using react-testing-library and provide a couple of extra properties on the return to enable you to interact with it.

Firstly you can pass in some special parameters to the render call:

  • modules - an array of functions exported from standard modules to bind to a widget event emitter. You can just bind everything to globalWidgets and omit this, it depends on how you’ve built your module.
  • design - a design document, the test renderer will provide an empty one if you don’t supply a value
  • document - a document, the test renderer will provide an empty one if you don’t supply a value
  • type - a type of the document

After the render finished you will have an object result that contains a number of properties in addition to the ones provided by react-testing-library (getByText, getByTestId, asFragment etc).

  • design - the design used for the widgets
  • document - the document used for the widgets
  • bag - the bag used for the component
  • setEditMode(bool) - a function used to turn edit mode on and off
  • selectEditorTab(tabTitleOrName) - a function used to select an editor tab
  • widgets - a WidgetEvents emitter to interact with the rendered modules

So now some tests for your module might look like this: example-module.test.js

import testModule from "./example-module"
import {render, fireEvent} from "react-ioc-widgets-test-renderer"

describe("Example Module", ()=>{

    it("Should render into the document", ()=>{
        const {getByText} = render({modules:[testModule], design: {title: "test"}, type: "test"})
        getByText("test")
    })

    it("should have an editor which updates the rendering", ()=>{
        const {getByText, setEditMode, getByTestId, selectEditorTab, asFragment} = render({modules: [testModule], design: {title: "testing"}, type: "test"})
        selectEditorTab("general")
        fireEvent.change(getByTestId("input"), {target: {value: "updated"}})
        setEditMode(false)
        expect(getByText("updated").nodeName).toBe("DIV")
        expect(asFragment()).toMatchSnapshot()
    })
})

Writing a test for a module that uses globalWidgets

example-global.js

import React from "react"
import {globalWidgets, useLayout} from "react-ioc-widgets"

function TestRenderer() {
    return <div>Test Global 1</div>
}

globalWidgets.configure("test", function() {
    useLayout({content: [TestRenderer]})
})

Now you can write a test like this:

import {render} from "react-ioc-test-renderer"
import "./example-global"

it("should be able to render global widgets", function() {
    const {getByText} = render({type: "test"})
    getByText("Test Global 1")
})