When I create a new helper on Ember CLI, a test is created inside tests/unit/helpers. I would like to know how to test this helpers using the unit test?. I tried to find a documentation, but nothing helps. I need to test the function createArray in order to pass the test coverage to a 100%.
Now, this is my helper:
import Ember from 'ember';
export function createArray(array) {
return array;
}
export default Ember.Helper.helper(createArray);
This is my unit test: tests/unit/helpers/create-array-test.js
module('Unit | Helper | create array');
// Replace this with your real tests.
test('it works', function(assert) {
let result = createArray([42]);
assert.ok(result);
});
Hope someone can guide me.
What version of Ember CLI are you using? The blueprint should generate a test file with an import of the named export so you can use it directly.
What export function createArray does is create a named export named createArray. This means you can import the function directly and use it like you a normal function:
import { createArray } from 'app-name/helpers/create-array'
createArray(arrayOfArguments);
I modified #ykaragol's Twiddle to demonstrate how to do this in a test:
import { createArray } from 'app-name/helpers/create-array';
import { module, test } from 'qunit';
module('Unit | Helper | create array');
test('it works', function(assert) {
let result = createArray([42]);
assert.ok(result);
});
Replace app-name with the name of your application.
The code posted on twiddle helped me understand how to solve the helpers unit test. This is how I tested it, and it works like a charm.
test('Return the argument is passed', function(assert) {
assert.ok(createArray([8,4,5,6]));
assert.ok(createArray(['test1','test2','test3']));
});
Related
I am writing an Ember Addon that provides some services that are not exposed through the app/ folder.
// project Foo
// addon/services/foo.js
import Ember from 'ember';
export default Ember.Service.extend({})
The unit test that gets generated by Ember CLI uses moduleFor helper.
// tests/unit/services/foo.js
import { moduleFor, test } from 'ember-qunit';
moduleFor('service:foo', 'Unit | Service | foo', {
// Specify the other units that are required for this test.
// needs: ['service:foo']
});
// Replace this with your real tests.
test('it exists', function(assert) {
let service = this.subject();
assert.ok(service);
});
Problem is that since my FooService is not exposed through the app/ folder, moduleFor helper cannot find it using service:foo name.
What would be the best way to unit test my service here?
I can see three possibilities:
1) add tests/dummy/app/services/foo.js that exports FooService
// tests/dummy/app/services/foo.js
export { default } from 'foo/services/foo.js';
2) create initializers in the dummy app that registers service:foo
// tests/dummy/app/initializers/account-data.js
import FooService from 'foo/services/foo'
export function initialize(application) {
application.register('service:foo', FooService);
}
EDIT
turns out I can't do this. it's not that moduleFor helper is trying to find 'service:foo' but trying to register 'app/services/foo' as 'service:foo'. So registering 'service:foo' ahead of the time does not help.
3) don't use moduleFor helper.
EDIT
By this I meant something like what #Andy Pye's answer. But it would be nice to be able to use moduleFor helper... Especially for models since I need access to store.
EDIT
turns out it gets more complicated for models since I can't create them directly. So if I go with not using moduleFor helper, I need an instead of store object...
I've just had the same (or a very similar) issue. I've found that this seems to work:
// tests/unit/services/foo.js
import { module, test } from 'ember-qunit';
import FooService from 'Foo/services/foo';
module('Unit | Service | foo', {
// Specify the other units that are required for this test.
// needs: ['service:foo']
});
// Replace this with your real tests.
test('it exists', function (assert) {
let service = FooService.create();
assert.ok(service);
});
I'm trying to create a test for the following initializer:
import Ember from 'ember';
const { Inflector } = Ember;
export function initialize() {
Inflector.inflector.uncountable('settings');
Inflector.inflector.uncountable('feedback');
}
export default {
name: 'inflector',
initialize
};
Ember-cli generates the following test for an initializer:
import Ember from 'ember';
import InflectorInitializer from 'redirect/initializers/inflector';
import { module, test } from 'qunit';
let application;
module('Unit | Initializer | inflector', {
beforeEach() {
Ember.run(function() {
application = Ember.Application.create();
application.deferReadiness();
});
}
});
test('it works', function(assert) {
InflectorInitializer.initialize(application);
assert.ok(true);
});
As I understand it, a beforeEach() hook creates an application first, and then pauses it so the initializer test can run.
The test fails because Ember.Inflector in undefined when the initializer is called by the test.
How do I test custom inflector rules?
I'd like to have the following assertions:
assert.equal(inflector.singularize('settings'), 'settings');
assert.equal(inflector.pluralize('settings'), 'settings');
assert.equal(inflector.singularize('feedback'), 'feedback');
assert.equal(inflector.pluralize('feedback'), 'feedback');
assert.equal(inflector.rules.uncountable['settings'], true);
assert.equal(inflector.rules.uncountable['feedback'], true);
I'd be willing to configure inflector rules in a different way if this will make it testable.
I tried to create an application and remove deferReadiness to then see If I can put those assertions in the test. But even though Ember.Inflector is then defined, it doesn't contain my custom rules.
I'm installing the 'ember-moment' helper and then I'm using it in components. As soon as I do that, those components' tests break saying pretty much nothing:
not ok 120 PhantomJS 1.9 - StatusCardComponent: it renders
---
actual: >
null
message: >
Died on test #2 at http://localhost:7357/assets/test-support.js:2779
at test (http://localhost:7357/assets/test-support.js:1796)
at http://localhost:7357/assets/client.js:11190
at http://localhost:7357/assets/vendor.js:150
at tryFinally (http://localhost:7357/assets/vendor.js:30)
at http://localhost:7357/assets/vendor.js:156
at http://localhost:7357/assets/test-loader.js:29
at http://localhost:7357/assets/test-loader.js:21
at http://localhost:7357/assets/test-loader.js:40
at http://localhost:7357/assets/test-support.js:5545: Assertion Failed: A helper named 'moment' could not be found
Log: >
...
And here is the code of the test itself, it's just the auto generation:
import {
moduleForComponent,
test
} from 'ember-qunit';
moduleForComponent('event-card', {
// Specify the other units that are required for this test
// needs: ['component:foo', 'helper:bar']
});
test('it renders', function(assert) {
assert.expect(2);
// Creates the component instance
var component = this.subject();
assert.equal(component._state, 'preRender');
// Renders the component to the page
this.render();
assert.equal(component._state, 'inDOM');
});
I tried a bunch of ways of adding this helper to the test as a dependency like needs: ['helper:moment'] and adding its initializer signature to the moduleForComponent function's params, but nothing worked and I can't find any information about it. Help is much appreciated.
Edit: According to this PR, you should be able to specify { integration: true } to turn your existing unit test into an integration test, which eliminates the need for needs:.
moduleForComponent('post', { integration: true });
More background can be found here: https://github.com/rwjblue/ember-qunit/issues/108. Essentially, the integration flag disables the isolated container for the test, so that it has access to the app's resolver.
Note: Requires ember-qunit#0.2.11.
Old Answer: Take a look at this PR: https://github.com/switchfly/ember-test-helpers/pull/21 which adds moduleForIntegration. Here's the relavant bit:
This adds a new kind of test module that fills a gap in the current
set of possible tests. So far we have:
• unit tests that are good for testing algorithmic correctness in isolation.
• acceptance tests that are good for testing within a complete
application.
But we're missing the ability to integration test a unit smaller than
whole-application. This PR adds a new TestModuleForIntegration that
lets you drive an integration test with a template. I think this is
often a more appropriate way to test Ember Components than a unit
test, because interesting components tend to have rich dependence on
other components.
You can see it in use in liquid-fire tests:
/* global sinon */
import Ember from "ember";
import moduleForIntegration from "../../helpers/module-for-integration";
import { test } from "ember-qunit";
moduleForIntegration('Integration: liquid-if');
test('it should render', function(assert) {
this.set('person', 'Tom');
this.render(`
{{#liquid-if isReady}}
{{person}} is ready
{{else}}
{{person}} is not ready
{{/liquid-if}}
`); // }}`)
assert.equal(this.$().text().trim(), 'Tom is not ready');
this.set('person', 'Yehuda');
assert.equal(this.$().text().trim(), 'Yehuda is not ready');
this.set('isReady', true);
assert.equal(this.$().text().trim(), 'Yehuda is ready');
});
So this is what ended up working:
import {
moduleForComponent,
test
} from 'ember-qunit';
import Ember from 'ember';
import { initialize } from '../../../../../initializers/ember-moment';
moduleForComponent('event-card', {
// Specify the other units that are required for this test
// needs: ['helper:moment'],
setup: function (container) {
Ember.run(function () {
// these two arguments are not used
// but probably still good to pass them in
// in the event we leverage them in the future
initialize(container);
});
}
});
test('it renders', function (assert) {
assert.expect(2);
// Creates the component instance
var component = this.subject();
assert.equal(component._state, 'preRender');
// Renders the component to the page
this.render();
assert.equal(component._state, 'inDOM');
});
Do you see that line that is commented out that reads:
// needs: ['component:foo', 'helper:bar']
You need to uncomment it out and make it read:
needs: ['helper:moment']
That should help, if your moment helper is registered correctly
I'm using Pikaday to create an Ember Datepicker Component within an Ember CLI project. It seems to be impossible to test user interactions within the component test. Does anyone know how to do this?
For example I'm trying to test that the Pikaday widget is displayed when the input of the component is clicked. The test looks like this:
import { test, moduleForComponent } from 'ember-qunit';
moduleForComponent('datepicker-input');
test('is an input tag', function() {
equal('INPUT', this.$().prop('tagName'));
});
test('clicking the input opens the pikaday dialog', function() {
ok($('.pika-single').hasClass('is-hidden'));
click(this.$().find('input'));
ok(!$('.pika-single').hasClass('is-hidden'));
});
The second tests fails due to ReferenceError: click is not defined. I don't know what I'm doing wrong, as far as I can tell my tests do the same as the example on the Ember.js website: http://emberjs.com/guides/testing/testing-components/#toc_interacting-with-components-in-the-dom
So I'm guessing the problem could be also with Ember CLI. Any help is welcome, I'm open to suggestions how to test the user interactions of an component.
You need to add the component to the DOM.
test('clicking the input opens the pikaday dialog', function() {
$input = this.append();
ok($('.pika-single').hasClass('is-hidden'));
click('#your-input').then(function() {
ok(!$('.pika-single').hasClass('is-hidden'));
});
});
I ended up starting and destroying the app by hand. In addition I also teardown the component after every test by hand. This is necessary until a few upstream changes from the QUnit addon land in Ember CLI.
You can look at the complete test file on GitHub: https://github.com/edgycircle/ember-pikaday/blob/master/tests/unit/components/pikaday-input-test.js
I think you need to call App.setupForTesting, and in older versions of ember, additionally App.injectTestHelpers before the tests are run.
http://emberjs.com/guides/testing/integration/#toc_setup
You also need to call this.append to make the component show up in the DOM.
In what version of Ember was this problem? I've tested with the auto-generated component test almost identically on how I tested on an ember App on an Ember AddOn (ember 2.4.3).
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
moduleForComponent('image-item', 'Integration | Component | image item', {
integration: true
});
test('it renders an image with alt', function(assert) {
this.set('src', 'image.png');
this.set('alt', 'grandmother');
this.render(hbs`{{image-item src=src alt=alt}}`);
assert.equal(this.$('img').attr('src'), 'image.png');
assert.equal(this.$('img').attr('alt'), 'grandmother');
});
Can somebody point me to a resource on how to implement a test helper with ember-cli?
Or else a simple explanation?
I know the helpers go in the test/helpers directory, but how do you load them into the integration tests?
Thanks
The only way I found to do this is:
// tests/helpers/controller.js
import Ember from 'ember';
Ember.Test.registerHelper('controller', function (app, name) {
return app.__container__.lookup('controller:' + name);
});
then in my acceptance test:
// acceptance/index-test.js
import Ember from 'ember';
// import our helper (this might be done within helpers/start-app.js to always import all helpers)
import '../helpers/controller';
import startApp from '../helpers/start-app';
// your tests using the helper(s)
But there might be some better way of doing.