diff --git a/circle.yml b/circle.yml
index 599249d254..3316522162 100644
--- a/circle.yml
+++ b/circle.yml
@@ -17,7 +17,7 @@ dependencies:
test:
override:
- - echo "No tests are written at the moment. But we will attempt to build the library with the latest changes."
+ - npm test
- npm run build
deployment:
diff --git a/karma.conf.ts b/karma.conf.ts
new file mode 100644
index 0000000000..da215d038e
--- /dev/null
+++ b/karma.conf.ts
@@ -0,0 +1,60 @@
+const WATCH = process.argv.indexOf('--watch') > -1;
+
+module.exports = config => {
+ config.set({
+
+ // base path that will be used to resolve all patterns (eg. files, exclude)
+ basePath: './',
+
+ // frameworks to use
+ // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
+ frameworks: ['jasmine', 'browserify'],
+
+ // list of files / patterns to load in the browser
+ files: [
+ 'test/**/*.spec.ts'
+ ],
+
+ // preprocess matching files before serving them to the browser
+ // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
+ preprocessors: {
+ 'test/**/*.spec.ts': ['browserify']
+ },
+
+ browserify: {
+ plugin: [ 'tsify' ],
+ extensions: ['.js', '.ts']
+ },
+
+ phantomjsLauncher: {
+ // Have phantomjs exit if a ResourceError is encountered (useful if karma exits without killing phantom)
+ exitOnResourceError: true
+ },
+
+ // test results reporter to use
+ // possible values: 'dots', 'progress'
+ // available reporters: https://npmjs.org/browse/keyword/karma-reporter
+ reporters: ['dots'],
+
+ // web server port
+ port: 9876,
+
+ // enable / disable colors in the output (reporters and logs)
+ colors: true,
+
+ // level of logging
+ // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
+ logLevel: config.LOG_INFO,
+
+ // enable / disable watching file and executing tests whenever any file changes
+ autoWatch: WATCH,
+
+ // start these browsers
+ // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
+ browsers: ['PhantomJS'],
+
+ // Continuous Integration mode
+ // if true, Karma captures browsers, runs the tests and exits
+ singleRun: !WATCH
+ });
+};
diff --git a/package.json b/package.json
index b0c46e4422..feac394595 100644
--- a/package.json
+++ b/package.json
@@ -19,6 +19,7 @@
"decamelize": "^1.2.0",
"dgeni": "^0.4.2",
"dgeni-packages": "^0.10.18",
+ "es6-shim": "~0.35.1",
"glob": "^6.0.4",
"gulp": "^3.9.1",
"gulp-rename": "^1.2.2",
@@ -26,18 +27,27 @@
"gulp-tslint": "^5.0.0",
"gulp-uglify": "^1.5.4",
"ionic-gulp-tslint": "^1.0.0",
+ "jasmine-core": "~2.5.0",
+ "karma": "~1.2.0",
+ "karma-browserify": "~5.1.0",
+ "karma-jasmine": "~1.0.2",
+ "karma-phantomjs-launcher": "~1.0.2",
"lodash": "3.10.1",
"minimist": "^1.1.3",
"mkdirp": "^0.5.1",
"node-html-encoder": "0.0.2",
"q": "1.4.1",
"semver": "^5.0.1",
+ "tsify": "~1.0.4",
"tslint": "^3.8.1",
"tslint-ionic-rules": "0.0.5",
- "typescript": "^1.8.10"
+ "typescript": "^1.8.10",
+ "watchify": "~3.7.0"
},
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1",
+ "test": "karma start",
+ "test:watch": "npm test -- --watch",
+ "start": "npm run test:watch",
"lint": "./node_modules/.bin/gulp lint",
"watch": "./node_modules/.bin/tsc -w",
"build": "npm run lint && npm run build:js && npm run build:bundle && npm run build:minify",
diff --git a/src/ng1.ts b/src/ng1.ts
index 384bd02f8f..615b3f6aec 100644
--- a/src/ng1.ts
+++ b/src/ng1.ts
@@ -7,14 +7,15 @@ declare var window;
*/
export function initAngular1(plugins) {
if (window.angular) {
- window.angular.module('ionic.native', []);
+
+ const ngModule = window.angular.module('ionic.native', []);
for (var name in plugins) {
let serviceName = '$cordova' + name;
let cls = plugins[name];
(function(serviceName, cls, name) {
- window.angular.module('ionic.native').service(serviceName, [function() {
+ ngModule.service(serviceName, [function() {
var funcs = window.angular.copy(cls);
funcs.prototype['name'] = name;
return funcs;
diff --git a/src/plugins/plugin.ts b/src/plugins/plugin.ts
index e0eaa1587e..810c9fcc20 100644
--- a/src/plugins/plugin.ts
+++ b/src/plugins/plugin.ts
@@ -3,8 +3,6 @@ import { Observable } from 'rxjs/Observable';
declare var window;
declare var Promise;
-declare var $q;
-
/**
* @private
diff --git a/test/plugin.spec.ts b/test/plugin.spec.ts
new file mode 100644
index 0000000000..3fd61f1597
--- /dev/null
+++ b/test/plugin.spec.ts
@@ -0,0 +1,141 @@
+///
+
+import 'es6-shim';
+import {Plugin, Cordova} from './../src/plugins/plugin';
+
+declare const window: any;
+window.plugins = {
+ test: {}
+};
+
+const testPluginMeta = {
+ plugin: 'cordova-plugin-test',
+ pluginRef: 'plugins.test',
+ repo: 'https://github.com/apache/cordova-plugin-test',
+ platforms: ['Android', 'iOS']
+};
+
+describe('plugin', () => {
+
+ it('sync method', () => {
+
+ window.plugins.test.syncMethod = () => {
+ return 'syncResult';
+ };
+
+ @Plugin(testPluginMeta)
+ class Test {
+
+ @Cordova({
+ sync: true
+ })
+ static syncMethod(arg: any): boolean { return; };
+
+ }
+
+ const spy = spyOn(window.plugins.test, 'syncMethod').and.callThrough();
+ const result = Test.syncMethod('foo');
+ expect(result).toEqual('syncResult');
+ expect(spy).toHaveBeenCalledWith('foo', undefined, undefined);
+
+ });
+
+ it('normal order callback', done => {
+
+ window.plugins.test.normalOrderCallback = (args, success, error) => {
+ success('normalOrderCallback');
+ };
+
+ @Plugin(testPluginMeta)
+ class Test {
+ @Cordova()
+ static normalOrderCallback(args: any): Promise { return; }
+ }
+
+ const spy = spyOn(window.plugins.test, 'normalOrderCallback').and.callThrough();
+ Test.normalOrderCallback('foo').then(result => {
+ expect(result).toEqual('normalOrderCallback');
+ done();
+ });
+ expect(spy.calls.mostRecent().args[0]).toEqual('foo');
+
+ });
+
+ it('reverse order callback', done => {
+
+ window.plugins.test.reverseOrderCallback = (success, error, args) => {
+ success('reverseOrderCallback');
+ };
+
+ @Plugin(testPluginMeta)
+ class Test {
+
+ @Cordova({
+ callbackOrder: 'reverse'
+ })
+ static reverseOrderCallback(args: any): Promise { return; }
+
+ }
+
+ const spy = spyOn(window.plugins.test, 'reverseOrderCallback').and.callThrough();
+ Test.reverseOrderCallback('foo').then(result => {
+ expect(result).toEqual('reverseOrderCallback');
+ done();
+ });
+ expect(spy.calls.mostRecent().args[2]).toEqual('foo');
+
+ });
+
+ it('node style callback', done => {
+
+ window.plugins.test.nodeStyleCallback = (args, done) => {
+ done(null, 'nodeStyleCallback');
+ };
+
+ @Plugin(testPluginMeta)
+ class Test {
+
+ @Cordova({
+ callbackStyle: 'node'
+ })
+ static nodeStyleCallback(args: any): Promise { return; }
+
+ }
+
+ const spy = spyOn(window.plugins.test, 'nodeStyleCallback').and.callThrough();
+ Test.nodeStyleCallback('foo').then(result => {
+ expect(result).toEqual('nodeStyleCallback');
+ done();
+ });
+ expect(spy.calls.mostRecent().args[0]).toEqual('foo');
+
+ });
+
+ it('object style callback', done => {
+
+ window.plugins.test.objectStyleCallback = (args, {success}) => {
+ success('objectStyleCallback');
+ };
+
+ @Plugin(testPluginMeta)
+ class Test {
+
+ @Cordova({
+ callbackStyle: 'object',
+ successName: 'success',
+ errorName: 'error'
+ })
+ static objectStyleCallback(args: any): Promise { return; }
+
+ }
+
+ const spy = spyOn(window.plugins.test, 'objectStyleCallback').and.callThrough();
+ Test.objectStyleCallback('foo').then(result => {
+ expect(result).toEqual('objectStyleCallback');
+ done();
+ });
+ expect(spy.calls.mostRecent().args[0]).toEqual('foo');
+
+ });
+
+});
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
index fc1c522253..be48d5b1bc 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -5,7 +5,8 @@
"sourceMap": true,
"declaration": true,
"experimentalDecorators": true,
- "outDir": "dist"
+ "outDir": "dist",
+ "moduleResolution": "node"
},
"files": [
"typings/es6-shim/es6-shim.d.ts",
diff --git a/typings.json b/typings.json
new file mode 100644
index 0000000000..dbbc9d62fd
--- /dev/null
+++ b/typings.json
@@ -0,0 +1,5 @@
+{
+ "globalDevDependencies": {
+ "jasmine": "registry:dt/jasmine#2.2.0+20160621224255"
+ }
+}
diff --git a/typings/globals/jasmine/index.d.ts b/typings/globals/jasmine/index.d.ts
new file mode 100644
index 0000000000..e81f5ace5d
--- /dev/null
+++ b/typings/globals/jasmine/index.d.ts
@@ -0,0 +1,502 @@
+// Generated by typings
+// Source: https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/c49913aa9ea419ea46c1c684e488cf2a10303b1a/jasmine/jasmine.d.ts
+declare function describe(description: string, specDefinitions: () => void): void;
+declare function fdescribe(description: string, specDefinitions: () => void): void;
+declare function xdescribe(description: string, specDefinitions: () => void): void;
+
+declare function it(expectation: string, assertion?: () => void, timeout?: number): void;
+declare function it(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void;
+declare function fit(expectation: string, assertion?: () => void, timeout?: number): void;
+declare function fit(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void;
+declare function xit(expectation: string, assertion?: () => void, timeout?: number): void;
+declare function xit(expectation: string, assertion?: (done: DoneFn) => void, timeout?: number): void;
+
+/** If you call the function pending anywhere in the spec body, no matter the expectations, the spec will be marked pending. */
+declare function pending(reason?: string): void;
+
+declare function beforeEach(action: () => void, timeout?: number): void;
+declare function beforeEach(action: (done: DoneFn) => void, timeout?: number): void;
+declare function afterEach(action: () => void, timeout?: number): void;
+declare function afterEach(action: (done: DoneFn) => void, timeout?: number): void;
+
+declare function beforeAll(action: () => void, timeout?: number): void;
+declare function beforeAll(action: (done: DoneFn) => void, timeout?: number): void;
+declare function afterAll(action: () => void, timeout?: number): void;
+declare function afterAll(action: (done: DoneFn) => void, timeout?: number): void;
+
+declare function expect(spy: Function): jasmine.Matchers;
+declare function expect(actual: any): jasmine.Matchers;
+
+declare function fail(e?: any): void;
+/** Action method that should be called when the async work is complete */
+interface DoneFn extends Function {
+ (): void;
+
+ /** fails the spec and indicates that it has completed. If the message is an Error, Error.message is used */
+ fail: (message?: Error|string) => void;
+}
+
+declare function spyOn(object: any, method: string): jasmine.Spy;
+
+declare function runs(asyncMethod: Function): void;
+declare function waitsFor(latchMethod: () => boolean, failureMessage?: string, timeout?: number): void;
+declare function waits(timeout?: number): void;
+
+declare namespace jasmine {
+
+ var clock: () => Clock;
+
+ function any(aclass: any): Any;
+ function anything(): Any;
+ function arrayContaining(sample: any[]): ArrayContaining;
+ function objectContaining(sample: any): ObjectContaining;
+ function createSpy(name: string, originalFn?: Function): Spy;
+ function createSpyObj(baseName: string, methodNames: any[]): any;
+ function createSpyObj(baseName: string, methodNames: any[]): T;
+ function pp(value: any): string;
+ function getEnv(): Env;
+ function addCustomEqualityTester(equalityTester: CustomEqualityTester): void;
+ function addMatchers(matchers: CustomMatcherFactories): void;
+ function stringMatching(str: string): Any;
+ function stringMatching(str: RegExp): Any;
+
+ interface Any {
+
+ new (expectedClass: any): any;
+
+ jasmineMatches(other: any): boolean;
+ jasmineToString(): string;
+ }
+
+ // taken from TypeScript lib.core.es6.d.ts, applicable to CustomMatchers.contains()
+ interface ArrayLike {
+ length: number;
+ [n: number]: T;
+ }
+
+ interface ArrayContaining {
+ new (sample: any[]): any;
+
+ asymmetricMatch(other: any): boolean;
+ jasmineToString(): string;
+ }
+
+ interface ObjectContaining {
+ new (sample: any): any;
+
+ jasmineMatches(other: any, mismatchKeys: any[], mismatchValues: any[]): boolean;
+ jasmineToString(): string;
+ }
+
+ interface Block {
+
+ new (env: Env, func: SpecFunction, spec: Spec): any;
+
+ execute(onComplete: () => void): void;
+ }
+
+ interface WaitsBlock extends Block {
+ new (env: Env, timeout: number, spec: Spec): any;
+ }
+
+ interface WaitsForBlock extends Block {
+ new (env: Env, timeout: number, latchFunction: SpecFunction, message: string, spec: Spec): any;
+ }
+
+ interface Clock {
+ install(): void;
+ uninstall(): void;
+ /** Calls to any registered callback are triggered when the clock is ticked forward via the jasmine.clock().tick function, which takes a number of milliseconds. */
+ tick(ms: number): void;
+ mockDate(date?: Date): void;
+ }
+
+ interface CustomEqualityTester {
+ (first: any, second: any): boolean;
+ }
+
+ interface CustomMatcher {
+ compare(actual: T, expected: T): CustomMatcherResult;
+ compare(actual: any, expected: any): CustomMatcherResult;
+ }
+
+ interface CustomMatcherFactory {
+ (util: MatchersUtil, customEqualityTesters: Array): CustomMatcher;
+ }
+
+ interface CustomMatcherFactories {
+ [index: string]: CustomMatcherFactory;
+ }
+
+ interface CustomMatcherResult {
+ pass: boolean;
+ message?: string;
+ }
+
+ interface MatchersUtil {
+ equals(a: any, b: any, customTesters?: Array): boolean;
+ contains(haystack: ArrayLike | string, needle: any, customTesters?: Array): boolean;
+ buildFailureMessage(matcherName: string, isNot: boolean, actual: any, ...expected: Array): string;
+ }
+
+ interface Env {
+ setTimeout: any;
+ clearTimeout: void;
+ setInterval: any;
+ clearInterval: void;
+ updateInterval: number;
+
+ currentSpec: Spec;
+
+ matchersClass: Matchers;
+
+ version(): any;
+ versionString(): string;
+ nextSpecId(): number;
+ addReporter(reporter: Reporter): void;
+ execute(): void;
+ describe(description: string, specDefinitions: () => void): Suite;
+ // ddescribe(description: string, specDefinitions: () => void): Suite; Not a part of jasmine. Angular team adds these
+ beforeEach(beforeEachFunction: () => void): void;
+ beforeAll(beforeAllFunction: () => void): void;
+ currentRunner(): Runner;
+ afterEach(afterEachFunction: () => void): void;
+ afterAll(afterAllFunction: () => void): void;
+ xdescribe(desc: string, specDefinitions: () => void): XSuite;
+ it(description: string, func: () => void): Spec;
+ // iit(description: string, func: () => void): Spec; Not a part of jasmine. Angular team adds these
+ xit(desc: string, func: () => void): XSpec;
+ compareRegExps_(a: RegExp, b: RegExp, mismatchKeys: string[], mismatchValues: string[]): boolean;
+ compareObjects_(a: any, b: any, mismatchKeys: string[], mismatchValues: string[]): boolean;
+ equals_(a: any, b: any, mismatchKeys: string[], mismatchValues: string[]): boolean;
+ contains_(haystack: any, needle: any): boolean;
+ addCustomEqualityTester(equalityTester: CustomEqualityTester): void;
+ addMatchers(matchers: CustomMatcherFactories): void;
+ specFilter(spec: Spec): boolean;
+ throwOnExpectationFailure(value: boolean): void;
+ }
+
+ interface FakeTimer {
+
+ new (): any;
+
+ reset(): void;
+ tick(millis: number): void;
+ runFunctionsWithinRange(oldMillis: number, nowMillis: number): void;
+ scheduleFunction(timeoutKey: any, funcToCall: () => void, millis: number, recurring: boolean): void;
+ }
+
+ interface HtmlReporter {
+ new (): any;
+ }
+
+ interface HtmlSpecFilter {
+ new (): any;
+ }
+
+ interface Result {
+ type: string;
+ }
+
+ interface NestedResults extends Result {
+ description: string;
+
+ totalCount: number;
+ passedCount: number;
+ failedCount: number;
+
+ skipped: boolean;
+
+ rollupCounts(result: NestedResults): void;
+ log(values: any): void;
+ getItems(): Result[];
+ addResult(result: Result): void;
+ passed(): boolean;
+ }
+
+ interface MessageResult extends Result {
+ values: any;
+ trace: Trace;
+ }
+
+ interface ExpectationResult extends Result {
+ matcherName: string;
+ passed(): boolean;
+ expected: any;
+ actual: any;
+ message: string;
+ trace: Trace;
+ }
+
+ interface Trace {
+ name: string;
+ message: string;
+ stack: any;
+ }
+
+ interface PrettyPrinter {
+
+ new (): any;
+
+ format(value: any): void;
+ iterateObject(obj: any, fn: (property: string, isGetter: boolean) => void): void;
+ emitScalar(value: any): void;
+ emitString(value: string): void;
+ emitArray(array: any[]): void;
+ emitObject(obj: any): void;
+ append(value: any): void;
+ }
+
+ interface StringPrettyPrinter extends PrettyPrinter {
+ }
+
+ interface Queue {
+
+ new (env: any): any;
+
+ env: Env;
+ ensured: boolean[];
+ blocks: Block[];
+ running: boolean;
+ index: number;
+ offset: number;
+ abort: boolean;
+
+ addBefore(block: Block, ensure?: boolean): void;
+ add(block: any, ensure?: boolean): void;
+ insertNext(block: any, ensure?: boolean): void;
+ start(onComplete?: () => void): void;
+ isRunning(): boolean;
+ next_(): void;
+ results(): NestedResults;
+ }
+
+ interface Matchers {
+
+ new (env: Env, actual: any, spec: Env, isNot?: boolean): any;
+
+ env: Env;
+ actual: any;
+ spec: Env;
+ isNot?: boolean;
+ message(): any;
+
+ toBe(expected: any, expectationFailOutput?: any): boolean;
+ toEqual(expected: any, expectationFailOutput?: any): boolean;
+ toMatch(expected: string | RegExp, expectationFailOutput?: any): boolean;
+ toBeDefined(expectationFailOutput?: any): boolean;
+ toBeUndefined(expectationFailOutput?: any): boolean;
+ toBeNull(expectationFailOutput?: any): boolean;
+ toBeNaN(): boolean;
+ toBeTruthy(expectationFailOutput?: any): boolean;
+ toBeFalsy(expectationFailOutput?: any): boolean;
+ toHaveBeenCalled(): boolean;
+ toHaveBeenCalledWith(...params: any[]): boolean;
+ toHaveBeenCalledTimes(expected: number): boolean;
+ toContain(expected: any, expectationFailOutput?: any): boolean;
+ toBeLessThan(expected: number, expectationFailOutput?: any): boolean;
+ toBeGreaterThan(expected: number, expectationFailOutput?: any): boolean;
+ toBeCloseTo(expected: number, precision?: any, expectationFailOutput?: any): boolean;
+ toThrow(expected?: any): boolean;
+ toThrowError(message?: string | RegExp): boolean;
+ toThrowError(expected?: new (...args: any[]) => Error, message?: string | RegExp): boolean;
+ not: Matchers;
+
+ Any: Any;
+ }
+
+ interface Reporter {
+ reportRunnerStarting(runner: Runner): void;
+ reportRunnerResults(runner: Runner): void;
+ reportSuiteResults(suite: Suite): void;
+ reportSpecStarting(spec: Spec): void;
+ reportSpecResults(spec: Spec): void;
+ log(str: string): void;
+ }
+
+ interface MultiReporter extends Reporter {
+ addReporter(reporter: Reporter): void;
+ }
+
+ interface Runner {
+
+ new (env: Env): any;
+
+ execute(): void;
+ beforeEach(beforeEachFunction: SpecFunction): void;
+ afterEach(afterEachFunction: SpecFunction): void;
+ beforeAll(beforeAllFunction: SpecFunction): void;
+ afterAll(afterAllFunction: SpecFunction): void;
+ finishCallback(): void;
+ addSuite(suite: Suite): void;
+ add(block: Block): void;
+ specs(): Spec[];
+ suites(): Suite[];
+ topLevelSuites(): Suite[];
+ results(): NestedResults;
+ }
+
+ interface SpecFunction {
+ (spec?: Spec): void;
+ }
+
+ interface SuiteOrSpec {
+ id: number;
+ env: Env;
+ description: string;
+ queue: Queue;
+ }
+
+ interface Spec extends SuiteOrSpec {
+
+ new (env: Env, suite: Suite, description: string): any;
+
+ suite: Suite;
+
+ afterCallbacks: SpecFunction[];
+ spies_: Spy[];
+
+ results_: NestedResults;
+ matchersClass: Matchers;
+
+ getFullName(): string;
+ results(): NestedResults;
+ log(arguments: any): any;
+ runs(func: SpecFunction): Spec;
+ addToQueue(block: Block): void;
+ addMatcherResult(result: Result): void;
+ expect(actual: any): any;
+ waits(timeout: number): Spec;
+ waitsFor(latchFunction: SpecFunction, timeoutMessage?: string, timeout?: number): Spec;
+ fail(e?: any): void;
+ getMatchersClass_(): Matchers;
+ addMatchers(matchersPrototype: CustomMatcherFactories): void;
+ finishCallback(): void;
+ finish(onComplete?: () => void): void;
+ after(doAfter: SpecFunction): void;
+ execute(onComplete?: () => void): any;
+ addBeforesAndAftersToQueue(): void;
+ explodes(): void;
+ spyOn(obj: any, methodName: string, ignoreMethodDoesntExist: boolean): Spy;
+ removeAllSpies(): void;
+ }
+
+ interface XSpec {
+ id: number;
+ runs(): void;
+ }
+
+ interface Suite extends SuiteOrSpec {
+
+ new (env: Env, description: string, specDefinitions: () => void, parentSuite: Suite): any;
+
+ parentSuite: Suite;
+
+ getFullName(): string;
+ finish(onComplete?: () => void): void;
+ beforeEach(beforeEachFunction: SpecFunction): void;
+ afterEach(afterEachFunction: SpecFunction): void;
+ beforeAll(beforeAllFunction: SpecFunction): void;
+ afterAll(afterAllFunction: SpecFunction): void;
+ results(): NestedResults;
+ add(suiteOrSpec: SuiteOrSpec): void;
+ specs(): Spec[];
+ suites(): Suite[];
+ children(): any[];
+ execute(onComplete?: () => void): void;
+ }
+
+ interface XSuite {
+ execute(): void;
+ }
+
+ interface Spy {
+ (...params: any[]): any;
+
+ identity: string;
+ and: SpyAnd;
+ calls: Calls;
+ mostRecentCall: { args: any[]; };
+ argsForCall: any[];
+ wasCalled: boolean;
+ }
+
+ interface SpyAnd {
+ /** By chaining the spy with and.callThrough, the spy will still track all calls to it but in addition it will delegate to the actual implementation. */
+ callThrough(): Spy;
+ /** By chaining the spy with and.returnValue, all calls to the function will return a specific value. */
+ returnValue(val: any): Spy;
+ /** By chaining the spy with and.returnValues, all calls to the function will return specific values in order until it reaches the end of the return values list. */
+ returnValues(...values: any[]): Spy;
+ /** By chaining the spy with and.callFake, all calls to the spy will delegate to the supplied function. */
+ callFake(fn: Function): Spy;
+ /** By chaining the spy with and.throwError, all calls to the spy will throw the specified value. */
+ throwError(msg: string): Spy;
+ /** When a calling strategy is used for a spy, the original stubbing behavior can be returned at any time with and.stub. */
+ stub(): Spy;
+ }
+
+ interface Calls {
+ /** By chaining the spy with calls.any(), will return false if the spy has not been called at all, and then true once at least one call happens. **/
+ any(): boolean;
+ /** By chaining the spy with calls.count(), will return the number of times the spy was called **/
+ count(): number;
+ /** By chaining the spy with calls.argsFor(), will return the arguments passed to call number index **/
+ argsFor(index: number): any[];
+ /** By chaining the spy with calls.allArgs(), will return the arguments to all calls **/
+ allArgs(): any[];
+ /** By chaining the spy with calls.all(), will return the context (the this) and arguments passed all calls **/
+ all(): CallInfo[];
+ /** By chaining the spy with calls.mostRecent(), will return the context (the this) and arguments for the most recent call **/
+ mostRecent(): CallInfo;
+ /** By chaining the spy with calls.first(), will return the context (the this) and arguments for the first call **/
+ first(): CallInfo;
+ /** By chaining the spy with calls.reset(), will clears all tracking for a spy **/
+ reset(): void;
+ }
+
+ interface CallInfo {
+ /** The context (the this) for the call */
+ object: any;
+ /** All arguments passed to the call */
+ args: any[];
+ /** The return value of the call */
+ returnValue: any;
+ }
+
+ interface Util {
+ inherit(childClass: Function, parentClass: Function): any;
+ formatException(e: any): any;
+ htmlEscape(str: string): string;
+ argsToArray(args: any): any;
+ extend(destination: any, source: any): any;
+ }
+
+ interface JsApiReporter extends Reporter {
+
+ started: boolean;
+ finished: boolean;
+ result: any;
+ messages: any;
+
+ new (): any;
+
+ suites(): Suite[];
+ summarize_(suiteOrSpec: SuiteOrSpec): any;
+ results(): any;
+ resultsForSpec(specId: any): any;
+ log(str: any): any;
+ resultsForSpecs(specIds: any): any;
+ summarizeResult_(result: any): any;
+ }
+
+ interface Jasmine {
+ Spec: Spec;
+ clock: Clock;
+ util: Util;
+ }
+
+ export var HtmlReporter: HtmlReporter;
+ export var HtmlSpecFilter: HtmlSpecFilter;
+ export var DEFAULT_TIMEOUT_INTERVAL: number;
+}
\ No newline at end of file
diff --git a/typings/globals/jasmine/typings.json b/typings/globals/jasmine/typings.json
new file mode 100644
index 0000000000..3fb336cf1c
--- /dev/null
+++ b/typings/globals/jasmine/typings.json
@@ -0,0 +1,8 @@
+{
+ "resolution": "main",
+ "tree": {
+ "src": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/c49913aa9ea419ea46c1c684e488cf2a10303b1a/jasmine/jasmine.d.ts",
+ "raw": "registry:dt/jasmine#2.2.0+20160621224255",
+ "typings": "https://raw.githubusercontent.com/DefinitelyTyped/DefinitelyTyped/c49913aa9ea419ea46c1c684e488cf2a10303b1a/jasmine/jasmine.d.ts"
+ }
+}
diff --git a/typings/index.d.ts b/typings/index.d.ts
new file mode 100644
index 0000000000..7cf8a3f75b
--- /dev/null
+++ b/typings/index.d.ts
@@ -0,0 +1 @@
+///