Ember cli mirage: using fixtures in acceptance test - ember.js

I am trying to use fixtures with my acceptance tests however its causing tests to fail due to duplicate data since fixtures are re-inserted in the mirage DB every test. Is there a way to get around this or remove the fixtures every test
setupApplicationTest(hooks);
setupMirage(hooks);
hooks.beforeEach(function() {
this.server.loadFixtures();
});

Where is this code that you're showing me above coming from?
In an acceptance test, Mirage automatically starts / stops the server from an initializer it bundles in its addon under addon/instance-initializers/ember-cli-mirage-autostart.js:
let server = startMirage(appInstance);
testContext.server = server;
// To ensure that the server is shut down when the application is
// destroyed, register and create a singleton object that shuts the server
// down in its willDestroy() hook.
appInstance.register('mirage:shutdown', MirageShutdown);
which calls:
willDestroy() {
let testContext = this.get('testContext');
testContext.server.shutdown();
delete testContext.server;
}
Ember starts and stops the app between every test which means that each acceptance test automatically starts with an empty database.
If you are outside the context of an acceptance test, you need to do the start stopping yourself.
// tests/integration/components/your-test.js
import { startMirage } from 'yourapp/initializers/ember-cli-mirage';
moduleForComponent('your-component', 'Integration | Component | your component', {
integration: true,
beforeEach() {
this.server = startMirage();
},
afterEach() {
this.server.shutdown();
}
});
Calling shutdown after each test is vital for clearing the data

Related

Assert inside of a stub/mock ember service during acceptance/integration tests

In unit tests for a service, I have been putting asserts inside of service stubs, which has come in rather handy.
unit-test.js
let fooServiceStub = Ember.Object.extend({
fooMethod(bar) {
this.assert.ok(bar, 'fooMethod called with bar');
}
});
...
test('blah', function(assert) {
assert.expect(1);
let stubFooService = fooServiceStub.create({ assert });
let fooService = this.subject({
fooService: stubFooService
});
fooService.fooMethod('data');
});
Is an assert inside of a stub service possible for an acceptance/integration test?
The issue that I am running into is that for acceptance/integration tests, the way the service is injected is different from unit tests.
acceptance-test.js
let fooServiceStub = Ember.Service.extend({
fooMethod(bar) {
return 'baz';
}
});
....
beforeEach: function () {
this.application.register('service:mockFooService', fooServiceStub);
this.application.inject('controller', 'fooService', 'service:mockFooService');
}
I have not found a way to pass in the 'assert' object into such a stub.
To me, this is desirable to do during an acceptance test. The service goes off and does stuff that would be rather complicated to mock in the acceptance test, and I don't want to re-test my service. I just want to confirm the expected service calls were triggered.
You can just do something like this in your test:
this.set('fooService.FooMethod', bar => assert.ok(bar, 'bla'));

dangerouslyRenderMarkup(...): Cannot render markup in a worker thread [duplicate]

React Tests Fails after set State causes second render
Up until now testing has been going well with JSDOM and Mocha. So far have not had to test any components that change their state. I found my first issue testing a component that changes it's state.
The Error
1) Reduced Test Case - #current Tests that Fail when Component changes state and renders "before each" hook:
Error: Invariant Violation: dangerouslyRenderMarkup(...): Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use React.renderToString for server rendering.
at Context.<anonymous> (test/react-reflux/parts/Reduced-spec.js:47:32)
The Component : Reduced.js
var React = require('react');
var Reduced = React.createClass({
getInitialState() {
console.log("start off with editing as false");
return {editing: false};
},
edit() {
console.log("Setting State to Edit");
this.setState({editing: true});
},
render() {
console.log("Rendering");
return (
<span onClick={this.edit}>
{(this.state.editing) ? "Editing" : "Click To Edit"}
</span>
);
}
});
module.exports = Reduced;
The Tests : 1-pass, 1-fail
var React, TestUtils, jsdom, Reduced, expect;
describe('Reduced Test Case', function () {
before(function () {
jsdom = require('jsdom');
global.document = jsdom.jsdom('<!doctype html><html><body></body></html>');
global.window = global.document.parentWindow;
React = require('react/addons');
TestUtils = React.addons.TestUtils;
Reduced = require('./Reduced');
expect = require('chai').expect;
this.component = TestUtils.renderIntoDocument(
<Reduced />
);
var root = TestUtils.findRenderedDOMComponentWithTag(this.component, 'span');
this.el = root.getDOMNode();
});
describe("Tests Pass without simulate", function () {
it("Root Element Reads 'Click To Edit'", function () {
expect(this.el.innerHTML).to.equal('Click To Edit');
});
});
describe("Tests that Fail when Component changes state and renders", function () {
beforeEach(function () {
//
// Simulate invokes edit, invokes set state, invokes render, then error occures
//
TestUtils.Simulate.click(this.el);
});
it("Root Element Reads 'Editing'", function () {
expect(this.el.innerHTML).to.equal('Editing');
});
});
});
The Results
> mocha --compilers js:babel/register
Reduced Test Case - #current
start off with editing as false
Rendering
Tests Pass without simulate
✓ Root Element Reads 'Click To Edit'
Tests that Fail when Component changes state and renders
Setting State to Edit
Rendering
1) "before each" hook
1 passing (379ms)
1 failing
1) Reduced Test Case Tests that Fail when Component changes state and renders "before each" hook:
Error: Invariant Violation: dangerouslyRenderMarkup(...): Cannot render markup in a worker thread. Make sure `window` and `document` are available globally before requiring React when unit testing or use React.renderToString for server rendering.
at Context.<anonymous> (test/Reduced-spec.js:47:32)
I've been going crazy
Everything is loaded after global.window and global.document
The Simulate Event invokes edit(), then render() before error
All React Mocha JSDOM tests have been working well until this state change issue
Please help ???
The setup JSDOM setup was missing global.navigator.
global.navigator = {
userAgent: 'node.js'
};
Insert your global object modifying(passing window and document objects to global) before React is required.
Because React creates its ExecutionEnvironment object while required and don't modify it while works.

