Backbone Testing Library
DOM testing utilities for Backbone
with an API that mirrors React Testing Library
.
Interested in working on projects like this? Close is looking for great engineers to join our team!
Why would you want this... It's nearly 2021!?
At Close a large portion of our app is still written in Backbone
and we're carefully
transitioning this to React
. We created this library as a way to write tests on our
Backbone
components in the style of React Testing Library
. This means, as we port
components over, we are able to use the same tests with very minimal changes and so
minimize regressions in our app. While we wouldn't recommend building a brand new FE app
with Backbone
, we're open sourcing this to help anyone else looking to transition a
legacy codebase.
Installation
This module is distributed via npm which is bundled with node and
should be installed as one of your project's devDependencies
.
This library also has peerDependencies
listings for @testing-library/dom
:
npm install --save-dev @closeio/backbone-testing-library @testing-library/dom
or
for installation via yarn
yarn add --dev @closeio/backbone-testing-library @testing-library/dom
You may also be interested in installing @testing-library/jest-dom
so you can
use the custom jest matchers.
Example
import Backbone from 'backbone';
const HiddenMessageModel = Backbone.Model.extend({
defaults: {
message: '',
showMessage: false,
},
});
export default HiddenMessageModel;
import Backbone from 'backbone';
const HiddenMessageView = Backbone.View.extend({
events: {
'change #toggle': 'setShowMessage',
},
initialize({ model }) {
this.model = model;
this.model.on('change', this.render.bind(this));
},
setShowMessage(e) {
this.model.set('showMessage', e.target.checked);
},
template({ showMessage, message }) {
return `<div>
<label for="toggle">Show Message</label>
<input
id="toggle"
type="checkbox"
${showMessage ? 'checked' : ''}
/>
${showMessage ? message : ''}
</div>`;
},
render() {
this.$el.html(this.template(this.model.attributes));
},
});
export default HiddenMessageView;
import '@testing-library/jest-dom';
import { render, fireEvent } from '@closeio/backbone-testing-library';
import HiddenMessageModel from '../models/HiddenMessageModel';
import HiddenMessageView from './HiddenMessageView';
test('shows the children when the checkbox is checked', () => {
const testMessage = 'Test Message';
const testModel = new HiddenMessageModel({
message: testMessage,
});
const { queryByText, getByLabelText, getByText } = render(HiddenMessageView, {
model: testModel,
});
expect(queryByText(testMessage)).toBeNull();
fireEvent.click(getByLabelText(/show/i));
expect(getByText(testMessage)).toBeInTheDocument();
});
render
Parameters
View
- the first argument is the Backbone.View
Class to test, it will be
instantiated by the render functionoptions
- optional - the second argument is an options object with the following
parameters:
container
- optional - behaves like RTL's container
by default creates a div
and appends it to document.body
baseElement
- optional - behaves like RTL's baseElement
if container
is specified, then it defaults to that, otherwise this defaults to document.body
autoRender
- optional - this defaults to true
. Sometimes you may want to
assert on something in between your Backbone.View
's initialize
and render
methods, if
so you can pass false
here and call render
manually on the returned view
instance....options
- any other properties will be passed through as options
to the
Backbone.View
's constructor. For example, you could add el
if you wanted to manually
provide this to the view rather than have Backbone
auto create it. You'll also likely
often want to pass a model
.
render
Result
The render method returns an object that has a few properties:
...queries
- The most important feature of render is that the queries from DOM Testing Library
are automatically returned with their first argument bound to the baseElement
, which
defaults to document.body
view
- The Backbone
view instance itself.container
- behaves like RTL's container
returns either a div
autocreated for you, or the container
passed to render
. To get
the root element of your rendered element, use container.firstChild
or view.el
.baseElement
- behaves like RTL's baseElement
returns either document.body
or the baseElement
passed to `render.debug
- behaves like RTL's debug
this function is a shortcut for console.log(prettyDOM(baseElement))
.unmount
- calls remove
on the Backbone.View
instance and cleans up the container
element. Useful for testing what happens when your view is removed from the page.
By default, when RTL_SKIP_AUTO_CLEANUP
is false
, cleanup
is called in every afterEach
block which runs render
, which means you don't need to manually unmount your views if
you're not testing remove
. While it might seem odd to rely on a ENV var from another
library, our intention here is that this library is run in tandem with RTL and behaves
identically for porting components.
License
MIT © Close