Skip to content

Commit

Permalink
Merge pull request #14545 from trentmwillis/engine-loading
Browse files Browse the repository at this point in the history
[BUGFIX beta] Make substates great again!
  • Loading branch information
rwjblue authored Oct 30, 2016
2 parents d37d38b + abf1c9d commit 10857fd
Show file tree
Hide file tree
Showing 7 changed files with 391 additions and 200 deletions.
245 changes: 243 additions & 2 deletions packages/ember-glimmer/tests/integration/application/engine-test.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
import { moduleFor, ApplicationTest } from '../../utils/test-case';
import { strip } from '../../utils/abstract-test-case';
import { compile } from '../../utils/helpers';
import { Controller } from 'ember-runtime';
import { Controller, RSVP } from 'ember-runtime';
import { Component } from 'ember-glimmer';
import { Engine } from 'ember-application';
import { Route } from 'ember-routing';

moduleFor('Application test: engine rendering', class extends ApplicationTest {
setupAppAndRoutableEngine(hooks = []) {
let self = this;

this.application.register('template:application', compile('Application{{outlet}}'));

this.router.map(function() {
this.mount('blog');
});
this.application.register('route-map:blog', function() { });
this.application.register('route-map:blog', function() {
this.route('post', function() {
this.route('comments');
this.route('likes');
});
});
this.registerRoute('application', Route.extend({
model() {
hooks.push('application - application');
Expand All @@ -33,6 +40,10 @@ moduleFor('Application test: engine rendering', class extends ApplicationTest {
hooks.push('engine - application');
}
}));

if (self._additionalEngineRegistrations) {
self._additionalEngineRegistrations.call(this);
}
}
}));
}
Expand Down Expand Up @@ -108,6 +119,10 @@ moduleFor('Application test: engine rendering', class extends ApplicationTest {
}));
}

additionalEngineRegistrations(callback) {
this._additionalEngineRegistrations = callback;
}

setupEngineWithAttrs(hooks) {
this.application.register('template:application', compile('Application{{mount "chat-engine"}}'));

Expand Down Expand Up @@ -331,4 +346,230 @@ moduleFor('Application test: engine rendering', class extends ApplicationTest {
this.assertText('ApplicationEngineEnglish');
});
}

['@test error substate route works for the application route of an Engine'](assert) {
assert.expect(2);

this.setupAppAndRoutableEngine();
this.application.__registry__.resolver.moduleBasedResolver = true;
this.additionalEngineRegistrations(function() {
this.register('template:application_error', compile('Error! {{model.message}}'));
this.register('route:post', Route.extend({
model() {
return RSVP.reject(new Error('Oh, noes!'));
}
}));
});

return this.visit('/').then(() => {
this.assertText('Application');
return this.transitionTo('blog.post');
}).catch(() => {
this.assertText('ApplicationError! Oh, noes!');
});
}

['@test error route works for the application route of an Engine'](assert) {
assert.expect(2);

this.setupAppAndRoutableEngine();
this.application.__registry__.resolver.moduleBasedResolver = true;
this.additionalEngineRegistrations(function() {
this.register('template:error', compile('Error! {{model.message}}'));
this.register('route:post', Route.extend({
model() {
return RSVP.reject(new Error('Oh, noes!'));
}
}));
});

return this.visit('/').then(() => {
this.assertText('Application');
return this.transitionTo('blog.post');
}).catch(() => {
this.assertText('ApplicationEngineError! Oh, noes!');
});
}

['@test error substate route works for a child route of an Engine'](assert) {
assert.expect(2);

this.setupAppAndRoutableEngine();
this.application.__registry__.resolver.moduleBasedResolver = true;
this.additionalEngineRegistrations(function() {
this.register('template:post_error', compile('Error! {{model.message}}'));
this.register('route:post', Route.extend({
model() {
return RSVP.reject(new Error('Oh, noes!'));
}
}));
});

return this.visit('/').then(() => {
this.assertText('Application');
return this.transitionTo('blog.post');
}).catch(() => {
this.assertText('ApplicationEngineError! Oh, noes!');
});
}

['@test error route works for a child route of an Engine'](assert) {
assert.expect(2);

this.setupAppAndRoutableEngine();
this.application.__registry__.resolver.moduleBasedResolver = true;
this.additionalEngineRegistrations(function() {
this.register('template:post.error', compile('Error! {{model.message}}'));
this.register('route:post.comments', Route.extend({
model() {
return RSVP.reject(new Error('Oh, noes!'));
}
}));
});

return this.visit('/').then(() => {
this.assertText('Application');
return this.transitionTo('blog.post.comments');
}).catch(() => {
this.assertText('ApplicationEngineError! Oh, noes!');
});
}

['@test loading substate route works for the application route of an Engine'](assert) {
assert.expect(3);

let resolveLoading;

this.setupAppAndRoutableEngine();
this.application.__registry__.resolver.moduleBasedResolver = true;
this.additionalEngineRegistrations(function() {
this.register('template:application_loading', compile('Loading'));
this.register('template:post', compile('Post'));
this.register('route:post', Route.extend({
model() {
return new RSVP.Promise((resolve) => {
resolveLoading = resolve;
});
}
}));
});

return this.visit('/').then(() => {
this.assertText('Application');
let transition = this.transitionTo('blog.post');

this.runTaskNext(() => {
this.assertText('ApplicationLoading');
resolveLoading();
});

return transition.then(() => {
this.runTaskNext(() => this.assertText('ApplicationEnginePost'));
});
});
}

