From ee93b9a62301a1a42447ad8766fa7a664ad20545 Mon Sep 17 00:00:00 2001 From: Gaurav Munjal Date: Fri, 22 Nov 2019 12:09:02 -0500 Subject: [PATCH] [BUGFIX] Make RouterService.transitionTo engine aware --- .../-internals/routing/lib/services/router.ts | 34 ++++++++++++-- .../routing/tests/services/router-test.js | 47 +++++++++++++++++++ 2 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 packages/@ember/-internals/routing/tests/services/router-test.js diff --git a/packages/@ember/-internals/routing/lib/services/router.ts b/packages/@ember/-internals/routing/lib/services/router.ts index 35563451c43..8e3c944d4b4 100644 --- a/packages/@ember/-internals/routing/lib/services/router.ts +++ b/packages/@ember/-internals/routing/lib/services/router.ts @@ -1,5 +1,7 @@ +import { getOwner } from '@ember/-internals/owner'; import { Evented } from '@ember/-internals/runtime'; import { assert } from '@ember/debug'; +import EmberError from '@ember/error'; import { readOnly } from '@ember/object/computed'; import Service from '@ember/service'; import { DEBUG } from '@glimmer/env'; @@ -120,11 +122,12 @@ export default class RouterService extends Service { @public */ transitionTo(...args: string[]) { - if (resemblesURL(args[0])) { - return this._router._doURLTransition('transitionTo', args[0]); - } - let { routeName, models, queryParams } = extractRouteArgs(args); + routeName = this._prefixRouteName(routeName); + + if (resemblesURL(routeName)) { + return this._router._doURLTransition('transitionTo', routeName); + } let transition = this._router._doTransition(routeName, models, queryParams, true); transition['_keepDefaultQueryParamValues'] = true; @@ -132,6 +135,29 @@ export default class RouterService extends Service { return transition; } + /* + Returns a route name which is prefixed based on the mount point + + @private + */ + _prefixRouteName(routeName: string) { + let owner = getOwner(this); + let prefix = owner.mountPoint; + + // only alter the routeName if it's actually referencing a route. + if (owner.routable && typeof routeName === 'string') { + if (resemblesURL(routeName)) { + throw new EmberError( + 'Programmatic transitions by URL cannot be used within an Engine. Please use the route name instead.' + ); + } else { + routeName = `${prefix}.${routeName}`; + } + } + + return routeName; + } + /** Transition into another route while replacing the current URL, if possible. The route may be either a single route or route path: diff --git a/packages/@ember/-internals/routing/tests/services/router-test.js b/packages/@ember/-internals/routing/tests/services/router-test.js new file mode 100644 index 00000000000..7efdd03a7f7 --- /dev/null +++ b/packages/@ember/-internals/routing/tests/services/router-test.js @@ -0,0 +1,47 @@ +import { buildOwner, moduleFor, AbstractTestCase } from 'internal-test-helpers'; +import { setOwner } from '@ember/-internals/owner'; +import RouterService from '../../lib/services/router'; + +moduleFor( + 'RouterService with engines', + class extends AbstractTestCase { + ["@test transitionTo considers an engine's mountPoint"](assert) { + let router = { + on() {}, + off() {}, + _doTransition(route) { + return { route }; + }, + }; + + let engineInstance = buildOwner({ + ownerOptions: { + routable: true, + mountPoint: 'foo.bar', + }, + }); + + let routerService = RouterService.create({ _router: router }); + setOwner(routerService, engineInstance); + + assert.strictEqual( + routerService.transitionTo('application').route, + 'foo.bar.application', + 'properly prefixes application route' + ); + assert.strictEqual( + routerService.transitionTo('posts').route, + 'foo.bar.posts', + 'properly prefixes child routes' + ); + assert.throws(() => routerService.transitionTo('/posts'), 'throws when trying to use a url'); + + let queryParams = {}; + assert.strictEqual( + routerService.transitionTo(queryParams).route, + queryParams, + 'passes query param only transitions through' + ); + } + } +);