Skip to content

Commit 652a760

Browse files
fix(redirect): Do not update URL after redirect with { location: false }
Closes angular-ui/ui-router#3317
1 parent afdeec2 commit 652a760

File tree

3 files changed

+34
-5
lines changed

3 files changed

+34
-5
lines changed

src/transition/interface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export interface TransitionOptions {
2323
*
2424
* - If `true`, it will update the url in the location bar.
2525
* - If `false`, it will not update the url in the location bar.
26-
* - If it is the string "`replace`", it will update the url and also replace the last history record.
26+
* - If it is the string `"replace"`, it will update the url and also replace the last history record.
2727
*
2828
* @default `true`
2929
*/

src/transition/transition.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { services } from '../common/coreservices';
88
import {
99
map, find, extend, mergeR, tail, omit, toJson, arrayTuples, unnestR, identity, anyTrueR
1010
} from '../common/common';
11-
import { isObject } from '../common/predicates';
11+
import { isObject, isUndefined } from '../common/predicates';
1212
import { prop, propEq, val, not, is } from '../common/hof';
1313
import { StateDeclaration, StateOrName } from '../state/interface';
1414
import {
@@ -517,8 +517,10 @@ export class Transition implements IHookRegistry {
517517

518518
let redirectOpts: TransitionOptions = { redirectedFrom: this, source: "redirect" };
519519
// If the original transition was caused by URL sync, then use { location: 'replace' }
520-
// on the new transition (unless the target state explicitly specifies location)
521-
if (this.options().source === 'url') {
520+
// on the new transition (unless the target state explicitly specifies location: false).
521+
// This causes the original url to be replaced with the url for the redirect target
522+
// so the original url disappears from the browser history.
523+
if (this.options().source === 'url' && targetState.options().location !== false) {
522524
redirectOpts.location = 'replace';
523525
}
524526

test/transitionSpec.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,9 +681,10 @@ describe('transition', function () {
681681
});
682682

683683
describe('redirected transition', () => {
684-
let urlRedirect;
684+
let urlRedirect, requiresAuth;
685685
beforeEach(() => {
686686
urlRedirect = router.stateRegistry.register({ name: 'urlRedirect', url: '/urlRedirect', redirectTo: 'redirectTarget' });
687+
requiresAuth = router.stateRegistry.register({ name: 'requiresAuth', url: '/requiresAuth' });
687688
router.stateRegistry.register({ name: 'redirectTarget', url: '/redirectTarget' });
688689
});
689690

@@ -703,6 +704,9 @@ describe('transition', function () {
703704
router.transitionService.onSuccess({}, () => {
704705
expect(transitionTo).toHaveBeenCalledWith(urlRedirect, {}, { inherit: true, source: 'url' });
705706

707+
expect(router.stateService.current.name).toBe('redirectTarget');
708+
expect(router.urlService.path()).toBe('/redirectTarget');
709+
706710
expect(url.calls.count()).toEqual(2);
707711
expect(url.calls.argsFor(0)).toEqual(["/urlRedirect"]);
708712
expect(url.calls.argsFor(1)).toEqual(["/redirectTarget", true]);
@@ -713,6 +717,29 @@ describe('transition', function () {
713717
router.urlService.url('/urlRedirect');
714718
});
715719

720+
it("should not replace the current url when redirecting a url sync with { location: false }", (done) => {
721+
router.transitionService.onBefore({ to: 'requiresAuth' }, trans => {
722+
return router.stateService.target('redirectTarget', null, { location: false })
723+
});
724+
725+
let url = spyOn(router.urlService, "url").and.callThrough();
726+
let transitionTo = spyOn(router.stateService, "transitionTo").and.callThrough();
727+
728+
router.transitionService.onSuccess({}, () => {
729+
expect(transitionTo).toHaveBeenCalledWith(requiresAuth, {}, { inherit: true, source: 'url' });
730+
731+
expect(router.globals.current.name).toBe("redirectTarget");
732+
expect(router.urlService.path()).toBe('/requiresAuth');
733+
734+
expect(url.calls.count()).toEqual(1);
735+
expect(url.calls.argsFor(0)).toEqual(["/requiresAuth"]);
736+
737+
done();
738+
});
739+
740+
router.urlService.url('/requiresAuth');
741+
});
742+
716743
});
717744
});
718745

0 commit comments

Comments
 (0)