@lumjs/tests 1.5.0 → 1.7.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.
- package/CHANGELOG.md +48 -2
- package/TODO.md +2 -3
- package/bin/lumtest.js +65 -0
- package/lib/grammar/README.md +6 -0
- package/lib/grammar/tap.js +996 -0
- package/lib/harness/browser.js +18 -0
- package/lib/harness/errors.js +44 -0
- package/lib/harness/index.js +260 -0
- package/lib/harness/node.js +71 -0
- package/lib/harness/parser.js +153 -0
- package/lib/harness/plugin.js +77 -0
- package/lib/harness/queuedtest.js +14 -0
- package/lib/index.js +19 -14
- package/lib/{functional.js → test/functional.js} +21 -14
- package/lib/{test.js → test/index.js} +64 -296
- package/lib/{log.js → test/log.js} +31 -15
- package/lib/test/stats.js +385 -0
- package/package.json +22 -13
- package/lib/harness.js +0 -25
- package/test/basics.js +0 -50
- package/test/data/people.js +0 -58
- package/test/dies.js +0 -17
- package/test/functional_basics.js +0 -54
- package/test/functional_dies.js +0 -17
- package/test/functional_isa.js +0 -23
- package/test/inc/basics.js +0 -72
- package/test/inc/dies.js +0 -78
- package/test/inc/isa.js +0 -110
- package/test/isa.js +0 -23
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
// A functional interface to the test library.
|
|
2
|
-
const Test = require('./
|
|
3
|
-
|
|
4
|
-
// A list of methods we can proxy directly.
|
|
5
|
-
const PROXY_METHODS = Test.$METHODS.all;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Module defining the functional API.
|
|
9
|
-
* @module @lumjs/tests/functional
|
|
10
|
-
*/
|
|
2
|
+
const Test = require('./index');
|
|
11
3
|
|
|
12
4
|
/**
|
|
13
5
|
* A new test instance and a set of functions wrapping it.
|
|
14
|
-
*
|
|
6
|
+
*
|
|
7
|
+
* @typedef {object} module:@lumjs/tests/test/functional.Functional
|
|
15
8
|
* @property {Test} test - The new test instance.
|
|
16
9
|
*
|
|
17
10
|
* All of the rest of the properties are functions that
|
|
18
11
|
* can be imported into a JS scope using destructuring, and
|
|
19
12
|
* which wrap the corresponding test instance method.
|
|
13
|
+
*
|
|
14
|
+
* Basically anything that is a method of the `Test` instance
|
|
15
|
+
* will become a wrapped `function` available in this structure.
|
|
20
16
|
*/
|
|
21
17
|
|
|
22
18
|
/**
|
|
@@ -42,14 +38,25 @@ const PROXY_METHODS = Test.$METHODS.all;
|
|
|
42
38
|
*
|
|
43
39
|
* @param {object} [opts] Options to pass to the `Test` constructor.
|
|
44
40
|
*
|
|
45
|
-
* @
|
|
41
|
+
* @param {function} [testClass=Test] The class we're creating an instance of.
|
|
42
|
+
*
|
|
43
|
+
* This defaults to `Test`, but can be changed to be a sub-class such as
|
|
44
|
+
* `DOMTest` (defined in the `@lumjs/tests-dom` library.) This feature is
|
|
45
|
+
* likely not useful for most end users, as knowledge of the internals is
|
|
46
|
+
* required to make the functional API work.
|
|
47
|
+
*
|
|
48
|
+
* @returns {module:@lumjs/tests/test/functional.Functional}
|
|
46
49
|
*
|
|
50
|
+
* @exports module:@lumjs/tests/test/functional
|
|
47
51
|
*/
|
|
48
|
-
function functional(opts={})
|
|
52
|
+
function functional(opts={}, testClass=Test)
|
|
49
53
|
{
|
|
50
|
-
|
|
54
|
+
//console.debug("functional()", testClass, testClass.$METHODS);
|
|
55
|
+
// A list of methods we can proxy directly.
|
|
56
|
+
const proxyMethods = testClass.$METHODS.all;
|
|
57
|
+
const test = new testClass(opts);
|
|
51
58
|
const functions = { test };
|
|
52
|
-
for (const meth of
|
|
59
|
+
for (const meth of proxyMethods)
|
|
53
60
|
{
|
|
54
61
|
functions[meth] = function ()
|
|
55
62
|
{
|
|
@@ -1,20 +1,14 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Module defining the Test class.
|
|
3
|
-
* @module @lumjs/tests/test
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
1
|
const core = require('@lumjs/core');
|
|
7
|
-
const types = core
|
|
8
|
-
const {F,S,
|
|
9
|
-
|
|
10
|
-
// We use a separate class to represent test logs.
|
|
2
|
+
const {types,obj} = core;
|
|
3
|
+
const {F,S,isObj,isArray,needs,def} = types;
|
|
4
|
+
const Stats = require('./stats');
|
|
11
5
|
const Log = require('./log');
|
|
12
6
|
|
|
13
7
|
// A list of Test methods that return Log objects.
|
|
14
8
|
const TEST_METHODS =
|
|
15
9
|
[
|
|
16
|
-
'ok', 'call', 'fail', 'pass', 'dies', 'diesWith', 'lives', 'cmp',
|
|
17
|
-
'is', 'isnt', 'isa', 'nota', 'isJSON', 'isntJSON', 'skip',
|
|
10
|
+
'ok', 'call', 'callIs', 'fail', 'pass', 'dies', 'diesWith', 'lives', 'cmp',
|
|
11
|
+
'is', 'isnt', 'isa', 'nota', 'isJSON', 'isntJSON', 'matches', 'skip',
|
|
18
12
|
];
|
|
19
13
|
|
|
20
14
|
// A list of other methods to export that are not standard tests.
|
|
@@ -45,15 +39,11 @@ function $call (testfunc, args)
|
|
|
45
39
|
* Which itself was based on Perl 5's Test::More, and
|
|
46
40
|
* Raku's Test libraries.
|
|
47
41
|
*
|
|
48
|
-
* @
|
|
49
|
-
* @
|
|
50
|
-
*
|
|
51
|
-
* @property {number} ran - Number of tests ran (*calculated*).
|
|
52
|
-
* @property {string} id - Unique test id used by `Harness` libary.
|
|
53
|
-
* @property {boolean} isTop - Test module was loaded from the command line.
|
|
54
|
-
* @property {?object} harness - The top-level `Harness` if one was found.
|
|
42
|
+
* @exports module:@lumjs/tests/test
|
|
43
|
+
* @extends module:@lumjs/tests/test~Base
|
|
44
|
+
*
|
|
55
45
|
*/
|
|
56
|
-
class Test
|
|
46
|
+
class Test extends Stats
|
|
57
47
|
{
|
|
58
48
|
/**
|
|
59
49
|
* Build a new Test instance.
|
|
@@ -76,143 +66,34 @@ class Test
|
|
|
76
66
|
*
|
|
77
67
|
*/
|
|
78
68
|
constructor (opts={})
|
|
79
|
-
{
|
|
80
|
-
|
|
81
|
-
{
|
|
82
|
-
opts = {plan: opts};
|
|
83
|
-
}
|
|
84
|
-
else if (typeof opts === S)
|
|
85
|
-
{
|
|
86
|
-
opts = {id: opts};
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const hasModule = isObj(opts.module);
|
|
90
|
-
|
|
91
|
-
if (typeof opts.id === S)
|
|
92
|
-
{ // A specific id was specified.
|
|
93
|
-
this.id = opts.id;
|
|
94
|
-
}
|
|
95
|
-
else if (hasModule)
|
|
96
|
-
{ // We're going to generate a simple name.
|
|
97
|
-
this.id = core.modules.name(opts.module, opts.moduleName);
|
|
98
|
-
}
|
|
99
|
-
else
|
|
100
|
-
{ // An anonymous test.
|
|
101
|
-
this.id = null;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
this.stringifyDepth = opts.stringify ?? 1;
|
|
105
|
-
|
|
106
|
-
this.failed = 0;
|
|
107
|
-
this.skipped = 0;
|
|
108
|
-
this.planned = 0;
|
|
109
|
-
this.log = [];
|
|
110
|
-
|
|
111
|
-
// These three will be updated below if possible.
|
|
112
|
-
this.isTop = false;
|
|
113
|
-
this.harness = null;
|
|
114
|
-
|
|
115
|
-
if (typeof opts.plan === N)
|
|
116
|
-
{
|
|
117
|
-
this.plan(opts.plan);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (hasModule)
|
|
121
|
-
{ // If a module was passed, its going to export this test.
|
|
122
|
-
opts.module.exports = this;
|
|
123
|
-
// We'll also use the module to determine if we're Harnessed or not.
|
|
124
|
-
if (require.main === opts.module)
|
|
125
|
-
{ // Was called directly.
|
|
126
|
-
this.isTop = true;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (!this.isTop)
|
|
131
|
-
{ // Try to find a Harness instance.
|
|
132
|
-
if (isObj(require.main) && require.main.exports instanceof Harness)
|
|
133
|
-
{ // We found the Harness instance.
|
|
134
|
-
this.harness = require.main.exports;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
69
|
+
{ // First call the Base constructor.
|
|
70
|
+
super(opts);
|
|
137
71
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
// A wrapper around types.stringify()
|
|
141
|
-
stringify(what)
|
|
142
|
-
{
|
|
143
|
-
return types.stringify(what, this.stringifyDepth);
|
|
72
|
+
// Now register methods that can be ran via run().
|
|
73
|
+
this.$testMethods = TEST_METHODS.slice();
|
|
144
74
|
}
|
|
145
75
|
|
|
146
76
|
/**
|
|
147
|
-
*
|
|
77
|
+
* A static shortcut for creating a new instance.
|
|
148
78
|
*
|
|
149
|
-
* @param {
|
|
79
|
+
* @param {object} [opts] Options to pass to constructor.
|
|
80
|
+
* @returns {module:@lumjs/tests/test}
|
|
150
81
|
*/
|
|
151
|
-
|
|
82
|
+
static new(opts={})
|
|
152
83
|
{
|
|
153
|
-
|
|
154
|
-
{
|
|
155
|
-
this.planned = num;
|
|
156
|
-
}
|
|
157
|
-
else if (num === false)
|
|
158
|
-
{
|
|
159
|
-
this.planned = 0;
|
|
160
|
-
}
|
|
161
|
-
else
|
|
162
|
-
{
|
|
163
|
-
throw new Error("Invalid value passed to plan()");
|
|
164
|
-
}
|
|
84
|
+
return new this(opts);
|
|
165
85
|
}
|
|
166
86
|
|
|
167
87
|
/**
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
* This is the absolute most basic method that every other testing method
|
|
171
|
-
* uses to log the results.
|
|
172
|
-
*
|
|
173
|
-
* I won't document the `desc` and `directive` parameters on any of the
|
|
174
|
-
* other methods as they are exactly the same as here.
|
|
88
|
+
* A static shortcut for creating a `Functional` API object.
|
|
175
89
|
*
|
|
176
|
-
* @param {
|
|
177
|
-
*
|
|
178
|
-
* If it evaluates as `false` (a falsey value), the test fails.
|
|
179
|
-
*
|
|
180
|
-
* @param {string} [desc] A short description of the test.
|
|
181
|
-
* @param {(string|Error)} [directive] Further information for the log.
|
|
182
|
-
* @param {object} [details] Extra details to add to the log.
|
|
183
|
-
* @returns {Log} The test log with the results.
|
|
90
|
+
* @param {object} [opts] Options to pass to constructor.
|
|
91
|
+
* @returns {module:@lumjs/tests/functional.Functional}
|
|
184
92
|
*/
|
|
185
|
-
|
|
93
|
+
static functional(opts={})
|
|
186
94
|
{
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (test)
|
|
190
|
-
{
|
|
191
|
-
log.ok = true;
|
|
192
|
-
}
|
|
193
|
-
else
|
|
194
|
-
{
|
|
195
|
-
this.failed++;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
if (typeof desc === S)
|
|
199
|
-
{
|
|
200
|
-
log.desc = desc;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
if (directive)
|
|
204
|
-
{
|
|
205
|
-
log.directive = directive;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
if (isObj(details))
|
|
209
|
-
{
|
|
210
|
-
log.details = details;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
this.log.push(log);
|
|
214
|
-
|
|
215
|
-
return log;
|
|
95
|
+
//console.debug('functional this', this);
|
|
96
|
+
return require('./functional')(opts, this);
|
|
216
97
|
}
|
|
217
98
|
|
|
218
99
|
/**
|
|
@@ -233,30 +114,6 @@ class Test
|
|
|
233
114
|
return this.ok(ret.val, desc, ret.err);
|
|
234
115
|
}
|
|
235
116
|
|
|
236
|
-
/**
|
|
237
|
-
* Mark a test as failed.
|
|
238
|
-
*
|
|
239
|
-
* @param {string} desc
|
|
240
|
-
* @param {*} [directive]
|
|
241
|
-
* @returns {Log}
|
|
242
|
-
*/
|
|
243
|
-
fail (desc, directive)
|
|
244
|
-
{
|
|
245
|
-
return this.ok(false, desc, directive);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
/**
|
|
249
|
-
* Mark a test as passed.
|
|
250
|
-
*
|
|
251
|
-
* @param {string} desc
|
|
252
|
-
* @param {*} [directive]
|
|
253
|
-
* @returns {Log}
|
|
254
|
-
*/
|
|
255
|
-
pass (desc, directive)
|
|
256
|
-
{
|
|
257
|
-
return this.ok(true, desc, directive);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
117
|
/**
|
|
261
118
|
* See if a function throws an Error.
|
|
262
119
|
*
|
|
@@ -689,36 +546,6 @@ class Test
|
|
|
689
546
|
}
|
|
690
547
|
}
|
|
691
548
|
|
|
692
|
-
/**
|
|
693
|
-
* Skip a test.
|
|
694
|
-
*
|
|
695
|
-
* @param {?string} reason - Why the test was skipped.
|
|
696
|
-
* @param {string} desc
|
|
697
|
-
* @returns {Log}
|
|
698
|
-
*/
|
|
699
|
-
skip (reason, desc)
|
|
700
|
-
{
|
|
701
|
-
const log = this.ok(true, desc);
|
|
702
|
-
log.skipped = true;
|
|
703
|
-
if (typeof reason === S)
|
|
704
|
-
log.skippedReason = reason;
|
|
705
|
-
this.skipped++;
|
|
706
|
-
return log;
|
|
707
|
-
}
|
|
708
|
-
|
|
709
|
-
/**
|
|
710
|
-
* Add diagnostics info directly to our test logs.
|
|
711
|
-
*
|
|
712
|
-
* @param {*} msg - The info to add.
|
|
713
|
-
* If this is a `string` it will be displayed as a comment as is.
|
|
714
|
-
* If it is anything else, it will be encoded as JSON first.
|
|
715
|
-
*
|
|
716
|
-
*/
|
|
717
|
-
diag (msg)
|
|
718
|
-
{
|
|
719
|
-
this.log.push(msg);
|
|
720
|
-
}
|
|
721
|
-
|
|
722
549
|
/**
|
|
723
550
|
* Run an assortment of tests using a map.
|
|
724
551
|
*
|
|
@@ -758,7 +585,7 @@ class Test
|
|
|
758
585
|
for (const test of tests)
|
|
759
586
|
{
|
|
760
587
|
const tt = typeof test;
|
|
761
|
-
if (tt === S &&
|
|
588
|
+
if (tt === S && this.$testMethods.includes(test))
|
|
762
589
|
{ // Set the current test to a built-in.
|
|
763
590
|
current = test;
|
|
764
591
|
}
|
|
@@ -791,99 +618,11 @@ class Test
|
|
|
791
618
|
return logs;
|
|
792
619
|
}
|
|
793
620
|
|
|
794
|
-
/**
|
|
795
|
-
* Return TAP formatted output for all the tests.
|
|
796
|
-
*
|
|
797
|
-
* @returns {string} The test logs, in TAP format.
|
|
798
|
-
*/
|
|
799
|
-
tap ()
|
|
800
|
-
{
|
|
801
|
-
let out = '';
|
|
802
|
-
if (this.planned > 0)
|
|
803
|
-
{
|
|
804
|
-
out += '1..'+this.planned+"\n";
|
|
805
|
-
}
|
|
806
|
-
let t = 1;
|
|
807
|
-
for (const log of this.log)
|
|
808
|
-
{
|
|
809
|
-
if (log instanceof Log)
|
|
810
|
-
{
|
|
811
|
-
out += log.tap(t++);
|
|
812
|
-
}
|
|
813
|
-
else
|
|
814
|
-
{ // A comment.
|
|
815
|
-
out += '# ' + (typeof log === S ? log : types.stringify(log)) + "\n";
|
|
816
|
-
}
|
|
817
|
-
}
|
|
818
|
-
if (this.skipped)
|
|
819
|
-
{
|
|
820
|
-
out += '# Skipped '+this.skipped+" tests\n";
|
|
821
|
-
}
|
|
822
|
-
if (this.failed)
|
|
823
|
-
{
|
|
824
|
-
out += '# Failed '+this.failed+(this.failed>1?' tests':' test');
|
|
825
|
-
if (this.planned)
|
|
826
|
-
out += ' out of '+this.planned;
|
|
827
|
-
out += "\n";
|
|
828
|
-
}
|
|
829
|
-
const ran = t-1;
|
|
830
|
-
if (this.planned > 0 && this.planned != ran)
|
|
831
|
-
{
|
|
832
|
-
out += '# Looks like you planned '+this.planned+' but ran '+ran+" tests\n";
|
|
833
|
-
}
|
|
834
|
-
return out;
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
/**
|
|
838
|
-
* A calculated property of the number of tests that were ran.
|
|
839
|
-
* @type {int}
|
|
840
|
-
*/
|
|
841
|
-
get ran ()
|
|
842
|
-
{
|
|
843
|
-
let ran = 0;
|
|
844
|
-
for (const log of this.log)
|
|
845
|
-
{
|
|
846
|
-
if (log instanceof Log)
|
|
847
|
-
{
|
|
848
|
-
ran++;
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
return ran;
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
/**
|
|
855
|
-
* Send the TAP output to the `console`.
|
|
856
|
-
*
|
|
857
|
-
* This is a low-level method and is no longer recommended for use.
|
|
858
|
-
* Instead call the `done()` method, which will *do the right thing*.
|
|
859
|
-
*/
|
|
860
|
-
output ()
|
|
861
|
-
{
|
|
862
|
-
console.log(this.tap());
|
|
863
|
-
return this;
|
|
864
|
-
}
|
|
865
|
-
|
|
866
|
-
/**
|
|
867
|
-
* We're done testing.
|
|
868
|
-
*
|
|
869
|
-
* This will mark the test-set as finished, so attempting to run further
|
|
870
|
-
* tests after will result in a `RangeError` being thrown.
|
|
871
|
-
*
|
|
872
|
-
* If no `Harness` is in use, this will also run `this.output()`.
|
|
873
|
-
*/
|
|
874
|
-
done ()
|
|
875
|
-
{
|
|
876
|
-
if (this.$done)
|
|
877
|
-
{
|
|
878
|
-
throw new RangeError('Test set is already done');
|
|
879
|
-
}
|
|
880
|
-
this.$done = true;
|
|
881
|
-
|
|
882
|
-
return (this.harness ? this : this.output());
|
|
883
|
-
}
|
|
884
|
-
|
|
885
621
|
} // class Test
|
|
886
622
|
|
|
623
|
+
// May want this for sub-classes.
|
|
624
|
+
def(Test, 'Stats', Stats);
|
|
625
|
+
|
|
887
626
|
// Should never need this, but...
|
|
888
627
|
def(Test, 'Log', Log);
|
|
889
628
|
|
|
@@ -895,12 +634,17 @@ def(Test, '$METHODS',
|
|
|
895
634
|
{
|
|
896
635
|
test: TEST_METHODS,
|
|
897
636
|
meta: META_METHODS,
|
|
637
|
+
$meta:
|
|
638
|
+
[ // A list of properties to skip in `all`.
|
|
639
|
+
'$meta', 'all', 'extend',
|
|
640
|
+
],
|
|
898
641
|
get all()
|
|
899
642
|
{
|
|
900
643
|
const list = [];
|
|
644
|
+
const skip = this.$meta;
|
|
901
645
|
for (const name in this)
|
|
902
646
|
{
|
|
903
|
-
if (name
|
|
647
|
+
if (skip.includes(name)) continue;
|
|
904
648
|
const prop = this[name];
|
|
905
649
|
if (isArray(prop))
|
|
906
650
|
{
|
|
@@ -909,12 +653,36 @@ def(Test, '$METHODS',
|
|
|
909
653
|
}
|
|
910
654
|
return list;
|
|
911
655
|
},
|
|
912
|
-
})
|
|
656
|
+
extend(newClass, opts={})
|
|
657
|
+
{
|
|
658
|
+
const mode = obj.CLONE.DEEP;
|
|
659
|
+
const clone = obj.clone(this, {mode});
|
|
913
660
|
|
|
914
|
-
//
|
|
915
|
-
|
|
661
|
+
//console.debug("extend:clone<pre>", clone);
|
|
662
|
+
|
|
663
|
+
if (isObj(opts.add))
|
|
664
|
+
{ // Add in the extra properties.
|
|
665
|
+
//console.debug("opts.add", opts.add);
|
|
666
|
+
obj.copyProps(opts.add, clone, opts.addOpts);
|
|
667
|
+
}
|
|
916
668
|
|
|
917
|
-
|
|
918
|
-
//
|
|
919
|
-
const
|
|
669
|
+
if (isArray(opts.meta))
|
|
670
|
+
{ // Added properties to skip in 'all'.
|
|
671
|
+
for (const val of opts.meta)
|
|
672
|
+
{
|
|
673
|
+
if (!clone.$meta.includes(val))
|
|
674
|
+
{
|
|
675
|
+
clone.$meta.push(val);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
920
679
|
|
|
680
|
+
//console.debug("extend:clone<post>", clone);
|
|
681
|
+
|
|
682
|
+
// Add a new cloned and extended `$METHODS` property.
|
|
683
|
+
def(newClass, '$METHODS', {value: clone});
|
|
684
|
+
}, // extend()
|
|
685
|
+
}); // Test.$METHODS
|
|
686
|
+
|
|
687
|
+
// Export the class
|
|
688
|
+
module.exports = Test;
|
|
@@ -5,25 +5,35 @@ const {S,O,isArray,stringify,def} = types;
|
|
|
5
5
|
/**
|
|
6
6
|
* A log representing the results of a test.
|
|
7
7
|
*
|
|
8
|
+
* @alias module:@lumjs/tests/test~Log
|
|
9
|
+
*
|
|
8
10
|
* @property {boolean} ok - Did the test pass.
|
|
9
11
|
* @property {boolean} skipped - Was the test skipped?
|
|
10
|
-
* @property {
|
|
12
|
+
* @property {boolean} todo - Was the test marked TODO?
|
|
13
|
+
* @property {string} reason - If the test was skipped or TODO, why?
|
|
11
14
|
* @property {?string} desc - A short description of the test.
|
|
12
15
|
* @property {*} directive - Special directives describing the test.
|
|
13
16
|
* @property {object} details - Extra information about the test.
|
|
14
17
|
*
|
|
15
|
-
* @property {*} [details.got] The value that was received in
|
|
16
|
-
* @property {*} [details.wanted] The value that was expectged in
|
|
17
|
-
* @property {
|
|
18
|
+
* @property {*} [details.got] The value that was received in a test.
|
|
19
|
+
* @property {*} [details.wanted] The value that was expectged in a test.
|
|
20
|
+
* @property {string} [details.comparitor] The comparitor used in a test.
|
|
21
|
+
* @property {boolean} [details.stringify] If `true` then output the details as JSON.
|
|
22
|
+
* @property {object} [details.info] An optional array of extra information.
|
|
18
23
|
*
|
|
19
24
|
*/
|
|
20
25
|
class Log
|
|
21
26
|
{
|
|
27
|
+
/**
|
|
28
|
+
* (Internal Constructor)
|
|
29
|
+
* @param {object} test - The parent `Test` or `Stats` instance.
|
|
30
|
+
*/
|
|
22
31
|
constructor (test)
|
|
23
32
|
{
|
|
24
33
|
this.ok = false;
|
|
25
34
|
this.skipped = false;
|
|
26
|
-
this.
|
|
35
|
+
this.todo = false;
|
|
36
|
+
this.reason = '';
|
|
27
37
|
this.desc = null;
|
|
28
38
|
this.directive = null;
|
|
29
39
|
this.details = {};
|
|
@@ -60,21 +70,27 @@ class Log
|
|
|
60
70
|
else if (typeof this.directive == O && this.directive instanceof Error)
|
|
61
71
|
out += ` # ${this.directive.name}: ${this.directive.message}`;
|
|
62
72
|
else if (this.skipped)
|
|
63
|
-
out += ' # SKIP ' + this.
|
|
73
|
+
out += ' # SKIP ' + this.reason;
|
|
74
|
+
else if (this.todo)
|
|
75
|
+
out += ' # TODO ' + this.reason;
|
|
64
76
|
|
|
65
77
|
out += "\n";
|
|
66
78
|
|
|
67
|
-
if ('got' in this.details
|
|
79
|
+
if ('got' in this.details)
|
|
68
80
|
{
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
81
|
+
const stringy = this.details.stringify;
|
|
82
|
+
|
|
83
|
+
let got = this.details.got;
|
|
84
|
+
if (stringy) got = stringify(got, SD);
|
|
85
|
+
out += `# got: ${got}\n`;
|
|
86
|
+
|
|
87
|
+
if ('wanted' in this.details)
|
|
72
88
|
{
|
|
73
|
-
|
|
74
|
-
want = stringify(want, SD);
|
|
89
|
+
let want = this.details.wanted;
|
|
90
|
+
if (stringy) want = stringify(want, SD);
|
|
91
|
+
out += `# expected: ${want}\n`;
|
|
75
92
|
}
|
|
76
|
-
|
|
77
|
-
out += `# expected: ${want}\n`;
|
|
93
|
+
|
|
78
94
|
if (typeof this.details.comparitor === S)
|
|
79
95
|
{
|
|
80
96
|
out += `# op: ${this.details.comparitor}\n`;
|
|
@@ -91,7 +107,7 @@ class Log
|
|
|
91
107
|
for (const i in info)
|
|
92
108
|
{
|
|
93
109
|
const line = (typeof info[i] === S) ? info[i] : stringify(info[i], SD);
|
|
94
|
-
out +=
|
|
110
|
+
out += `# - ${line}\n`;
|
|
95
111
|
}
|
|
96
112
|
}
|
|
97
113
|
|