Ember-CLI tests can't include modules from 'app' directory - ember.js

I am trying to include a module in my app from one of the tests. Is it even possible to do that? I am only able to include a module in the 'tests' directory.
I keep getting the infamous "Could not find module" error.
http://localhost:4200/assets/test-support.js:5578:16: Could not find module d3graph/app/controllers/index imported from d3graph/tests/unit/utils/graph-helper-test
This is my test code:
import { moduleFor, test } from 'ember-qunit';
import Ember from 'ember';
import helper from '../../../app/anything/anywhere'; // <- THIS LINE FAILS
moduleFor('util:graph-helper', 'Graph Helper', {
beforeEach: () => initialize()
});
function initialize() { /* something */ };
test('test desc', function(assert) {
var testObj = this.subject();
// test logic follows
});
I did try various modifications of the path to the module, including absolute path from root, I even tried including via 'require()', but alas without success.
Please help.

Shouldn't be a problem. You will need a needs line inside your moduleFor call:
import { moduleFor, test } from 'ember-qunit';
import Ember from 'ember';
moduleFor('util:graph-helper', 'Graph Helper', {
needs: ['controller:index'],
beforeEach: () => initialize()
});
function initialize() { /* something */ };
test('test desc', function(assert) {
var testObj = this.subject();
// test logic follows
});
See http://guides.emberjs.com/v1.10.0/testing/testing-controllers/#toc_testing-controller-needs for more details about needs.
Edit
Disregard the above information... that's for Ember modules which resolve the standard way. To include modules off the beaten Ember path, a simple ES6 import will suffice (this example demonstrates pulling in some-util for the controller:index unit tests):
import { moduleFor, test } from 'ember-qunit';
import Ember from 'ember';
import SomeUsefulUtil from '<application-name>/utils/some-useful-util';
moduleFor('controller:index', 'Graph Helper', {
beforeEach: () => initialize()
});
function initialize() { /* something */ };
test('test desc', function(assert) {
var testObj = this.subject();
// Create utility class instance
var someUsefulUtilInstance = new SomeUsefulUtil();
// test logic follows
});
The potentially non-intuitive part of this is that you have to prefix the import with your application's name instead of the standard app directory.

Related

TypeError when using before all hook in ember mocha

I'm running into some issues with the before all hook in ember-mocha (version 0.14.0). Here's an example from the docs that's been slightly modified to include a beforeEach hook:
import { expect } from 'chai';
import { describe, it } from 'mocha';
import { setupApplicationTest } from 'ember-mocha';
import { visit, currentURL } from '#ember/test-helpers';
describe('basic acceptance test', function() {
setupApplicationTest();
beforeEach(async function() {
await visit('index');
});
it('can visit /', async function() {
await visit('/');
expect(currentURL()).to.equal('/');
});
});
The above test runs as expected with no issues. However, when I substitute before for beforeEach I encounter an error:
import { expect } from 'chai';
import { describe, it } from 'mocha';
import { setupApplicationTest } from 'ember-mocha';
import { visit, currentURL } from '#ember/test-helpers';
describe('basic acceptance test', function() {
setupApplicationTest();
before(async function() {
await visit('index');
});
it('can visit /', async function() {
await visit('/');
expect(currentURL()).to.equal('/');
});
});
TypeError: Cannot destructure property `owner` of 'undefined' or 'null'.
at visit (assets/test-support.js:24931:9)
at Context.<anonymous> (assets/tests.js:339:36)
at invoke (assets/test-support.js:22801:21)
at Context.asyncFn (assets/test-support.js:22786:11)
at callFnAsync (assets/test-support.js:14070:8)
at Hook.Runnable.run (assets/test-support.js:14022:7)
at next (assets/test-support.js:14386:10)
at assets/test-support.js:14408:5
at timeslice (assets/test-support.js:9651:27)
Please let me know if any clarification is needed. Thanks in advance for your help!
Thats expected!
before only runs once for all tests.
That means before all beforeEach hooks
However setupApplicationTest utilizes beforeEach to setup the app (and the container), and afterEach to tear it down again.
This means you get a fresh app for all tests.
However you can not really visit anything without an app.
This means for every test you get a new app instance.
This means there is no app for all tests so there is no app that could visit a route.
The same question was asked in the ember discord channel. This answer tries to take the essence of the discussion to archive it on SO.

How to setup ember-intl service in Ember integration tests?

