fix(common): adjust MockPlatformLocation to set state to new object (#30055)

When using the `history` API, setting a new `state` and retrieving it does not pass a `===` test to the object used to set the state. In other words, `history.state` is always a copy. This change makes the `MockPlatformLocation` behave in the same way.

PR Close #30055
This commit is contained in:
Jason Aden 2019-04-23 06:42:52 -07:00 committed by Ben Lesh
parent 3a9cf3f2ba
commit 825efa8721
2 changed files with 16 additions and 11 deletions

View File

@ -12,10 +12,10 @@ import {Subject} from 'rxjs';
function parseUrl(urlStr: string, baseHref: string) { function parseUrl(urlStr: string, baseHref: string) {
const verifyProtocol = /^((http[s]?|ftp):\/\/)/; const verifyProtocol = /^((http[s]?|ftp):\/\/)/;
let serverBase = ''; let serverBase;
// URL class requires full URL. If the URL string doesn't start with protocol, we need to add an // URL class requires full URL. If the URL string doesn't start with protocol, we need to add
// arbitrary base URL which can be removed afterward. // an arbitrary base URL which can be removed afterward.
if (!verifyProtocol.test(urlStr)) { if (!verifyProtocol.test(urlStr)) {
serverBase = 'http://empty.com/'; serverBase = 'http://empty.com/';
} }
@ -62,7 +62,7 @@ export class MockPlatformLocation implements PlatformLocation {
this.baseHref = config.appBaseHref || ''; this.baseHref = config.appBaseHref || '';
const parsedChanges = const parsedChanges =
this.parseChanges(null, config.startUrl || 'http://<empty>', this.baseHref); this.parseChanges(null, config.startUrl || 'http://<empty>/', this.baseHref);
this.urlChanges[0] = {...parsedChanges}; this.urlChanges[0] = {...parsedChanges};
} }
} }
@ -86,7 +86,9 @@ export class MockPlatformLocation implements PlatformLocation {
onHashChange(fn: LocationChangeListener): void { this.hashUpdate.subscribe(fn); } onHashChange(fn: LocationChangeListener): void { this.hashUpdate.subscribe(fn); }
get href(): string { get href(): string {
return `${this.protocol}//${this.hostname}${this.baseHref}${this.pathname === '/' ? '' : this.pathname}${this.search}${this.hash}`; let url = `${this.protocol}//${this.hostname}${this.port ? ':' + this.port : ''}`;
url += `${this.pathname === '/' ? '' : this.pathname}${this.search}${this.hash}`
return url;
} }
get url(): string { return `${this.pathname}${this.search}${this.hash}`; } get url(): string { return `${this.pathname}${this.search}${this.hash}`; }
@ -104,6 +106,8 @@ export class MockPlatformLocation implements PlatformLocation {
} }
private parseChanges(state: unknown, url: string, baseHref: string = '') { private parseChanges(state: unknown, url: string, baseHref: string = '') {
// When the `history.state` value is stored, it is always copied.
state = JSON.parse(JSON.stringify(state));
return {...parseUrl(url, baseHref), state}; return {...parseUrl(url, baseHref), state};
} }

View File

@ -1,21 +1,22 @@
{ {
"extends": "../tsconfig-build.json", "extends": "../tsconfig-build.json",
"compilerOptions": { "compilerOptions": {
"baseUrl": ".", "baseUrl": ".",
"rootDir": "../", "rootDir": "../",
"paths": { "paths": {
"@angular/core": ["../../../dist/packages/core"], "@angular/core": [
"@angular/common": ["../../../dist/packages/common"] "../../../dist/packages/core"
],
"@angular/common": [
"../../../dist/packages/common"
]
}, },
"outDir": "../../../dist/packages/common" "outDir": "../../../dist/packages/common"
}, },
"files": [ "files": [
"public_api.ts", "public_api.ts",
"../../../node_modules/zone.js/dist/zone.js.d.ts" "../../../node_modules/zone.js/dist/zone.js.d.ts"
], ],
"angularCompilerOptions": { "angularCompilerOptions": {
"annotateForClosureCompiler": true, "annotateForClosureCompiler": true,
"strictMetadataEmit": false, "strictMetadataEmit": false,
@ -23,4 +24,4 @@
"flatModuleOutFile": "testing.js", "flatModuleOutFile": "testing.js",
"flatModuleId": "@angular/common/testing" "flatModuleId": "@angular/common/testing"
} }
} }