jasmine-react-helpers
Advanced tools
Comparing version 0.2.0 to 0.2.1
{ | ||
"name": "jasmine-react-helpers", | ||
"version": "0.2.0", | ||
"version": "0.2.1", | ||
"description": "a small suite of helper functions to make unit testing React.js components painless.", | ||
@@ -22,5 +22,5 @@ "main": "src/jasmine-react.js", | ||
"karma-react-jsx-preprocessor": "^0.1.1", | ||
"react": "^0.8.0", | ||
"react-tools": "^0.11.1" | ||
"react": "^0.12.1", | ||
"react-tools": "^0.12.1" | ||
} | ||
} |
@@ -31,6 +31,6 @@ *jasmine-react* is a small suite of helper functions to make unit testing React.js components painless. | ||
// jasmineReact wraps React.renderComponent, so you don't have to worry | ||
// jasmineReact wraps React.render, so you don't have to worry | ||
// about the async nature of when the actual DOM get's rendered, or selecting | ||
// where your component needs to get rendered (default is #jasmine_content) | ||
var myWorld = jasmineReact.renderComponent(<HelloWorld />); | ||
var myWorld = jasmineReact.render(<HelloWorld />); | ||
@@ -43,3 +43,3 @@ expect(myWorld.state.number).toBe(42); | ||
jasmineReact.renderComponent(HelloWorld()); | ||
jasmineReact.render(<HelloWorld />; | ||
@@ -82,3 +82,3 @@ // because we spy on the class and not the instance, we have to assert that the | ||
// This line won't throw the "I like to blow up" error because we've replaced the class with a test double! | ||
var avatar = jasmineReact.renderComponent(<Avatar />); | ||
var avatar = jasmineReact.render(<Avatar />); | ||
@@ -120,3 +120,3 @@ expect(avatar.refs.pic.props.username).toBe("Zuck") | ||
var avatar = jasmineReact.renderComponent(<Avatar />); | ||
var avatar = jasmineReact.render(<Avatar />); | ||
@@ -133,7 +133,7 @@ expect(jasmineReact.classPrototype(profileClassStub).rotate).not.toHaveBeenCalled(); | ||
## jasmineReact.renderComponent | ||
## jasmineReact.render | ||
`jasmineReact.renderComponent(component, [container], [callback]);` | ||
`jasmineReact.render(component, [container], [callback]);` | ||
When rendering a React component, this is a convenience function for `React.renderComponent`. | ||
When rendering a React component, this is a convenience function for `React.render`. | ||
@@ -145,10 +145,10 @@ It has a few helpful features: | ||
* the component will be automatically unmounted after the test is complete. | ||
NOTE: If you call React.renderComponent in a jasmine test and the component is not unmounted, that component | ||
NOTE: If you call React.render in a jasmine test and the component is not unmounted, that component | ||
will pollute any subsequent tests which try to render into that container. | ||
* the container argument is optional. By default it will be: `document.getElementById("jasmine_content"). If you | ||
want to override this behavior, look at the documentation for `jasmineReact.getDefaultContainer` | ||
* `React.renderComponent` will return before the rendering has occurred. `jasmineReact.renderComponent` will wait | ||
* `React.render` will return before the rendering has occurred. `jasmineReact.render` will wait | ||
until the async render has been performed. | ||
Just like `React.renderComponent`, this method will return the component instance. | ||
Just like `React.render`, this method will return the component instance. | ||
@@ -182,3 +182,3 @@ | ||
var myAvatar = jasmineReact.renderComponent(<Avatar />); | ||
var myAvatar = jasmineReact.render(<Avatar />); | ||
myAvatar.getWidth(); | ||
@@ -219,3 +219,3 @@ | ||
```js | ||
var myAvatar = jasmineReact.renderComponent(<Avatar />); | ||
var myAvatar = jasmineReact.render(<Avatar />); | ||
jasmineReact.unmountComponent(myAvatar); | ||
@@ -222,0 +222,0 @@ ``` |
@@ -8,3 +8,3 @@ var React = require('react'); | ||
var jasmineReact = { | ||
renderComponent: function(component, container, callback){ | ||
render: function(component, container, callback){ | ||
if(typeof container === "undefined"){ | ||
@@ -15,4 +15,4 @@ container = this.getDefaultContainer(); | ||
var comp = (typeof callback === "undefined") ? | ||
React.renderComponent(component, container) : | ||
React.renderComponent(component, container, callback); | ||
React.render(component, container) : | ||
React.render(component, container, callback); | ||
@@ -27,6 +27,13 @@ // keep track of the components we render, so we can unmount them later | ||
var klassProto = this.classPrototype(klass), | ||
original = klassProto[methodName], | ||
jasmineSpy = spyOn(klassProto, methodName); | ||
// keep track of the spies, so we can clean up the __reactAutoBindMap later | ||
spies.push(jasmineSpy); | ||
// (Jasmine 2.1) | ||
spies.push({ | ||
spy: jasmineSpy, | ||
baseObj: klassProto, | ||
methodName: methodName, | ||
originalValue: original | ||
}); | ||
@@ -51,3 +58,3 @@ // react.js will autobind `this` to the correct value and it caches that | ||
if(typeof componentConstructor === "undefined"){ | ||
throw("A component constructor could not be found for this class. Are you sure you passed in a the component definition for a React component?") | ||
throw("A component constructor could not be found for this class. Are you sure you passed in a the component definition for a React component?"); | ||
} | ||
@@ -127,2 +134,2 @@ | ||
module.exports = jasmineReact; | ||
module.exports = jasmineReact; |
@@ -1,3 +0,1 @@ | ||
/** @jsx React.DOM */ | ||
/* | ||
@@ -30,6 +28,6 @@ * The objective of this spec is to test all of the code samples in the official documentation. | ||
// jasmineReact wraps React.renderComponent, so you don't have to worry | ||
// jasmineReact wraps React.render, so you don't have to worry | ||
// about the async nature of when the actual DOM get's rendered, or selecting | ||
// where your component needs to get rendered (default is #jasmine_content) | ||
var myWorld = jasmineReact.renderComponent(<HelloWorld />); | ||
var myWorld = jasmineReact.render(<HelloWorld />); | ||
@@ -42,3 +40,3 @@ expect(myWorld.state.number).toBe(42); | ||
jasmineReact.renderComponent(HelloWorld()); | ||
jasmineReact.render(<HelloWorld />); | ||
@@ -75,5 +73,5 @@ // because we spy on the class and not the instance, we have to assert that the | ||
// This line won't throw the "I like to blow up" error because we've replaced the class with a test double! | ||
var avatar = jasmineReact.renderComponent(<Avatar />); | ||
var avatar = jasmineReact.render(<Avatar />); | ||
expect(avatar.refs.pic.props.username).toBe("Zuck") | ||
expect(avatar.refs.pic.props.username).toBe("Zuck"); | ||
}); | ||
@@ -109,3 +107,3 @@ | ||
var avatar = jasmineReact.renderComponent(<Avatar />); | ||
var avatar = jasmineReact.render(<Avatar />); | ||
@@ -120,2 +118,2 @@ expect(jasmineReact.classPrototype(profileClassStub).rotate).not.toHaveBeenCalled(); | ||
}); | ||
}); |
@@ -9,7 +9,7 @@ describe("jasmineReact", function(){ | ||
describe("renderComponent", function(){ | ||
var fooKlass; | ||
describe("render", function(){ | ||
var FooKlass; | ||
beforeEach(function(){ | ||
fooKlass = React.createClass({ | ||
FooKlass = React.createClass({ | ||
render: function(){ | ||
@@ -20,36 +20,36 @@ return React.DOM.div({}); | ||
spyOn(React, "renderComponent").andCallThrough(); | ||
spyOn(React, "render").andCallThrough(); | ||
}); | ||
it("should call React.renderComponent with the passed in component", function(){ | ||
jasmineReact.renderComponent(fooKlass({foo: "bar"}), document.getElementById("jasmine_content")); | ||
it("should call React.render with the passed in component", function(){ | ||
jasmineReact.render(<FooKlass foo="bar" />, document.getElementById("jasmine_content")); | ||
var renderComponentArgs = React.renderComponent.mostRecentCall.args[0]; | ||
var renderArgs = React.render.mostRecentCall.args[0]; | ||
expect(renderComponentArgs.props.foo).toBe("bar"); | ||
expect(renderArgs.props.foo).toBe("bar"); | ||
}); | ||
it("should call React.renderComponent with the passed in container", function(){ | ||
it("should call React.render with the passed in container", function(){ | ||
var container = document.getElementById("jasmine_content"); | ||
jasmineReact.renderComponent(fooKlass(), container); | ||
jasmineReact.render(<FooKlass />, container); | ||
expect(React.renderComponent).toHaveBeenCalledWith(jasmine.any(Object), container); | ||
expect(React.render).toHaveBeenCalledWith(jasmine.any(Object), container); | ||
}); | ||
it("should call React.renderComponent with #jasmine_content container if no container is passed in", function(){ | ||
jasmineReact.renderComponent(fooKlass()); | ||
it("should call React.render with #jasmine_content container if no container is passed in", function(){ | ||
jasmineReact.render(<FooKlass />); | ||
expect(React.renderComponent).toHaveBeenCalledWith(jasmine.any(Object), document.getElementById("jasmine_content")); | ||
expect(React.render).toHaveBeenCalledWith(jasmine.any(Object), document.getElementById("jasmine_content")); | ||
}); | ||
it("should call React.renderComponent with a callback if one is passed in", function(){ | ||
it("should call React.render with a callback if one is passed in", function(){ | ||
var fakeCallbackSpy = jasmine.createSpy("fakeCallback"); | ||
jasmineReact.renderComponent(fooKlass(), document.getElementById("jasmine_content"), fakeCallbackSpy); | ||
jasmineReact.render(<FooKlass />, document.getElementById("jasmine_content"), fakeCallbackSpy); | ||
expect(React.renderComponent).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Object), fakeCallbackSpy); | ||
expect(React.render).toHaveBeenCalledWith(jasmine.any(Object), jasmine.any(Object), fakeCallbackSpy); | ||
}); | ||
it("should return the return value of React.renderComponent", function(){ | ||
var returnValue = jasmineReact.renderComponent(fooKlass({baz: "bat"}), document.getElementById("jasmine_content")); | ||
it("should return the return value of React.render", function(){ | ||
var returnValue = jasmineReact.render(<FooKlass baz="bat" />, document.getElementById("jasmine_content")); | ||
@@ -60,5 +60,5 @@ expect(returnValue.props.baz).toBe("bat"); | ||
describe("renderComponent: test pollution", function(){ | ||
describe("render: test pollution", function(){ | ||
it("should not pollute a rendered component from one test into another test", function(){ | ||
var coolKlass = React.createClass({ | ||
var CoolKlass = React.createClass({ | ||
render: function(){ | ||
@@ -72,7 +72,7 @@ return React.DOM.div({ | ||
// lets pretend this is test #1 | ||
jasmineReact.renderComponent(coolKlass()); | ||
jasmineReact.render(<CoolKlass />); | ||
expect(document.getElementById("really-cool")).toBeDefined(); | ||
// this is the method in the afterEach which is needed to prevent test pollution for renderComponent | ||
// this is the method in the afterEach which is needed to prevent test pollution for render | ||
jasmineReact.unmountAllRenderedComponents(); | ||
@@ -86,6 +86,6 @@ | ||
describe("spyOnClass", function(){ | ||
var fooKlass; | ||
var FooKlass; | ||
beforeEach(function(){ | ||
fooKlass = React.createClass({ | ||
FooKlass = React.createClass({ | ||
render: function(){ | ||
@@ -102,5 +102,5 @@ return React.DOM.div({}); | ||
it("should allow a react class to have a function be spied on (when called externally)", function(){ | ||
jasmineReact.spyOnClass(fooKlass, "bar").andReturn("fake value"); | ||
jasmineReact.spyOnClass(FooKlass, "bar").andReturn("fake value"); | ||
var foo = jasmineReact.renderComponent(fooKlass()); | ||
var foo = jasmineReact.render(<FooKlass />); | ||
@@ -112,3 +112,3 @@ expect(foo.bar()).not.toBe("real value"); | ||
it("should allow a react class to have a function be spied on (when called internally in a lifecycle function)", function(){ | ||
var klassWithAnInitialState = React.createClass({ | ||
var KlassWithAnInitialState = React.createClass({ | ||
render: function(){ | ||
@@ -121,3 +121,3 @@ return React.DOM.div({}); | ||
initialBar: this.bar() | ||
} | ||
}; | ||
}, | ||
@@ -130,5 +130,5 @@ | ||
jasmineReact.spyOnClass(klassWithAnInitialState, "bar").andReturn("fake value"); | ||
jasmineReact.spyOnClass(KlassWithAnInitialState, "bar").andReturn("fake value"); | ||
var foo = jasmineReact.renderComponent(klassWithAnInitialState()); | ||
var foo = jasmineReact.render(<KlassWithAnInitialState />); | ||
@@ -140,3 +140,3 @@ expect(foo.state.initialBar).not.toBe("real value"); | ||
it("should allow a react class to have a function be spied on (when called inside the render function)", function(){ | ||
var klassWithARenderFunction = React.createClass({ | ||
var KlassWithARenderFunction = React.createClass({ | ||
render: function(){ | ||
@@ -153,5 +153,5 @@ return React.DOM.div({ | ||
jasmineReact.spyOnClass(klassWithARenderFunction, "bar").andReturn("fake-value"); | ||
jasmineReact.spyOnClass(KlassWithARenderFunction, "bar").andReturn("fake-value"); | ||
var foo = jasmineReact.renderComponent(klassWithARenderFunction()); | ||
var foo = jasmineReact.render(<KlassWithARenderFunction />); | ||
@@ -173,4 +173,4 @@ expect(foo.getDOMNode().className).not.toBe("real-value"); | ||
it("should return the spy as the return value", function(){ | ||
var mySpy = jasmineReact.spyOnClass(fooKlass, "bar"); | ||
var foo = jasmineReact.renderComponent(fooKlass()); | ||
var mySpy = jasmineReact.spyOnClass(FooKlass, "bar"); | ||
var foo = jasmineReact.render(<FooKlass />); | ||
@@ -183,7 +183,7 @@ expect(mySpy.callCount).toBe(0); | ||
}); | ||
it("should maintain regular jasmine spy behavior", function(){ | ||
jasmineReact.spyOnClass(fooKlass, "bar").andReturn(42); | ||
jasmineReact.spyOnClass(FooKlass, "bar").andReturn(42); | ||
var foo = jasmineReact.renderComponent(fooKlass()); | ||
var foo = jasmineReact.render(<FooKlass />); | ||
@@ -196,3 +196,3 @@ expect(foo.bar()).toBe(42); | ||
it("should not pollute a spied on function from one test into another test", function(){ | ||
var barKlass = React.createClass({ | ||
var BarKlass = React.createClass({ | ||
render: function(){ | ||
@@ -208,6 +208,6 @@ return React.DOM.div({}); | ||
// lets pretend this is test #1 | ||
jasmineReact.spyOnClass(barKlass, "bar").andCallFake(function(){ | ||
jasmineReact.spyOnClass(BarKlass, "bar").andCallFake(function(){ | ||
return "fake value"; | ||
}); | ||
var barOne = jasmineReact.renderComponent(barKlass()); | ||
var barOne = jasmineReact.render(<BarKlass />); | ||
expect(barOne.bar()).toBe("fake value"); | ||
@@ -220,3 +220,3 @@ | ||
// lets pretend this is test #2 | ||
var barTwo = jasmineReact.renderComponent(barKlass()); | ||
var barTwo = jasmineReact.render(<BarKlass />); | ||
expect(barTwo.bar()).toBe("real value"); | ||
@@ -241,10 +241,11 @@ }); | ||
it("should have a react class definition which can be rendered", function(){ | ||
jasmineReact.createStubComponent(namespace, "Profile"); | ||
// React is now doing this itself ... | ||
// it("should have a react class definition which can be rendered", function(){ | ||
// jasmineReact.createStubComponent(namespace, "Profile"); | ||
// | ||
// expect(function(){ | ||
// jasmineReact.render(namespace.Profile()); | ||
// }).not.toThrow(); | ||
// }); | ||
expect(function(){ | ||
jasmineReact.renderComponent(namespace.Profile()); | ||
}).not.toThrow(); | ||
}); | ||
it("should return the component stub", function(){ | ||
@@ -269,6 +270,8 @@ var returnValue = jasmineReact.createStubComponent(namespace, "Profile"); | ||
expect(typeof namespace.Profile).toBe("function"); | ||
expect(function(){ | ||
jasmineReact.renderComponent(namespace.Profile()); | ||
}).not.toThrow(); | ||
// React is now doing this itself ... | ||
// expect(function(){ | ||
// jasmineReact.render(namespace.Profile()); | ||
// }).not.toThrow(); | ||
// these are the methods in the afterEach which are needed to prevent test pollution for createStubComponent | ||
@@ -284,6 +287,6 @@ jasmineReact.resetComponentStubs(); | ||
var fooKlass; | ||
var FooKlass; | ||
beforeEach(function(){ | ||
fooKlass = React.createClass({ | ||
FooKlass = React.createClass({ | ||
render: function(){ | ||
@@ -299,3 +302,3 @@ return React.DOM.div({}); | ||
it("should return the prototype of the react class' component constructor", function(){ | ||
var proto = jasmineReact.classPrototype(fooKlass); | ||
var proto = jasmineReact.classPrototype(FooKlass); | ||
expect(proto.bar).toBeDefined(); | ||
@@ -306,3 +309,3 @@ expect(proto.baz).toBe("test"); | ||
it("should throw a friendly error if a component is passed in (instead of a component class definition)", function(){ | ||
var foo = jasmineReact.renderComponent(fooKlass()); | ||
var foo = jasmineReact.render(<FooKlass />); | ||
@@ -316,6 +319,6 @@ expect(function(){ | ||
describe("addMethodToClass", function(){ | ||
var fooKlass; | ||
var FooKlass; | ||
beforeEach(function(){ | ||
fooKlass = React.createClass({ | ||
FooKlass = React.createClass({ | ||
render: function(){ | ||
@@ -328,9 +331,9 @@ return React.DOM.div({}); | ||
it("should allow a method to be added to a react component class", function(){ | ||
var fooOne = jasmineReact.renderComponent(fooKlass()); | ||
var fooOne = jasmineReact.render(<FooKlass />); | ||
expect(fooOne.newMethod).toBeUndefined(); | ||
jasmineReact.addMethodToClass(fooKlass, "newMethod", function(){}); | ||
jasmineReact.addMethodToClass(FooKlass, "newMethod", function(){}); | ||
var fooTwo = jasmineReact.renderComponent(fooKlass()); | ||
var fooTwo = jasmineReact.render(<FooKlass />); | ||
@@ -341,7 +344,7 @@ expect(fooTwo.newMethod).toBeDefined(); | ||
it("should accept a method definition for the new method", function(){ | ||
jasmineReact.addMethodToClass(fooKlass, "newMethod", function(){ | ||
jasmineReact.addMethodToClass(FooKlass, "newMethod", function(){ | ||
return "I'm a stub for a real method!"; | ||
}); | ||
var foo = jasmineReact.renderComponent(fooKlass()); | ||
var foo = jasmineReact.render(<FooKlass />); | ||
@@ -352,5 +355,5 @@ expect(foo.newMethod()).toBe("I'm a stub for a real method!"); | ||
it("should default the method definition to a no-op", function(){ | ||
jasmineReact.addMethodToClass(fooKlass, "newMethod"); | ||
jasmineReact.addMethodToClass(FooKlass, "newMethod"); | ||
var foo = jasmineReact.renderComponent(fooKlass()); | ||
var foo = jasmineReact.render(<FooKlass />); | ||
@@ -361,5 +364,5 @@ expect(foo.newMethod()).toBeUndefined(); | ||
it("should return the react class", function(){ | ||
var returnValue = jasmineReact.addMethodToClass(fooKlass, "newMethod", function(){}); | ||
var returnValue = jasmineReact.addMethodToClass(FooKlass, "newMethod", function(){}); | ||
expect(returnValue).toEqual(fooKlass); | ||
expect(returnValue).toEqual(FooKlass); | ||
}); | ||
@@ -369,3 +372,3 @@ }); | ||
describe("unmountComponent", function(){ | ||
var componentWillUnmountSpy, barKlass; | ||
var componentWillUnmountSpy, BarKlass; | ||
@@ -375,3 +378,3 @@ beforeEach(function(){ | ||
barKlass = React.createClass({ | ||
BarKlass = React.createClass({ | ||
render: function(){ | ||
@@ -389,3 +392,3 @@ return React.DOM.div(); | ||
it("should unmount the component", function(){ | ||
var barComponent = jasmineReact.renderComponent(barKlass()); | ||
var barComponent = jasmineReact.render(<BarKlass />); | ||
expect(componentWillUnmountSpy.callCount).toBe(0); | ||
@@ -399,3 +402,3 @@ | ||
it("should return the return value of unmountComponentAtNode", function(){ | ||
var barComponent = jasmineReact.renderComponent(barKlass({cool: "town"})); | ||
var barComponent = jasmineReact.render(<BarKlass cool="town" />); | ||
@@ -411,3 +414,3 @@ var returnValue = jasmineReact.unmountComponent(barComponent); | ||
it("should not unmount the component", function(){ | ||
var barComponent = jasmineReact.renderComponent(barKlass()); | ||
var barComponent = jasmineReact.render(<BarKlass />); | ||
@@ -426,3 +429,3 @@ React.unmountComponentAtNode(barComponent.getDOMNode().parentNode); | ||
it("should return false", function(){ | ||
var barComponent = jasmineReact.renderComponent(barKlass()); | ||
var barComponent = jasmineReact.render(<BarKlass />); | ||
@@ -444,2 +447,2 @@ React.unmountComponentAtNode(barComponent.getDOMNode().parentNode); | ||
}); | ||
}); |
582
34570