@ -25,19 +25,27 @@ export class SpyLocation implements Location {
|
||||
/** @internal */
|
||||
_baseHref: string = '';
|
||||
/** @internal */
|
||||
_platformStrategy: LocationStrategy = null !;
|
||||
_platformStrategy: LocationStrategy = null!;
|
||||
/** @internal */
|
||||
_platformLocation: PlatformLocation = null !;
|
||||
_platformLocation: PlatformLocation = null!;
|
||||
/** @internal */
|
||||
_urlChangeListeners: ((url: string, state: unknown) => void)[] = [];
|
||||
|
||||
setInitialPath(url: string) { this._history[this._historyIndex].path = url; }
|
||||
setInitialPath(url: string) {
|
||||
this._history[this._historyIndex].path = url;
|
||||
}
|
||||
|
||||
setBaseHref(url: string) { this._baseHref = url; }
|
||||
setBaseHref(url: string) {
|
||||
this._baseHref = url;
|
||||
}
|
||||
|
||||
path(): string { return this._history[this._historyIndex].path; }
|
||||
path(): string {
|
||||
return this._history[this._historyIndex].path;
|
||||
}
|
||||
|
||||
getState(): unknown { return this._history[this._historyIndex].state; }
|
||||
getState(): unknown {
|
||||
return this._history[this._historyIndex].state;
|
||||
}
|
||||
|
||||
isCurrentPathEqualTo(path: string, query: string = ''): boolean {
|
||||
const givenPath = path.endsWith('/') ? path.substring(0, path.length - 1) : path;
|
||||
@ -115,7 +123,9 @@ export class SpyLocation implements Location {
|
||||
}
|
||||
onUrlChange(fn: (url: string, state: unknown) => void) {
|
||||
this._urlChangeListeners.push(fn);
|
||||
this.subscribe(v => { this._notifyUrlChangeListeners(v.url, v.state); });
|
||||
this.subscribe(v => {
|
||||
this._notifyUrlChangeListeners(v.url, v.state);
|
||||
});
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
@ -129,7 +139,9 @@ export class SpyLocation implements Location {
|
||||
return this._subject.subscribe({next: onNext, error: onThrow, complete: onReturn});
|
||||
}
|
||||
|
||||
normalize(url: string): string { return null !; }
|
||||
normalize(url: string): string {
|
||||
return null!;
|
||||
}
|
||||
}
|
||||
|
||||
class LocationState {
|
||||
|
@ -26,14 +26,18 @@ export class MockLocationStrategy extends LocationStrategy {
|
||||
/** @internal */
|
||||
_subject: EventEmitter<any> = new EventEmitter();
|
||||
private stateChanges: any[] = [];
|
||||
constructor() { super(); }
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
simulatePopState(url: string): void {
|
||||
this.internalPath = url;
|
||||
this._subject.emit(new _MockPopStateEvent(this.path()));
|
||||
}
|
||||
|
||||
path(includeHash: boolean = false): string { return this.internalPath; }
|
||||
path(includeHash: boolean = false): string {
|
||||
return this.internalPath;
|
||||
}
|
||||
|
||||
prepareExternalUrl(internal: string): string {
|
||||
if (internal.startsWith('/') && this.internalBaseHref.endsWith('/')) {
|
||||
@ -68,9 +72,13 @@ export class MockLocationStrategy extends LocationStrategy {
|
||||
this.urlChanges.push('replace: ' + externalUrl);
|
||||
}
|
||||
|
||||
onPopState(fn: (value: any) => void): void { this._subject.subscribe({next: fn}); }
|
||||
onPopState(fn: (value: any) => void): void {
|
||||
this._subject.subscribe({next: fn});
|
||||
}
|
||||
|
||||
getBaseHref(): string { return this.internalBaseHref; }
|
||||
getBaseHref(): string {
|
||||
return this.internalBaseHref;
|
||||
}
|
||||
|
||||
back(): void {
|
||||
if (this.urlChanges.length > 0) {
|
||||
@ -81,9 +89,13 @@ export class MockLocationStrategy extends LocationStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
forward(): void { throw 'not implemented'; }
|
||||
forward(): void {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
getState(): unknown { return this.stateChanges[(this.stateChanges.length || 1) - 1]; }
|
||||
getState(): unknown {
|
||||
return this.stateChanges[(this.stateChanges.length || 1) - 1];
|
||||
}
|
||||
}
|
||||
|
||||
class _MockPopStateEvent {
|
||||
|
@ -126,23 +126,41 @@ export class MockPlatformLocation implements PlatformLocation {
|
||||
}
|
||||
}
|
||||
|
||||
get hostname() { return this.urlChanges[0].hostname; }
|
||||
get protocol() { return this.urlChanges[0].protocol; }
|
||||
get port() { return this.urlChanges[0].port; }
|
||||
get pathname() { return this.urlChanges[0].pathname; }
|
||||
get search() { return this.urlChanges[0].search; }
|
||||
get hash() { return this.urlChanges[0].hash; }
|
||||
get state() { return this.urlChanges[0].state; }
|
||||
get hostname() {
|
||||
return this.urlChanges[0].hostname;
|
||||
}
|
||||
get protocol() {
|
||||
return this.urlChanges[0].protocol;
|
||||
}
|
||||
get port() {
|
||||
return this.urlChanges[0].port;
|
||||
}
|
||||
get pathname() {
|
||||
return this.urlChanges[0].pathname;
|
||||
}
|
||||
get search() {
|
||||
return this.urlChanges[0].search;
|
||||
}
|
||||
get hash() {
|
||||
return this.urlChanges[0].hash;
|
||||
}
|
||||
get state() {
|
||||
return this.urlChanges[0].state;
|
||||
}
|
||||
|
||||
|
||||
getBaseHrefFromDOM(): string { return this.baseHref; }
|
||||
getBaseHrefFromDOM(): string {
|
||||
return this.baseHref;
|
||||
}
|
||||
|
||||
onPopState(fn: LocationChangeListener): void {
|
||||
// No-op: a state stack is not implemented, so
|
||||
// no events will ever come.
|
||||
}
|
||||
|
||||
onHashChange(fn: LocationChangeListener): void { this.hashUpdate.subscribe(fn); }
|
||||
onHashChange(fn: LocationChangeListener): void {
|
||||
this.hashUpdate.subscribe(fn);
|
||||
}
|
||||
|
||||
get href(): string {
|
||||
let url = `${this.protocol}//${this.hostname}${this.port ? ':' + this.port : ''}`;
|
||||
@ -150,7 +168,9 @@ export class MockPlatformLocation implements PlatformLocation {
|
||||
return url;
|
||||
}
|
||||
|
||||
get url(): string { return `${this.pathname}${this.search}${this.hash}`; }
|
||||
get url(): string {
|
||||
return `${this.pathname}${this.search}${this.hash}`;
|
||||
}
|
||||
|
||||
private parseChanges(state: unknown, url: string, baseHref: string = '') {
|
||||
// When the `history.state` value is stored, it is always copied.
|
||||
@ -169,7 +189,9 @@ export class MockPlatformLocation implements PlatformLocation {
|
||||
this.urlChanges.unshift({...this.urlChanges[0], pathname, search, hash, state: parsedState});
|
||||
}
|
||||
|
||||
forward(): void { throw new Error('Not implemented'); }
|
||||
forward(): void {
|
||||
throw new Error('Not implemented');
|
||||
}
|
||||
|
||||
back(): void {
|
||||
const oldUrl = this.url;
|
||||
@ -178,13 +200,15 @@ export class MockPlatformLocation implements PlatformLocation {
|
||||
const newHash = this.hash;
|
||||
|
||||
if (oldHash !== newHash) {
|
||||
scheduleMicroTask(() => this.hashUpdate.next({
|
||||
type: 'hashchange', state: null, oldUrl, newUrl: this.url
|
||||
} as LocationChangeEvent));
|
||||
scheduleMicroTask(
|
||||
() => this.hashUpdate.next(
|
||||
{type: 'hashchange', state: null, oldUrl, newUrl: this.url} as LocationChangeEvent));
|
||||
}
|
||||
}
|
||||
|
||||
getState(): unknown { return this.state; }
|
||||
getState(): unknown {
|
||||
return this.state;
|
||||
}
|
||||
}
|
||||
|
||||
export function scheduleMicroTask(cb: () => any) {
|
||||
|
Reference in New Issue
Block a user