@brightinteractive/bright-js-framework

Test Support

Testing Controllers

Previously, we looked at using plugins to add application-level behavior. This presents us with a problem when we come to test components that depend on plugins.

Let’s take a look at the ControlPanel component that we built previously:

src/components/ControlPanel.tsx
import * as React from 'react'
import { controller } from '@brightinteractive/bright-js-framework'
import { eventManager, EventManager } from '../plugins/EventManagerPlugin'

@controller()
export class ControlPanel extends React.PureComponent {
  @eventManager
  eventManager: EventManager

  handleOpenClick = () => {
    this.eventManager.emit('request-open-pod-bay-doors')
  }

  componentDidMount() {
    this.eventManager.registerHandler('request-open-pod-bay-doors', () => {
      console.error('I’m sorry but I can’t do that, Dave')
    })
  }

  render() {
    return (
      <div>
        <h3>Pod Bay doors:</h3>
        <button onClick={this.handleOpenClick}>Open</button>
      </div>
    )
  }
}

As a slightly contrived example of a test, let’s imagine that we want to verify that when the button is clicked, it dispatches the appropriate event.

src/components/ControlPanel.test.before.tsx
import * as React from 'react'
import { mount } from 'enzyme'
import { ControlPanel } from './ControlPanel'

describe('ControlPanel', () => {
  it('posts message when button is clicked', () => {
    const dom = mount(<ControlPanel />)
    dom.closest('button').simulate('click')
  })
})

This test will throw an exception. The ControlPanel component is expecting to receive the EventManager instance from a plugin, but we haven't provided this plugin to the test case.

Bright-js-framework provides the TestFixture class to help with this. Let’s rewrite this test case using the TestFixture class to provide an EventManager to the test:

src/components/ControlPanel.test.tsx
import * as React from 'react'
import { controllerTestFixture } from '@brightinteractive/bright-js-framework/test-utils'
import { ControlPanel } from './ControlPanel'
import EventManagerPlugin from '../plugins/EventManagerPlugin'

describe('ControlPanel', () => {
  it('posts message when button is clicked', async (done) => {
    const fixture = await controllerTestFixture({
      plugins: [EventManagerPlugin],
      markup: (
        <ControlPanel />
      )
    })

    return new Promise((resolve) => {
      fixture.getPlugin(EventManagerPlugin).eventManager.registerHandler('request-open-pod-bay-doors', () => {
        done()
      })
    })
  })
})