Skip to content

Commit

Permalink
Merge pull request #14054 from trentmwillis/reset-substates
Browse files Browse the repository at this point in the history
[BUGFIX beta] Ensure substates properly work with resetNamespace
  • Loading branch information
rwjblue authored Aug 12, 2016
2 parents 6558db6 + 9a69d63 commit caa9d3f
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 10 deletions.
4 changes: 2 additions & 2 deletions packages/ember-routing/lib/system/dsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ DSL.prototype = {

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

if (callback) {
Expand Down Expand Up @@ -193,7 +193,7 @@ if (isEnabled('ember-application-engines')) {
if (this.enableLoadingSubstates) {
let dummyErrorRoute = `/_unused_dummy_error_path_route_${name}/:error`;
createRoute(this, `${name}_loading`, { resetNamespace: options.resetNamespace });
createRoute(this, `${name}_error`, { path: dummyErrorRoute });
createRoute(this, `${name}_error`, { resetNamespace: options.resetNamespace, path: dummyErrorRoute });
}

let localFullName = 'application';
Expand Down
20 changes: 14 additions & 6 deletions packages/ember-routing/lib/system/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -1014,16 +1014,24 @@ function findChildRouteName(parentRoute, originatingChildRoute, name) {
}
}

let targetChildRouteName = originatingChildRouteName.split('.').pop();
let namespace = parentRoute.routeName === 'application' ? '' : parentRoute.routeName + '.';

// First, try a named loading state, e.g. 'foo_loading'
childName = namespace + targetChildRouteName + '_' + name;
// First, try a named loading state of the route, e.g. 'foo_loading'
childName = originatingChildRouteName + '_' + name;
if (routeHasBeenDefined(router, childName)) {
return childName;
}

// Second, try general loading state, e.g. 'loading'
// Second, try general loading state of the parent, e.g. 'loading'
let originatingChildRouteParts = originatingChildRouteName.split('.').slice(0, -1);
let namespace;

// If there is a namespace on the route, then we use that, otherwise we use
// the parent route as the namespace.
if (originatingChildRouteParts.length) {
namespace = originatingChildRouteParts.join('.') + '.';
} else {
namespace = parentRoute.routeName === 'application' ? '' : parentRoute.routeName + '.';
}

childName = namespace + name;
if (routeHasBeenDefined(router, childName)) {
return childName;
Expand Down
58 changes: 58 additions & 0 deletions packages/ember-routing/tests/system/dsl_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,33 @@ QUnit.test('should not add loading and error routes if _isRouterMapResult is fal
ok(!router.router.recognizer.names['blork_error'], 'error route was not added');
});

QUnit.test('should reset namespace of loading and error routes for routes with resetNamespace', function() {
Router.map(function() {
this.route('blork', function() {
this.route('blorp');
this.route('bleep', { resetNamespace: true });
});
});

let router = Router.create({
_hasModuleBasedResolver() { return true; }
});

router._initRouterJs();

ok(router.router.recognizer.names['blork.blorp'], 'nested route was created');
ok(router.router.recognizer.names['blork.blorp_loading'], 'nested loading route was added');
ok(router.router.recognizer.names['blork.blorp_error'], 'nested error route was added');

ok(router.router.recognizer.names['bleep'], 'reset route was created');
ok(router.router.recognizer.names['bleep_loading'], 'reset loading route was added');
ok(router.router.recognizer.names['bleep_error'], 'reset error route was added');

ok(!router.router.recognizer.names['blork.bleep'], 'nested reset route was not created');
ok(!router.router.recognizer.names['blork.bleep_loading'], 'nested reset loading route was not added');
ok(!router.router.recognizer.names['blork.bleep_error'], 'nested reset error route was not added');
});

if (isEnabled('ember-application-engines')) {
QUnit.test('should throw an error when defining a route serializer outside an engine', function() {
Router.map(function() {
Expand Down Expand Up @@ -267,4 +294,35 @@ if (isEnabled('ember-application-engines')) {
ok(!router.router.recognizer.names['chat_loading'], 'loading route was not added');
ok(!router.router.recognizer.names['chat_error'], 'error route was not added');
});

QUnit.test('should reset namespace of loading and error routes for mounts with resetNamespace', function() {
Router.map(function() {
this.route('news', function() {
this.mount('chat');
this.mount('blog', { resetNamespace: true });
});
});

let engineInstance = buildOwner({
routable: true
});

let router = Router.create({
_hasModuleBasedResolver() { return true; }
});
setOwner(router, engineInstance);
router._initRouterJs();

ok(router.router.recognizer.names['news.chat'], 'nested route was created');
ok(router.router.recognizer.names['news.chat_loading'], 'nested loading route was added');
ok(router.router.recognizer.names['news.chat_error'], 'nested error route was added');

ok(router.router.recognizer.names['blog'], 'reset route was created');
ok(router.router.recognizer.names['blog_loading'], 'reset loading route was added');
ok(router.router.recognizer.names['blog_error'], 'reset error route was added');

ok(!router.router.recognizer.names['news.blog'], 'nested reset route was not created');
ok(!router.router.recognizer.names['news.blog_loading'], 'nested reset loading route was not added');
ok(!router.router.recognizer.names['news.blog_error'], 'nested reset error route was not added');
});
}
71 changes: 69 additions & 2 deletions packages/ember/tests/routing/substates_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ QUnit.test('Default error event moves into nested route, prioritizing more speci

templates['grandma'] = 'GRANDMA {{outlet}}';
templates['grandma/error'] = 'ERROR: {{model.msg}}';
templates['grandma/mom_error'] = 'MOM ERROR: {{model.msg}}';
templates['mom_error'] = 'MOM ERROR: {{model.msg}}';

Router.map(function() {
this.route('grandma', function() {
Expand Down Expand Up @@ -842,7 +842,7 @@ QUnit.test('Prioritized substate entry works with preserved-namespace nested rou

Router.map(function() {
this.route('foo', function() {
this.route('foo.bar', { path: '/bar', resetNamespace: true }, function() {
this.route('bar', { path: '/bar' }, function() {
});
});
});
Expand All @@ -865,6 +865,37 @@ QUnit.test('Prioritized substate entry works with preserved-namespace nested rou
equal(jQuery('#app', '#qunit-fixture').text(), 'YAY');
});

QUnit.test('Prioritized substate entry works with reset-namespace nested routes', function() {
expect(2);

templates['bar_loading'] = 'BAR LOADING';
templates['bar/index'] = 'YAY';

Router.map(function() {
this.route('foo', function() {
this.route('bar', { path: '/bar', resetNamespace: true }, function() {
});
});
});

App.ApplicationController = Controller.extend();

let deferred = RSVP.defer();
App.BarRoute = Route.extend({
model() {
return deferred.promise;
}
});

bootApplication('/foo/bar');

equal(jQuery('#app', '#qunit-fixture').text(), 'BAR LOADING', 'foo.bar_loading was entered (as opposed to something like foo/foo/bar_loading)');

run(deferred, 'resolve');

equal(jQuery('#app', '#qunit-fixture').text(), 'YAY');
});

QUnit.test('Prioritized loading substate entry works with preserved-namespace nested routes', function() {
expect(2);

Expand Down Expand Up @@ -1090,4 +1121,40 @@ if (isEnabled('ember-application-engines')) {

equal(jQuery('#app', '#qunit-fixture').text(), 'BLOG ERROR', 'news/blog_loading was entered');
});

QUnit.test('Slow Promise from an Engine application route enters the mounts loading state with resetNamespace', function() {
expect(1);

templates['blog_loading'] = 'BLOG LOADING';

// Register engine
let BlogEngine = Engine.extend();
registry.register('engine:blog', BlogEngine);

// Register engine route map
let BlogMap = function() {};
registry.register('route-map:blog', BlogMap);

Router.map(function() {
this.route('news', function() {
this.mount('blog', { resetNamespace: true });
});
});

let deferred = RSVP.defer();
let BlogRoute = Route.extend({
model() {
return deferred.promise;
}
});

var blog = container.lookup('engine:blog');
blog.register('route:application', BlogRoute);

bootApplication('/news/blog');

equal(jQuery('#app', '#qunit-fixture').text(), 'BLOG LOADING', 'news/blog_loading was entered');

run(deferred, 'resolve');
});
}

0 comments on commit caa9d3f

Please sign in to comment.