diff --git a/tests/instance-binded-method.js b/tests/instance-binded-method.js new file mode 100644 index 0000000..5ce0c2a --- /dev/null +++ b/tests/instance-binded-method.js @@ -0,0 +1,158 @@ +import React, { Component } from 'react'; +import createShallowRenderer from './helpers/createShallowRenderer'; +import expect from 'expect'; +import { createProxy } from '../src'; + +const fixtures = { + modern: { + Counter1x: class Counter1x extends Component { + constructor(props) { + super(props); + this.state = { counter: 0 }; + } + + increment = () => { + this.setState({ + counter: this.state.counter + 1 + }); + } + + render() { + return {this.state.counter}; + } + }, + + Counter10x: class Counter10x extends Component { + constructor(props) { + super(props); + this.state = { counter: 0 }; + } + + increment = () => { + this.setState({ + counter: this.state.counter + 10 + }); + } + + render() { + return {this.state.counter}; + } + }, + + Counter100x: class Counter100x extends Component { + constructor(props) { + super(props); + this.state = { counter: 0 }; + } + + increment = () => { + this.setState({ + counter: this.state.counter + 100 + }); + } + + render() { + return {this.state.counter}; + } + }, + + CounterWithoutIncrementMethod: class CounterWithoutIncrementMethod extends Component { + constructor(props) { + super(props); + this.state = { counter: 0 }; + } + + render() { + return {this.state.counter}; + } + } + } +}; + +describe('instance binded method', () => { + let renderer; + let warnSpy; + + beforeEach(() => { + renderer = createShallowRenderer(); + warnSpy = expect.spyOn(console, 'warn').andCallThrough(); + }); + + afterEach(() => { + warnSpy.destroy(); + expect(warnSpy.calls.length).toBe(0); + }); + + Object.keys(fixtures).forEach(type => { + describe(type, () => { + const { Counter1x, Counter10x, Counter100x, CounterWithoutIncrementMethod } = fixtures[type]; + + it('gets added', () => { + const proxy = createProxy(CounterWithoutIncrementMethod); + const CounterProxy = proxy.get(); + const instance = renderer.render(); + expect(renderer.getRenderOutput().props.children).toEqual(0); + + proxy.update(Counter1x); + instance.increment(); + expect(renderer.getRenderOutput().props.children).toEqual(1); + }); + + it('gets replaced', () => { + const proxy = createProxy(Counter1x); + const CounterProxy = proxy.get(); + const instance = renderer.render(); + expect(renderer.getRenderOutput().props.children).toEqual(0); + instance.increment(); + expect(renderer.getRenderOutput().props.children).toEqual(1); + + proxy.update(Counter10x); + instance.increment(); + renderer.render(); + expect(renderer.getRenderOutput().props.children).toEqual(11); + + proxy.update(Counter100x); + instance.increment(); + renderer.render(); + expect(renderer.getRenderOutput().props.children).toEqual(111); + }); + + /** + * It is important to make deleted methods no-ops + * so they don't crash if setTimeout-d or setInterval-d. + */ + it('is detached and acts as a no-op if not reassigned and deleted', () => { + const proxy = createProxy(Counter1x); + const CounterProxy = proxy.get(); + const instance = renderer.render(); + expect(renderer.getRenderOutput().props.children).toEqual(0); + instance.increment(); + const savedIncrement = instance.increment; + expect(renderer.getRenderOutput().props.children).toEqual(1); + + proxy.update(CounterWithoutIncrementMethod); + expect(instance.increment).toEqual(undefined); + savedIncrement.call(instance); + renderer.render(); + expect(renderer.getRenderOutput().props.children).toEqual(1); + }); + + it('is attached and acts as a no-op if reassigned and deleted', () => { + const proxy = createProxy(Counter1x); + const CounterProxy = proxy.get(); + const instance = renderer.render(); + + instance.increment = instance.increment.bind(instance); + + expect(renderer.getRenderOutput().props.children).toEqual(0); + instance.increment(); + expect(renderer.getRenderOutput().props.children).toEqual(1); + + proxy.update(CounterWithoutIncrementMethod); + instance.increment(); + renderer.render(); + expect(renderer.getRenderOutput().props.children).toEqual(1); + }); + }); + }); +}); \ No newline at end of file