test
, with two directories; in the lib
folder, the scripts to run the tests and the spec
folder, in which the tests themselves are located:tube tracker / App── app / Public──public / Test── test / Lib── lib / │ └── jasmine-2.0.0 / Spec── spec / Common ├── common / │ ├── component / │ ├── bundle.js Suite └── suite.js Spec── SpecRunner.html
suite.js
file and used it as an entry point for Browserify: $ browserify -e test/spec/suite.js -t reactify -o test/spec/bundle.js
Note: I switched from using Bower to NPM React distribution. In the Bower version of React, utilities for testing and other add-ons come with the library core, which means that the kernel can be turned on twice in the test environment. This causes conflicts between components declared in different packages. Using the NPM distribution allows Browserify to build each package with only the dependencies it needs, avoiding duplication.
React.addons.TestUtils
namespace contains methods for simulating events, sampling by components, and testing their types.renderIntoDocument
method that can render components into an anonymous DOM node, but for some tests, it still remains necessary to specify a container, for example, to capture events or test a component’s life cycle when it is destroyed: describe("A component", function() { var instance; var container = document.createElement("div"); afterEach(function() { if (instance && instance.isMounted()) { // Only components with a parent will be unmounted React.unmountComponentAtNode(instance.getDOMNode().parent); } }); describe("rendered without a container reference", function() { beforeEach(function() { // This component does not use any lifecycle methods or broadcast // events so it does not require rendering to the DOM to be tested. instance = TestUtils.renderIntoDocument(<ComponentAlpha title="Hello World" />); }); it("should render a heading with the given text", function() { // TestUtils provide methods to filter the rendered DOM so that // individual components may be inspected easily. var heading = TestUtils.findRenderedDOMComponentWithTag(instance, "h1"); expect(heading.getDOMNode().textContent).toBe("Hello World"); }); }); describe("with a container reference required", function() { beforeEach(function() { // This component broadcasts events and has lifecycle methods // so it should be rendered into an accessible container. instance = React.renderComponent(<ComponentBeta />, container); this.eventSpy = jasmine.createSpy(); container.addEventListener("broadcast", this.eventSpy, false); }); afterEach(function() { container.removeEventListener("broadcast", this.eventSpy, false); }); it("should broadcast with data when component is clicked", function() { // TestUtils can simulate events TestUtils.Simulate.click(instance.getDOMNode()); expect(this.eventSpy).toHaveBeenCalledWith("some", "data"); }); }); });
tube-tracker.js
contains the network.js
and predictions.js
dependencies: /** @jsx React.DOM */ var React = require("react"); var Predictions = require("./predictions"); var Network = require("./network"); var TubeTracker = React.createClass({ render: function() { return ( <div className="layout"> <div className="layout__sidebar"> <Network networkData={this.props.networkData} /> </div> <div className="layout__content"> <Predictions line={this.state.line} station={this.state.station} networkData={this.props.networkData} /> </div> </div> ); } }); module.exports = TubeTracker;
$ npm install --save-dev rewireify $ browserify -e test/spec/suite.js -t reactify -t rewireify -o test/spec/bundle.js
__get__
and __set__
methods into each module so that their internal properties can be accessed from the outside. Module dependencies can now be replaced with stubs: /** @jsx React.DOM */ var React = require("react/addons"); var TubeTracker = require("../../../app/component/tube-tracker"); var stubComponent = require("../../lib/stub/component"); describe("Tube Tracker", function() { var TestUtils = React.addons.TestUtils; beforeEach(function() { this.original = { network: TubeTracker.__get__("Network"), predictions: TubeTracker.__get__("Predictions") }; this.stubbed ={ network: stubComponent(), predictions: stubComponent() }; TubeTracker.__set__({ Network: this.stubbed.network, Predictions: this.stubbed.predictions }); }); afterEach(function() { TubeTracker.__set__({ Network: this.original.network, Predictions: this.original.predictions }); }); });
mockComponent
method that allows you to change the output of a passed component, but that’s basically all that it can do. In fact, it is sometimes more convenient to replace whole components, especially for asynchronous tests.Jest , the newly created Facebook team wrapper for Jasmine, is an alternative way to replace CommonJS dependencies. Documentation on using Jest with React is available here .
Predictions
component will always show a Message
instance before displaying the DepartureBoard
. The inability to trace (spy) or replace (stub) methods of a component's life cycle, such as componentDidMount
or componentWillUnmount
, is a problem, since you cannot find out when a component is created or destroyed. /** @jsx React.DOM */ var React = require("react"); module.exports = function stub(mount, unmount) { var mixins = []; if (mount) { mixins.push({ componentDidMount: function() { mount.call(this); } }); } if (unmount) { mixins.push({ componentWillUnmount: function() { unmount.call(this); } }); } return React.createClass({ mixins: mixins, render: function() { return <div />; } }); };
Source: https://habr.com/ru/post/229987/
All Articles