test(router): add Router regression test for hash location strategy (#40409)

This situation can probably happen only when using
`HashLocationStrategy` and by manually changing hash that triggers a route
guard that returns a new `UrlTree`. Then hash in the browser might not
match the current route because navigation was canceled, while hash in
the URL remained set by the user.

Related to #37048

PR Close #40409
This commit is contained in:
Martin Sikora 2021-01-10 19:55:39 +01:00 committed by Zach Arend
parent 4329ccae2c
commit 0d55d4557f
1 changed files with 50 additions and 1 deletions

View File

@ -6,7 +6,8 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {CommonModule} from '@angular/common'; import {CommonModule, Location} from '@angular/common';
import {SpyLocation} from '@angular/common/testing';
import {ChangeDetectionStrategy, ChangeDetectorRef, Component, NgModule, TemplateRef, Type, ViewChild, ViewContainerRef} from '@angular/core'; import {ChangeDetectionStrategy, ChangeDetectorRef, Component, NgModule, TemplateRef, Type, ViewChild, ViewContainerRef} from '@angular/core';
import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'; import {ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing';
import {Router} from '@angular/router'; import {Router} from '@angular/router';
@ -227,6 +228,54 @@ describe('Integration', () => {
expect(fixture.nativeElement.innerHTML).toContain('router-outlet'); expect(fixture.nativeElement.innerHTML).toContain('router-outlet');
expect(fixture.nativeElement.innerHTML).not.toContain('simple'); expect(fixture.nativeElement.innerHTML).not.toContain('simple');
})); }));
describe('useHash', () => {
it('should restore hash to match current route - #28561', fakeAsync(() => {
@Component({selector: 'root-cmp', template: `<router-outlet></router-outlet>`})
class RootCmp {
}
@Component({template: 'simple'})
class SimpleCmp {
}
TestBed.configureTestingModule({
imports: [RouterTestingModule.withRoutes([
{path: '', component: SimpleCmp},
{path: 'one', component: SimpleCmp, canActivate: ['returnRootUrlTree']}
])],
declarations: [SimpleCmp, RootCmp],
providers: [
{
provide: 'returnRootUrlTree',
useFactory: (router: Router) => () => {
return router.parseUrl('/');
},
deps: [Router]
},
],
});
const router = TestBed.inject(Router);
const location = TestBed.inject(Location) as SpyLocation;
router.navigateByUrl('/');
// Will setup location change listeners
const fixture = createRoot(router, RootCmp);
location.simulateHashChange('/one');
advance(fixture);
const BASE_ERROR_MESSAGE =
'This asserts current behavior, which is incorrect. When #28561 is fixed, it should be: ';
expect(location.path()).toEqual('/one', BASE_ERROR_MESSAGE + '/');
const urlChanges = ['replace: /', 'hash: /one'];
expect(location.urlChanges)
.toEqual(
urlChanges, BASE_ERROR_MESSAGE + JSON.stringify(urlChanges.concat('replace: /')));
}));
});
}); });
function advance<T>(fixture: ComponentFixture<T>): void { function advance<T>(fixture: ComponentFixture<T>): void {