Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add runnable example for Spies documentation - Resolves #2040 #2122

Merged
merged 3 commits into from
Oct 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .markdownlintrc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"punctuation": ".,;:!"
},
"MD033": {
"allowed_elements": ["dl", "dt", "dd", "code", "var"]
"allowed_elements": ["dl", "dt", "dd", "code", "var", "div"]
},
"first-line-h1": false,
"no-hard-tabs": true,
Expand Down
21 changes: 21 additions & 0 deletions docs/_includes/embed-scripts.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{% for example in page.examples %}
{% assign filename = 'examples/' | append: example | append: '.stub' %}
<template data-example-script="{{ example }}">{% include_relative {{filename}} %}</template>
<script>
(function(){
// get script example div
var element = document.querySelector("[data-example-id={{ example }}]");

// get script example source from the template
var scriptTemplate = document.querySelector("[data-example-script={{ example }}]");

var notebook = RunKit.createNotebook({
// the parent element for the new notebook
element: element,
// specify the source of the notebook
source: scriptTemplate.innerHTML,
theme: "untilted-c3qcs6lijfuc"
});
})(); // IIFE - to avoid leaking variables
</script>
{% endfor %}
2 changes: 2 additions & 0 deletions docs/_includes/footer.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script src="{{ "/assets/js/prism.js" | prepend: site.baseurl }}"></script>
<script src="https://embed.runkit.com"></script>
{% include embed-scripts.html %}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just put the script at the end of this file, along with the include

    <script src="https://embed.runkit.com"></script>

<div class="footer">
<div class="container text-center">
Expand Down
16 changes: 16 additions & 0 deletions docs/release-source/release/examples/spies-1-pubsub.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require("@fatso83/mini-mocha").install();
var sinon = require("sinon");
var PubSub = require("pubsub-js");
var referee = require("@sinonjs/referee");
var assertTrue = referee.assert;

describe('PubSub', function() {
it("should call subscribers on publish", function () {
var callback = sinon.spy();

PubSub.subscribe("message", callback);
PubSub.publishSync("message");

assertTrue(callback.called);
})
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require("@fatso83/mini-mocha").install();
var sinon = require("sinon");
var referee = require("@sinonjs/referee");
var assert = referee.assert;
var jsdom = require('jsdom');
var JSDOM = jsdom.JSDOM;
var window = (new JSDOM()).window;
var document = (new JSDOM('')).window;
var jQuery = require('jquery')(window);
global.document = document;

describe('Wrap all object method', function() {
var sandbox = sinon.createSandbox();

beforeEach(function() {
sandbox.spy(jQuery);
});

afterEach(function() {
sandbox.restore();
});

it("should inspect jQuery.getJSON's usage of jQuery.ajax", function () {
var url = "https://jsonplaceholder.typicode.com/todos/1";
jQuery.getJSON(url);

assert(jQuery.ajax.calledOnce);
assert.equals(url, jQuery.ajax.getCall(0).args[0].url);
assert.equals("json", jQuery.ajax.getCall(0).args[0].dataType);
})
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require("@fatso83/mini-mocha").install();
var sinon = require("sinon");
var referee = require("@sinonjs/referee");
var assert = referee.assert;
var jsdom = require('jsdom');
var JSDOM = jsdom.JSDOM;
var window = (new JSDOM()).window;
var document = (new JSDOM('')).window;
var jQuery = require('jquery')(window);
global.document = document;

describe('Wrap existing method', function() {
var sandbox = sinon.createSandbox();

beforeEach(function() {
sandbox.spy(jQuery, "ajax");
});

afterEach(function() {
sandbox.restore();
});

it("should inspect jQuery.getJSON's usage of jQuery.ajax", function () {
var url = "https://jsonplaceholder.typicode.com/todos/1";
jQuery.getJSON(url);

assert(jQuery.ajax.calledOnce);
assert.equals(url, jQuery.ajax.getCall(0).args[0].url);
assert.equals("json", jQuery.ajax.getCall(0).args[0].dataType);
})
});
17 changes: 17 additions & 0 deletions docs/release-source/release/examples/spies-4-pubsub-message-1.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require("@fatso83/mini-mocha").install();
var sinon = require("sinon");
var PubSub = require("pubsub-js");
var referee = require("@sinonjs/referee");
var assert = referee.assert;

describe('PubSub', function() {
it("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));
})
});
17 changes: 17 additions & 0 deletions docs/release-source/release/examples/spies-5-pubsub-message-2.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require("@fatso83/mini-mocha").install();
var sinon = require("sinon");
var PubSub = require("pubsub-js");
var referee = require("@sinonjs/referee");
var assert = referee.assert;

describe('PubSub', function() {
it("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.equals(message, spy.args[0][0]);
})
});
17 changes: 17 additions & 0 deletions docs/release-source/release/examples/spies-6-pubsub-message-3.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require("@fatso83/mini-mocha").install();
var sinon = require("sinon");
var PubSub = require("pubsub-js");
var referee = require("@sinonjs/referee");
var assert = referee.assert;

describe('PubSub', function() {
it("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.equals(message, spy.getCall(0).args[0]);
})
});
17 changes: 17 additions & 0 deletions docs/release-source/release/examples/spies-7-with-args.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
require("@fatso83/mini-mocha").install();
var sinon = require("sinon");
var referee = require("@sinonjs/referee");
var assert = referee.assert;

describe('withArgs', function() {
it("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);
})
});
30 changes: 30 additions & 0 deletions docs/release-source/release/examples/spies-8-spy-call.stub
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
require("@fatso83/mini-mocha").install();
var sinon = require("sinon");
var referee = require("@sinonjs/referee");
var assert = referee.assert;
var jsdom = require('jsdom');
var JSDOM = jsdom.JSDOM;
var window = (new JSDOM()).window;
var document = (new JSDOM('')).window;
var jQuery = require('jquery')(window);
global.document = document;

