diff --git a/jest/jest-tests.ts b/jest/jest-tests.ts
index f3e33c4061..b547bd40ad 100644
--- a/jest/jest-tests.ts
+++ b/jest/jest-tests.ts
@@ -1,4 +1,5 @@
///
+///
// Tests based on the Jest website
jest.unmock('../sum');
@@ -37,8 +38,6 @@ describe('fetchCurrentUser', function() {
// unmock is the recommended approach for unmocking...
jest.unmock('../displayUser.js')
-// ...but dontMock also still works.
-jest.dontMock('jquery');
describe('displayUser', function() {
it('displays a user after a click', function() {
@@ -100,6 +99,157 @@ describe('CheckboxWithLabel', function() {
});
});
+jest.runAllTicks();
+xdescribe('Hooks and Suits', function () {
+ let tested: boolean;
+
+ beforeEach(function () {
+ tested = false;
+ });
+
+ afterEach(function () {
+ tested = true;
+ });
+
+ test('tested', function () {
+ expect(tested).toBeTruthy();
+ expect(tested).not.toBeFalsy();
+ });
+
+ fit('tested', function () {
+ expect(tested).toBeDefined();
+ expect(tested).not.toBeUndefined();
+ });
+
+ xit('expect null to be null', function () {
+ expect(null).toBeNull();
+ });
+});
+
+describe('compartion', function () {
+ var sum: (a: number, b: number) => number = require.requireMock('../sum');
+
+ it('compares is 7 + 2 greater than 3', function () {
+ expect(sum(7, 2)).toBeGreaterThan(3);
+ });
+
+ it('compares is 2 + 7 greater than or equal to 3', function () {
+ expect(sum(2, 7)).toBeGreaterThanOrEqual(3);
+ });
+
+ it('compares is 3 less than 3 + 4', function () {
+ expect(3).toBeLessThan(sum(3, 4));
+ });
+
+ it('compares is 3 less than or equal to 4 + 3', function () {
+ expect(3).toBeLessThanOrEqual(sum(4, 3));
+ });
+
+ it('works sanely with simple decimals', function () {
+ expect(0.2 + 0.1).toBeCloseTo(0.3, 5);
+ });
+});
+
+describe('toThrow API', function () {
+ function throwTypeError(): void {
+ throw new TypeError('toThrow Definition was out of date');
+ }
+
+ it('throws', function () {
+ expect(throwTypeError()).toThrow();
+ });
+
+ it('throws TypeError', function () {
+ expect(throwTypeError()).toThrowError(TypeError);
+ });
+
+ it('throws \'Definition was out of date\'', function () {
+ expect(throwTypeError()).toThrowError(/Definition was out of date/);
+ });
+
+ it('throws \'toThorow Definition was out of date\'', function () {
+ expect(throwTypeError()).toThrowError('toThrow Definition was out of date');
+ });
+});
+
+describe('missing tests', function () {
+ it('creates closures', function () {
+ class Closure {
+ private arg: T;
+
+ public constructor(private fn: (arg: T) => void) {
+ this.fn = fn;
+ }
+
+ public bind(arg: T): void {
+ this.arg = arg;
+ }
+
+ public call(): void {
+ this.fn(this.arg);
+ }
+ }
+
+ type StringClosure = (arg: string) => void;
+ let spy: jest.Mock = jest.fn();
+ let closure: Closure = new Closure(spy);
+ closure.bind('jest');
+ closure.call();
+ expect(spy).lastCalledWith('jest');
+ expect(spy).toBeCalledWith('jest');
+ expect(jest.isMockFunction(spy)).toBeTruthy();
+ });
+
+ it('tests all mising Mocks functionality', function () {
+ type FruitsGetter = () => Array;
+ let mock: jest.Mock = jest.fn();
+ mock.mockImplementationOnce(() => ['Orange', 'Apple', 'Plum'])
+ jest.setMock('./../tesks/getFruits', mock);
+ const getFruits: FruitsGetter = require('./../tesks/getFruits');
+ expect(getFruits()).toContain('Orange');
+ mock.mockReturnValueOnce(['Apple', 'Plum']);
+ expect(mock()).not.toContain('Orange');
+ mock.mockReturnValue([]); //Deprecated: Use jest.fn(() => value) instead.
+ mock.mockClear();
+ let thisMock: jest.Mock = jest.fn().mockReturnThis();
+ expect(thisMock()).toBe(this);
+ });
+
+ it('creates snapshoter', function () {
+ jest.disableAutomock();
+ jest.mock('./render', () => jest.fn((): string => "{Link to: \"facebook\"}"), { virtual: true });
+ const render: () => string = require('./render');
+ expect(render()).toMatch(/Link/);
+ jest.enableAutomock();
+ });
+
+ it('runs only pending timers', function () {
+ jest.useRealTimers();
+ setTimeout(() => expect(1).not.toEqual(0), 3000);
+ jest.runOnlyPendingTimers();
+ });
+
+ it('runs all timers', function () {
+ jest.clearAllTimers();
+ jest.useFakeTimers();
+ setTimeout(() => expect(0).not.toEqual(1), 3000);
+ jest.runAllTimers();
+ });
+
+ it('cleares cache', function () {
+ const sum1 = require('../sum');
+ jest.resetModules();
+ const sum2 = require('../sum');
+ expect(sum1).not.toBe(sum2);
+ })
+});
+
+describe('toMatchSnapshot', function () {
+ it('compares snapshots', function () {
+ expect({ type: 'a', props: { href: 'https://www.facebook.com/' }, children: [ 'Facebook' ] }).toMatchSnapshot();
+ });
+});
+
function testInstances() {
var mockFn = jest.fn();
var a = new mockFn();
@@ -123,3 +273,82 @@ function testMockImplementation() {
mockFn.mock.calls[0][0] === 0; // true
mockFn.mock.calls[1][0] === 1; // true
}
+
+// Test from jest Docs:
+describe('genMockFromModule', function () {
+ // Interfaces:
+ interface MockFiles {
+ [index: string]: string;
+ }
+
+ interface MockedFS {
+ readdirSync: (dir: string) => string[];
+ __setMockFiles: (newMockFiles: MockFiles) => void ;
+ }
+
+ // ------------------------------------------------------------------------------------
+ // FileSummarizer.ts
+
+ const fs = require('fs');
+
+ function summarizeFilesInDirectorySync(directory: string): string[] {
+ return fs.readdirSync(directory).map((fileName: string) => ({
+ fileName,
+ directory,
+ }));
+ }
+
+ //export default summarizeFilesInDirectorySync; // For sake of compilation
+
+ // ------------------------------------------------------------------------------------
+ // __mocks__/fs.js
+
+ const path = require('path');
+
+ const mockedFS: MockedFS = jest.genMockFromModule('fs');
+
+ let mockFiles: any = Object.create(null);
+ function __setMockFiles(newMockFiles: MockFiles): void {
+ mockFiles = Object.create(null);
+ for(const file in newMockFiles) {
+ const dir: string = path.dirname(file);
+
+ if (!mockFiles[dir]) {
+ mockFiles[dir] = [];
+ }
+ mockFiles[dir].push(path.basename(file));
+ }
+ }
+
+ function readdirSync(directoryPath: string): string[] {
+ return mockFiles[directoryPath] || [];
+ }
+
+ mockedFS.readdirSync = readdirSync;
+ mockedFS.__setMockFiles = __setMockFiles;
+
+ //export = mockedFS; // For sake of compilation
+ // ------------------------------------------------------------------------------------
+ // __tests__/FileSummarizer-test.js
+
+ jest.mock('fs');
+
+ describe('listFilesInDirectorySync', () => {
+ const MOCK_FILE_INFO: MockFiles = {
+ '/path/to/file1.js': 'console.log("file1 contents");',
+ '/path/to/file2.txt': 'file2 contents',
+ };
+
+ beforeEach(() => {
+ // Set up some mocked out file info before each test
+ (require('fs') as MockedFS).__setMockFiles(MOCK_FILE_INFO);
+ });
+
+ it('includes all files in the directory in the summary', () => {
+ const FileSummarizer: (dir: string) => string[] = require('../FileSummarizer');
+ const fileSummary = FileSummarizer('/path/to');
+
+ expect(fileSummary.length).toBe(2);
+ });
+ });
+});
diff --git a/jest/jest.d.ts b/jest/jest.d.ts
index b2484dfcc5..d0660193f6 100644
--- a/jest/jest.d.ts
+++ b/jest/jest.d.ts
@@ -1,79 +1,150 @@
-// Type definitions for Jest 0.9.0
+// Type definitions for Jest 15.1.1
// Project: http://facebook.github.io/jest/
-// Definitions by: Asana
+// Definitions by: Asana , Ivo Stratev , jwbay
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
-///
-
-declare function afterEach(fn: jest.EmptyFunction): void;
-declare function beforeEach(fn: jest.EmptyFunction): void;
-declare function describe(name: string, fn: jest.EmptyFunction): void;
+declare var beforeAll: jest.Lifecycle;
+declare var beforeEach: jest.Lifecycle;
+declare var afterAll: jest.Lifecycle;
+declare var afterEach: jest.Lifecycle;
+declare var describe: jest.Describe;
+declare var fdescribe: jest.Describe;
+declare var xdescribe: jest.Describe;
declare var it: jest.It;
-declare function pit(name: string, fn: jest.EmptyFunction): void;
-
-declare function xdescribe(name: string, fn: jest.EmptyFunction): void;
-declare function xit(name: string, fn: jest.EmptyFunction): void;
+declare var fit: jest.It;
+declare var xit: jest.It;
+declare var test: jest.It;
+declare var xtest: jest.It;
declare function expect(actual: any): jest.Matchers;
interface NodeRequire {
+ /** Returns the actual module instead of a mock, bypassing all checks on whether the module should receive a mock implementation or not. */
requireActual(moduleName: string): any;
+ /** Returns a mock module instead of the actual module, bypassing all checks on whether the module should be required normally or not. */
+ requireMock(moduleName: string): any;
}
declare namespace jest {
- function addMatchers(matchers: CustomMatcherFactories): void;
+ function addMatchers(matchers: jasmine.CustomMatcherFactories): void;
+ /** Disables automatic mocking in the module loader. */
function autoMockOff(): void;
+ /** Enables automatic mocking in the module loader. */
function autoMockOn(): void;
+ /** Removes any pending timers from the timer system. If any timers have been scheduled, they will be cleared and will never have the opportunity to execute in the future. */
function clearAllTimers(): void;
- function currentTestPath(): string;
+ /** Indicates that the module system should never return a mocked version of the specified module, including all of the specificied module's dependencies. */
+ function deepUnmock(moduleName: string): void;
+ /** Disables automatic mocking in the module loader. */
function disableAutomock(): void;
- function fn(implementation?: Function): Mock;
+ /** Mocks a module with an auto-mocked version when it is being required. */
+ function doMock(moduleName: string): void;
+ /** Indicates that the module system should never return a mocked version of the specified module from require() (e.g. that it should always return the real module). */
function dontMock(moduleName: string): void;
- function genMockFromModule(moduleName: string): Mock;
- function mock(moduleName: string, factory?: Function): void;
+ /** Enables automatic mocking in the module loader. */
+ function enableAutomock(): void;
+ /** Creates a mock function. Optionally takes a mock implementation. */
+ function fn(implementation?: Function): Mock;
+ /** Use the automatic mocking system to generate a mocked version of the given module. */
+ function genMockFromModule(moduleName: string): T;
+ /** Returns whether the given function is a mock function. */
+ function isMockFunction(fn: any): fn is Mock;
+ /** Mocks a module with an auto-mocked version when it is being required. */
+ function mock(moduleName: string, factory?: any, options?: MockOptions): void;
+ /** Resets the module registry - the cache of all required modules. This is useful to isolate modules where local state might conflict between tests. */
+ function resetModuleRegistry(): void;
+ /** Resets the module registry - the cache of all required modules. This is useful to isolate modules where local state might conflict between tests. */
+ function resetModules(): void;
+ /** Exhausts tasks queued by setImmediate(). */
+ function runAllImmediates(): void;
+ /** Exhausts the micro-task queue (usually interfaced in node via process.nextTick). */
function runAllTicks(): void;
+ /** Exhausts the macro-task queue (i.e., all tasks queued by setTimeout() and setInterval()). */
function runAllTimers(): void;
+ /** Executes only the macro-tasks that are currently pending (i.e., only the tasks that have been queued by setTimeout() or setInterval() up to this point).
+ * If any of the currently pending macro-tasks schedule new macro-tasks, those new tasks will not be executed by this call. */
function runOnlyPendingTimers(): void;
+ /** Explicitly supplies the mock object that the module system should return for the specified module. */
function setMock(moduleName: string, moduleExports: T): void;
+ /** Indicates that the module system should never return a mocked version of the specified module from require() (e.g. that it should always return the real module). */
function unmock(moduleName: string): void;
+ /** Instructs Jest to use fake versions of the standard timer functions. */
+ function useFakeTimers(): void;
+ /** Instructs Jest to use the real versions of the standard timer functions. */
+ function useRealTimers(): void;
+
+ interface MockOptions {
+ virtual?: boolean;
+ }
interface EmptyFunction {
(): void;
}
- interface Matchers {
- not: Matchers;
- toThrow(expected?: any): boolean;
- toThrowError(expected?: any): boolean;
- toBe(expected: any): boolean;
- toEqual(expected: any): boolean;
- toBeFalsy(): boolean;
- toBeTruthy(): boolean;
- toBeNull(): boolean;
- toBeDefined(): boolean;
- toBeUndefined(): boolean;
- toMatch(expected: RegExp): boolean;
- toContain(expected: string): boolean;
- toBeCloseTo(expected: number, delta: number): boolean;
- toBeGreaterThan(expected: number): boolean;
- toBeLessThan(expected: number): boolean;
- toBeCalled(): boolean;
- toBeCalledWith(...args: any[]): boolean;
- lastCalledWith(...args: any[]): boolean;
+ interface DoneCallback {
+ (...args: any[]): any
+ fail(error?: string | { message: string }): any;
+ }
+
+ interface ProvidesCallback {
+ (cb?: DoneCallback): any;
+ }
+
+ interface Lifecycle {
+ (fn: ProvidesCallback): any;
}
interface It {
- (name: string, fn: EmptyFunction): void;
- only(name: string, fn: EmptyFunction): void;
+ (name: string, fn: ProvidesCallback): void;
+ only: It;
+ skip: It;
}
- interface Mock {
+ interface Describe {
+ (name: string, fn: EmptyFunction): void
+ only: Describe;
+ skip: Describe;
+ }
+
+ interface Matchers {
+ not: Matchers;
+ lastCalledWith(...args: any[]): void;
+ toBe(expected: any): void;
+ toBeCalled(): void;
+ toBeCalledWith(...args: any[]): void;
+ toBeCloseTo(expected: number, delta: number): void;
+ toBeDefined(): void;
+ toBeFalsy(): void;
+ toBeGreaterThan(expected: number): void;
+ toBeGreaterThanOrEqual(expected: number): void;
+ toBeInstanceOf(expected: any): void
+ toBeLessThan(expected: number): void;
+ toBeLessThanOrEqual(expected: number): void;
+ toBeNull(): void;
+ toBeTruthy(): void;
+ toBeUndefined(): void;
+ toContain(expected: any): void;
+ toEqual(expected: any): void;
+ toHaveBeenCalled(): boolean;
+ toHaveBeenCalledTimes(expected: number): boolean;
+ toHaveBeenCalledWith(...params: any[]): boolean;
+ toMatch(expected: string | RegExp): void;
+ toMatchSnapshot(): void;
+ toThrow(): void;
+ toThrowError(error?: string | Constructable | RegExp): void;
+ }
+
+ interface Constructable {
+ new (...args: any[]): any
+ }
+
+ interface Mock extends Function {
new (): T;
- (...args: any[]): any; // TODO please fix this line! added for TypeScript 1.1.0-1 https://github.com/DefinitelyTyped/DefinitelyTyped/pull/2932
+ (...args: any[]): any;
mock: MockContext;
mockClear(): void;
mockImplementation(fn: Function): Mock;
- mockImpl(fn: Function): Mock;
+ mockImplementationOnce(fn: Function): Mock;
mockReturnThis(): Mock;
mockReturnValue(value: any): Mock;
mockReturnValueOnce(value: any): Mock;
@@ -83,42 +154,138 @@ declare namespace jest {
calls: any[][];
instances: T[];
}
+}
+
+//Jest ships with a copy of Jasmine. They monkey-patch its APIs and divergence/deprecation are expected.
+//Relevant parts of Jasmine's API are below so they can be changed and removed over time.
+//This file can't reference jasmine.d.ts since the globals aren't compatible.
+
+declare function spyOn(object: any, method: string): jasmine.Spy;
+/** 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;
+/** Fails a test when called within one. */
+declare function fail(error?: any): 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 addCustomEqualityTester(equalityTester: CustomEqualityTester): void;
+ function addMatchers(matchers: CustomMatcherFactories): void;
+ function stringMatching(value: string | RegExp): 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 Any {
+ new (expectedClass: any): any;
+ jasmineMatches(other: any): boolean;
+ jasmineToString(): string;
+ }
+
+ 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 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;
+ }
- // taken from Jasmine since addMatchers calls into the jasmine api
interface CustomMatcherFactories {
[index: string]: CustomMatcherFactory;
}
- // taken from Jasmine since addMatchers calls into the jasmine api
interface CustomMatcherFactory {
(util: MatchersUtil, customEqualityTesters: Array): CustomMatcher;
}
- // taken from Jasmine since addMatchers calls into the jasmine api
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;
}
- // taken from Jasmine since addMatchers calls into the jasmine api
interface CustomEqualityTester {
(first: any, second: any): boolean;
}
- // taken from Jasmine since addMatchers calls into the jasmine api
interface CustomMatcher {
compare(actual: T, expected: T): CustomMatcherResult;
compare(actual: any, expected: any): CustomMatcherResult;
}
- // taken from Jasmine since addMatchers calls into the jasmine api
interface CustomMatcherResult {
pass: boolean;
- message: string;
+ message: string | (() => string);
}
- // taken from Jasmine which takes from TypeScript lib.core.es6.d.ts, applicable to CustomMatchers.contains()
interface ArrayLike {
length: number;
[n: number]: T;