├── LICENSE
├── Mocha-Unit-Testing-Example
├── .gitignore
├── README.md
├── js
│ └── className.js
├── package.json
├── test
│ ├── arrayTest.js
│ └── classNameTest.js
└── testrunner.html
├── README.md
├── Section-1
├── 1.3
│ └── 01-Writing-your-first-unit-test
│ │ ├── .DS_Store
│ │ ├── after
│ │ ├── .gitignore
│ │ ├── math.js
│ │ └── package.json
│ │ └── before
│ │ ├── .gitignore
│ │ ├── math.js
│ │ └── package.json
├── 1.4
│ └── 04-testing-numbers-and-strings
│ │ ├── .DS_Store
│ │ ├── after
│ │ ├── .DS_Store
│ │ ├── math.js
│ │ ├── package.json
│ │ ├── tests
│ │ │ ├── math.test.js
│ │ │ └── util.test.js
│ │ └── util.js
│ │ └── before
│ │ ├── .DS_Store
│ │ ├── math.js
│ │ ├── package.json
│ │ ├── tests
│ │ ├── .DS_Store
│ │ └── math.test.js
│ │ └── util.js
├── 1.5
│ └── 05-testing-thruthiness
│ │ ├── .DS_Store
│ │ ├── after
│ │ ├── package.json
│ │ ├── tests
│ │ │ └── util.test.js
│ │ └── util.js
│ │ └── before
│ │ ├── package.json
│ │ ├── tests
│ │ └── util.test.js
│ │ └── util.js
├── 1.6
│ └── 06-testing-arrays-and-objects
│ │ ├── after
│ │ ├── .DS_Store
│ │ ├── package.json
│ │ ├── tests
│ │ │ └── util.test.js
│ │ └── util.js
│ │ └── before
│ │ ├── package.json
│ │ ├── tests
│ │ └── util.test.js
│ │ └── util.js
└── 1.7
│ └── 07-testing-exceptions
│ ├── .DS_Store
│ ├── after
│ ├── package.json
│ ├── tests
│ │ └── util.test.js
│ └── util.js
│ └── before
│ ├── .DS_Store
│ ├── package.json
│ ├── tests
│ └── util.test.js
│ └── util.js
├── Section-2
├── 2.2
│ ├── BankAccount.js
│ ├── package.json
│ └── tests
│ │ └── BankAcount.test.js
└── 2.4
│ ├── Gruntfile.js
│ ├── README.md
│ ├── features
│ └── addition.feature
│ ├── gulpfile.js
│ ├── package-lock.json
│ └── package.json
├── Section-3
├── 3.1
│ ├── package-lock.json
│ ├── package.json
│ └── tests
│ │ └── assert-demo.test.js
├── 3.2
│ ├── math.js
│ ├── package-lock.json
│ ├── package.json
│ └── tests
│ │ ├── assert-demo.test.js
│ │ ├── chai.js-demo.test.js
│ │ ├── expect-demo.test.js
│ │ └── should.js-demo.test.js
├── 3.3
│ ├── math.js
│ ├── package-lock.json
│ ├── package.json
│ └── tests
│ │ ├── assert-demo.test.js
│ │ ├── chai.js-demo.test.js
│ │ ├── expect-demo.test.js
│ │ └── should.js-demo.test.js
└── 3.4
│ ├── math.js
│ ├── package-lock.json
│ ├── package.json
│ └── tests
│ ├── assert-demo.test.js
│ ├── chai.js-demo.test.js
│ ├── expect-demo.test.js
│ └── should.js-demo.test.js
├── Section-4
├── 4.1
│ ├── package-lock.json
│ ├── package.json
│ └── spec
│ │ ├── math.spec.js
│ │ └── support
│ │ └── jasmine.json
├── 4.2
│ ├── math.js
│ ├── package-lock.json
│ ├── package.json
│ └── test
│ │ ├── db.js
│ │ └── test.js
├── 4.3
│ ├── data.txt
│ ├── package-lock.json
│ ├── package.json
│ └── tests
│ │ └── math.test.js
├── 4.4
│ ├── package-lock.json
│ ├── package.json
│ └── tests
│ │ └── test.js
└── 4.5
│ ├── intern.json
│ ├── package-lock.json
│ ├── package.json
│ └── tests
│ └── unit
│ └── test.js
├── Section-5
├── config-overrides.js
├── package.json
└── src
│ ├── __mocks__
│ └── axios.js
│ └── services
│ ├── __tests__
│ ├── posts.js
│ └── users.js
│ ├── posts.js
│ └── users.js
├── javascript-unit-testing-with-mocha
├── .gitignore
├── 01-basic-spec
│ ├── .gitignore
│ ├── package.json
│ └── test
│ │ └── test.js
├── 02-testing-function
│ ├── .gitignore
│ ├── controllers
│ │ └── login.controller.js
│ ├── package.json
│ └── test
│ │ └── controllers
│ │ └── login.controller.spec.js
├── 03-async-callback
│ ├── .gitignore
│ ├── controllers
│ │ └── login.controller.js
│ ├── package.json
│ └── test
│ │ └── controllers
│ │ └── login.controller.spec.js
├── 04-hooks
│ ├── .gitignore
│ ├── controllers
│ │ └── login.controller.js
│ ├── package.json
│ └── test
│ │ └── controllers
│ │ └── login.controller.spec.js
├── 05-expect-should
│ ├── .gitignore
│ ├── controllers
│ │ └── login.controller.js
│ ├── package.json
│ └── test
│ │ └── controllers
│ │ └── login.controller.spec.js
├── 06-promise
│ ├── .gitignore
│ ├── controllers
│ │ └── login.controller.js
│ ├── package.json
│ └── test
│ │ └── controllers
│ │ └── login.controller.spec.js
├── 07-chai-assertion
│ ├── .gitignore
│ ├── package.json
│ └── test
│ │ └── test.js
└── README.md
├── js-unit-test-examples
├── .gitignore
├── LICENSE
├── README.md
├── ava-nyc
│ ├── package.json
│ ├── src
│ │ └── index.js
│ └── test
│ │ └── MathLib
│ │ ├── add.test.js
│ │ ├── fibonacci.test.js
│ │ └── multiply.test.js
├── ava
│ ├── package.json
│ ├── src
│ │ └── index.js
│ └── test
│ │ └── MathLib
│ │ ├── add.test.js
│ │ ├── fibonacci.test.js
│ │ └── multiply.test.js
├── jasmine-chutzpah
│ ├── Program.cs
│ ├── chutzpah.json
│ ├── jasmine-chutzpah.csproj
│ ├── jasmine-chutzpah.sln
│ ├── spec
│ │ └── index.spec.js
│ └── src
│ │ └── index.js
├── jasmine
│ ├── package.json
│ ├── spec
│ │ ├── index.spec.js
│ │ └── support
│ │ │ └── jasmine.json
│ └── src
│ │ └── index.js
├── jest
│ ├── package.json
│ ├── src
│ │ └── index.js
│ └── test
│ │ └── index.test.js
├── mocha-chai-istanbul
│ ├── package.json
│ ├── src
│ │ └── index.js
│ └── test
│ │ └── index.test.js
├── mocha-chai-ts-istanbul
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ └── test
│ │ └── index.test.ts
├── mocha-chai-ts
│ ├── package.json
│ ├── src
│ │ └── index.ts
│ └── test
│ │ └── index.test.ts
├── mocha-chai
│ ├── package.json
│ ├── src
│ │ └── index.js
│ └── test
│ │ └── index.test.js
└── tap-nyc
│ ├── package.json
│ ├── src
│ └── index.js
│ └── test
│ └── MathLib
│ ├── add.spec.js
│ ├── fibonacci.spec.js
│ └── multiply.spec.js
└── js-unit-testing-examples
├── .babelrc
├── .editorconfig
├── .eslintrc.json
├── .gitignore
├── .vscode
└── settings.json
├── LICENSE
├── README.md
├── index.js
├── package.json
├── src
├── data
│ └── fakeData.js
├── launch.js
├── middleware
│ ├── api
│ │ └── eventsGetAll.js
│ ├── authenticate.js
│ ├── dashboard.js
│ ├── homepage.js
│ ├── login.js
│ └── promiseTest.js
├── routes
│ └── api.js
└── services
│ └── events.js
└── test
├── examples
└── asynchronous.test.js
├── mocha.opts
├── src
├── launch.test.js
└── middleware
│ ├── api
│ └── dataGetAll.test.js
│ ├── promiseTest.test.js
│ └── services
│ └── events.test.js
└── support
└── base.js
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Packt
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Mocha-Unit-Testing-Example/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/Mocha-Unit-Testing-Example/README.md:
--------------------------------------------------------------------------------
1 | ## Getting Started with JavaScript Unit Testing Using Mocha
2 |
3 | Code to accompany the following article: http://www.sitepoint.com/unit-test-javascript-mocha-chai
4 |
5 | To run the code samples:
6 |
7 | - Clone the repo
8 | - Run `npm install`
9 | - Open `testrunner.html` in browser
10 | - Alternatively, uncomment Node specific code and run `mocha` from the command line (this requires Mocha to be installed globally).
11 |
12 | License MIT
13 |
--------------------------------------------------------------------------------
/Mocha-Unit-Testing-Example/js/className.js:
--------------------------------------------------------------------------------
1 | // Browser version
2 | function addClass(el, newClass) {
3 | if(el.className.indexOf(newClass) !== -1) {
4 | return;
5 | }
6 |
7 | if(el.className !== '') {
8 | //ensure class names are separated by a space
9 | newClass = ' ' + newClass;
10 | }
11 |
12 | el.className += newClass;
13 | }
14 |
15 | // Node Version
16 | // module.exports = {
17 | // addClass: function(el, newClass) {
18 | // if(el.className.indexOf(newClass) !== -1) {
19 | // return;
20 | // }
21 |
22 | // if(el.className !== '') {
23 | // //ensure class names are separated by a space
24 | // newClass = ' ' + newClass;
25 | // }
26 |
27 | // el.className += newClass;
28 | // }
29 | // }
30 |
--------------------------------------------------------------------------------
/Mocha-Unit-Testing-Example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mocha-unit-testing",
3 | "version": "1.0.0",
4 | "description": "Mocha Tests",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "mocha"
8 | },
9 | "author": "Jani Hartikainen",
10 | "license": "MIT",
11 | "devDependencies": {
12 | "chai": "^3.4.1",
13 | "mocha": "^2.3.4"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Mocha-Unit-Testing-Example/test/arrayTest.js:
--------------------------------------------------------------------------------
1 | // Uncomment if using Node
2 | // var chai = require('chai');
3 | var assert = chai.assert;
4 |
5 | describe('Array', function() {
6 | it('should start empty', function() {
7 | var arr = [];
8 |
9 | assert.equal(arr.length, 0);
10 | });
11 | });
12 |
--------------------------------------------------------------------------------
/Mocha-Unit-Testing-Example/test/classNameTest.js:
--------------------------------------------------------------------------------
1 | // Uncomment if using Node
2 | // var chai = require('chai');
3 | var assert = chai.assert;
4 |
5 | // var className = require('../js/className.js');
6 | // var addClass = className.addClass;
7 |
8 | describe('addClass', function() {
9 | it('should add class into element', function() {
10 | var element = { className: '' };
11 |
12 | addClass(element, 'test-class');
13 |
14 | assert.equal(element.className, 'test-class');
15 | });
16 |
17 | it('should not add a class which already exists in element', function() {
18 | var element = { className: 'exists' };
19 |
20 | addClass(element, 'exists');
21 |
22 | var numClasses = element.className.split(' ').length;
23 | assert.equal(numClasses, 1);
24 | });
25 |
26 | it('should append new class after existing one', function() {
27 | var element = { className: 'exists' };
28 |
29 | addClass(element, 'new-class');
30 |
31 | var classes = element.className.split(' ');
32 | assert.equal(classes[1], 'new-class');
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/Mocha-Unit-Testing-Example/testrunner.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Mocha Tests
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JavaScript Unit Testing
2 |
3 | > *Click ★ if you like the project. Your contributions are heartily ♡ welcome.*
4 |
5 |
6 |
7 | **Unit = Unit of work**
8 |
9 | This could involve **multiple methods and classes** invoked by some public API that can:
10 |
11 | + Return a value or throw an exception
12 | + Change the state of the system
13 | + Make 3rd party calls (API, database, ...)
14 |
15 | A unit test should test the behaviour of a unit of work: for a given input, it expects an end result that can be any of the above.
16 |
17 | **Unit tests are isolated and independent of each other**
18 |
19 | + Any given behaviour should be specified in **one and only one test**
20 | + The execution/order of execution of one test **cannot affect the others**
21 |
22 | The code is designed to support this independence (see "Design principles" below).
23 |
24 | **Unit tests are lightweight tests**
25 |
26 | + Repeatable
27 | + Fast
28 | + Consistent
29 | + Easy to write and read
30 |
31 | **Unit tests are code too**
32 |
33 | They should meet the same level of quality as the code being tested. They can be refactored as well to make them more maintainable and/or readable.
34 |
35 |
36 |
37 | ### Design principles
38 |
39 | The key to good unit testing is to write **testable code**. Applying simple design principles can help, in particular:
40 |
41 | + Use a **good naming** convention and **comment** your code (the "why?" not the "how"), keep in mind that comments are not a substitute for bad naming or bad design
42 | + **DRY**: Don't Repeat Yourself, avoid code duplication
43 | + **Single responsibility**: each object/function must focus on a single task
44 | + Keep a **single level of abstraction** in the same component (for example, do not mix business logic with lower-level technical details in the same method)
45 | + **Minimize dependencies** between components: encapsulate, interchange less information between components
46 | + **Support configurability** rather than hard-coding, this prevents having to replicate the exact same environment when testing (e.g.: markup)
47 | + Apply adequate **design patterns**, especially **dependency injection** that allows separating an object's creation responsibility from business logic
48 | + Avoid global mutable state
49 |
50 |
53 |
54 | ## Guidelines
55 |
56 | The goal of these guidelines is to make your tests:
57 |
58 | + **Readable**
59 | + **Maintainable**
60 | + **Trustworthy**
61 |
62 | These are the 3 pillars of good unit testing.
63 |
64 | All the following examples assume the usage of the [Jasmine](http://jasmine.github.io) framework.
65 |
66 |
67 | ### Whenever possible, use TDD
68 |
69 | TDD is a _design process_, not a testing process. TDD is a robust way of designing software components ("units") interactively so that their behaviour is specified through unit tests.
70 |
71 | How? Why?
72 |
73 | #### Test-first cycle
74 |
75 | 1. Write a simple failing test
76 | 2. Make the test pass by writing the minimum amount of code, don't bother with code quality
77 | 3. Refactor the code by applying design principles/patterns
78 |
79 | #### Consequences of the test-first cycle
80 |
81 | + Writing a test first makes the code design testable de facto
82 | + Writing just the amount of code needed to implement the required functionality makes the resulting codebase minimal, thus more maintainable
83 | + The codebase can be enhanced using refactoring mechanisms, the tests give you confidence that the new code is not modifying the existing functionalities
84 | + Cleaning the code in each cycle makes the codebase more maintainable, it is much cheaper to change the code frequently and in small increments
85 | + Fast feedback for the developers, you know that you don't break anything and that you are evolving the system in a good direction
86 | + Generates confidence to add features, fix bugs, or explore new designs
87 |
88 | Note that code written without a test-first approach is often very hard to test.
89 |
90 |
93 |
94 | ### Structure your tests properly
95 |
96 | Don't hesitate to nest your suites to structure logically your tests in subsets.
97 |
98 | **:(**
99 |
100 | ```js
101 | describe('A set of functionalities', () => {
102 | it('a set of functionalities should do something nice', () => {
103 | });
104 |
105 | it('a subset of functionalities should do something great', () => {
106 | });
107 |
108 | it('a subset of functionalities should do something awesome', () => {
109 | });
110 |
111 | it('another subset of functionalities should also do something great', () => {
112 | });
113 | });
114 | ```
115 |
116 | **:)**
117 |
118 | ```js
119 | describe('A set of functionalities', () => {
120 | it('should do something nice', () => {
121 | });
122 |
123 | describe('A subset of functionalities', () => {
124 | it('should do something great', () => {
125 | });
126 |
127 | it('should do something awesome', () => {
128 | });
129 | });
130 |
131 | describe('Another subset of functionalities', () => {
132 | it('should also do something great', () => {
133 | });
134 | });
135 | });
136 | ```
137 |
138 |
141 |
142 | ### Name your tests properly
143 |
144 | Tests names should be concise, explicit, descriptive and in correct English. Read the output of the spec runner and verify that it is understandable! Keep in mind that someone else will read it too. Tests can be the live documentation of the code.
145 |
146 | **:(**
147 |
148 | ```js
149 | describe('MyGallery', () => {
150 | it('init set correct property when called (thumb size, thumbs count)', () => {
151 | });
152 |
153 | // ...
154 | });
155 | ```
156 |
157 | **:)**
158 |
159 | ```js
160 | describe('The Gallery instance', () => {
161 | it('should properly calculate the thumb size when initialized', () => {
162 | });
163 |
164 | it('should properly calculate the thumbs count when initialized', () => {
165 | });
166 |
167 | // ...
168 | });
169 | ```
170 |
171 | In order to help you write test names properly, you can use the **"unit of work - scenario/context - expected behaviour"** pattern:
172 |
173 | ```js
174 | describe('[unit of work]', () => {
175 | it('should [expected behaviour] when [scenario/context]', () => {
176 | });
177 | });
178 | ```
179 |
180 | Or whenever you have many tests that follow the same scenario or are related to the same context:
181 |
182 | ```js
183 | describe('[unit of work]', () => {
184 | describe('when [scenario/context]', () => {
185 | it('should [expected behaviour]', () => {
186 | });
187 | });
188 | });
189 | ```
190 |
191 | For example:
192 |
193 | **:) :)**
194 |
195 | ```js
196 | describe('The Gallery instance', () => {
197 | describe('when initialized', () => {
198 | it('should properly calculate the thumb size', () => {
199 | });
200 |
201 | it('should properly calculate the thumbs count', () => {
202 | });
203 | });
204 |
205 | // ...
206 | });
207 | ```
208 |
209 |
212 |
213 | ### Don't comment out tests
214 |
215 | Never. Ever. Tests have a reason to be or not.
216 |
217 | Don't comment them out because they are too slow, too complex or produce false negatives. Instead, make them fast, simple and trustworthy. If not, remove them completely.
218 |
219 |
220 |
221 | ### Avoid logic in your tests
222 |
223 | Always use simple statements. Don't use loops and/or conditionals. If you do, you add a possible entry point for bugs in the test itself:
224 |
225 | + Conditionals: you don't know which path the test will take
226 | + Loops: you could be sharing state between tests
227 |
228 | **:(**
229 |
230 | ```js
231 | it('should properly sanitize strings', () => {
232 | let result;
233 | const testValues = {
234 | 'Avion' : 'Avi' + String.fromCharCode(243) + 'n',
235 | 'The-space' : 'The space',
236 | 'Weird-chars-' : 'Weird chars!!',
237 | 'file-name.zip' : 'file name.zip',
238 | 'my-name.zip' : 'my.name.zip'
239 | };
240 |
241 | for (result in testValues) {
242 | expect(sanitizeString(testValues[result])).toBe(result);
243 | }
244 | });
245 | ```
246 |
247 | **:)**
248 |
249 | ```js
250 | it('should properly sanitize strings', () => {
251 | expect(sanitizeString('Avi'+String.fromCharCode(243)+'n')).toBe('Avion');
252 | expect(sanitizeString('The space')).toBe('The-space');
253 | expect(sanitizeString('Weird chars!!')).toBe('Weird-chars-');
254 | expect(sanitizeString('file name.zip')).toBe('file-name.zip');
255 | expect(sanitizeString('my.name.zip')).toBe('my-name.zip');
256 | });
257 | ```
258 |
259 | Better: write a test for each type of sanitization. It will give a nice output of all possible cases, improving maintainability.
260 |
261 | **:) :)**
262 |
263 | ```js
264 | it('should sanitize a string containing non-ASCII chars', () => {
265 | expect(sanitizeString('Avi'+String.fromCharCode(243)+'n')).toBe('Avion');
266 | });
267 |
268 | it('should sanitize a string containing spaces', () => {
269 | expect(sanitizeString('The space')).toBe('The-space');
270 | });
271 |
272 | it('should sanitize a string containing exclamation signs', () => {
273 | expect(sanitizeString('Weird chars!!')).toBe('Weird-chars-');
274 | });
275 |
276 | it('should sanitize a filename containing spaces', () => {
277 | expect(sanitizeString('file name.zip')).toBe('file-name.zip');
278 | });
279 |
280 | it('should sanitize a filename containing more than one dot', () => {
281 | expect(sanitizeString('my.name.zip')).toBe('my-name.zip');
282 | });
283 | ```
284 |
287 |
288 | ### Don't write unnecessary expectations
289 |
290 | Remember, unit tests are a design specification of how a certain *behaviour* should work, not a list of observations of everything the code happens to do.
291 |
292 | **:(**
293 |
294 | ```js
295 | it('should multiply the number passed as parameter and subtract one', () => {
296 | const multiplySpy = spyOn(Calculator, 'multiple').and.callThrough();
297 | const subtractSpy = spyOn(Calculator, 'subtract').and.callThrough();
298 |
299 | const result = Calculator.compute(21.5);
300 |
301 | expect(multiplySpy).toHaveBeenCalledWith(21.5, 2);
302 | expect(subtractSpy).toHaveBeenCalledWith(43, 1);
303 | expect(result).toBe(42);
304 | });
305 | ```
306 |
307 | **:)**
308 |
309 | ```js
310 | it('should multiply the number passed as parameter and subtract one', () => {
311 | const result = Calculator.compute(21.5);
312 | expect(result).toBe(42);
313 | });
314 | ```
315 |
316 | This will improve maintainability. Your test is no longer tied to implementation details.
317 |
318 |
321 |
322 | ### Properly setup the actions that apply to all the tests involved
323 |
324 | **:(**
325 |
326 | ```js
327 | describe('Saving the user profile', () => {
328 | let profileModule;
329 | let notifyUserSpy;
330 | let onCompleteSpy;
331 |
332 | beforeEach(() => {
333 | profileModule = new ProfileModule();
334 | notifyUserSpy = spyOn(profileModule, 'notifyUser');
335 | onCompleteSpy = jasmine.createSpy();
336 | });
337 |
338 | it('should send the updated profile data to the server', () => {
339 | jasmine.Ajax.install();
340 |
341 | profileModule.save();
342 |
343 | const request = jasmine.Ajax.requests.mostRecent();
344 |
345 | expect(request.url).toBe('/profiles/1');
346 | expect(request.method).toBe('POST');
347 | expect(request.data()).toEqual({ username: 'mawrkus' });
348 |
349 | jasmine.Ajax.uninstall();
350 | });
351 |
352 | it('should notify the user', () => {
353 | jasmine.Ajax.install();
354 |
355 | profileModule.save();
356 |
357 | expect(notifyUserSpy).toHaveBeenCalled();
358 |
359 | jasmine.Ajax.uninstall();
360 | });
361 |
362 | it('should properly execute the callback passed as parameter', () => {
363 | jasmine.Ajax.install();
364 |
365 | profileModule.save(onCompleteSpy);
366 |
367 | jasmine.Ajax.uninstall();
368 |
369 | expect(onCompleteSpy).toHaveBeenCalled();
370 | });
371 | });
372 | ```
373 |
374 | The setup code should apply to all the tests:
375 |
376 | **:)**
377 |
378 | ```js
379 | describe('Saving the user profile', () => {
380 | let profileModule;
381 |
382 | beforeEach(() => {
383 | jasmine.Ajax.install();
384 | profileModule = new ProfileModule();
385 | });
386 |
387 | afterEach( () => {
388 | jasmine.Ajax.uninstall();
389 | });
390 |
391 | it('should send the updated profile data to the server', () => {
392 | profileModule.save();
393 |
394 | const request = jasmine.Ajax.requests.mostRecent();
395 |
396 | expect(request.url).toBe('/profiles/1');
397 | expect(request.method).toBe('POST');
398 |
399 | });
400 |
401 | it('should notify the user', () => {
402 | spyOn(profileModule, 'notifyUser');
403 |
404 | profileModule.save();
405 |
406 | expect(profileModule.notifyUser).toHaveBeenCalled();
407 | });
408 |
409 | it('should properly execute the callback passed as parameter', () => {
410 | const onCompleteSpy = jasmine.createSpy();
411 |
412 | profileModule.save(onCompleteSpy);
413 |
414 | expect(onCompleteSpy).toHaveBeenCalled();
415 | });
416 | });
417 | ```
418 |
419 | Consider keeping the setup code minimal to preserve readability and maintainability.
420 |
421 |
424 |
425 | ### Consider using factory functions in the tests
426 |
427 | Factories can:
428 |
429 | + help reduce the setup code, especially if you use dependency injection
430 | + make each test more readable, since the creation is a single function call that can be in the test itself instead of the setup
431 | + provide flexibility when creating new instances (setting an initial state, for example)
432 |
433 | There's a trade-off to find here between applying the DRY principle and readability.
434 |
435 | **:(**
436 |
437 | ```js
438 | describe('User profile module', () => {
439 | let profileModule;
440 | let pubSub;
441 |
442 | beforeEach(() => {
443 | const element = document.getElementById('my-profile');
444 | pubSub = new PubSub({ sync: true });
445 |
446 | profileModule = new ProfileModule({
447 | element,
448 | pubSub,
449 | likes: 0
450 | });
451 | });
452 |
453 | it('should publish a topic when a new "like" is given', () => {
454 | spyOn(pubSub, 'notify');
455 | profileModule.incLikes();
456 | expect(pubSub.notify).toHaveBeenCalledWith('likes:inc', { count: 1 });
457 | });
458 |
459 | it('should retrieve the correct number of likes', () => {
460 | profileModule.incLikes();
461 | profileModule.incLikes();
462 | expect(profileModule.getLikes()).toBe(2);
463 | });
464 | });
465 | ```
466 |
467 | **:)**
468 |
469 | ```js
470 | describe('User profile module', () => {
471 | function createProfileModule({
472 | element = document.getElementById('my-profile'),
473 | likes = 0,
474 | pubSub = new PubSub({ sync: true })
475 | }) {
476 | return new ProfileModule({ element, likes, pubSub });
477 | }
478 |
479 | it('should publish a topic when a new "like" is given', () => {
480 | const pubSub = jasmine.createSpyObj('pubSub', ['notify']);
481 | const profileModule = createProfileModule({ pubSub });
482 |
483 | profileModule.incLikes();
484 |
485 | expect(pubSub.notify).toHaveBeenCalledWith('likes:inc');
486 | });
487 |
488 | it('should retrieve the correct number of likes', () => {
489 | const profileModule = createProfileModule({ likes: 40 });
490 |
491 | profileModule.incLikes();
492 | profileModule.incLikes();
493 |
494 | expect(profileModule.getLikes()).toBe(42);
495 | });
496 | });
497 | ```
498 |
499 | Factories are particularly useful when dealing with the DOM:
500 |
501 | **:(**
502 |
503 | ```js
504 | describe('The search component', () => {
505 | describe('when the search button is clicked', () => {
506 | let container;
507 | let form;
508 | let searchInput;
509 | let submitInput;
510 |
511 | beforeEach(() => {
512 | fixtures.inject(`
513 |
517 |
`);
518 |
519 | container = document.getElementById('container');
520 | form = container.getElementsByClassName('js-form')[0];
521 | searchInput = form.querySelector('input[type=search]');
522 | submitInput = form.querySelector('input[type=submith]');
523 | });
524 |
525 | it('should validate the text entered', () => {
526 | const search = new Search({ container });
527 | spyOn(search, 'validate');
528 |
529 | search.init();
530 |
531 | input(searchInput, 'peace');
532 | click(submitInput);
533 |
534 | expect(search.validate).toHaveBeenCalledWith('peace');
535 | });
536 |
537 | // ...
538 | });
539 | });
540 | ```
541 |
542 | **:)**
543 |
544 | ```js
545 | function createHTMLFixture() {
546 | fixtures.inject(`
547 |
551 |
`);
552 |
553 | const container = document.getElementById('container');
554 | const form = container.getElementsByClassName('js-form')[0];
555 | const searchInput = form.querySelector('input[type=search]');
556 | const submitInput = form.querySelector('input[type=submith]');
557 |
558 | return {
559 | container,
560 | form,
561 | searchInput,
562 | submitInput
563 | };
564 | }
565 |
566 | describe('The search component', () => {
567 | describe('when the search button is clicked', () => {
568 | it('should validate the text entered', () => {
569 | const { container, form, searchInput, submitInput } = createHTMLFixture();
570 | const search = new Search({ container });
571 | spyOn(search, 'validate');
572 |
573 | search.init();
574 |
575 | input(searchInput, 'peace');
576 | click(submitInput);
577 |
578 | expect(search.validate).toHaveBeenCalledWith('peace');
579 | });
580 |
581 | // ...
582 | });
583 | });
584 | ```
585 |
588 |
589 | ### Know your testing framework API
590 |
591 | The API documentation of the testing framework/library should be your bedside book!
592 |
593 | Having a good knowledge of the API can help you in reducing the size/complexity of your test code and, in general, help you during development. A simple example:
594 |
595 | **:(**
596 |
597 | ```js
598 | it('should call a method with the proper arguments', () => {
599 | const foo = {
600 | bar: jasmine.createSpy(),
601 | baz: jasmine.createSpy()
602 | };
603 |
604 | foo.bar('qux');
605 |
606 | expect(foo.bar).toHaveBeenCalled();
607 | expect(foo.bar.calls.argsFor(0)).toEqual(['qux']);
608 | });
609 |
610 | /*it('should do more but not now', () => {
611 | });
612 |
613 | it('should do much more but not now', () => {
614 | });*/
615 | ```
616 |
617 | **:)**
618 |
619 | ```js
620 | fit('should call once a method with the proper arguments', () => {
621 | const foo = jasmine.createSpyObj('foo', ['bar', 'baz']);
622 |
623 | foo.bar('baz');
624 |
625 | expect(foo.bar).toHaveBeenCalledWith('baz');
626 | });
627 |
628 | it('should do something else but not now', () => {
629 | });
630 |
631 | it('should do something else but not now', () => {
632 | });
633 | ```
634 |
637 |
638 | #### Note
639 |
640 | The handy `fit` function used in the example above allows you to execute only one test without having to comment out all the tests below. `fdescribe` does the same for test suites. This could help save a lot of time when developing.
641 |
642 | More information on the [Jasmine website](http://jasmine.github.io).
643 |
644 |
645 |
646 | ### Don't test multiple concerns in the same test
647 |
648 | If a method has several end results, each one should be tested separately. Whenever a bug occurs, it will help you locate the source of the problem.
649 |
650 | **:(**
651 |
652 | ```js
653 | it('should send the profile data to the server and update the profile view properly', () => {
654 | // expect(...)to(...);
655 | // expect(...)to(...);
656 | });
657 | ```
658 |
659 | **:)**
660 |
661 | ```js
662 | it('should send the profile data to the server', () => {
663 | // expect(...)to(...);
664 | });
665 |
666 | it('should update the profile view properly', () => {
667 | // expect(...)to(...);
668 | });
669 | ```
670 |
671 | Beware that writing "AND" or "OR" when naming your test smells bad...
672 |
673 |
676 |
677 | ### Cover the general case and the edge cases
678 |
679 | "Strange behaviour" usually happens at the edges... Remember that your tests can be the live documentation of your code.
680 |
681 | **:(**
682 |
683 | ```js
684 | it('should properly calculate a RPN expression', () => {
685 | const result = RPN('5 1 2 + 4 * - 10 /');
686 | expect(result).toBe(-0.7);
687 | });
688 | ```
689 |
690 | **:)**
691 |
692 | ```js
693 | describe('The RPN expression evaluator', () => {
694 | it('should return null when the expression is an empty string', () => {
695 | const result = RPN('');
696 | expect(result).toBeNull();
697 | });
698 |
699 | it('should return the same value when the expression holds a single value', () => {
700 | const result = RPN('42');
701 | expect(result).toBe(42);
702 | });
703 |
704 | it('should properly calculate an expression', () => {
705 | const result = RPN('5 1 2 + 4 * - 10 /');
706 | expect(result).toBe(-0.7);
707 | });
708 |
709 | it('should throw an error whenever an invalid expression is passed', () => {
710 | const compute = () => RPN('1 + - 1');
711 | expect(compute).toThrow();
712 | });
713 | });
714 | ```
715 |
716 |
719 |
720 | ### When applying TDD, always start by writing the simplest failing test
721 |
722 | **:(**
723 |
724 | ```js
725 | it('should suppress all chars that appear multiple times', () => {
726 | expect(keepUniqueChars('Hello Fostonic !!')).toBe('HeFstnic');
727 | });
728 | ```
729 |
730 | **:)**
731 |
732 | ```js
733 | it('should return an empty string when passed an empty string', () => {
734 | expect(keepUniqueChars('')).toBe('');
735 | });
736 | ```
737 |
738 | From there, start building the functionalities incrementally.
739 |
740 |
741 |
742 | ### When applying TDD, always make small steps in each test-first cycle
743 |
744 | Build your tests suite from the simple case to the more complex ones. Keep in mind the incremental design. Deliver software fast, incrementally, and in short iterations.
745 |
746 | **:(**
747 |
748 | ```js
749 | it('should return null when the expression is an empty string', () => {
750 | const result = RPN('');
751 | expect(result).toBeNull();
752 | });
753 |
754 | it('should properly calculate a RPN expression', () => {
755 | const result = RPN('5 1 2 + 4 * - 10 /');
756 | expect(result).toBe(-0.7);
757 | });
758 | ```
759 |
760 | **:)**
761 |
762 | ```js
763 | describe('The RPN expression evaluator', () => {
764 | it('should return null when the expression is an empty string', () => {
765 | const result = RPN('');
766 | expect(result).toBeNull();
767 | });
768 |
769 | it('should return the same value when the expression holds a single value', () => {
770 | const result = RPN('42');
771 | expect(result).toBe(42);
772 | });
773 |
774 | describe('Additions-only expressions', () => {
775 | it('should properly calculate a simple addition', () => {
776 | const result = RPN('41 1 +');
777 | expect(result).toBe(42);
778 | });
779 |
780 | it('should properly calculate a complex addition', () => {
781 | const result = RPN('2 9 + 15 3 + + 7 6 + +');
782 | expect(result).toBe(42);
783 | });
784 | });
785 |
786 | // ...
787 |
788 | describe('Complex expressions', () => {
789 | it('should properly calculate an expression containing all 4 operators', () => {
790 | const result = RPN('5 1 2 + 4 * - 10 /');
791 | expect(result).toBe(-0.7);
792 | });
793 | });
794 | });
795 | ```
796 |
799 |
800 | ### Test the behaviour, not the internal implementation
801 |
802 | **:(**
803 |
804 | ```js
805 | it('should add a user in memory', () => {
806 | userManager.addUser('Dr. Falker', 'Joshua');
807 |
808 | expect(userManager._users[0].name).toBe('Dr. Falker');
809 | expect(userManager._users[0].password).toBe('Joshua');
810 | });
811 | ```
812 |
813 | A better approach is to test at the same level of the API:
814 |
815 | **:)**
816 |
817 | ```js
818 | it('should add a user in memory', () => {
819 | userManager.addUser('Dr. Falker', 'Joshua');
820 |
821 | expect(userManager.loginUser('Dr. Falker', 'Joshua')).toBe(true);
822 | });
823 | ```
824 |
825 | Pro:
826 |
827 | + Changing the internal implementation of a class/object will not necessarily force you to refactor the tests
828 |
829 | Con:
830 |
831 | + If a test is failing, we might have to debug to know which part of the code needs to be fixed
832 |
833 | Here, a balance has to be found, unit-testing some key parts can be beneficial.
834 |
835 |
838 |
839 | ### Don't mock everything
840 |
841 | **:(**
842 |
843 | ```js
844 | describe('when the user has already visited the page', () => {
845 | // storage.getItem('page-visited', '1') === '1'
846 | describe('when the survey is not disabled', () => {
847 | // storage.getItem('survey-disabled') === null
848 | it('should display the survey', () => {
849 | const storage = jasmine.createSpyObj('storage', ['setItem', 'getItem']);
850 | storage.getItem.and.returnValue('1'); // ouch.
851 |
852 | const surveyManager = new SurveyManager(storage);
853 | spyOn(surveyManager, 'display');
854 |
855 | surveyManager.start();
856 |
857 | expect(surveyManager.display).toHaveBeenCalled();
858 | });
859 | });
860 |
861 | // ...
862 | });
863 | ```
864 |
865 | This test fails, because the survey is considered disabled. Let's fix this:
866 |
867 | **:)**
868 |
869 | ```js
870 | describe('when the user has already visited the page', () => {
871 | // storage.getItem('page-visited', '1') === '1'
872 | describe('when the survey is not disabled', () => {
873 | // storage.getItem('survey-disabled') === null
874 | it('should display the survey', () => {
875 | const storage = jasmine.createSpyObj('storage', ['setItem', 'getItem']);
876 | storage.getItem.and.callFake(key => {
877 | switch (key) {
878 | case 'page-visited':
879 | return '1';
880 |
881 | case 'survey-disabled':
882 | return null;
883 | }
884 |
885 | return null;
886 | }); // ouch.
887 |
888 | const surveyManager = new SurveyManager(storage);
889 | spyOn(surveyManager, 'display');
890 |
891 | surveyManager.start();
892 |
893 | expect(surveyManager.display).toHaveBeenCalled();
894 | });
895 | });
896 |
897 | // ...
898 | });
899 | ```
900 |
901 | This will work... but needs a lot of code. Let's try a simpler approach:
902 |
903 | **:(**
904 |
905 | ```js
906 | describe('when the user has already visited the page', () => {
907 | // storage.getItem('page-visited', '1') === '1'
908 | describe('when the survey is not disabled', () => {
909 | // storage.getItem('survey-disabled') === null
910 | it('should display the survey', () => {
911 | const storage = window.localStorage; // ouch.
912 | storage.setItem('page-visited', '1');
913 |
914 | const surveyManager = new SurveyManager();
915 | spyOn(surveyManager, 'display');
916 |
917 | surveyManager.start();
918 |
919 | expect(surveyManager.display).toHaveBeenCalled();
920 | });
921 | });
922 |
923 | // ...
924 | });
925 | ```
926 |
927 | We created a permanent storage of data. What happens if we do not properly clean it?
928 | We might affect the other tests. Let's fix this:
929 |
930 | **:) :)**
931 |
932 | ```js
933 | describe('when the user has already visited the page', () => {
934 | // storage.getItem('page-visited', '1') === '1'
935 | describe('when the survey is not disabled', () => {
936 | // storage.getItem('survey-disabled') === null
937 | it('should display the survey', () => {
938 | const storage = new MemoryStorage(); // see https://github.com/tatsuyaoiw/webstorage
939 | storage.setItem('page-visited', '1');
940 |
941 | const surveyManager = new SurveyManager(storage);
942 | spyOn(surveyManager, 'display');
943 |
944 | surveyManager.start();
945 |
946 | expect(surveyManager.display).toHaveBeenCalled();
947 | });
948 | });
949 | });
950 | ```
951 |
952 | The `MemoryStorage` used here does not persist data. Nice and easy, with no side effects.
953 |
954 |
957 |
958 | #### Takeaway
959 |
960 | The idea to keep in mind is that *dependencies can still be "real" objects*. Don't mock everything because you can.
961 | In particular, consider using the "real" version of the objects if:
962 |
963 | + it leads to a simple, nice and easy tests setup
964 | + it does not create a shared state between the tests, causing unexpected side effects
965 | + the code being tested does not make AJAX requests, API calls or browser page reloads
966 | + the speed of execution of the tests stays *within the limits you fixed*
967 |
968 |
969 |
970 | ### Create new tests for every defect
971 |
972 | Whenever a bug is found, create a test that replicates the problem **before touching any code**. From there, you can apply TDD as usual to fix it.
973 |
974 |
975 |
976 | ### Don't write unit tests for complex user interactions
977 |
978 | Examples of complex user interactions:
979 |
980 | + Filling a form, drag and dropping some items then submitting the form
981 | + Clicking a tab, clicking an image thumbnail then navigating through a gallery of images previously loaded from a database
982 | + (...)
983 |
984 | These interactions might involve many units of work and should be handled at a higher level by **functional tests**. They will take more time to execute. They could be flaky (false negatives) and they need debugging whenever a failure is reported.
985 |
986 | For functional testing, consider using a test automation framework ([Selenium](http://docs.seleniumhq.org/), ...) or QA manual testing.
987 |
988 |
991 |
992 | ### Test simple user actions
993 |
994 | Example of simple user actions:
995 |
996 | + Clicking on a link that toggles the visibility of a DOM element
997 | + Submitting a form that triggers the form validation
998 | + (...)
999 |
1000 | These actions can be easily tested **by simulating DOM events**, for example:
1001 |
1002 | ```js
1003 | describe('clicking on the "Preview profile" link', () => {
1004 | it('should show the profile preview if it is hidden', () => {
1005 | const previewLink = document.createElement('a');
1006 | const profileModule = createProfileModule({ previewLink, previewIsVisible: false });
1007 |
1008 | spyOn(profileModule, 'showPreview');
1009 |
1010 | click(previewLink);
1011 |
1012 | expect(profileModule.showPreview).toHaveBeenCalled();
1013 | });
1014 |
1015 | it('should hide the profile preview if it is displayed', () => {
1016 | const previewLink = document.createElement('a');
1017 | const profileModule = createProfileModule({ previewLink, previewIsVisible: true });
1018 |
1019 | spyOn(profileModule, 'hidePreview');
1020 |
1021 | click(previewLink);
1022 |
1023 | expect(profileModule.hidePreview).toHaveBeenCalled();
1024 | });
1025 | });
1026 | ```
1027 |
1028 | Note how simple the test is because the UI (DOM) layer does not mix with the business logic layer:
1029 |
1030 | + a "click" event occurs
1031 | + a public method is called
1032 |
1033 | The next step could be to test the business logic implemented in "showPreview()" or "hidePreview()".
1034 |
1035 | ### Libraries
1036 |
1037 | + Jasmine: https://jasmine.github.io/
1038 | + Jest: https://jestjs.io/
1039 | + Mocha: https://mochajs.org/
1040 | + Tape: https://github.com/substack/tape
1041 |
1042 |
1045 |
--------------------------------------------------------------------------------
/Section-1/1.3/01-Writing-your-first-unit-test/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/learning-zone/javascript-unit-testing/2bce97478b1231a70d5ef1a572bf43b7078dfd83/Section-1/1.3/01-Writing-your-first-unit-test/.DS_Store
--------------------------------------------------------------------------------
/Section-1/1.3/01-Writing-your-first-unit-test/after/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io/api/node,test,macos
2 |
3 | ### macOS ###
4 | # General
5 | .DS_Store
6 | .AppleDouble
7 | .LSOverride
8 |
9 | # Icon must end with two \r
10 | Icon
11 |
12 | # Thumbnails
13 | ._*
14 |
15 | # Files that might appear in the root of a volume
16 | .DocumentRevisions-V100
17 | .fseventsd
18 | .Spotlight-V100
19 | .TemporaryItems
20 | .Trashes
21 | .VolumeIcon.icns
22 | .com.apple.timemachine.donotpresent
23 |
24 | # Directories potentially created on remote AFP share
25 | .AppleDB
26 | .AppleDesktop
27 | Network Trash Folder
28 | Temporary Items
29 | .apdisk
30 |
31 | ### Node ###
32 | # Logs
33 | logs
34 | *.log
35 | npm-debug.log*
36 | yarn-debug.log*
37 | yarn-error.log*
38 |
39 | # Runtime data
40 | pids
41 | *.pid
42 | *.seed
43 | *.pid.lock
44 |
45 | # Directory for instrumented libs generated by jscoverage/JSCover
46 | lib-cov
47 |
48 | # Coverage directory used by tools like istanbul
49 | coverage
50 |
51 | # nyc test coverage
52 | .nyc_output
53 |
54 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
55 | .grunt
56 |
57 | # Bower dependency directory (https://bower.io/)
58 | bower_components
59 |
60 | # node-waf configuration
61 | .lock-wscript
62 |
63 | # Compiled binary addons (https://nodejs.org/api/addons.html)
64 | build/Release
65 |
66 | # Dependency directories
67 | node_modules/
68 | jspm_packages/
69 |
70 | # TypeScript v1 declaration files
71 | typings/
72 |
73 | # Optional npm cache directory
74 | .npm
75 |
76 | # Optional eslint cache
77 | .eslintcache
78 |
79 | # Optional REPL history
80 | .node_repl_history
81 |
82 | # Output of 'npm pack'
83 | *.tgz
84 |
85 | # Yarn Integrity file
86 | .yarn-integrity
87 |
88 | # dotenv environment variables file
89 | .env
90 |
91 | # parcel-bundler cache (https://parceljs.org/)
92 | .cache
93 |
94 | # next.js build output
95 | .next
96 |
97 | # nuxt.js build output
98 | .nuxt
99 |
100 | # vuepress build output
101 | .vuepress/dist
102 |
103 | # Serverless directories
104 | .serverless
105 |
106 | ### Test ###
107 | ### Ignore all files that could be used to test your code and
108 | ### you wouldn't want to push
109 |
110 | # Reference https://en.wikipedia.org/wiki/Metasyntactic_variable
111 |
112 | # Most common
113 | *foo
114 | *bar
115 | *fubar
116 | *foobar
117 | *baz
118 |
119 | # Less common
120 | *qux
121 | *quux
122 | *bongo
123 | *bazola
124 | *ztesch
125 |
126 | # UK, Australia
127 | *wibble
128 | *wobble
129 | *wubble
130 | *flob
131 | *blep
132 | *blah
133 | *boop
134 | *beep
135 |
136 | # Japanese
137 | *hoge
138 | *piyo
139 | *fuga
140 | *hogera
141 | *hogehoge
142 |
143 | # Portugal, Spain
144 | *fulano
145 | *sicrano
146 | *beltrano
147 | *mengano
148 | *perengano
149 | *zutano
150 |
151 | # France, Italy, the Netherlands
152 | *toto
153 | *titi
154 | *tata
155 | *tutu
156 | *pipppo
157 | *pluto
158 | *paperino
159 | *aap
160 | *noot
161 | *mies
162 |
163 | # Other names that would make sense
164 | *tests
165 | *testsdir
166 | *testsfile
167 | *testsfiles
168 | *test
169 | *testdir
170 | *testfile
171 | *testfiles
172 | *testing
173 | *testingdir
174 | *testingfile
175 | *testingfiles
176 | *temp
177 | *tempdir
178 | *tempfile
179 | *tempfiles
180 | *tmp
181 | *tmpdir
182 | *tmpfile
183 | *tmpfiles
184 | *lol
185 | .DS_Store
186 |
187 | # End of https://www.gitignore.io/api/node,test,macos
--------------------------------------------------------------------------------
/Section-1/1.3/01-Writing-your-first-unit-test/after/math.js:
--------------------------------------------------------------------------------
1 | function sum(a, b){
2 | return a + b;
3 | }
4 | module.exports = {
5 | sum
6 | }
--------------------------------------------------------------------------------
/Section-1/1.3/01-Writing-your-first-unit-test/after/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "test": "jest"
8 | },
9 | "directories": {
10 | "test": "tests"
11 | },
12 | "devDependencies": {
13 | "jest": "^23.6.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Section-1/1.3/01-Writing-your-first-unit-test/before/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by https://www.gitignore.io/api/node,test,macos
2 |
3 | ### macOS ###
4 | # General
5 | .DS_Store
6 | .AppleDouble
7 | .LSOverride
8 |
9 | # Icon must end with two \r
10 | Icon
11 |
12 | # Thumbnails
13 | ._*
14 |
15 | # Files that might appear in the root of a volume
16 | .DocumentRevisions-V100
17 | .fseventsd
18 | .Spotlight-V100
19 | .TemporaryItems
20 | .Trashes
21 | .VolumeIcon.icns
22 | .com.apple.timemachine.donotpresent
23 |
24 | # Directories potentially created on remote AFP share
25 | .AppleDB
26 | .AppleDesktop
27 | Network Trash Folder
28 | Temporary Items
29 | .apdisk
30 |
31 | ### Node ###
32 | # Logs
33 | logs
34 | *.log
35 | npm-debug.log*
36 | yarn-debug.log*
37 | yarn-error.log*
38 |
39 | # Runtime data
40 | pids
41 | *.pid
42 | *.seed
43 | *.pid.lock
44 |
45 | # Directory for instrumented libs generated by jscoverage/JSCover
46 | lib-cov
47 |
48 | # Coverage directory used by tools like istanbul
49 | coverage
50 |
51 | # nyc test coverage
52 | .nyc_output
53 |
54 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
55 | .grunt
56 |
57 | # Bower dependency directory (https://bower.io/)
58 | bower_components
59 |
60 | # node-waf configuration
61 | .lock-wscript
62 |
63 | # Compiled binary addons (https://nodejs.org/api/addons.html)
64 | build/Release
65 |
66 | # Dependency directories
67 | node_modules/
68 | jspm_packages/
69 |
70 | # TypeScript v1 declaration files
71 | typings/
72 |
73 | # Optional npm cache directory
74 | .npm
75 |
76 | # Optional eslint cache
77 | .eslintcache
78 |
79 | # Optional REPL history
80 | .node_repl_history
81 |
82 | # Output of 'npm pack'
83 | *.tgz
84 |
85 | # Yarn Integrity file
86 | .yarn-integrity
87 |
88 | # dotenv environment variables file
89 | .env
90 |
91 | # parcel-bundler cache (https://parceljs.org/)
92 | .cache
93 |
94 | # next.js build output
95 | .next
96 |
97 | # nuxt.js build output
98 | .nuxt
99 |
100 | # vuepress build output
101 | .vuepress/dist
102 |
103 | # Serverless directories
104 | .serverless
105 |
106 | ### Test ###
107 | ### Ignore all files that could be used to test your code and
108 | ### you wouldn't want to push
109 |
110 | # Reference https://en.wikipedia.org/wiki/Metasyntactic_variable
111 |
112 | # Most common
113 | *foo
114 | *bar
115 | *fubar
116 | *foobar
117 | *baz
118 |
119 | # Less common
120 | *qux
121 | *quux
122 | *bongo
123 | *bazola
124 | *ztesch
125 |
126 | # UK, Australia
127 | *wibble
128 | *wobble
129 | *wubble
130 | *flob
131 | *blep
132 | *blah
133 | *boop
134 | *beep
135 |
136 | # Japanese
137 | *hoge
138 | *piyo
139 | *fuga
140 | *hogera
141 | *hogehoge
142 |
143 | # Portugal, Spain
144 | *fulano
145 | *sicrano
146 | *beltrano
147 | *mengano
148 | *perengano
149 | *zutano
150 |
151 | # France, Italy, the Netherlands
152 | *toto
153 | *titi
154 | *tata
155 | *tutu
156 | *pipppo
157 | *pluto
158 | *paperino
159 | *aap
160 | *noot
161 | *mies
162 |
163 | # Other names that would make sense
164 | *tests
165 | *testsdir
166 | *testsfile
167 | *testsfiles
168 | *test
169 | *testdir
170 | *testfile
171 | *testfiles
172 | *testing
173 | *testingdir
174 | *testingfile
175 | *testingfiles
176 | *temp
177 | *tempdir
178 | *tempfile
179 | *tempfiles
180 | *tmp
181 | *tmpdir
182 | *tmpfile
183 | *tmpfiles
184 | *lol
185 | .DS_Store
186 |
187 | # End of https://www.gitignore.io/api/node,test,macos
--------------------------------------------------------------------------------
/Section-1/1.3/01-Writing-your-first-unit-test/before/math.js:
--------------------------------------------------------------------------------
1 | function sum(a, b){
2 | return a + b;
3 | }
4 | module.exports = {
5 | sum
6 | }
--------------------------------------------------------------------------------
/Section-1/1.3/01-Writing-your-first-unit-test/before/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "directories": {
7 | "test": "tests"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Section-1/1.4/04-testing-numbers-and-strings/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/learning-zone/javascript-unit-testing/2bce97478b1231a70d5ef1a572bf43b7078dfd83/Section-1/1.4/04-testing-numbers-and-strings/.DS_Store
--------------------------------------------------------------------------------
/Section-1/1.4/04-testing-numbers-and-strings/after/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/learning-zone/javascript-unit-testing/2bce97478b1231a70d5ef1a572bf43b7078dfd83/Section-1/1.4/04-testing-numbers-and-strings/after/.DS_Store
--------------------------------------------------------------------------------
/Section-1/1.4/04-testing-numbers-and-strings/after/math.js:
--------------------------------------------------------------------------------
1 | function sum(a, b){
2 | return a + b;
3 | }
4 | module.exports = {
5 | sum
6 | }
--------------------------------------------------------------------------------
/Section-1/1.4/04-testing-numbers-and-strings/after/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "test": "jest"
8 | },
9 | "directories": {
10 | "test": "tests"
11 | },
12 | "devDependencies": {
13 | "jest": "^23.6.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Section-1/1.4/04-testing-numbers-and-strings/after/tests/math.test.js:
--------------------------------------------------------------------------------
1 | const { sum } = require('../math');
2 |
3 | describe('Sum Feature', () => {
4 | test('should calculate the sum of two numbers', () => {
5 | const results = sum(2,2);
6 | expect(results).toBe(4);
7 | expect(results).toBeGreaterThan(3)
8 | expect(results).toBeGreaterThanOrEqual(3)
9 | expect(results).toBeLessThan(5)
10 | expect(results).toBeLessThanOrEqual(5);
11 | expect(results).toEqual(4)
12 | });
13 | test('should calculate the sum of two floating point numbers', () => {
14 | const results = sum(0.1 , 0.3);
15 | expect(results).toBeCloseTo(0.4);
16 | })
17 | });
18 |
--------------------------------------------------------------------------------
/Section-1/1.4/04-testing-numbers-and-strings/after/tests/util.test.js:
--------------------------------------------------------------------------------
1 | const {greet} = require('../util');
2 |
3 | describe('Greet Feature', () => {
4 | it('should get the greet message', () => {
5 | const results = greet('Jane');
6 | expect(results).toBe('Hello Jane');
7 | expect(results).toMatch('Jane');
8 | expect(results).toMatch(/Jane/);
9 | })
10 | })
11 |
--------------------------------------------------------------------------------
/Section-1/1.4/04-testing-numbers-and-strings/after/util.js:
--------------------------------------------------------------------------------
1 | function greet(name){
2 | return `Hello ${name}`;
3 | }
4 | module.exports ={
5 | greet
6 | }
--------------------------------------------------------------------------------
/Section-1/1.4/04-testing-numbers-and-strings/before/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/learning-zone/javascript-unit-testing/2bce97478b1231a70d5ef1a572bf43b7078dfd83/Section-1/1.4/04-testing-numbers-and-strings/before/.DS_Store
--------------------------------------------------------------------------------
/Section-1/1.4/04-testing-numbers-and-strings/before/math.js:
--------------------------------------------------------------------------------
1 | function sum(a, b){
2 | return a + b;
3 | }
4 | module.exports = {
5 | sum
6 | }
--------------------------------------------------------------------------------
/Section-1/1.4/04-testing-numbers-and-strings/before/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "test": "jest"
8 | },
9 | "directories": {
10 | "test": "tests"
11 | },
12 | "devDependencies": {
13 | "jest": "^23.6.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Section-1/1.4/04-testing-numbers-and-strings/before/tests/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/learning-zone/javascript-unit-testing/2bce97478b1231a70d5ef1a572bf43b7078dfd83/Section-1/1.4/04-testing-numbers-and-strings/before/tests/.DS_Store
--------------------------------------------------------------------------------
/Section-1/1.4/04-testing-numbers-and-strings/before/tests/math.test.js:
--------------------------------------------------------------------------------
1 | const { sum } = require('../math');
2 |
3 | test('should calculate the sum of two numbers', () => {
4 |
5 | });
6 |
--------------------------------------------------------------------------------
/Section-1/1.4/04-testing-numbers-and-strings/before/util.js:
--------------------------------------------------------------------------------
1 | function greet(name){
2 | return `Hello ${name}`;
3 | }
4 | module.exports ={
5 | greet
6 | }
--------------------------------------------------------------------------------
/Section-1/1.5/05-testing-thruthiness/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/learning-zone/javascript-unit-testing/2bce97478b1231a70d5ef1a572bf43b7078dfd83/Section-1/1.5/05-testing-thruthiness/.DS_Store
--------------------------------------------------------------------------------
/Section-1/1.5/05-testing-thruthiness/after/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "test": "jest"
8 | },
9 | "directories": {
10 | "test": "tests"
11 | },
12 | "devDependencies": {
13 | "jest": "^23.6.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Section-1/1.5/05-testing-thruthiness/after/tests/util.test.js:
--------------------------------------------------------------------------------
1 | const { greet, isEven, isOdd } = require('../util');
2 |
3 | describe('Greet Feature', () => {
4 | it('should get the greet message', () => {
5 | const results = greet('Jane');
6 | expect(results).toBe('Hello Jane');
7 | expect(results).toMatch('Jane');
8 | expect(results).toMatch(/Jane/);
9 | });
10 | });
11 |
12 | describe('Even', () => {
13 | it('should return true if number is even', () => {
14 | const results = isEven(2);
15 | expect(results).toBeTruthy();
16 | expect(results).not.toBeFalsy();
17 | });
18 | it('should return false if number is not even', () => {
19 | const results = isEven(3);
20 | expect(results).not.toBeTruthy();
21 | expect(results).toBeFalsy();
22 | });
23 | });
24 | describe('Odd', () => {
25 | it('should return true if number is odd', () => {
26 | const results = isOdd(3);
27 | expect(results).toBeTruthy();
28 | expect(results).not.toBeFalsy();
29 | });
30 | it('should return false if number is not odd', () => {
31 | const results = isOdd(4);
32 | expect(results).not.toBeTruthy();
33 | expect(results).toBeFalsy();
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/Section-1/1.5/05-testing-thruthiness/after/util.js:
--------------------------------------------------------------------------------
1 | function greet(name) {
2 | return `Hello ${name}`;
3 | }
4 | function isEven(n) {
5 | return n % 2 == 0;
6 | }
7 | function isOdd(n) {
8 | return Math.abs(n % 2) == 1;
9 | }
10 | module.exports = {
11 | greet,
12 | isEven,
13 | isOdd
14 | };
15 |
--------------------------------------------------------------------------------
/Section-1/1.5/05-testing-thruthiness/before/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "test": "jest"
8 | },
9 | "directories": {
10 | "test": "tests"
11 | },
12 | "devDependencies": {
13 | "jest": "^23.6.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Section-1/1.5/05-testing-thruthiness/before/tests/util.test.js:
--------------------------------------------------------------------------------
1 | const { greet, isEven, isOdd } = require('../util');
2 |
3 | describe('Greet Feature', () => {
4 | it('should get the greet message', () => {
5 | const results = greet('Jane');
6 | expect(results).toBe('Hello Jane');
7 | expect(results).toMatch('Jane');
8 | expect(results).toMatch(/Jane/);
9 | });
10 | });
11 |
12 | describe('Even', () => {
13 | it('should return true if number is even', () => {
14 | const results = isEven(2);
15 | expect(results).toBeTruthy();
16 | expect(results).not.toBeFalsy();
17 | });
18 | it('should return false if number is not even', () => {
19 | const results = isEven(3);
20 | expect(results).not.toBeTruthy();
21 | expect(results).toBeFalsy();
22 | });
23 | });
24 | describe('Odd', () => {
25 | it('should return true if number is odd', () => {
26 | const results = isOdd(3);
27 | expect(results).toBeTruthy();
28 | expect(results).not.toBeFalsy();
29 | });
30 | it('should return false if number is not odd', () => {
31 | const results = isOdd(4);
32 | expect(results).not.toBeTruthy();
33 | expect(results).toBeFalsy();
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/Section-1/1.5/05-testing-thruthiness/before/util.js:
--------------------------------------------------------------------------------
1 | function greet(name) {
2 | return `Hello ${name}`;
3 | }
4 | function isEven(n) {
5 | return n % 2 == 0;
6 | }
7 | function isOdd(n) {
8 | return Math.abs(n % 2) == 1;
9 | }
10 | module.exports = {
11 | greet,
12 | isEven,
13 | isOdd
14 | };
15 |
--------------------------------------------------------------------------------
/Section-1/1.6/06-testing-arrays-and-objects/after/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/learning-zone/javascript-unit-testing/2bce97478b1231a70d5ef1a572bf43b7078dfd83/Section-1/1.6/06-testing-arrays-and-objects/after/.DS_Store
--------------------------------------------------------------------------------
/Section-1/1.6/06-testing-arrays-and-objects/after/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "test": "jest"
8 | },
9 | "directories": {
10 | "test": "tests"
11 | },
12 | "devDependencies": {
13 | "jest": "^23.6.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Section-1/1.6/06-testing-arrays-and-objects/after/tests/util.test.js:
--------------------------------------------------------------------------------
1 | const { greet, isEven, isOdd, getCustomer, getPersons } = require('../util');
2 |
3 | describe('Greet Feature', () => {
4 | it('should get the greet message', () => {
5 | const results = greet('Jane');
6 | expect(results).toBe('Hello Jane');
7 | expect(results).toMatch('Jane');
8 | expect(results).toMatch(/Jane/);
9 | });
10 | });
11 |
12 | describe('Even', () => {
13 | it('should return true if number is even', () => {
14 | const results = isEven(2);
15 | expect(results).toBeTruthy();
16 | expect(results).not.toBeFalsy();
17 | });
18 | it('should return false if number is not even', () => {
19 | const results = isEven(3);
20 | expect(results).not.toBeTruthy();
21 | expect(results).toBeFalsy();
22 | });
23 | });
24 | describe('Odd', () => {
25 | it('should return true if number is odd', () => {
26 | const results = isOdd(3);
27 | expect(results).toBeTruthy();
28 | expect(results).not.toBeFalsy();
29 | });
30 | it('should return false if number is not odd', () => {
31 | const results = isOdd(4);
32 | expect(results).not.toBeTruthy();
33 | expect(results).toBeFalsy();
34 | });
35 | });
36 | describe('Customer', () => {
37 | it('should find customer by id', () => {
38 | const results = getCustomer(1);
39 | expect(results).toBeDefined();
40 | expect(results).not.toBeUndefined();
41 |
42 | expect(results).toEqual({ id: 1, name: 'Jane' });
43 | expect(results).toHaveProperty('id', 1);
44 |
45 | expect(results).toEqual(expect.objectContaining({ id: 1 }));
46 | });
47 | });
48 | describe('Persons', () => {
49 | it('should fetch all the persons', () => {
50 | const results = getPersons();
51 | expect(results).toHaveLength(4);
52 | expect(results).toContain('Doe');
53 |
54 | expect(results).toEqual(expect.arrayContaining(['Jane', 'Doe']));
55 | });
56 | });
57 |
--------------------------------------------------------------------------------
/Section-1/1.6/06-testing-arrays-and-objects/after/util.js:
--------------------------------------------------------------------------------
1 | function greet(name) {
2 | return `Hello ${name}`;
3 | }
4 | function isEven(n) {
5 | return n % 2 == 0;
6 | }
7 | function isOdd(n) {
8 | return Math.abs(n % 2) == 1;
9 | }
10 | function getCustomer(id) {
11 | return { id, name: 'Jane' };
12 | }
13 | const persons = ['Jane', 'Doe', 'Sane', 'Mathew'];
14 | function getPersons() {
15 | return persons;
16 | }
17 | module.exports = {
18 | greet,
19 | isEven,
20 | isOdd,
21 | getCustomer,
22 | getPersons
23 | };
24 |
--------------------------------------------------------------------------------
/Section-1/1.6/06-testing-arrays-and-objects/before/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "test": "jest"
8 | },
9 | "directories": {
10 | "test": "tests"
11 | },
12 | "devDependencies": {
13 | "jest": "^23.6.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Section-1/1.6/06-testing-arrays-and-objects/before/tests/util.test.js:
--------------------------------------------------------------------------------
1 | const { greet, isEven, isOdd, getCustomer, getPersons } = require('../util');
2 |
3 | describe('Greet Feature', () => {
4 | it('should get the greet message', () => {
5 | const results = greet('Jane');
6 | expect(results).toBe('Hello Jane');
7 | expect(results).toMatch('Jane');
8 | expect(results).toMatch(/Jane/);
9 | });
10 | });
11 |
12 | describe('Even', () => {
13 | it('should return true if number is even', () => {
14 | const results = isEven(2);
15 | expect(results).toBeTruthy();
16 | expect(results).not.toBeFalsy();
17 | });
18 | it('should return false if number is not even', () => {
19 | const results = isEven(3);
20 | expect(results).not.toBeTruthy();
21 | expect(results).toBeFalsy();
22 | });
23 | });
24 | describe('Odd', () => {
25 | it('should return true if number is odd', () => {
26 | const results = isOdd(3);
27 | expect(results).toBeTruthy();
28 | expect(results).not.toBeFalsy();
29 | });
30 | it('should return false if number is not odd', () => {
31 | const results = isOdd(4);
32 | expect(results).not.toBeTruthy();
33 | expect(results).toBeFalsy();
34 | });
35 | });
36 | describe('Customer', () => {
37 | it('should find customer by id', () => {
38 | const results = getCustomer(1);
39 | expect(results).toBeDefined();
40 | expect(results).not.toBeUndefined();
41 |
42 | expect(results).toEqual({ id: 1, name: 'Jane' });
43 | expect(results).toHaveProperty('id', 1);
44 |
45 | expect(results).toEqual(expect.objectContaining({ id: 1 }));
46 | });
47 | });
48 | describe('Persons', () => {
49 | it('should fetch all the persons', () => {
50 | const results = getPersons();
51 | expect(results).toHaveLength(4);
52 | expect(results).toContain('Doe');
53 |
54 | expect(results).toEqual(expect.arrayContaining(['Jane', 'Doe']));
55 | });
56 | });
57 |
--------------------------------------------------------------------------------
/Section-1/1.6/06-testing-arrays-and-objects/before/util.js:
--------------------------------------------------------------------------------
1 | function greet(name) {
2 | return `Hello ${name}`;
3 | }
4 | function isEven(n) {
5 | return n % 2 == 0;
6 | }
7 | function isOdd(n) {
8 | return Math.abs(n % 2) == 1;
9 | }
10 | function getCustomer(id) {
11 | return { id, name: 'Jane' };
12 | }
13 | const persons = ['Jane', 'Doe', 'Sane', 'Mathew'];
14 | function getPersons() {
15 | return persons;
16 | }
17 | module.exports = {
18 | greet,
19 | isEven,
20 | isOdd,
21 | getCustomer,
22 | getPersons
23 | };
24 |
--------------------------------------------------------------------------------
/Section-1/1.7/07-testing-exceptions/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/learning-zone/javascript-unit-testing/2bce97478b1231a70d5ef1a572bf43b7078dfd83/Section-1/1.7/07-testing-exceptions/.DS_Store
--------------------------------------------------------------------------------
/Section-1/1.7/07-testing-exceptions/after/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "test": "jest"
8 | },
9 | "directories": {
10 | "test": "tests"
11 | },
12 | "devDependencies": {
13 | "jest": "^23.6.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Section-1/1.7/07-testing-exceptions/after/tests/util.test.js:
--------------------------------------------------------------------------------
1 | const {
2 | greet,
3 | isEven,
4 | isOdd,
5 | getCustomer,
6 | getPersons,
7 | downloadCV
8 | } = require('../util');
9 |
10 | describe('Greet Feature', () => {
11 | it('should get the greet message', () => {
12 | const results = greet('Jane');
13 | expect(results).toBe('Hello Jane');
14 | expect(results).toMatch('Jane');
15 | expect(results).toMatch(/Jane/);
16 | });
17 | });
18 |
19 | describe('Even', () => {
20 | it('should return true if number is even', () => {
21 | const results = isEven(2);
22 | expect(results).toBeTruthy();
23 | expect(results).not.toBeFalsy();
24 | });
25 | it('should return false if number is not even', () => {
26 | const results = isEven(3);
27 | expect(results).not.toBeTruthy();
28 | expect(results).toBeFalsy();
29 | });
30 | });
31 | describe('Odd', () => {
32 | it('should return true if number is odd', () => {
33 | const results = isOdd(3);
34 | expect(results).toBeTruthy();
35 | expect(results).not.toBeFalsy();
36 | });
37 | it('should return false if number is not odd', () => {
38 | const results = isOdd(4);
39 | expect(results).not.toBeTruthy();
40 | expect(results).toBeFalsy();
41 | });
42 | });
43 | describe('Customer', () => {
44 | it('should find customer by id', () => {
45 | const results = getCustomer(1);
46 | expect(results).toBeDefined();
47 | expect(results).not.toBeUndefined();
48 |
49 | expect(results).toEqual({ id: 1, name: 'Jane' });
50 | expect(results).toHaveProperty('id', 1);
51 |
52 | expect(results).toEqual(expect.objectContaining({ id: 1 }));
53 | });
54 | });
55 | describe('Persons', () => {
56 | it('should fetch all the persons', () => {
57 | const results = getPersons();
58 | expect(results).toHaveLength(4);
59 | expect(results).toContain('Doe');
60 |
61 | expect(results).toEqual(expect.arrayContaining(['Jane', 'Doe']));
62 | });
63 | });
64 |
65 | describe('Download CV', () => {
66 | it('should throw error if user does not provide path', () => {
67 | expect(() => {
68 | downloadCV();
69 | }).toThrow();
70 | expect(() => {
71 | downloadCV();
72 | }).toThrow('invalid URL');
73 | expect(() => {
74 | downloadCV(null);
75 | }).toThrow();
76 | });
77 | it('should get the contents from the CV', () => {
78 | const results = downloadCV('http://localhost:3000/cv/1');
79 | expect(results).toBe('Content');
80 | });
81 | });
82 |
--------------------------------------------------------------------------------
/Section-1/1.7/07-testing-exceptions/after/util.js:
--------------------------------------------------------------------------------
1 | function greet(name) {
2 | return `Hello ${name}`;
3 | }
4 | function isEven(n) {
5 | return n % 2 == 0;
6 | }
7 | function isOdd(n) {
8 | return Math.abs(n % 2) == 1;
9 | }
10 | function getCustomer(id) {
11 | return { id, name: 'Jane' };
12 | }
13 | const persons = ['Jane', 'Doe', 'Sane', 'Mathew'];
14 | function getPersons() {
15 | return persons;
16 | }
17 |
18 | function downloadCV(path) {
19 | if (!path) {
20 | throw new Error('invalid URL');
21 | }
22 | return 'Content';
23 | }
24 | module.exports = {
25 | greet,
26 | isEven,
27 | isOdd,
28 | getCustomer,
29 | getPersons,
30 | downloadCV
31 | };
32 |
--------------------------------------------------------------------------------
/Section-1/1.7/07-testing-exceptions/before/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/learning-zone/javascript-unit-testing/2bce97478b1231a70d5ef1a572bf43b7078dfd83/Section-1/1.7/07-testing-exceptions/before/.DS_Store
--------------------------------------------------------------------------------
/Section-1/1.7/07-testing-exceptions/before/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "test": "jest"
8 | },
9 | "directories": {
10 | "test": "tests"
11 | },
12 | "devDependencies": {
13 | "jest": "^23.6.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Section-1/1.7/07-testing-exceptions/before/tests/util.test.js:
--------------------------------------------------------------------------------
1 | const { greet, isEven, isOdd, getCustomer, getPersons } = require('../util');
2 |
3 | describe('Greet Feature', () => {
4 | it('should get the greet message', () => {
5 | const results = greet('Jane');
6 | expect(results).toBe('Hello Jane');
7 | expect(results).toMatch('Jane');
8 | expect(results).toMatch(/Jane/);
9 | });
10 | });
11 |
12 | describe('Even', () => {
13 | it('should return true if number is even', () => {
14 | const results = isEven(2);
15 | expect(results).toBeTruthy();
16 | expect(results).not.toBeFalsy();
17 | });
18 | it('should return false if number is not even', () => {
19 | const results = isEven(3);
20 | expect(results).not.toBeTruthy();
21 | expect(results).toBeFalsy();
22 | });
23 | });
24 | describe('Odd', () => {
25 | it('should return true if number is odd', () => {
26 | const results = isOdd(3);
27 | expect(results).toBeTruthy();
28 | expect(results).not.toBeFalsy();
29 | });
30 | it('should return false if number is not odd', () => {
31 | const results = isOdd(4);
32 | expect(results).not.toBeTruthy();
33 | expect(results).toBeFalsy();
34 | });
35 | });
36 | describe('Customer', () => {
37 | it('should find customer by id', () => {
38 | const results = getCustomer(1);
39 | expect(results).toBeDefined();
40 | expect(results).not.toBeUndefined();
41 |
42 | expect(results).toEqual({ id: 1, name: 'Jane' });
43 | expect(results).toHaveProperty('id', 1);
44 |
45 | expect(results).toEqual(expect.objectContaining({ id: 1 }));
46 | });
47 | });
48 | describe('Persons', () => {
49 | it('should fetch all the persons', () => {
50 | const results = getPersons();
51 | expect(results).toHaveLength(4);
52 | expect(results).toContain('Doe');
53 |
54 | expect(results).toEqual(expect.arrayContaining(['Jane', 'Doe']));
55 | });
56 | });
57 |
--------------------------------------------------------------------------------
/Section-1/1.7/07-testing-exceptions/before/util.js:
--------------------------------------------------------------------------------
1 | function greet(name) {
2 | return `Hello ${name}`;
3 | }
4 | function isEven(n) {
5 | return n % 2 == 0;
6 | }
7 | function isOdd(n) {
8 | return Math.abs(n % 2) == 1;
9 | }
10 | function getCustomer(id) {
11 | return { id, name: 'Jane' };
12 | }
13 | const persons = ['Jane', 'Doe', 'Sane', 'Mathew'];
14 | function getPersons() {
15 | return persons;
16 | }
17 |
18 | function downloadCV(path) {
19 | if (!path) {
20 | throw new Error('invalid URL');
21 | }
22 | return 'Content';
23 | }
24 | module.exports = {
25 | greet,
26 | isEven,
27 | isOdd,
28 | getCustomer,
29 | getPersons,
30 | downloadCV
31 | };
32 |
--------------------------------------------------------------------------------
/Section-2/2.2/BankAccount.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/learning-zone/javascript-unit-testing/2bce97478b1231a70d5ef1a572bf43b7078dfd83/Section-2/2.2/BankAccount.js
--------------------------------------------------------------------------------
/Section-2/2.2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "test": "jest --watchAll"
8 | },
9 | "directories": {
10 | "test": "tests"
11 | },
12 | "devDependencies": {
13 | "jest": "^23.6.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Section-2/2.2/tests/BankAcount.test.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/learning-zone/javascript-unit-testing/2bce97478b1231a70d5ef1a572bf43b7078dfd83/Section-2/2.2/tests/BankAcount.test.js
--------------------------------------------------------------------------------
/Section-2/2.4/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 | // Project configuration.
3 | grunt.initConfig({
4 | shell: {
5 | simple: {
6 | command: 'cucumber.js simple/features -r simple/steps'
7 | }
8 | }
9 | });
10 |
11 | // These plugins provide necessary tasks.
12 | grunt.loadNpmTasks('grunt-shell');
13 | };
14 |
--------------------------------------------------------------------------------
/Section-2/2.4/README.md:
--------------------------------------------------------------------------------
1 | # BDD in JavaScript: Getting Started with Cucumber and Gherkin
2 |
3 | This repository exists as a set of example implementations of Cucumber.js functionality.
4 | Article URL: https://www.sitepoint.com/bdd-in-javascript-cucumber-gherkin
5 |
6 | ## Examples
7 |
8 | This repository has the following set of examples:
9 |
10 | * simple - A very simple example that does nothing special
11 | * background - Identical to the 'simple' example in terms of Javascript, but using a Background for common initialisation
12 | * outline - Identical to the 'simple' example in terms of Javascript, but using a Scenario Outline to generate Scenarios
13 | * datatable - Adaptation of the 'simple' example to use a Data Table to add an arbitrary list of numbers
14 | * hooks - Demonstration of a Before hook for resetting data
15 | * events - Demonstration of event handling for the lifecycle of running tests
16 | * world - Demonstration of the World concept for data sharing
17 |
18 | ## Running examples
19 |
20 | The examples are all set up to run with either npm Scripts, Grunt or Gulp. They can all be run as either:
21 |
22 | * npm run-script
23 | * grunt shell:
24 | * gulp
25 |
26 | ## License
27 |
28 | For example, `npm run-script simple`, `grunt shell:background` or `gulp outline`.
29 |
30 | SitePoint's code archives and code examples are licensed under the MIT license.
31 |
32 | Copyright © 2017 SitePoint
33 |
34 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
35 |
36 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
37 |
38 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
39 |
--------------------------------------------------------------------------------
/Section-2/2.4/features/addition.feature:
--------------------------------------------------------------------------------
1 | Feature: Addition
2 | Scenario: 1 + 2
3 | Given I start with 1
4 | When I add 2
5 | Then I end up with 3
6 |
--------------------------------------------------------------------------------
/Section-2/2.4/gulpfile.js:
--------------------------------------------------------------------------------
1 | const gulp = require('gulp');
2 | const shell = require('gulp-shell');
3 |
4 | gulp.task(
5 | 'simple',
6 | shell.task(['cucumber.js simple/features -r simple/steps'])
7 | );
8 |
--------------------------------------------------------------------------------
/Section-2/2.4/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bdd",
3 | "version": "1.0.0",
4 | "description": "Behaviour Driven Development in Javascript",
5 | "main": "index.js",
6 | "scripts": {
7 | "dev": "cucumber.js features -r steps"
8 | },
9 | "author": "Haider Malik",
10 | "license": "ISC",
11 | "dependencies": {
12 | "chai": "^3.5.0",
13 | "cucumber": "^2.1.0",
14 | "grunt": "^1.0.1",
15 | "grunt-cli": "^1.2.0",
16 | "grunt-shell": "^2.1.0",
17 | "gulp": "^3.9.1",
18 | "gulp-shell": "^0.6.3"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/Section-3/3.1/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "test": "jest --watchAll"
8 | },
9 | "directories": {
10 | "test": "tests"
11 | },
12 | "devDependencies": {
13 | "jest": "^23.6.0"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Section-3/3.1/tests/assert-demo.test.js:
--------------------------------------------------------------------------------
1 | const assert = require('assert');
2 | describe('Assert library', () => {
3 | it('assert() demo', () => {
4 | assert(100 > 70, 'Expected value is not greater than received value');
5 | });
6 | //If two objects, or their child objects, are not equal, an error is thrown and the program is terminated:
7 | it('deepEqual() demo', () => {
8 | let x = { a: { n: 0 } };
9 | let y = { a: { n: 0 } };
10 | let z = { a: { n: 0 } };
11 | assert.deepEqual(x, y); //OK
12 | assert.deepEqual(
13 | x,
14 | z
15 | ); /*AssertionError: { a: { n: 0 } } deepEqual {a: { n: 1 } }*/
16 | });
17 | //If two values are not equal, an error is thrown and the program is terminated:
18 | it('equal() demo', () => {
19 | assert.equal(50, 50); //OK
20 | assert.equal(50, '50'); //OK
21 | assert.equal(50, 50); /*AssertionError: 50 == 70 */
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/Section-3/3.2/math.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | sum(a, b) {
3 | return a + b;
4 | }
5 | };
6 |
--------------------------------------------------------------------------------
/Section-3/3.2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "test": "jest --watchAll"
8 | },
9 | "directories": {
10 | "test": "tests"
11 | },
12 | "devDependencies": {
13 | "chai": "^4.2.0",
14 | "jest": "^23.6.0"
15 | },
16 | "dependencies": {
17 | "should": "^13.2.3"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Section-3/3.2/tests/assert-demo.test.js:
--------------------------------------------------------------------------------
1 | const assert = require('assert');
2 | describe('Assert library', () => {
3 | it('assert() demo', () => {
4 | assert(100 > 70, 'Expected value is not greater than received value');
5 | });
6 | //If two objects, or their child objects, are not equal, an error is thrown and the program is terminated:
7 | it('deepEqual() demo', () => {
8 | let x = { a: { n: 0 } };
9 | let y = { a: { n: 0 } };
10 | let z = { a: { n: 0 } };
11 | assert.deepEqual(x, y); //OK
12 | assert.deepEqual(
13 | x,
14 | z
15 | ); /*AssertionError: { a: { n: 0 } } deepEqual {a: { n: 1 } }*/
16 | });
17 | //If two values are not equal, an error is thrown and the program is terminated:
18 | it('equal() demo', () => {
19 | assert.equal(50, 50); //OK
20 | assert.equal(50, '50'); //OK
21 | assert.equal(50, 50); /*AssertionError: 50 == 70 */
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/Section-3/3.2/tests/chai.js-demo.test.js:
--------------------------------------------------------------------------------
1 | const assert = require('chai').assert;
2 | const expect = require('chai').expect;
3 | const should = require('chai').should(); //actually call the function
4 | describe('chai assetion library', () => {
5 | it('assert with chai demo', () => {
6 | let foo = 'bar',
7 | beverages = { tea: ['chai', 'matcha', 'oolong'] };
8 | assert.typeOf(foo, 'string'); // without optional message
9 | assert.typeOf(foo, 'string', 'foo is a string'); // with optional message
10 | assert.equal(foo, 'bar', 'foo equal `bar`');
11 | assert.lengthOf(foo, 3, 'foo`s value has a length of 3');
12 | assert.lengthOf(beverages.tea, 3, 'beverages has 3 types of tea');
13 | });
14 | it('expect with chai', () => {
15 | const foo = 'bar',
16 | beverages = { tea: ['chai', 'matcha', 'oolong'] };
17 |
18 | expect(foo).to.be.a('string');
19 | expect(foo).to.equal('bar');
20 | expect(foo).to.have.lengthOf(3);
21 | expect(beverages)
22 | .to.have.property('tea')
23 | .with.lengthOf(3);
24 | });
25 |
26 | it('should with chai.js', () => {
27 | const foo = 'bar',
28 | beverages = { tea: ['chai', 'matcha', 'oolong'] };
29 |
30 | foo.should.be.a('string');
31 | foo.should.equal('bar');
32 | foo.should.have.lengthOf(3);
33 | beverages.should.have.property('tea').with.lengthOf(3);
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/Section-3/3.2/tests/expect-demo.test.js:
--------------------------------------------------------------------------------
1 | describe('Expect Assertion library', () => {
2 | it('toBe Demo', () => {
3 | expect(2 + 2).toBe(4);
4 | });
5 | it('toEqual demo', () => {
6 | const data = { one: 1 };
7 | data['two'] = 2;
8 | expect(data).toEqual({ one: 1, two: 2 });
9 | });
10 |
11 | it('truthiness', () => {
12 | const z = 0;
13 | expect(z).not.toBeNull();
14 | expect(z).toBeDefined();
15 | expect(z).not.toBeUndefined();
16 | expect(z).not.toBeTruthy();
17 | expect(z).toBeFalsy();
18 | });
19 |
20 | it('toContain demo', () => {
21 | const shoppingList = [
22 | 'diapers',
23 | 'kleenex',
24 | 'trash bags',
25 | 'paper towels',
26 | 'beer'
27 | ];
28 | expect(shoppingList).toContain('beer');
29 | });
30 |
31 | it('toMatch Demo', () => {
32 | expect('Christoph').toMatch(/stop/);
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/Section-3/3.2/tests/should.js-demo.test.js:
--------------------------------------------------------------------------------
1 | //docs https://github.com/tj/should.js/
2 | const { sum } = require('../math');
3 | const should = require('should');
4 | describe('Should.js', () => {
5 | it('should return 4 when the input number are 1 and 3', function() {
6 | sum(1, 3).should.be.exactly(4);
7 | sum(1, 3).should.be.exactly(4).and.be.a.Number;
8 | });
9 | it('startWith demo', () => {
10 | 'foobar'.should.startWith('foo');
11 | 'foobar'.should.not.startWith('bar');
12 | });
13 | it('above and greaterThan demo', () => {
14 | const user = { age: 20 };
15 | user.age.should.be.above(5);
16 | user.age.should.not.be.above(100);
17 | });
18 | it('type demo', () => {
19 | const user = {};
20 | user.should.be.type('object');
21 | 'test'.should.be.type('string');
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/Section-3/3.3/math.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | sum(a, b) {
3 | return a + b;
4 | }
5 | };
6 |
--------------------------------------------------------------------------------
/Section-3/3.3/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "test": "jest --watchAll"
8 | },
9 | "directories": {
10 | "test": "tests"
11 | },
12 | "devDependencies": {
13 | "chai": "^4.2.0",
14 | "jest": "^23.6.0"
15 | },
16 | "dependencies": {
17 | "should": "^13.2.3"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Section-3/3.3/tests/assert-demo.test.js:
--------------------------------------------------------------------------------
1 | const assert = require('assert');
2 | describe('Assert library', () => {
3 | it('assert() demo', () => {
4 | assert(100 > 70, 'Expected value is not greater than received value');
5 | });
6 | //If two objects, or their child objects, are not equal, an error is thrown and the program is terminated:
7 | it('deepEqual() demo', () => {
8 | let x = { a: { n: 0 } };
9 | let y = { a: { n: 0 } };
10 | let z = { a: { n: 0 } };
11 | assert.deepEqual(x, y); //OK
12 | assert.deepEqual(
13 | x,
14 | z
15 | ); /*AssertionError: { a: { n: 0 } } deepEqual {a: { n: 1 } }*/
16 | });
17 | //If two values are not equal, an error is thrown and the program is terminated:
18 | it('equal() demo', () => {
19 | assert.equal(50, 50); //OK
20 | assert.equal(50, '50'); //OK
21 | assert.equal(50, 50); /*AssertionError: 50 == 70 */
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/Section-3/3.3/tests/chai.js-demo.test.js:
--------------------------------------------------------------------------------
1 | const assert = require('chai').assert;
2 | const expect = require('chai').expect;
3 | const should = require('chai').should(); //actually call the function
4 | describe('chai assetion library', () => {
5 | it('assert with chai demo', () => {
6 | let foo = 'bar',
7 | beverages = { tea: ['chai', 'matcha', 'oolong'] };
8 | assert.typeOf(foo, 'string'); // without optional message
9 | assert.typeOf(foo, 'string', 'foo is a string'); // with optional message
10 | assert.equal(foo, 'bar', 'foo equal `bar`');
11 | assert.lengthOf(foo, 3, 'foo`s value has a length of 3');
12 | assert.lengthOf(beverages.tea, 3, 'beverages has 3 types of tea');
13 | });
14 | it('expect with chai', () => {
15 | const foo = 'bar',
16 | beverages = { tea: ['chai', 'matcha', 'oolong'] };
17 |
18 | expect(foo).to.be.a('string');
19 | expect(foo).to.equal('bar');
20 | expect(foo).to.have.lengthOf(3);
21 | expect(beverages)
22 | .to.have.property('tea')
23 | .with.lengthOf(3);
24 | });
25 |
26 | it('should with chai.js', () => {
27 | const foo = 'bar',
28 | beverages = { tea: ['chai', 'matcha', 'oolong'] };
29 |
30 | foo.should.be.a('string');
31 | foo.should.equal('bar');
32 | foo.should.have.lengthOf(3);
33 | beverages.should.have.property('tea').with.lengthOf(3);
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/Section-3/3.3/tests/expect-demo.test.js:
--------------------------------------------------------------------------------
1 | describe('Expect Assertion library', () => {
2 | it('toBe Demo', () => {
3 | expect(2 + 2).toBe(4);
4 | });
5 | it('toEqual demo', () => {
6 | const data = { one: 1 };
7 | data['two'] = 2;
8 | expect(data).toEqual({ one: 1, two: 2 });
9 | });
10 |
11 | it('truthiness', () => {
12 | const z = 0;
13 | expect(z).not.toBeNull();
14 | expect(z).toBeDefined();
15 | expect(z).not.toBeUndefined();
16 | expect(z).not.toBeTruthy();
17 | expect(z).toBeFalsy();
18 | });
19 |
20 | it('toContain demo', () => {
21 | const shoppingList = [
22 | 'diapers',
23 | 'kleenex',
24 | 'trash bags',
25 | 'paper towels',
26 | 'beer'
27 | ];
28 | expect(shoppingList).toContain('beer');
29 | });
30 |
31 | it('toMatch Demo', () => {
32 | expect('Christoph').toMatch(/stop/);
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/Section-3/3.3/tests/should.js-demo.test.js:
--------------------------------------------------------------------------------
1 | //docs https://github.com/tj/should.js/
2 | const { sum } = require('../math');
3 | const should = require('should');
4 | describe('Should.js', () => {
5 | it('should return 4 when the input number are 1 and 3', function() {
6 | sum(1, 3).should.be.exactly(4);
7 | sum(1, 3).should.be.exactly(4).and.be.a.Number;
8 | });
9 | it('startWith demo', () => {
10 | 'foobar'.should.startWith('foo');
11 | 'foobar'.should.not.startWith('bar');
12 | });
13 | it('above and greaterThan demo', () => {
14 | const user = { age: 20 };
15 | user.age.should.be.above(5);
16 | user.age.should.not.be.above(100);
17 | });
18 | it('type demo', () => {
19 | const user = {};
20 | user.should.be.type('object');
21 | 'test'.should.be.type('string');
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/Section-3/3.4/math.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | sum(a, b) {
3 | return a + b;
4 | }
5 | };
6 |
--------------------------------------------------------------------------------
/Section-3/3.4/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "first-unit-test",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "test": "jest --watchAll"
8 | },
9 | "directories": {
10 | "test": "tests"
11 | },
12 | "devDependencies": {
13 | "chai": "^4.2.0",
14 | "jest": "^23.6.0"
15 | },
16 | "dependencies": {
17 | "should": "^13.2.3"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Section-3/3.4/tests/assert-demo.test.js:
--------------------------------------------------------------------------------
1 | const assert = require('assert');
2 | describe('Assert library', () => {
3 | it('assert() demo', () => {
4 | assert(100 > 70, 'Expected value is not greater than received value');
5 | });
6 | //If two objects, or their child objects, are not equal, an error is thrown and the program is terminated:
7 | it('deepEqual() demo', () => {
8 | let x = { a: { n: 0 } };
9 | let y = { a: { n: 0 } };
10 | let z = { a: { n: 0 } };
11 | assert.deepEqual(x, y); //OK
12 | assert.deepEqual(
13 | x,
14 | z
15 | ); /*AssertionError: { a: { n: 0 } } deepEqual {a: { n: 1 } }*/
16 | });
17 | //If two values are not equal, an error is thrown and the program is terminated:
18 | it('equal() demo', () => {
19 | assert.equal(50, 50); //OK
20 | assert.equal(50, '50'); //OK
21 | assert.equal(50, 50); /*AssertionError: 50 == 70 */
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/Section-3/3.4/tests/chai.js-demo.test.js:
--------------------------------------------------------------------------------
1 | const assert = require('chai').assert;
2 | const expect = require('chai').expect;
3 | const should = require('chai').should(); //actually call the function
4 | describe('chai assetion library', () => {
5 | it('assert with chai demo', () => {
6 | let foo = 'bar',
7 | beverages = { tea: ['chai', 'matcha', 'oolong'] };
8 | assert.typeOf(foo, 'string'); // without optional message
9 | assert.typeOf(foo, 'string', 'foo is a string'); // with optional message
10 | assert.equal(foo, 'bar', 'foo equal `bar`');
11 | assert.lengthOf(foo, 3, 'foo`s value has a length of 3');
12 | assert.lengthOf(beverages.tea, 3, 'beverages has 3 types of tea');
13 | });
14 | it('expect with chai', () => {
15 | const foo = 'bar',
16 | beverages = { tea: ['chai', 'matcha', 'oolong'] };
17 |
18 | expect(foo).to.be.a('string');
19 | expect(foo).to.equal('bar');
20 | expect(foo).to.have.lengthOf(3);
21 | expect(beverages)
22 | .to.have.property('tea')
23 | .with.lengthOf(3);
24 | });
25 |
26 | it('should with chai.js', () => {
27 | const foo = 'bar',
28 | beverages = { tea: ['chai', 'matcha', 'oolong'] };
29 |
30 | foo.should.be.a('string');
31 | foo.should.equal('bar');
32 | foo.should.have.lengthOf(3);
33 | beverages.should.have.property('tea').with.lengthOf(3);
34 | });
35 | });
36 |
--------------------------------------------------------------------------------
/Section-3/3.4/tests/expect-demo.test.js:
--------------------------------------------------------------------------------
1 | describe('Expect Assertion library', () => {
2 | it('toBe Demo', () => {
3 | expect(2 + 2).toBe(4);
4 | });
5 | it('toEqual demo', () => {
6 | const data = { one: 1 };
7 | data['two'] = 2;
8 | expect(data).toEqual({ one: 1, two: 2 });
9 | });
10 |
11 | it('truthiness', () => {
12 | const z = 0;
13 | expect(z).not.toBeNull();
14 | expect(z).toBeDefined();
15 | expect(z).not.toBeUndefined();
16 | expect(z).not.toBeTruthy();
17 | expect(z).toBeFalsy();
18 | });
19 |
20 | it('toContain demo', () => {
21 | const shoppingList = [
22 | 'diapers',
23 | 'kleenex',
24 | 'trash bags',
25 | 'paper towels',
26 | 'beer'
27 | ];
28 | expect(shoppingList).toContain('beer');
29 | });
30 |
31 | it('toMatch Demo', () => {
32 | expect('Christoph').toMatch(/stop/);
33 | });
34 | });
35 |
--------------------------------------------------------------------------------
/Section-3/3.4/tests/should.js-demo.test.js:
--------------------------------------------------------------------------------
1 | //docs https://github.com/tj/should.js/
2 | const { sum } = require('../math');
3 | const should = require('should');
4 | describe('Should.js', () => {
5 | it('should return 4 when the input number are 1 and 3', function() {
6 | sum(1, 3).should.be.exactly(4);
7 | sum(1, 3).should.be.exactly(4).and.be.a.Number;
8 | });
9 | it('startWith demo', () => {
10 | 'foobar'.should.startWith('foo');
11 | 'foobar'.should.not.startWith('bar');
12 | });
13 | it('above and greaterThan demo', () => {
14 | const user = { age: 20 };
15 | user.age.should.be.above(5);
16 | user.age.should.not.be.above(100);
17 | });
18 | it('type demo', () => {
19 | const user = {};
20 | user.should.be.type('object');
21 | 'test'.should.be.type('string');
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/Section-4/4.1/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jasmine-demo",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "balanced-match": {
8 | "version": "1.0.0",
9 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
10 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
11 | "dev": true
12 | },
13 | "brace-expansion": {
14 | "version": "1.1.11",
15 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
16 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
17 | "dev": true,
18 | "requires": {
19 | "balanced-match": "^1.0.0",
20 | "concat-map": "0.0.1"
21 | }
22 | },
23 | "concat-map": {
24 | "version": "0.0.1",
25 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
26 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
27 | "dev": true
28 | },
29 | "fs.realpath": {
30 | "version": "1.0.0",
31 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
32 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
33 | "dev": true
34 | },
35 | "glob": {
36 | "version": "7.1.3",
37 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
38 | "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
39 | "dev": true,
40 | "requires": {
41 | "fs.realpath": "^1.0.0",
42 | "inflight": "^1.0.4",
43 | "inherits": "2",
44 | "minimatch": "^3.0.4",
45 | "once": "^1.3.0",
46 | "path-is-absolute": "^1.0.0"
47 | }
48 | },
49 | "inflight": {
50 | "version": "1.0.6",
51 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
52 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
53 | "dev": true,
54 | "requires": {
55 | "once": "^1.3.0",
56 | "wrappy": "1"
57 | }
58 | },
59 | "inherits": {
60 | "version": "2.0.3",
61 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
62 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
63 | "dev": true
64 | },
65 | "jasmine": {
66 | "version": "3.3.1",
67 | "resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.3.1.tgz",
68 | "integrity": "sha512-/vU3/H7U56XsxIXHwgEuWpCgQ0bRi2iiZeUpx7Nqo8n1TpoDHfZhkPIc7CO8I4pnMzYsi3XaSZEiy8cnTfujng==",
69 | "dev": true,
70 | "requires": {
71 | "glob": "^7.0.6",
72 | "jasmine-core": "~3.3.0"
73 | }
74 | },
75 | "jasmine-core": {
76 | "version": "3.3.0",
77 | "resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.3.0.tgz",
78 | "integrity": "sha512-3/xSmG/d35hf80BEN66Y6g9Ca5l/Isdeg/j6zvbTYlTzeKinzmaTM4p9am5kYqOmE05D7s1t8FGjzdSnbUbceA==",
79 | "dev": true
80 | },
81 | "minimatch": {
82 | "version": "3.0.4",
83 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
84 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
85 | "dev": true,
86 | "requires": {
87 | "brace-expansion": "^1.1.7"
88 | }
89 | },
90 | "once": {
91 | "version": "1.4.0",
92 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
93 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
94 | "dev": true,
95 | "requires": {
96 | "wrappy": "1"
97 | }
98 | },
99 | "path-is-absolute": {
100 | "version": "1.0.1",
101 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
102 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
103 | "dev": true
104 | },
105 | "wrappy": {
106 | "version": "1.0.2",
107 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
108 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
109 | "dev": true
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/Section-4/4.1/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jasmine-demo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "jasmine"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "jasmine": "^3.3.1"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Section-4/4.1/spec/math.spec.js:
--------------------------------------------------------------------------------
1 | describe('A suite', function() {
2 | it('contains spec with an expectation', function() {
3 | expect(true).toBe(true);
4 | });
5 | });
6 |
--------------------------------------------------------------------------------
/Section-4/4.1/spec/support/jasmine.json:
--------------------------------------------------------------------------------
1 | {
2 | "spec_dir": "spec",
3 | "spec_files": [
4 | "**/*[sS]pec.js"
5 | ],
6 | "helpers": [
7 | "helpers/**/*.js"
8 | ],
9 | "stopSpecOnExpectationFailure": false,
10 | "random": true
11 | }
12 |
--------------------------------------------------------------------------------
/Section-4/4.2/math.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | async add(a, b) {
3 | return Promise.resolve(a + b);
4 | }
5 | };
6 |
--------------------------------------------------------------------------------
/Section-4/4.2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "mocha-demo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "./node_modules/mocha/bin/mocha"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "chai": "^4.2.0",
14 | "mocha": "^6.0.2"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Section-4/4.2/test/db.js:
--------------------------------------------------------------------------------
1 | // const expect = require('chai').expect;
2 | // const Sequelize = require('sequelize');
3 |
4 | // describe('users', () => {
5 | // let database;
6 | // let User;
7 |
8 | // // runs before all tests in this block
9 | // before(async () => {
10 | // database = new Sequelize('postgresql://localhost/app_test', {
11 | // logging: false
12 | // });
13 | // User = database.define('user', {
14 | // username: Sequelize.STRING,
15 | // birthday: Sequelize.DATE
16 | // });
17 | // });
18 |
19 | // // runs before each test in this block
20 | // beforeEach(async () => {
21 | // await User.sync();
22 | // await User.create({
23 | // username: 'zaiste',
24 | // birthday: new Date(1988, 1, 21)
25 | // });
26 | // });
27 |
28 | // // runs after each test in this block
29 | // afterEach(async () => {
30 | // await User.drop();
31 | // });
32 |
33 | // describe('#find()', () => {
34 | // it('should find a user', async () => {
35 | // const user = await User.findOne({ where: { username: 'zaiste' } });
36 | // expect(user).to.be.a('object');
37 | // expect(user).to.have.property('username');
38 | // expect(user).to.have.property('birthday');
39 | // expect(user.username).to.equal('zaiste');
40 | // });
41 | // });
42 | // });
43 |
--------------------------------------------------------------------------------
/Section-4/4.2/test/test.js:
--------------------------------------------------------------------------------
1 | const assert = require('chai').assert;
2 | const expect = require('chai').expect;
3 | const should = require('chai').should();
4 | const { add } = require('../math');
5 | describe('Mocha demo', () => {
6 | it('assert demo', () => {
7 | const numbers = [1, 2, 3, 4, 5];
8 | assert.isArray(numbers, 'is array of numbers');
9 | assert.include(numbers, 1, 'array contains 2');
10 | assert.lengthOf(numbers, 5, 'array contains 5 numbers');
11 | });
12 | it('expect style', () => {
13 | const numbers = [1, 2, 3, 4, 5];
14 | expect(numbers)
15 | .to.be.an('array')
16 | .that.includes(2);
17 | expect(numbers).to.have.lengthOf(5);
18 | });
19 | it('should style', () => {
20 | const numbers = [1, 2, 3, 4, 5];
21 | numbers.should.be.an('array').that.includes(2);
22 | numbers.should.have.lengthOf(5);
23 | });
24 | });
25 | describe('#add()', () => {
26 | it('2 + 2 is 4', async () => {
27 | const p = await add(2, 2);
28 | expect(p).to.equal(4);
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/Section-4/4.3/data.txt:
--------------------------------------------------------------------------------
1 | Hellow orld
--------------------------------------------------------------------------------
/Section-4/4.3/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ava-demo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "node_modules/.bin/ava tests/**/*.test.js --verbose"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "ava": "^1.3.1"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Section-4/4.3/tests/math.test.js:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | const fs = require('fs');
3 |
4 | //Running tests serially
5 | test('foo', t => {
6 | t.pass();
7 | });
8 |
9 | test('bar', async t => {
10 | const bar = Promise.resolve('bar');
11 | t.is(await bar, 'bar');
12 | });
13 |
14 | const getValue = () => {
15 | return new Promise(resolve => {
16 | return resolve(true);
17 | });
18 | };
19 | test('promises the truth', async t => {
20 | const value = await getValue();
21 | t.true(value);
22 | });
23 |
24 | test.cb('data.txt can be read', t => {
25 | // `t.end` automatically checks for error as first argument
26 | fs.readFile('data.txt', t.end);
27 | });
28 | test.failing('demonstrate some bug', t => {
29 | t.fail(); // Test will count as passed
30 | });
31 |
--------------------------------------------------------------------------------
/Section-4/4.4/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tape-demo",
3 | "version": "1.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "balanced-match": {
8 | "version": "1.0.0",
9 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
10 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
11 | "dev": true
12 | },
13 | "brace-expansion": {
14 | "version": "1.1.11",
15 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
16 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
17 | "dev": true,
18 | "requires": {
19 | "balanced-match": "^1.0.0",
20 | "concat-map": "0.0.1"
21 | }
22 | },
23 | "concat-map": {
24 | "version": "0.0.1",
25 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
26 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
27 | "dev": true
28 | },
29 | "deep-equal": {
30 | "version": "1.0.1",
31 | "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
32 | "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=",
33 | "dev": true
34 | },
35 | "define-properties": {
36 | "version": "1.1.3",
37 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
38 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
39 | "dev": true,
40 | "requires": {
41 | "object-keys": "^1.0.12"
42 | }
43 | },
44 | "defined": {
45 | "version": "1.0.0",
46 | "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
47 | "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM=",
48 | "dev": true
49 | },
50 | "es-abstract": {
51 | "version": "1.13.0",
52 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
53 | "integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
54 | "dev": true,
55 | "requires": {
56 | "es-to-primitive": "^1.2.0",
57 | "function-bind": "^1.1.1",
58 | "has": "^1.0.3",
59 | "is-callable": "^1.1.4",
60 | "is-regex": "^1.0.4",
61 | "object-keys": "^1.0.12"
62 | }
63 | },
64 | "es-to-primitive": {
65 | "version": "1.2.0",
66 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
67 | "integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
68 | "dev": true,
69 | "requires": {
70 | "is-callable": "^1.1.4",
71 | "is-date-object": "^1.0.1",
72 | "is-symbol": "^1.0.2"
73 | }
74 | },
75 | "for-each": {
76 | "version": "0.3.3",
77 | "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
78 | "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
79 | "dev": true,
80 | "requires": {
81 | "is-callable": "^1.1.3"
82 | }
83 | },
84 | "fs.realpath": {
85 | "version": "1.0.0",
86 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
87 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
88 | "dev": true
89 | },
90 | "function-bind": {
91 | "version": "1.1.1",
92 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
93 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
94 | "dev": true
95 | },
96 | "glob": {
97 | "version": "7.1.3",
98 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz",
99 | "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==",
100 | "dev": true,
101 | "requires": {
102 | "fs.realpath": "^1.0.0",
103 | "inflight": "^1.0.4",
104 | "inherits": "2",
105 | "minimatch": "^3.0.4",
106 | "once": "^1.3.0",
107 | "path-is-absolute": "^1.0.0"
108 | }
109 | },
110 | "has": {
111 | "version": "1.0.3",
112 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
113 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
114 | "dev": true,
115 | "requires": {
116 | "function-bind": "^1.1.1"
117 | }
118 | },
119 | "has-symbols": {
120 | "version": "1.0.0",
121 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
122 | "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
123 | "dev": true
124 | },
125 | "inflight": {
126 | "version": "1.0.6",
127 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
128 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
129 | "dev": true,
130 | "requires": {
131 | "once": "^1.3.0",
132 | "wrappy": "1"
133 | }
134 | },
135 | "inherits": {
136 | "version": "2.0.3",
137 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
138 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
139 | "dev": true
140 | },
141 | "is-callable": {
142 | "version": "1.1.4",
143 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
144 | "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
145 | "dev": true
146 | },
147 | "is-date-object": {
148 | "version": "1.0.1",
149 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
150 | "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
151 | "dev": true
152 | },
153 | "is-regex": {
154 | "version": "1.0.4",
155 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
156 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
157 | "dev": true,
158 | "requires": {
159 | "has": "^1.0.1"
160 | }
161 | },
162 | "is-symbol": {
163 | "version": "1.0.2",
164 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
165 | "integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
166 | "dev": true,
167 | "requires": {
168 | "has-symbols": "^1.0.0"
169 | }
170 | },
171 | "minimatch": {
172 | "version": "3.0.4",
173 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
174 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
175 | "dev": true,
176 | "requires": {
177 | "brace-expansion": "^1.1.7"
178 | }
179 | },
180 | "minimist": {
181 | "version": "1.2.0",
182 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
183 | "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
184 | "dev": true
185 | },
186 | "object-inspect": {
187 | "version": "1.6.0",
188 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.6.0.tgz",
189 | "integrity": "sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ==",
190 | "dev": true
191 | },
192 | "object-keys": {
193 | "version": "1.1.0",
194 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.0.tgz",
195 | "integrity": "sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==",
196 | "dev": true
197 | },
198 | "once": {
199 | "version": "1.4.0",
200 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
201 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
202 | "dev": true,
203 | "requires": {
204 | "wrappy": "1"
205 | }
206 | },
207 | "path-is-absolute": {
208 | "version": "1.0.1",
209 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
210 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
211 | "dev": true
212 | },
213 | "path-parse": {
214 | "version": "1.0.6",
215 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
216 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
217 | "dev": true
218 | },
219 | "resolve": {
220 | "version": "1.10.0",
221 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.10.0.tgz",
222 | "integrity": "sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg==",
223 | "dev": true,
224 | "requires": {
225 | "path-parse": "^1.0.6"
226 | }
227 | },
228 | "resumer": {
229 | "version": "0.0.0",
230 | "resolved": "https://registry.npmjs.org/resumer/-/resumer-0.0.0.tgz",
231 | "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=",
232 | "dev": true,
233 | "requires": {
234 | "through": "~2.3.4"
235 | }
236 | },
237 | "string.prototype.trim": {
238 | "version": "1.1.2",
239 | "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz",
240 | "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
241 | "dev": true,
242 | "requires": {
243 | "define-properties": "^1.1.2",
244 | "es-abstract": "^1.5.0",
245 | "function-bind": "^1.0.2"
246 | }
247 | },
248 | "tape": {
249 | "version": "4.10.1",
250 | "resolved": "https://registry.npmjs.org/tape/-/tape-4.10.1.tgz",
251 | "integrity": "sha512-G0DywYV1jQeY3axeYnXUOt6ktnxS9OPJh97FGR3nrua8lhWi1zPflLxcAHavZ7Jf3qUfY7cxcVIVFa4mY2IY1w==",
252 | "dev": true,
253 | "requires": {
254 | "deep-equal": "~1.0.1",
255 | "defined": "~1.0.0",
256 | "for-each": "~0.3.3",
257 | "function-bind": "~1.1.1",
258 | "glob": "~7.1.3",
259 | "has": "~1.0.3",
260 | "inherits": "~2.0.3",
261 | "minimist": "~1.2.0",
262 | "object-inspect": "~1.6.0",
263 | "resolve": "~1.10.0",
264 | "resumer": "~0.0.0",
265 | "string.prototype.trim": "~1.1.2",
266 | "through": "~2.3.8"
267 | }
268 | },
269 | "through": {
270 | "version": "2.3.8",
271 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
272 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=",
273 | "dev": true
274 | },
275 | "wrappy": {
276 | "version": "1.0.2",
277 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
278 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
279 | "dev": true
280 | }
281 | }
282 | }
283 |
--------------------------------------------------------------------------------
/Section-4/4.4/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "tape-demo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "node_modules/.bin/tape tests/**/*.js"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "tape": "^4.10.1"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/Section-4/4.4/tests/test.js:
--------------------------------------------------------------------------------
1 | const test = require('tape');
2 |
3 | test('A passing test', assert => {
4 | assert.pass('This test will pass.');
5 | assert.end();
6 | });
7 | test('Assertions with tape.', assert => {
8 | const expected = 'something to test';
9 | const actual = 'something to test';
10 |
11 | assert.equal(
12 | actual,
13 | expected,
14 | 'Given two mismatched values, .equal() should produce a nice bug report'
15 | );
16 |
17 | assert.end();
18 | });
19 | test('My first test', function(assert) {
20 | assert.equal(1, 1, 'Numbers 1 and 2 are the same');
21 | assert.end();
22 | });
23 |
--------------------------------------------------------------------------------
/Section-4/4.5/intern.json:
--------------------------------------------------------------------------------
1 | {
2 | "suites": "tests/unit/**/*.js"
3 | }
4 |
--------------------------------------------------------------------------------
/Section-4/4.5/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "intern-demo",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "dependencies": {
7 | "intern": "^4.4.2"
8 | },
9 | "devDependencies": {},
10 | "scripts": {
11 | "test": "./node_modules/.bin/intern"
12 | },
13 | "keywords": [],
14 | "author": "",
15 | "license": "ISC"
16 | }
17 |
--------------------------------------------------------------------------------
/Section-4/4.5/tests/unit/test.js:
--------------------------------------------------------------------------------
1 | const { suite, test } = intern.getInterface('tdd');
2 | const { assert } = intern.getPlugin('chai');
3 |
4 | suite('app', () => {
5 | test('print', () => {
6 | const result = 'Smith';
7 | assert.equal(result, 'Smith');
8 | });
9 | });
10 |
--------------------------------------------------------------------------------
/Section-5/config-overrides.js:
--------------------------------------------------------------------------------
1 | const { injectBabelPlugin } = require("react-app-rewired");
2 | const rewireMobX = require("react-app-rewire-mobx");
3 |
4 | module.exports = function override(config, env) {
5 | config = injectBabelPlugin("babel-plugin-styled-components", config);
6 | config = rewireMobX(config, env);
7 |
8 | return config;
9 | };
10 |
--------------------------------------------------------------------------------
/Section-5/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "jesttestingasync",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "axios": "^0.18.0",
7 | "babel-plugin-styled-components": "^1.5.1",
8 | "concurrently": "^3.5.1",
9 | "react": "^16.2.0",
10 | "react-app-rewire-mobx": "^1.0.7",
11 | "react-app-rewired": "^1.5.0",
12 | "react-dom": "^16.2.0"
13 | },
14 | "devDependencies": {
15 | "react-scripts": "1.1.1",
16 | "enzyme": "^3.3.0",
17 | "enzyme-adapter-react-16": "^1.1.1",
18 | "enzyme-to-json": "^3.3.3",
19 | "sinon": "^4.4.9"
20 | },
21 | "scripts": {
22 | "start": "react-app-rewired start",
23 | "build": "react-app-rewired build",
24 | "test": "react-app-rewired test --env=jsdom",
25 | "eject": "react-app-rewired eject",
26 | "watch": "concurrently --prefix \"[{name}]\" --names \"REACT,SASS\" -c \"bgBlue.bold,bgMagenta.bold\" \"yarn run start\" \"yarn run watch-styles\"",
27 | "watch-styles": "sass --watch src/css/styles.scss:src/css/styles.css"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Section-5/src/__mocks__/axios.js:
--------------------------------------------------------------------------------
1 | export default {
2 | get: jest.fn(() => Promise.resolve({ data: {} }))
3 | };
4 |
--------------------------------------------------------------------------------
/Section-5/src/services/__tests__/posts.js:
--------------------------------------------------------------------------------
1 | import mockAxios from 'axios';
2 | import getPosts from '../posts';
3 |
4 | it('calls axios and returns posts', async () => {
5 | // setup
6 | mockAxios.get.mockImplementationOnce(() =>
7 | Promise.resolve({
8 | data: {
9 | results: [
10 | {
11 | userId: 1,
12 | id: 1,
13 | title:
14 | 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit',
15 | body:
16 | 'quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto'
17 | }
18 | ]
19 | }
20 | })
21 | );
22 |
23 | // work
24 | const posts = await getPosts();
25 |
26 | // assertions / expects
27 | expect(posts).toEqual([
28 | {
29 | userId: 1,
30 | id: 1,
31 | title:
32 | 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit',
33 | body:
34 | 'quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto'
35 | }
36 | ]);
37 | expect(mockAxios.get).toHaveBeenCalledTimes(1);
38 | expect(mockAxios.get).toHaveBeenCalledWith(
39 | 'https://jsonplaceholder.typicode.com/posts'
40 | );
41 | });
42 |
--------------------------------------------------------------------------------
/Section-5/src/services/__tests__/users.js:
--------------------------------------------------------------------------------
1 | import mockAxios from 'axios';
2 | import getUsers from '../users';
3 |
4 | it('calls axios and returns users', async () => {
5 | // setup
6 | mockAxios.get.mockImplementationOnce(() =>
7 | Promise.resolve({
8 | data: {
9 | results: [
10 | {
11 | id: 1,
12 | name: 'Leanne Graham',
13 | username: 'Bret',
14 | email: 'Sincere@april.biz',
15 | address: {
16 | street: 'Kulas Light',
17 | suite: 'Apt. 556',
18 | city: 'Gwenborough',
19 | zipcode: '92998-3874',
20 | geo: {
21 | lat: '-37.3159',
22 | lng: '81.1496'
23 | }
24 | },
25 | phone: '1-770-736-8031 x56442',
26 | website: 'hildegard.org',
27 | company: {
28 | name: 'Romaguera-Crona',
29 | catchPhrase: 'Multi-layered client-server neural-net',
30 | bs: 'harness real-time e-markets'
31 | }
32 | }
33 | ]
34 | }
35 | })
36 | );
37 |
38 | // work
39 | const users = await getUsers();
40 |
41 | // assertions / expects
42 | expect(users).toEqual([
43 | {
44 | id: 1,
45 | name: 'Leanne Graham',
46 | username: 'Bret',
47 | email: 'Sincere@april.biz',
48 | address: {
49 | street: 'Kulas Light',
50 | suite: 'Apt. 556',
51 | city: 'Gwenborough',
52 | zipcode: '92998-3874',
53 | geo: {
54 | lat: '-37.3159',
55 | lng: '81.1496'
56 | }
57 | },
58 | phone: '1-770-736-8031 x56442',
59 | website: 'hildegard.org',
60 | company: {
61 | name: 'Romaguera-Crona',
62 | catchPhrase: 'Multi-layered client-server neural-net',
63 | bs: 'harness real-time e-markets'
64 | }
65 | }
66 | ]);
67 | expect(mockAxios.get).toHaveBeenCalledTimes(1);
68 | expect(mockAxios.get).toHaveBeenCalledWith(
69 | 'https://jsonplaceholder.typicode.com/users'
70 | );
71 | });
72 |
--------------------------------------------------------------------------------
/Section-5/src/services/posts.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | export default async () => {
4 | const response = await axios.get(
5 | 'https://jsonplaceholder.typicode.com/posts'
6 | );
7 |
8 | return response.data.results;
9 | };
10 |
--------------------------------------------------------------------------------
/Section-5/src/services/users.js:
--------------------------------------------------------------------------------
1 | import axios from 'axios';
2 |
3 | export default async () => {
4 | const response = await axios.get(
5 | 'https://jsonplaceholder.typicode.com/users'
6 | );
7 |
8 | return response.data.results;
9 | };
10 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/**
2 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/01-basic-spec/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /coverage
6 |
7 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/01-basic-spec/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "01",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "mocha"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "mocha": "5.0.1"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/01-basic-spec/test/test.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | describe('Basic Mocha String Test', function () {
3 | it('should return number of charachters in a string', function () {
4 | assert.equal("Hello".length, 5);
5 | });
6 | it('should return first charachter of the string', function () {
7 | assert.equal("Hello".charAt(0), 'H');
8 | //throw {myError:'throwing error to fail test'}
9 | });
10 | });
11 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/02-testing-function/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /coverage
6 |
7 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/02-testing-function/controllers/login.controller.js:
--------------------------------------------------------------------------------
1 | function LoginController() {
2 |
3 | function isValidUserId(userList, user) {
4 | return userList.indexOf(user) >= 0;
5 | }
6 |
7 | return {
8 | isValidUserId
9 | }
10 |
11 | }
12 |
13 | module.exports = LoginController();
14 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/02-testing-function/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "02",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "mocha './test/**/*.spec.js'"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "mocha": "5.0.1"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/02-testing-function/test/controllers/login.controller.spec.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var loginController = require('../../controllers/login.controller');
3 |
4 | describe('LoginController', function () {
5 |
6 | describe('isValidUserId', function(){
7 |
8 | it('should return true if valid user id', function(){
9 | var isValid = loginController.isValidUserId(['abc123','xyz321'], 'abc123')
10 | assert.equal(isValid, true);
11 | });
12 |
13 | it('should return false if invalid user id', function(){
14 | var isValid = loginController.isValidUserId(['abc123','xyz321'],'abc1234')
15 | assert.equal(isValid, false);
16 | });
17 |
18 | });
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/03-async-callback/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /coverage
6 |
7 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/03-async-callback/controllers/login.controller.js:
--------------------------------------------------------------------------------
1 | function LoginController() {
2 |
3 | function isValidUserId(userList, user) {
4 | return userList.indexOf(user) >= 0;
5 | }
6 |
7 | function isValidUserIdAsync(userList, user, callback) {
8 | setTimeout(function(){
9 | callback(userList.indexOf(user) >= 0)
10 | }, 1);
11 | }
12 |
13 | return {
14 | isValidUserId,
15 | isValidUserIdAsync
16 | }
17 |
18 | }
19 |
20 | module.exports = LoginController();
21 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/03-async-callback/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "03",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "mocha './test/**/*.spec.js'"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "mocha": "5.0.1"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/03-async-callback/test/controllers/login.controller.spec.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var loginController = require('../../controllers/login.controller');
3 |
4 | describe('LoginController', function () {
5 |
6 | describe('isValidUserId', function(){
7 |
8 | it('should return true if valid user id', function(){
9 | var isValid = loginController.isValidUserId(['abc123','xyz321'], 'abc123')
10 | assert.equal(isValid, true);
11 | });
12 |
13 | it('should return false if invalid user id', function(){
14 | var isValid = loginController.isValidUserId(['abc123','xyz321'],'abc1234')
15 | assert.equal(isValid, false);
16 | });
17 |
18 | });
19 |
20 | describe('isValidUserIdAsync', function(){
21 |
22 | it('should return true if valid user id', function(done){
23 | loginController.isValidUserIdAsync(['abc123','xyz321'], 'abc123',
24 | function(isValid){
25 | assert.equal(isValid, true);
26 | done();
27 | });
28 | });
29 |
30 | });
31 |
32 | });
33 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/04-hooks/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /coverage
6 |
7 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/04-hooks/controllers/login.controller.js:
--------------------------------------------------------------------------------
1 | function LoginController() {
2 |
3 | var userList;
4 | function loadUserList(users){
5 | userList = users;
6 | }
7 |
8 | function isValidUserId(user) {
9 | return userList.indexOf(user) >= 0;
10 | }
11 |
12 | function isValidUserIdAsync(user, callback) {
13 | setTimeout(function(){
14 | callback(userList.indexOf(user) >= 0)
15 | }, 1);
16 | }
17 |
18 | return {
19 | isValidUserId,
20 | isValidUserIdAsync,
21 | loadUserList
22 | }
23 |
24 | }
25 |
26 | module.exports = LoginController();
27 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/04-hooks/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "04",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "mocha './test/**/*.spec.js'"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "mocha": "5.0.1"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/04-hooks/test/controllers/login.controller.spec.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var loginController = require('../../controllers/login.controller');
3 |
4 | beforeEach('Setting up the userList', function(){
5 | console.log('beforeEach');
6 | loginController.loadUserList(['abc123','xyz321']);
7 | //throw {error: 'Thrwoing Error to fail'}
8 | });
9 |
10 | describe('LoginController', function () {
11 |
12 | describe('isValidUserId', function(){
13 |
14 | it('should return true if valid user id', function(){
15 | var isValid = loginController.isValidUserId('abc123')
16 | assert.equal(isValid, true);
17 | });
18 |
19 | it('should return false if invalid user id', function(){
20 | var isValid = loginController.isValidUserId('abc1234')
21 | assert.equal(isValid, false);
22 | });
23 |
24 | });
25 |
26 | describe('isValidUserIdAsync', function(){
27 |
28 | it('should return true if valid user id', function(done){
29 | loginController.isValidUserIdAsync('abc123',
30 | function(isValid){
31 | assert.equal(isValid, true);
32 | done();
33 | });
34 | });
35 |
36 | });
37 |
38 | });
39 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/05-expect-should/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /coverage
6 |
7 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/05-expect-should/controllers/login.controller.js:
--------------------------------------------------------------------------------
1 | function LoginController() {
2 |
3 | var userList;
4 | function loadUserList(users){
5 | userList = users;
6 | }
7 |
8 | function isValidUserId(user) {
9 | return userList.indexOf(user) >= 0;
10 | }
11 |
12 | function isValidUserIdAsync(user, callback) {
13 | setTimeout(function(){
14 | callback(userList.indexOf(user) >= 0)
15 | }, 1);
16 | }
17 |
18 | return {
19 | isValidUserId,
20 | isValidUserIdAsync,
21 | loadUserList
22 | }
23 |
24 | }
25 |
26 | module.exports = LoginController();
27 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/05-expect-should/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "05",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "mocha './test/**/*.spec.js'"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "chai": "4.1.2",
13 | "mocha": "5.0.1"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/05-expect-should/test/controllers/login.controller.spec.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var loginController = require('../../controllers/login.controller');
3 |
4 | var expect = require('chai').expect;
5 | var should = require('chai').should();
6 |
7 | beforeEach('Setting up the userList', function(){
8 | console.log('beforeEach');
9 | loginController.loadUserList(['abc123','xyz321']);
10 | });
11 |
12 | describe('LoginController', function () {
13 |
14 | describe('isValidUserId', function(){
15 |
16 | it('should return true if valid user id', function(){
17 | var isValid = loginController.isValidUserId('abc123')
18 | //assert.equal(isValid, true);
19 | expect(isValid).to.be.true;
20 | });
21 |
22 | it('should return false if invalid user id', function(){
23 | var isValid = loginController.isValidUserId('abc1234')
24 | //assert.equal(isValid, false);
25 | isValid.should.equal(false);
26 | });
27 |
28 | });
29 |
30 | describe('isValidUserIdAsync', function(){
31 |
32 | it('should return true if valid user id', function(done){
33 | loginController.isValidUserIdAsync('abc123',
34 | function(isValid){
35 | //assert.equal(isValid, true);
36 | isValid.should.equal(true);
37 | done();
38 | });
39 | });
40 |
41 | });
42 |
43 | });
44 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/06-promise/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /coverage
6 |
7 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/06-promise/controllers/login.controller.js:
--------------------------------------------------------------------------------
1 | function LoginController() {
2 |
3 | var userList;
4 | function loadUserList(users){
5 | userList = users;
6 | }
7 |
8 | function isValidUserId(user) {
9 | return userList.indexOf(user) >= 0;
10 | }
11 |
12 | function isValidUserIdAsync(user, callback) {
13 | setTimeout(function(){
14 | callback(userList.indexOf(user) >= 0)
15 | }, 1);
16 | }
17 |
18 | function isAuthorizedPromise(user){
19 | return new Promise(function(resolve){
20 | setTimeout(function(){resolve(userList.indexOf(user) >= 0)}, 10);
21 | });
22 | }
23 |
24 | return {
25 | isValidUserId,
26 | isValidUserIdAsync,
27 | loadUserList,
28 | isAuthorizedPromise
29 | }
30 |
31 | }
32 |
33 | module.exports = LoginController();
34 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/06-promise/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "06",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "mocha './test/**/*.spec.js'"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "chai": "4.1.2",
13 | "chai-as-promised": "7.1.1",
14 | "mocha": "5.0.1"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/06-promise/test/controllers/login.controller.spec.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | var loginController = require('../../controllers/login.controller');
3 |
4 | var expect = require('chai').expect;
5 | var should = require('chai').should();
6 |
7 | var chai = require('chai');
8 | var chaiAsPromised = require('chai-as-promised');
9 | chai.use(chaiAsPromised).should();
10 |
11 | beforeEach('Setting up the userList', function(){
12 | console.log('beforeEach');
13 | loginController.loadUserList(['abc123','xyz321']);
14 | });
15 |
16 | describe('LoginController', function () {
17 |
18 | describe('isValidUserId', function(){
19 |
20 | it('should return true if valid user id', function(){
21 | var isValid = loginController.isValidUserId('abc123')
22 | //assert.equal(isValid, true);
23 | expect(isValid).to.be.true;
24 | });
25 |
26 | it('should return false if invalid user id', function(){
27 | var isValid = loginController.isValidUserId('abc1234')
28 | //assert.equal(isValid, false);
29 | isValid.should.equal(false);
30 | });
31 |
32 | });
33 |
34 | describe('isValidUserIdAsync', function(){
35 |
36 | it('should return true if valid user id', function(done){
37 | loginController.isValidUserIdAsync('abc123',
38 | function(isValid){
39 | //assert.equal(isValid, true);
40 | isValid.should.equal(true);
41 | done();
42 | });
43 | });
44 |
45 | });
46 |
47 | describe('isAuthorizedPromise', function(){
48 |
49 | it('should return true if valid user id', function(){
50 | return loginController.isAuthorizedPromise('abc123').should.eventually.be.true;
51 | });
52 |
53 | });
54 | });
55 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/07-chai-assertion/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /coverage
6 |
7 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/07-chai-assertion/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "07",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "mocha"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "chai": "4.2.0",
13 | "chai-as-promised": "^7.1.1",
14 | "mocha": "5.0.1"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/07-chai-assertion/test/test.js:
--------------------------------------------------------------------------------
1 |
2 | var assert = require('assert');
3 | var should = require('chai').should();
4 |
5 | describe('Object Test', function(){
6 | it('should have property name', function(){
7 | var car = {name:'Figo', Maker:'Ford'}
8 |
9 | car.should.have.property('name');
10 | });
11 |
12 | it('should have property name with value Figo', function(){
13 | var car = {name:'Figo', Maker:'Ford'}
14 | car.should.have.property('name').equal('Figo');
15 | });
16 |
17 | it('should compare objects', function(){
18 | var car = {name:'Figo', Maker:'Ford'}
19 | var car1 = {name:'Figo', Maker:'Ford'}
20 |
21 | // car.should.equal(car1);
22 | car.should.deep.equal(car1);
23 | });
24 |
25 | it('handling null', function(){
26 | var car = null;
27 | //car.should.not.exist;
28 | should.not.exist(car);
29 | });
30 | });
31 |
--------------------------------------------------------------------------------
/javascript-unit-testing-with-mocha/README.md:
--------------------------------------------------------------------------------
1 | ## Javascript Unit Testing with Mocha
2 | code about JavaScript Unit test with Mocha, Chai, Sinon
3 |
4 | ### Setup
5 | * Install [Nodejs](http://nodejs.org) >= v6.10.3
6 | * Install Mocha by running the command `$ npm install --global mocha`
7 | * Clone this Project and navigate to the javascript-unit-testing-with-mocha/xx directory in command line (xx is like 01)
8 | * Run `npm install` to install all dependencies from package.json
9 | * Run `npm test` to run all test specs.
10 | OR
11 | * RUN `bash src/bash/install-n-run-them-all.sh`
12 |
--------------------------------------------------------------------------------
/js-unit-test-examples/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | node_modules
31 | jspm_packages
32 |
33 | # Optional npm cache directory
34 | .npm
35 |
36 | # Optional REPL history
37 | .node_repl_history
38 |
39 | ## Ignore Visual Studio temporary files, build results, and
40 | ## files generated by popular Visual Studio add-ons.
41 | ##
42 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
43 |
44 | # User-specific files
45 | *.suo
46 | *.user
47 | *.userosscache
48 | *.sln.docstates
49 |
50 | # User-specific files (MonoDevelop/Xamarin Studio)
51 | *.userprefs
52 |
53 | # Build results
54 | [Dd]ebug/
55 | [Dd]ebugPublic/
56 | [Rr]elease/
57 | [Rr]eleases/
58 | x64/
59 | x86/
60 | bld/
61 | [Bb]in/
62 | [Oo]bj/
63 | [Ll]og/
64 |
65 | # Visual Studio 2015 cache/options directory
66 | .vs/
67 | # Uncomment if you have tasks that create the project's static files in wwwroot
68 | #wwwroot/
69 |
70 | # MSTest test Results
71 | [Tt]est[Rr]esult*/
72 | [Bb]uild[Ll]og.*
73 |
74 | # NUNIT
75 | *.VisualState.xml
76 | TestResult.xml
77 |
78 | # Build Results of an ATL Project
79 | [Dd]ebugPS/
80 | [Rr]eleasePS/
81 | dlldata.c
82 |
83 | # .NET Core
84 | project.lock.json
85 | project.fragment.lock.json
86 | artifacts/
87 | **/Properties/launchSettings.json
88 |
89 | *_i.c
90 | *_p.c
91 | *_i.h
92 | *.ilk
93 | *.meta
94 | *.obj
95 | *.pch
96 | *.pdb
97 | *.pgc
98 | *.pgd
99 | *.rsp
100 | *.sbr
101 | *.tlb
102 | *.tli
103 | *.tlh
104 | *.tmp
105 | *.tmp_proj
106 | *.log
107 | *.vspscc
108 | *.vssscc
109 | .builds
110 | *.pidb
111 | *.svclog
112 | *.scc
113 |
114 | # Chutzpah Test files
115 | _Chutzpah*
116 |
117 | # Visual C++ cache files
118 | ipch/
119 | *.aps
120 | *.ncb
121 | *.opendb
122 | *.opensdf
123 | *.sdf
124 | *.cachefile
125 | *.VC.db
126 | *.VC.VC.opendb
127 |
128 | # Visual Studio profiler
129 | *.psess
130 | *.vsp
131 | *.vspx
132 | *.sap
133 |
134 | # TFS 2012 Local Workspace
135 | $tf/
136 |
137 | # Guidance Automation Toolkit
138 | *.gpState
139 |
140 | # ReSharper is a .NET coding add-in
141 | _ReSharper*/
142 | *.[Rr]e[Ss]harper
143 | *.DotSettings.user
144 |
145 | # JustCode is a .NET coding add-in
146 | .JustCode
147 |
148 | # TeamCity is a build add-in
149 | _TeamCity*
150 |
151 | # DotCover is a Code Coverage Tool
152 | *.dotCover
153 |
154 | # Visual Studio code coverage results
155 | *.coverage
156 | *.coveragexml
157 |
158 | # NCrunch
159 | _NCrunch_*
160 | .*crunch*.local.xml
161 | nCrunchTemp_*
162 |
163 | # MightyMoose
164 | *.mm.*
165 | AutoTest.Net/
166 |
167 | # Web workbench (sass)
168 | .sass-cache/
169 |
170 | # Installshield output folder
171 | [Ee]xpress/
172 |
173 | # DocProject is a documentation generator add-in
174 | DocProject/buildhelp/
175 | DocProject/Help/*.HxT
176 | DocProject/Help/*.HxC
177 | DocProject/Help/*.hhc
178 | DocProject/Help/*.hhk
179 | DocProject/Help/*.hhp
180 | DocProject/Help/Html2
181 | DocProject/Help/html
182 |
183 | # Click-Once directory
184 | publish/
185 |
186 | # Publish Web Output
187 | *.[Pp]ublish.xml
188 | *.azurePubxml
189 | # TODO: Comment the next line if you want to checkin your web deploy settings
190 | # but database connection strings (with potential passwords) will be unencrypted
191 | *.pubxml
192 | *.publishproj
193 |
194 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
195 | # checkin your Azure Web App publish settings, but sensitive information contained
196 | # in these scripts will be unencrypted
197 | PublishScripts/
198 |
199 | # NuGet Packages
200 | *.nupkg
201 | # The packages folder can be ignored because of Package Restore
202 | **/packages/*
203 | # except build/, which is used as an MSBuild target.
204 | !**/packages/build/
205 | # Uncomment if necessary however generally it will be regenerated when needed
206 | #!**/packages/repositories.config
207 | # NuGet v3's project.json files produces more ignoreable files
208 | *.nuget.props
209 | *.nuget.targets
210 |
211 | # Microsoft Azure Build Output
212 | csx/
213 | *.build.csdef
214 |
215 | # Microsoft Azure Emulator
216 | ecf/
217 | rcf/
218 |
219 | # Windows Store app package directories and files
220 | AppPackages/
221 | BundleArtifacts/
222 | Package.StoreAssociation.xml
223 | _pkginfo.txt
224 |
225 | # Visual Studio cache files
226 | # files ending in .cache can be ignored
227 | *.[Cc]ache
228 | # but keep track of directories ending in .cache
229 | !*.[Cc]ache/
230 |
231 | # Others
232 | ClientBin/
233 | ~$*
234 | *~
235 | *.dbmdl
236 | *.dbproj.schemaview
237 | *.jfm
238 | *.pfx
239 | *.publishsettings
240 | node_modules/
241 | orleans.codegen.cs
242 |
243 | # Since there are multiple workflows, uncomment next line to ignore bower_components
244 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
245 | #bower_components/
246 |
247 | # RIA/Silverlight projects
248 | Generated_Code/
249 |
250 | # Backup & report files from converting an old project file
251 | # to a newer Visual Studio version. Backup files are not needed,
252 | # because we have git ;-)
253 | _UpgradeReport_Files/
254 | Backup*/
255 | UpgradeLog*.XML
256 | UpgradeLog*.htm
257 |
258 | # SQL Server files
259 | *.mdf
260 | *.ldf
261 |
262 | # Business Intelligence projects
263 | *.rdl.data
264 | *.bim.layout
265 | *.bim_*.settings
266 |
267 | # Microsoft Fakes
268 | FakesAssemblies/
269 |
270 | # GhostDoc plugin setting file
271 | *.GhostDoc.xml
272 |
273 | # Node.js Tools for Visual Studio
274 | .ntvs_analysis.dat
275 |
276 | # Visual Studio 6 build log
277 | *.plg
278 |
279 | # Visual Studio 6 workspace options file
280 | *.opt
281 |
282 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
283 | *.vbw
284 |
285 | # Visual Studio LightSwitch build output
286 | **/*.HTMLClient/GeneratedArtifacts
287 | **/*.DesktopClient/GeneratedArtifacts
288 | **/*.DesktopClient/ModelManifest.xml
289 | **/*.Server/GeneratedArtifacts
290 | **/*.Server/ModelManifest.xml
291 | _Pvt_Extensions
292 |
293 | # Paket dependency manager
294 | .paket/paket.exe
295 | paket-files/
296 |
297 | # FAKE - F# Make
298 | .fake/
299 |
300 | # JetBrains Rider
301 | .idea/
302 | *.sln.iml
303 |
304 | # CodeRush
305 | .cr/
306 |
307 | # Python Tools for Visual Studio (PTVS)
308 | __pycache__/
309 | *.pyc
310 |
311 | # Cake - Uncomment if you are using it
312 | # tools/**
313 | # !tools/packages.config
314 |
--------------------------------------------------------------------------------
/js-unit-test-examples/LICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/js-unit-test-examples/README.md:
--------------------------------------------------------------------------------
1 | ## JavaScript Unit Test Examples
2 | This repository contains a collection of example setups for common JavaScript unit testing frameworks and tools.
3 |
4 | |Example|Coverage|ES6|TypeScript|
5 | |---|---|---|---|
6 | |[ava](https://github.com/Wedvich/js-unit-test-examples/tree/master/ava)|:heavy_check_mark:|||
7 | |[ava-nyc](https://github.com/Wedvich/js-unit-test-examples/tree/master/ava-nyc)|:heavy_check_mark:|:heavy_check_mark:||
8 | |[jasmine](https://github.com/Wedvich/js-unit-test-examples/tree/master/jasmine)||||
9 | |[jasmine-chutzpah](https://github.com/Wedvich/js-unit-test-examples/tree/master/jasmine-chutzpah)||||
10 | |[jest](https://github.com/Wedvich/js-unit-test-examples/tree/master/jest)|:heavy_check_mark:|:heavy_check_mark:||
11 | |[mocha-chai](https://github.com/Wedvich/js-unit-test-examples/tree/master/mocha-chai)||||
12 | |[mocha-chai-istanbul](https://github.com/Wedvich/js-unit-test-examples/tree/master/mocha-chai-istanbul)|:heavy_check_mark:|||
13 | |[mocha-chai-ts](https://github.com/Wedvich/js-unit-test-examples/tree/master/mocha-chai-ts)||:heavy_check_mark:|:heavy_check_mark:|
14 | |[mocha-chai-ts-istanbul](https://github.com/Wedvich/js-unit-test-examples/tree/master/mocha-chai-ts-istanbul)|:heavy_check_mark:|:heavy_check_mark:|:heavy_check_mark:|
15 | |[tap-nyc](https://github.com/Wedvich/js-unit-test-examples/tree/master/tap-nyc)|:heavy_check_mark:|||
16 |
--------------------------------------------------------------------------------
/js-unit-test-examples/ava-nyc/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "js-unit-test-examples-ava-nyc",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "nyc ava"
8 | },
9 | "author": "",
10 | "license": "Unlicense",
11 | "devDependencies": {
12 | "ava": "^0.17.0",
13 | "nyc": "^10.1.2"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/js-unit-test-examples/ava-nyc/src/index.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | this.add = function (a, b) {
3 | return a + b;
4 | };
5 |
6 | this.multiply = function (a, b) {
7 | return a * b;
8 | };
9 |
10 | this.fibonacci = function (length) {
11 | var sequence = [0, 1];
12 | for (var i = 2; i <= length; ++i) {
13 | sequence[i] = sequence[i - 1] + sequence[i - 2];
14 | }
15 | return sequence;
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/js-unit-test-examples/ava-nyc/test/MathLib/add.test.js:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import MathLib from '../../src/index';
3 |
4 | test('add', t => {
5 | const mathLib = new MathLib();
6 | const result = mathLib.add(1, 2);
7 | t.is(result, 3);
8 | });
9 |
--------------------------------------------------------------------------------
/js-unit-test-examples/ava-nyc/test/MathLib/fibonacci.test.js:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import MathLib from '../../src/index';
3 |
4 | test('fibonacci', t => {
5 | const mathLib = new MathLib();
6 | const result = mathLib.fibonacci(12);
7 | t.is(result[12], 144);
8 | });
9 |
--------------------------------------------------------------------------------
/js-unit-test-examples/ava-nyc/test/MathLib/multiply.test.js:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import MathLib from '../../src/index';
3 |
4 | test('multiply', t => {
5 | const mathLib = new MathLib();
6 | const result = mathLib.multiply(3, 3);
7 | t.is(result, 9);
8 | });
9 |
--------------------------------------------------------------------------------
/js-unit-test-examples/ava/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "js-unit-test-examples-ava",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "ava"
8 | },
9 | "author": "",
10 | "license": "Unlicense",
11 | "devDependencies": {
12 | "ava": "^0.17.0"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/js-unit-test-examples/ava/src/index.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | this.add = function (a, b) {
3 | return a + b;
4 | };
5 |
6 | this.multiply = function (a, b) {
7 | return a * b;
8 | };
9 |
10 | this.fibonacci = function (length) {
11 | var sequence = [0, 1];
12 | for (var i = 2; i <= length; ++i) {
13 | sequence[i] = sequence[i - 1] + sequence[i - 2];
14 | }
15 | return sequence;
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/js-unit-test-examples/ava/test/MathLib/add.test.js:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import MathLib from '../../src/index';
3 |
4 | test('add', t => {
5 | const mathLib = new MathLib();
6 | const result = mathLib.add(1, 2);
7 | t.is(result, 3);
8 | });
9 |
--------------------------------------------------------------------------------
/js-unit-test-examples/ava/test/MathLib/fibonacci.test.js:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import MathLib from '../../src/index';
3 |
4 | test('fibonacci', t => {
5 | const mathLib = new MathLib();
6 | const result = mathLib.fibonacci(12);
7 | t.is(result[12], 144);
8 | });
9 |
--------------------------------------------------------------------------------
/js-unit-test-examples/ava/test/MathLib/multiply.test.js:
--------------------------------------------------------------------------------
1 | import test from 'ava';
2 | import MathLib from '../../src/index';
3 |
4 | test('multiply', t => {
5 | const mathLib = new MathLib();
6 | const result = mathLib.multiply(3, 3);
7 | t.is(result, 9);
8 | });
9 |
--------------------------------------------------------------------------------
/js-unit-test-examples/jasmine-chutzpah/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace jasmine_chutzpah
8 | {
9 | class Program
10 | {
11 | static void Main(string[] args)
12 | {
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/js-unit-test-examples/jasmine-chutzpah/chutzpah.json:
--------------------------------------------------------------------------------
1 | {
2 | "Framework": "jasmine",
3 | "References": [
4 | {
5 | "Path": "src",
6 | "Includes": ["*.js"]
7 | }
8 | ],
9 | "Tests": [
10 | { "Includes": ["*.spec.js"] }
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/js-unit-test-examples/jasmine-chutzpah/jasmine-chutzpah.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {B303D105-FF28-4F88-9B2F-751FE1485E9D}
8 | Exe
9 | Properties
10 | jasmine_chutzpah
11 | jasmine-chutzpah
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
68 |
--------------------------------------------------------------------------------
/js-unit-test-examples/jasmine-chutzpah/jasmine-chutzpah.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "jasmine-chutzpah", "jasmine-chutzpah.csproj", "{B303D105-FF28-4F88-9B2F-751FE1485E9D}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {B303D105-FF28-4F88-9B2F-751FE1485E9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {B303D105-FF28-4F88-9B2F-751FE1485E9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {B303D105-FF28-4F88-9B2F-751FE1485E9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {B303D105-FF28-4F88-9B2F-751FE1485E9D}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/js-unit-test-examples/jasmine-chutzpah/spec/index.spec.js:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | describe('MathLib', function () {
5 | describe('add', function () {
6 | it('adds two numbers together', function () {
7 | var mathLib = new MathLib();
8 | var result = mathLib.add(1, 2);
9 | expect(result).toEqual(3);
10 | });
11 | });
12 |
13 | describe('multiply', function () {
14 | it('multiply two numbers', function () {
15 | var mathLib = new MathLib();
16 | var result = mathLib.multiply(3, 3);
17 | expect(result).toEqual(9);
18 | });
19 | });
20 |
21 | describe('fibonacci', function () {
22 | it('generates a valid fibonacci sequence', function () {
23 | var mathLib = new MathLib();
24 | var result = mathLib.fibonacci(12);
25 | expect(result[12]).toEqual(144);
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/js-unit-test-examples/jasmine-chutzpah/src/index.js:
--------------------------------------------------------------------------------
1 | var MathLib = function () {
2 | this.add = function (a, b) {
3 | return a + b;
4 | };
5 |
6 | this.multiply = function (a, b) {
7 | return a * b;
8 | };
9 |
10 | this.fibonacci = function (length) {
11 | var sequence = [0, 1];
12 | for (var i = 2; i <= length; ++i) {
13 | sequence[i] = sequence[i - 1] + sequence[i - 2];
14 | }
15 | return sequence;
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/js-unit-test-examples/jasmine/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "js-unit-test-examples-jasmine",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "jasmine"
8 | },
9 | "author": "",
10 | "license": "Unlicense",
11 | "devDependencies": {
12 | "jasmine": "^2.5.3"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/js-unit-test-examples/jasmine/spec/index.spec.js:
--------------------------------------------------------------------------------
1 | describe('MathLib', function () {
2 | var MathLib = require('../src/index.js');
3 |
4 | describe('add', function () {
5 | it('adds two numbers together', function () {
6 | var mathLib = new MathLib();
7 | var result = mathLib.add(1, 2);
8 | expect(result).toEqual(3);
9 | });
10 | });
11 |
12 | describe('multiply', function () {
13 | it('multiply two numbers', function () {
14 | var mathLib = new MathLib();
15 | var result = mathLib.multiply(3, 3);
16 | expect(result).toEqual(9);
17 | });
18 | });
19 |
20 | describe('fibonacci', function () {
21 | it('generates a valid fibonacci sequence', function () {
22 | var mathLib = new MathLib();
23 | var result = mathLib.fibonacci(12);
24 | expect(result[12]).toEqual(144);
25 | });
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/js-unit-test-examples/jasmine/spec/support/jasmine.json:
--------------------------------------------------------------------------------
1 | {
2 | "spec_dir": "spec",
3 | "spec_files": [
4 | "**/*[sS]pec.js"
5 | ],
6 | "helpers": [
7 | "helpers/**/*.js"
8 | ],
9 | "stopSpecOnExpectationFailure": false,
10 | "random": false
11 | }
12 |
--------------------------------------------------------------------------------
/js-unit-test-examples/jasmine/src/index.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | this.add = function (a, b) {
3 | return a + b;
4 | };
5 |
6 | this.multiply = function (a, b) {
7 | return a * b;
8 | };
9 |
10 | this.fibonacci = function (length) {
11 | var sequence = [0, 1];
12 | for (var i = 2; i <= length; ++i) {
13 | sequence[i] = sequence[i - 1] + sequence[i - 2];
14 | }
15 | return sequence;
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/js-unit-test-examples/jest/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "js-unit-test-examples-jest",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "jest"
8 | },
9 | "author": "",
10 | "license": "Unlicense",
11 | "devDependencies": {
12 | "jest": "^18.1.0"
13 | },
14 | "jest": {
15 | "collectCoverage": true,
16 | "collectCoverageFrom": ["src/**/*.js"]
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/js-unit-test-examples/jest/src/index.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | this.add = function (a, b) {
3 | return a + b;
4 | };
5 |
6 | this.multiply = function (a, b) {
7 | return a * b;
8 | };
9 |
10 | this.fibonacci = function (length) {
11 | var sequence = [0, 1];
12 | for (var i = 2; i <= length; ++i) {
13 | sequence[i] = sequence[i - 1] + sequence[i - 2];
14 | }
15 | return sequence;
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/js-unit-test-examples/jest/test/index.test.js:
--------------------------------------------------------------------------------
1 | const MathLib = require('../src');
2 |
3 | describe('MathLib', () => {
4 | describe('add', () => {
5 | it('adds two numbers together', () => {
6 | const mathLib = new MathLib();
7 | const result = mathLib.add(1, 2);
8 | expect(result).toBe(3);
9 | });
10 | });
11 |
12 | describe('multiply', () => {
13 | it('multiply two numbers', () => {
14 | const mathLib = new MathLib();
15 | const result = mathLib.multiply(3, 3);
16 | expect(result).toBe(9);
17 | });
18 | });
19 |
20 | describe('fibonacci', () => {
21 | it('generates a valid fibonacci sequence', () => {
22 | const mathLib = new MathLib();
23 | const result = mathLib.fibonacci(12);
24 | expect(result[12]).toBe(144);
25 | });
26 | });
27 | });
28 |
--------------------------------------------------------------------------------
/js-unit-test-examples/mocha-chai-istanbul/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "js-unit-test-examples-mocha-chai-istanbul",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "test": "istanbul cover node_modules/mocha/bin/_mocha"
11 | },
12 | "author": "",
13 | "license": "Unlicense",
14 | "devDependencies": {
15 | "chai": "^3.5.0",
16 | "istanbul": "^0.4.5",
17 | "mocha": "^3.2.0"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/js-unit-test-examples/mocha-chai-istanbul/src/index.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | this.add = function (a, b) {
3 | return a + b;
4 | };
5 |
6 | this.multiply = function (a, b) {
7 | return a * b;
8 | };
9 |
10 | this.fibonacci = function (length) {
11 | var sequence = [0, 1];
12 | for (var i = 2; i <= length; ++i) {
13 | sequence[i] = sequence[i - 1] + sequence[i - 2];
14 | }
15 | return sequence;
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/js-unit-test-examples/mocha-chai-istanbul/test/index.test.js:
--------------------------------------------------------------------------------
1 | describe('MathLib', function () {
2 | var expect = require('chai').expect;
3 | var MathLib = require('../src/index.js');
4 |
5 | describe('add', function () {
6 | it('adds two numbers together', function () {
7 | var mathLib = new MathLib();
8 | var result = mathLib.add(1, 2);
9 | expect(result).to.equal(3);
10 | });
11 | });
12 |
13 | describe('multiply', function () {
14 | it('multiply two numbers', function () {
15 | var mathLib = new MathLib();
16 | var result = mathLib.multiply(3, 3);
17 | expect(result).to.equal(9);
18 | });
19 | });
20 |
21 | describe('fibonacci', function () {
22 | it('generates a valid fibonacci sequence', function () {
23 | var mathLib = new MathLib();
24 | var result = mathLib.fibonacci(12);
25 | expect(result[12]).to.equal(144);
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/js-unit-test-examples/mocha-chai-ts-istanbul/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "js-unit-test-examples-mocha-chai-ts-istanbul",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "test": "ts-node node_modules/istanbul/lib/cli.js cover -e .ts node_modules/mocha/bin/_mocha -- test/**/*.test.ts"
11 | },
12 | "author": "",
13 | "license": "Unlicense",
14 | "devDependencies": {
15 | "@types/mocha": "^2.2.38",
16 | "@types/node": "^7.0.4",
17 | "chai": "^3.5.0",
18 | "istanbul": "^1.1.0-alpha.1",
19 | "mocha": "^3.2.0",
20 | "ts-node": "^2.0.0",
21 | "typescript": "^2.1.5"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/js-unit-test-examples/mocha-chai-ts-istanbul/src/index.ts:
--------------------------------------------------------------------------------
1 | export class MathLib {
2 | add(a, b): Number {
3 | return a + b;
4 | }
5 |
6 | multiply(a, b): Number {
7 | return a * b;
8 | }
9 |
10 | fibonacci(length): Number[] {
11 | const sequence = [0, 1];
12 | for (let i = 2; i <= length; ++i) {
13 | sequence[i] = sequence[i - 1] + sequence[i - 2];
14 | }
15 | return sequence;
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/js-unit-test-examples/mocha-chai-ts-istanbul/test/index.test.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | import { expect } from 'chai';
5 | import { MathLib } from '../src';
6 |
7 | describe('MathLib', () => {
8 | describe('add', () => {
9 | it('adds two numbers together', () => {
10 | const mathLib = new MathLib();
11 | const result = mathLib.add(1, 2);
12 | expect(result).to.equal(3);
13 | });
14 | });
15 |
16 | describe('multiply', () => {
17 | it('multiply two numbers', () =>{
18 | const mathLib = new MathLib();
19 | const result = mathLib.multiply(3, 3);
20 | expect(result).to.equal(9);
21 | });
22 | });
23 |
24 | describe('fibonacci', () =>{
25 | it('generates a valid fibonacci sequence', () =>{
26 | const mathLib = new MathLib();
27 | const result = mathLib.fibonacci(12);
28 | expect(result[12]).to.equal(144);
29 | });
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/js-unit-test-examples/mocha-chai-ts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "js-unit-test-examples-mocha-chai-ts",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "test": "mocha --compilers ts:ts-node/register test/**/*.test.ts"
11 | },
12 | "author": "",
13 | "license": "Unlicense",
14 | "devDependencies": {
15 | "@types/mocha": "^2.2.38",
16 | "@types/node": "^7.0.4",
17 | "chai": "^3.5.0",
18 | "mocha": "^3.2.0",
19 | "ts-node": "^2.0.0",
20 | "typescript": "^2.1.5"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/js-unit-test-examples/mocha-chai-ts/src/index.ts:
--------------------------------------------------------------------------------
1 | export class MathLib {
2 | add(a, b): Number {
3 | return a + b;
4 | }
5 |
6 | multiply(a, b): Number {
7 | return a * b;
8 | }
9 |
10 | fibonacci(length): Number[] {
11 | const sequence = [0, 1];
12 | for (let i = 2; i <= length; ++i) {
13 | sequence[i] = sequence[i - 1] + sequence[i - 2];
14 | }
15 | return sequence;
16 | };
17 | }
18 |
--------------------------------------------------------------------------------
/js-unit-test-examples/mocha-chai-ts/test/index.test.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | import { expect } from 'chai';
5 | import { MathLib } from '../src';
6 |
7 | describe('MathLib', () => {
8 | describe('add', () => {
9 | it('adds two numbers together', () => {
10 | const mathLib = new MathLib();
11 | const result = mathLib.add(1, 2);
12 | expect(result).to.equal(3);
13 | });
14 | });
15 |
16 | describe('multiply', () => {
17 | it('multiply two numbers', () =>{
18 | const mathLib = new MathLib();
19 | const result = mathLib.multiply(3, 3);
20 | expect(result).to.equal(9);
21 | });
22 | });
23 |
24 | describe('fibonacci', () =>{
25 | it('generates a valid fibonacci sequence', () =>{
26 | const mathLib = new MathLib();
27 | const result = mathLib.fibonacci(12);
28 | expect(result[12]).to.equal(144);
29 | });
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/js-unit-test-examples/mocha-chai/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "js-unit-test-examples-mocha-chai",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "scripts": {
10 | "test": "mocha"
11 | },
12 | "author": "",
13 | "license": "Unlicense",
14 | "devDependencies": {
15 | "chai": "^3.5.0",
16 | "mocha": "^3.2.0"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/js-unit-test-examples/mocha-chai/src/index.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | this.add = function (a, b) {
3 | return a + b;
4 | };
5 |
6 | this.multiply = function (a, b) {
7 | return a * b;
8 | };
9 |
10 | this.fibonacci = function (length) {
11 | var sequence = [0, 1];
12 | for (var i = 2; i <= length; ++i) {
13 | sequence[i] = sequence[i - 1] + sequence[i - 2];
14 | }
15 | return sequence;
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/js-unit-test-examples/mocha-chai/test/index.test.js:
--------------------------------------------------------------------------------
1 | describe('MathLib', function () {
2 | var expect = require('chai').expect;
3 | var MathLib = require('../src/index.js');
4 |
5 | describe('add', function () {
6 | it('adds two numbers together', function () {
7 | var mathLib = new MathLib();
8 | var result = mathLib.add(1, 2);
9 | expect(result).to.equal(3);
10 | });
11 | });
12 |
13 | describe('multiply', function () {
14 | it('multiply two numbers', function () {
15 | var mathLib = new MathLib();
16 | var result = mathLib.multiply(3, 3);
17 | expect(result).to.equal(9);
18 | });
19 | });
20 |
21 | describe('fibonacci', function () {
22 | it('generates a valid fibonacci sequence', function () {
23 | var mathLib = new MathLib();
24 | var result = mathLib.fibonacci(12);
25 | expect(result[12]).to.equal(144);
26 | });
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/js-unit-test-examples/tap-nyc/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "js-unit-test-examples-tap-nyc",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "nyc --reporter=html tap ./test/**/*.spec.js"
8 | },
9 | "author": "",
10 | "license": "Unlicense",
11 | "devDependencies": {
12 | "nyc": "^10.1.2",
13 | "tap": "^9.0.3"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/js-unit-test-examples/tap-nyc/src/index.js:
--------------------------------------------------------------------------------
1 | module.exports = function () {
2 | this.add = function (a, b) {
3 | return a + b;
4 | };
5 |
6 | this.multiply = function (a, b) {
7 | return a * b;
8 | };
9 |
10 | this.fibonacci = function (length) {
11 | var sequence = [0, 1];
12 | for (var i = 2; i <= length; ++i) {
13 | sequence[i] = sequence[i - 1] + sequence[i - 2];
14 | }
15 | return sequence;
16 | };
17 | };
18 |
--------------------------------------------------------------------------------
/js-unit-test-examples/tap-nyc/test/MathLib/add.spec.js:
--------------------------------------------------------------------------------
1 | var tap = require('tap');
2 | var MathLib = require('../../src/index.js');
3 |
4 | var mathLib = new MathLib();
5 | var result = mathLib.add(1, 2);
6 | tap.equal(result, 3);
7 |
--------------------------------------------------------------------------------
/js-unit-test-examples/tap-nyc/test/MathLib/fibonacci.spec.js:
--------------------------------------------------------------------------------
1 | var tap = require('tap');
2 | var MathLib = require('../../src/index.js');
3 |
4 | var mathLib = new MathLib();
5 | var result = mathLib.fibonacci(12);
6 | tap.equal(result[12], 144);
7 |
--------------------------------------------------------------------------------
/js-unit-test-examples/tap-nyc/test/MathLib/multiply.spec.js:
--------------------------------------------------------------------------------
1 | var tap = require('tap');
2 | var MathLib = require('../../src/index.js');
3 |
4 | var mathLib = new MathLib();
5 | var result = mathLib.multiply(3, 3);
6 | tap.equal(result, 9);
7 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015"]
3 | }
--------------------------------------------------------------------------------
/js-unit-testing-examples/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | insert_final_newline = true
5 | charset = utf-8
6 | trim_trailing_whitespace = true
7 | end_of_line = lf
8 |
9 | [*.{js,md}]
10 | indent_style = space
11 | indent_size = 4
12 |
13 | [{package.json,.travis.yml}]
14 | indent_style = space
15 | indent_size = 2
16 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "es6": true,
4 | "node": true,
5 | "mocha": true
6 | },
7 | "globals": {
8 | "chai": true,
9 | "expect": true,
10 | "sinon": true
11 | },
12 | "extends": "eslint:recommended",
13 | "parserOptions": {
14 | "sourceType": "module"
15 | },
16 | "rules": {
17 | "indent": [
18 | "error",
19 | 4
20 | ],
21 | "linebreak-style": [
22 | "error",
23 | "unix"
24 | ],
25 | "quotes": [
26 | "error",
27 | "single"
28 | ],
29 | "semi": [
30 | "error",
31 | "always"
32 | ],
33 | "no-console": "warn"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 |
6 | # Runtime data
7 | pids
8 | *.pid
9 | *.seed
10 |
11 | # Directory for instrumented libs generated by jscoverage/JSCover
12 | lib-cov
13 |
14 | # Coverage directory used by tools like istanbul
15 | coverage
16 |
17 | # nyc test coverage
18 | .nyc_output
19 |
20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
21 | .grunt
22 |
23 | # node-waf configuration
24 | .lock-wscript
25 |
26 | # Compiled binary addons (http://nodejs.org/api/addons.html)
27 | build/Release
28 |
29 | # Dependency directories
30 | node_modules
31 | jspm_packages
32 |
33 | # Optional npm cache directory
34 | .npm
35 |
36 | # Optional REPL history
37 | .node_repl_history
38 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "vsicons.presets.angular": false
3 | }
--------------------------------------------------------------------------------
/js-unit-testing-examples/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Marc Littlemore
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/README.md:
--------------------------------------------------------------------------------
1 | # JavaScript Unit Testing Examples
2 |
3 | Example project to allow me to show how best to unit test a JavaScript Express application.
4 |
5 | ## Install
6 |
7 | Clone this repository and install the dependencies as follows:
8 |
9 | ```
10 | git clone git@github.com:MarcL/js-unit-testing-framework.git
11 | npm install
12 | ```
13 |
14 | ## Running the tests
15 |
16 | The code sets up a basic Express server with a few routes and some tests which cover testing the server setup. Run the test suite using npm:
17 |
18 | ```
19 | npm test
20 | ```
21 |
22 | ## JavaScript Tests
23 |
24 | Take a look in the `test` directory to see all of the test code. There are lots of examples of different types of tests and how to create them.
25 |
26 | ### Asynchronous functions and promises
27 |
28 | Some examples of how to test asynchronous functions and promises, including some tips and tricks and gotchas.
29 |
30 | #### Asynchronous function
31 | - Timeout because `done` callback isn't called when function succeeds
32 | - Passing test but slow because timer isn't stubbed
33 | - Passing test and fast because timer is stubbed
34 | - Timeout because `done` callback isn't called when function throws an error
35 | - Passing test to call `done` callback when function throws an error
36 |
37 | #### Promise : resolving
38 | - Test passes incorrectly because Promise isn't returned
39 | - Passing test because promise is returned
40 | - Passing test because `done` callback is called after resolution
41 | - Passing test because `done` callback is called after resolution using `chai-as-promised` syntax
42 |
43 | #### Promise : rejecting
44 | - Test passes incorrectly because Promise isn't returned
45 | - Failing test because rejected Promise error isn't caught
46 | - Passing test because Promise is returned and rejection is caught
47 | - Passing test because Promise rejection is caught and `done` callback is called
48 | - Passing test because Promise rejection is caught and `done` callback is called using `chai-as-promised` syntax
49 |
50 | #### Slow tests
51 | - Passing test but is slow due to Promise function in chain taking a long time
52 | - Passing test and much faster as longer function is now stubbed to execute immediately
53 |
54 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/index.js:
--------------------------------------------------------------------------------
1 | require('babel-register');
2 |
3 | var server = require('./src/launch');
4 | server.start();
--------------------------------------------------------------------------------
/js-unit-testing-examples/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "js-unit-testing-framework",
3 | "version": "0.0.1",
4 | "description": "Unit testing Express routes using Mocha",
5 | "main": "index.js",
6 | "scripts": {
7 | "lint": "eslint src/ test/",
8 | "precommit": "npm run lint",
9 | "prepush": "npm run test",
10 | "start": "node .",
11 | "test": "mocha",
12 | "test:watch": "mocha --watch"
13 | },
14 | "repository": {
15 | "type": "git",
16 | "url": "git+ssh://git@github.com/MarcL/js-unit-testing-framework.git"
17 | },
18 | "keywords": [
19 | "unit",
20 | "testing",
21 | "mocha",
22 | "express",
23 | "routes"
24 | ],
25 | "author": "Marc Littlemore",
26 | "license": "MIT",
27 | "homepage": "https://github.com/MarcL/unit-test-express-routes#readme",
28 | "dependencies": {
29 | "babel-preset-es2015": "^6.24.1",
30 | "babel-register": "^6.24.1",
31 | "bluebird": "^3.5.0",
32 | "express": "^4.15.2"
33 | },
34 | "devDependencies": {
35 | "chai": "^3.5.0",
36 | "chai-as-promised": "~6.0.0",
37 | "eslint": "^3.19.0",
38 | "eslint-config-airbnb-base": "^11.1.3",
39 | "eslint-plugin-import": "~2.2.0",
40 | "husky": "^0.13.3",
41 | "mocha": "~3.4.1",
42 | "node-mocks-http": "^1.6.1",
43 | "proxyquire": "^1.7.10",
44 | "sinon": "^2.2.0",
45 | "sinon-chai": "^2.10.0"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/src/data/fakeData.js:
--------------------------------------------------------------------------------
1 | export default {
2 | events: []
3 | };
4 |
5 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/src/launch.js:
--------------------------------------------------------------------------------
1 | import express from 'express';
2 |
3 | import homepage from './middleware/homepage';
4 | import login from './middleware/login';
5 | import authenticate from './middleware/authenticate';
6 | import dashboard from './middleware/dashboard';
7 | import promiseTest from './middleware/promiseTest';
8 | import apiRoutes from './routes/api';
9 |
10 | function setupRoutes(app) {
11 | app.get('/', homepage);
12 | app.get('/login', login);
13 | app.get('/dashboard',
14 | authenticate,
15 | dashboard
16 | );
17 | app.get('/promises', promiseTest);
18 |
19 | app.use('/api', apiRoutes);
20 | }
21 |
22 | function start(port = 7080) {
23 | const app = express();
24 |
25 | setupRoutes(app);
26 |
27 | const server = app.listen(port, () => {
28 | console.log(`Server running on: ${port}`);
29 | });
30 |
31 | return server;
32 | }
33 |
34 | export {
35 | start
36 | };
37 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/src/middleware/api/eventsGetAll.js:
--------------------------------------------------------------------------------
1 | import * as events from '../../services/events';
2 |
3 | const eventsGetAll = (request, response) => {
4 | const renderJsonResponse = (dataObject, success = true) => {
5 | const jsonResponse = Object.assign(
6 | dataObject,
7 | {success}
8 | );
9 | response.json(jsonResponse);
10 | };
11 |
12 | return events.getAll()
13 | .then((data) => {
14 | renderJsonResponse({
15 | data
16 | });
17 | })
18 | .catch((error) => {
19 | renderJsonResponse({
20 | message: error.name
21 | }, false);
22 | });
23 | };
24 |
25 | export default eventsGetAll;
26 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/src/middleware/authenticate.js:
--------------------------------------------------------------------------------
1 | function authenticate(request, response, next) {
2 | // TODO: Authenticate request and redirect to login if not authenticated
3 | console.log('verify authentication or redirect');
4 | next();
5 | }
6 |
7 | export default authenticate;
8 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/src/middleware/dashboard.js:
--------------------------------------------------------------------------------
1 | function dashboard(request, response) {
2 | response.send('dashboard is here');
3 | }
4 |
5 | export default dashboard;
6 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/src/middleware/homepage.js:
--------------------------------------------------------------------------------
1 | function homepage(request, response) {
2 | response.send('homepage is here');
3 | }
4 |
5 | export default homepage;
6 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/src/middleware/login.js:
--------------------------------------------------------------------------------
1 | function homepage(request, response) {
2 | response.send('login is here');
3 | }
4 |
5 | export default homepage;
6 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/src/middleware/promiseTest.js:
--------------------------------------------------------------------------------
1 | function promiseWrapper(shouldFail) {
2 | return shouldFail ?
3 | Promise.reject() :
4 | Promise.resolve();
5 | }
6 |
7 | function promiseTest(request, response) {
8 | const {fail: shouldFail = false} = request.query;
9 |
10 | return promiseWrapper(shouldFail)
11 | .then(() => {
12 | response.json({
13 | message: 'resolved Promise',
14 | error: false
15 | });
16 | })
17 | .catch(() => {
18 | response.json({
19 | message: 'rejected Promise',
20 | error: true
21 | });
22 | });
23 | }
24 |
25 | export default promiseTest;
26 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/src/routes/api.js:
--------------------------------------------------------------------------------
1 | import express from 'express';
2 | import eventsGetAll from '../middleware/api/eventsGetAll';
3 |
4 | const router = express.Router();
5 |
6 | router.get('/', (request, response) => {
7 | response.json({success: true});
8 | });
9 |
10 | // TODO
11 | // - Add GET for all data /events - return data + 200
12 | router.get('/events', eventsGetAll);
13 | //router.get('/events/:id', dataGetById);
14 |
15 | // - Add POST to add new data /events - return 201
16 | // - Add GET for single data element /events/:id -200 / 404
17 | // - Add PUT to update single data element /events/:id - 200/204 (no content)/4040
18 | // - Add DELETE to delete single data element /events/:id - 200/404
19 | // - Add authentication - basic auth - 'auth' -> 'key:' (no password) + base64 encoded - 401 if failed
20 |
21 | export default router;
22 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/src/services/events.js:
--------------------------------------------------------------------------------
1 | import fakeData from '../data/fakeData';
2 |
3 | const getAll = () => {
4 | return Promise.resolve(fakeData.events);
5 | };
6 |
7 | export {
8 | getAll
9 | };
10 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/test/examples/asynchronous.test.js:
--------------------------------------------------------------------------------
1 | // All tests that are skipped are done so because otherwise I won't allow
2 | // them to be pushed to a git repo due to running the tests on the prepush rule in package.json
3 | describe('Example asynchronous JavaScript tests', () => {
4 | describe('while testing asynchronous function', () => {
5 | // eslint-disable-next-line no-unused-vars
6 | it.skip('[FAILING TEST] should timeout because the done callback is not called', (done) => {
7 | setTimeout(() => {
8 | expect(true).to.be.true;
9 | }, 1000);
10 | });
11 |
12 | it('[PASSING BUT BAD TEST] should pass because the done callback is called but takes too long (~1000ms) to run', (done) => {
13 | setTimeout(() => {
14 | expect(true).to.be.true;
15 | done();
16 | }, 1000);
17 | });
18 |
19 | describe('better asynchronous test that stubs timer', () => {
20 | let fakeClock;
21 |
22 | beforeEach(() => {
23 | fakeClock = sinon.useFakeTimers();
24 | });
25 |
26 | afterEach(() => {
27 | fakeClock.restore();
28 | });
29 |
30 | it('[PASSING AND BETTER TEST] should stub clock to allow quick resolution of asynchronous function', (done) => {
31 | setTimeout(() => {
32 | expect(true).to.be.true;
33 | done();
34 | }, 1000);
35 |
36 | fakeClock.tick(1000);
37 | });
38 | });
39 |
40 | // eslint-disable-next-line no-unused-vars
41 | it.skip('[FAILING TEST] should timeout because the done callback is not called when function has errors', (done) => {
42 | setTimeout(() => {
43 | throw new Error('Something has gone wrong');
44 |
45 | // eslint-disable-next-line no-unreachable
46 | expect(true).to.be.true;
47 | }, 10);
48 | });
49 |
50 | it('[PASSING TEST] should call the done callback when error occurs', (done) => {
51 | setTimeout(() => {
52 | try {
53 | throw new Error('Something has gone wrong');
54 |
55 | } catch(error) {
56 | expect(true).to.be.true;
57 | done();
58 | }
59 | }, 10);
60 | });
61 | });
62 |
63 | describe('while testing Promises', () => {
64 | describe('when Promise resolves', () => {
65 | it('[INCORRECT TEST] should pass but it never checks expectation', () => {
66 | const givenString = 'finished';
67 | Promise.resolve(givenString)
68 | .then((data) => {
69 | expect(data).to.equal(givenString);
70 | });
71 | });
72 |
73 | it('[PASSING TEST] should pass because it returns the promise', () => {
74 | const givenString = 'finished';
75 | return Promise.resolve(givenString)
76 | .then((data) => {
77 | expect(data).to.equal(givenString);
78 | });
79 | });
80 |
81 | it('[PASSING TEST] should pass because it calls the done callback when Promise has resolved', (done) => {
82 | const givenString = 'finished';
83 | Promise.resolve(givenString)
84 | .then((data) => {
85 | expect(data).to.equal(givenString);
86 | done();
87 | });
88 | });
89 |
90 | it('[PASSING TEST] should pass because it calls the done callback when Promise has resolved using chai-as-promised syntax', (done) => {
91 | const givenString = 'finished';
92 | Promise.resolve(givenString)
93 | .then((data) => {
94 | expect(data).to.equal(givenString);
95 | })
96 | .should.notify(done);
97 | });
98 | });
99 |
100 | describe('when Promise rejects', () => {
101 | it('[FAILING TEST] should pass because it does not return the Promise', () => {
102 | const givenString = 'error';
103 | Promise.reject(givenString);
104 | });
105 |
106 | it.skip('[FAILING TEST] should fail because it does not catch the rejection when returning the Promise', () => {
107 | const givenString = 'error';
108 | return Promise.reject(givenString);
109 | });
110 |
111 | it('[PASSING TEST] should pass because it catches the rejection and returns the Promise', () => {
112 | const givenString = 'error';
113 | return Promise.reject(givenString)
114 | .catch((error) => {
115 | expect(error).to.equal(givenString);
116 | });
117 | });
118 |
119 | it('[PASSING TEST] should pass because it catches the rejection and calls the done callback', (done) => {
120 | const givenString = 'error';
121 | Promise.reject(givenString)
122 | .catch((error) => {
123 | expect(error).to.equal(givenString);
124 | done();
125 | });
126 | });
127 |
128 | it('[PASSING TEST] should pass because it catches the rejection and calls the done callback using chai-as-promised syntax', (done) => {
129 | const givenString = 'error';
130 | Promise.reject(givenString)
131 | .catch((error) => {
132 | expect(error).to.equal(givenString);
133 | })
134 | .should.notify(done);
135 | });
136 | });
137 | });
138 |
139 | describe('while testing function with internal function which takes some time', () => {
140 | const moduleUnderTest = {
141 | longFunction(data) {
142 | return new Promise((resolve) => {
143 | setTimeout(() => {
144 | resolve(data);
145 | }, 1000);
146 | });
147 | }
148 | };
149 |
150 | it('[BAD TEST] should pass but takes too long (~1000ms) to run', () => {
151 | const givenString = 'finished';
152 |
153 | return Promise.resolve(givenString)
154 | .then(data => moduleUnderTest.longFunction(data))
155 | .then((data) => {
156 | expect(data).to.equal(givenString);
157 | });
158 | });
159 |
160 | describe('when long function is stubbed to execute immediately', () => {
161 | let stubLongFunction;
162 |
163 | beforeEach(() => {
164 | stubLongFunction = sinon.stub(moduleUnderTest, 'longFunction');
165 | });
166 |
167 | afterEach(() => {
168 | stubLongFunction.restore();
169 | });
170 |
171 | it('[FIXED TEST] should pass and long function will execute immediately', () => {
172 | const givenString = 'finished';
173 |
174 | // Stub our long function so it returns immediately
175 | // with the data we expect it to return
176 | stubLongFunction.resolves(givenString);
177 |
178 | return Promise.resolve(givenString)
179 | .then(data => moduleUnderTest.longFunction(data))
180 | .then((data) => {
181 | expect(data).to.equal(givenString);
182 | });
183 | });
184 | });
185 | });
186 | });
187 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/test/mocha.opts:
--------------------------------------------------------------------------------
1 | --recursive
2 | --require test/support/base
3 | --compilers js:babel-register
4 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/test/src/launch.test.js:
--------------------------------------------------------------------------------
1 | import proxyquire from 'proxyquire';
2 |
3 | describe('Express server', () => {
4 | let stubExpress;
5 | let spyExpressGet;
6 | let stubExpressListen;
7 | let spyHomepage;
8 | let spyLogin;
9 | let spyAuthenticate;
10 | let spyDashboard;
11 | let fakeExpress;
12 | let server;
13 | const fakeHttpServer = {};
14 |
15 | beforeEach(() => {
16 | spyExpressGet = sinon.spy();
17 | stubExpressListen = sinon.stub();
18 | spyHomepage = sinon.spy();
19 | spyLogin = sinon.spy();
20 | spyAuthenticate = sinon.spy();
21 | spyDashboard = sinon.spy();
22 |
23 | // Create fake express application with spy methods
24 | fakeExpress = {
25 | get: spyExpressGet,
26 | listen: stubExpressListen,
27 | use: () => {}
28 | };
29 |
30 | // Return fake express application when express() is called
31 | stubExpress = sinon.stub().returns(fakeExpress);
32 |
33 | // app.listen returns a fake HttpServer
34 | stubExpressListen.returns(fakeHttpServer);
35 |
36 | // Use proxyquire to stub required modules and return
37 | // our spies so we can check assertions
38 | server = proxyquire('../../src/launch', {
39 | express: stubExpress,
40 | './middleware/homepage' : {default: spyHomepage},
41 | './middleware/login': {default: spyLogin},
42 | './middleware/authenticate': {default: spyAuthenticate},
43 | './middleware/dashboard': {default: spyDashboard}
44 | });
45 | });
46 |
47 | it('should return expected http server', () => {
48 | const returnedServer = server.start();
49 | expect(returnedServer).to.eql(fakeHttpServer);
50 | });
51 |
52 | it('should setup default route', () => {
53 | server.start();
54 | spyExpressGet.should.have.been.calledWithExactly('/', spyHomepage);
55 | });
56 |
57 | it('should setup login route', () => {
58 | server.start();
59 | spyExpressGet.should.have.been.calledWithExactly('/login', spyLogin);
60 | });
61 |
62 | it('should setup dashboard route', () => {
63 | server.start();
64 | spyExpressGet.should.have.been.calledWithExactly(
65 | '/dashboard',
66 | spyAuthenticate,
67 | spyDashboard
68 | );
69 | });
70 |
71 | it('should listen on default port 7080', () => {
72 | server.start();
73 | stubExpressListen.should.have.been.calledWithExactly(7080, sinon.match.func);
74 | });
75 |
76 | it('should listen on expected port if passed', () => {
77 | const expectedPort = 8888;
78 | server.start(expectedPort);
79 | stubExpressListen.should.have.been.calledWithExactly(expectedPort, sinon.match.func);
80 | });
81 | });
82 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/test/src/middleware/api/dataGetAll.test.js:
--------------------------------------------------------------------------------
1 | import {createRequest, createResponse} from 'node-mocks-http';
2 | import eventsGetAll from '../../../../src/middleware/api/eventsGetAll';
3 | import * as eventsService from '../../../../src/services/events';
4 |
5 | describe('eventsGetAll()', () => {
6 | let fakeRequest;
7 | let fakeResponse;
8 | let stubEventServiceGetAll;
9 | let spyResponseJson;
10 |
11 | const fakeData = [];
12 |
13 | beforeEach(() => {
14 | fakeRequest = createRequest();
15 | fakeResponse = createResponse();
16 |
17 | stubEventServiceGetAll = sinon.stub(eventsService, 'getAll');
18 | stubEventServiceGetAll.resolves(fakeData);
19 | spyResponseJson = sinon.spy(fakeResponse, 'json');
20 | });
21 |
22 | afterEach(() => {
23 | stubEventServiceGetAll.restore();
24 | });
25 |
26 | it('should call data service getAll()', (done) => {
27 | eventsGetAll(fakeRequest, fakeResponse)
28 | .should.be.fulfilled
29 | .then(() => {
30 | expect(stubEventServiceGetAll.callCount).to.equal(1);
31 | })
32 | .should.notify(done);
33 | });
34 |
35 | it('should render expected json when data request succeeds', (done) => {
36 | const expectedData = {
37 | data: [],
38 | success: true
39 | };
40 |
41 | eventsGetAll(fakeRequest, fakeResponse)
42 | .should.be.fulfilled
43 | .then(() => {
44 | expect(spyResponseJson)
45 | .to.have.been.calledWithExactly(expectedData);
46 | })
47 | .should.notify(done);
48 | });
49 |
50 | it('should render expected failure json when data request fails', (done) => {
51 | const givenFailureData = 'error connecting to database';
52 | stubEventServiceGetAll.rejects(givenFailureData);
53 |
54 | const expectedData = {
55 | success: false,
56 | message: givenFailureData
57 | };
58 |
59 | eventsGetAll(fakeRequest, fakeResponse)
60 | .should.be.fulfilled
61 | .then(() => {
62 | expect(spyResponseJson)
63 | .to.have.been.calledWithExactly(expectedData);
64 | })
65 | .should.notify(done);
66 | });
67 | });
68 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/test/src/middleware/promiseTest.test.js:
--------------------------------------------------------------------------------
1 | import {createRequest, createResponse} from 'node-mocks-http';
2 | import promiseTest from '../../../src/middleware/promiseTest';
3 |
4 | describe('promiseTest middleware', () => {
5 | let fakeRequest;
6 | let fakeResponse;
7 | let stubResponseJson;
8 |
9 | beforeEach(() => {
10 | fakeRequest = createRequest();
11 | fakeResponse = createResponse();
12 |
13 | stubResponseJson = sinon.stub(fakeResponse, 'json');
14 | });
15 |
16 | afterEach(() => {
17 | stubResponseJson.restore();
18 | });
19 |
20 | it('should render expected json when Promise resolves', () => {
21 | const expectedJson = {
22 | message: 'resolved Promise',
23 | error: false
24 | };
25 |
26 | return promiseTest(fakeRequest, fakeResponse)
27 | .then(() => {
28 | expect(stubResponseJson)
29 | .to.have.been.calledWithExactly(expectedJson);
30 | });
31 | });
32 |
33 | it('should render expected json when Promise rejects', () => {
34 | fakeRequest.query.fail = true;
35 | const expectedJson = {
36 | message: 'rejected Promise',
37 | error: true
38 | };
39 |
40 | return promiseTest(fakeRequest, fakeResponse)
41 | .then(() => {
42 | expect(stubResponseJson)
43 | .to.have.been.calledWithExactly(expectedJson);
44 | });
45 | });
46 | });
47 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/test/src/middleware/services/events.test.js:
--------------------------------------------------------------------------------
1 | import * as eventsService from '../../../../src/services/events';
2 |
3 | describe('events service', () => {
4 | describe('getAll()', () => {
5 | it('should resolve with expected data', () => {
6 | const expectedData = [];
7 |
8 | eventsService.getAll()
9 | .should.be.fulfilled
10 | .then((data) => {
11 | expect(data).to.deep.equal(expectedData);
12 | });
13 | });
14 | });
15 | });
16 |
--------------------------------------------------------------------------------
/js-unit-testing-examples/test/support/base.js:
--------------------------------------------------------------------------------
1 | import Bluebird from 'bluebird';
2 | import sinon from 'sinon';
3 | import chai, {expect} from 'chai';
4 | import chaiAsPromised from 'chai-as-promised';
5 | import chaiSinon from 'sinon-chai';
6 |
7 | process.env.NODE_ENV = 'test';
8 |
9 | chai.use(chaiAsPromised);
10 | chai.use(chaiSinon);
11 | chai.should();
12 |
13 | // Expose all modules to node.js modules
14 | global.Promise = Bluebird;
15 | global.sinon = sinon;
16 | global.chai = chai;
17 | global.expect = expect;
18 |
--------------------------------------------------------------------------------