parent
a9e7c90960
commit
fdffcaba9b
19
modules/angular2/src/router/helpers.ts
Normal file
19
modules/angular2/src/router/helpers.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import {isPresent} from 'angular2/src/facade/lang';
|
||||||
|
|
||||||
|
export function parseAndAssignParamString(splitToken: string, paramString: string,
|
||||||
|
keyValueMap: StringMap<string, string>): void {
|
||||||
|
var first = paramString[0];
|
||||||
|
if (first == '?' || first == ';') {
|
||||||
|
paramString = paramString.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
paramString.split(splitToken)
|
||||||
|
.forEach((entry) => {
|
||||||
|
var tuple = entry.split('=');
|
||||||
|
var key = tuple[0];
|
||||||
|
if (!isPresent(keyValueMap[key])) {
|
||||||
|
var value = tuple.length > 1 ? tuple[1] : true;
|
||||||
|
keyValueMap[key] = value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
@ -27,10 +27,9 @@ export class Instruction {
|
|||||||
reuse: boolean = false;
|
reuse: boolean = false;
|
||||||
specificity: number;
|
specificity: number;
|
||||||
|
|
||||||
private _params: StringMap<string, string>;
|
|
||||||
|
|
||||||
constructor(public component: any, public capturedUrl: string,
|
constructor(public component: any, public capturedUrl: string,
|
||||||
private _recognizer: PathRecognizer, public child: Instruction = null) {
|
private _recognizer: PathRecognizer, public child: Instruction = null,
|
||||||
|
private _params: StringMap<string, any> = null) {
|
||||||
this.accumulatedUrl = capturedUrl;
|
this.accumulatedUrl = capturedUrl;
|
||||||
this.specificity = _recognizer.specificity;
|
this.specificity = _recognizer.specificity;
|
||||||
if (isPresent(child)) {
|
if (isPresent(child)) {
|
||||||
|
@ -17,7 +17,7 @@ import {
|
|||||||
ListWrapper
|
ListWrapper
|
||||||
} from 'angular2/src/facade/collection';
|
} from 'angular2/src/facade/collection';
|
||||||
import {IMPLEMENTS} from 'angular2/src/facade/lang';
|
import {IMPLEMENTS} from 'angular2/src/facade/lang';
|
||||||
|
import {parseAndAssignParamString} from 'angular2/src/router/helpers';
|
||||||
import {escapeRegex} from './url';
|
import {escapeRegex} from './url';
|
||||||
import {RouteHandler} from './route_handler';
|
import {RouteHandler} from './route_handler';
|
||||||
|
|
||||||
@ -63,19 +63,6 @@ function normalizeString(obj: any): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseAndAssignMatrixParams(keyValueMap, matrixString) {
|
|
||||||
if (matrixString[0] == ';') {
|
|
||||||
matrixString = matrixString.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
matrixString.split(';').forEach((entry) => {
|
|
||||||
var tuple = entry.split('=');
|
|
||||||
var key = tuple[0];
|
|
||||||
var value = tuple.length > 1 ? tuple[1] : true;
|
|
||||||
keyValueMap[key] = value;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
class ContinuationSegment extends Segment {}
|
class ContinuationSegment extends Segment {}
|
||||||
|
|
||||||
class StaticSegment extends Segment {
|
class StaticSegment extends Segment {
|
||||||
@ -198,7 +185,10 @@ export class PathRecognizer {
|
|||||||
specificity: number;
|
specificity: number;
|
||||||
terminal: boolean = true;
|
terminal: boolean = true;
|
||||||
|
|
||||||
constructor(public path: string, public handler: RouteHandler) {
|
static matrixRegex: RegExp = RegExpWrapper.create('^(.*\/[^\/]+?)(;[^\/]+)?\/?$');
|
||||||
|
static queryRegex: RegExp = RegExpWrapper.create('^(.*\/[^\/]+?)(\\?[^\/]+)?$');
|
||||||
|
|
||||||
|
constructor(public path: string, public handler: RouteHandler, public isRoot: boolean = false) {
|
||||||
assertPath(path);
|
assertPath(path);
|
||||||
var parsed = parsePathString(path);
|
var parsed = parsePathString(path);
|
||||||
var specificity = parsed['specificity'];
|
var specificity = parsed['specificity'];
|
||||||
@ -228,16 +218,16 @@ export class PathRecognizer {
|
|||||||
var containsStarSegment =
|
var containsStarSegment =
|
||||||
segmentsLimit >= 0 && this.segments[segmentsLimit] instanceof StarSegment;
|
segmentsLimit >= 0 && this.segments[segmentsLimit] instanceof StarSegment;
|
||||||
|
|
||||||
var matrixString;
|
var paramsString, useQueryString = this.isRoot && this.terminal;
|
||||||
if (!containsStarSegment) {
|
if (!containsStarSegment) {
|
||||||
var matches =
|
var matches = RegExpWrapper.firstMatch(
|
||||||
RegExpWrapper.firstMatch(RegExpWrapper.create('^(.*\/[^\/]+?)(;[^\/]+)?\/?$'), url);
|
useQueryString ? PathRecognizer.queryRegex : PathRecognizer.matrixRegex, url);
|
||||||
if (isPresent(matches)) {
|
if (isPresent(matches)) {
|
||||||
url = matches[1];
|
url = matches[1];
|
||||||
matrixString = matches[2];
|
paramsString = matches[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
url = StringWrapper.replaceAll(url, /(;[^\/]+)(?=(\/|\Z))/g, '');
|
url = StringWrapper.replaceAll(url, /(;[^\/]+)(?=(\/|$))/g, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
var params = StringMapWrapper.create();
|
var params = StringMapWrapper.create();
|
||||||
@ -256,8 +246,11 @@ export class PathRecognizer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPresent(matrixString) && matrixString.length > 0 && matrixString[0] == ';') {
|
if (isPresent(paramsString) && paramsString.length > 0) {
|
||||||
parseAndAssignMatrixParams(params, matrixString);
|
var expectedStartingValue = useQueryString ? '?' : ';';
|
||||||
|
if (paramsString[0] == expectedStartingValue) {
|
||||||
|
parseAndAssignParamString(expectedStartingValue, paramsString, params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return params;
|
return params;
|
||||||
@ -266,6 +259,7 @@ export class PathRecognizer {
|
|||||||
generate(params: StringMap<string, any>): string {
|
generate(params: StringMap<string, any>): string {
|
||||||
var paramTokens = new TouchMap(params);
|
var paramTokens = new TouchMap(params);
|
||||||
var applyLeadingSlash = false;
|
var applyLeadingSlash = false;
|
||||||
|
var useQueryString = this.isRoot && this.terminal;
|
||||||
|
|
||||||
var url = '';
|
var url = '';
|
||||||
for (var i = 0; i < this.segments.length; i++) {
|
for (var i = 0; i < this.segments.length; i++) {
|
||||||
@ -279,12 +273,23 @@ export class PathRecognizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var unusedParams = paramTokens.getUnused();
|
var unusedParams = paramTokens.getUnused();
|
||||||
|
if (!StringMapWrapper.isEmpty(unusedParams)) {
|
||||||
|
url += useQueryString ? '?' : ';';
|
||||||
|
var paramToken = useQueryString ? '&' : ';';
|
||||||
|
var i = 0;
|
||||||
StringMapWrapper.forEach(unusedParams, (value, key) => {
|
StringMapWrapper.forEach(unusedParams, (value, key) => {
|
||||||
url += ';' + key;
|
if (i++ > 0) {
|
||||||
|
url += paramToken;
|
||||||
|
}
|
||||||
|
url += key;
|
||||||
|
if (!isPresent(value) && useQueryString) {
|
||||||
|
value = 'true';
|
||||||
|
}
|
||||||
if (isPresent(value)) {
|
if (isPresent(value)) {
|
||||||
url += '=' + value;
|
url += '=' + value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (applyLeadingSlash) {
|
if (applyLeadingSlash) {
|
||||||
url += '/';
|
url += '/';
|
||||||
|
@ -22,6 +22,7 @@ import {RouteHandler} from './route_handler';
|
|||||||
import {Route, AsyncRoute, Redirect, RouteDefinition} from './route_config_impl';
|
import {Route, AsyncRoute, Redirect, RouteDefinition} from './route_config_impl';
|
||||||
import {AsyncRouteHandler} from './async_route_handler';
|
import {AsyncRouteHandler} from './async_route_handler';
|
||||||
import {SyncRouteHandler} from './sync_route_handler';
|
import {SyncRouteHandler} from './sync_route_handler';
|
||||||
|
import {parseAndAssignParamString} from 'angular2/src/router/helpers';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* `RouteRecognizer` is responsible for recognizing routes for a single component.
|
* `RouteRecognizer` is responsible for recognizing routes for a single component.
|
||||||
@ -33,6 +34,8 @@ export class RouteRecognizer {
|
|||||||
redirects: Map<string, string> = new Map();
|
redirects: Map<string, string> = new Map();
|
||||||
matchers: Map<RegExp, PathRecognizer> = new Map();
|
matchers: Map<RegExp, PathRecognizer> = new Map();
|
||||||
|
|
||||||
|
constructor(public isRoot: boolean = false) {}
|
||||||
|
|
||||||
config(config: RouteDefinition): boolean {
|
config(config: RouteDefinition): boolean {
|
||||||
var handler;
|
var handler;
|
||||||
if (config instanceof Redirect) {
|
if (config instanceof Redirect) {
|
||||||
@ -44,7 +47,7 @@ export class RouteRecognizer {
|
|||||||
} else if (config instanceof AsyncRoute) {
|
} else if (config instanceof AsyncRoute) {
|
||||||
handler = new AsyncRouteHandler(config.loader);
|
handler = new AsyncRouteHandler(config.loader);
|
||||||
}
|
}
|
||||||
var recognizer = new PathRecognizer(config.path, handler);
|
var recognizer = new PathRecognizer(config.path, handler, this.isRoot);
|
||||||
MapWrapper.forEach(this.matchers, (matcher, _) => {
|
MapWrapper.forEach(this.matchers, (matcher, _) => {
|
||||||
if (recognizer.regex.toString() == matcher.regex.toString()) {
|
if (recognizer.regex.toString() == matcher.regex.toString()) {
|
||||||
throw new BaseException(
|
throw new BaseException(
|
||||||
@ -80,6 +83,17 @@ export class RouteRecognizer {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var queryParams = StringMapWrapper.create();
|
||||||
|
var queryString = '';
|
||||||
|
var queryIndex = url.indexOf('?');
|
||||||
|
if (queryIndex >= 0) {
|
||||||
|
queryString = url.substring(queryIndex + 1);
|
||||||
|
url = url.substring(0, queryIndex);
|
||||||
|
}
|
||||||
|
if (this.isRoot && queryString.length > 0) {
|
||||||
|
parseAndAssignParamString('&', queryString, queryParams);
|
||||||
|
}
|
||||||
|
|
||||||
MapWrapper.forEach(this.matchers, (pathRecognizer, regex) => {
|
MapWrapper.forEach(this.matchers, (pathRecognizer, regex) => {
|
||||||
var match;
|
var match;
|
||||||
if (isPresent(match = RegExpWrapper.firstMatch(regex, url))) {
|
if (isPresent(match = RegExpWrapper.firstMatch(regex, url))) {
|
||||||
@ -89,7 +103,12 @@ export class RouteRecognizer {
|
|||||||
matchedUrl = match[0];
|
matchedUrl = match[0];
|
||||||
unmatchedUrl = url.substring(match[0].length);
|
unmatchedUrl = url.substring(match[0].length);
|
||||||
}
|
}
|
||||||
solutions.push(new RouteMatch(pathRecognizer, matchedUrl, unmatchedUrl));
|
var params = null;
|
||||||
|
if (pathRecognizer.terminal && !StringMapWrapper.isEmpty(queryParams)) {
|
||||||
|
params = queryParams;
|
||||||
|
matchedUrl += '?' + queryString;
|
||||||
|
}
|
||||||
|
solutions.push(new RouteMatch(pathRecognizer, matchedUrl, unmatchedUrl, params));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -109,10 +128,22 @@ export class RouteRecognizer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class RouteMatch {
|
export class RouteMatch {
|
||||||
constructor(public recognizer: PathRecognizer, public matchedUrl: string,
|
private _params: StringMap<string, any>;
|
||||||
public unmatchedUrl: string) {}
|
private _paramsParsed: boolean = false;
|
||||||
|
|
||||||
params(): StringMap<string, string> { return this.recognizer.parseParams(this.matchedUrl); }
|
constructor(public recognizer: PathRecognizer, public matchedUrl: string,
|
||||||
|
public unmatchedUrl: string, p: StringMap<string, any> = null) {
|
||||||
|
this._params = isPresent(p) ? p : StringMapWrapper.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
params(): StringMap<string, any> {
|
||||||
|
if (!this._paramsParsed) {
|
||||||
|
this._paramsParsed = true;
|
||||||
|
StringMapWrapper.forEach(this.recognizer.parseParams(this.matchedUrl),
|
||||||
|
(value, key) => { StringMapWrapper.set(this._params, key, value); });
|
||||||
|
}
|
||||||
|
return this._params;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function configObjToHandler(config: any): RouteHandler {
|
function configObjToHandler(config: any): RouteHandler {
|
||||||
|
@ -37,13 +37,13 @@ export class RouteRegistry {
|
|||||||
/**
|
/**
|
||||||
* Given a component and a configuration object, add the route to this registry
|
* Given a component and a configuration object, add the route to this registry
|
||||||
*/
|
*/
|
||||||
config(parentComponent: any, config: RouteDefinition): void {
|
config(parentComponent: any, config: RouteDefinition, isRootLevelRoute: boolean = false): void {
|
||||||
config = normalizeRouteConfig(config);
|
config = normalizeRouteConfig(config);
|
||||||
|
|
||||||
var recognizer: RouteRecognizer = this._rules.get(parentComponent);
|
var recognizer: RouteRecognizer = this._rules.get(parentComponent);
|
||||||
|
|
||||||
if (isBlank(recognizer)) {
|
if (isBlank(recognizer)) {
|
||||||
recognizer = new RouteRecognizer();
|
recognizer = new RouteRecognizer(isRootLevelRoute);
|
||||||
this._rules.set(parentComponent, recognizer);
|
this._rules.set(parentComponent, recognizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ export class RouteRegistry {
|
|||||||
/**
|
/**
|
||||||
* Reads the annotations of a component and configures the registry based on them
|
* Reads the annotations of a component and configures the registry based on them
|
||||||
*/
|
*/
|
||||||
configFromComponent(component: any): void {
|
configFromComponent(component: any, isRootComponent: boolean = false): void {
|
||||||
if (!isType(component)) {
|
if (!isType(component)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -77,7 +77,8 @@ export class RouteRegistry {
|
|||||||
var annotation = annotations[i];
|
var annotation = annotations[i];
|
||||||
|
|
||||||
if (annotation instanceof RouteConfig) {
|
if (annotation instanceof RouteConfig) {
|
||||||
ListWrapper.forEach(annotation.configs, (config) => this.config(component, config));
|
ListWrapper.forEach(annotation.configs,
|
||||||
|
(config) => this.config(component, config, isRootComponent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,7 +121,8 @@ export class RouteRegistry {
|
|||||||
|
|
||||||
if (partialMatch.unmatchedUrl.length == 0) {
|
if (partialMatch.unmatchedUrl.length == 0) {
|
||||||
if (recognizer.terminal) {
|
if (recognizer.terminal) {
|
||||||
return new Instruction(componentType, partialMatch.matchedUrl, recognizer);
|
return new Instruction(componentType, partialMatch.matchedUrl, recognizer, null,
|
||||||
|
partialMatch.params());
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -87,8 +87,9 @@ export class Router {
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
config(definitions: List<RouteDefinition>): Promise<any> {
|
config(definitions: List<RouteDefinition>): Promise<any> {
|
||||||
definitions.forEach(
|
definitions.forEach((routeDefinition) => {
|
||||||
(routeDefinition) => { this.registry.config(this.hostComponent, routeDefinition); });
|
this.registry.config(this.hostComponent, routeDefinition, this instanceof RootRouter);
|
||||||
|
});
|
||||||
return this.renavigate();
|
return this.renavigate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -290,7 +291,7 @@ export class RootRouter extends Router {
|
|||||||
super(registry, pipeline, null, hostComponent);
|
super(registry, pipeline, null, hostComponent);
|
||||||
this._location = location;
|
this._location = location;
|
||||||
this._location.subscribe((change) => this.navigate(change['url']));
|
this._location.subscribe((change) => this.navigate(change['url']));
|
||||||
this.registry.configFromComponent(hostComponent);
|
this.registry.configFromComponent(hostComponent, true);
|
||||||
this.navigate(location.path());
|
this.navigate(location.path());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,6 +39,21 @@ export function main() {
|
|||||||
.toThrowError(`Path "hi//there" contains "//" which is not allowed in a route config.`);
|
.toThrowError(`Path "hi//there" contains "//" which is not allowed in a route config.`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('querystring params', () => {
|
||||||
|
it('should parse querystring params so long as the recognizer is a root', () => {
|
||||||
|
var rec = new PathRecognizer('/hello/there', mockRouteHandler, true);
|
||||||
|
var params = rec.parseParams('/hello/there?name=igor');
|
||||||
|
expect(params).toEqual({'name': 'igor'});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a combined map of parameters with the param expected in the URL path',
|
||||||
|
() => {
|
||||||
|
var rec = new PathRecognizer('/hello/:name', mockRouteHandler, true);
|
||||||
|
var params = rec.parseParams('/hello/paul?topic=success');
|
||||||
|
expect(params).toEqual({'name': 'paul', 'topic': 'success'});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('matrix params', () => {
|
describe('matrix params', () => {
|
||||||
it('should recognize a trailing matrix value on a path value and assign it to the params return value',
|
it('should recognize a trailing matrix value on a path value and assign it to the params return value',
|
||||||
() => {
|
() => {
|
||||||
|
@ -125,6 +125,66 @@ export function main() {
|
|||||||
.toThrowError('Route generator for \'name\' was not included in parameters passed.');
|
.toThrowError('Route generator for \'name\' was not included in parameters passed.');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('querystring params', () => {
|
||||||
|
it('should recognize querystring parameters within the URL path', () => {
|
||||||
|
var recognizer = new RouteRecognizer(true);
|
||||||
|
recognizer.config(new Route({path: 'profile/:name', component: DummyCmpA, as: 'user'}));
|
||||||
|
|
||||||
|
var solution = recognizer.recognize('/profile/matsko?comments=all')[0];
|
||||||
|
var params = solution.params();
|
||||||
|
expect(params['name']).toEqual('matsko');
|
||||||
|
expect(params['comments']).toEqual('all');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should generate and populate the given static-based route with querystring params',
|
||||||
|
() => {
|
||||||
|
var recognizer = new RouteRecognizer(true);
|
||||||
|
recognizer.config(
|
||||||
|
new Route({path: 'forum/featured', component: DummyCmpA, as: 'forum-page'}));
|
||||||
|
|
||||||
|
var params = StringMapWrapper.create();
|
||||||
|
params['start'] = 10;
|
||||||
|
params['end'] = 100;
|
||||||
|
|
||||||
|
var result = recognizer.generate('forum-page', params);
|
||||||
|
expect(result['url']).toEqual('forum/featured?start=10&end=100');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should place a higher priority on actual route params incase the same params are defined in the querystring',
|
||||||
|
() => {
|
||||||
|
var recognizer = new RouteRecognizer(true);
|
||||||
|
recognizer.config(new Route({path: 'profile/:name', component: DummyCmpA, as: 'user'}));
|
||||||
|
|
||||||
|
var solution = recognizer.recognize('/profile/yegor?name=igor')[0];
|
||||||
|
var params = solution.params();
|
||||||
|
expect(params['name']).toEqual('yegor');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should strip out any occurences of matrix params when querystring params are allowed',
|
||||||
|
() => {
|
||||||
|
var recognizer = new RouteRecognizer(true);
|
||||||
|
recognizer.config(new Route({path: '/home', component: DummyCmpA, as: 'user'}));
|
||||||
|
|
||||||
|
var solution = recognizer.recognize('/home;showAll=true;limit=100?showAll=false')[0];
|
||||||
|
var params = solution.params();
|
||||||
|
|
||||||
|
expect(params['showAll']).toEqual('false');
|
||||||
|
expect(params['limit']).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should strip out any occurences of matrix params as input data', () => {
|
||||||
|
var recognizer = new RouteRecognizer(true);
|
||||||
|
recognizer.config(new Route({path: '/home/:subject', component: DummyCmpA, as: 'user'}));
|
||||||
|
|
||||||
|
var solution = recognizer.recognize('/home/zero;one=1?two=2')[0];
|
||||||
|
var params = solution.params();
|
||||||
|
|
||||||
|
expect(params['subject']).toEqual('zero');
|
||||||
|
expect(params['one']).toBeFalsy();
|
||||||
|
expect(params['two']).toEqual('2');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('matrix params', () => {
|
describe('matrix params', () => {
|
||||||
it('should recognize matrix parameters within the URL path', () => {
|
it('should recognize matrix parameters within the URL path', () => {
|
||||||
var recognizer = new RouteRecognizer();
|
var recognizer = new RouteRecognizer();
|
||||||
@ -199,6 +259,40 @@ export function main() {
|
|||||||
var result = recognizer.generate('profile-page', params);
|
var result = recognizer.generate('profile-page', params);
|
||||||
expect(result['url']).toEqual('hello/matsko');
|
expect(result['url']).toEqual('hello/matsko');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should place a higher priority on actual route params incase the same params are defined in the matrix params string',
|
||||||
|
() => {
|
||||||
|
var recognizer = new RouteRecognizer();
|
||||||
|
recognizer.config(new Route({path: 'profile/:name', component: DummyCmpA, as: 'user'}));
|
||||||
|
|
||||||
|
var solution = recognizer.recognize('/profile/yegor;name=igor')[0];
|
||||||
|
var params = solution.params();
|
||||||
|
expect(params['name']).toEqual('yegor');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should strip out any occurences of querystring params when matrix params are allowed',
|
||||||
|
() => {
|
||||||
|
var recognizer = new RouteRecognizer();
|
||||||
|
recognizer.config(new Route({path: '/home', component: DummyCmpA, as: 'user'}));
|
||||||
|
|
||||||
|
var solution = recognizer.recognize('/home;limit=100?limit=1000&showAll=true')[0];
|
||||||
|
var params = solution.params();
|
||||||
|
|
||||||
|
expect(params['showAll']).toBeFalsy();
|
||||||
|
expect(params['limit']).toEqual('100');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should strip out any occurences of matrix params as input data', () => {
|
||||||
|
var recognizer = new RouteRecognizer();
|
||||||
|
recognizer.config(new Route({path: '/home/:subject', component: DummyCmpA, as: 'user'}));
|
||||||
|
|
||||||
|
var solution = recognizer.recognize('/home/zero;one=1?two=2')[0];
|
||||||
|
var params = solution.params();
|
||||||
|
|
||||||
|
expect(params['subject']).toEqual('zero');
|
||||||
|
expect(params['one']).toEqual('1');
|
||||||
|
expect(params['two']).toBeFalsy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import {
|
|||||||
describe,
|
describe,
|
||||||
expect,
|
expect,
|
||||||
iit,
|
iit,
|
||||||
|
flushMicrotasks,
|
||||||
inject,
|
inject,
|
||||||
it,
|
it,
|
||||||
xdescribe,
|
xdescribe,
|
||||||
@ -21,7 +22,14 @@ import {DOCUMENT_TOKEN} from 'angular2/src/render/dom/dom_renderer';
|
|||||||
import {RouteConfig, Route, Redirect} from 'angular2/src/router/route_config_decorator';
|
import {RouteConfig, Route, Redirect} from 'angular2/src/router/route_config_decorator';
|
||||||
import {PromiseWrapper} from 'angular2/src/facade/async';
|
import {PromiseWrapper} from 'angular2/src/facade/async';
|
||||||
import {BaseException} from 'angular2/src/facade/lang';
|
import {BaseException} from 'angular2/src/facade/lang';
|
||||||
import {routerInjectables, Router, appBaseHrefToken, routerDirectives} from 'angular2/router';
|
import {
|
||||||
|
routerInjectables,
|
||||||
|
RouteParams,
|
||||||
|
Router,
|
||||||
|
appBaseHrefToken,
|
||||||
|
routerDirectives
|
||||||
|
} from 'angular2/router';
|
||||||
|
|
||||||
import {LocationStrategy} from 'angular2/src/router/location_strategy';
|
import {LocationStrategy} from 'angular2/src/router/location_strategy';
|
||||||
import {MockLocationStrategy} from 'angular2/src/mock/mock_location_strategy';
|
import {MockLocationStrategy} from 'angular2/src/mock/mock_location_strategy';
|
||||||
import {appComponentTypeToken} from 'angular2/src/core/application_tokens';
|
import {appComponentTypeToken} from 'angular2/src/core/application_tokens';
|
||||||
@ -112,6 +120,30 @@ export function main() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
// TODO: add a test in which the child component has bindings
|
// TODO: add a test in which the child component has bindings
|
||||||
|
|
||||||
|
describe('querystring params app', () => {
|
||||||
|
beforeEachBindings(
|
||||||
|
() => { return [bind(appComponentTypeToken).toValue(QueryStringAppCmp)]; });
|
||||||
|
|
||||||
|
it('should recognize and return querystring params with the injected RouteParams',
|
||||||
|
inject([AsyncTestCompleter, TestComponentBuilder], (async, tcb: TestComponentBuilder) => {
|
||||||
|
tcb.createAsync(QueryStringAppCmp)
|
||||||
|
.then((rootTC) => {
|
||||||
|
var router = rootTC.componentInstance.router;
|
||||||
|
router.subscribe((_) => {
|
||||||
|
rootTC.detectChanges();
|
||||||
|
|
||||||
|
expect(rootTC.nativeElement).toHaveText('qParam = search-for-something');
|
||||||
|
/*
|
||||||
|
expect(applicationRef.hostComponent.location.path())
|
||||||
|
.toEqual('/qs?q=search-for-something');*/
|
||||||
|
async.done();
|
||||||
|
});
|
||||||
|
router.navigate('/qs?q=search-for-something');
|
||||||
|
rootTC.detectChanges();
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,6 +173,20 @@ class HierarchyAppCmp {
|
|||||||
constructor(public router: Router, public location: LocationStrategy) {}
|
constructor(public router: Router, public location: LocationStrategy) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Component({selector: 'qs-cmp'})
|
||||||
|
@View({template: "qParam = {{q}}"})
|
||||||
|
class QSCmp {
|
||||||
|
q: string;
|
||||||
|
constructor(params: RouteParams) { this.q = params.get('q'); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({selector: 'app-cmp'})
|
||||||
|
@View({template: `<router-outlet></router-outlet>`, directives: routerDirectives})
|
||||||
|
@RouteConfig([new Route({path: '/qs', component: QSCmp})])
|
||||||
|
class QueryStringAppCmp {
|
||||||
|
constructor(public router: Router, public location: LocationStrategy) {}
|
||||||
|
}
|
||||||
|
|
||||||
@Component({selector: 'oops-cmp'})
|
@Component({selector: 'oops-cmp'})
|
||||||
@View({template: "oh no"})
|
@View({template: "oh no"})
|
||||||
class BrokenCmp {
|
class BrokenCmp {
|
||||||
|
@ -116,6 +116,27 @@ export function main() {
|
|||||||
expect(router.generate(['/firstCmp/secondCmp'])).toEqual('/first/second');
|
expect(router.generate(['/firstCmp/secondCmp'])).toEqual('/first/second');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('querstring params', () => {
|
||||||
|
it('should only apply querystring params if the given URL is on the root router and is terminal',
|
||||||
|
() => {
|
||||||
|
router.config([
|
||||||
|
new Route({path: '/hi/how/are/you', component: DummyComponent, as: 'greeting-url'})
|
||||||
|
]);
|
||||||
|
|
||||||
|
var path = router.generate(['/greeting-url', {'name': 'brad'}]);
|
||||||
|
expect(path).toEqual('/hi/how/are/you?name=brad');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should use parameters that are not apart of the route definition as querystring params',
|
||||||
|
() => {
|
||||||
|
router.config(
|
||||||
|
[new Route({path: '/one/two/:three', component: DummyComponent, as: 'number-url'})]);
|
||||||
|
|
||||||
|
var path = router.generate(['/number-url', {'three': 'three', 'four': 'four'}]);
|
||||||
|
expect(path).toEqual('/one/two/three?four=four');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('matrix params', () => {
|
describe('matrix params', () => {
|
||||||
it('should apply inline matrix params for each router path within the generated URL', () => {
|
it('should apply inline matrix params for each router path within the generated URL', () => {
|
||||||
router.config(
|
router.config(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user