Testing React/Redux components and containers using <Provider /> - unit-testing

I am writing react container components at the moment that use the connect() wrapper/decorator. I'm interested in providing a fake store to my container when I test using mocha and expect / should. After reading the documentation I should export a flat/simple version of my component and then in the test use <Provider ...>. Below is a link to the documentation.
https://github.com/reactjs/redux/blob/master/docs/recipes/WritingTests.md
However I am struggling to find an example/guideline on actually implementing this. I understand the documentation might omit it as its obvious but I am lost trying to hook up my tests.

I have used redux-mock-store before and using Provider around the connected component to test rendering (I used enzyme) and interactions.
To test mapStateToProps:
create mock store with initial state
render component
assert expectations against the component
To test mapDispatchToProps:
create mock store with initial state
render component
trigger action in component
assert expectation against the mock store

Related

mocking a class used by a Gradle plugin when testing

I'm writing a Gradle plugin that interacts with an external HTTP API. This interaction is handled by a single class (let's call it ApiClient). I'm writing some high-level tests that use Gradle TestKit to simulate an entire build that uses the plugin, but I obviously don't want them to actually hit the API. Instead, I'd like to mock ApiClient and check that its methods have been called with the appropriate arguments, but I'm not sure how to actually inject the mocked version into the plugin. The plugin is instantiated somewhere deep within Gradle, and gets applied to the project being executed using its void apply(Project project) method, so there doesn't appear to be a way to inject a MockApiClient object.
Perhaps one way is to manually instantiate a Project, apply() the plugin to it (at which point, I can inject the mocked object because I have control over plugin instantiation), and then programmatically execute a task on the project, but how can I do that? I've read the Gradle API documentation and haven't seen an obvious way.
A worst-case solution will be to pass in a debug flag through the plugin extension configuration, which the plugin will then use to determine whether it should use the real ApiClient or a mock (which would print some easily grep-able messages to the STDOUT). This isn't ideal, though, since it's more fuzzy than checking the arguments actually passed to the ApiClient methods.
Perhaps you could split your plugin into a few different plugins
my-plugin-common - All the common stuff
my-plugin-real-services - Adds the "real" services to the model (eg RealApiClient)
my-plugin-mock-services - Adds "mock" services to the model (eg MockApiClient)
my-plugin - Applies my-plugin-real-services and my-plugin-common
my-plugin-mock - Applies my-plugin-mock-services and my-plugin-common
In the real world, people will only ever apply: 'my-plugin'
For testing you could apply: 'my-plugin-mock'

React Application Unit Testing

I am currently testing a React app using Selenium for Functional Testing. Selenium is used to launch the app on the browser, and simulate user actions and keep asserting/verifying at each step.
However it gets very tedious to debug these tests as the UI automation is heavy as it has to actually launch the browser , wait for pages to load (which at times is a pain given the unstable environments).
I read about some frameworks like chai which are very lightweight and very fast since I do not have to wait for the pages to load.
On similar lines , can anyone suggest me ways to do the complete functional testing of this application where I can bypass the UI actions (as done by Selenium) , for eg. instead of making selenium to go around clicking and simulation user actions on the UI, is there any way we can load a react component and try to simulate certain user actions through the code and then do the functional verification from the DB and also have data providers for my test . For eg - I have a set of data to be passed to my test function , and this test will run for all the set of data and keep asserting respectively.
Will something like unit testing/white box testing work ?
Will testing frameworks like chai help me with this requirement ?
Do suggest me any other approach if you know.
Ok, so this is the testing stack I have used on my projects.
Karma is an example of a test runner
Mocha is an example of a testing framework
Chai is an example of an assertion library
Sinon is an example of a testing plugin
Enzyme is an example for element selection. (Similar to Jquery)
Karma: Test Runner
Karma is a type of test runner which creates a fake server, and then spins up tests in various browsers using data derived from that fake server. Karma is only a test runner, and requires a testing framework such as Mocha to plug into it in order to actually run tests.
I used webpack + karma.conf.js file. to setup the Karma ecosystem. You can setup a command to watch the test cases run in parellel while coding.
Mocha: Testing Framework
The following file uses Mocha as a testing framework, and Chai as an assertion library:
describe('the todo.App', function() {
context('the todo object', function(){
it('should have all the necessary methods', function(){
var msg = "method should exist";
expect(todo.util.trimTodoName, msg).to.exist;
expect(todo.util.isValidTodoName, msg).to.exist;
expect(todo.util.getUniqueId, msg).to.exist;
});
});
});
Distinguish Between Mocha and Chai
We can distinguish between framework (Mocha) methods and assertion library (Chai) methods by looking at the contents of the it block. Methods outside the it block are generally derived from the testing framework. Everything within the it block is code coming from the assertion library. beforeEach, describe, context, it, are all methods extending from Mocha. expect, equal, and exist, are all methods extending from Chai.
afterEach(function() {
$httpBackend.verifyNoOutstandingExpectation();
$httpBackend.verifyNoOutstandingRequest();
$window.localStorage.removeItem('com.shortly');
});
it('should have a signup method', function() {
expect($scope.signup).to.be.a('function');
});
All the methods concerned with the testing framework are occurring outside the it block, and all methods concerned with the assertion library are occurring inside the it block. Therefore we can conclude that anything occurring inside the it block is indeed occurring on a lower level of abstraction than the testing framework.
Or in terms of our classification schema, everything occurring inside the it blocks is either part of an assertion library or a part of a testing plugin. The notion that anything inside the it block is occurring on a lower level of abstraction than the testing framework is only a heuristic, that is- it is merely a rule of thumb.
Sinon: Testing Plugin
Sinon is a plugin which hooks into Chai and gives us the ability to perform a more diverse set of tests. Through the Sinon plugin we can create mocks, stubs, and fake servers:
describe('API integration', function(){
var server, setupStub, JSONresponse;
beforeEach(function() {
setupStub = sinon.stub(todo, 'setup');
server = sinon.fakeServer.create();
});
it('todo.setup receives an array of todos when todo.init is called', function () {
});
afterEach(function() {
server.restore();
setupStub.restore();
});
});
Sinon has a bunch of cool features that allow you to really get into the nooks and crannies of your source code and see what is really going on under the hood.
You could use the spy function for event handlers as well
Think this should provide a direction.
Source

