Permalink
Browse files

feat(dialog-controller): pass close result to lifecycle hooks

BREAKING CHANGE - DialogController.prototype.error wraps the passed reason
in DialogCloseError
  • Loading branch information...
StrahilKazlachev committed May 7, 2017
1 parent 42ad7f3 commit 320504ca34b935527c1dff76fe889ec3e535a8bd
Showing with 46 additions and 14 deletions.
  1. +15 −0 src/dialog-close-error.ts
  2. +8 −6 src/dialog-controller.ts
  3. +4 −2 src/interfaces.ts
  4. +19 −6 test/unit/dialog-controller.spec.ts
View
@@ -0,0 +1,15 @@
/**
* The error is thrown when the dialog is closed with the `DialogController.prototype.error` method.
*/
export interface DialogCloseError extends Error {
reason: any;
}
/**
* @internal
*/
export function createDialogCloseError(reason: any): DialogCloseError {
const error = new Error() as DialogCloseError;
error.reason = reason;
return error;
}
View
@@ -3,6 +3,7 @@ import { Renderer } from './renderer';
import { DialogCancelableOperationResult, DialogCloseResult, DialogCancelResult } from './dialog-result';
import { DialogSettings } from './dialog-settings';
import { invokeLifecycle } from './lifecycle';
import { createDialogCloseError, DialogCloseError } from './dialog-close-error';
import { createDialogCancelError } from './dialog-cancel-error';
/**
@@ -45,8 +46,8 @@ export class DialogController {
/**
* @internal
*/
public releaseResources(dialogResult?: any): Promise<void> {
return invokeLifecycle(this.controller.viewModel || {}, 'deactivate', dialogResult)
public releaseResources(result: DialogCloseResult | DialogCloseError): Promise<void> {
return invokeLifecycle(this.controller.viewModel || {}, 'deactivate', result)
.then(() => this.renderer.hideDialog(this))
.then(() => { this.controller.unbind(); });
}
@@ -79,11 +80,12 @@ export class DialogController {
/**
* Closes the dialog with an error result.
* @param message An error message.
* @param reason A reason for closing with an error.
* @returns Promise An empty promise object.
*/
public error(message: any): Promise<void> {
return this.releaseResources().then(() => { this.reject(message); });
public error(reason: any): Promise<void> {
const closeError = createDialogCloseError(reason);
return this.releaseResources(closeError).then(() => { this.reject(closeError); });
}
/**
@@ -119,6 +121,6 @@ export class DialogController {
this.closePromise = undefined;
return Promise.reject(reason);
});
});
});
}
}
View
@@ -1,3 +1,5 @@
import { DialogCloseError } from './dialog-close-error';
import { DialogCloseResult } from './dialog-result';
/**
* An optional interface describing the dialog canActivate convention.
*/
@@ -29,7 +31,7 @@ export interface DialogComponentCanDeactivate {
* To cancel the closing of the dialog return false or a promise that resolves to false.
* Any other returned value is coerced to true.
*/
canDeactivate(): boolean | Promise<boolean> | PromiseLike<boolean>;
canDeactivate(result: DialogCloseResult): boolean | Promise<boolean> | PromiseLike<boolean>;
}
/**
@@ -39,5 +41,5 @@ export interface DialogComponentDeactivate {
/**
* Implement this hook if you want to perform custom logic when the dialog is being closed.
*/
deactivate(): void | Promise<void> | PromiseLike<void>;
deactivate(result: DialogCloseResult | DialogCloseError): void | Promise<void> | PromiseLike<void>;
}
@@ -1,7 +1,9 @@
import {DefaultDialogSettings} from '../../src/dialog-settings';
import {Renderer} from '../../src/renderer';
import {DialogController} from '../../src/dialog-controller';
import {DialogCancelError} from '../../src/dialog-cancel-error';
import { DialogCloseResult } from './../../src/dialog-result';
import { DialogComponentCanDeactivate } from './../../src/interfaces';
import { DefaultDialogSettings } from '../../src/dialog-settings';
import { Renderer } from '../../src/renderer';
import { DialogController } from '../../src/dialog-controller';
import { DialogCancelError } from '../../src/dialog-cancel-error';
describe('DialogController', () => {
let resolveCallback: jasmine.Spy;
@@ -43,13 +45,14 @@ describe('DialogController', () => {
});
describe('".releaseResources" should', () => {
const expectedDeactivateArg = {} as any;
beforeEach(async done => {
await _success(() => dialogController.releaseResources(), done);
await _success(() => dialogController.releaseResources(expectedDeactivateArg), done);
done();
});
it('call ".deactivate" on the view model', () => {
expect((dialogController.controller.viewModel as any).deactivate).toHaveBeenCalled();
expect((dialogController.controller.viewModel as any).deactivate).toHaveBeenCalledWith(expectedDeactivateArg);
});
it('call ".hideDialog" on the renderer', () => {
@@ -179,6 +182,16 @@ describe('DialogController', () => {
done();
});
it('call ".canDeactivate" with the close result', async done => {
const output = 'expected output';
await _success(() => dialogController.close(true, output), done);
const vm = dialogController.controller.viewModel as DialogComponentCanDeactivate;
const expectedResult = (vm.canDeactivate as jasmine.Spy).calls.argsFor(0)[0] as DialogCloseResult;
expect(expectedResult).toBeDefined();
expect(expectedResult.output).toBe(output);
done();
});
it('call the "resolve" callback on "cancel" when "rejectOnCancel" is "false"', async done => {
const expected = 'cancel output';
dialogController.settings.rejectOnCancel = false;

0 comments on commit 320504c

Please sign in to comment.