From 7f2c8c28bf1c2538cf3671d0bc4016cb0ed8c850 Mon Sep 17 00:00:00 2001 From: Morgan Roderick Date: Fri, 1 Mar 2019 23:08:31 +0000 Subject: [PATCH] Add release documentation for v7.2.6 --- docs/_releases/latest.md | 2 +- docs/_releases/v7.2.6.md | 51 ++ docs/_releases/v7.2.6/assertions.md | 202 ++++++ docs/_releases/v7.2.6/fake-timers.md | 140 ++++ docs/_releases/v7.2.6/fake-xhr-and-server.md | 395 +++++++++++ docs/_releases/v7.2.6/fakes.md | 178 +++++ docs/_releases/v7.2.6/general-setup.md | 33 + docs/_releases/v7.2.6/json-p.md | 18 + docs/_releases/v7.2.6/matchers.md | 266 ++++++++ docs/_releases/v7.2.6/mocks.md | 174 +++++ docs/_releases/v7.2.6/sandbox.md | 302 +++++++++ docs/_releases/v7.2.6/spies.md | 438 ++++++++++++ docs/_releases/v7.2.6/spy-call.md | 145 ++++ docs/_releases/v7.2.6/stubs.md | 664 +++++++++++++++++++ docs/_releases/v7.2.6/utils.md | 25 + 15 files changed, 3032 insertions(+), 1 deletion(-) create mode 100644 docs/_releases/v7.2.6.md create mode 100644 docs/_releases/v7.2.6/assertions.md create mode 100644 docs/_releases/v7.2.6/fake-timers.md create mode 100644 docs/_releases/v7.2.6/fake-xhr-and-server.md create mode 100644 docs/_releases/v7.2.6/fakes.md create mode 100644 docs/_releases/v7.2.6/general-setup.md create mode 100644 docs/_releases/v7.2.6/json-p.md create mode 100644 docs/_releases/v7.2.6/matchers.md create mode 100644 docs/_releases/v7.2.6/mocks.md create mode 100644 docs/_releases/v7.2.6/sandbox.md create mode 100644 docs/_releases/v7.2.6/spies.md create mode 100644 docs/_releases/v7.2.6/spy-call.md create mode 100644 docs/_releases/v7.2.6/stubs.md create mode 100644 docs/_releases/v7.2.6/utils.md diff --git a/docs/_releases/latest.md b/docs/_releases/latest.md index ab8c452cf..a3c243d23 100644 --- a/docs/_releases/latest.md +++ b/docs/_releases/latest.md @@ -1,7 +1,7 @@ --- layout: page title: API documentation - Sinon.JS -release_id: v7.2.5 +release_id: v7.2.6 --- # {{page.title}} - `{{page.release_id}}` diff --git a/docs/_releases/v7.2.6.md b/docs/_releases/v7.2.6.md new file mode 100644 index 000000000..a3c243d23 --- /dev/null +++ b/docs/_releases/v7.2.6.md @@ -0,0 +1,51 @@ +--- +layout: page +title: API documentation - Sinon.JS +release_id: v7.2.6 +--- + +# {{page.title}} - `{{page.release_id}}` + +This page contains the entire Sinon.JS API documentation along with brief introductions to the concepts Sinon implements. + +* [General setup](./general-setup) +* [Fakes](./fakes) +* [Spies](./spies) +* [Stubs](./stubs) +* [Mocks](./mocks) +* [Spy calls](./spy-call) +* [Fake timers](./fake-timers) +* [Fake XHR and server](./fake-xhr-and-server) +* [JSON-P](./json-p) +* [Assertions](./assertions) +* [Matchers](./matchers) +* [Sandboxes](./sandbox) +* [Utils](./utils) + +{% include docs/migration-guides.md %} + +### Compatibility + +### ES5.1 + +Sinon `{{page.release_id}}` is written as [ES5.1][ES5] and requires no transpiler or polyfills to run in the runtimes listed below. + +### Supported runtimes + +`{{page.release_id}}` has been verified in these runtimes: + +* Firefox 45 +* Chrome 48 +* Internet Explorer 11 +* Edge 14 +* Safari 9 +* [Node.js LTS versions](https://github.com/nodejs/Release) + +There should not be any issues with using Sinon `{{page.release_id}}` in newer versions of the same runtimes. + +If you need to support very old runtimes that have incomplete support for [ES5.1][ES5] you might get away with using loading [`es5-shim`][es5-shim] in your test environment. + +{% include docs/contribute.md %} + +[ES5]: http://www.ecma-international.org/ecma-262/5.1/ +[es5-shim]: https://github.com/es-shims/es5-shim diff --git a/docs/_releases/v7.2.6/assertions.md b/docs/_releases/v7.2.6/assertions.md new file mode 100644 index 000000000..1d0302be1 --- /dev/null +++ b/docs/_releases/v7.2.6/assertions.md @@ -0,0 +1,202 @@ +--- +layout: page +title: Assertions - Sinon.JS +breadcrumb: assertions +--- + +Sinon.JS ships with a set of assertions that mirror most behavior verification methods and properties on spies and stubs. The advantage of using the assertions is that failed expectations on stubs and spies can be expressed directly as assertion failures with detailed and helpful error messages. + +To make sure assertions integrate nicely with your test framework, you should customize either `sinon.assert.fail` or `sinon.assert.failException` and look into `sinon.assert.expose` and `sinon.assert.pass`. + +The assertions can be used with either spies or stubs. + +```javascript +"test should call subscribers with message as first argument" : function () { + var message = "an example message"; + var spy = sinon.spy(); + + PubSub.subscribe(message, spy); + PubSub.publishSync(message, "some payload"); + + sinon.assert.calledOnce(spy); + sinon.assert.calledWith(spy, message); +} +``` + +## Assertions API + +#### `sinon.assert.fail(message)` + +Every assertion fails by calling this method. + +By default it throws an error of type `sinon.assert.failException`. + +If the test framework looks for assertion errors by checking for a specific exception, you can simply override the kind of exception thrown. If that does not fit with your testing framework of choice, override the `fail` method to do the right thing. + + +#### `sinon.assert.failException;` + +Defaults to `AssertError`. + + +#### `sinon.assert.pass(assertion);` + +Called every time `assertion` passes. + +Default implementation does nothing. + + +#### `sinon.assert.notCalled(spy);` + +Passes if `spy` was never called + +#### `sinon.assert.called(spy);` + +Passes if `spy` was called at least once. + + +#### `sinon.assert.calledOnce(spy);` + +Passes if `spy` was called once and only once. + + +#### `sinon.assert.calledTwice(spy);` + +Passes if `spy` was called exactly twice. + + +#### `sinon.assert.calledThrice(spy)` + +Passes if `spy` was called exactly three times. + + +#### `sinon.assert.callCount(spy, num)` +Passes if `spy` was called exactly `num` times. + + +#### `sinon.assert.callOrder(spy1, spy2, ...)` +Passes if provided spies were called in the specified order. + + +#### `sinon.assert.calledOn(spyOrSpyCall, obj)` + +Passes if `spy` was ever called with `obj` as its `this` value. + +It's possible to assert on a dedicated spy call: `sinon.assert.calledOn(spy.firstCall, arg1, arg2, ...);`. + + +#### `sinon.assert.alwaysCalledOn(spy, obj)` + +Passes if `spy` was always called with `obj` as its `this` value. + + +#### `sinon.assert.calledWith(spyOrSpyCall, arg1, arg2, ...);` + +Passes if `spy` was called with the provided arguments. + +It's possible to assert on a dedicated spy call: `sinon.assert.calledWith(spy.firstCall, arg1, arg2, ...);`. + + +#### `sinon.assert.alwaysCalledWith(spy, arg1, arg2, ...);` + +Passes if `spy` was always called with the provided arguments. + + +#### `sinon.assert.neverCalledWith(spy, arg1, arg2, ...);` + +Passes if `spy` was never called with the provided arguments. + + +#### `sinon.assert.calledWithExactly(spyOrSpyCall, arg1, arg2, ...);` + +Passes if `spy` was called with the provided arguments and no others. + +It's possible to assert on a dedicated spy call: `sinon.assert.calledWithExactly(spy.getCall(1), arg1, arg2, ...);`. + + +#### `sinon.assert.alwaysCalledWithExactly(spy, arg1, arg2, ...);` + +Passes if `spy` was always called with the provided arguments and no others. + + +#### `sinon.assert.calledWithMatch(spyOrSpyCall, arg1, arg2, ...)` + +Passes if `spy` was called with matching arguments. + +This behaves the same way as `sinon.assert.calledWith(spy, sinon.match(arg1), sinon.match(arg2), ...)`. + +It's possible to assert on a dedicated spy call: `sinon.assert.calledWithMatch(spy.secondCall, arg1, arg2, ...);`. + + +#### `sinon.assert.alwaysCalledWithMatch(spy, arg1, arg2, ...)` + +Passes if `spy` was always called with matching arguments. + +This behaves the same way as `sinon.assert.alwaysCalledWith(spy, sinon.match(arg1), sinon.match(arg2), ...)`. + + +#### `sinon.assert.calledWithNew(spyOrSpyCall)` + +Passes if `spy` was called with the `new` operator. + +It's possible to assert on a dedicated spy call: `sinon.assert.calledWithNew(spy.secondCall, arg1, arg2, ...);`. + + +#### `sinon.assert.neverCalledWithMatch(spy, arg1, arg2, ...)` + +Passes if `spy` was never called with matching arguments. + +This behaves the same way as `sinon.assert.neverCalledWith(spy, sinon.match(arg1), sinon.match(arg2), ...)`. + + +#### `sinon.assert.threw(spyOrSpyCall, exception);` + +Passes if `spy` threw the given exception. + +The exception can be a `String` denoting its type, or an actual object. + +If only one argument is provided, the assertion passes if `spy` ever threw any exception. + +It's possible to assert on a dedicated spy call: `sinon.assert.threw(spy.thirdCall, exception);`. + + +#### `sinon.assert.alwaysThrew(spy, exception);` + +Like above, only required for all calls to the spy. + +#### `sinon.assert.match(actual, expectation);` + +Uses [`sinon.match`](../matchers) to test if the arguments can be considered a match. + +```javascript +var sinon = require('sinon'); + +describe('example', function(){ + it('should match on `x` property, and ignore `y` property', function() { + var expected = {x: 1}, + actual = {x: 1, y: 2}; + + sinon.assert.match(actual, expected); + }); +}); +``` + +#### `sinon.assert.expose(object, options);` + +Exposes assertions into another object, to better integrate with the test framework. For instance, JsTestDriver uses global assertions, and to make Sinon.JS assertions appear alongside them, you can do. + +```javascript +sinon.assert.expose(this); +``` + +This will give you `assertCalled(spy)`,`assertCallOrder(spy1, spy2, ...)` and so on. + +The method accepts an optional options object with two options. + +
+
prefix
+
is a prefix to give assertions. By default it is "assert", so sinon.assert.called becomes target.assertCalled. By passing a blank string, the exposed method will be target.called.
+ +
includeFail
+
true by default, copies over the fail and failException properties
+
diff --git a/docs/_releases/v7.2.6/fake-timers.md b/docs/_releases/v7.2.6/fake-timers.md new file mode 100644 index 000000000..8563b0606 --- /dev/null +++ b/docs/_releases/v7.2.6/fake-timers.md @@ -0,0 +1,140 @@ +--- +layout: page +title: Fake timers - Sinon.JS +breadcrumb: fake timers +--- + +Fake timers are synchronous implementations of `setTimeout` and friends that +Sinon.JS can overwrite the global functions with to allow you to more easily +test code using them. + +Fake timers provide a `clock` object to pass time, which can also be used to control `Date` objects created through either `new Date();` +or `Date.now();` (if supported by the browser). + +For standalone usage of fake timers it is recommended to use [lolex](https://github.com/sinonjs/lolex) package instead. It provides the same +set of features (Sinon uses it under the hood) and was previously extracted from Sinon.JS. + +```javascript +{ + setUp: function () { + this.clock = sinon.useFakeTimers(); + }, + + tearDown: function () { + this.clock.restore(); + }, + + "test should animate element over 500ms" : function(){ + var el = jQuery("
"); + el.appendTo(document.body); + + el.animate({ height: "200px", width: "200px" }); + this.clock.tick(510); + + assertEquals("200px", el.css("height")); + assertEquals("200px", el.css("width")); + } +} +``` + +## Fake timers API + + +#### `var clock = sinon.useFakeTimers();` + +Causes Sinon to replace the global `setTimeout`, `clearTimeout`, `setInterval`, `clearInterval`, `setImmediate`, `clearImmediate`, `process.hrtime`, `performance.now`(when available) and `Date` with a custom implementation which is bound to the returned `clock` object. + +Starts the clock at the UNIX epoch (timestamp of `0`). + + +#### `var clock = sinon.useFakeTimers(now);` + +As above, but rather than starting the clock with a timestamp of 0, start at the provided timestamp `now`. + +*Since `sinon@2.0.0`* + +You can also pass in a Date object, and its `getTime()` will be used for the starting timestamp. + +#### `var clock = sinon.useFakeTimers(config);` + +As above, but allows further configuration options, some of which are: + +- `config.now` - *Number/Date* - installs lolex with the specified unix epoch (default: 0) +- `config.toFake` - *String[ ]* - an array with explicit function names to fake. By default lolex will automatically fake all methods *except* `process.nextTick`. You could, however, still fake `nextTick` by providing it explicitly +- `config.shouldAdvanceTime` - *Boolean* - tells lolex to increment mocked time automatically based on the real system time shift (default: false) + +Please visit the `lolex.install` [documentation](https://github.com/sinonjs/lolex#var-clock--lolexinstallconfig) for the full feature set. + +**Important note:** when faking `nextTick`, normal calls to `process.nextTick()` would not execute automatically as they would during normal event-loop phases. You would have to call either `clock.next()`, `clock.tick()`, `clock.runAll()` or `clock.runToLast()` (see example below). Please refer to the [lolex](https://github.com/sinonjs/lolex) documentation for more information. + +#### Examples + +Installs fake timers at January 1st 2017 and fakes `setTimeout` and `process.nextTick` only: + +```javascript +var clock = sinon.useFakeTimers({ + now: 1483228800000, + toFake: ["setTimeout", "nextTick"] + }); + +var called = false; + +process.nextTick(function () { + called = true; +}); + +clock.runAll(); //forces nextTick calls to flush synchronously +assert(called); //true +``` + +Install at the same date, advancing the fake time automatically (default is every `20ms`), causing timers to be fired automatically without the need to `tick()` the clock: + +```js +var clock = sinon.useFakeTimers({ + now: 1483228800000, + shouldAdvanceTime: true + }); + +setImmediate(function () { + console.log('tick'); //will print after 20ms +}); + +setTimeout(function () { + console.log('tock'); //will print after 20ms +}, 15); + +setTimeout(function () { + console.log('tack'); //will print after 40ms +}, 35); +``` + +Please refer to the `lolex.install` [documentation](https://github.com/sinonjs/lolex#var-clock--lolexinstallconfig) for the full set of features available and more elaborate explanations. + +*Since `sinon@3.0.0`* + +`var clock = sinon.useFakeTimers([now, ]prop1, prop2, ...)` is no longer supported. To define which methods to fake, please use `config.toFake`. + + +#### `clock.tick(time);` + +Tick the clock ahead `time` milliseconds. + +Causes all timers scheduled within the affected time range to be called. `time` may be the number of milliseconds to advance the clock by or a human-readable string. Valid string formats are "08" for eight seconds, "01:00" for one minute and "02:34:10" for two hours, 34 minutes and ten seconds. + +time may be negative, which causes the clock to change but won't fire any callbacks. + +#### `clock.next();` + +Advances the clock to the the moment of the first scheduled timer, firing it. + +#### `clock.runAll();` + +This runs all pending timers until there are none remaining. If new timers are added while it is executing they will be run as well. + +This makes it easier to run asynchronous tests to completion without worrying about the number of timers they use, or the delays in those timers. + +#### `clock.restore();` + +Restore the faked methods. + +Call in e.g. `tearDown`. diff --git a/docs/_releases/v7.2.6/fake-xhr-and-server.md b/docs/_releases/v7.2.6/fake-xhr-and-server.md new file mode 100644 index 000000000..e1eb2a3c5 --- /dev/null +++ b/docs/_releases/v7.2.6/fake-xhr-and-server.md @@ -0,0 +1,395 @@ +--- +layout: page +title: Fake XHR and server - Sinon.JS +breadcrumb: fake XHR and server +--- + +## Fake `XMLHttpRequest` + +Provides a fake implementation of `XMLHttpRequest` and provides +several interfaces for manipulating objects created by it. + +Also fakes native `XMLHttpRequest` and `ActiveXObject` (when available, and only for `XMLHTTP` progids). Helps with testing requests made with `XHR`. + +The fake server and XHR can be used completely stand-alone by downloading `sinon-server.js`. + +```javascript +{ + setUp: function () { + this.xhr = sinon.useFakeXMLHttpRequest(); + var requests = this.requests = []; + + this.xhr.onCreate = function (xhr) { + requests.push(xhr); + }; + }, + + tearDown: function () { + this.xhr.restore(); + }, + + "test should fetch comments from server" : function () { + var callback = sinon.spy(); + myLib.getCommentsFor("/some/article", callback); + assertEquals(1, this.requests.length); + + this.requests[0].respond(200, { "Content-Type": "application/json" }, + '[{ "id": 12, "comment": "Hey there" }]'); + assert(callback.calledWith([{ id: 12, comment: "Hey there" }])); + } +} +``` + + +### `sinon.useFakeXMLHttpRequest` + +#### `var xhr = sinon.useFakeXMLHttpRequest();` + +Causes Sinon to replace the native `XMLHttpRequest` object in browsers that support it with a custom implementation which does not send actual requests. + +In browsers that support `ActiveXObject`, this constructor is replaced, and fake objects are returned for `XMLHTTP` progIds. Other progIds, such as `XMLDOM` are left untouched. + +The native `XMLHttpRequest` object will be available at `sinon.xhr.XMLHttpRequest` + + +#### `xhr.onCreate = function (xhr) {};` + +By assigning a function to the `onCreate` property of the returned object from `useFakeXMLHttpRequest()` you can subscribe to newly created `FakeXMLHttpRequest` objects. See below for the fake xhr object API. + +Using this observer means you can still reach objects created by e.g. `jQuery.ajax` (or other abstractions/frameworks). + +#### `xhr.restore();` + +Restore original function(s). + + +### `FakeXMLHttpRequest` + +#### `String request.url` + +The URL set on the request object. + + +#### `String request.method` + +The request method as a string. + + +#### `Object request.requestHeaders` + +An object of all request headers, i.e.: + +```javascript +{ + "Accept": "text/html, */*", + "Connection": "keep-alive" +} +``` + + +#### `String request.requestBody` + +The request body + +#### `int request.status` + +The request's status code. + +`undefined` if the request has not been handled (see [`respond`](#serverrespond) below) + + +#### `String request.statusText` + +Only populated if the [`respond`](#serverrespond) method is called (see below). + + +#### `boolean request.async` + +Whether or not the request is asynchronous. + + +#### `String request.username` + +Username, if any. + + +#### `String request.password` + +Password, if any. + + +#### `Document request.responseXML` + +When using [`respond`](#serverrespond), this property is populated with a parsed document if response headers indicate as much (see [the spec](http://www.w3.org/TR/XMLHttpRequest/)) + + +#### `String request.getResponseHeader(header);` + +The value of the given response header, if the request has been responded to (see [`respond`](#serverrespond)). + + +#### `Object request.getAllResponseHeaders();` + +All response headers as an object. + + +### Filtered requests + +When using Sinon.JS for mockups or partial integration/functional testing, you might want to fake some requests, while allowing others to go through to the backend server. With filtered `FakeXMLHttpRequest`s (new in v1.3.0), you can. + + +#### `FakeXMLHttpRequest.useFilters` + +Default `false`. + +When set to `true`, Sinon will check added filters if certain requests should be "unfaked" + + +#### `FakeXMLHttpRequest.addFilter(fn)` + +Add a filter that will decide whether or not to fake a request. + +The filter will be called when `xhr.open` is called, with the exact same arguments (`method`, `url`, `async`, `username`, `password`). If the filter returns `true`, the request will not be faked. + + +### Simulating server responses + +#### `request.setStatus(status);` + +Sets response status (`status` and `statusText` properties). + +Status should be a number, the status text is looked up from `sinon.FakeXMLHttpRequest.statusCodes`. + +#### `request.setResponseHeaders(object);` + +Sets response headers (e.g. `{ "Content-Type": "text/html", /* ... */ }`, updates the `readyState` property and fires `onreadystatechange`. + + +#### `request.setResponseBody(body);` + +Sets the respond body, updates the `readyState` property and fires `onreadystatechange`. + +Additionally, populates `responseXML` with a parsed document if [response headers indicate as much](http://www.w3.org/TR/XMLHttpRequest/). + + +#### `request.respond(status, headers, body);` + +Calls the above three methods. + +#### `request.error();` + +Simulates a network error on the request. The `onerror` handler will be called and the `status` will be `0`. + +#### `Boolean request.autoRespond` + +When set to `true`, causes the server to automatically respond to incoming requests after a timeout. + +The default timeout is 10ms but you can control it through the `autoRespondAfter` property. + +Note that this feature is intended to help during mockup development, and is not suitable for use in tests. + +#### `Number request.autoRespondAfter` + +When `autoRespond` is `true`, respond to requests after this number of milliseconds. Default is 10. + + +## Fake server +High-level API to manipulate `FakeXMLHttpRequest` instances. + +For help with handling JSON-P please refer to our [notes below](#json-p) + +```javascript +{ + setUp: function () { + this.server = sinon.createFakeServer(); + }, + + tearDown: function () { + this.server.restore(); + }, + + "test should fetch comments from server" : function () { + this.server.respondWith("GET", "/some/article/comments.json", + [200, { "Content-Type": "application/json" }, + '[{ "id": 12, "comment": "Hey there" }]']); + + var callback = sinon.spy(); + myLib.getCommentsFor("/some/article", callback); + this.server.respond(); + + sinon.assert.calledWith(callback, [{ id: 12, comment: "Hey there" }]); + + assert(server.requests.length > 0) + } +} +``` + + +#### `var server = sinon.createFakeServer([config]);` + +Creates a new server. + +This function also calls `sinon.useFakeXMLHttpRequest()`. + +`createFakeServer` accepts optional properties to configure the fake server. See [options](#fake-server-options) below for configuration parameters. + + +#### `var server = sinon.createFakeServerWithClock();` + +Creates a server that also manages fake timers. + +This is useful when testing `XHR` objects created with e.g. jQuery 1.3.x, which uses a timer to poll the object for completion, rather than the usual `onreadystatechange`. + + +#### `server.configure(config);` + +Configures the fake server. + +See [options](#fake-server-options) below for configuration parameters. + +#### `server.respondWith(response);` + +Causes the server to respond to any request not matched by another response with the provided data. The default catch-all response is `[404, {}, ""]`. + +`response` can be one of three things: + +1. A `String` representing the response body +2. An `Array` with status, headers and response body, e.g. `[200, { "Content-Type": "text/html", "Content-Length": 2 }, "OK"]` +3. A `Function`. + +Default status is 200 and default headers are none. + +When the response is a `Function`, it will be passed the request object. You +must manually call [respond](#serverrespond) on it to complete the +request. + + +#### `server.respondWith(url, response);` + +Responds to all requests to given URL, e.g. `/posts/1`. + + +#### `server.respondWith(method, url, response);` + +Responds to all `method` requests to the given URL with the given response. + +`method` is an HTTP verb. + + +#### `server.respondWith(urlRegExp, response);` + +URL may be a regular expression, e.g. `/\\/post\\//\\d+` + +If the response is a `Function`, it will be passed any capture groups from the regular expression along with the XMLHttpRequest object: + +```javascript +server.respondWith(/\/todo-items\/(\d+)/, function (xhr, id) { + xhr.respond(200, { "Content-Type": "application/json" }, '[{ "id": ' + id + " }]"); +}); +``` + + +#### `server.respondWith(method, urlRegExp, response);` + +Responds to all `method` requests to URLs matching the regular expression. + +#### `server.respond();` + +Causes all queued asynchronous requests to receive a response. + +If none of the responses added through `respondWith` match, the default response is `[404, {}, ""]`. + +Synchronous requests are responded to immediately, so make sure to call `respondWith` upfront. + +If called with arguments, `respondWith` will be called with those arguments before responding to requests. + + +#### `server.autoRespond = true;` + +If set, will automatically respond to every request after a timeout. + +The default timeout is 10ms but you can control it through the `autoRespondAfter` property. + +Note that this feature is intended to help during mockup development, and is not suitable for use in tests. For synchronous immediate responses, use `respondImmediately` instead. + + +#### `server.autoRespondAfter = ms;` + +Causes the server to automatically respond to incoming requests after a timeout. + +#### `server.respondImmediately = true;` + +If set, the server will respond to every request immediately and synchronously. + +This is ideal for faking the server from within a test without having to call `server.respond()` after each request made in that test. + +As this is synchronous and immediate, this is not suitable for simulating actual network latency in tests or mockups. To simulate network latency with automatic responses, see `server.autoRespond` and `server.autoRespondAfter`. + +#### array `server.requests` + +You can inspect the `server.requests` to verify request ordering, find unmatched requests or check that no requests has been done. +`server.requests` is an array of all the `FakeXMLHttpRequest` objects that have been created. + +#### `Boolean server.fakeHTTPMethods` + +If set to `true`, server will find `_method` parameter in POST body and recognize that as the actual method. + +Supports a pattern common to Ruby on Rails applications. For custom HTTP method faking, override `server.getHTTPMethod(request)`. + + +#### `server.getHTTPMethod(request)` + +Used internally to determine the HTTP method used with the provided request. + +By default this method simply returns `request.method`. When `server.fakeHTTPMethods` is true, the method will return the value of the `_method` parameter if the method is "POST". + +This method can be overridden to provide custom behavior. + + +#### `server.restore();` + +Restores the native XHR constructor. + + +### Fake server options + +These options are properties on the server object and can be set directly + + +```javascript +server.autoRespond = true +``` + +You can also pass options with an object literal to `createFakeServer` and `.configure`. + +#### `Boolean autoRespond` + +If set, will automatically respond to every request after a timeout. + +The default timeout is 10ms but you can control it through the `autoRespondAfter` property. + +Note that this feature is intended to help during mockup development, and is not suitable for use in tests. + +For synchronous immediate responses, use `respondImmediately` instead. + + +#### `Number autoRespondAfter (ms)` + +Causes the server to automatically respond to incoming requests after a timeout. + +#### `Boolean respondImmediately` + +If set, the server will respond to every request immediately and synchronously. + +This is ideal for faking the server from within a test without having to call `server.respond()` after each request made in that test. + +As this is synchronous and immediate, this is not suitable for simulating actual network latency in tests or mockups. To simulate network latency with automatic responses, see `server.autoRespond` and `server.autoRespondAfter`. + + +#### `boolean fakeHTTPMethods` + +If set to `true`, server will find `_method` parameter in `POST` body and recognize that as the actual method. + +Supports a pattern common to Ruby on Rails applications. + +For custom HTTP method faking, override `server.getHTTPMethod(request)` diff --git a/docs/_releases/v7.2.6/fakes.md b/docs/_releases/v7.2.6/fakes.md new file mode 100644 index 000000000..50c30f8cc --- /dev/null +++ b/docs/_releases/v7.2.6/fakes.md @@ -0,0 +1,178 @@ +--- +layout: page +title: Fakes - Sinon.JS +breadcrumb: fakes +--- + +### Introduction + +`fake` was introduced with Sinon with v5. It simplifies and merges concepts from [`spies`][spies] and [`stubs`][stubs]. + +In Sinon, a `fake` is a `Function` that records arguments, return value, the value of `this` and exception thrown (if any) for all of its calls. + +It can be created with or without behavior; it can wrap an existing function. + +A fake is immutable: once created, the behavior will not change. + +Unlike [`sinon.spy`][spies] and [`sinon.stub`][stubs] methods, the `sinon.fake` API knows only how to create fakes, and doesn't concern itself with plugging them into the system under test. To plug the fakes into the system under test, you can use the [`sinon.replace*`](../sandbox#sandboxreplaceobject-property-replacement) methods. + + +### Creating a fake + +```js +// create a basic fake, with no behavior +var fake = sinon.fake(); + +fake(); + +console.log(fake.callCount); +// 1 +``` + +### Fakes with behavior + +Fakes can be created with behavior, which cannot be changed once the fake has been created. + +#### `sinon.fake.returns(value);` + +Creates a fake that returns the `value` argument + +```js +var fake = sinon.fake.returns('apple pie'); + +fake(); +// apple pie +``` + +#### `sinon.fake.throws(value);` + +Creates a fake that throws an `Error` with the provided value as the `message` property. + +If an `Error` is passed as the `value` argument, then that will be the thrown value. If any other value is passed, then that will be used for the `message` property of the thrown `Error`. + +```js +var fake = sinon.fake.throws(new Error('not apple pie')); + +fake(); +// Error: not apple pie +``` + +#### `sinon.fake.resolves(value);` + +Creates a fake that returns a resolved `Promise` for the passed value. + +#### `sinon.fake.rejects(value);` + +Creates a fake that returns a rejected `Promise` for the passed value. + +If an `Error` is passed as the `value` argument, then that will be the value of the promise. If any other value is passed, then that will be used for the `message` property of the `Error` returned by the promise. + +#### `sinon.fake.yields(callback[, value1, ..., valueN]);` + +`fake` expects the last argument to be a callback and will invoke it with the given arguments. + +```js +var fake = sinon.fake.yields('hello world'); + +fake(console.log); +// hello world +``` + +#### `sinon.fake.yieldsAsync(callback[, value1, ..., valueN]);` + +`fake` expects the last argument to be a callback and will invoke it asynchronously with the given arguments. + +```js +var fake = sinon.fake.yieldsAsync('hello world'); + +fake(console.log); +// hello world +``` + +#### `sinon.fake(func);` + +Wraps an existing `Function` to record all interactions, while leaving it up to the `func` to provide the behavior. + +This is useful when complex behavior not covered by the `sinon.fake.*` methods is required or when wrapping an existing function or method. + +### Instance properties + +#### `f.callback` + +This property is a convenience to easily get a reference to the last callback passed in the last to the fake. + +```js +var f = sinon.fake(); +var cb1 = function () {}; +var cb2 = function () {}; + +f(1, 2, 3, cb1); +f(1, 2, 3, cb2); + +f.callback === cb2; +// true +``` + +The same convenience has been added to [spy calls](../spy-call): + +```js +f.getCall(1).callback === cb2; +// true +// +f.lastCall.callback === cb2; +// true +``` + +#### `f.lastArg` + +This property is a convenient way to get a reference to the last argument passed in the last call to the fake. + +```js +var f = sinon.fake(); +var date1 = new Date(); +var date2 = new Date(); + +f(1, 2, date1); +f(1, 2, date2); + +f.lastArg === date2; +// true +``` + +The same convenience has been added to [spy calls](../spy-call): + +```js +f.getCall(0).lastArg === date1; +// true +f.getCall(1).lastArg === date2; +// true + +f.lastCall.lastArg === date2; +// true +``` + + +### Adding the fake to the system under test + +Unlike `sinon.spy` and `sinon.stub`, `sinon.fake` only knows about creating fakes, not about replacing properties in the system under test. + +To replace a property, you can use the [`sinon.replace`](../sandbox/#sandboxreplaceobject-property-replacement) method. + +```js +var fake = sinon.fake.returns('42'); + +sinon.replace(console, 'log', fake); + +console.log('apple pie'); +// 42 +``` + +When you want to restore the replaced properties, simply call the `sinon.restore` method. + +```js +// restores all replaced properties set by sinon methods (replace, spy, stub) +sinon.restore(); +``` + +[spies]: ../spies +[stubs]: ../stubs diff --git a/docs/_releases/v7.2.6/general-setup.md b/docs/_releases/v7.2.6/general-setup.md new file mode 100644 index 000000000..d426edf40 --- /dev/null +++ b/docs/_releases/v7.2.6/general-setup.md @@ -0,0 +1,33 @@ +--- +layout: page +title: General setup - Sinon.JS +breadcrumb: general-setup +--- + +We will be making fakes, spies and stubs. By default these are created in the _default sandbox_. +Be sure to `restore` this sandbox after each test. + +For example, if you're using mocha you can place this in a test file at the root level: + +```js +afterEach(() => { + // Restore the default sandbox here + sinon.restore(); +}); +``` + +Or in Jasmine you should place it in each describe: + +```js +describe('My test suite', () => { + + afterEach(() => { + // Restore the default sandbox here + sinon.restore(); + }); +}); +``` + +Forgetting to restore your sandbox results in a memory leak. + +For more advanced setups using multiple sandboxes, please see [sandbox](../sandbox) diff --git a/docs/_releases/v7.2.6/json-p.md b/docs/_releases/v7.2.6/json-p.md new file mode 100644 index 000000000..2d817337b --- /dev/null +++ b/docs/_releases/v7.2.6/json-p.md @@ -0,0 +1,18 @@ +--- +layout: page +title: JSON-P - Sinon.JS +breadcrumb: JSON-P +--- + +# JSON-P + +JSON-P doesn't use `XHR` requests, which is what the fake server is concerned with. A JSON-P request creates a script element and inserts it into the document. + +There is no sufficiently unobtrusive way to fake this automatically. The best option is to simply stub jQuery in this case: + +```javascript +sinon.stub(jQuery, "ajax"); +sinon.assert.calledOnce(jQuery.ajax); +``` + +We could potentially have had the fake server detect `jQuery` and fake any calls to `jQuery.ajax` when JSON-P is used, but that felt like a compromise in the focus of the Sinon project compared to simply documenting the above practice. diff --git a/docs/_releases/v7.2.6/matchers.md b/docs/_releases/v7.2.6/matchers.md new file mode 100644 index 000000000..4b242d777 --- /dev/null +++ b/docs/_releases/v7.2.6/matchers.md @@ -0,0 +1,266 @@ +--- +layout: page +title: Matchers - Sinon.JS +breadcrumb: matchers +--- + +Matchers can be passed as arguments to `spy.calledOn`, `spy.calledWith`, `spy.returned` and the +corresponding `sinon.assert` functions as well as `spy.withArgs`. Matchers allow to be either more fuzzy or more specific about the expected value. + +```javascript +"test should assert fuzzy": function () { + var book = { + pages: 42, + author: "cjno" + id: { + isbn10: "0596517742", + isbn13: "978-0596517748" + } + }; + var spy = sinon.spy(); + + spy(book); + + sinon.assert.calledWith(spy, sinon.match({ author: "cjno" })); + sinon.assert.calledWith(spy, sinon.match.has("pages", 42)); + sinon.assert.calledWith(spy, sinon.match.has("id", sinon.match.has("isbn13", "978-0596517748"))); +} +``` + +```javascript +"test should stub method differently based on argument types": function () { + var callback = sinon.stub(); + callback.withArgs(sinon.match.string).returns(true); + callback.withArgs(sinon.match.number).throws("TypeError"); + + callback("abc"); // Returns true + callback(123); // Throws TypeError +} +``` + +## Matchers API + +#### `sinon.match(number);` + +Requires the value to be == to the given number. + + +#### `sinon.match(string);` + +Requires the value to be a string and have the expectation as a substring. + +#### `sinon.match(regexp);` + +Requires the value to be a string and match the given regular expression. + +#### `sinon.match(object);` + +Requires the value to be not `null` or `undefined` and have at least the same properties as `expectation`. + +This supports nested matchers. + +#### `sinon.match(function)` + +See `custom matchers`. + + +#### `sinon.match.any` + +Matches anything. + + +#### `sinon.match.defined` + +Requires the value to be defined. + + +#### `sinon.match.truthy` + +Requires the value to be truthy. + + +#### `sinon.match.falsy` + +Requires the value to be falsy. + + +#### `sinon.match.bool` + +Requires the value to be a `Boolean` + + +#### `sinon.match.number` + +Requires the value to be a `Number`. + + +#### `sinon.match.string` + +Requires the value to be a `String`. + + +#### `sinon.match.object` + +Requires the value to be an `Object`. + + +#### `sinon.match.func` + +Requires the value to be a `Function`. + + +#### `sinon.match.array` + +Requires the value to be an `Array`. + + +#### `sinon.match.array.deepEquals(arr)` + +Requires an `Array` to be deep equal another one. + + +#### `sinon.match.array.startsWith(arr)` + +Requires an `Array` to start with the same values as another one. + + +#### `sinon.match.array.endsWith(arr)` + +Requires an `Array` to end with the same values as another one. + + +#### `sinon.match.array.contains(arr)` + +Requires an `Array` to contain each one of the values the given array has. + + +#### `sinon.match.map` + +Requires the value to be a `Map`. + + +#### `sinon.match.map.deepEquals(map)` + +Requires a `Map` to be deep equal another one. + +#### `sinon.match.map.contains(map)` + +Requires a `Map` to contain each one of the items the given map has. + + +#### `sinon.match.set` + +Requires the value to be a `Set`. + + +#### `sinon.match.set.deepEquals(set)` + +Requires a `Set` to be deep equal another one. + + +#### `sinon.match.set.contains(set)` + +Requires a `Set` to contain each one of the items the given set has. + + +#### `sinon.match.regexp` + +Requires the value to be a regular expression. + + +#### `sinon.match.date` + +Requires the value to be a `Date` object. + + +#### `sinon.match.symbol` + +Requires the value to be a `Symbol`. + +#### `sinon.match.in(array)` + +Requires the value to be in the `array`. + +#### `sinon.match.same(ref)` + +Requires the value to strictly equal `ref`. + +#### `sinon.match.typeOf(type)` + +Requires the value to be of the given type, where `type` can be one of + `"undefined"`, + `"null"`, + `"boolean"`, + `"number"`, + `"string"`, + `"object"`, + `"function"`, + `"array"`, + `"regexp"`, + `"date"` or + `"symbol"`. + + +#### `sinon.match.instanceOf(type)` + +Requires the value to be an instance of the given `type`. + +#### `sinon.match.has(property[, expectation])` + +Requires the value to define the given `property`. + +The property might be inherited via the prototype chain. If the optional expectation is given, the value of the property is deeply compared with the expectation. The expectation can be another matcher. + +#### `sinon.match.hasOwn(property[, expectation])` + +Same as `sinon.match.has` but the property must be defined by the value itself. Inherited properties are ignored. + + +#### `sinon.match.hasNested(propertyPath[, expectation])` + +Requires the value to define the given `propertyPath`. Dot (`prop.prop`) and bracket (`prop[0]`) notations are supported as in [Lodash.get](https://lodash.com/docs/4.4.2#get). + +The propertyPath might be inherited via the prototype chain. If the optional expectation is given, the value at the propertyPath is deeply compared with the expectation. The expectation can be another matcher. + + +```javascript +sinon.match.hasNested("a[0].b.c"); + +// Where actual is something like +var actual = { "a": [{ "b": { "c": 3 } }] }; + +sinon.match.hasNested("a.b.c"); + +// Where actual is something like +var actual = { "a": { "b": { "c": 3 } } }; +``` + +#### `sinon.match.every(matcher)` + +Requires **every** element of an `Array`, `Set` or `Map`, or alternatively **every** value of an `Object` to match the given `matcher`. + +#### `sinon.match.some(matcher)` + +Requires **any** element of an `Array`, `Set` or `Map`, or alternatively **any** value of an `Object` to match the given `matcher`. + +## Combining matchers + +All matchers implement `and` and `or`. This allows to logically combine mutliple matchers. The result is a new matchers that requires both (and) or one of the matchers (or) to return `true`. + +```javascript +var stringOrNumber = sinon.match.string.or(sinon.match.number); +var bookWithPages = sinon.match.instanceOf(Book).and(sinon.match.has("pages")); +``` + + +## Custom matchers + +Custom matchers are created with the `sinon.match` factory which takes a test function and an optional message. + +The test function takes a value as the only argument, returns `true` if the value matches the expectation and `false` otherwise. The message string is used to generate the error message in case the value does not match the expectation. + +```javascript +var trueIsh = sinon.match(function (value) { + return !!value; +}, "trueIsh"); +``` diff --git a/docs/_releases/v7.2.6/mocks.md b/docs/_releases/v7.2.6/mocks.md new file mode 100644 index 000000000..915e1fa67 --- /dev/null +++ b/docs/_releases/v7.2.6/mocks.md @@ -0,0 +1,174 @@ +--- +layout: page +title: Mocks - Sinon.JS +breadcrumb: mocks +--- + +### Introduction + +### What are mocks? + +Mocks (and mock expectations) are fake methods (like spies) with pre-programmed behavior (like stubs) as well as **pre-programmed expectations**. + +A mock will fail your test if it is not used as expected. + + +### When to use mocks? + +Mocks should only be used for the *method under test*. In every unit test, there should be one unit under test. + +If you want to control how your unit is being used and like stating expectations upfront (as opposed to asserting after the fact), use a mock. + + +### When to **not** use mocks? + +Mocks come with built-in expectations that may fail your test. + +Thus, they enforce implementation details. The rule of thumb is: if you wouldn't add an assertion for some specific call, don't mock it. Use a stub instead. + +In general you should have **no more than one** mock (possibly with several expectations) in a single test. + +[Expectations](#expectations) implement both the [spies](../spies) and [stubs](../stubs) APIs. + +To see what mocks look like in Sinon.JS, here is one of the [PubSubJS][pubsubjs] tests again, this time using a method as callback and using mocks to verify its behavior + +```javascript +"test should call all subscribers when exceptions": function () { + var myAPI = { method: function () {} }; + + var spy = sinon.spy(); + var mock = sinon.mock(myAPI); + mock.expects("method").once().throws(); + + PubSub.subscribe("message", myAPI.method); + PubSub.subscribe("message", spy); + PubSub.publishSync("message", undefined); + + mock.verify(); + assert(spy.calledOnce); +} +``` + +[pubsubjs]: https://github.com/mroderick/pubsubjs + + +## Mocks API + +### Properties + +#### `var mock = sinon.mock(obj);` + +Creates a mock for the provided object. + +Does not change the object, but returns a mock object to set expectations on the object's methods. + + +#### `var expectation = mock.expects("method");` + +Overrides `obj.method` with a mock function and returns it. + +See [expectations](#expectations) below. + + +#### `mock.restore();` + +Restores all mocked methods. + + +#### `mock.verify();` + +Verifies all expectations on the mock. + +If any expectation is not satisfied, an exception is thrown. + +Also restores the mocked methods. + +#### `mock.usingPromise(promiseLibrary);` + +Causes all expectations created from the mock to return promises using a specific +Promise library instead of the global one when using `expectation.rejects` or +`expectation.resolves`. Returns the mock object to allow chaining. + +*Since `sinon@6.2.0`* + + +### Expectations + +All the expectation methods return the expectation, meaning you can chain them. + +Typical usage: + +```javascript +sinon.mock(jQuery).expects("ajax").atLeast(2).atMost(5); +jQuery.ajax.verify(); +``` + + +#### `var expectation = sinon.expectation.create([methodName]);` + +Creates an expectation without a mock object, basically an anonymous mock function. + +Method name is optional and is used in exception messages to make them more readable. + + +#### `var expectation = sinon.mock([methodName]);` + +The same as the above. + + +#### `expectation.atLeast(number);` + +Specify the minimum amount of calls expected. + + +#### `expectation.atMost(number);` + +Specify the maximum amount of calls expected. + + +#### `expectation.never();` +Expect the method to never be called. + + +#### `expectation.once();` + +Expect the method to be called exactly once. + + +#### `expectation.twice();` + +Expect the method to be called exactly twice. + + +#### `expectation.thrice();` + +Expect the method to be called exactly thrice. + + +#### `expectation.exactly(number);` + +Expect the method to be called exactly `number` times. + + +#### `expectation.withArgs(arg1, arg2, ...);` + +Expect the method to be called with the provided arguments and possibly others. + +An `expectation` instance only holds onto a single set of arguments specified with `withArgs`. Subsequent calls will overwrite the previously-specified set of arguments (even if they are different), so it is generally not intended that this method be invoked more than once per test case. + + +#### `expectation.withExactArgs(arg1, arg2, ...);` + +Expect the method to be called with the provided arguments and no others. + +An `expectation` instance only holds onto a single set of arguments specified with `withExactArgs`. Subsequent calls will overwrite the previously-specified set of arguments (even if they are different), so it is generally not intended that this method be invoked more than once per test case. + + +#### `expectation.on(obj);` + +Expect the method to be called with `obj` as `this`."} + + +#### `expectation.verify();` + +Verifies the expectation and throws an exception if it's not met. diff --git a/docs/_releases/v7.2.6/sandbox.md b/docs/_releases/v7.2.6/sandbox.md new file mode 100644 index 000000000..f4649410e --- /dev/null +++ b/docs/_releases/v7.2.6/sandbox.md @@ -0,0 +1,302 @@ +--- +layout: page +title: Sandboxes - Sinon.JS +breadcrumb: sandbox +--- + +Sandboxes removes the need to keep track of every fake created, which greatly simplifies cleanup. + +```javascript +var sandbox = require('sinon').createSandbox(); +var myAPI = { hello: function () {} }; + +describe('myAPI.hello method', function () { + + beforeEach(function () { + // stub out the `hello` method + sandbox.stub(myAPI, 'hello'); + }); + + afterEach(function () { + // completely restore all fakes created through the sandbox + sandbox.restore(); + }); + + it('should be called once', function () { + myAPI.hello(); + sandbox.assert.calledOnce(myAPI.hello); + }); + + it('should be called twice', function () { + myAPI.hello(); + myAPI.hello(); + sandbox.assert.calledTwice(myAPI.hello); + }); +}); +``` + +## Sandbox API + +#### Default sandbox + +Since `sinon@5.0.0`, the `sinon` object is a default sandbox. Unless you have a very advanced setup or need a special configuration, you probably want to just use that one. + +```javascript +const myObject = { + 'hello': 'world' +}; + +sinon.stub(myObject, 'hello').value('Sinon'); + +console.log(myObject.hello); +// Sinon + +sinon.restore(); +console.log(myObject.hello); +// world +``` + +#### `var sandbox = sinon.createSandbox();` + +Creates a new sandbox object with spies, stubs, and mocks. + +#### `var sandbox = sinon.createSandbox(config);` + +The `sinon.createSandbox(config)` method is often an integration feature, and can be used for scenarios including a global object to coordinate all fakes through. + +Sandboxes are partially configured by default such that calling: + +```javascript +var sandbox = sinon.createSandbox({}); +``` + +will merge in extra defaults analogous to: + +```javascript +var sandbox = sinon.createSandbox({ + // ... + injectInto: null, + properties: ["spy", "stub", "mock"], + useFakeTimers: false, + useFakeServer: false +}); +``` + +The `useFakeTimers` and `useFakeServers` are **false** as opposed to the defaults in `sinon.defaultConfig`: + +```javascript +sinon.defaultConfig = { + // ... + injectInto: null, + properties: ["spy", "stub", "mock", "clock", "server", "requests"], + useFakeTimers: true, + useFakeServer: true +} +``` + +To get a full sandbox with stubs, spies, etc. **and** fake timers and servers, you can call: + +```javascript +// Inject the sinon defaults explicitly. +var sandbox = sinon.createSandbox(sinon.defaultConfig); + +// (OR) Add the extra properties that differ from the sinon defaults. +var sandbox = sinon.createSandbox({ + useFakeTimers: true + useFakeServer: true +}); +``` + +##### injectInto + +The sandbox's methods can be injected into another object for convenience. The +`injectInto` configuration option can name an object to add properties to. + +##### properties + +What properties to inject. Note that simply naming "server" here is not +sufficient to have a `server` property show up in the target object, you also +have to set `useFakeServer` to `true`. + +##### useFakeTimers + +If set to `true`, the sandbox will have a `clock` property. You can optionally pass +in a configuration object that follows the [specification for fake timers](../fake-timers), +such as `{ toFake: ["setTimeout", "setInterval"] }`. + +##### useFakeServer + +If `true`, `server` and `requests` properties are added to the sandbox. Can +also be an object to use for fake server. The default one is `sinon.fakeServer`, +but if you're using jQuery 1.3.x or some other library that does not set the XHR's +`onreadystatechange` handler, you might want to do: + +```javascript +sinon.config = { + useFakeServer: sinon.fakeServerWithClock +}; +``` + +#### `sandbox.assert();` + +A convenience reference for [`sinon.assert`](./assertions) + +*Since `sinon@2.0.0`* + +#### `sandbox.replace(object, property, replacement);` + +Replaces `property` on `object` with `replacement` argument. Attempts to replace an already replaced value cause an exception. + +`replacement` can be any value, including `spies`, `stubs` and `fakes`. + +This method only works on non-accessor properties, for replacing accessors, use `sandbox.replaceGetter()` and `sandbox.replaceSetter()`. + + +```js +var myObject = { + myMethod: function() { + return 'apple pie'; + } +}; + +sandbox.replace(myObject, 'myMethod', function () { + return 'strawberry'; +}); + +console.log(myObject.myMethod()); +// strawberry +``` + +#### `sandbox.replaceGetter();` + +Replaces getter for `property` on `object` with `replacement` argument. Attempts to replace an already replaced getter cause an exception. + +`replacement` must be a `Function`, and can be instances of `spies`, `stubs` and `fakes`. + +```js +var myObject = { + get myProperty: function() { + return 'apple pie'; + } +}; + +sandbox.replaceGetter(myObject, 'myMethod', function () { + return 'strawberry'; +}); + +console.log(myObject.myProperty); +// strawberry +``` + +#### `sandbox.replaceSetter();` + +Replaces setter for `property` on `object` with `replacement` argument. Attempts to replace an already replaced setter cause an exception. + +`replacement` must be a `Function`, and can be instances of `spies`, `stubs` and `fakes`. + +```js +var object = { + set myProperty(value) { + this.prop = value; + } +}; + +sandbox.replaceSetter(object, 'myProperty', function (value) { + this.prop = 'strawberry ' + value; +}); + +object.myProperty = 'pie'; + +console.log(object.prop); +// strawberry pie +``` + +#### `sandbox.spy();` + +Works exactly like `sinon.spy` + +#### `sandbox.createStubInstance();` + +Works almost exactly like `sinon.createStubInstance`, only also adds the returned stubs to the internal collection of fakes for easy restoring through `sandbox.restore()`. + +#### `sandbox.stub();` + +Works exactly like `sinon.stub`. + + +##### Stubbing a non-function property +```javascript +const myObject = { + 'hello': 'world' +}; + +sandbox.stub(myObject, 'hello').value('Sinon'); + +console.log(myObject.hello); +// Sinon + +sandbox.restore(); +console.log(myObject.hello); +// world +``` + +#### `sandbox.mock();` + +Works exactly like `sinon.mock` + + +#### `sandbox.useFakeTimers();` + +Fakes timers and binds the `clock` object to the sandbox such that it too is restored when calling `sandbox.restore()`. + +Access through `sandbox.clock`. + + +#### `sandbox.useFakeXMLHttpRequest();` + +Fakes XHR and binds the resulting object to the sandbox such that it too is restored when calling `sandbox.restore()`. + +Since 2.x, you can no longer access requests through `sandbox.requests` - use `sandbox.useFakeServer` to do this. This function maps to `sinon.useFakeXMLHttpRequest`, only with sandboxing. + + +#### `sandbox.useFakeServer();` + +Fakes XHR and binds a server object to the sandbox such that it too is restored when calling `sandbox.restore()`. + +Access requests through `sandbox.requests` and server through `sandbox.server` + +#### `sandbox.usingPromise(promiseLibrary);` + +Causes all stubs and mocks created from the sandbox to return promises using a specific +Promise library instead of the global one when using `stub.rejects` or +`stub.resolves`. Returns the stub to allow chaining. + +*Since `sinon@2.0.0`* + +#### `sandbox.restore();` + +Restores all fakes created through sandbox. + +#### `sandbox.reset();` + +Resets the internal state of all fakes created through sandbox. + +#### `sandbox.resetBehavior();` + +Resets the behaviour of all stubs created through the sandbox. + +*Since `sinon@2.0.0`* + +#### `sandbox.resetHistory();` + +Resets the history of all stubs created through the sandbox. + +*Since `sinon@2.0.0`* + +#### `sandbox.verify();` + +Verifies all mocks created through the sandbox. + +#### `sandbox.verifyAndRestore();` + +Verifies all mocks and restores all fakes created through the sandbox. diff --git a/docs/_releases/v7.2.6/spies.md b/docs/_releases/v7.2.6/spies.md new file mode 100644 index 000000000..906837158 --- /dev/null +++ b/docs/_releases/v7.2.6/spies.md @@ -0,0 +1,438 @@ +--- +layout: page +title: Spies - Sinon.JS +breadcrumb: spies +--- + +### Introduction + +### What is a test spy? + +A test spy is a function that records arguments, return value, the value of +`this` and exception thrown (if any) for all its [calls][call]. There are two types of spies: +Some are anonymous functions, while others wrap methods that already exist in +the system under test. + + +### Creating a spy as an anonymous function + +When the behavior of the spied-on function is not under test, you can use an +anonymous function spy. The spy won't do anything except record information +about its [calls][call]. A common use case for this type of spy is testing how a function +handles a callback, as in the following simplified example: + +```javascript +"test should call subscribers on publish": function () { + var callback = sinon.spy(); + PubSub.subscribe("message", callback); + + PubSub.publishSync("message"); + + assertTrue(callback.called); +} +``` + + +### Using a spy to wrap an existing method + +`sinon.spy(object, "method")` creates a spy that wraps the existing function +`object.method`. The spy will behave exactly like the original method +(including when used as a constructor), but you will have access to data about +all [calls][call]. The following is a slightly contrived example: + +```javascript +{ + setUp: function () { + sinon.spy(jQuery, "ajax"); + }, + + tearDown: function () { + jQuery.ajax.restore(); // Unwraps the spy + }, + + "test should inspect jQuery.getJSON's usage of jQuery.ajax": function () { + jQuery.getJSON("/some/resource"); + + assert(jQuery.ajax.calledOnce); + assertEquals("/some/resource", jQuery.ajax.getCall(0).args[0].url); + assertEquals("json", jQuery.ajax.getCall(0).args[0].dataType); + } +} +``` + + +### Creating spies: `sinon.spy()` Method Signatures + +
+
var spy = sinon.spy();
+
+ Creates an anonymous function that records arguments, this value, + exceptions and return values for all calls. +
+
var spy = sinon.spy(myFunc);
+
Spies on the provided function
+
var spy = sinon.spy(object, "method");
+
+ Creates a spy for object.method and + replaces the original method with the spy. An exception is thrown if the property + is not already a function. The spy acts exactly like the original method in + all cases. The original method can be restored by calling + object.method.restore(). The returned spy is the function + object which replaced the original method. spy === object.method. +
+
+ + +### Spy API + +Spies provide a rich interface to inspect their usage. The above examples showed +the `calledOnce` boolean property as well as the `getCall` method and the +returned object's `args` property. There are three ways of inspecting [call][call] data. + +The preferred approach is to use the spy's `calledWith` method (and friends) +because it keeps your test from being too specific about which call did what and +so on. It will return `true` if the spy was ever called with the provided +arguments. + +```javascript +"test should call subscribers with message as first argument" : function () { + var message = 'an example message'; + var spy = sinon.spy(); + + PubSub.subscribe(message, spy); + PubSub.publishSync(message, "some payload"); + + assert(spy.calledWith(message)); +} +``` + +If you want to be specific, you can directly check the first argument of the +first [call][call]. There are two ways of achieving this: + +```javascript +"test should call subscribers with message as first argument" : function () { + var message = 'an example message'; + var spy = sinon.spy(); + + PubSub.subscribe(message, spy); + PubSub.publishSync(message, "some payload"); + + assertEquals(message, spy.args[0][0]); +} +``` + +```javascript +"test should call subscribers with message as first argument" : function () { + var message = 'an example message'; + var spy = sinon.spy(); + + PubSub.subscribe(message, spy); + PubSub.publishSync(message, "some payload"); + + assertEquals(message, spy.getCall(0).args[0]); +} +``` + +The first example uses the two-dimensional `args` array directly on the spy, +while the second example fetches the first [call][call] object and then accesses its +`args` array. Which one to use is a matter of preference, but the recommended +approach is going with `spy.calledWith(arg1, arg2, ...)` unless there's a need +to make the tests highly specific. + + +## API + +Spy objects are objects returned from `sinon.spy()`. When spying on existing +methods with `sinon.spy(object, method)`, the following properties and methods +are also available on `object.method`. + +### Properties + + +#### `spy.withArgs(arg1[, arg2, ...]);` + +Creates a spy that only records [calls][call] when the received arguments match those passed to `withArgs`. This is useful to be more expressive in your assertions, where you can access the spy with the same [call][call]. + +```javascript +"should call method once with each argument": function () { + var object = { method: function () {} }; + var spy = sinon.spy(object, "method"); + + object.method(42); + object.method(1); + + assert(spy.withArgs(42).calledOnce); + assert(spy.withArgs(1).calledOnce); +} +``` + + +#### `spy.callCount` + +The number of recorded [calls][call]. + + +#### `spy.called` + +`true` if the spy was called at least once + + +#### `spy.notCalled` + +`true` if the spy was not called + + +#### `spy.calledOnce` + +`true` if spy was called exactly once + + +#### `spy.calledTwice` + +`true` if the spy was called exactly twice + + +#### `spy.calledThrice` + +`true` if the spy was called exactly thrice + + +#### `spy.firstCall` + +The first [call][call] + + +#### `spy.secondCall` + +The second [call][call] + + +#### `spy.thirdCall` + +The third [call][call] + + +#### `spy.lastCall` + +The last [call][call] + + +#### `spy.calledBefore(anotherSpy);` + +Returns `true` if the spy was called before `anotherSpy` + + +#### `spy.calledAfter(anotherSpy);` + +Returns `true` if the spy was called after `anotherSpy` + + +#### `spy.calledImmediatelyBefore(anotherSpy);` + +Returns `true` if `spy` was called before `anotherSpy`, and no spy [calls][call] +occurred between `spy` and `anotherSpy`. + + +#### `spy.calledImmediatelyAfter(anotherSpy);` + +Returns `true` if `spy` was called after `anotherSpy`, and no spy [calls][call] +occurred between `anotherSpy` and `spy`. + + +#### `spy.calledOn(obj);` + +Returns `true` if the spy was called at least once with `obj` as `this`. `calledOn` also accepts a matcher `spyCall.calledOn(sinon.match(fn))` (see [matchers](matchers)). + + +#### `spy.alwaysCalledOn(obj);` + +Returns `true` if the spy was always called with `obj` as `this`. + + +#### `spy.calledWith(arg1, arg2, ...);` + +Returns `true` if spy was called at least once with the provided arguments. + +Can be used for partial matching, Sinon only checks the provided arguments against actual arguments, so a call that received the provided arguments (in the same spots) and possibly others as well will return `true`. + +#### `spy.calledOnceWith(arg1, arg2, ...);` + +Returns `true` if spy was called at exactly once with the provided arguments. + + +#### `spy.alwaysCalledWith(arg1, arg2, ...);` + +Returns `true` if spy was always called with the provided arguments (and possibly others). + + +#### `spy.calledWithExactly(arg1, arg2, ...);` + +Returns `true` if spy was called at least once with the provided arguments and no others. + +#### `spy.calledOnceWithExactly(arg1, arg2, ...);` + +Returns `true` if spy was called exactly once and with only the provided arguments. + + +#### `spy.alwaysCalledWithExactly(arg1, arg2, ...);` + +Returns `true` if spy was always called with the exact provided arguments. + + +#### `spy.calledWithMatch(arg1, arg2, ...);` + +Returns `true` if spy was called with matching arguments (and possibly others). + +This behaves the same as `spy.calledWith(sinon.match(arg1), sinon.match(arg2), ...)`. + + +#### `spy.alwaysCalledWithMatch(arg1, arg2, ...);` + +Returns `true` if spy was always called with matching arguments (and possibly others). + +This behaves the same as `spy.alwaysCalledWith(sinon.match(arg1), sinon.match(arg2), ...)`. + + +#### `spy.calledWithNew();` + +Returns `true` if spy/stub was called the `new` operator. + +Beware that this is inferred based on the value of the `this` object and the spy function's `prototype`, so it may give false positives if you actively return the right kind of object. + + +#### `spy.neverCalledWith(arg1, arg2, ...);` + +Returns `true` if the spy/stub was never called with the provided arguments. + + +#### `spy.neverCalledWithMatch(arg1, arg2, ...);` + +Returns `true` if the spy/stub was never called with matching arguments. + +This behaves the same as `spy.neverCalledWith(sinon.match(arg1), sinon.match(arg2), ...)`. + + +#### `spy.threw();` + +Returns `true` if spy threw an exception at least once. + + +#### `spy.threw("TypeError");` + +Returns `true` if spy threw an exception of the provided type at least once. + + +#### `spy.threw(obj);` + +Returns `true` if spy threw the provided exception object at least once. + + +#### `spy.alwaysThrew();` + +Returns `true` if spy always threw an exception. + + +#### `spy.alwaysThrew("TypeError");` + +Returns `true` if spy always threw an exception of the provided type. + + +#### `spy.alwaysThrew(obj);` + +Returns `true` if spy always threw the provided exception object. + + +#### `spy.returned(obj);` + +Returns `true` if spy returned the provided value at least once. + +Uses deep comparison for objects and arrays. Use `spy.returned(sinon.match.same(obj))` for strict comparison (see [matchers](matchers)). + + +#### `spy.alwaysReturned(obj);` + +Returns `true` if spy always returned the provided value. + + +#### `var spyCall = spy.getCall(n);` + +Returns the *nth* [call](#spycall). + +Accessing individual calls helps with more detailed behavior verification when the spy is called more than once. + +```javascript +sinon.spy(jQuery, "ajax"); +jQuery.ajax("/stuffs"); +var spyCall = jQuery.ajax.getCall(0); + +assertEquals("/stuffs", spyCall.args[0]); +``` + + +#### `var spyCalls = spy.getCalls();` + +Returns an `Array` of all [calls][call] recorded by the spy. + + +#### `spy.thisValues` + +Array of `this` objects, `spy.thisValues[0]` is the `this` object for the first [call][call]. + + +#### `spy.args` + +Array of arguments received, `spy.args[0]` is an array of arguments received in the first [call][call]. + + +#### `spy.exceptions` + +Array of exception objects thrown, `spy.exceptions[0]` is the exception thrown by the first [call][call]. + +If the call did not throw an error, the value at the call's location in `.exceptions` will be `undefined`. + + +#### `spy.returnValues` + +Array of return values, `spy.returnValues[0]` is the return value of the first [call][call]. + +If the call did not explicitly return a value, the value at the call's location in `.returnValues` will be `undefined`. + + +#### `spy.resetHistory();` + +Resets the state of a spy. + + +#### `spy.restore();` + +Replaces the spy with the original method. Only available if the spy replaced an existing method. + + +#### `spy.printf("format string", [arg1, arg2, ...]);` + +Returns the passed format string with the following replacements performed: + +
+
%n
+
the name of the spy "spy" by default)
+ +
%c
+
the number of times the spy was called, in words ("once", "twice", etc.)
+ +
%C
+
a list of string representations of the calls to the spy, with each call prefixed by a newline and four spaces
+ +
%t
+
a comma-delimited list of this values the spy was called on
+ +
%n
+
the formatted value of the nth argument passed to printf
+ +
%*
+
a comma-delimited list of the (non-format string) arguments passed to printf
+ +
%D
+
a multi-line list of the arguments received by all calls to the spy
+
+ +[call]: ../spy-call diff --git a/docs/_releases/v7.2.6/spy-call.md b/docs/_releases/v7.2.6/spy-call.md new file mode 100644 index 000000000..e6ea1ec38 --- /dev/null +++ b/docs/_releases/v7.2.6/spy-call.md @@ -0,0 +1,145 @@ +--- +layout: page +title: Spy call - Sinon.JS +breadcrumb: spy-call +--- + +## Spy call + +A spy call is an object representation of an invididual call to a *spied* function, which could be a [fake](../fakes), [spy](../spies), [stub](../stubs) or [mock method](../mocks). + +### `var spyCall = spy.getCall(n)` + +Returns the *nth* [call](#spycall). Accessing individual calls helps with more detailed behavior verification when the spy is called more than once. + +```javascript +sinon.spy(jQuery, "ajax"); +jQuery.ajax("/stuffs"); +var spyCall = jQuery.ajax.getCall(0); + +assertEquals("/stuffs", spyCall.args[0]); +``` + + +### `spyCall.calledOn(obj);` + +Returns `true` if `obj` was `this` for this call. `calledOn` also accepts a matcher `spyCall.calledOn(sinon.match(fn))` (see [matchers](matchers)). + + +### `spyCall.calledWith(arg1, arg2, ...);` + +Returns `true` if call received provided arguments (and possibly others). + + +### `spyCall.calledWithExactly(arg1, arg2, ...);` + +Returns `true` if call received provided arguments and no others. + + +### `spyCall.calledWithMatch(arg1, arg2, ...);` + +Returns `true` if call received matching arguments (and possibly others). +This behaves the same as `spyCall.calledWith(sinon.match(arg1), sinon.match(arg2), ...)`. + + +### `spyCall.notCalledWith(arg1, arg2, ...);` + +Returns `true` if call did not receive provided arguments. + + +### `spyCall.notCalledWithMatch(arg1, arg2, ...);` + +Returns `true` if call did not receive matching arguments. +This behaves the same as `spyCall.notCalledWith(sinon.match(arg1), sinon.match(arg2), ...)`. + +### `spyCall.returned(value);` + +Returns `true` if spied function returned the provided `value` on this call. + +Uses deep comparison for objects and arrays. Use `spyCall.returned(sinon.match.same(obj))` for strict comparison (see [matchers](matchers)). + +### `spyCall.threw();` + +Returns `true` if call threw an exception. + + +### `spyCall.threw("TypeError");` + +Returns `true` if call threw exception of provided type. + + +### `spyCall.threw(obj);` + +Returns `true` if call threw provided exception object. + + +### `spyCall.calledBefore(otherCall)` + +Returns `true` if the spy call occurred before another spy call. + + +### `spyCall.calledAfter(otherCall)` + +Returns `true` if the spy call occurred after another spy call. + + +### `spyCall.calledImmediatelyBefore(otherCall)` + +Returns `true` if the spy call occurred before another call, and no calls to any +other spy occurred in-between. + + +### `spyCall.calledImmediatelyAfter(otherCall)` + +Returns `true` if the spy call occurred after another call, and no calls to any +other spy occurred in-between. + + +### `spyCall.thisValue` + +The call's `this` value. + + +### `spyCall.args` + +Array of received arguments. + + +### `spyCall.callback` + +This property is a convenience for a call's callback. + +When the last argument in a call is a `Function`, then `callback` will reference that. Otherwise it will be `undefined`. + +```js +var spy = sinon.spy(); +var callback = function () {}; + +spy(1, 2, 3, callback); + +spy.lastCall.callback === callback; +// true +``` + +#### `spyCall.lastArg` + +This property is a convenience for the last argument of the call. + +```js +var spy = sinon.spy(); +var date = new Date(); + +spy(1, 2, date); + +spy.lastCall.lastArg === date; +// true +``` + +### `spyCall.exception` + +Exception thrown, if any. + + +### `spyCall.returnValue` + +Return value. diff --git a/docs/_releases/v7.2.6/stubs.md b/docs/_releases/v7.2.6/stubs.md new file mode 100644 index 000000000..0d6778610 --- /dev/null +++ b/docs/_releases/v7.2.6/stubs.md @@ -0,0 +1,664 @@ +--- +layout: page +title: Stubs - Sinon.JS +breadcrumb: stubs +--- + +### What are stubs? + +Test stubs are functions (spies) with pre-programmed behavior. + +They support the full [test spy API](../spies) in addition to methods which can be used to alter the stub's behavior. + +As spies, stubs can be either anonymous, or wrap existing functions. When +wrapping an existing function with a stub, the original function is not called. + + +### When to use stubs? + +Use a stub when you want to: + +1. Control a method's behavior from a test to force the code down a specific path. Examples include forcing a method to throw an error in order to test error handling. + +2. When you want to prevent a specific method from being called directly (possibly because it triggers undesired behavior, such as a `XMLHttpRequest` or similar). + +The following example is yet another test from [PubSubJS][pubsubjs] which shows how to create an anonymous stub that throws an exception when called. + +```javascript +"test should call all subscribers, even if there are exceptions" : function(){ + var message = 'an example message'; + var stub = sinon.stub().throws(); + var spy1 = sinon.spy(); + var spy2 = sinon.spy(); + + PubSub.subscribe(message, stub); + PubSub.subscribe(message, spy1); + PubSub.subscribe(message, spy2); + + PubSub.publishSync(message, undefined); + + assert(spy1.called); + assert(spy2.called); + assert(stub.calledBefore(spy1)); +} +``` + +Note how the stub also implements the spy interface. The test verifies that all +callbacks were called, and also that the exception throwing stub was called +before one of the other callbacks. + +### Defining stub behavior on consecutive calls + +Calling behavior defining methods like `returns` or `throws` multiple times +overrides the behavior of the stub. As of Sinon version 1.8, you can use the +[`onCall`](#stuboncalln-added-in-v18) method to make a stub respond differently on +consecutive calls. + +Note that in Sinon version 1.5 to version 1.7, multiple calls to the `yields*` +and `callsArg*` family of methods define a sequence of behaviors for consecutive +calls. As of 1.8, this functionality has been removed in favor of the +[`onCall`](#stuboncalln-added-in-v18) API. + +[pubsubjs]: https://github.com/mroderick/pubsubjs + +### Stub API + +### Properties + +#### `var stub = sinon.stub();` + +Creates an anonymous stub function + + +#### `var stub = sinon.stub(object, "method");` + +Replaces `object.method` with a stub function. An exception is thrown if the property is not already a function. + +The original function can be restored by calling `object.method.restore();` (or `stub.restore();`). + +#### ~~`var stub = sinon.stub(object, "method", func);`~~ + +This has been removed from `v3.0.0`. Instead you should use + +`stub(obj, 'meth').callsFake(fn)` + +A [codemod is available](https://github.com/hurrymaplelad/sinon-codemod) to upgrade your code + +#### `var stub = sinon.stub(obj);` + +Stubs all the object's methods. + +Note that it's usually better practice to stub individual methods, particularly on objects that you don't understand or control all the methods for (e.g. library dependencies). + +Stubbing individual methods tests intent more precisely and is less susceptible to unexpected behavior as the object's code evolves. + +If you want to create a stub object of `MyConstructor`, but don't want the constructor to be invoked, use this utility function. + +```javascript +var stub = sinon.createStubInstance(MyConstructor, overrides); +``` + +`overrides` is an optional map overriding created stubs, for example: + +```javascript + +var stub = sinon.createStubInstance(MyConstructor, { + foo: sinon.stub().returnsThis() +}); +``` + +is the same as: + +```javascript +var stub = sinon.createStubInstance(MyConstructor); +stub.foo.returnsThis(); +``` + +If provided value is not a stub, it will be used as the returned value: + +```javascript +var stub = sinon.createStubInstance(MyConstructor, { + foo: 3 +}); +``` +is the same as: + +```javascript +var stub = sinon.createStubInstance(MyConstructor); +stub.foo.returns(3); +``` + +#### `stub.withArgs(arg1[, arg2, ...]);` + +Stubs the method only for the provided arguments. + +This is useful to be more expressive in your assertions, where you can access the spy with the same call. It is also useful to create a stub that can act differently in response to different arguments. + +```javascript +"test should stub method differently based on arguments": function () { + var callback = sinon.stub(); + callback.withArgs(42).returns(1); + callback.withArgs(1).throws("name"); + + callback(); // No return value, no exception + callback(42); // Returns 1 + callback(1); // Throws Error("name") +} +``` + +#### `stub.onCall(n);` *Added in v1.8* + +Defines the behavior of the stub on the *nth* call. Useful for testing sequential interactions. + +```javascript +"test should stub method differently on consecutive calls": function () { + var callback = sinon.stub(); + callback.onCall(0).returns(1); + callback.onCall(1).returns(2); + callback.returns(3); + + callback(); // Returns 1 + callback(); // Returns 2 + callback(); // All following calls return 3 +} +``` + +There are methods `onFirstCall`, `onSecondCall`,`onThirdCall` to make stub definitions read more naturally. + +`onCall` can be combined with all of the behavior defining methods in this section. In particular, it can be used together with `withArgs`. + +```javascript +"test should stub method differently on consecutive calls with certain argument": function () { + var callback = sinon.stub(); + callback.withArgs(42) + .onFirstCall().returns(1) + .onSecondCall().returns(2); + callback.returns(0); + + callback(1); // Returns 0 + callback(42); // Returns 1 + callback(1); // Returns 0 + callback(42); // Returns 2 + callback(1); // Returns 0 + callback(42); // Returns 0 +} +``` + +Note how the behavior of the stub for argument `42` falls back to the default behavior once no more calls have been defined. + +#### `stub.onFirstCall();` + +Alias for `stub.onCall(0);` + +#### `stub.onSecondCall();` + +Alias for `stub.onCall(1);` + +#### `stub.onThirdCall();` +Alias for `stub.onCall(2);` + + +#### `stub.reset();` + +Resets both behaviour and history of the stub. + +This is equivalent to calling both `stub.resetBehavior()` and `stub.resetHistory()` + +*Updated in `sinon@2.0.0`* + +*Since `sinon@5.0.0`* + +As a convenience, you can apply `stub.reset()` to all stubs using `sinon.reset()` + +#### `stub.resetBehavior();` + +Resets the stub's behaviour to the default behaviour + +```javascript +var stub = sinon.stub(); + +stub.returns(54) + +stub(); // 54 + +stub.resetBehavior(); + +stub(); // undefined +``` + +*Since `sinon@5.0.0`* + +You can reset behaviour of all stubs using `sinon.resetBehavior()` + + +#### `stub.resetHistory();` + +*Since `sinon@2.0.0`* + +Resets the stub's history + +```javascript +var stub = sinon.stub(); + +stub.called // false + +stub(); + +stub.called // true + +stub.resetHistory(); + +stub.called // false +``` + + +*Since `sinon@5.0.0`* + +You can reset history of all stubs using `sinon.resetHistory()` + + +#### `stub.callsFake(fakeFunction);` +Makes the stub call the provided `fakeFunction` when invoked. + +```javascript +var myObj = {}; +myObj.prop = function propFn() { + return 'foo'; +}; + +sinon.stub(myObj, 'prop').callsFake(function fakeFn() { + return 'bar'; +}); + +myObj.prop(); // 'bar' +``` + +#### `stub.returns(obj);` +Makes the stub return the provided value. + +#### `stub.returnsArg(index);` + +Causes the stub to return the argument at the provided index. + +`stub.returnsArg(0);` causes the stub to return the first argument. + +If the argument at the provided index is not available, prior to `sinon@6.1.2`, +an `undefined` value will be returned; starting from `sinon@6.1.2`, a `TypeError` +will be thrown. + + +#### `stub.returnsThis();` +Causes the stub to return its this value. + +Useful for stubbing jQuery-style fluent APIs. + +#### `stub.resolves(value);` + +Causes the stub to return a Promise which resolves to the provided value. + +When constructing the Promise, sinon uses the `Promise.resolve` method. You are +responsible for providing a polyfill in environments which do not provide `Promise`. +The Promise library can be overwritten using the `usingPromise` method. + +*Since `sinon@2.0.0`* + +#### `stub.resolvesArg(index);` + +Causes the stub to return a Promise which resolves to the argument at the +provided index. + +`stub.resolvesArg(0);` causes the stub to return a Promise which resolves to the +first argument. + +If the argument at the provided index is not available, a `TypeError` will be +thrown. + +*Since `sinon@6.1.1`* + +#### `stub.throws();` + +Causes the stub to throw an exception (`Error`). + + +#### `stub.throws("name"[, "optional message"]);` + +Causes the stub to throw an exception with the `name` property set to the provided string. The message parameter is optional and will set the `message` property of the exception. + + +#### `stub.throws(obj);` + +Causes the stub to throw the provided exception object. + + +#### `stub.throws(function() { return new Error(); });` + +Causes the stub to throw the exception returned by the function. + + +### `stub.throwsArg(index);` + +Causes the stub to throw the argument at the provided index. + +`stub.throwsArg(0);` causes the stub to throw the first argument as the +exception. + +If the argument at the provided index is not available, a `TypeError` will be +thrown. + +*Since `sinon@2.3.0`* + +#### `stub.rejects();` + +Causes the stub to return a Promise which rejects with an exception (`Error`). + +When constructing the Promise, sinon uses the `Promise.reject` method. You are +responsible for providing a polyfill in environments which do not provide `Promise`. +The Promise library can be overwritten using the `usingPromise` method. + +*Since `sinon@2.0.0`* + + +#### `stub.rejects("TypeError");` + +Causes the stub to return a Promise which rejects with an exception of the provided type. + +*Since `sinon@2.0.0`* + + +#### `stub.rejects(value);` + +Causes the stub to return a Promise which rejects with the provided exception object. + +*Since `sinon@2.0.0`* + + +#### `stub.callsArg(index);` + +Causes the stub to call the argument at the provided index as a callback function. + +`stub.callsArg(0);` causes the stub to call the first argument as a callback. + +If the argument at the provided index is not available or is not a function, +a `TypeError` will be thrown. + + +#### `stub.callThrough();` + +Causes the original method wrapped into the stub to be called when none of the conditional stubs are matched. + +```javascript +var stub = sinon.stub(); + +var obj = {}; + +obj.sum = function sum(a, b) { + return a + b; +}; + +stub(obj, 'sum'); + +obj.sum.withArgs(2, 2).callsFake(function foo() { + return 'bar'; +}); + +obj.sum.callThrough(); + +obj.sum(2, 2); // 'bar' +obj.sum(1, 2); // 3 +``` + + +#### `stub.callsArgOn(index, context);` + +Like `stub.callsArg(index);` but with an additional parameter to pass the `this` context. + + +#### `stub.callsArgWith(index, arg1, arg2, ...);` + +Like `callsArg`, but with arguments to pass to the callback. + + +#### `stub.callsArgOnWith(index, context, arg1, arg2, ...);` + +Like above but with an additional parameter to pass the `this` context. + +#### `stub.usingPromise(promiseLibrary);` + +Causes the stub to return promises using a specific Promise library instead of +the global one when using `stub.rejects` or `stub.resolves`. Returns the stub +to allow chaining. + +```javascript +var myObj = { + saveSomething: sinon.stub().usingPromise(bluebird.Promise).resolves("baz"); +} + +myObj.saveSomething() + .tap(function(actual) { + console.log(actual); // baz + }); +``` + +*Since `sinon@2.0.0`* + +#### `stub.yields([arg1, arg2, ...])` + +Similar to `callsArg`. + +Causes the stub to call the first callback it receives with the provided arguments (if any). + +If a method accepts more than one callback, you need to use `yieldsRight` to call the last callback or `callsArg` to have the stub invoke other callbacks than the first or last one. + + +#### `stub.yieldsRight([arg1, arg2, ...])` + +Like `yields` but calls the last callback it receives. + + +#### `stub.yieldsOn(context, [arg1, arg2, ...])` + +Like `yields` but with an additional parameter to pass the `this` context. + + +#### `stub.yieldsTo(property, [arg1, arg2, ...])` + +Causes the spy to invoke a callback passed as a property of an object to the spy. + +Like `yields`, `yieldsTo` grabs the first matching argument, finds the callback and calls it with the (optional) arguments. + + +#### `stub.yieldsToOn(property, context, [arg1, arg2, ...])` + +Like above but with an additional parameter to pass the `this` context. + +```javascript +"test should fake successful ajax request": function () { + sinon.stub(jQuery, "ajax").yieldsTo("success", [1, 2, 3]); + + jQuery.ajax({ + success: function (data) { + assertEquals([1, 2, 3], data); + } + }); +} +``` + + +#### `stub.yield([arg1, arg2, ...])` + +Invoke callbacks passed to the `stub` with the given arguments. + +If the stub was never called with a function argument, `yield` throws an error. + +Returns an Array with all callbacks return values in the order they were called, if no error is thrown. + +Also aliased as `invokeCallback`. + + +#### `stub.yieldTo(callback, [arg1, arg2, ...])` + +Invokes callbacks passed as a property of an object to the stub. + +Like `yield`, `yieldTo` grabs the first matching argument, finds the callback and calls it with the (optional) arguments. + +```javascript +"calling callbacks": function () { + var callback = sinon.stub(); + callback({ + "success": function () { + console.log("Success!"); + }, + "failure": function () { + console.log("Oh noes!"); + } + }); + + callback.yieldTo("failure"); // Logs "Oh noes!" +} +``` + + +#### `stub.callArg(argNum)` + +Like `yield`, but with an explicit argument number specifying which callback to call. + +Useful if a function is called with more than one callback, and simply calling the first callback is not desired. + +```javascript +"calling the last callback": function () { + var callback = sinon.stub(); + callback(function () { + console.log("Success!"); + }, function () { + console.log("Oh noes!"); + }); + + callback.callArg(1); // Logs "Oh noes!" +} +``` + +#### `stub.callArgWith(argNum, [arg1, arg2, ...])` + +Like `callArg`, but with arguments. + +#### Asynchronous calls + +Same as their corresponding non-Async counterparts, but with callback being deferred at called after all instructions in the current call stack are processed. + +* In Node environment the callback is deferred with `process.nextTick`. +* In a browser the callback is deferred with `setTimeout(callback, 0)`. + +More information: + +* , +* , +* . + +##### `stub.callsArgAsync(index);` + +Async version of [stub.callsArg(index)](#stubcallsargindex). See also [Asynchronous calls](#asynchronous-calls). + +##### `stub.callsArgOnAsync(index, context);` + +Async version of [stub.callsArgOn(index, context)](#stubcallsargonindex-context). See also [Asynchronous calls](#asynchronous-calls). + +##### `stub.callsArgWithAsync(index, arg1, arg2, ...);` + +Async version of [stub.callsArgWith(index, arg1, arg2, ...)](#stubcallsargwithindex-arg1-arg2-). See also [Asynchronous calls](#asynchronous-calls). + +##### `stub.callsArgOnWithAsync(index, context, arg1, arg2, ...);` + +Async version of [stub.callsArgOnWith(index, context, arg1, arg2, ...)](#stubcallsargonwithindex-context-arg1-arg2-). See also [Asynchronous calls](#asynchronous-calls). + +##### `stub.yieldsAsync([arg1, arg2, ...]);` + +Async version of [stub.yields([arg1, arg2, ...])](#stubyieldsarg1-arg2-). See also [Asynchronous calls](#asynchronous-calls). + +##### `stub.yieldsOnAsync(context, [arg1, arg2, ...]);` + +Async version of [stub.yieldsOn(context, [arg1, arg2, ...])](#stubyieldsoncontext-arg1-arg2-). See also [Asynchronous calls](#asynchronous-calls). + +##### `stub.yieldsToAsync(property, [arg1, arg2, ...]);` + +Async version of [stub.yieldsTo(property, [arg1, arg2, ...])](#stubyieldstoproperty-arg1-arg2-). See also [Asynchronous calls](#asynchronous-calls). + +##### `stub.yieldsToOnAsync(property, context, [arg1, arg2, ...])` + +Async version of [stub.yieldsToOn(property, context, [arg1, arg2, ...])](#stubyieldstoonproperty-context-arg1-arg2-). See also [Asynchronous calls](#asynchronous-calls). + +#### `sinon.addBehavior(name, fn);` + +Add a custom behavior. The name will be available as a function on stubs, and the chaining mechanism will be set up for you (e.g. no need to return anything from your function, its return value will be ignored). The `fn` will be passed the fake instance as its first argument, and then the user's arguments. + +```javascript +const sinon = require('sinon'); + +sinon.addBehavior('returnsNum', (fake, n) => fake.returns(n)); + +var stub = sinon.stub().returnsNum(42); + +assert.equals(stub(), 42); +``` + +#### `stub.get(getterFn)` + +Replaces a new getter for this stub. + +```javascript +var myObj = { + prop: 'foo' +}; + +sinon.stub(myObj, 'prop').get(function getterFn() { + return 'bar'; +}); + +myObj.prop; // 'bar' +``` + +#### `stub.set(setterFn)` + +Defines a new setter for this stub. + +```javascript +var myObj = { + example: 'oldValue', + prop: 'foo' +}; + +sinon.stub(myObj, 'prop').set(function setterFn(val) { + myObj.example = val; +}); + +myObj.prop = 'baz'; + +myObj.example; // 'baz' +``` + +#### `stub.value(newVal)` + +Defines a new value for this stub. + +```javascript +var myObj = { + example: 'oldValue', +}; + +sinon.stub(myObj, 'example').value('newValue'); + +myObj.example; // 'newValue' +``` + +You can restore values by calling the `restore` method: + +```javascript +var myObj = { + example: 'oldValue', +}; + +var stub = sinon.stub(myObj, 'example').value('newValue'); +stub.restore() + +myObj.example; // 'oldValue' +``` + diff --git a/docs/_releases/v7.2.6/utils.md b/docs/_releases/v7.2.6/utils.md new file mode 100644 index 000000000..79ca18dea --- /dev/null +++ b/docs/_releases/v7.2.6/utils.md @@ -0,0 +1,25 @@ +--- +layout: page +title: Utilities - Sinon.JS +breadcrumb: utilities +--- + +Sinon.JS has a few utilities used internally in `lib/sinon.js`. Unless the method in question is documented here, it should not be considered part of the public API, and thus is subject to change. + +## Utils API + +#### `sinon.createStubInstance(constructor);` + +Creates a new object with the given function as the protoype and stubs all implemented functions. + +```javascript + class Container { + contains(item) { /* ... */ } + } + + var stubContainer = sinon.createStubInstance(Container); + stubContainer.contains.returns(false); + stubContainer.contains.withArgs("item").returns(true); +``` + +The given constructor function is not invoked. See also the [stub API](../stubs).