diff options
author | Florian Dold <florian.dold@gmail.com> | 2017-05-28 00:38:50 +0200 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2017-05-28 00:40:43 +0200 |
commit | 7fff4499fd915bcea3fa93b1aa8b35f4fe7a6027 (patch) | |
tree | 6de9a1aebd150a23b7f8c273ec657a5d0a18fe3e /node_modules/jest-mock | |
parent | 963b7a41feb29cc4be090a2446bdfe0c1f1bcd81 (diff) |
add linting (and some initial fixes)
Diffstat (limited to 'node_modules/jest-mock')
-rw-r--r-- | node_modules/jest-mock/.npmignore | 3 | ||||
-rw-r--r-- | node_modules/jest-mock/README.md | 122 | ||||
-rw-r--r-- | node_modules/jest-mock/build/index.js | 606 | ||||
-rw-r--r-- | node_modules/jest-mock/package.json | 10 |
4 files changed, 741 insertions, 0 deletions
diff --git a/node_modules/jest-mock/.npmignore b/node_modules/jest-mock/.npmignore new file mode 100644 index 000000000..85e48fe7b --- /dev/null +++ b/node_modules/jest-mock/.npmignore @@ -0,0 +1,3 @@ +**/__mocks__/** +**/__tests__/** +src diff --git a/node_modules/jest-mock/README.md b/node_modules/jest-mock/README.md new file mode 100644 index 000000000..2de10c3b4 --- /dev/null +++ b/node_modules/jest-mock/README.md @@ -0,0 +1,122 @@ +# jest-mock + +## API + +### `constructor(global)` + +Creates a new module mocker that generates mocks as if they were created in an +environment with the given global object. + +### `generateFromMetadata(metadata)` + +Generates a mock based on the given metadata (Metadata for the mock in +the schema returned by the getMetadata method of this module). Mocks treat +functions specially, and all mock functions have additional members, described +in the documentation for `fn` in this module. + + +One important note: function prototypes are handled specially by this +mocking framework. For functions with prototypes, when called as a +constructor, the mock will install mocked function members on the instance. +This allows different instances of the same constructor to have different +values for its mocks member and its return values. + +### `getMetadata(component)` + +Inspects the argument and returns its schema in the following recursive format: + +```js +{ + type: ... + members : {} +} +``` + +Where type is one of `array`, `object`, `function`, or `ref`, and members +is an optional dictionary where the keys are member names and the values +are metadata objects. Function prototypes are defined simply by defining +metadata for the `member.prototype` of the function. The type of a function +prototype should always be `object`. For instance, a simple class might be +defined like this: + +```js +{ + type: 'function', + members: { + staticMethod: {type: 'function'}, + prototype: { + type: 'object', + members: { + instanceMethod: {type: 'function'} + } + } + } +} + ``` + +Metadata may also contain references to other objects defined within the +same metadata object. The metadata for the referent must be marked with +`refID` key and an arbitrary value. The referrer must be marked with a +`ref` key that has the same value as object with refID that it refers to. +For instance, this metadata blob: + +```js +{ + type: 'object', + refID: 1, + members: { + self: {ref: 1} + } +} +``` + +defines an object with a slot named `self` that refers back to the object. + +### `fn` + +Generates a stand-alone function with members that help drive unit tests or +confirm expectations. Specifically, functions returned by this method have +the following members: + +##### `.mock` + +An object with two members, `calls`, and `instances`, which are both +lists. The items in the `calls` list are the arguments with which the +function was called. The "instances" list stores the value of 'this' for +each call to the function. This is useful for retrieving instances from a +constructor. + +##### `.mockReturnValueOnce(value)` + +Pushes the given value onto a FIFO queue of return values for the +function. + +##### `.mockReturnValue(value)` + +Sets the default return value for the function. + +##### `.mockImplementationOnce(function)` + +Pushes the given mock implementation onto a FIFO queue of mock +implementations for the function. + +##### `.mockImplementation(function)` + +Sets the default mock implementation for the function. + +##### `.mockReturnThis()` + +Syntactic sugar for .mockImplementation(function() {return this;}) + + + +In case both `mockImplementationOnce()/mockImplementation()` and +`mockReturnValueOnce()/mockReturnValue()` are called. The priority of which to +use is based on what is the last call: +- if the last call is mockReturnValueOnce() or mockReturnValue(), + use the specific return value or default return value. + If specific return values are used up or no default return value is set, + fall back to try mockImplementation(); +- if the last call is mockImplementationOnce() or mockImplementation(), + run the specific implementation and return the result or run default + implementation and return the result. diff --git a/node_modules/jest-mock/build/index.js b/node_modules/jest-mock/build/index.js new file mode 100644 index 000000000..d99c0bb98 --- /dev/null +++ b/node_modules/jest-mock/build/index.js @@ -0,0 +1,606 @@ +/** + * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * + */ + +'use strict'; + + + + + + + + + + + + + + + + + + + + + + + + + + + +const MOCK_CONSTRUCTOR_NAME = 'mockConstructor'; + +// $FlowFixMe +const RESERVED_KEYWORDS = Object.assign(Object.create(null), { + arguments: true, + await: true, + break: true, + case: true, + catch: true, + class: true, + const: true, + continue: true, + debugger: true, + default: true, + delete: true, + do: true, + else: true, + enum: true, + eval: true, + export: true, + extends: true, + false: true, + finally: true, + for: true, + function: true, + if: true, + implements: true, + import: true, + in: true, + instanceof: true, + interface: true, + let: true, + new: true, + null: true, + package: true, + private: true, + protected: true, + public: true, + return: true, + static: true, + super: true, + switch: true, + this: true, + throw: true, + true: true, + try: true, + typeof: true, + var: true, + void: true, + while: true, + with: true, + yield: true }); + + +function isA(typeName, value) { + return Object.prototype.toString.apply(value) === '[object ' + typeName + ']'; +} + +function getType(ref) { + if (isA('Function', ref)) { + return 'function'; + } else if (Array.isArray(ref)) { + return 'array'; + } else if (isA('Object', ref)) { + return 'object'; + } else if ( + isA('Number', ref) || + isA('String', ref) || + isA('Boolean', ref) || + isA('Symbol', ref)) + { + return 'constant'; + } else if (isA('Map', ref) || isA('WeakMap', ref) || isA('Set', ref)) { + return 'collection'; + } else if (isA('RegExp', ref)) { + return 'regexp'; + } else if (ref === undefined) { + return 'undefined'; + } else if (ref === null) { + return 'null'; + } else { + return null; + } +} + +function isReadonlyProp(object, prop) { + return ( + + ( + prop === 'arguments' || + prop === 'caller' || + prop === 'callee' || + prop === 'name' || + prop === 'length') && + + isA('Function', object) || + + + ( + prop === 'source' || + prop === 'global' || + prop === 'ignoreCase' || + prop === 'multiline') && + + isA('RegExp', object)); + + +} + +function getSlots(object) { + const slots = {}; + if (!object) { + return []; + } + + let parent = Object.getPrototypeOf(object); + do { + if (object === Object.getPrototypeOf(Function)) { + break; + } + const ownNames = Object.getOwnPropertyNames(object); + for (let i = 0; i < ownNames.length; i++) { + const prop = ownNames[i]; + if (!isReadonlyProp(object, prop)) { + const propDesc = Object.getOwnPropertyDescriptor(object, prop); + if (!propDesc.get || object.__esModule) { + slots[prop] = true; + } + } + } + object = parent; + } while (object && (parent = Object.getPrototypeOf(object)) !== null); + return Object.keys(slots); +} + + +class ModuleMockerClass { + + + + + + /** + * @see README.md + * @param global Global object of the test environment, used to create + * mocks + */ + constructor(global) { + this._environmentGlobal = global; + this._mockState = new WeakMap(); + this._mockConfigRegistry = new WeakMap(); + this.ModuleMocker = ModuleMockerClass; + } + + _ensureMockConfig(f) { + let config = this._mockConfigRegistry.get(f); + if (!config) { + config = this._defaultMockConfig(); + this._mockConfigRegistry.set(f, config); + } + return config; + } + + _ensureMockState(f) { + let state = this._mockState.get(f); + if (!state) { + state = this._defaultMockState(); + this._mockState.set(f, state); + } + return state; + } + + _defaultMockConfig() { + return { + defaultReturnValue: undefined, + isReturnValueLastSet: false, + mockImpl: undefined, + specificMockImpls: [], + specificReturnValues: [] }; + + } + + _defaultMockState() { + return { + calls: [], + instances: [] }; + + } + + _makeComponent(metadata, restore) { + if (metadata.type === 'object') { + return new this._environmentGlobal.Object(); + } else if (metadata.type === 'array') { + return new this._environmentGlobal.Array(); + } else if (metadata.type === 'regexp') { + return new this._environmentGlobal.RegExp(''); + } else if ( + metadata.type === 'constant' || + metadata.type === 'collection' || + metadata.type === 'null' || + metadata.type === 'undefined') + { + return metadata.value; + } else if (metadata.type === 'function') { + /* eslint-disable prefer-const */ + let f; + /* eslint-enable prefer-const */ + + const prototype = + metadata.members && + metadata.members.prototype && + metadata.members.prototype.members || + {}; + const prototypeSlots = getSlots(prototype); + const mocker = this; + const mockConstructor = function () { + const mockState = mocker._ensureMockState(f); + const mockConfig = mocker._ensureMockConfig(f); + mockState.instances.push(this); + mockState.calls.push(Array.prototype.slice.call(arguments)); + if (this instanceof f) { + // This is probably being called as a constructor + prototypeSlots.forEach(slot => { + // Copy prototype methods to the instance to make + // it easier to interact with mock instance call and + // return values + if (prototype[slot].type === 'function') { + const protoImpl = this[slot]; + this[slot] = mocker.generateFromMetadata(prototype[slot]); + this[slot]._protoImpl = protoImpl; + } + }); + + // Run the mock constructor implementation + return ( + mockConfig.mockImpl && + mockConfig.mockImpl.apply(this, arguments)); + + } + + let returnValue; + // If return value is last set, either specific or default, i.e. + // mockReturnValueOnce()/mockReturnValue() is called and no + // mockImplementationOnce()/mockImplementation() is called after that. + // use the set return value. + if (mockConfig.isReturnValueLastSet) { + returnValue = mockConfig.specificReturnValues.shift(); + if (returnValue === undefined) { + returnValue = mockConfig.defaultReturnValue; + } + } + + // If mockImplementationOnce()/mockImplementation() is last set, + // or specific return values are used up, use the mock implementation. + let specificMockImpl; + if (returnValue === undefined) { + specificMockImpl = mockConfig.specificMockImpls.shift(); + if (specificMockImpl === undefined) { + specificMockImpl = mockConfig.mockImpl; + } + if (specificMockImpl) { + return specificMockImpl.apply(this, arguments); + } + } + + // Otherwise use prototype implementation + if (returnValue === undefined && f._protoImpl) { + return f._protoImpl.apply(this, arguments); + } + + return returnValue; + }; + + f = this._createMockFunction(metadata, mockConstructor); + f._isMockFunction = true; + f.getMockImplementation = () => this._ensureMockConfig(f).mockImpl; + + this._mockState.set(f, this._defaultMockState()); + this._mockConfigRegistry.set(f, this._defaultMockConfig()); + + // $FlowFixMe - defineProperty getters not supported + Object.defineProperty(f, 'mock', { + configurable: false, + enumerable: true, + get: () => this._ensureMockState(f), + set: val => this._mockState.set(f, val) }); + + + f.mockClear = () => { + this._mockState.delete(f); + }; + + f.mockReset = () => { + this._mockState.delete(f); + this._mockConfigRegistry.delete(f); + }; + + f.mockReturnValueOnce = value => { + // next function call will return this value or default return value + const mockConfig = this._ensureMockConfig(f); + mockConfig.isReturnValueLastSet = true; + mockConfig.specificReturnValues.push(value); + return f; + }; + + f.mockReturnValue = value => { + // next function call will return specified return value or this one + const mockConfig = this._ensureMockConfig(f); + mockConfig.isReturnValueLastSet = true; + mockConfig.defaultReturnValue = value; + return f; + }; + + f.mockImplementationOnce = fn => { + // next function call will use this mock implementation return value + // or default mock implementation return value + const mockConfig = this._ensureMockConfig(f); + mockConfig.isReturnValueLastSet = false; + mockConfig.specificMockImpls.push(fn); + return f; + }; + + f.mockImplementation = fn => { + // next function call will use mock implementation return value + const mockConfig = this._ensureMockConfig(f); + mockConfig.isReturnValueLastSet = false; + mockConfig.mockImpl = fn; + return f; + }; + + f.mockReturnThis = () => + f.mockImplementation(function () { + return this; + }); + + if (metadata.mockImpl) { + f.mockImplementation(metadata.mockImpl); + } + + f.mockRestore = restore ? restore : () => {}; + + return f; + } else { + const unknownType = metadata.type || 'undefined type'; + throw new Error('Unrecognized type ' + unknownType); + } + } + + _createMockFunction( + metadata, + mockConstructor) + { + let name = metadata.name; + // Special case functions named `mockConstructor` to guard for infinite + // loops. + if (!name || name === MOCK_CONSTRUCTOR_NAME) { + return mockConstructor; + } + + // Preserve `name` property of mocked function. + const boundFunctionPrefix = 'bound '; + let bindCall = ''; + // if-do-while for perf reasons. The common case is for the if to fail. + if (name && name.startsWith(boundFunctionPrefix)) { + do { + name = name.substring(boundFunctionPrefix.length); + // Call bind() just to alter the function name. + bindCall = '.bind(null)'; + } while (name && name.startsWith(boundFunctionPrefix)); + } + + // It's a syntax error to define functions with a reserved keyword + // as name. + if (RESERVED_KEYWORDS[name]) { + name = '$' + name; + } + + // It's also a syntax error to define a function with a reserved character + // as part of it's name. + if (/[\s-]/.test(name)) { + name = name.replace(/[\s-]/g, '$'); + } + + const body = + 'return function ' + name + '() {' + + 'return ' + MOCK_CONSTRUCTOR_NAME + '.apply(this,arguments);' + + '}' + bindCall; + const createConstructor = new this._environmentGlobal.Function( + MOCK_CONSTRUCTOR_NAME, + body); + + return createConstructor(mockConstructor); + } + + _generateMock( + metadata, + callbacks, + refs) + { + const mock = this._makeComponent(metadata); + if (metadata.refID != null) { + refs[metadata.refID] = mock; + } + + getSlots(metadata.members).forEach(slot => { + const slotMetadata = metadata.members && metadata.members[slot] || {}; + if (slotMetadata.ref != null) { + callbacks.push(() => mock[slot] = refs[slotMetadata.ref]); + } else { + mock[slot] = this._generateMock(slotMetadata, callbacks, refs); + } + }); + + if ( + metadata.type !== 'undefined' && + metadata.type !== 'null' && + mock.prototype) + { + mock.prototype.constructor = mock; + } + + return mock; + } + + /** + * @see README.md + * @param metadata Metadata for the mock in the schema returned by the + * getMetadata method of this module. + */ + generateFromMetadata(_metadata) { + const callbacks = []; + const refs = {}; + const mock = this._generateMock(_metadata, callbacks, refs); + callbacks.forEach(setter => setter()); + return mock; + } + + /** + * @see README.md + * @param component The component for which to retrieve metadata. + */ + getMetadata( + component, + _refs) + { + const refs = _refs || new Map(); + const ref = refs.get(component); + if (ref != null) { + return { ref }; + } + + const type = getType(component); + if (!type) { + return null; + } + + const metadata = { type }; + if ( + type === 'constant' || + type === 'collection' || + type === 'undefined' || + type === 'null') + { + metadata.value = component; + return metadata; + } else if (type === 'function') { + metadata.name = component.name; + if (component._isMockFunction) { + metadata.mockImpl = component.getMockImplementation(); + } + } + + metadata.refID = refs.size; + refs.set(component, metadata.refID); + + let members = null; + // Leave arrays alone + if (type !== 'array') { + if (type !== 'undefined') { + getSlots(component).forEach(slot => { + if ( + type === 'function' && + component._isMockFunction && + slot.match(/^mock/)) + { + return; + } + + if ( + !component.hasOwnProperty && component[slot] !== undefined || + component.hasOwnProperty && component.hasOwnProperty(slot) || + type === 'object' && component[slot] != Object.prototype[slot]) + { + const slotMetadata = this.getMetadata(component[slot], refs); + if (slotMetadata) { + if (!members) { + members = {}; + } + members[slot] = slotMetadata; + } + } + }); + } + + // If component is native code function, prototype might be undefined + if (type === 'function' && component.prototype) { + const prototype = this.getMetadata(component.prototype, refs); + if (prototype && prototype.members) { + if (!members) { + members = {}; + } + members.prototype = prototype; + } + } + } + + if (members) { + metadata.members = members; + } + + return metadata; + } + + isMockFunction(fn) { + return !!fn._isMockFunction; + } + + fn(implementation) { + const fn = this._makeComponent({ type: 'function' }); + if (implementation) { + fn.mockImplementation(implementation); + } + return fn; + } + + spyOn(object, methodName) { + const original = object[methodName]; + + if (!this.isMockFunction(original)) { + if (typeof original !== 'function') { + throw new Error( + 'Cannot spyOn the ' + methodName + ' property; it is not a function'); + + } + + object[methodName] = this._makeComponent({ type: 'function' }, () => { + object[methodName] = original; + }); + object[methodName].mockImplementation(function () { + return original.apply(this, arguments); + }); + } + + return object[methodName]; + } + + clearAllMocks() { + this._mockState = new WeakMap(); + } + + resetAllMocks() { + this._mockConfigRegistry = new WeakMap(); + this._mockState = new WeakMap(); + }} + + + +module.exports = new ModuleMockerClass(global);
\ No newline at end of file diff --git a/node_modules/jest-mock/package.json b/node_modules/jest-mock/package.json new file mode 100644 index 000000000..ac6073b18 --- /dev/null +++ b/node_modules/jest-mock/package.json @@ -0,0 +1,10 @@ +{ + "name": "jest-mock", + "version": "19.0.0", + "repository": { + "type": "git", + "url": "https://github.com/facebook/jest.git" + }, + "license": "BSD-3-Clause", + "main": "build/index.js" +} |