UNPKG

react-injectables

Version:

Explicitly inject Components into any part of your React render tree.

140 lines (109 loc) 4.64 kB
/* eslint-disable react/no-multi-comp */ import React, { Component } from 'react'; import { expect } from 'chai'; import sinon from 'sinon'; import { mount } from 'enzyme'; describe(`Given the Injector interface`, () => { const Injectable = require(`../src/Injectable`).default; describe(`When creating an Injectable`, () => { function assertIsValidInjectable(injectableInstance) { const actual = typeof injectableInstance === `function` && !!injectableInstance.contextTypes && !!injectableInstance.contextTypes.registerInjectable && !!injectableInstance.contextTypes.removeInjectable; const expected = true; expect(actual).to.equal(expected, `Invalid Injectable created.`); } it(`It should allow use of a stateless component`, () => { const StatelessComponent = () => <div>bar</div>; const InjectableBob = Injectable(StatelessComponent); assertIsValidInjectable(InjectableBob); }); it(`It should allow use of an ES6 class based component`, () => { class ClassComponent extends Component { state = { bob: `baz` } render() { return <div>foo</div>; } } const InjectableBob = Injectable(ClassComponent); assertIsValidInjectable(InjectableBob); }); it(`It should allow use of a React.createClass based component`, () => { const CreateClassComponent = React.createClass({ // eslint-disable-line react/prefer-es6-class state: { foo: `bar` }, render() { return <div>foo</div>; } }); const InjectableBob = Injectable(CreateClassComponent); assertIsValidInjectable(InjectableBob); }); }); describe(`When using an Injectable Component`, () => { let InjectableComponentBob; let context; beforeEach(() => { InjectableComponentBob = Injectable(({ injections }) => <div>{injections}</div>); context = { registerInjectable: sinon.spy(), removeInjectable: sinon.spy() }; }); it(`It should have an "injectionId" static set`, () => { expect(InjectableComponentBob.injectionId) .to.match(/^injectionId_[\d]+$/); }); it(`It should not render anything when initially mounted`, () => { const mounted = mount(<InjectableComponentBob />, { context }); expect(mounted.html()).to.equal(`<div></div>`); }); it(`It should call the correct context items on mount`, () => { const mounted = mount(<InjectableComponentBob />, { context }); expect(context.registerInjectable.callCount).to.equal(1); expect(context.removeInjectable.callCount).to.equal(0); const { injectionId: actualInjectionId, injectableInstance: actualInjectableInstance, receive: actualReceive } = context.registerInjectable.args[0][0]; expect(actualInjectionId).to.equal(InjectableComponentBob.injectionId); expect(actualInjectableInstance).to.equal(mounted.instance()); expect(typeof actualReceive).to.equal(`function`); }); it(`It should call the correct context items on unmount`, () => { const mounted = mount(<InjectableComponentBob />, { context }); const actualInstance = mounted.instance(); mounted.unmount(); expect(context.registerInjectable.callCount).to.equal(1); expect(context.removeInjectable.callCount).to.equal(1); const { injectionId: actualInjectionId, injectableInstance: actualInjectableInstance } = context.registerInjectable.args[0][0]; expect(actualInjectionId).to.equal(InjectableComponentBob.injectionId); expect(actualInjectableInstance).to.equal(actualInstance); }); it(`It should render consumed injections`, () => { const mounted = mount(<InjectableComponentBob />, { context }); const injectionOne = <div>injection 1</div>; const injectionTwo = <div>injection 2</div>; mounted.instance().consume([ injectionOne, injectionTwo ]); expect(mounted.state(`injections`)).to.eql([injectionOne, injectionTwo]); expect(mounted.html()) .to.equal(`<div><div>injection 1</div><div>injection 2</div></div>`); }); it(`It should not render duplicate elements`, () => { const mounted = mount(<InjectableComponentBob />, { context }); const injectionOne = <div>injection 1</div>; mounted.instance().consume([injectionOne]); mounted.instance().consume([injectionOne]); expect(mounted.html()) .to.equal(`<div><div>injection 1</div></div>`); }); }); });