Skip to content

Commit

Permalink
Merge pull request #14979 from scalvert/router-service
Browse files Browse the repository at this point in the history
Phase 3 of public Router Service - adding urlFor
  • Loading branch information
rwjblue authored Mar 8, 2017
2 parents dacfaa5 + 5d01fd3 commit 431be5c
Show file tree
Hide file tree
Showing 5 changed files with 314 additions and 5 deletions.
24 changes: 20 additions & 4 deletions packages/ember-routing/lib/services/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const RouterService = Service.extend({
@method transitionTo
@category ember-routing-router-service
@param {String} name the name of the route or a URL
@param {String} routeNameOrUrl the name of the route or a URL
@param {...Object} models the model(s) or identifier(s) to be used while
transitioning to the route.
@param {Object} [options] optional hash with a queryParams property
Expand All @@ -41,7 +41,7 @@ const RouterService = Service.extend({
attempted transition
@public
*/
transitionTo() {
transitionTo(/* routeNameOrUrl, ...models, options */) {
return this.router.transitionTo(...arguments);
},

Expand All @@ -53,7 +53,7 @@ const RouterService = Service.extend({
@method replaceWith
@category ember-routing-router-service
@param {String} name the name of the route or a URL
@param {String} routeNameOrUrl the name of the route or a URL
@param {...Object} models the model(s) or identifier(s) to be used while
transitioning to the route.
@param {Object} [options] optional hash with a queryParams property
Expand All @@ -62,8 +62,24 @@ const RouterService = Service.extend({
attempted transition
@public
*/
replaceWith() {
replaceWith(/* routeNameOrUrl, ...models, options */) {
return this.router.replaceWith(...arguments);
},

/**
Generate a URL based on the supplied route name.
@method urlFor
@param {String} routeName the name of the route
@param {...Object} models the model(s) or identifier(s) to be used while
transitioning to the route.
@param {Object} [options] optional hash with a queryParams property
containing a mapping of query parameters
@return {String} the string representing the generated URL
@public
*/
urlFor(/* routeName, ...models, options */) {
return this.router.generate(...arguments);
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,24 @@ if (isFeatureEnabled('ember-routing-router-service')) {
});
}

['@test RouterService#replaceWith with basic route using URLs replaces location'](assert) {
assert.expect(1);

return this.visit('/')
.then(() => {
return this.routerService.transitionTo('/child');
})
.then(() => {
return this.routerService.transitionTo('/sister');
})
.then(() => {
return this.routerService.replaceWith('/brother');
})
.then(() => {
assert.deepEqual(this.state, ['/', '/child', '/brother']);
});
}

['@test RouterService#replaceWith transitioning back to previously visited route replaces location'](assert) {
assert.expect(1);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,38 @@ if (isFeatureEnabled('ember-routing-router-service')) {
});
}

['@test RouterService#transitionTo with basic route using URL'](assert) {
assert.expect(1);

let componentInstance;

this.registerTemplate('parent.index', '{{foo-bar}}');

this.registerComponent('foo-bar', {
ComponentClass: Component.extend({
routerService: inject.service('router'),
init() {
this._super();
componentInstance = this;
},
actions: {
transitionToSister() {
get(this, 'routerService').transitionTo('/sister');
}
}
}),
template: `foo-bar`
});

return this.visit('/').then(() => {
run(function() {
componentInstance.send('transitionToSister');
});

assert.equal(this.routerService.get('currentRouteName'), 'parent.sister');
});
}

['@test RouterService#transitionTo with dynamic segment'](assert) {
assert.expect(3);

Expand Down
243 changes: 243 additions & 0 deletions packages/ember/tests/routing/router_service_test/urlFor_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
import {
Controller,
inject,
String
} from 'ember-runtime';
import { Component } from 'ember-glimmer';
import { Route, NoneLocation } from 'ember-routing';
import {
get,
set
} from 'ember-metal';
import {
RouterTestCase,
moduleFor
} from 'internal-test-helpers';

import { isFeatureEnabled } from 'ember-metal';

function setupController(app, name) {
let controllerName = `${String.capitalize(name)}Controller`;

Object.defineProperty(app, controllerName, {
get() {
throw new Error(`Generating a URL should not require instantiation of a ${controllerName}.`);
}
});
}

function buildQueryParams(queryParams) {
return {
queryParams
};
}

if (isFeatureEnabled('ember-routing-router-service')) {
moduleFor('Router Service - urlFor', class extends RouterTestCase {
['@test RouterService#urlFor returns URL for simple route'](assert) {
assert.expect(1);

return this.visit('/').then(() => {
let expectedURL = this.routerService.urlFor('parent.child');

assert.equal('/child', expectedURL);
});
}

['@test RouterService#urlFor returns URL for simple route with dynamic segments'](assert) {
assert.expect(1);

setupController(this.application, 'dynamic');

let dynamicModel = { id: 1, contents: 'much dynamicism' };

return this.visit('/').then(() => {
let expectedURL = this.routerService.urlFor('dynamic', dynamicModel);

assert.equal('/dynamic/1', expectedURL);
});
}

['@test RouterService#urlFor returns URL for simple route with basic query params'](assert) {
assert.expect(1);

let queryParams = buildQueryParams({ foo: 'bar' });

return this.visit('/').then(() => {
let expectedURL = this.routerService.urlFor('parent.child', queryParams);

assert.equal('/child?foo=bar', expectedURL);
});
}

['@test RouterService#urlFor returns URL for simple route with array as query params'](assert) {
assert.expect(1);

let queryParams = buildQueryParams({ selectedItems: ['a', 'b', 'c'] });

return this.visit('/').then(() => {
let expectedURL = this.routerService.urlFor('parent.child', queryParams);

assert.equal('/child?selectedItems[]=a&selectedItems[]=b&selectedItems[]=c', expectedURL);
});
}

['@test RouterService#urlFor returns URL for simple route with null query params'](assert) {
assert.expect(1);

let queryParams = buildQueryParams({ foo: null });

return this.visit('/').then(() => {
let expectedURL = this.routerService.urlFor('parent.child', queryParams);

assert.equal('/child', expectedURL);
});
}

['@test RouterService#urlFor returns URL for simple route with undefined query params'](assert) {
assert.expect(1);

let queryParams = buildQueryParams({ foo: undefined });

return this.visit('/').then(() => {
let expectedURL = this.routerService.urlFor('parent.child', queryParams);

assert.equal('/child', expectedURL);
});
}

['@test RouterService#urlFor returns URL for simple route with dynamic segments and basic query params'](assert) {
assert.expect(1);

let queryParams = buildQueryParams({ foo: 'bar' });

return this.visit('/').then(() => {
let expectedURL = this.routerService.urlFor('dynamic', { id: 1 }, queryParams);

assert.equal('/dynamic/1?foo=bar', expectedURL);
});
}

['@test RouterService#urlFor returns URL for simple route with dynamic segments and array as query params'](assert) {
assert.expect(1);

let queryParams = buildQueryParams({ selectedItems: ['a', 'b', 'c'] });

return this.visit('/').then(() => {
let expectedURL = this.routerService.urlFor('dynamic', { id: 1 }, queryParams);

assert.equal('/dynamic/1?selectedItems[]=a&selectedItems[]=b&selectedItems[]=c', expectedURL);
});
}

['@test RouterService#urlFor returns URL for simple route with dynamic segments and null query params'](assert) {
assert.expect(1);

let queryParams = buildQueryParams({ foo: null });

return this.visit('/').then(() => {
let expectedURL = this.routerService.urlFor('dynamic', { id: 1 }, queryParams);

assert.equal('/dynamic/1', expectedURL);
});
}

['@test RouterService#urlFor returns URL for simple route with dynamic segments and undefined query params'](assert) {
assert.expect(1);

let queryParams = buildQueryParams({ foo: undefined });

return this.visit('/').then(() => {
let expectedURL = this.routerService.urlFor('dynamic', { id: 1 }, queryParams);

assert.equal('/dynamic/1', expectedURL);
});
}

['@test RouterService#urlFor correctly transitions to route via generated path'](assert) {
assert.expect(1);

let expectedURL;

return this.visit('/')
.then(() => {
expectedURL = this.routerService.urlFor('parent.child');

return this.routerService.transitionTo(expectedURL);
})
.then(() => {
assert.equal(expectedURL, this.routerService.get('currentURL'));
});
}

['@test RouterService#urlFor correctly transitions to route via generated path with dynamic segments'](assert) {
assert.expect(1);

let expectedURL;
let dynamicModel = { id: 1 };

this.registerRoute('dynamic', Route.extend({
model() {
return dynamicModel;
}
}));

return this.visit('/')
.then(() => {
expectedURL = this.routerService.urlFor('dynamic', dynamicModel);

return this.routerService.transitionTo(expectedURL);
})
.then(() => {
assert.equal(expectedURL, this.routerService.get('currentURL'));
});
}

['@test RouterService#urlFor correctly transitions to route via generated path with query params'](assert) {
assert.expect(1);

let expectedURL;
let actualURL;
let queryParams = buildQueryParams({ foo: 'bar' });

return this.visit('/')
.then(() => {
expectedURL = this.routerService.urlFor('parent.child', queryParams);

return this.routerService.transitionTo(expectedURL);
})
.then(() => {
actualURL = `${this.routerService.get('currentURL')}?foo=bar`;

assert.equal(expectedURL, actualURL);
});
}

['@test RouterService#urlFor correctly transitions to route via generated path with dynamic segments and query params'](assert) {
assert.expect(1);

let expectedURL;
let actualURL;
let queryParams = buildQueryParams({ foo: 'bar' });
let dynamicModel = { id: 1 };

this.registerRoute('dynamic', Route.extend({
model() {
return dynamicModel;
}
}));

return this.visit('/')
.then(() => {
expectedURL = this.routerService.urlFor('dynamic', dynamicModel, queryParams);

return this.routerService.transitionTo(expectedURL);
})
.then(() => {
actualURL = `${this.routerService.get('currentURL')}?foo=bar`;

assert.equal(expectedURL, actualURL);
});
}
});
}
2 changes: 1 addition & 1 deletion packages/internal-test-helpers/lib/test-cases/router.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default class RouterTestCase extends ApplicationTestCase {
this.route('sister');
this.route('brother');
});
this.route('dynamic', { path: '/dynamic/:post_id' });
this.route('dynamic', { path: '/dynamic/:dynamic_id' });
});
}

Expand Down

0 comments on commit 431be5c

Please sign in to comment.