### Verify Environment Setup Source: https://github.com/testdouble/testdouble.js/blob/main/RELEASE.md Run these commands to ensure your environment is set up correctly before proceeding with a release. This includes installing dependencies, running CI tests, and checking the exit code. ```bash npm install npm run test:ci echo $? ``` -------------------------------- ### Example function to test Source: https://github.com/testdouble/testdouble.js/blob/main/docs/B-frequently-asked-questions.md This is the function under test that will be used in the example. ```javascript function getName(load, id) { return load(id).name } ``` -------------------------------- ### Install testdouble.js via npm Source: https://github.com/testdouble/testdouble.js/blob/main/docs/1-installation.md Use this command to add testdouble as a development dependency in your project. ```bash $ npm install --save-dev testdouble ``` -------------------------------- ### Explain a basic test double Source: https://github.com/testdouble/testdouble.js/blob/main/docs/9-debugging.md Use `td.explain()` on a test double function to get its configuration and state. This is useful for understanding initial setup and verifying no stubbings or calls have occurred. ```javascript var myTestDouble = td.function('.someFunction') td.explain(myTestDouble) /* { name: '.someFunction', callCount: 0, calls: [], description: 'This test double has 0 stubbings and 0 invocations.' } */ ``` -------------------------------- ### Define ESM module structure Source: https://github.com/testdouble/testdouble.js/blob/main/docs/7-replacing-dependencies.md Example structure for ESM modules to be replaced. ```javascript // brake.mjs export default function brake() {...} export function abs() {...} // car.mjs import brake, {abs} from './brake.mjs' ``` -------------------------------- ### Use custom 'isA' matcher in testdouble.js Source: https://github.com/testdouble/testdouble.js/blob/main/docs/8-custom-matchers.md Demonstrates how to use the custom 'isA' matcher when stubbing a function with `td.when()`. The example shows a successful match with a `Date` object and an unsuccessful match with a number. ```javascript var datePicker = td.function() td.when(datePicker(isA(Date))).thenReturn('good') datePicker(new Date()) // 'good' datePicker(5) // undefined ``` -------------------------------- ### Stubbing Callback APIs Source: https://github.com/testdouble/testdouble.js/blob/main/docs/5-stubbing-results.md Provides examples of how to stub functions that accept callbacks, including scenarios where the callback is at an arbitrary position or when the return value of the function is significant. ```APIDOC ## DELETE /api/users/{id} ### Description Deletes a specific user by their unique identifier. ### Method DELETE ### Endpoint /api/users/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the user to delete. ### Response #### Success Response (200) - **message** (string) - A confirmation message indicating the user was deleted. #### Response Example ```json { "message": "User with id user-123 deleted successfully." } ``` ``` -------------------------------- ### Define function with anonymous callback Source: https://github.com/testdouble/testdouble.js/blob/main/docs/6-verifying-invocations.md Example of a function that accepts a fetcher and logger, using an anonymous callback to process response data. ```javascript function logInvalidComments(fetcher, logger) { fetcher('/comments', function(response){ response.comments.forEach(function(comment) { if(!comment.valid) { logger('Hey, '+comment.text+' is invalid') } }) }) } ``` -------------------------------- ### Test Double Verification Failure Example Source: https://github.com/testdouble/testdouble.js/blob/main/docs/3-getting-started.md This is an example of the error message received when a `td.verify` assertion fails because the test double was not invoked as expected. It shows the 'Wanted' arguments versus the actual invocations (or lack thereof). ```javascript Error: Unsatisfied verification on test double `submitProblem`. Wanted: - called with `("saved problem")`. But there were no invocations of the test double. ``` -------------------------------- ### td.verify() failure example Source: https://github.com/testdouble/testdouble.js/blob/main/docs/6-verifying-invocations.md When a verification fails, an error is thrown detailing the expected and actual invocations. This helps in debugging by showing discrepancies in arguments or call counts. ```javascript td.verify(quack()) Error: Unsatisfied verification on test double `quack`. Wanted: - called with `()`. But was actually called: - called with `("QUACK")`. at Object.module.exports [as verify] (/Users/justin/code/testdouble/testdouble.js/lib/verify.js:22:15) ``` -------------------------------- ### Download testdouble.js via curl Source: https://github.com/testdouble/testdouble.js/blob/main/docs/1-installation.md Fetch the browser distribution directly from the unpkg CDN. ```bash $ curl -L https://unpkg.com/testdouble/dist/testdouble.js ``` -------------------------------- ### Initial Test Structure Source: https://github.com/testdouble/testdouble.js/blob/main/docs/3-getting-started.md Sets up a basic test structure using a Jasmine/Mocha compatible DSL for testing the MathProblem class. ```javascript describe('MathProblem', function(){ it('POSTs a random problem', function(){ }) }) ``` -------------------------------- ### Initialize testdouble.js in Node.js Source: https://github.com/testdouble/testdouble.js/blob/main/docs/1-installation.md Assign the library to a global variable in a test helper file to simplify access throughout your test suite. ```javascript globalThis.td = require('testdouble') ``` -------------------------------- ### Create Instance with td.instance() Source: https://context7.com/testdouble/testdouble.js/llms.txt Creates a constructor double and returns a new instance immediately. This is a shorthand for creating a constructor and instantiating it manually. ```javascript import * as td from 'testdouble' class Logger { log(message) {} error(message) {} } // One-liner to get a test double instance const fakeLogger = td.instance(Logger) // Configure and use immediately td.when(fakeLogger.log(td.matchers.anything())).thenReturn(true) fakeLogger.log('test message') // true // Equivalent to: const FakeLogger = td.constructor(Logger) const fakeLoggerAlt = new FakeLogger() ``` -------------------------------- ### td.instance() Source: https://context7.com/testdouble/testdouble.js/llms.txt Creates a constructor double and immediately returns a new instance. ```APIDOC ## td.instance(constructor) ### Description Convenience function that creates a constructor double and immediately returns a new instance. Equivalent to calling `new td.constructor(SomeClass)()`. ### Parameters #### Request Body - **constructor** (Class) - Required - The class or constructor function to instantiate. ### Request Example ```javascript const fakeLogger = td.instance(Logger); ``` ### Response #### Success Response (200) - **instance** (Object) - The created test double instance. ``` -------------------------------- ### Configure testdouble.js Source: https://github.com/testdouble/testdouble.js/blob/main/README.md Import or assign the library to a global variable for convenient access in test files. ```javascript // ES import syntax import * as td from 'testdouble' // CommonJS modules (e.g. Node.js) globalThis.td = require('testdouble') // Global set in our browser distribution window.td ``` -------------------------------- ### Stubbing with td.matchers.argThat for custom argument validation Source: https://github.com/testdouble/testdouble.js/blob/main/docs/5-stubbing-results.md Employ `td.matchers.argThat` to provide a custom truth test function for validating arguments when built-in matchers are insufficient. Be mindful of side effects in the predicate function, as they will be invoked during stubbing setup. ```javascript var pet = td.function() td.when(pet(td.matchers.argThat(function(animals){ return animals.length > 2 }))).thenReturn('goood') pet(['cat', 'dog', 'horse']) // 'goood' pet(['cat', 'dog']) // undefined pet({length: 81}) // 'goood' ``` -------------------------------- ### Defining Constructor and Method Source: https://github.com/testdouble/testdouble.js/blob/main/docs/3-getting-started.md Provides the minimal implementation for the MathProblem constructor and its generate method to make the test pass. ```javascript MathProblem = function(){} MathProblem.prototype.generate = function() {} // Green ``` -------------------------------- ### Create Typed Test Double from Function Type in TypeScript Source: https://context7.com/testdouble/testdouble.js/llms.txt Use `td.func()` to create a type-safe mock for a function. This is useful for mocking asynchronous operations or functions with specific signatures. The example shows mocking a `FetchUser` function type. ```typescript type FetchUser = (id: number) => Promise const mockFetch = td.func() td.when(mockFetch(1)).thenResolve({ id: 1, email: 'test@example.com', name: 'Test' }) ``` -------------------------------- ### Create a fake instance with td.instance Source: https://github.com/testdouble/testdouble.js/blob/main/README.md td.instance is a shorthand for td.constructor followed by creating a new instance. It returns a new instance of a fake constructor function. ```javascript const fakeObject = td.instance(RealConstructor) ``` ```javascript const FakeConstructor = td.constructor(RealConstructor) const fakeObject = new FakeConstructor() ``` -------------------------------- ### Create Typed Test Double from Abstract Class in TypeScript Source: https://context7.com/testdouble/testdouble.js/llms.txt Use `td.object()` to create a type-safe mock of an abstract class. This allows you to mock abstract methods and properties, ensuring type safety. The example demonstrates mocking an abstract `BaseRepository`. ```typescript abstract class BaseRepository { abstract find(id: number): T abstract save(entity: T): T } const mockBase = td.object>() td.when(mockBase.find(1)).thenReturn({ id: 1, email: 'a@b.com', name: 'Alice' }) ``` -------------------------------- ### Reset and Clean Working Directory Source: https://github.com/testdouble/testdouble.js/blob/main/RELEASE.md If a release attempt fails, use these commands to reset your local repository to a previous state, force push changes, delete local and remote tags, and clean untracked files before re-attempting. ```bash git reset --hard PREVIOUS_REF git push -f origin/main ``` ```bash git tag -d vX.Y.Z git push origin :vX.Y.Z ``` ```bash git clean -xdf ``` -------------------------------- ### Create Typed Test Double from Interface in TypeScript Source: https://context7.com/testdouble/testdouble.js/llms.txt Use `td.object()` to create a type-safe mock of an interface. TypeScript enforces that all methods and properties used on the mock adhere to the interface's definition. This example demonstrates mocking a `UserRepository` interface. ```typescript import * as td from 'testdouble' // Create typed test double from interface interface UserRepository { findById(id: number): User | null findByEmail(email: string): User | null save(user: User): User delete(id: number): boolean } interface User { id: number email: string name: string } const mockRepo = td.object() // TypeScript enforces correct types td.when(mockRepo.findById(1)).thenReturn({ id: 1, email: 'a@b.com', name: 'Alice' }) td.when(mockRepo.findById(td.matchers.isA(Number))).thenReturn(null) // Type errors caught at compile time: // td.when(mockRepo.findById('1')) // Error: string not assignable to number // td.when(mockRepo.findByID(1)) // Error: findByID does not exist // td.when(mockRepo.findById(1)).thenReturn('user') // Error: string not assignable to User ``` -------------------------------- ### Implement Subject Function to Pass Verification Source: https://github.com/testdouble/testdouble.js/blob/main/docs/3-getting-started.md Implement the `generate` method within the `MathProblem` constructor to ensure it calls the necessary dependencies in the correct order: create a problem, save it, and then submit the saved problem. This implementation makes the test pass. ```javascript function MathProblem(createRandomProblem, savesProblem, submitProblem) { this.createRandomProblem = createRandomProblem this.savesProblem = savesProblem this.submitProblem = submitProblem } MathProblem.prototype.generate = function(){ var problem = this.createRandomProblem(), savedProblem = this.savesProblem.save(problem) this.submitProblem(savedProblem) } ``` -------------------------------- ### Create Typed Test Double from Concrete Class in TypeScript Source: https://context7.com/testdouble/testdouble.js/llms.txt Use `td.object()` to create a type-safe mock of a concrete class. This ensures that the mock adheres to the class's methods and properties, including those inherited or implemented from interfaces. The example shows mocking a `ConcreteRepository` class. ```typescript class ConcreteRepository implements UserRepository { findById(id: number) { return null } findByEmail(email: string) { return null } save(user: User) { return user } delete(id: number) { return false } } const mockConcrete = td.object() ``` -------------------------------- ### td.when() Configuration Options Source: https://context7.com/testdouble/testdouble.js/llms.txt Modifies stubbing behavior using configuration options. ```APIDOC ## td.when(invocation, options) ### Description Additional options can be passed to `td.when()` to modify stubbing behavior including argument matching, invocation limits, and timing controls. ### Parameters #### Request Body - **invocation** (Function) - Required - The function call to stub. - **options** (Object) - Optional - Configuration object. - **ignoreExtraArgs** (Boolean) - Match regardless of additional arguments. - **times** (Number) - Limit number of times stubbing is satisfied. - **defer** (Boolean) - Invoke callbacks asynchronously. - **delay** (Number) - Wait milliseconds before completing. - **cloneArgs** (Boolean) - Compare against argument values at stubbing time. ### Request Example ```javascript td.when(logger('Error:'), { ignoreExtraArgs: true }).thenReturn('logged'); ``` ``` -------------------------------- ### Using td.matchers.argThat Source: https://github.com/testdouble/testdouble.js/blob/main/docs/5-stubbing-results.md Explains how to use `argThat` to provide a custom predicate function for matching arguments based on specific conditions. ```APIDOC ## GET /api/users/{id} ### Description Retrieves a specific user by their unique identifier. ### Method GET ### Endpoint /api/users/{id} ### Parameters #### Path Parameters - **id** (string) - Required - The unique identifier of the user to retrieve. ### Response #### Success Response (200) - **id** (string) - The unique identifier for the user. - **name** (string) - The name of the user. - **email** (string) - The email address of the user. #### Response Example ```json { "id": "user-123", "name": "John Doe", "email": "john.doe@example.com" } ``` ``` -------------------------------- ### Inspecting a Test Double Source: https://github.com/testdouble/testdouble.js/blob/main/docs/3-getting-started.md Demonstrates how to use `td.explain` to inspect the state of a test double, showing call counts, stubbings, and invocations. ```javascript { callCount: 0, calls: [], description: "This test double `createRandomProblem` has 0 stubbings and 0 invocations." } ``` -------------------------------- ### Creating a Test Double Function Source: https://github.com/testdouble/testdouble.js/blob/main/docs/3-getting-started.md Creates a test double for a function named 'createRandomProblem' and passes it as a dependency to the MathProblem constructor. ```javascript describe('MathProblem', function(){ var subject, createRandomProblem; beforeEach(function(){ createRandomProblem = td.function('createRandomProblem') subject = new MathProblem(createRandomProblem) }) it('POSTs a random problem', function(){ subject.generate() }) }) ``` -------------------------------- ### Create a test double constructor from function names Source: https://github.com/testdouble/testdouble.js/blob/main/docs/4-creating-test-doubles.md Create a constructable object with specific instance methods by passing an array of function names to td.constructor. ```javascript var FakeCat = td.constructor(['meow', 'scratch']) FakeCat.prototype.meow // a test double function named '#meow' FakeCat.prototype.scratch // a test double function named '#scratch' ``` -------------------------------- ### Create Custom Argument Matchers with td.matchers.create() Source: https://context7.com/testdouble/testdouble.js/llms.txt Define custom argument matchers for complex scenarios using td.matchers.create(). This allows for flexible matching based on value, type, or even side effects. ```javascript import * as td from 'testdouble' // Create a custom 'between' matcher for numbers const between = td.matchers.create({ name: 'between', matches: function(matcherArgs, actual) { const [min, max] = matcherArgs return typeof actual === 'number' && actual >= min && actual <= max } }) const rateLimit = td.function('rateLimit') td.when(rateLimit(between(1, 100))).thenReturn('allowed') td.when(rateLimit(between(101, 1000))).thenReturn('throttled') rateLimit(50) // 'allowed' rateLimit(150) // 'throttled' rateLimit(1500) // undefined // Create matcher with dynamic name const hasProperty = td.matchers.create({ name: function(matcherArgs) { return `hasProperty(${matcherArgs[0]})` }, matches: function(matcherArgs, actual) { const propName = matcherArgs[0] return actual && propName in actual } }) const process = td.function('process') td.when(process(hasProperty('id'))).thenReturn('has id') process({ id: 1, name: 'test' }) // 'has id' process({ name: 'test' }) // undefined // Matcher with side effects via onCreate const trackUsage = td.matchers.create({ name: 'trackUsage', matches: () => true, onCreate: function(matcherInstance, matcherArgs) { matcherInstance.usageCount = 0 }, afterSatisfaction: function(matcherArgs, actual) { console.log(`Matcher satisfied with: ${actual}`) } }) ``` -------------------------------- ### Publish Release Source: https://github.com/testdouble/testdouble.js/blob/main/RELEASE.md Use this command to publish a new release to npm. Specify 'patch', 'minor', or 'major' to bump the appropriate version segment. This command automates tagging, pushing to GitHub, updating the changelog, and publishing to npm. ```bash npm version patch #<-- or "minor" or "major" ``` -------------------------------- ### td.instance() Source: https://github.com/testdouble/testdouble.js/blob/main/docs/4-creating-test-doubles.md A convenience method that instantiates a constructor created by td.constructor(). ```APIDOC ## td.instance(constructorOrArrayOfNames) ### Description Performs a no-arg instantiation of a constructor mock. ### Parameters - **constructorOrArrayOfNames** (Function|Array) - Required - The constructor or array of names to instantiate. ``` -------------------------------- ### Creating multiple test doubles Source: https://github.com/testdouble/testdouble.js/blob/main/docs/3-getting-started.md Initialize multiple test doubles within a beforeEach block to prepare the subject under test. ```javascript describe('MathProblem', function(){ var subject, createRandomProblem, savesProblem, submitProblem; beforeEach(function(){ createRandomProblem = td.function('createRandomProblem') savesProblem = td.object(SavesProblem) submitProblem = td.function('submitProblem') subject = new MathProblem(createRandomProblem, savesProblem, submitProblem) }) it('POSTs a random problem', function(){ // ... }) }) ``` -------------------------------- ### Explain a test double with stubbings Source: https://github.com/testdouble/testdouble.js/blob/main/docs/9-debugging.md When stubbings are configured, `td.explain()` will list them in the description. This helps in verifying that stubbings are set up as intended. ```javascript td.when(myTestDouble(5)).thenReturn(10) td.explain(myTestDouble) /* { name: 'someFunction', callCount: 0, calls: [], description: 'This test double `.someFunction` has 1 stubbings and 0 invocations. Stubbings: - when called with `(5)`, then return `10`.' } */ ``` -------------------------------- ### Default Stubbing Behavior (Argument Mutation) Source: https://github.com/testdouble/testdouble.js/blob/main/docs/5-stubbing-results.md Demonstrates the default behavior where stubbing is satisfied even if arguments are mutated after configuration. This can lead to unexpected results if the stubbing is based on the initial state of the arguments. ```javascript const func = td.func() const person = { age: 17 } td.when(func(person)).thenReturn('minor') // Later, in your code person.age = 30 func(person) // 'minor' ``` -------------------------------- ### Configure non-native Promise library Source: https://github.com/testdouble/testdouble.js/blob/main/docs/5-stubbing-results.md If using a non-native Promise library, configure testdouble.js to use it by setting the `promiseConstructor` option. This only needs to be done once. ```js td.config({ promiseConstructor: require('bluebird') }) ``` -------------------------------- ### Defining a constructor for a dependency Source: https://github.com/testdouble/testdouble.js/blob/main/docs/3-getting-started.md Define a constructor function and prototype method to represent a dependency that will be mocked. ```javascript function SavesProblem() {} SavesProblem.prototype.save = function(){} ``` -------------------------------- ### Implement subject under test Source: https://github.com/testdouble/testdouble.js/blob/main/docs/7-replacing-dependencies.md The subject module consumes the dependency via require. ```javascript var brake = require('./brake') module.exports.slowDown = function(){ brake(10) } ``` -------------------------------- ### List replaced modules with td.listReplacedModules() Source: https://github.com/testdouble/testdouble.js/blob/main/README.md Retrieve an array of full paths for modules currently being replaced by td.replace() or td.replaceEsm(). ```js td.replace('../src/save') ``` ```js td.listReplacedModules() ``` ```js ['file:///users/example/code/foo/src/save.js'] ``` -------------------------------- ### One-Liner Stubbing Configuration Source: https://github.com/testdouble/testdouble.js/blob/main/docs/5-stubbing-results.md Create and stub a test double in a single line. This is a concise way to set up a one-off stubbing. ```javascript var woof = td.when(td.function()()).thenReturn('bark') ``` -------------------------------- ### Stubbing with cloneArgs: true Source: https://github.com/testdouble/testdouble.js/blob/main/docs/5-stubbing-results.md Shows how to use `cloneArgs: true` to ensure stubbing is only satisfied if the arguments remain unchanged from the time of configuration. This is useful when the arguments might be mutated by the code under test. ```javascript const func = td.func() const person = { age: 17 } td.when(func(person), { cloneArgs: true }).thenReturn('minor') // Later, in your code person.age = 30 func(person) // undefined ``` -------------------------------- ### Create Test Double from Real Function with Properties Source: https://github.com/testdouble/testdouble.js/blob/main/docs/4-creating-test-doubles.md Create a test double function that inherits properties from a real function. Any function properties on the original function will also be replaced with test double functions. ```javascript function meow () { throw 'unimplemented' } meow.volume = 'loud' meow.stop = function () {} var fakeMeow = td.function(meow) // test double for "meow" fakeMeow.volume // 'loud' fakeMeow.stop // test double for "meow.stop" ``` -------------------------------- ### Configure Promise Constructor Source: https://github.com/testdouble/testdouble.js/blob/main/README.md Specify a custom Promise constructor, such as bluebird, for use with thenResolve and thenReject. ```javascript td.config({promiseConstructor: require('bluebird')}) ``` -------------------------------- ### Instantiate a test double constructor Source: https://github.com/testdouble/testdouble.js/blob/main/docs/4-creating-test-doubles.md Use td.instance as a convenience method to create an instance of a test double constructor directly. ```javascript const dog = td.instance(Dog) ``` ```javascript const FakeDog = td.constructor(Dog) const dog = new FakeDog() ``` -------------------------------- ### Using td.matchers.anything() for flexible verification Source: https://github.com/testdouble/testdouble.js/blob/main/docs/6-verifying-invocations.md The `td.matchers.anything()` matcher asserts that an argument was provided, regardless of its value. It's useful when the specific value of an argument doesn't matter for the verification. ```javascript var bark = td.function() bark('woof') td.verify(bark('woof')) // passes td.verify(bark(td.matchers.anything())) // passes td.verify(bark(td.matchers.anything(), td.matchers.anything())) // throws - was 1 arg td.verify(bark()) // throws - 1 arg needed ``` -------------------------------- ### td.config Source: https://github.com/testdouble/testdouble.js/blob/main/docs/C-configuration.md Configures global settings for testdouble.js. These settings persist for the duration of the test suite unless manually reverted. ```APIDOC ## td.config ### Description Configures global options for testdouble.js. Settings are persisted for the duration of the test suite. ### Method Function Call ### Parameters #### Request Body - **ignoreWarnings** (boolean) - Optional - Set to true to squelch generated console warnings. Default: false. - **promiseConstructor** (object) - Optional - The promise constructor to use. Default: native Promise. - **suppressErrors** (boolean) - Optional - Set to true to no longer throw API errors. Default: false. ### Request Example ```js td.config({ ignoreWarnings: false, promiseConstructor: Promise, suppressErrors: false }) ``` ``` -------------------------------- ### Define a subject module using a dependency Source: https://github.com/testdouble/testdouble.js/blob/main/docs/7-replacing-dependencies.md A sample module that depends on an external library, intended to be tested by replacing that dependency. ```javascript var isNumber = require('is-number') module.exports = function (thing) { if (!isNumber(thing)) { throw new Error('numbers only!') } return true } ``` -------------------------------- ### Subject Instantiation and Invocation Source: https://github.com/testdouble/testdouble.js/blob/main/docs/3-getting-started.md Instantiates the subject under test and invokes its generate method within a beforeEach block. ```javascript describe('MathProblem', function(){ var subject; before(function(){ subject = new MathProblem() }) it('POSTs a random problem', function(){ subject.generate() }) // Red -- ReferenceError: MathProblem is not defined }) ``` -------------------------------- ### Configure testdouble.js Global Options Source: https://github.com/testdouble/testdouble.js/blob/main/docs/C-configuration.md Use td.config to set global options like ignoreWarnings, promiseConstructor, and suppressErrors. Configuration is persisted throughout the test suite; manage changes for individual tests manually. ```javascript td.config({ ignoreWarnings: false, // set to true to squelch generated console warnings promiseConstructor: Promise // defaults to native Promise (if available) suppressErrors: false // set to true to no longer throw API errors }) ``` -------------------------------- ### Using td.matchers.anything() Source: https://github.com/testdouble/testdouble.js/blob/main/docs/5-stubbing-results.md Ignore specific parameters during stub matching by using the anything matcher. ```javascript var bark = td.function() td.when(bark(td.matchers.anything())).thenReturn('woof') bark(1) // 'woof' bark('lol') // 'woof' bark() // undefined bark(2, 'other stuff') // undefined ``` -------------------------------- ### td.verify() - Basic Usage Source: https://github.com/testdouble/testdouble.js/blob/main/docs/6-verifying-invocations.md Demonstrates the basic usage of `td.verify()` to check if a test double function was called with specific arguments. If the verification is satisfied, nothing happens. If it fails, an error is thrown. ```APIDOC ## td.verify() ### Description A basic verification looks like this: ### Method `td.verify` ### Endpoint N/A (Function within the testdouble.js library) ### Parameters This function takes arguments that mirror the expected invocation of the test double. ### Request Example ```javascript var quack = td.function('quack') quack('QUACK') td.verify(quack('QUACK')) // Nothing happens, because verification was satisfied ``` ### Response No direct response, but throws an error if verification fails. #### Error Response Example ``` Error: Unsatisfied verification on test double `quack`. Wanted: - called with `()`. But was actually called: - called with `("QUACK")`. ``` ``` -------------------------------- ### td.constructor() - Creating Test Double Constructors Source: https://context7.com/testdouble/testdouble.js/llms.txt Creates a fake constructor function or ES class with all prototypal and static methods replaced by test doubles. Useful for testing code that instantiates dependencies. ```APIDOC ## td.constructor() ### Description Creates a fake constructor function or ES class with all prototypal and static methods replaced by test doubles. Useful for testing code that instantiates dependencies. ### Method `td.constructor(constructorOrNames)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```javascript import * as td from 'testdouble' // Create from existing constructor function RealDatabase() {} RealDatabase.prototype.query = function() {} RealDatabase.prototype.close = function() {} RealDatabase.connect = function() {} // static method const FakeDatabase = td.constructor(RealDatabase) FakeDatabase.prototype.query // test double for 'RealDatabase#query' FakeDatabase.connect // test double for 'RealDatabase.connect' // Stub the prototype, use on instances td.when(FakeDatabase.prototype.query('SELECT * FROM users')).thenReturn([ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]) const db = new FakeDatabase() db.query('SELECT * FROM users') // [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }] // Create from array of method names const FakeCache = td.constructor(['get', 'set', 'delete']) FakeCache.prototype.get // test double function named '#get' FakeCache.prototype.set // test double function named '#set' ``` ### Response #### Success Response (200) Returns a test double constructor. #### Response Example (A test double constructor) ``` -------------------------------- ### td.when() Source: https://github.com/testdouble/testdouble.js/blob/main/README.md Configures stubbing for test double functions by rehearsing an invocation and defining the desired outcome. ```APIDOC ## td.when(rehearsal[, options]) ### Description Defines how a test double should behave when invoked with specific arguments. ### Parameters - **rehearsal** (Function) - Required - A call to the test double demonstrating the expected invocation. - **options** (Object) - Optional - Configuration object for advanced stubbing behavior. ### Methods - **thenReturn(value[, ...values])** - Specifies the value(s) to return when the rehearsal is matched. ``` -------------------------------- ### Configure td.when() Options Source: https://context7.com/testdouble/testdouble.js/llms.txt Modifies stubbing behavior using options like ignoreExtraArgs, times, defer, delay, and cloneArgs. ```javascript import * as td from 'testdouble' const logger = td.function('logger') // ignoreExtraArgs - match regardless of additional arguments td.when(logger('Error:'), { ignoreExtraArgs: true }).thenReturn('logged') logger('Error:') // 'logged' logger('Error:', 'details', 123) // 'logged' logger('Info:') // undefined // times - limit number of times stubbing is satisfied const getToken = td.function('getToken') td.when(getToken(), { times: 2 }).thenReturn('token123') td.when(getToken()).thenReturn('expired') getToken() // 'token123' getToken() // 'token123' getToken() // 'expired' (falls back after times exhausted) // defer - invoke callbacks asynchronously const asyncOp = td.function('asyncOp') td.when(asyncOp(), { defer: true }).thenCallback(null, 'result') // delay - wait milliseconds before completing const slowFetch = td.function('slowFetch') td.when(slowFetch('/slow'), { delay: 100 }).thenResolve('done') // cloneArgs - compare against argument values at stubbing time const func = td.function('func') const obj = { value: 1 } td.when(func(obj), { cloneArgs: true }).thenReturn('original') obj.value = 2 func(obj) // undefined (obj changed since stubbing) ``` -------------------------------- ### td.verify() - Argument Matchers Source: https://github.com/testdouble/testdouble.js/blob/main/docs/6-verifying-invocations.md Details how to use argument matchers with `td.verify()` to relax verification conditions. ```APIDOC ### Relaxing verifications with argument matchers Each of the argument matchers supported when stubbing also work when verifying an interaction. Below are simple examples of each built-in matcher. #### td.matchers.anything() The `anything()` matcher will only ensure that an argument was passed, but will ignore whatever its value was. ##### Request Example ```javascript var bark = td.function() bark('woof') td.verify(bark('woof')) // passes td.verify(bark(td.matchers.anything())) // passes td.verify(bark(td.matchers.anything(), td.matchers.anything())) // throws - was 1 arg td.verify(bark()) // throws - 1 arg needed ``` #### td.matchers.isA() The `isA()` matcher can be used to verify a matching type for a given argument. ##### Request Example ```javascript var eatBiscuit = td.function() eatBiscuit(44) td.verify(eatBiscuit(44)) // passes td.verify(eatBiscuit(td.matchers.isA(Number))) // passes td.verify(eatBiscuit(td.matchers.isA(Date))) // throws - 44 is not a Date td.verify(eatBiscuit(td.matchers.isA(Object))) // throws - Number is not an Object ``` #### td.matchers.contains() The contains matcher is satisified if the passed-in portion of a string, array, or object is found on an actual invocation of the test double. ##### Strings ```javascript var log = td.function() log('Why hello there!') td.verify(log('Why hello there!')) // passes td.verify(log(td.matchers.contains('hello'))) // passes td.verify(log(td.matchers.contains('goodbye'))) // throws - string not found ``` ``` -------------------------------- ### td.when().thenReturn() Source: https://github.com/testdouble/testdouble.js/blob/main/docs/5-stubbing-results.md Configures a test double to return a sequence of values when invoked multiple times. ```APIDOC ## td.when().thenReturn() ### Description Configures a test double to return a specific sequence of values upon successive invocations. If the function is called more times than values provided, the final value in the sequence is returned for all subsequent calls. ### Request Example ```javascript var randomSound = td.function('randomSound'); td.when(randomSound()).thenReturn('quack', 'honk', 'moo'); ``` ### Response - **First call**: 'quack' - **Second call**: 'honk' - **Third call**: 'moo' - **Subsequent calls**: 'moo' ``` -------------------------------- ### Create a custom 'isA' argument matcher Source: https://github.com/testdouble/testdouble.js/blob/main/docs/8-custom-matchers.md Define a custom matcher named 'isA' that checks if an argument is an instance of a specified type. This matcher can be used in `td.when()` and `td.verify()` calls. ```javascript isA = td.matchers.create({ name: 'isA', matches: function(matcherArgs, actual) { var expected = matcherArgs[0] return actual instanceof expected } }) ``` -------------------------------- ### Prototype dependency for replacement Source: https://github.com/testdouble/testdouble.js/blob/main/docs/7-replacing-dependencies.md Export a function from the dependency file so testdouble.js can correctly identify it as a function double. ```javascript module.exports = function(){} ``` -------------------------------- ### Create an Unnamed Test Double Function Source: https://github.com/testdouble/testdouble.js/blob/main/docs/4-creating-test-doubles.md Use `td.function()` to create a basic test double function. This double can be configured with `td.when`, verified with `td.verify`, and inspected with `td.explain`. ```javascript var bark = td.function() // '[test double (unnamed)]' ``` -------------------------------- ### Other Utility Functions Source: https://github.com/testdouble/testdouble.js/blob/main/README.md Provides access to other utility functions for debugging, configuration, and state management. ```APIDOC ## Other top-level features in the testdouble.js API ### `td.explain(someTestDouble)` - **Description**: Helps in debugging and introspecting test doubles. - **Link**: [/docs/9-debugging.md#tdexplainsometestdouble](/docs/9-debugging.md#tdexplainsometestdouble) ### `td.config(options)` - **Description**: Changes globally configurable options for testdouble.js. - **Link**: [/docs/C-configuration.md#tdconfig](/docs/C-configuration.md#tdconfig) ### `td.reset()` - **Description**: Resets testdouble.js state between test runs. - **Link**: [/docs/1-installation.md#resetting-state-between-test-runs](/docs/1-installation.md#resetting-state-between-test-runs) ### `td.matchers` and custom matchers - **Description**: Used for configuring more advanced stubbings and verifications with argument matchers. - **Link**: [/docs/5-stubbing-results.md#loosening-stubbings-with-argument-matchers](/docs/5-stubbing-results.md#loosening-stubbings-with-argument-matchers), [/docs/8-custom-matchers.md#custom-argument-matchers](/docs/8-custom-matchers.md#custom-argument-matchers) ``` -------------------------------- ### defer Option Source: https://github.com/testdouble/testdouble.js/blob/main/docs/5-stubbing-results.md Schedules callback invocations to a later execution stack. ```APIDOC ## defer Option ### Description The `defer` option, when set to `true`, ensures that stubbed callbacks are invoked asynchronously on a later execution stack. This is useful for testing scenarios where the subject under test might incorrectly rely on synchronous callback execution. ### Method `td.when(..., {defer: true}).thenCallback(...)` ### Endpoint N/A (This is a configuration option for stubbing) ### Parameters #### Options Object - **defer** (boolean) - Required - If `true`, the callback will be deferred to the next tick of the event loop. ### Request Example ```javascript var fetchBalance = td.function('.fetchBalance') var print = td.function('.print') td.when(fetchBalance(42), {defer: true}).thenCallback(null, 1337) // ... subject under test code ... // Note: The test function needs to be asynchronous (e.g., use a 'done' callback) ``` ### Response N/A (This option affects stubbing behavior, not direct response values) ``` -------------------------------- ### td.constructor() Source: https://github.com/testdouble/testdouble.js/blob/main/docs/4-creating-test-doubles.md Creates artificial constructor functions where all prototype and static functions are replaced by test doubles. ```APIDOC ## td.constructor(someConstructorFunction) ### Description Creates a test double of a constructor function, including prototype and static methods. ### Parameters - **someConstructorFunction** (Function) - Required - The constructor or class to mock. ## td.constructor(arrayOfFunctionNames) ### Description Creates a constructable object with instance methods defined from an array of names. ### Parameters - **arrayOfFunctionNames** (Array) - Required - List of instance method names. ``` -------------------------------- ### Using td.matchers.anything() for Flexible Matching Source: https://context7.com/testdouble/testdouble.js/llms.txt Use td.matchers.anything() to match any single argument in stubbings or verifications when the exact value is not important. It matches any value, including undefined if no argument is passed. ```javascript import * as td from 'testdouble' const process = td.function('process') // td.matchers.anything() - matches any single argument td.when(process(td.matchers.anything())).thenReturn('processed') process('any value') // 'processed' process(12345) // 'processed' process({ complex: {} }) // 'processed' process() // undefined (no argument passed) ``` -------------------------------- ### Basic Stubbing with td.when() Source: https://github.com/testdouble/testdouble.js/blob/main/docs/5-stubbing-results.md Configure a test double function to return a specific value when called. The `td.when()` function rehearses the invocation to be stubbed. ```javascript var quack = td.function('quack') td.when(quack()).thenReturn('some return value') quack() // 'some return value' ``` -------------------------------- ### Stub Function to Execute Custom Logic Source: https://github.com/testdouble/testdouble.js/blob/main/README.md Use thenDo to provide a function that will be executed when the stubbing is satisfied. The return value of this function will be the return value of the stubbed function. ```javascript td.when(__rehearsal__[, options]).thenDo(function (arg1, arg2) {}) ``` -------------------------------- ### Explain a test double with invocations Source: https://github.com/testdouble/testdouble.js/blob/main/docs/9-debugging.md After a test double has been invoked, `td.explain()` will detail the calls made, including arguments and context. This is crucial for debugging unexpected behavior or verifying call sequences. ```javascript myTestDouble(7) // undefined td.explain(myTestDouble) /* { name: '.someFunction', callCount: 1, calls: [ { args: [7], context: window } ], description: 'This test double has 1 stubbings and 1 invocations. Stubbings: - when called with `(5)`, then return `10`. Invocations: - called with `(7)`.' } */ ``` -------------------------------- ### Using td.matchers.isA() Source: https://github.com/testdouble/testdouble.js/blob/main/docs/5-stubbing-results.md Match arguments based on their type, such as Number, String, or custom constructors. ```javascript var eatBiscuit = td.function() td.when(eatBiscuit(td.matchers.isA(Number))).thenReturn('yum') eatBiscuit(5) // 'yum' eatBiscuit('stuff') // undefined eatBiscuit() // undefined ``` -------------------------------- ### td.matchers.create Source: https://github.com/testdouble/testdouble.js/blob/main/docs/8-custom-matchers.md Defines a custom argument matcher for use in td.when() or td.verify() calls. ```APIDOC ## td.matchers.create ### Description Creates a custom argument matcher object that can be used to validate arguments passed to test double functions. ### Parameters #### Request Body - **matches** (function) - Required - A function that returns truthy when an 'actual' argument satisfies the matcher's rules, given 'matcherArgs'. - **name** (string|function) - Optional - A string name or a function returning a string for better error messages. - **onCreate** (function) - Optional - A function invoked when an instance of the matcher is created. - **afterSatisfaction** (function) - Optional - A function invoked when the matcher is satisfied during a stubbing or verification. ### Request Example { "name": "isA", "matches": "function(matcherArgs, actual) { return actual instanceof matcherArgs[0] }" } ``` -------------------------------- ### Create a fake constructor with td.constructor Source: https://github.com/testdouble/testdouble.js/blob/main/README.md Use td.constructor to create a fake constructor function. Its prototype functions are replaced with test double functions. Configure stubbing by addressing its prototype functions. ```javascript const FakeConstructor = td.constructor(RealConstructor) td.when(FakeConstructor.prototype.doStuff()).thenReturn('ok') subject(FakeConstructor) ``` ```javascript const subject = function (SomeConstructor) { const thing = new SomeConstructor() return thing.doStuff() // returns "ok" } ``` ```javascript const FakeConstructor = td.constructor(['select', 'save']) ``` -------------------------------- ### td.listReplacedModules() - Listing Replaced Modules Source: https://github.com/testdouble/testdouble.js/blob/main/README.md Retrieves a list of all modules currently being replaced by testdouble.js. ```APIDOC ## td.listReplacedModules() for listing the modules that were replaced ### Description Returns an array of the full paths to modules that are currently being replaced via `td.replace()` or `td.replaceEsm()`. ### Method `td.listReplacedModules()` ### Response - `Array`: An array of file URLs (e.g., `file:///path/to/module.js`) representing the replaced modules. ### Request Example ```javascript // Assuming '../src/save' has been replaced td.listReplacedModules() // Returns something like: ['file:///users/example/code/foo/src/save.js'] ``` ``` -------------------------------- ### Node.js Module Replacement with td.replace Source: https://github.com/testdouble/testdouble.js/blob/main/docs/7-replacing-dependencies.md Use td.replace('../path/to/dependency') to intercept require calls and provide a fake module. The original module is restored after td.reset(). ```javascript td.replace('../path/to/dependency') ``` -------------------------------- ### Create a Test Double Object Imitating a Real Object Source: https://github.com/testdouble/testdouble.js/blob/main/README.md Pass a real object to td.object to create a deep imitation. Functions within the object are replaced with test double functions named for their property path. ```javascript td.object(realObject) ``` -------------------------------- ### Create Test Double Functions with td.function() Source: https://context7.com/testdouble/testdouble.js/llms.txt Use td.function() to create fake functions for stubbing or verification. Named functions are recommended for better debugging. Properties from real functions are preserved. ```javascript import * as td from 'testdouble' // Create an anonymous test double function const anonymousDouble = td.function() // Create a named test double function (recommended for debugging) const namedDouble = td.function('.fetchUser') // Create from an existing function (copies properties) function realFetch() { throw 'unimplemented' } realFetch.timeout = 5000 realFetch.retry = function() {} const fakeFetch = td.function(realFetch) fakeFetch.timeout // 5000 (preserved) fakeFetch.retry // test double for "realFetch.retry" // Use the test double td.when(namedDouble(123)).thenReturn({ id: 123, name: 'Alice' }) namedDouble(123) // { id: 123, name: 'Alice' } namedDouble(456) // undefined (no stubbing matched) ``` -------------------------------- ### Create a Test Double Function Imitating a Real Function Source: https://github.com/testdouble/testdouble.js/blob/main/README.md Pass a real function to td.func to create a test double that imitates its name and custom properties. This preserves some characteristics of the original function. ```javascript td.func(someRealFunction) ``` -------------------------------- ### Verify function interactions with td.verify() Source: https://github.com/testdouble/testdouble.js/blob/main/README.md Use this to assert that a dependency was called with specific arguments after exercising the subject under test. ```js module.exports = function shouldSaveThings () { const save = td.replace('../src/save') const subject = require('../src/index') subject({name: 'dataz', data: '010101'}) td.verify(save('dataz', '010101')) } ``` -------------------------------- ### td.object() Source: https://github.com/testdouble/testdouble.js/blob/main/docs/4-creating-test-doubles.md Creates a test double object from an existing object, an array of function names, or a string name using a Proxy. ```APIDOC ## td.object(someObjectWithFunctions) ### Description Creates a deep copy of an object and replaces all functions with test doubles. ### Parameters - **someObjectWithFunctions** (Object) - Required - The object to clone and mock. ## td.object(functionNames) ### Description Creates a plain object with properties set as named test double functions. ### Parameters - **functionNames** (Array) - Required - List of function names to create. ## td.object([objectName]) ### Description Returns an ES2015 Proxy object that forwards property access as test double functions. ### Parameters - **objectName** (string) - Optional - Name for the proxy object. - **options** (Object) - Optional - Configuration object. - **excludeMethods** (Array) - Optional - Methods to exclude from the proxy. ``` -------------------------------- ### td.when() Source: https://github.com/testdouble/testdouble.js/blob/main/docs/5-stubbing-results.md Configures a test double to return a specific value when invoked with matching arguments. ```APIDOC ## td.when() ### Description Configures a test double to return a specific value when invoked with a rehearsed set of arguments. The function returns an object with methods like thenReturn, thenDo, and thenThrow. ### Parameters - **rehearsal** (function call) - Required - A call to a test double function representing the expected invocation. ### Request Example ```javascript var quack = td.function('quack'); td.when(quack()).thenReturn('some return value'); ``` ### Response - **Stubbing Object** (object) - Returns an object containing thenReturn, thenDo, and thenThrow methods. ``` -------------------------------- ### Create a test double from a constructor function Source: https://github.com/testdouble/testdouble.js/blob/main/docs/4-creating-test-doubles.md Pass a constructor or class to td.constructor to return a constructor where all prototype and static functions are replaced by test doubles. ```javascript function Dog(){} Dog.prototype.bark = function(){} Dog.woof = function(){} ``` ```javascript var FakeDog = td.constructor(Dog) FakeDog.prototype.bark // a test double function named 'Dog#bark' FakeDog.woof // a test double function named 'Dog.woof' ``` ```javascript td.when(FakeDog.prototype.bark()).thenReturn('YIP') var dog = new FakeDog() dog.bark() // 'YIP ``` -------------------------------- ### Create Test Double Constructors with td.constructor() Source: https://context7.com/testdouble/testdouble.js/llms.txt Use td.constructor() to create fake constructors or ES classes. It replaces prototypal and static methods with test doubles, useful for testing instantiation. Stubs can be applied to the prototype. ```javascript import * as td from 'testdouble' // Create from existing constructor function RealDatabase() {} RealDatabase.prototype.query = function() {} RealDatabase.prototype.close = function() {} RealDatabase.connect = function() {} // static method const FakeDatabase = td.constructor(RealDatabase) FakeDatabase.prototype.query // test double for 'RealDatabase#query' FakeDatabase.connect // test double for 'RealDatabase.connect' // Stub the prototype, use on instances td.when(FakeDatabase.prototype.query('SELECT * FROM users')).thenReturn([ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]) const db = new FakeDatabase() db.query('SELECT * FROM users') // [{ id: 1, name: 'Alice' }, { id: 2, name: 'Bob' }] // Create from array of method names const FakeCache = td.constructor(['get', 'set', 'delete']) FakeCache.prototype.get // test double function named '#get' FakeCache.prototype.set // test double function named '#set' ```