From 63b9c778499fe3f9110a3626087f7a3632abe5a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Krysiak?= Date: Tue, 22 Mar 2016 20:29:22 +0100 Subject: [PATCH] feat: #153 - Passing state parameters inside redirectTo Huge thanks for @nanarth for his contribution and support with implementing this feature. --- src/core/permissionModule.js | 4 +- src/models/PermissionMap.js | 25 ++++- .../PermissionMap/redirectToParam.test.js | 103 +++++++++++++++++- 3 files changed, 121 insertions(+), 11 deletions(-) diff --git a/src/core/permissionModule.js b/src/core/permissionModule.js index 93c357b..996b40b 100644 --- a/src/core/permissionModule.js +++ b/src/core/permissionModule.js @@ -120,8 +120,8 @@ return permissions .resolveRedirectState(rejectedPermission) - .then(function (redirectStateName) { - $state.go(redirectStateName, toParams); + .then(function (redirect) { + $state.go(redirect.state, redirect.params, redirect.options); }); }) .finally(function () { diff --git a/src/models/PermissionMap.js b/src/models/PermissionMap.js index 6a44c65..f60c4eb 100644 --- a/src/models/PermissionMap.js +++ b/src/models/PermissionMap.js @@ -51,7 +51,9 @@ } if (angular.isString(this.redirectTo)) { - return $q.resolve(this.redirectTo); + return $q.resolve({ + state: this.redirectTo + }); } // If redirectTo state is not defined stay where you are @@ -70,10 +72,17 @@ return $q .when(redirectFunction.call(null, permission)) .then(function (redirectState) { - if (!angular.isString(redirectState)) { - throw new TypeError('When used "redirectTo" as function, returned value must be string with state name'); + if (angular.isString(redirectState)) { + return { + state: redirectState + }; + } + + if (angular.isObject(redirectState)) { + return redirectState; } - return redirectState; + + throw new TypeError('When used "redirectTo" as function, returned value must be string or object'); }); } @@ -100,9 +109,15 @@ return resolveFunctionRedirect(redirectState, permission); } - if (angular.isString(redirectState)) { + if (angular.isObject(redirectState)) { return $q.resolve(redirectState); } + + if (angular.isString(redirectState)) { + return $q.resolve({ + state: redirectState + }); + } } /** diff --git a/test/models/PermissionMap/redirectToParam.test.js b/test/models/PermissionMap/redirectToParam.test.js index 5287c74..3355ac3 100644 --- a/test/models/PermissionMap/redirectToParam.test.js +++ b/test/models/PermissionMap/redirectToParam.test.js @@ -154,7 +154,46 @@ describe('model: PermissionMap', function () { expect($state.current.name).not.toBe('default'); }); - it('should redirect based on results of rejected permission with function', function () { + it('should redirect based on results of rejected permission with redirection object', function () { + // GIVEN + var sut = { + state: 'redirected', + params: { + paramOne: 'one', + paramTwo: 'two' + }, + options: { + reload: true + } + }; + + $stateProvider + .state('redirect', { + data: { + permissions: { + only: ['denied'], + redirectTo: { + denied: sut, + default: 'default' + } + } + } + }) + .state('default', {}) + .state('redirected', {}); + + // WHEN + $state.go('redirect'); + $rootScope.$apply(); + + // THEN + expect($state.current.name).toBe('redirected'); + expect($state.current.name).not.toBe('default'); + expect($state.current.params).not.toBe(sut.params); + expect($state.current.params).not.toBe(sut.options); + }); + + it('should redirect based on results of rejected permission with function returning string', function () { // GIVEN $stateProvider .state('redirect', { @@ -182,6 +221,37 @@ describe('model: PermissionMap', function () { expect($state.current.name).not.toBe('default'); }); + + it('should redirect based on results of rejected permission with function returning object', function () { + // GIVEN + $stateProvider + .state('redirect', { + data: { + permissions: { + only: ['denied'], + redirectTo: { + denied: function () { + return { + state: 'redirected' + }; + }, + default: 'default' + } + } + } + }) + .state('default', {}) + .state('redirected', {}); + + // WHEN + $state.go('redirect'); + $rootScope.$apply(); + + // THEN + expect($state.current.name).toBe('redirected'); + expect($state.current.name).not.toBe('default'); + }); + it('should redirect based on results of rejected permission with promise', function () { // GIVEN $stateProvider @@ -212,7 +282,7 @@ describe('model: PermissionMap', function () { }); describe('used as function/promise', function () { - it('should throw error when function do not return state string', function () { + it('should throw error when function do not return state string or object', function () { // GIVEN var error; @@ -238,10 +308,10 @@ describe('model: PermissionMap', function () { } // THEN - expect(error.message).toBe('When used "redirectTo" as function, returned value must be string with state name'); + expect(error.message).toBe('When used "redirectTo" as function, returned value must be string or object'); }); - it('should redirect based on results of function', function () { + it('should redirect based on string returned results of function', function () { // GIVEN $stateProvider .state('redirect', { @@ -264,6 +334,31 @@ describe('model: PermissionMap', function () { expect($state.current.name).toBe('other'); }); + it('should redirect based on object returned results of function', function () { + // GIVEN + $stateProvider + .state('redirect', { + data: { + permissions: { + only: ['denied'], + redirectTo: function () { + return { + state: 'other' + }; + } + } + } + }) + .state('other', {}); + + // WHEN + $state.go('redirect'); + $rootScope.$apply(); + + // THEN + expect($state.current.name).toBe('other'); + }); + it('should redirect with promise based functions', function () { // GIVEN $stateProvider.state('redirect', {