KhodeN
5/30/2016 - 10:33 AM

mocks.ts

/// <reference path="./index.d.ts"/>

import { MockUtils } from './MockUtils';
import 'ngMockE2E';

let moduleName = 'stMocks';

angular.module(moduleName, ['ngMockE2E'])
	.service('$mockUtils', MockUtils)
	.constant('mockDelay', 0)
	.config(['$provide', 'mockDelay', function ($provide: ng.auto.IProvideService, mockDelay: number) {
		if ( !mockDelay ) {
			return;
		}
		$provide.decorator('$httpBackend', ($delegate: any) => {
			let proxy: any = (method: string,
									url: string,
									data: any,
									callback: Function,
									headers: any,
									timeout: number|ng.IPromise<void>,
									withCredentials: boolean) => {

				let interceptor = function () {
					let self = this;
					let _arguments = arguments;

					// для шаблонов задержку не надо
					if ( _.includes(url, 'html') ) {
						callback.apply(self, _arguments);
					} else {
						setTimeout(() => {
							// return result to the client AFTER delay
							callback.apply(self, _arguments);
						}, mockDelay);
					}
				};

				return $delegate.call(this, method, url, data, interceptor, headers, timeout, withCredentials);
			};
			for (let key in $delegate) {
				if ( $delegate.hasOwnProperty(key) ) {
					proxy[key] = $delegate[key];
				}
			}
			return proxy;
		});
	}])
	.run(['$httpBackend', ($httpBackend: ng.IHttpBackendService) => {

		// в этом разделе хакается $httpBackend, добавляется логирование запросов и ответов
		// в код можно не лазить, править не нужно, just works
		function logResult(result: any, args: any, status: number) {
			let $log: any = console;
			let method = args[0];
			let url = args[1];
			let data = args[2];
			let headers = args[3];
			$log.groupCollapsed('[' + method + '] ' + decodeURI(url));

			$log.log('input:', data !== undefined ? JSON.parse(data) : undefined);

			if ( angular.isArray(result) ) {
				$log.log('output:');
				if ( _.isFunction($log.table) ) {
					$log.table(result);
				}
				$log.dir(result);
			} else {
				$log.log('output (' + status + '):', result);
			}

			$log.log('headers:', headers);

			$log.groupEnd();
		}

		let createResponse = (status: number|Function, data: any, headers: any, statusText: string) => {
			let result: Function;
			if ( angular.isFunction(status) ) {
				result = <Function>status;
			} else {
				result = () => angular.isNumber(status) ?
					[status, data, headers, statusText] :
					[200, status, data];
			}
			return function () {
				let response = result.apply(undefined, arguments);
				logResult(response[1], arguments, response[0]);
				return response;
			};
		};

		// monkey-patching для поддержки логирования в консоль результатов запросов
		_.forEach(['whenGET', 'whenPOST', 'whenPUT', 'whenDELETE'], (method: string) => {
			(<any>$httpBackend)[method] = _.wrap((<any>$httpBackend)[method],
				(f: Function, method_: string, url: string, inputData: any, headers: () => any) => {
					let result = f(method_, url, inputData, headers);

					result.respond = _.wrap(result.respond,
						(respond: Function,
						 status: number,
						 data: any,
						 headers_: () => any,
						 statusText: string) => {
							let generator = createResponse(status, data, headers_, statusText);
							respond(generator);
						});
					return result;
				});
		});
	}])
	.run(['$httpBackend', '$mockUtils', ($httpBackend: ng.IHttpBackendService, $mockUtils: mocks.IMockUtils) => {
		// шаблоны всегда грузим с сервера
		$httpBackend.whenGET(/\.html$/).passThrough();
	}]);

export = moduleName;