UNPKG

8.65 kBMarkdownView Raw
1[![Build Status](https://travis-ci.org/box/leche.png?branch=master)](https://travis-ci.org/box/leche)
2[![Project Status](http://opensource.box.com/badges/stable.svg)](http://opensource.box.com/badges)
3
4# Leche
5
6A JavaScript testing utility designed to work with Mocha and Sinon. This is intended for use both by Node.js and in browsers, so any changes must work in both locations.
7
8## Installation
9
10There are slightly different installation instructions based on where you want to use Leche.
11
12### Including in Node.js
13
14To include Leche in your Node.js project, go to your project directory and type:
15
16```
17npm i leche --save-dev
18```
19
20This command will automatically add Leche as a dependency inside of your `package.json` file.
21To include Leche in a Node.js file, use `require()`:
22
23```js
24var leche = require('leche');
25```
26
27The `leche` object is a singleton, so there is no need to initialize it.
28
29### Including in a Web Page
30
31To include Leche in a web page, you can use [RawGit](http://rawgit.com).
32
33The last published release:
34
35```
36<script src="https://cdn.rawgit.com/box/leche/master/dist/leche.js"></script>
37```
38
39Minified:
40
41```
42<script src="https://cdn.rawgit.com/box/leche/master/dist/leche.min.js"></script>
43```
44
45A specific version (in this example v2.1.0):
46
47```
48<script src="https://cdn.rawgit.com/box/leche/v2.1.0/dist/leche.js"></script>
49```
50
51Minified:
52
53```
54<script src="https://cdn.rawgit.com/box/leche/v2.1.0/dist/leche.min.js"></script>
55```
56
57**Note:** We highly recommend using a specific version as the master branch may change without notice.
58
59A global `leche` object is created and is the same as the Node.js version.
60
61## Creating Objects
62
63Sometimes in testing you need to quickly create an object with specific methods that don't do anything in particular. The `leche.create()` method lets you specify an array of methods to create, and it returns an object with those methods stubbed out to do nothing. For example:
64
65```js
66var myObject = leche.create(["doSomething", "doSomethingElse"]);
67
68myObject.doSomething(); // does nothing, actually
69myObject.doSomethingElse(); // ditto
70
71assert.ok(myObject.hasOwnProperty("doSomething")); // passes
72assert.ok(myObject.hasOwnProperty("doSomethingElse")); // passes
73```
74
75Creating objects in this manner is useful when you don't have an original object from which to create a fake. You can pass this object into `leche.fake()` in order to create a fake (see next section).
76
77## Creating Fakes
78
79Fakes are objects that share a prototype chain and method definitions of another object, but do not implement any of the methods. Instead, the methods throw exceptions when called. This makes fakes useful for testing in several ways:
80
81* You can create an object with the same interface as an actual object.
82* You can use this object with `sinon.mock()` to set expectations that override the default method behavior of throwing an error. This ensures that only methods with expectations explicitly set can be called.
83* The fake will pass any `instanceof` checks that the original object would pass.
84
85Additionally, fakes contain all of the properties of the passed-in object. In ECMAScript 5 environments, accessing these properties without first setting them to a value will result in an errow.
86
87To create a fake, pass in the object you want to fake to `leche.fake()`, such as:
88
89```js
90// source
91function Person(name) {
92 this.name = name;
93}
94
95Person.prototype.sayName = function() {
96 console.log(this.name);
97};
98
99Person.prototype.sayHi = function() {
100 console.log('Hi!');
101
102};
103
104// in a test
105var fakePerson = leche.fake(new Person('Jeff'));
106
107assert.ok(fakePerson instanceof Person); // passes
108assert.ok('sayName' in fakePerson); // passes
109assert.ok('name' in fakePerson); // passes
110
111// throws an error
112fakePerson.sayName();
113
114// also throws an error
115var name = fakePerson.name;
116
117// won't throw an error because you've assigned a value
118fakePerson.name = 'Jeff';
119var name = fakePerson.name;
120```
121
122Fakes are useful for creating mocks, where you set an expectation that a certain method will be called. Sinon will redefine the method with the expectation and no error will be thrown. However, trying to call any other method on the fake will result in an error. For example:
123
124```js
125 // in a test
126var fakePersonMock = leche.fake(Person.prototype);
127var fakePersonMockHandler = sinon.mock(fakePersonMock);
128
129fakePersonMockHandler.expects('sayName');
130
131fakePersonMock.sayName(); // no error - Sinon has mocked it out
132fakePersonMock.sayHi(); // throws an error
133```
134
135This pattern is useful for a couple reasons:
136
1371. Sinon will not let you set an expectation for a method that doesn't exist on fakePerson. It will throw an error.
1381. Leche won't let you call a method for which an expectation has not been set. It will throw an error.
139
140These features let you test the interface of existing objects in a robust and less error-prone way.
141
142## Mocha Data Provider
143
144Leche has a Mocha-specific data provider implementation called `withData()`. The intent of `withData()` is to mimic the `QUnit.cases` functionality in QUnit, allowing you to run the same tests over multiple values in a dataset. The basic format (using labels) is:
145
146```js
147var withData = leche.withData;
148
149describe('MyObject', function() {
150
151 withData({
152 label1: [1, 2],
153 label2: [3, 4]
154 }, function(first, second) {
155
156 it('should say the values are equal when they are passed', function() {
157 assert.equal(first, second);
158 });
159 });
160});
161```
162
163In this example, there are two data sets. The first is called "label1" and has an array of two values. The second is called "label2" and also has an array of two values. The label is used as part of the output from Mocha when an error occurs in the test. The arrays are used to specify the arguments that should be passed into the function. In this example, `first` would be 1 for the first dataset and `second` would be 2. For the second dataset, `first` would be 3 and `second` would be 4.
164
165### Naming tests when using withData with labels
166
167When using the label form of `withData()`, you should name the labels so that they complete the sentence created by your "it('should...')" definition. For example:
168
169```js
170describe('getSharedLinkForPadByClientID', function() {
171 withData({
172 'no fileId in session': [{authToken: 'abcdef123456'}],
173 'no authToken in session': [{fileId: '123456678'}],
174 }, function(sessionInfo) {
175 it('should send error to client', function() {
176 //...
177 });
178 });
179});
180```
181
182If both these test failed, the outputted error message would look like:
183
184```
1851) getSharedLinkForPadByClientID with no fileId in session should send error to client
1862) getSharedLinkForPadByClientID with no authToken in session should send error to client
187```
188
189### withData() without labels
190
191You can also pass data without labels, and `withData()` will do its best to create a label that makes sense:
192
193```js
194var withData = leche.withData;
195
196describe('MyObject', function() {
197
198 withData([
199 [1, 2],
200 [3, 4]
201 ], function(first, second) {
202
203 it('should say the values are equal when they are passed', function() {
204 assert.equal(first, second);
205 });
206 });
207});
208```
209
210This is the same as the previous example, except the labels will come out as "1,2" for the first dataset and "3,4" for the second.
211
212## Frequently Asked Questions
213
214### What is "Leche"?
215
216You put leche in your mocha to make it taste awesome.
217
218## Build System
219
220This project uses `make` for its build system, but you should use `npm` for executing commands. The following commands are available:
221
222* `npm test` - runs linting and unit tests (plus code coverage)
223* `npm run lint` - runs just linting
224* `npm run jsdoc` - creates JSDoc documentation
225
226## Developing Leche
227
2281. Clone this repo.
2291. Run `npm install`.
2301. Run `npm test` to ensure everything is working.
2311. Profit.
232
233## Support
234
235Need to contact us directly? Email oss@box.com and be sure to include the name of this project in the subject.
236
237## Copyright and License
238
239Copyright 2014-2015 Box, Inc. All rights reserved.
240
241Licensed under the Apache License, Version 2.0 (the "License");
242you may not use this file except in compliance with the License.
243You may obtain a copy of the License at
244
245 http://www.apache.org/licenses/LICENSE-2.0
246
247Unless required by applicable law or agreed to in writing, software
248distributed under the License is distributed on an "AS IS" BASIS,
249WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
250See the License for the specific language governing permissions and
251limitations under the License.