['@test loading route works for the application route of an Engine'](assert) {
assert.expect(3);

let resolveLoading;

this.setupAppAndRoutableEngine();
this.additionalEngineRegistrations(function() {
this.register('template:loading', compile('Loading'));
this.register('template:post', compile('Post'));
this.register('route:post', Route.extend({
model() {
return new RSVP.Promise((resolve) => {
resolveLoading = resolve;
});
}
}));
});

return this.visit('/').then(() => {
this.assertText('Application');
let transition = this.transitionTo('blog.post');

this.runTaskNext(() => {
this.assertText('ApplicationEngineLoading');
resolveLoading();
});

return transition.then(() => {
this.runTaskNext(() => this.assertText('ApplicationEnginePost'));
});
});
}

['@test loading substate route works for a child route of an Engine'](assert) {
assert.expect(3);

let resolveLoading;

this.setupAppAndRoutableEngine();
this.application.__registry__.resolver.moduleBasedResolver = true;
this.additionalEngineRegistrations(function() {
this.register('template:post', compile('{{outlet}}'));
this.register('template:post.comments', compile('Comments'));
this.register('template:post.likes_loading', compile('Loading'));
this.register('template:post.likes', compile('Likes'));
this.register('route:post.likes', Route.extend({
model() {
return new RSVP.Promise((resolve) => {
resolveLoading = resolve;
});
}
}));
});

return this.visit('/blog/post/comments').then(() => {
this.assertText('ApplicationEngineComments');
let transition = this.transitionTo('blog.post.likes');

this.runTaskNext(() => {
this.assertText('ApplicationEngineLoading');
resolveLoading();
});

return transition.then(() => {
this.runTaskNext(() => this.assertText('ApplicationEngineLikes'));
});
});
}

['@test loading route works for a child route of an Engine'](assert) {
assert.expect(3);

let resolveLoading;

this.setupAppAndRoutableEngine();
this.additionalEngineRegistrations(function() {
this.register('template:post', compile('{{outlet}}'));
this.register('template:post.comments', compile('Comments'));
this.register('template:post.loading', compile('Loading'));
this.register('template:post.likes', compile('Likes'));
this.register('route:post.likes', Route.extend({
model() {
return new RSVP.Promise((resolve) => {
resolveLoading = resolve;
});
}
}));
});

return this.visit('/blog/post/comments').then(() => {
this.assertText('ApplicationEngineComments');
let transition = this.transitionTo('blog.post.likes');

this.runTaskNext(() => {
this.assertText('ApplicationEngineLoading');
resolveLoading();
});

return transition.then(() => {
this.runTaskNext(() => this.assertText('ApplicationEngineLikes'));
});
});
}
});
26 changes: 20 additions & 6 deletions packages/ember-routing/lib/system/dsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ DSL.prototype.mount = function(_name, _options) {
}

let callback;
let dummyErrorRoute = `/_unused_dummy_error_path_route_${name}/:error`;
if (engineRouteMap) {
let shouldResetEngineInfo = false;
let oldEngineInfo = this.options.engineInfo;
Expand All @@ -177,6 +178,9 @@ DSL.prototype.mount = function(_name, _options) {
let optionsForChild = assign({ engineInfo }, this.options);
let childDSL = new DSL(fullName, optionsForChild);

createRoute(childDSL, 'loading');
createRoute(childDSL, 'error', { path: dummyErrorRoute });

engineRouteMap.call(childDSL);

callback = childDSL.generate();
Expand All @@ -186,15 +190,25 @@ DSL.prototype.mount = function(_name, _options) {
}
}

if (this.enableLoadingSubstates) {
let dummyErrorRoute = `/_unused_dummy_error_path_route_${name}/:error`;
createRoute(this, `${name}_loading`, { resetNamespace: options.resetNamespace });
createRoute(this, `${name}_error`, { resetNamespace: options.resetNamespace, path: dummyErrorRoute });
}

let localFullName = 'application';
let routeInfo = assign({ localFullName }, engineInfo);

if (this.enableLoadingSubstates) {
// These values are important to register the loading routes under their
// proper names for the Router and within the Engine's registry.
let substateName = `${name}_loading`;
let localFullName = `application_loading`;
let routeInfo = assign({ localFullName }, engineInfo);
createRoute(this, substateName, { resetNamespace: options.resetNamespace });
this.options.addRouteForEngine(substateName, routeInfo);

substateName = `${name}_error`;
localFullName = `application_error`;
routeInfo = assign({ localFullName }, engineInfo);
createRoute(this, substateName, { resetNamespace: options.resetNamespace, path: dummyErrorRoute });
this.options.addRouteForEngine(substateName, routeInfo);
}

this.options.addRouteForEngine(fullName, routeInfo);

this.push(path, fullName, callback);
Expand Down
Loading

0 comments on commit 10857fd

Please sign in to comment.