a 2.1.1 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/AUTHORS +1 -1
  2. package/README.md +744 -737
  3. package/index.js +17 -17
  4. package/package.json +16 -19
  5. package/.npmignore +0 -2
package/README.md CHANGED
@@ -1,737 +1,744 @@
1
- _a_
2
- ===
3
- _Mocking framework_ + _testing framework_.
4
-
5
-
6
- The mocking framework can be used in any JavaScript testing framework.
7
-
8
- The testing framework has a short and concise bdd syntax - with reusable contexts.
9
-
10
- __how to install__
11
-
12
- ```
13
- npm install a
14
- ```
15
-
16
-
17
-
18
- __if you want the test framework, install it globally too__
19
-
20
- ```
21
- npm install a -g
22
- ```
23
-
24
-
25
-
26
- _Mocking_
27
- ===================
28
-
29
- Mocking a function
30
- ------------------
31
-
32
- __partial mock__
33
-
34
- ```js
35
- var original = function() {
36
- return 'realValue';
37
- }
38
-
39
- var mock = require('a').mock(original);
40
- original = mock;
41
- mock.expect().return('fake');
42
-
43
- original(); //returns 'fake'
44
- original(); //returns 'realValue'
45
- ```
46
-
47
-
48
-
49
- __strict mock__
50
-
51
- ```js
52
- var mock = require('a').mock();
53
- mock.expect().return('fake');
54
-
55
- mock(); //returns 'fake'
56
- mock(); //throws unexpected arguments
57
- ```
58
-
59
-
60
-
61
- __expecting arguments__
62
-
63
- ```js
64
- var mock = require('a').mock();
65
- mock.expect('testValue1').return('fake1');
66
- mock.expect('testValue2').return('fake2');
67
-
68
- mock('testValue1'); //returns 'fake1'
69
- mock('testValue2'); //returns 'fake2'
70
- mock(); //throws unexpected arguments
71
- mock('foo'); //throws unexpected arguments
72
- ```
73
-
74
-
75
-
76
- __expecting multiple arguments__
77
-
78
- ```js
79
- var mock = require('a').mock();
80
- mock.expect('firstArg1', 'secondArg1').return('fake1');
81
- mock.expect('firstArg2', 'secondArg2').return('fake2');
82
-
83
-
84
- mock('firstArg1', 'secondArg1'); //returns 'fake1'
85
- mock('firstArg2', 'secondArg2'); //returns 'fake2'
86
- mock('foo'); //throws unexpected arguments
87
- mock('foo', 'bar'); //throws unexpected arguments
88
- ```
89
-
90
- __expecting array__
91
-
92
- ```js
93
- var mock = require('a').mock();
94
- mock.expect(['a','b']).return('fake1');
95
- mock.expect(['a','b').return('fake2');
96
- mock.expect(['c','d').return('fake3');
97
-
98
- mock(['a','b']); //returns 'fake1'
99
- mock(['a','b']); //returns 'fake2'
100
- mock(['c','d']); //returns 'fake3'
101
- mock(['a','b']); //throws unexpected arguments
102
- mock(['foo', 'bar']); //throws unexpected arguments
103
- ```
104
-
105
- __expecting struct__
106
-
107
- ```js
108
- var mock = require('a').mock();
109
- var obj = {};
110
- mock.expect({a : 1}).return('fake1');
111
- mock.expect({a : 2}).return('fake2');
112
- mock.expect({a : 2, b : {c : 'foo', d : ['me', 'too']}}).return('fake3');
113
- mock.expect(obj).return('fake4');
114
- mock.expect({}).return('will never happen');
115
-
116
- mock({a : 'x'}); //throws unexpected arguments
117
- mock({a : 1}); //returns 'fake1'
118
- mock({a : 2}); //returns 'fake2'
119
- mock({a : 2, b : {c : 'foo', d : ['me', 'too']}}); //returns 'fake3'
120
- mock(obj); //returns 'fake3'
121
- mock({}); //throws unexpected arguments
122
- ```
123
-
124
- __repeats__
125
-
126
- ```js
127
- var mock = require('a').mock();
128
- mock.expect().return('fake').repeat(2);
129
-
130
- mock(); //returns 'fake'
131
- mock(); //returns 'fake'
132
- mock(); //throws unexpected arguments
133
- ```
134
-
135
- __infinite repeats__
136
-
137
- ```js
138
- var mock = require('a').mock();
139
- mock.expect().return('fake').repeatAny();
140
-
141
- mock(); //returns 'fake'
142
- mock(); //returns 'fake'
143
- mock(); //returns 'fake'...
144
- ```
145
-
146
-
147
- __ignoring a single argument__
148
-
149
- ```js
150
- var mock = require('a').mock();
151
- mock.ignore().expect('foo').return('fake1');
152
-
153
- mock('ignore me', 'foo'); //returns 'fake1'
154
- mock(); //throws unexpected arguments
155
- ```
156
-
157
- __ignoring all arguments__
158
-
159
- ```js
160
- var mock = require('a').mock();
161
- mock.expectAnything().return('fake1'); //same as expectAnything
162
-
163
- mock('someRandomValue', 'whatever'); //returns 'fake1'
164
- mock(); //throws unexpected arguments
165
- ```
166
-
167
-
168
- __throwing exceptions__
169
-
170
- ```js
171
- var mock = require('a').mock();
172
- var error = new Error('invalid operation');
173
- mock.expect().throw(error);
174
- mock.expect().return('fake');
175
-
176
- mock(); //throws error
177
- mock(); //returns 'fake'
178
- ```
179
-
180
- __intercepting__
181
-
182
- ```js
183
- var mock = require('a').mock();
184
- mock.expect('testValue').whenCalled(onCalled).return('fake1');
185
-
186
- function onCalled(arg) {
187
- //arg == 'testValue'
188
- }
189
-
190
- mock('testValue'); //returns 'fake1'
191
- mock(); //throws unexpected arguments
192
- ```
193
-
194
- __verify (fail)__
195
-
196
- ```js
197
- var mock = require('a').mock();
198
- mock.expect('testValue1').return('fake1');
199
- mock.expect('testValue2').return('fake2');
200
-
201
- mock('testValue1'); //returns 'fake1'
202
- mock.verify(); //throws mock has 1 pending functions
203
- ```
204
-
205
- __verify (success)__
206
-
207
- ```js
208
- var mock = require('a').mock();
209
- mock.expect('testValue1').return('fake1');
210
- mock.expect('testValue2').return('fake2');
211
-
212
- mock('testValue1'); //returns 'fake1'
213
- mock('testValue2'); //returns 'fake2'
214
- mock.verify(); //returns true
215
- ```
216
-
217
- __returning void (compact syntax)__
218
-
219
- ```js
220
- var mock = require('a').mock();
221
- mock.expect('testValue1');
222
- mock.expect('testValue2').repeat(2);
223
-
224
- mock('testValue1'); //returns undefined
225
- mock('testValue2'); //returns undefined
226
- mock('testValue2'); //returns undefined
227
- mock.verify(); //returns true
228
- ```
229
-
230
- __..is equivalent to ..__
231
- ```js
232
- var mock = require('a').mock();
233
- mock.expect('testValue1').return();
234
- mock.expect('testValue2').return().repeat(2);
235
-
236
- mock('testValue1'); //returns undefined
237
- mock('testValue2'); //returns undefined
238
- mock('testValue2'); //returns undefined
239
- mock.verify(); //returns true
240
- ```
241
-
242
- __reset mock__
243
- ```js
244
- var original = function() {
245
- return 'realValue';
246
- }
247
-
248
- var mock = require('a').mock(original);
249
- original = mock;
250
- mock.expect().return('fake');
251
- mock.reset();
252
-
253
- original(); //returns 'realValue'
254
- ```
255
-
256
- __returning resolved promise__
257
- ```js
258
- var mock = require('a').mock();
259
- mock.expect('foo').resolve('fake');
260
-
261
- mock('foo').then(function(returned){
262
- //returned == 'fake'
263
- });
264
- ```
265
-
266
- __returning rejected promise__
267
- ```js
268
- var mock = require('a').mock();
269
- mock.expect('foo').reject('fake');
270
-
271
- mock('foo').then(null, function(returned){
272
- //returned == 'fake'
273
- });
274
- ```
275
-
276
- __strict mock - advanced scenario__
277
-
278
- ```js
279
- var mock = require('a').mock();
280
- mock.expect('testValue').ignore().whenCalled(onCalled).return('fake1');
281
-
282
- function onCalled(arg,callback) {
283
- //arg == 'testValue'
284
- //callback == foo
285
- }
286
-
287
- function foo() {
288
- }
289
-
290
-
291
- mock('testValue', foo); //returns 'fake1'
292
- mock.verify() //returns true
293
- mock('testValue',foo); //throws unexpected arguments
294
- ```
295
-
296
- Mocking require
297
- ----------------
298
-
299
- __expectRequire__
300
-
301
- ```js
302
- var fakeDep = {};
303
-
304
- var expectRequire = require('a').expectRequire;
305
- expectRequire('./realDep').return(fakeDep);
306
-
307
- require('./realDep'); //returns fakeDep
308
- require('./realDep'); //returns realDep (behaves like a partial mock)
309
- ```
310
-
311
- __requireMock (compact syntax)__
312
-
313
- ```js
314
- var requireMock = require('a').requireMock;
315
- var fakeDep = requireMock('./realDep'); //returns a strict mock
316
-
317
- require('./realDep'); //returns fakeDep
318
- require('./realDep'); //returns realDep
319
- ```
320
-
321
- __..is equivalent to ..__
322
-
323
- ```js
324
- var mock = require('a').mock();
325
- var expectRequire = require('a').expectRequire;
326
-
327
- var fakeDep = mock;
328
- expectRequire('./realDep').return(fakeDep);
329
-
330
- require('./realDep'); //returns fakeDep
331
- require('./realDep'); //returns realDep
332
- ```
333
-
334
- __reset mocks for require__
335
-
336
- ```js
337
- var fakeDep = {};
338
-
339
- var expectRequire = require('a').expectRequire;
340
- expectRequire('./realDep').return(fakeDep);
341
- expectRequire.reset();
342
-
343
- require('./realDep'); //returns realDep
344
- ```
345
-
346
- __..is equivalent to ..__
347
-
348
- ```js
349
- var requireMock = require('a').requireMock;
350
- var fakeDep = requireMock('./realDep'); //returns a strict mock
351
- requireMock.reset(); //is an alias for expectRequire.reset()
352
-
353
- require('./realDep'); //returns realDep
354
-
355
- ```
356
- Mocking an object
357
- -----------------
358
- __partial object mock__
359
-
360
- ```js
361
- function newCustomer(_name) {
362
- var c = {};
363
-
364
- c.getName = function ()
365
- {
366
- return _name;
367
- };
368
-
369
- return c;
370
- }
371
-
372
- var customer = newCustomer('Alfonzo The Real');
373
- var customerMock = mock(customer);
374
-
375
- customerMock.getName.expect().return('Johnny Fake');
376
-
377
- customer.getName(); //returns Johnny Fake
378
- customer.getName(); //returns Alfonzo The Real
379
- customerMock.verify(); //returns true
380
- ```
381
-
382
- Mocking promises
383
- -----------------
384
- __mocking resolve__
385
-
386
- ```js
387
- var a = require('a');
388
-
389
- var promise = a.then(); //mocked promise
390
-
391
- promise.then(success,error);
392
- promise.resolve('success');
393
-
394
- function success(arg) {
395
- console.log(arg);//success
396
- }
397
-
398
- function error(e) {
399
- //will not happen
400
- }
401
- ```
402
-
403
- __mocking resolve (alternative syntax)__
404
-
405
- ```js
406
- var a = require('a');
407
-
408
- var promise = a.then(); //mocked promise
409
-
410
- promise.then(success,error);
411
- promise('success');
412
-
413
- function success(arg) {
414
- console.log(arg);//success
415
- }
416
-
417
- function error(e) {
418
- //will not happen
419
- }
420
- ```
421
-
422
- __mocking reject__
423
-
424
- ```js
425
- var a = require('a');
426
-
427
- var promise = a.then();
428
-
429
- promise.then(success,error);
430
- promise.reject(new Error('error'));
431
-
432
- function success(arg) {
433
- //will not happen
434
- }
435
-
436
- function error(e) {
437
- console.log(e.stack);//will happen
438
- }
439
- ```
440
-
441
- __mocking reject (alternative syntax)__
442
-
443
- ```js
444
- var a = require('a');
445
-
446
- var promise = a.then();
447
-
448
- promise.then(success,error);
449
- promise(null,new Error('error'));
450
-
451
- function success(arg) {
452
- //will not happen
453
- }
454
-
455
- function error(e) {
456
- console.log(e.stack);//will happen
457
- }
458
- ```
459
-
460
- _A test framework_
461
- ===================
462
- _A_ test framework is a simplistic, magic-free library providing unit-testing facilities with a compact, bdd-style syntax.
463
-
464
- In contrast to other bdd-style test frameworks, however, it doesn't allow nesting suites in each other in order to test the SUT(subject under test) in different states. Instead, the framework relies on folder structure to describe the state which the SUT currently is. Suite names are generated based on their filenames. As a result there will be many small test files instead of few big ones with test suites nested in each other.
465
-
466
- Test setup -- the "Arrange-Act" part of suites, is separated from the "Assert" part. This way the same setup can be used across different suites. Test setups can, of course, be chained.
467
-
468
-
469
- Examples below can be found here: https://github.com/alfateam/a_demo
470
-
471
- Example
472
- ---------
473
- The test runner ( _a_ ) will search for all files named when*.js in current directory and below.
474
-
475
- Given the following file structure
476
-
477
- - demo/
478
- - counter.js
479
- - counter_specs/
480
- - new/
481
- - increment.js
482
- - when_incremented.js
483
- - new.js
484
- - when_new.js
485
-
486
- __counter.js__
487
-
488
- ```js
489
- module.exports = function () {
490
- var counter = {
491
- value: 0,
492
- increment: function() { value++; }
493
- };
494
-
495
- return counter;
496
- }
497
- ```
498
-
499
- __counter_specs/new.js__
500
-
501
- ```js
502
- function act(c) {
503
- var createCounter = require('../counter');
504
- c.sut = createCounter();
505
- }
506
- module.exports = act;
507
- ```
508
-
509
- __counter_specs/when_new.js__
510
-
511
- ```js
512
- var c = {}; //test context object
513
- var when = require('a').when;
514
-
515
- when('./new', c). //set up
516
- it('should be an object').
517
- assertEqual('object', typeof c.sut)
518
- it('should have value equal to zero').
519
- assertEqual(0, c.sut.value).
520
- it('should fail just for fun').
521
- assertFail('error message');
522
-
523
- ```
524
-
525
- __counter_specs/new/increment.js__
526
-
527
- ```js
528
- function act(c) {
529
- c.sut.increment();
530
- }
531
- act.base = '../new';
532
- module.exports = act;
533
- ```
534
-
535
- __counter_specs/new/when_incremented.js__
536
-
537
- ```js
538
- var c = {};
539
- var when = require('a').when;
540
-
541
- when('./increment', c).
542
- it('should have value equal to 1').
543
- assertEqual(1, c.sut.value);
544
-
545
- ```
546
-
547
- In demo directory run _a_
548
-
549
- user@localhost:~/a_demo $ a
550
-
551
- » counter_specs » new
552
-
553
- ✓ should be an object
554
- ✓ should have value equal to zero
555
- should fail just for fun
556
-
557
- » counter_specs » new » increment
558
-
559
- ✓ should have value equal to 1
560
-
561
- ========== Summary =============
562
-
563
- counter_specs » new
564
- should fail just for fun
565
-
566
- AssertionError: error message
567
- at retval.assertFail (/home/user/a_demo/node_modules/a/when/it.js:14:11)
568
- at Object.test (/home/user/a_demo/node_modules/a/when/test_invoker.js:5:3)
569
- at Object.retval.assertFail (/home/user/a_demo/node_modules/a/when/it.js:13:5)
570
- at Object.<anonymous> (/home/user/a_demo/counter_specs/when_new.js:11:3)
571
- at Module._compile (module.js:449:26)
572
- at Object.Module._extensions..js (module.js:467:10)
573
- at Module.load (module.js:356:32)
574
- at Function.Module._load (module.js:312:12)
575
- at Module.require (module.js:362:17)
576
- at require (module.js:378:17)
577
- ------------
578
-
579
- suites: 2, passed: 3, failed: 1
580
-
581
- Async test support
582
- ------------------
583
- modified act file should like like this:
584
-
585
- ```js
586
-
587
- function act(c) {
588
- ...
589
- return c.sut(c.arguments); //returns promise
590
- }
591
-
592
- ```
593
-
594
- or
595
-
596
- ```js
597
-
598
- async function act(c) {
599
- ...
600
- await c.sut(c.arguments);
601
- }
602
-
603
- ```
604
- test file should look like this
605
- ```js
606
- var when = require('a').when;
607
- var c = {};
608
-
609
- when(c).then(it => {
610
- it('....').assertXXXX();
611
- });
612
-
613
- ```
614
-
615
- Release Notes
616
- ---------------
617
- __2.1.0__
618
- - short hand syntax for returning promises (sync)
619
-
620
- __2.0.13__
621
- - a_mock 1.0.4, implements promise mock which is synchronous
622
-
623
- __2.0.12__
624
- - assertOk(falsy) would not throw (#21)
625
- - report suites that cannot be loaded as unrunnable (#20)
626
- - fix async test result reporting order
627
-
628
- __2.0.11__
629
- - README update
630
-
631
- __2.0.10__
632
- - disable runtime babel transpiling by default, set A_TEST_BABEL_REGISTER environment variable to enable it.
633
-
634
- __2.0.9__
635
- - replace dependency for coloured console output in test runner.
636
-
637
- __2.0.8__
638
- - update README
639
-
640
- __2.0.7__
641
- - test runner is able to load modules exporting a default function.
642
-
643
- __2.0.6__
644
- - test runner reports when a file with tests is not runnable
645
-
646
- __2.0.5__
647
- - test runner uses _node_ instead of _nodejs_
648
-
649
- __2.0.4__
650
- - correct reporting of aborted promise mocks
651
-
652
- __2.0.3__
653
- - abort Unfulfilled promise mocks after 10secs.
654
-
655
- __2.0.2__
656
- - forgotten dependency version
657
-
658
- __2.0.1__
659
- - Fix bin section in package.json.
660
- - Fix memory leak in the test runner
661
-
662
- __2.0.0__
663
- BREAKING CHANGE: Support async testing.
664
- - Tests relying on ability of [deferred][2] to resolve synchronously expected to cause problems.
665
- - Unfulfilled promises will prevent runner from exiting.
666
- - Runner uses babel-runtime which implies strict mode.
667
-
668
- __1.0.1__
669
- ExpectAnything() can be nested - for backwards compatability only.
670
- __1.0.0__
671
- ExpectAnything() no longer expects only one argument, but arbitary number of arguments. Use ignore() if you want to ignore a single argument.
672
- __0.4.8__
673
- Executable test runner "when" is deprecated. Use "a" instead.
674
- __0.4.7__
675
- Inconclusive tests are accounted as failed in exit code.
676
- __0.4.6__
677
- Fixed memory leak in test runner.
678
- __0.4.5__
679
- Display stack trace of inconclusive suites.
680
- Use dependency [deferred][2] instead of [promise][3].
681
- __0.4.4__
682
- Introduced promise mocks.
683
- Tests with failing setup are reported as inconclusive.
684
- Bugfix: Test names no longer converted to lowercase.
685
- __0.4.3__
686
- Can reset expectations on mocks by mock.reset.
687
- Renamed expectRequire.clear to expectRequire.reset. Same goes for for requireMock.
688
- __0.4.2__
689
- Can clear expectations on require by using expectRequire.clear.
690
- __0.4.1__
691
- "When" can accept function instead of separate act file. See example in [demo][1] repo.
692
- __0.4.0__
693
- Cleaner output on failed assertions.
694
- __0.3.9__
695
- Can inherit act by convention. See examples in [demo][0] repo.
696
- __0.3.8__
697
- Cleaner stack trace on mock errors.
698
- __0.3.7__
699
- Test path can be sent as argument to test runner.
700
- If no path is specified, the test runner will run from current directory.
701
- Example: ```when c:/devel/foo/testFolder```
702
- __0.3.6__
703
- Exit code is equal to number of failing tests.
704
- __0.3.5__
705
- Tests files are run in hierarchical order from top to bottom.
706
- __0.3.4__
707
- Cache was cleared at wrong time. This could lead to overflow when running large amount of tests.
708
- Make sure you update globally (npm update a -g) to get this fix, not only the local dependency.
709
- __0.3.3__
710
- Error in documentation about structs.
711
- __0.3.2__
712
- Mocks can be set up to throw.
713
- __0.3.1__
714
- "when" deletes all cached modules before executing. This ensures tests are isolated.
715
- ignore is alias for expectAnything.
716
- "When" can resolve act by camcelCase convention. If test class is named "whenFoo.js", it will assume "foo.js" is the act.
717
-
718
- __0.3.0__
719
- expectArray is deprecated, use expect instead.
720
- expect now handles structs - equality is acheived when same propertyNames and equal leaf properties.
721
-
722
- __0.2.9__
723
- "When" can resolve act by convention. If test class is named "when_foo.js", it will assume "foo.js" is the act.
724
- Example, given when_foo.js:
725
- ```js
726
- var c = {};
727
- var when = require('a').when;
728
-
729
- when(c). //equivalent to: when('./foo',c)....
730
- it('should have value equal to 1').
731
- assertEqual(1, c.sut.value);
732
-
733
- ```
734
- [0]:https://github.com/alfateam/a_demo
735
- [1]:https://github.com/alfateam/a_demo/blob/master/assert_specs/when_assertions.js
736
- [2]:https://www.npmjs.org/package/deferred
737
- [3]:https://www.npmjs.org/package/promise
1
+ _a_
2
+ ===
3
+ _Mocking framework_ + _testing framework_.
4
+
5
+
6
+ The mocking framework can be used in any JavaScript testing framework.
7
+
8
+ The testing framework has a short and concise bdd syntax with reusable contexts.
9
+
10
+ __To install:__
11
+
12
+ ```
13
+ npm install a
14
+ ```
15
+
16
+
17
+
18
+ __If you want the test framework, install it globally too:__
19
+
20
+ ```
21
+ npm install a -g
22
+ ```
23
+
24
+
25
+
26
+ _Mocking_
27
+ ===================
28
+
29
+ Mocking a function
30
+ ------------------
31
+
32
+ __Partial mock__
33
+
34
+ ```js
35
+ var original = function() {
36
+ return 'realValue';
37
+ }
38
+
39
+ var mock = require('a').mock(original);
40
+ original = mock;
41
+ mock.expect().return('fake');
42
+
43
+ original(); //returns 'fake'
44
+ original(); //returns 'realValue'
45
+ ```
46
+
47
+
48
+
49
+ __Strict mock__
50
+
51
+ ```js
52
+ var mock = require('a').mock();
53
+ mock.expect().return('fake');
54
+
55
+ mock(); //returns 'fake'
56
+ mock(); //throws unexpected arguments
57
+ ```
58
+
59
+
60
+
61
+ __Expecting arguments__
62
+
63
+ ```js
64
+ var mock = require('a').mock();
65
+ mock.expect('testValue1').return('fake1');
66
+ mock.expect('testValue2').return('fake2');
67
+
68
+ mock('testValue1'); //returns 'fake1'
69
+ mock('testValue2'); //returns 'fake2'
70
+ mock(); //throws unexpected arguments
71
+ mock('foo'); //throws unexpected arguments
72
+ ```
73
+
74
+
75
+
76
+ __Expecting multiple arguments__
77
+
78
+ ```js
79
+ var mock = require('a').mock();
80
+ mock.expect('firstArg1', 'secondArg1').return('fake1');
81
+ mock.expect('firstArg2', 'secondArg2').return('fake2');
82
+
83
+
84
+ mock('firstArg1', 'secondArg1'); //returns 'fake1'
85
+ mock('firstArg2', 'secondArg2'); //returns 'fake2'
86
+ mock('foo'); //throws unexpected arguments
87
+ mock('foo', 'bar'); //throws unexpected arguments
88
+ ```
89
+
90
+ __Expecting array__
91
+
92
+ ```js
93
+ var mock = require('a').mock();
94
+ mock.expect(['a','b']).return('fake1');
95
+ mock.expect(['a','b').return('fake2');
96
+ mock.expect(['c','d').return('fake3');
97
+
98
+ mock(['a','b']); //returns 'fake1'
99
+ mock(['a','b']); //returns 'fake2'
100
+ mock(['c','d']); //returns 'fake3'
101
+ mock(['a','b']); //throws unexpected arguments
102
+ mock(['foo', 'bar']); //throws unexpected arguments
103
+ ```
104
+
105
+ __Expecting struct__
106
+
107
+ ```js
108
+ var mock = require('a').mock();
109
+ var obj = {};
110
+ mock.expect({a : 1}).return('fake1');
111
+ mock.expect({a : 2}).return('fake2');
112
+ mock.expect({a : 2, b : {c : 'foo', d : ['me', 'too']}}).return('fake3');
113
+ mock.expect(obj).return('fake4');
114
+ mock.expect({}).return('will never happen');
115
+
116
+ mock({a : 'x'}); //throws unexpected arguments
117
+ mock({a : 1}); //returns 'fake1'
118
+ mock({a : 2}); //returns 'fake2'
119
+ mock({a : 2, b : {c : 'foo', d : ['me', 'too']}}); //returns 'fake3'
120
+ mock(obj); //returns 'fake4'
121
+ mock({}); //throws unexpected arguments
122
+ ```
123
+
124
+ __Repeats__
125
+
126
+ ```js
127
+ var mock = require('a').mock();
128
+ mock.expect().return('fake').repeat(2);
129
+
130
+ mock(); //returns 'fake'
131
+ mock(); //returns 'fake'
132
+ mock(); //throws unexpected arguments
133
+ ```
134
+
135
+ __Infinite repeats__
136
+
137
+ ```js
138
+ var mock = require('a').mock();
139
+ mock.expect().return('fake').repeatAny();
140
+
141
+ mock(); //returns 'fake'
142
+ mock(); //returns 'fake'
143
+ mock(); //returns 'fake'...
144
+ ```
145
+
146
+
147
+ __Ignoring a single argument__
148
+
149
+ ```js
150
+ var mock = require('a').mock();
151
+ mock.ignore().expect('foo').return('fake1');
152
+
153
+ mock('ignore me', 'foo'); //returns 'fake1'
154
+ mock(); //throws unexpected arguments
155
+ ```
156
+
157
+ __Ignoring all arguments__
158
+
159
+ ```js
160
+ var mock = require('a').mock();
161
+ mock.expectAnything().return('fake1'); //same as expectAnything
162
+
163
+ mock('someRandomValue', 'whatever'); //returns 'fake1'
164
+ mock(); //throws unexpected arguments
165
+ ```
166
+
167
+
168
+ __Throwing exceptions__
169
+
170
+ ```js
171
+ var mock = require('a').mock();
172
+ var error = new Error('invalid operation');
173
+ mock.expect().throw(error);
174
+ mock.expect().return('fake');
175
+
176
+ mock(); //throws error
177
+ mock(); //returns 'fake'
178
+ ```
179
+
180
+ __Intercepting__
181
+
182
+ ```js
183
+ var mock = require('a').mock();
184
+ mock.expect('testValue').whenCalled(onCalled).return('fake1');
185
+
186
+ function onCalled(arg) {
187
+ //arg == 'testValue'
188
+ }
189
+
190
+ mock('testValue'); //returns 'fake1'
191
+ mock(); //throws unexpected arguments
192
+ ```
193
+
194
+ __Verify (fail)__
195
+
196
+ ```js
197
+ var mock = require('a').mock();
198
+ mock.expect('testValue1').return('fake1');
199
+ mock.expect('testValue2').return('fake2');
200
+
201
+ mock('testValue1'); //returns 'fake1'
202
+ mock.verify(); //throws mock has 1 pending functions
203
+ ```
204
+
205
+ __Verify (success)__
206
+
207
+ ```js
208
+ var mock = require('a').mock();
209
+ mock.expect('testValue1').return('fake1');
210
+ mock.expect('testValue2').return('fake2');
211
+
212
+ mock('testValue1'); //returns 'fake1'
213
+ mock('testValue2'); //returns 'fake2'
214
+ mock.verify(); //returns true
215
+ ```
216
+
217
+ __returning void (compact syntax)__
218
+
219
+ ```js
220
+ var mock = require('a').mock();
221
+ mock.expect('testValue1');
222
+ mock.expect('testValue2').repeat(2);
223
+
224
+ mock('testValue1'); //returns undefined
225
+ mock('testValue2'); //returns undefined
226
+ mock('testValue2'); //returns undefined
227
+ mock.verify(); //returns true
228
+ ```
229
+
230
+ __..is equivalent to ..__
231
+ ```js
232
+ var mock = require('a').mock();
233
+ mock.expect('testValue1').return();
234
+ mock.expect('testValue2').return().repeat(2);
235
+
236
+ mock('testValue1'); //returns undefined
237
+ mock('testValue2'); //returns undefined
238
+ mock('testValue2'); //returns undefined
239
+ mock.verify(); //returns true
240
+ ```
241
+
242
+ __Reset mock__
243
+ ```js
244
+ var original = function() {
245
+ return 'realValue';
246
+ }
247
+
248
+ var mock = require('a').mock(original);
249
+ original = mock;
250
+ mock.expect().return('fake');
251
+ mock.reset();
252
+
253
+ original(); //returns 'realValue'
254
+ ```
255
+
256
+ __Returning resolved promise__
257
+ ```js
258
+ var mock = require('a').mock();
259
+ mock.expect('foo').resolve('fake');
260
+
261
+ mock('foo').then(function(returned){
262
+ //returned == 'fake'
263
+ });
264
+ ```
265
+
266
+ __Returning rejected promise__
267
+ ```js
268
+ var mock = require('a').mock();
269
+ mock.expect('foo').reject('fake');
270
+
271
+ mock('foo').then(null, function(returned){
272
+ //returned == 'fake'
273
+ });
274
+ ```
275
+
276
+ __Strict mock - advanced scenario__
277
+
278
+ ```js
279
+ var mock = require('a').mock();
280
+ mock.expect('testValue').ignore().whenCalled(onCalled).return('fake1');
281
+
282
+ function onCalled(arg,callback) {
283
+ //arg == 'testValue'
284
+ //callback == foo
285
+ }
286
+
287
+ function foo() {
288
+ }
289
+
290
+
291
+ mock('testValue', foo); //returns 'fake1'
292
+ mock.verify() //returns true
293
+ mock('testValue',foo); //throws unexpected arguments
294
+ ```
295
+
296
+ Mocking require
297
+ ----------------
298
+
299
+ __expectRequire__
300
+
301
+ ```js
302
+ var fakeDep = {};
303
+
304
+ var expectRequire = require('a').expectRequire;
305
+ expectRequire('./realDep').return(fakeDep);
306
+
307
+ require('./realDep'); //returns fakeDep
308
+ require('./realDep'); //returns realDep (behaves like a partial mock)
309
+ ```
310
+
311
+ __requireMock (compact syntax)__
312
+
313
+ ```js
314
+ var requireMock = require('a').requireMock;
315
+ var fakeDep = requireMock('./realDep'); //returns a strict mock
316
+
317
+ require('./realDep'); //returns fakeDep
318
+ require('./realDep'); //returns realDep
319
+ ```
320
+
321
+ __..is equivalent to ..__
322
+
323
+ ```js
324
+ var mock = require('a').mock();
325
+ var expectRequire = require('a').expectRequire;
326
+
327
+ var fakeDep = mock;
328
+ expectRequire('./realDep').return(fakeDep);
329
+
330
+ require('./realDep'); //returns fakeDep
331
+ require('./realDep'); //returns realDep
332
+ ```
333
+
334
+ __Reset mocks for require__
335
+
336
+ ```js
337
+ var fakeDep = {};
338
+
339
+ var expectRequire = require('a').expectRequire;
340
+ expectRequire('./realDep').return(fakeDep);
341
+ expectRequire.reset();
342
+
343
+ require('./realDep'); //returns realDep
344
+ ```
345
+
346
+ __..is equivalent to ..__
347
+
348
+ ```js
349
+ var requireMock = require('a').requireMock;
350
+ var fakeDep = requireMock('./realDep'); //returns a strict mock
351
+ requireMock.reset(); //is an alias for expectRequire.reset()
352
+
353
+ require('./realDep'); //returns realDep
354
+
355
+ ```
356
+ Mocking an object
357
+ -----------------
358
+ __Partial object mock__
359
+
360
+ ```js
361
+ function newCustomer(_name) {
362
+ var c = {};
363
+
364
+ c.getName = function ()
365
+ {
366
+ return _name;
367
+ };
368
+
369
+ return c;
370
+ }
371
+
372
+ var customer = newCustomer('Alfonzo The Real');
373
+ var customerMock = mock(customer);
374
+
375
+ customerMock.getName.expect().return('Johnny Fake');
376
+
377
+ customer.getName(); //returns Johnny Fake
378
+ customer.getName(); //returns Alfonzo The Real
379
+ customerMock.verify(); //returns true
380
+ ```
381
+
382
+ Mocking promises
383
+ -----------------
384
+ __Mocking resolve__
385
+
386
+ ```js
387
+ var a = require('a');
388
+
389
+ var promise = a.then(); //mocked promise
390
+
391
+ promise.then(success,error);
392
+ promise.resolve('success');
393
+
394
+ function success(arg) {
395
+ console.log(arg);//success
396
+ }
397
+
398
+ function error(e) {
399
+ //will not happen
400
+ }
401
+ ```
402
+
403
+ __Mocking resolve (alternative syntax)__
404
+
405
+ ```js
406
+ var a = require('a');
407
+
408
+ var promise = a.then(); //mocked promise
409
+
410
+ promise.then(success,error);
411
+ promise('success');
412
+
413
+ function success(arg) {
414
+ console.log(arg);//success
415
+ }
416
+
417
+ function error(e) {
418
+ //will not happen
419
+ }
420
+ ```
421
+
422
+ __Mocking reject__
423
+
424
+ ```js
425
+ var a = require('a');
426
+
427
+ var promise = a.then();
428
+
429
+ promise.then(success,error);
430
+ promise.reject(new Error('error'));
431
+
432
+ function success(arg) {
433
+ //will not happen
434
+ }
435
+
436
+ function error(e) {
437
+ console.log(e.stack);//will happen
438
+ }
439
+ ```
440
+
441
+ __Mocking reject (alternative syntax)__
442
+
443
+ ```js
444
+ var a = require('a');
445
+
446
+ var promise = a.then();
447
+
448
+ promise.then(success,error);
449
+ promise(null,new Error('error'));
450
+
451
+ function success(arg) {
452
+ //will not happen
453
+ }
454
+
455
+ function error(e) {
456
+ console.log(e.stack);//will happen
457
+ }
458
+ ```
459
+
460
+ _A test framework_
461
+ ===================
462
+ <b>From version 3.0.0 this is in a separate package: [npmjs.com/package/a_test](https://npmjs.com/package/a_test)</b>
463
+ _A_ test framework is a simplistic, magic-free library providing unit-testing facilities with a compact, bdd-style syntax.
464
+
465
+ In contrast to other bdd-style test frameworks, it doesn't allow nesting suites in each other in order to test the SUT(subject under test) in different states. Instead, the framework relies on folder structure to describe the state. The SUT currently has that folder structure. Suite names are generated based on their filenames. As a result, there will be many small test files without nested test suites instead of a few big test files with nested test suites.
466
+
467
+ Test setup, the "Arrange-Act" part of suites, is separated from the "Assert" part. This way the same setup can be used across different suites. Test setups can be chained.
468
+
469
+
470
+ Examples below can be found here: https://github.com/alfateam/a_demo
471
+
472
+ Example
473
+ ---------
474
+ The test runner ( _a_ ) will search for all files named 'when*.js' in the current and sub-directories.
475
+
476
+ Given the following file structure
477
+
478
+ - demo/
479
+ - counter.js
480
+ - counter_specs/
481
+ - new/
482
+ - increment.js
483
+ - when_incremented.js
484
+ - new.js
485
+ - when_new.js
486
+
487
+ __counter.js__
488
+
489
+ ```js
490
+ module.exports = function () {
491
+ var counter = {
492
+ value: 0,
493
+ increment: function() { value++; }
494
+ };
495
+
496
+ return counter;
497
+ }
498
+ ```
499
+
500
+ __counter_specs/new.js__
501
+
502
+ ```js
503
+ function act(c) {
504
+ var createCounter = require('../counter');
505
+ c.sut = createCounter();
506
+ }
507
+ module.exports = act;
508
+ ```
509
+
510
+ __counter_specs/when_new.js__
511
+
512
+ ```js
513
+ var c = {}; //test context object
514
+ var when = require('a').when;
515
+
516
+ when('./new', c). //set up
517
+ it('should be an object').
518
+ assertEqual('object', typeof c.sut)
519
+ it('should have value equal to zero').
520
+ assertEqual(0, c.sut.value).
521
+ it('should fail just for fun').
522
+ assertFail('error message');
523
+
524
+ ```
525
+
526
+ __counter_specs/new/increment.js__
527
+
528
+ ```js
529
+ function act(c) {
530
+ c.sut.increment();
531
+ }
532
+ act.base = '../new';
533
+ module.exports = act;
534
+ ```
535
+
536
+ __counter_specs/new/when_incremented.js__
537
+
538
+ ```js
539
+ var c = {};
540
+ var when = require('a').when;
541
+
542
+ when('./increment', c).
543
+ it('should have value equal to 1').
544
+ assertEqual(1, c.sut.value);
545
+
546
+ ```
547
+
548
+ __In demo directory, run _a_ __
549
+
550
+ user@localhost:~/a_demo $ a
551
+
552
+ » counter_specs » new
553
+
554
+ ✓ should be an object
555
+ should have value equal to zero
556
+ ✘ should fail just for fun
557
+
558
+ » counter_specs » new » increment
559
+
560
+ ✓ should have value equal to 1
561
+
562
+ ========== Summary =============
563
+
564
+ counter_specs » new
565
+ ✘ should fail just for fun
566
+
567
+ AssertionError: error message
568
+ at retval.assertFail (/home/user/a_demo/node_modules/a/when/it.js:14:11)
569
+ at Object.test (/home/user/a_demo/node_modules/a/when/test_invoker.js:5:3)
570
+ at Object.retval.assertFail (/home/user/a_demo/node_modules/a/when/it.js:13:5)
571
+ at Object.<anonymous> (/home/user/a_demo/counter_specs/when_new.js:11:3)
572
+ at Module._compile (module.js:449:26)
573
+ at Object.Module._extensions..js (module.js:467:10)
574
+ at Module.load (module.js:356:32)
575
+ at Function.Module._load (module.js:312:12)
576
+ at Module.require (module.js:362:17)
577
+ at require (module.js:378:17)
578
+ ------------
579
+
580
+ suites: 2, passed: 3, failed: 1
581
+
582
+ Async test support
583
+ ------------------
584
+ Modified act files should look like this:
585
+
586
+ ```js
587
+
588
+ function act(c) {
589
+ ...
590
+ return c.sut(c.arguments); //returns promise
591
+ }
592
+
593
+ ```
594
+
595
+ or
596
+
597
+ ```js
598
+
599
+ async function act(c) {
600
+ ...
601
+ await c.sut(c.arguments);
602
+ }
603
+
604
+ ```
605
+ Test file should look like this:
606
+ ```js
607
+ var when = require('a').when;
608
+ var c = {};
609
+
610
+ when(c).then(it => {
611
+ it('....').assertXXXX();
612
+ });
613
+
614
+ ```
615
+
616
+ Release Notes
617
+ ---------------
618
+ __3.0.0__
619
+ - The the testing framework is moved to separate repo: [npmjs.com/package/a_test](https://npmjs.com/package/a_test)
620
+
621
+ __2.1.2__
622
+ - [typo in docs](https://github.com/alfateam/a/pull/4)
623
+
624
+ __2.1.0__
625
+ - short hand syntax for returning promises (sync)
626
+
627
+ __2.0.13__
628
+ - a_mock 1.0.4, implements promise mock which is synchronous
629
+
630
+ __2.0.12__
631
+ - assertOk(falsy) would not throw (#21)
632
+ - report suites that cannot be loaded as unrunnable (#20)
633
+ - fix async test result reporting order
634
+
635
+ __2.0.11__
636
+ - README update
637
+
638
+ __2.0.10__
639
+ - disable runtime babel transpiling by default, set A_TEST_BABEL_REGISTER environment variable to enable it.
640
+
641
+ __2.0.9__
642
+ - replace dependency for coloured console output in test runner.
643
+
644
+ __2.0.8__
645
+ - update README
646
+
647
+ __2.0.7__
648
+ - test runner is able to load modules exporting a default function.
649
+
650
+ __2.0.6__
651
+ - test runner reports when a file with tests is not runnable
652
+
653
+ __2.0.5__
654
+ - test runner uses _node_ instead of _nodejs_
655
+
656
+ __2.0.4__
657
+ - correct reporting of aborted promise mocks
658
+
659
+ __2.0.3__
660
+ - abort Unfulfilled promise mocks after 10secs.
661
+
662
+ __2.0.2__
663
+ - forgotten dependency version
664
+
665
+ __2.0.1__
666
+ - Fix bin section in package.json.
667
+ - Fix memory leak in the test runner
668
+
669
+ __2.0.0__
670
+ BREAKING CHANGE: Support async testing.
671
+ - Tests relying on ability of [deferred][2] to resolve synchronously expected to cause problems.
672
+ - Unfulfilled promises will prevent runner from exiting.
673
+ - Runner uses babel-runtime which implies strict mode.
674
+
675
+ __1.0.1__
676
+ ExpectAnything() can be nested - for backwards compatability only.
677
+ __1.0.0__
678
+ ExpectAnything() no longer expects only one argument, but arbitary number of arguments. Use ignore() if you want to ignore a single argument.
679
+ __0.4.8__
680
+ Executable test runner "when" is deprecated. Use "a" instead.
681
+ __0.4.7__
682
+ Inconclusive tests are accounted as failed in exit code.
683
+ __0.4.6__
684
+ Fixed memory leak in test runner.
685
+ __0.4.5__
686
+ Display stack trace of inconclusive suites.
687
+ Use dependency [deferred][2] instead of [promise][3].
688
+ __0.4.4__
689
+ Introduced promise mocks.
690
+ Tests with failing setup are reported as inconclusive.
691
+ Bugfix: Test names no longer converted to lowercase.
692
+ __0.4.3__
693
+ Can reset expectations on mocks by mock.reset.
694
+ Renamed expectRequire.clear to expectRequire.reset. Same goes for for requireMock.
695
+ __0.4.2__
696
+ Can clear expectations on require by using expectRequire.clear.
697
+ __0.4.1__
698
+ "When" can accept function instead of separate act file. See example in [demo][1] repo.
699
+ __0.4.0__
700
+ Cleaner output on failed assertions.
701
+ __0.3.9__
702
+ Can inherit act by convention. See examples in [demo][0] repo.
703
+ __0.3.8__
704
+ Cleaner stack trace on mock errors.
705
+ __0.3.7__
706
+ Test path can be sent as argument to test runner.
707
+ If no path is specified, the test runner will run from current directory.
708
+ Example: ```when c:/devel/foo/testFolder```
709
+ __0.3.6__
710
+ Exit code is equal to number of failing tests.
711
+ __0.3.5__
712
+ Tests files are run in hierarchical order from top to bottom.
713
+ __0.3.4__
714
+ Cache was cleared at wrong time. This could lead to overflow when running large amount of tests.
715
+ Make sure you update globally (npm update a -g) to get this fix, not only the local dependency.
716
+ __0.3.3__
717
+ Error in documentation about structs.
718
+ __0.3.2__
719
+ Mocks can be set up to throw.
720
+ __0.3.1__
721
+ "when" deletes all cached modules before executing. This ensures tests are isolated.
722
+ ignore is alias for expectAnything.
723
+ "When" can resolve act by camcelCase convention. If test class is named "whenFoo.js", it will assume "foo.js" is the act.
724
+
725
+ __0.3.0__
726
+ expectArray is deprecated, use expect instead.
727
+ expect now handles structs - equality is acheived when same propertyNames and equal leaf properties.
728
+
729
+ __0.2.9__
730
+ "When" can resolve act by convention. If test class is named "when_foo.js", it will assume "foo.js" is the act.
731
+ Example, given when_foo.js:
732
+ ```js
733
+ var c = {};
734
+ var when = require('a').when;
735
+
736
+ when(c). //equivalent to: when('./foo',c)....
737
+ it('should have value equal to 1').
738
+ assertEqual(1, c.sut.value);
739
+
740
+ ```
741
+ [0]:https://github.com/alfateam/a_demo
742
+ [1]:https://github.com/alfateam/a_demo/blob/master/assert_specs/when_assertions.js
743
+ [2]:https://www.npmjs.org/package/deferred
744
+ [3]:https://www.npmjs.org/package/promise