describe('Return nth call', function() {
var sandbox = sinon.createSandbox();

beforeEach(function() {
sandbox.spy(jQuery, "ajax");
});

afterEach(function() {
sandbox.restore();
});

it("should inspect jQuery.getJSON's usage of jQuery.ajax", function () {
var url = "https://jsonplaceholder.typicode.com/todos/1";
jQuery.ajax(url);
var spyCall = jQuery.ajax.getCall(0);

assert.equals(url, spyCall.args[0]);
})
});
121 changes: 18 additions & 103 deletions docs/release-source/release/spies.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@
layout: page
title: Spies - Sinon.JS
breadcrumb: spies
examples:
- spies-1-pubsub
- spies-2-wrap-object-methods
- spies-3-wrap-existing-method
- spies-4-pubsub-message-1
- spies-5-pubsub-message-2
- spies-6-pubsub-message-3
- spies-7-with-args
- spies-8-spy-call
---

### Introduction
Expand All @@ -21,16 +30,7 @@ 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);
}
```
<div data-example-id="spies-1-pubsub"></div>

### Using a spy to wrap all object method

Expand All @@ -42,29 +42,9 @@ Note that it's usually better practice to spy individual methods, particularly o

Spying individual methods tests intent more precisely and is less susceptible to unexpected behavior as the object's code evolves.

The following is a slightly contrived example:

```javascript
{
sandbox: sinon.createSandbox(),

setUp: function () {
this.sandbox.spy(jQuery);
},

tearDown: function () {
this.sandbox.restore(); // Unwraps all spied methods
},
The following is a slightly contrived example:

"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);
}
}
```
<div data-example-id="spies-2-wrap-object-methods"></div>


### Using a spy to wrap an existing method
Expand All @@ -74,25 +54,7 @@ Spying individual methods tests intent more precisely and is less susceptible to
(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);
}
}
```
<div data-example-id="spies-3-wrap-existing-method"></div>


### Creating spies: `sinon.spy()` Method Signatures
Expand Down Expand Up @@ -128,44 +90,14 @@ 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));
}
```
<div data-example-id="spies-4-pubsub-message-1"></div>

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();
<div data-example-id="spies-5-pubsub-message-2"></div>

PubSub.subscribe(message, spy);
PubSub.publishSync(message, "some payload");

assertEquals(message, spy.getCall(0).args[0]);
}
```
<div data-example-id="spies-6-pubsub-message-3"></div>

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
Expand All @@ -187,18 +119,7 @@ are also available on `object.method`.

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);
}
```
<div data-example-id="spies-7-with-args"></div>


#### `spy.callCount`
Expand Down Expand Up @@ -394,13 +315,7 @@ 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]);
```
<div data-example-id="spies-8-spy-call"></div>


#### `var spyCalls = spy.getCalls();`
Expand Down