I have just begun adding ember-intl into an application for which I had working tests. My acceptance tests are still working, but my integration tests on components whose templates are using ember-intl for string translation are failing with:
"No locale defined. Unable to resolve translation:..."
In the ember-intl docs there is a section on Integration Testing, which seems to be out of date:
import hbs from 'htmlbars-inline-precompile';
import wait from 'ember-test-helpers/wait';
import { moduleForComponent, test } from 'ember-qunit';
let service;
moduleForComponent('x-product', 'XProductComponent', {
integration: true,
setup() {
service = this.container.lookup('service:intl');
service.setLocale('en-us');
}
});
test('it renders', function(assert) {
assert.expect(1);
this.render(hbs`{{x-product price=price deadline=deadline}}`);
this.set('price', 1000);
this.set('deadline', new Date());
let output = this.$().text();
assert.ok(output);
});
test('it translates', function(assert) {
assert.expect(1);
/* waits for async behavior (loading translations on app boot) to settle */
return wait().then(() => {
assert.equal(service.t('some.key'), 'Hello world');
});
});
I've looked in the Ember docs and I can see how to stub a service for testing, but not how to just load the service in a test and then work with it.
Instead of using this.container, we now need to use this.owner in the new format tests. Here's a snippet of code showing how to use it in context:
import { module, test } from 'qunit';
import { setupRenderingTest } from 'ember-qunit';
import { find, render } from '#ember/test-helpers';
import hbs from 'htmlbars-inline-precompile';
module('Integration | Component | login-form', function(hooks) {
setupRenderingTest(hooks);
let service;
hooks.beforeEach(function() {
service = this.owner.lookup('service:intl');
service.setLocale('en-us');
});
test('it renders', async function(assert) {
await render(hbs`{{login-form}}`);
assert.equal(find('[data-test-login-title]').textContent.trim(), 'Login');
});
});
A PR has been submitted to ember-intl, so hopefully the docs will reflect the latest best-practice soon.

How to unit test custom Ember.Inflector rules

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.

Ember CLI Simple Auth test helper authenticateSession is not defined

I am using ember-cli 0.2.6 and ember-cli-simple-auth 0.8.0-beta.2.
Starting from scratch I do the following:
ember create project1
//inside project1
ember install ember-cli-simple-auth
now i am adding the following line to tests/helpers/start-app:
import 'simple-auth-testing/test-helpers';
and in environment.js only add this:
if (environment === 'test') {
ENV['simple-auth'] = {
store: 'simple-auth-session-store:ephemeral'
};
...
}
Also I created an acceptance test named "login"
ember generate acceptance-test login
Which i adjusted to make use of the authenticateSession(); helper:
import Ember from 'ember';
import {
module,
test
} from 'qunit';
import startApp from 'project1/tests/helpers/start-app';
var application;
module('Acceptance: Login', {
beforeEach: function() {
application = startApp();
},
afterEach: function() {
Ember.run(application, 'destroy');
}
});
test('visiting /login', function(assert) {
authenticateSession();
ok('yes');
});
Now however, whenever i run ember test I get the same error message:
acceptance/login-test.js: line 22, col 3, 'authenticateSession' is not defined.
What did I miss to be not able to access the simple-auth helpers inside my acceptance test? I also tried with the simple-auth 0.7.3 release,... In another try I set up a custom authorizer, but got the same error.
You need to import the testing helpers like this:
import initializeTestHelpers from 'simple-auth-testing/test-helpers';
initializeTestHelpers();

Import { module } from 'ember-qunit'

Looking over the Ember CLI docs, it says to create an integration test like so:
import Ember from "ember";
import { module, test } from 'ember-qunit';
import startApp from '../helpers/start-app';
var App;
module('An Integration test', {
beforeEach: function() {
App = startApp();
},
afterEach: function() {
Ember.run(App, App.destroy);
}
});
test("Page contents", function(assert) {
assert.expect(2);
visit('/foos').then(function() {
assert.equal(find('.foos-list').length, 1, "Page contains list of models");
assert.equal(find('.foos-list .foo-item').length, 5, "List contains expected number of models");
});
});
The problem is, this code results in:
TypeError: undefined is not a function
If I remove the test, I still get that error. If I remove the module, then I don't get the error. (But neither does qunit run the test.) This makes sense, because it looks like ember-qunit doesn't export a module.
So what am I suppose to do here?