a 2.1.2 → 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 (4) hide show
  1. package/AUTHORS +1 -1
  2. package/README.md +744 -740
  3. package/index.js +17 -17
  4. package/package.json +16 -20
package/README.md CHANGED
@@ -1,740 +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 '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
- _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.2__
618
- - [typo in docs](https://github.com/alfateam/a/pull/4)
619
-
620
- __2.1.0__
621
- - short hand syntax for returning promises (sync)
622
-
623
- __2.0.13__
624
- - a_mock 1.0.4, implements promise mock which is synchronous
625
-
626
- __2.0.12__
627
- - assertOk(falsy) would not throw (#21)
628
- - report suites that cannot be loaded as unrunnable (#20)
629
- - fix async test result reporting order
630
-
631
- __2.0.11__
632
- - README update
633
-
634
- __2.0.10__
635
- - disable runtime babel transpiling by default, set A_TEST_BABEL_REGISTER environment variable to enable it.
636
-
637
- __2.0.9__
638
- - replace dependency for coloured console output in test runner.
639
-
640
- __2.0.8__
641
- - update README
642
-
643
- __2.0.7__
644
- - test runner is able to load modules exporting a default function.
645
-
646
- __2.0.6__
647
- - test runner reports when a file with tests is not runnable
648
-
649
- __2.0.5__
650
- - test runner uses _node_ instead of _nodejs_
651
-
652
- __2.0.4__
653
- - correct reporting of aborted promise mocks
654
-
655
- __2.0.3__
656
- - abort Unfulfilled promise mocks after 10secs.
657
-
658
- __2.0.2__
659
- - forgotten dependency version
660
-
661
- __2.0.1__
662
- - Fix bin section in package.json.
663
- - Fix memory leak in the test runner
664
-
665
- __2.0.0__
666
- BREAKING CHANGE: Support async testing.
667
- - Tests relying on ability of [deferred][2] to resolve synchronously expected to cause problems.
668
- - Unfulfilled promises will prevent runner from exiting.
669
- - Runner uses babel-runtime which implies strict mode.
670
-
671
- __1.0.1__
672
- ExpectAnything() can be nested - for backwards compatability only.
673
- __1.0.0__
674
- ExpectAnything() no longer expects only one argument, but arbitary number of arguments. Use ignore() if you want to ignore a single argument.
675
- __0.4.8__
676
- Executable test runner "when" is deprecated. Use "a" instead.
677
- __0.4.7__
678
- Inconclusive tests are accounted as failed in exit code.
679
- __0.4.6__
680
- Fixed memory leak in test runner.
681
- __0.4.5__
682
- Display stack trace of inconclusive suites.
683
- Use dependency [deferred][2] instead of [promise][3].
684
- __0.4.4__
685
- Introduced promise mocks.
686
- Tests with failing setup are reported as inconclusive.
687
- Bugfix: Test names no longer converted to lowercase.
688
- __0.4.3__
689
- Can reset expectations on mocks by mock.reset.
690
- Renamed expectRequire.clear to expectRequire.reset. Same goes for for requireMock.
691
- __0.4.2__
692
- Can clear expectations on require by using expectRequire.clear.
693
- __0.4.1__
694
- "When" can accept function instead of separate act file. See example in [demo][1] repo.
695
- __0.4.0__
696
- Cleaner output on failed assertions.
697
- __0.3.9__
698
- Can inherit act by convention. See examples in [demo][0] repo.
699
- __0.3.8__
700
- Cleaner stack trace on mock errors.
701
- __0.3.7__
702
- Test path can be sent as argument to test runner.
703
- If no path is specified, the test runner will run from current directory.
704
- Example: ```when c:/devel/foo/testFolder```
705
- __0.3.6__
706
- Exit code is equal to number of failing tests.
707
- __0.3.5__
708
- Tests files are run in hierarchical order from top to bottom.
709
- __0.3.4__
710
- Cache was cleared at wrong time. This could lead to overflow when running large amount of tests.
711
- Make sure you update globally (npm update a -g) to get this fix, not only the local dependency.
712
- __0.3.3__
713
- Error in documentation about structs.
714
- __0.3.2__
715
- Mocks can be set up to throw.
716
- __0.3.1__
717
- "when" deletes all cached modules before executing. This ensures tests are isolated.
718
- ignore is alias for expectAnything.
719
- "When" can resolve act by camcelCase convention. If test class is named "whenFoo.js", it will assume "foo.js" is the act.
720
-
721
- __0.3.0__
722
- expectArray is deprecated, use expect instead.
723
- expect now handles structs - equality is acheived when same propertyNames and equal leaf properties.
724
-
725
- __0.2.9__
726
- "When" can resolve act by convention. If test class is named "when_foo.js", it will assume "foo.js" is the act.
727
- Example, given when_foo.js:
728
- ```js
729
- var c = {};
730
- var when = require('a').when;
731
-
732
- when(c). //equivalent to: when('./foo',c)....
733
- it('should have value equal to 1').
734
- assertEqual(1, c.sut.value);
735
-
736
- ```
737
- [0]:https://github.com/alfateam/a_demo
738
- [1]:https://github.com/alfateam/a_demo/blob/master/assert_specs/when_assertions.js
739
- [2]:https://www.npmjs.org/package/deferred
740
- [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