How to successfully instantiate a db model in a Sails test

I have been following the Sails.js documentation for testing, here:
http://sailsjs.org/documentation/concepts/testing
I have successfully been able to implement Controller tests that
hit different paths of my app, and check the responses of different Express requests.
My trouble is knowing A) How to instantiate a Model, specifically from my User model B) How I can guarantee that the model is successfully created.
I currently have a test in which, in a before hook, I create new user with all the required attributes:
before(function(){
User.create({firstName:"Bob", lastName: "Balaban", password:"12345", email:"bob#bob.com"})
});
The problem is that, I do not know how to verify if this record has been added to my tests database, or if a validation error or some other error is thrown upon the call to create.
NOTE: I ask this, because a test which is dependent upon the before() hook successfully functioning fails, and the only reason it could possible fail is if the User wasn't actually added to the db
You need to wait for the User to be created in before by using the done callback function argument, and calling it after you're done with setting up the test environment. Also, you're not lifting sails here for some reason despite the docs urging you to do so. I'd also recommend using a test database instead of your normal database so your test data is independent of your production / development data.
Example code below. The addition of done and the exec callback are probably the most vital parts.
var Sails = require('sails'), sails;
// ...
before(function(done) {
// Increase the Mocha timeout so that Sails has enough time to lift.
this.timeout(10000);
Sails.lift({
// If you want to use a different DB for testing, uncomment these and replace with your own DB info.
/*connections: {
// Replace the following with whatever suits you.
testMysql: {
adapter : 'sails-mysql',
host : 'localhost',
port : 3306,
user : 'mySQLUser',
password : 'MyAwesomePassword',
database : 'testDB'
}
},
models: {
connection: 'testMysql',
migrate: 'drop'
}
*/
}, function(err, server) {
sails = server;
if (err) return done(err);
User.create({firstName:"Bob", lastName: "Balaban", password:"12345", email:"bob#bob.com"})
.exec(function(err, createdUser) {
if (err) {
console.log("Failed to create user! Error below:");
console.log(err);
}
else {
console.log("User created successfully:");
console.log(user);
}
done(err, sails);
})
});
});

Ember-cli unit test using ember-cli-simple-auth

I'm trying to write a unit test for a controller that uses simple-auth authentication in an ajax call. Assertion tests work great but the session property does not appear to be defined in the unit test module scope.
Example action in controller:
authenticate() {
let credentials = this.getProperties('identification', 'password');
this.get('session').authenticate('simple-auth-authenticator:token', credentials)
.then(() => {
this.transitionToRoute('index');
}, (error) => {
this.set('errorMessage', error.error);
});
}
Example test:
it('should not authenticate', function () {
let controller = this.subject();
controller.send('authenticate');
expect(controller.get('errorMessage')).to.equal("Invalid email/password combination");
});
Session is undefined error message:
TypeError: Cannot read property 'authenticate' of undefined
at authenticate (http://localhost:7357/assets/app.js:587:28)
at mixin.Mixin.create.send (http://localhost:7357/assets/vendor.js:37164:54)
at Context.<anonymous> (http://localhost:7357/assets/app.js:2002:18)
at Context.wrapper (http://localhost:7357/assets/test-support.js:1756:27)
at invoke (http://localhost:7357/assets/test-support.js:13772:21)
at Context.suite.on.context.it.context.specify.method (http://localhost:7357/assets/test-support.js:13837:13)
at Test.require.register.Runnable.run (http://localhost:7357/assets/test-support.js:7064:15)
at Runner.require.register.Runner.runTest (http://localhost:7357/assets/test-support.js:7493:10)
at http://localhost:7357/assets/test-support.js:7571:12
at next (http://localhost:7357/assets/test-support.js:7418:14)
In unit tests you don't have a running application so injections etc. that happen in initializers aren't run. The best way to make sure the session exists in the controller would be to stub it which would also make it easy to make sure it behaves as you want it to behave in your test.
The alternative would be to turn the unit test into an acceptance test - in that case you have an initialized app that the test runs with and the session will be available in the controller already.

how does timeout work in angular tests running in karma

I love using console log for feedback perhaps too much, and sometimes I run into code that as convention we've added $timeout in the directive/service/controller, sometimes as long as 500 ms, and now the problem is during unit test, I noticed only console.logs directly under the it constructor gets sent out to karma and output to the screen.
wrapped console logs under timeout or rather wrapped assertions under $timeout do not yield any result as if ignored, what's the solution to timeouts?
In your unit tests, you load ngMock, which overwrites the orignal $timeout with its mock. Mock $timeout doesn't work like the real JavaScript timeout. To get it to call the code that's inside it, you have to do $timeout.flush() from your unit test.
If $timeout worked like the real timeout, you would've had to write asynchronous unit-tests for all functions that use $timeout.
Here's an example of a simplified function that uses $timeout and how I test it:
gaApi.getReport = function() {
report = $q.defer()
$timeout(function() {
$http({method: 'GET', url: 'https://www.googleapis.com/analytics/v3/data/ga'})
.success(function(body) {
report.resolve(body)
})
}, 300)
return report.promise
}
A unit test:
describe('getReport', function() {
it('should return report data from Google Analytics', function() {
gaApi.getReport().then(function(body) {
expect(body.kind).toBe('analytics#gaData')
})
$timeout.flush()
$httpBackend.flush()
})
})