From 7a9e383aac01bfe36e0c736c4869c6e3cd670eaa Mon Sep 17 00:00:00 2001 From: Chris Thielen Date: Tue, 16 Aug 2016 15:54:11 -0500 Subject: [PATCH] feat(Transition): expose the transition rejection reason as `Transition.error()` Closes #2866 --- src/transition/transition.ts | 16 ++++++++++++---- test/core/transitionSpec.ts | 13 +++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/transition/transition.ts b/src/transition/transition.ts index 821690bd3..bf945f080 100644 --- a/src/transition/transition.ts +++ b/src/transition/transition.ts @@ -58,6 +58,8 @@ export class Transition implements IHookRegistry { /** @hidden */ private _deferred = services.$q.defer(); + /** @hidden */ + private _error: any; /** * This promise is resolved or rejected based on the outcome of the Transition. * @@ -156,7 +158,7 @@ export class Transition implements IHookRegistry { /** * Determines whether two transitions are equivalent. */ - is(compare: (Transition|{to: any, from: any})): boolean { + is(compare: (Transition|{to?: any, from?: any})): boolean { if (compare instanceof Transition) { // TODO: Also compare parameters return this.is({ to: compare.$to().name, from: compare.$from().name }); @@ -474,6 +476,7 @@ export class Transition implements IHookRegistry { trace.traceError(reason, this); this.success = false; this._deferred.reject(reason); + this._error = reason; runSynchronousHooks(hookBuilder.getOnErrorHooks(), true); }; @@ -499,13 +502,16 @@ export class Transition implements IHookRegistry { * @returns true if the Transition is valid */ valid() { - return !this.error(); + return !this.error() || this.success !== undefined; } /** - * The reason the Transition is invalid + * The Transition error reason. + * + * If the transition is invalid (and could not be run), returns the reason the transition is invalid. + * If the transition was valid and ran, but was not successful, returns the reason the transition failed. * - * @returns an error message explaining why the transition is invalid + * @returns an error message explaining why the transition is invalid, or the reason the transition failed. */ error() { let state: State = this.$to(); @@ -514,6 +520,8 @@ export class Transition implements IHookRegistry { return `Cannot transition to abstract state '${state.name}'`; if (!Param.validates(state.parameters(), this.params())) return `Param values not valid for state '${state.name}'`; + if (this.success === false) + return this._error; } /** diff --git a/test/core/transitionSpec.ts b/test/core/transitionSpec.ts index 52127b907..37dd9ad78 100644 --- a/test/core/transitionSpec.ts +++ b/test/core/transitionSpec.ts @@ -343,6 +343,19 @@ describe('transition', function () { })); }); + // Test for #2866 + it('should have access to the failure reason in transition.error().', ((done) => { + let error = new Error("oops!"); + let transError; + $transitions.onEnter({ from: "A", entering: "C" }, function() { throw error; }); + $transitions.onError({ }, function(trans) { transError = trans.error(); }); + + Promise.resolve() + .then(goFail("A", "D")) + .then(() => expect(transError).toBe(error)) + .then(done); + })); + it("return value of 'false' should reject the transition with ABORT status", ((done) => { var states = [], rejection, transition = makeTransition("", "D"); $transitions.onEnter({ entering: "*" }, function(trans, state) { states.push(state); });