Using setTimeout() in React and Testing it

I realized that I have been using setTimeout() in my project -maybe- more than I should, I did a quick research and scroll through some open source react projects on Github and decided I should ask about it.
I use setTimeout mostly for changing the classname or adding styles to animate the DOM objects also using CSS transition, one point I thought it will be hard to write unit testing with this many setTimeout.
Since I came from using AngularJS, there is a $timeout service which has the same functionality with setTimeout, but in testing you can flush the timeout like $timeout.flush() and the timeout ends instantly.
My questions;
Is there an alternative testable way that I can use instead setTimeout (logicly or programaticly)?
Is there any builtin testable function in React does the same thing with setTimeout?
Is there any react addons I can use for "flushable" timeout?
Keep in mind I'm fairly new at reactjs and haven't write any unit test on it yet.
It depends what you are using. There's a sinonjs fake timers (http://sinonjs.org/) and Jest also has this functionality (with an example): https://facebook.github.io/jest/docs/timer-mocks.html
Cheers,
Mariusz

Sending actions to a component with Ember.js 1.13

I have an audio-player Ember.js component which I'd like to send events to from anywhere:
this.get('audioPlayer').send('play');
To get access to the component, I set the component as a property on itself which exposes it to the controller (link).
Working example Ember 1.12: http://emberjs.jsbin.com/wokelikice/1/edit
Failing example Ember 1.13: http://jsbin.com/yaporapuwu/2/edit
This stopped working in Ember 1.13-beta and I thought I must be doing it wrong. Data down, actions up and all.
How would you architect an application with a global audio-player?
And how would you send actions on a component? (or is there a better way?)
I managed to get it working in 1.13 like so: http://jsbin.com/serunaxozi/1/edit
The only change is modifying the _register method as follows:
_register: function() {
this.get('attrs.register-as.update')(this);
}.on('init')
1.13 is making changes to the way components reference attributes. Attributes on the components are accessed through the attrs object to differentiate them from component variables. They also have value and update properties to make due for implicit one-way binding with two-way binding via the mut keyword.
Remember this is still work-in-progress, so right now we need to manually get the update method from the attribute and invoke it, but I'd imagine in future this will be done using a setter as follows:
this.set('attrs.register-as', this);
Also bear in mind that eventually components will be used with angle-brackets, and you would need to specifically say that an attribute is a two-way binding for Ember to generate that update method:
<audio-player title="Michael Jackson" test={{test}} register-as={{mut audioPlayer}} />
This is still a little buggy at the moment (using the angle-bracket syntax, attrs is not available in the method which is run with on('init')).
-- Edit--
Attributes will not be available inside init in the future and will instead have another hook didInitAttrs. See https://github.com/emberjs/ember.js/issues/11200.

Headless testing Ember application with guard and jasmine

I'm trying to use jasmine and guard to test an ember based frontend for my rails 3.2 application. For this, I use jasminerice and guard-jasmine, phantomjs. The setup was very easy and simple and I can run some sample specs. When it comes to play with ember, things go mad. I have the spec below that test a video reader class. It should set videoHeight and videoWitdh property with the value of the corresponding video DOM element when calling loadVideo method.
When I run jasmine on my browser the test pass, but when I run it with guard and phantomjs, it fails. I got "Expect undefined to equal 640". It seems that my DOM element is not taking into account when the test run on phantomjs.
describe "VideoReader", ->
it "loads video from video DOM element", ->
videoDOM = Ember.$("<video width='640' height='480'><source src='/test.mp4'></source></video>")[0];
player = Topper.VideoReader.create();
player.loadVideo(videoDOM);
videoHeight = player.get('videoHeight');
videoWidth = player.get('videoWidth');
expect(videoHeight).toEqual(480);
expect(videoWidth).toEqual(640);
Is my spec correctly written ?
You should read the blog post about Testing in Ember.js.
I don't know what your Topper.VideoReader looks like but I guess your problem has to do with manipulating something on the DOM and not giving Ember.js a chance to propagate those changes. In your tests you should wrap your calls which interact with bindings or are manipulating the DOM in an Ember.run(function(){...}) call, as seen in the tests, for example child_views_test.js.
A summary from the discussion below:
If code you want to test interacts with the DOM, wrap it in an Ember.run call.
If you want to test for events which are fired in your code and you don't have control when exactly they are fired, use the asynchronous test features in the testing framework, like QUnit's asyncTest