ember-legacy-class-transform
Version:
The default blueprint for ember-cli addons.
314 lines (265 loc) • 7.78 kB
JavaScript
var QUnit = require('qunitjs');
var RSVP = require('rsvp');
var SimpleDOM = require('simple-dom');
var appModule = require('./helpers/app-module');
function assertHTMLMatches(assert, actualHTML, expectedHTML) {
assert.ok(actualHTML.match(expectedHTML), actualHTML + " matches " + expectedHTML);
}
function handleError(assert) {
return function(error) {
assert.ok(false, error.stack);
};
}
// This is based on what fastboot-server does
var HTMLSerializer = new SimpleDOM.HTMLSerializer(SimpleDOM.voidMap);
function fastbootVisit(App, url) {
var doc = new SimpleDOM.Document();
var rootElement = doc.body;
var options = { isBrowser: false, document: doc, rootElement: rootElement };
return App.visit(url, options).then(function(instance) {
try {
return {
url: instance.getURL(),
title: doc.title,
body: HTMLSerializer.serialize(rootElement)
};
} finally {
instance.destroy();
}
});
}
function assertFastbootResult(assert, expected) {
return function(actual) {
assert.equal(actual.url, expected.url);
assertHTMLMatches(assert, actual.body, expected.body);
};
}
appModule("Ember.Application - visit() Integration Tests");
QUnit.test('FastBoot: basic', function(assert) {
this.routes(function() {
this.route('a');
this.route('b');
});
this.template('application', '<h1>Hello world</h1>\n{{outlet}}');
this.template('a', '<h2>Welcome to {{x-foo page="A"}}</h2>');
this.template('b', '<h2>{{x-foo page="B"}}</h2>');
this.template('components/x-foo', 'Page {{page}}');
var initCalled = false;
var didInsertElementCalled = false;
this.component('x-foo', {
tagName: 'span',
init: function() {
this._super();
initCalled = true;
},
didInsertElement: function() {
didInsertElementCalled = true;
}
});
var App = this.createApplication();
return RSVP.all([
fastbootVisit(App, '/a').then(
assertFastbootResult(assert, {
url: '/a',
body: '<h1>Hello world</h1>\n<h2>Welcome to <span id=".+" class="ember-view">Page A</span></h2>'
}),
handleError(assert)
),
fastbootVisit(App, '/b').then(
assertFastbootResult(assert, {
url: '/b',
body: '<h1>Hello world</h1>\n<h2><span id=".+" class="ember-view">Page B</span></h2>'
}),
handleError
)
]).then(function() {
assert.ok(initCalled, 'Component#init should be called');
assert.ok(!didInsertElementCalled, 'Component#didInsertElement should not be called');
});
});
QUnit.test('FastBoot: redirect', function(assert) {
this.routes(function() {
this.route('a');
this.route('b');
this.route('c');
});
this.template('a', '<h1>Hello from A</h1>');
this.template('b', '<h1>Hello from B</h1>');
this.template('c', '<h1>Hello from C</h1>');
this.route('a', {
beforeModel: function() {
this.replaceWith('b');
}
});
this.route('b', {
afterModel: function() {
this.transitionTo('c');
}
});
var App = this.createApplication();
return RSVP.all([
fastbootVisit(App, '/a').then(
assertFastbootResult(assert, { url: '/c', body: '<h1>Hello from C</h1>' }),
handleError(assert)
),
fastbootVisit(App, '/b').then(
assertFastbootResult(assert, { url: '/c', body: '<h1>Hello from C</h1>' }),
handleError(assert)
)
]);
});
QUnit.test('FastBoot: attributes are sanitized', function(assert) {
this.template('application', '<a href={{test}}></a>');
this.controller('application', {
/*jshint scripturl:true*/
test: 'javascript:alert("hello")'
});
var App = this.createApplication();
return RSVP.all([
fastbootVisit(App, '/').then(
assertFastbootResult(assert, { url: '/', body: '<a href="unsafe:javascript:alert\\("hello"\\)"></a>' }),
handleError(assert)
)
]);
});
QUnit.test('FastBoot: route error', function(assert) {
this.routes(function() {
this.route('a');
this.route('b');
});
this.template('a', '<h1>Hello from A</h1>');
this.template('b', '<h1>Hello from B</h1>');
this.route('a', {
beforeModel: function() {
throw new Error('Error from A');
}
});
this.route('b', {
afterModel: function() {
throw new Error('Error from B');
}
});
var App = this.createApplication();
return RSVP.all([
fastbootVisit(App, '/a').then(
function(instance) {
assert.ok(false, 'It should not render');
instance.destroy();
},
function(error) {
assert.equal(error.message, 'Error from A');
}
),
fastbootVisit(App, '/b').then(
function(instance) {
assert.ok(false, 'It should not render');
instance.destroy();
},
function(error) {
assert.equal(error.message, 'Error from B');
}
)
]);
});
QUnit.test('Resource-discovery setup', function(assert) {
this.service('network', {
init: function() {
this.set('requests', []);
},
fetch: function(url) {
this.get('requests').push(url);
return RSVP.resolve();
}
});
this.routes(function() {
this.route('a');
this.route('b');
this.route('c');
this.route('d');
this.route('e');
});
this.route('a', {
model: function() {
return this.network.fetch('/a');
},
afterModel: function() {
this.replaceWith('b');
}
});
this.route('b', {
model: function() {
return this.network.fetch('/b');
},
afterModel: function() {
this.replaceWith('c');
}
});
this.route('c', {
model: function() {
return this.network.fetch('/c');
}
});
this.route('d', {
model: function() {
return this.network.fetch('/d');
},
afterModel: function() {
this.replaceWith('e');
}
});
this.route('e', {
model: function() {
return this.network.fetch('/e');
}
});
this.template('a', '{{x-foo}}');
this.template('b', '{{x-foo}}');
this.template('c', '{{x-foo}}');
this.template('d', '{{x-foo}}');
this.template('e', '{{x-foo}}');
var xFooInstances = 0;
this.component('x-foo', {
init: function() {
this._super();
xFooInstances++;
}
});
var App = this.createApplication();
App.inject('route', 'network', 'service:network');
function assertResources(url, resources) {
return App.visit(url, { isBrowser: false, shouldRender: false }).then(
function(instance) {
try {
var viewRegistry = instance.lookup('-view-registry:main');
assert.strictEqual(Object.keys(viewRegistry).length, 0, 'did not create any views');
var networkService = instance.lookup('service:network');
assert.deepEqual(networkService.get('requests'), resources);
} finally {
instance.destroy();
}
},
handleError(assert)
);
}
return RSVP.all([
assertResources('/a', ['/a', '/b', '/c']),
assertResources('/b', ['/b', '/c']),
assertResources('/c', ['/c']),
assertResources('/d', ['/d', '/e']),
assertResources('/e', ['/e'])
]).then(function() {
assert.strictEqual(xFooInstances, 0, 'it should not create any x-foo components');
});
});
QUnit.test('FastBoot: tagless components can render', function(assert) {
this.template('application', "<div class='my-context'>{{my-component}}</div>");
this.component('my-component', { tagName: '' });
this.template('components/my-component', '<h1>hello world</h1>');
var App = this.createApplication();
return RSVP.all([
fastbootVisit(App, '/').then(
assertFastbootResult(assert, { url: '/', body: /<div class="my-context"><h1>hello world<\/h1><\/div>/ }),
handleError(assert)
)
]);
});