UNPKG

web-atoms-mvvm

Version:

MVVM, REST Json Service, Message Subscriptions for Web Atoms

208 lines (176 loc) 6.92 kB
namespace WebAtoms { export type __windowType = (string | (new () => any)); export type __windowRegistration = { windowType: __windowType, action: (vm:AtomViewModel) => any }; export class MockConfirmViewModel extends AtomWindowViewModel { message: string; title: string; } /** * Mock of WindowService for unit tests * @export * @class MockWindowService * @extends {WebAtoms.WindowService} */ export class MockWindowService extends WebAtoms.WindowService { /** * DI resolved instance of MockWindowService (WindowService) * @readonly * @static * @type {MockWindowService} * @memberof MockWindowService */ static get instance(): MockWindowService{ var d:WindowService = WebAtoms.DI.resolve(WindowService); if(d instanceof MockWindowService) { return d as MockWindowService; } throw new Error("MockWindowService not yet setup"); } /** * Registers new MockWindowService * @static * @memberof MockWindowService */ static register():void { WebAtoms.DI.push(WindowService, new MockWindowService()); } /** * Internal usage * @param {string} msg * @param {string} [title] * @returns {Promise<any>} * @memberof MockWindowService */ alert(msg:string, title?:string):Promise<any> { var mvm:MockConfirmViewModel = new MockConfirmViewModel(); mvm.message = msg; mvm.title = title; return this.openWindow(`__AlertWindow_${msg}`, mvm ); } /** * Internal usage * @param {string} msg * @param {string} [title] * @returns {Promise<boolean>} * @memberof MockWindowService */ confirm(msg:string, title?:string):Promise<boolean> { var mvm:MockConfirmViewModel = new MockConfirmViewModel(); mvm.message = msg; mvm.title = title; return this.openWindow(`__ConfirmWindow_${msg}`, mvm ); } /** * Internal usage * @template T * @param {__windowType} c * @param {AtomViewModel} vm * @returns {Promise<T>} * @memberof MockWindowService */ openPopup<T>(c: __windowType, vm: AtomViewModel ): Promise<T> { return this.openWindow(c, vm); } /** * Internal usage * @template T * @param {__windowType} c * @param {AtomViewModel} vm * @returns {Promise<T>} * @memberof MockWindowService */ openWindow<T>(c: __windowType, vm: AtomViewModel ): Promise<T> { return new Promise((resolve,reject)=> { var w:any = this.windowStack.find(x => x.windowType === c); if(!w) { var ex:Error = new Error(`No window registered for ${c}`); reject(ex); return; } setTimeout(()=> { try { resolve(w.action(vm)); }catch(e) { reject(e); } },5); }); } private windowStack:Array<__windowRegistration> = []; /** * Call this method before any method that should expect an alert. * You can add many alerts, but each expected alert will only be called * once. * @param {string} msg * @returns {AtomDisposable} * @memberof MockWindowService */ expectAlert(msg:string):AtomDisposable { return this.expectWindow(`__AlertWindow_${msg}`, vm => true); } /** * Call this method before any method that should expect a confirm. * You can add many confirms, but each expected confirm will only be called * once. * @param {string} msg * @param {(vm:MockConfirmViewModel) => boolean} action * @returns {AtomDisposable} * @memberof MockWindowService */ expectConfirm(msg:string, action: (vm:MockConfirmViewModel) => boolean):AtomDisposable { return this.expectWindow(`__ConfirmWindow_${msg}`, action); } /** * Call this method before any method that should expect a window of given type. * Each window will only be used once and return value in windowAction will be * resolved in promise created by openWindow call. * @template TViewModel * @param {__windowType} windowType * @param {(vm:TViewModel) => any} windowAction * @param {number} [maxDelay=10000] * @returns {AtomDisposable} * @memberof MockWindowService */ expectPopup<TViewModel extends AtomViewModel>( popupType: __windowType, windowAction: (vm:TViewModel) => any): AtomDisposable { return this.expectWindow(popupType, windowAction); } /** * Call this method before any method that should expect a window of given type. * Each window will only be used once and return value in windowAction will be * resolved in promise created by openWindow call. * @template TViewModel * @param {__windowType} windowType * @param {(vm:TViewModel) => any} windowAction * @param {number} [maxDelay=10000] * @returns {AtomDisposable} * @memberof MockWindowService */ expectWindow<TViewModel extends AtomViewModel>( windowType: __windowType , windowAction: (vm:TViewModel) => any): AtomDisposable { var registration:any = { windowType: windowType, action: windowAction }; registration.action = (vm:TViewModel) => { this.removeRegistration(registration); return windowAction(vm); }; this.windowStack.push(registration); return new DisposableAction(()=> { this.removeRegistration(registration); }); } removeRegistration(r:__windowRegistration):void { this.windowStack = this.windowStack.filter(x => x !== r); } public assert():void { if(!this.windowStack.length) { return; } throw new Error(`Expected windows did not open ${this.windowStack.map(x=>x.windowType).join(",")}`); } } }