116 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			116 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @license
							 | 
						||
| 
								 | 
							
								 * Copyright Google Inc. All Rights Reserved.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Use of this source code is governed by an MIT-style license that can be
							 | 
						||
| 
								 | 
							
								 * found in the LICENSE file at https://angular.io/license
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import {scheduler} from '../src/utils';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export interface MockScheduler {
							 | 
						||
| 
								 | 
							
								  schedule: (typeof scheduler)['schedule'];
							 | 
						||
| 
								 | 
							
								  scheduleBeforeRender: (typeof scheduler)['scheduleBeforeRender'];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export class AsyncMockScheduler implements MockScheduler {
							 | 
						||
| 
								 | 
							
								  private uid = 0;
							 | 
						||
| 
								 | 
							
								  private pendingBeforeRenderCallbacks: ({id: number, cb: () => void})[] = [];
							 | 
						||
| 
								 | 
							
								  private pendingDelayedCallbacks: ({id: number, cb: () => void, delay: number})[] = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  flushBeforeRender(): void {
							 | 
						||
| 
								 | 
							
								    while (this.pendingBeforeRenderCallbacks.length) {
							 | 
						||
| 
								 | 
							
								      const cb = this.pendingBeforeRenderCallbacks.shift() !.cb;
							 | 
						||
| 
								 | 
							
								      cb();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  reset(): void {
							 | 
						||
| 
								 | 
							
								    this.pendingBeforeRenderCallbacks.length = 0;
							 | 
						||
| 
								 | 
							
								    this.pendingDelayedCallbacks.length = 0;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  schedule(cb: () => void, delay: number): () => void {
							 | 
						||
| 
								 | 
							
								    const id = ++this.uid;
							 | 
						||
| 
								 | 
							
								    let idx = this.pendingDelayedCallbacks.length;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (let i = this.pendingDelayedCallbacks.length - 1; i >= 0; --i) {
							 | 
						||
| 
								 | 
							
								      if (this.pendingDelayedCallbacks[i].delay <= delay) {
							 | 
						||
| 
								 | 
							
								        idx = i + 1;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    this.pendingDelayedCallbacks.splice(idx, 0, {id, cb, delay});
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    return () => this.remove(id, this.pendingDelayedCallbacks);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  scheduleBeforeRender(cb: () => void): () => void {
							 | 
						||
| 
								 | 
							
								    const id = ++this.uid;
							 | 
						||
| 
								 | 
							
								    this.pendingBeforeRenderCallbacks.push({id, cb});
							 | 
						||
| 
								 | 
							
								    return () => this.remove(id, this.pendingBeforeRenderCallbacks);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  tick(ms: number): void {
							 | 
						||
| 
								 | 
							
								    this.flushBeforeRender();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    this.pendingDelayedCallbacks.forEach(item => item.delay -= ms);
							 | 
						||
| 
								 | 
							
								    this.pendingDelayedCallbacks = this.pendingDelayedCallbacks.filter(item => {
							 | 
						||
| 
								 | 
							
								      if (item.delay <= 0) {
							 | 
						||
| 
								 | 
							
								        const cb = item.cb;
							 | 
						||
| 
								 | 
							
								        cb();
							 | 
						||
| 
								 | 
							
								        return false;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      return true;
							 | 
						||
| 
								 | 
							
								    });
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  private remove(id: number, items: {id: number}[]): void {
							 | 
						||
| 
								 | 
							
								    for (let i = 0, ii = items.length; i < ii; ++i) {
							 | 
						||
| 
								 | 
							
								      if (items[i].id === id) {
							 | 
						||
| 
								 | 
							
								        items.splice(i, 1);
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export class SyncMockScheduler implements MockScheduler {
							 | 
						||
| 
								 | 
							
								  schedule(cb: () => void, delay: number): () => void {
							 | 
						||
| 
								 | 
							
								    cb();
							 | 
						||
| 
								 | 
							
								    return () => undefined;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  scheduleBeforeRender(cb: () => void): () => void {
							 | 
						||
| 
								 | 
							
								    cb();
							 | 
						||
| 
								 | 
							
								    return () => undefined;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export function installMockScheduler(isSync?: false): AsyncMockScheduler;
							 | 
						||
| 
								 | 
							
								export function installMockScheduler(isSync: true): SyncMockScheduler;
							 | 
						||
| 
								 | 
							
								export function installMockScheduler(isSync?: boolean): AsyncMockScheduler|SyncMockScheduler {
							 | 
						||
| 
								 | 
							
								  const mockScheduler = isSync ? new SyncMockScheduler() : new AsyncMockScheduler();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  Object.keys(scheduler).forEach((method: keyof typeof scheduler) => {
							 | 
						||
| 
								 | 
							
								    spyOn(scheduler, method).and.callFake(mockScheduler[method].bind(mockScheduler));
							 | 
						||
| 
								 | 
							
								  });
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return mockScheduler;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export function patchEnv() {
							 | 
						||
| 
								 | 
							
								  // This helper function is defined in `test-main.js`. See there for more details.
							 | 
						||
| 
								 | 
							
								  // (//window as any).$$patchInnerHtmlProp();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export function restoreEnv() {
							 | 
						||
| 
								 | 
							
								  // This helper function is defined in `test-main.js`. See there for more details.
							 | 
						||
| 
								 | 
							
								  //(window as any).$$restoreInnerHtmlProp();
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export function supportsCustomElements() {
							 | 
						||
| 
								 | 
							
								  // The browser does not natively support custom elements and is not polyfillable.
							 | 
						||
| 
								 | 
							
								  return typeof customElements !== 'undefined';
							 | 
						||
| 
								 | 
							
								}
							 |