/* eslint-disable no-console */
var path = require('path');
var distPath = path.join(__dirname, '../../../dist');
var emberPath = path.join(distPath, 'ember.debug');
var templateCompilerPath = path.join(distPath, 'ember-template-compiler');
var SimpleDOM = require('simple-dom');
/*
* This helper sets up a QUnit test module with all of the environment and
* helper methods necessary to test an Ember.js application running in the
* server-side environment.
*
* On each test, it loads a fresh version of the compiled Ember.js library
* from `dist`, just like how FastBoot works. It uses the new `visit()` API
* to simulate a FastBoot environment (enabling that feature flag if it is
* not already turned on).
*
* To test an app, register the objects that make up the app. For example,
* to register a component:
*
* this.component('component-name', {
* componentProperty: true
* });
*
* Or a template:
*
* this.template('application', '{{outlet}}');
* this.template('components/foo-bar', '
Hello world
');
*
* Or a controller:
*
* this.controller('controller-name', {
* actions: {
* sendEmail: function() { }
* }
* });
*
* You can also provide the routes for the application by calling `this.routes()`,
* which is equivalent to `App.Router.map()`:
*
* this.routes(function() {
* this.route('photos');
* this.route('admin', function() {
* this.route('logout');
* });
* });
*
* Once all of the constituent parts of the app are registered, you can kick off
* app boot by calling either `this.visit(url)` or `this.renderToHTML(url)`.
*
* `visit` returns a promise that resolves to the application instance, and
* `renderToHTML` returns a promise that resolves to the rendered HTML of the
* application.
*
* return this.renderToHTML('/'photos).then(function(html) {
* assert.ok(html.matches('Hello world
'));
* });
*/
module.exports = function(moduleName) {
QUnit.module(moduleName, {
beforeEach: function() {
var Ember = (this.Ember = require(emberPath));
Ember.testing = true;
var precompile = require(templateCompilerPath).precompile;
this.compile = function(templateString, options) {
var templateSpec = precompile(templateString, options);
var template = new Function('return ' + templateSpec)();
return Ember.HTMLBars.template(template);
};
this.run = Ember.run;
this.all = Ember.RSVP.all;
this.visit = visit;
this.createApplication = createApplication;
this.register = register;
this.template = registerTemplate;
this.component = registerComponent;
this.controller = registerController;
this.route = registerRoute;
this.service = registerService;
this.routes = registerRoutes;
this.registry = {};
this.renderToHTML = renderToHTML;
},
afterEach: function() {
this.run(this.app, 'destroy');
delete global.Ember;
// clear the previously cached version of this module
delete require.cache[emberPath + '.js'];
delete require.cache[templateCompilerPath + '.js'];
},
});
};
function createApplication() {
if (this.app) return this.app;
var app = this.Ember.Application.extend().create({
autoboot: false,
});
app.Router = this.Ember.Router.extend({
location: 'none',
});
if (this.routesCallback) {
app.Router.map(this.routesCallback);
}
registerApplicationClasses(app, this.registry);
// Run application initializers
this.run(app, 'boot');
this.app = app;
return app;
}
function register(containerKey, klass) {
this.registry[containerKey] = klass;
}
function visit(url) {
var app = this.createApplication();
var dom = new SimpleDOM.Document();
return this.run(app, 'visit', url, {
isBrowser: false,
document: dom,
rootElement: dom.body,
}).catch(function(error) {
console.error(error.stack);
});
}
function renderToHTML(url) {
var app = this.createApplication();
var dom = new SimpleDOM.Document();
var root = dom.body;
return this.run(app, 'visit', url, {
isBrowser: false,
document: dom,
rootElement: root,
}).then(function() {
var serializer = new SimpleDOM.HTMLSerializer(SimpleDOM.voidMap);
return serializer.serialize(root);
});
}
function registerApplicationClasses(app, registry) {
app.initializer({
name: 'register-application-classes',
initialize: function(app) {
for (var key in registry) {
app.register(key, registry[key]);
}
},
});
}
function registerTemplate(name, template) {
this.register('template:' + name, this.compile(template));
}
function registerComponent(name, componentProps) {
var component = this.Ember.Component.extend(componentProps);
this.register('component:' + name, component);
}
function registerController(name, controllerProps) {
var controller = this.Ember.Controller.extend(controllerProps);
this.register('controller:' + name, controller);
}
function registerRoute(name, routeProps) {
var route = this.Ember.Route.extend(routeProps);
this.register('route:' + name, route);
}
function registerService(name, serviceProps) {
var service = this.Ember.Object.extend(serviceProps);
this.register('service:' + name, service);
}
function registerRoutes(cb) {
this.routesCallback = cb;
}