@lumjs/tests 1.5.0 → 1.6.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 CHANGED
@@ -6,6 +6,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [1.6.0] - 2022-09-12
10
+ #### The *sub-classes* update
11
+ ### Added
12
+ - `Test.new()` works like the `@lumjs/tests.new()`, but uses `this` so it's sub-classable.
13
+ - `Test.static()`, calls `@lumjs/tests.functional()`, and passes `this` as the `testClass`.
14
+ - `Test#TAP`, read-only accessor alias to `Test#tap()`.
15
+ - `Test.$METHODS.$meta`, a list of properties to skip in `$METHODS.all` output.
16
+ - `Test.$METHODS.extend()`, allow `Test` *sub-classes* to build upon the `$METHODS`
17
+ without changing the list in the original `Test` class.
18
+ ### Changed
19
+ - Reworked a bunch of the DocBlocks to make the docs better.
20
+ - Modified the `functional()` method to accept a `testClass` parameter.
21
+ This allows *sub-classes* to make their own functional APIs.
22
+ - Changed `Log.tap()` to make the `details` structure more flexible.
23
+ The `wanted` property is now optional.
24
+ - The `Test` class saves the test method list for `call()` into `this.$testMethods`
25
+ instead of using the `.$METHODS.test` directly.
26
+ ### Fixed
27
+ - Added some missing functions to the registered list of test methods.
28
+
9
29
  ## [1.5.0] - 2022-08-30
10
30
  ### Added
11
31
  - Sample `data` used in some of the old tests.
@@ -85,7 +105,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
85
105
  - Ported from Lum.js v4 library set.
86
106
  - Added a few more features from the PHP version.
87
107
 
88
- [Unreleased]: https://github.com/supernovus/lum.tests.js/compare/v1.5.0...HEAD
108
+ [Unreleased]: https://github.com/supernovus/lum.tests.js/compare/v1.6.0...HEAD
109
+ [1.6.0]: https://github.com/supernovus/lum.tests.js/compare/v1.5.0...v1.6.0
89
110
  [1.5.0]: https://github.com/supernovus/lum.tests.js/compare/v1.4.0...v1.5.0
90
111
  [1.4.0]: https://github.com/supernovus/lum.tests.js/compare/v1.3.0...v1.4.0
91
112
  [1.3.0]: https://github.com/supernovus/lum.tests.js/compare/v1.2.0...v1.3.0
package/lib/functional.js CHANGED
@@ -1,22 +1,18 @@
1
1
  // A functional interface to the test library.
2
2
  const Test = require('./test');
3
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
- */
11
-
12
4
  /**
13
5
  * A new test instance and a set of functions wrapping it.
14
- * @typedef {object} Functional
6
+ *
7
+ * @typedef {object} module:@lumjs/tests/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
- * @returns {Functional}
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/functional.Functional}
46
49
  *
50
+ * @exports module:@lumjs/tests/functional
47
51
  */
48
- function functional(opts={})
52
+ function functional(opts={}, testClass=Test)
49
53
  {
50
- const test = new Test(opts);
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 PROXY_METHODS)
59
+ for (const meth of proxyMethods)
53
60
  {
54
61
  functions[meth] = function ()
55
62
  {
package/lib/log.js CHANGED
@@ -5,6 +5,8 @@ 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
12
  * @property {string} skippedReason - If the test was skipped, why?
@@ -19,6 +21,10 @@ const {S,O,isArray,stringify,def} = types;
19
21
  */
20
22
  class Log
21
23
  {
24
+ /**
25
+ * (Internal Constructor)
26
+ * @param {module:@lumjs/tests/test} test - The parent `Test` instance.
27
+ */
22
28
  constructor (test)
23
29
  {
24
30
  this.ok = false;
@@ -64,17 +70,21 @@ class Log
64
70
 
65
71
  out += "\n";
66
72
 
67
- if ('got' in this.details && 'wanted' in this.details)
73
+ if ('got' in this.details)
68
74
  {
69
- var got = this.details.got;
70
- var want = this.details.wanted;
71
- if (this.details.stringify)
75
+ const stringy = this.details.stringify;
76
+
77
+ let got = this.details.got;
78
+ if (stringy) got = stringify(got, SD);
79
+ out += `# got: ${got}\n`;
80
+
81
+ if ('wanted' in this.details)
72
82
  {
73
- got = stringify(got, SD);
74
- want = stringify(want, SD);
83
+ let want = this.details.wanted;
84
+ if (stringy) want = stringify(want, SD);
85
+ out += `# expected: ${want}\n`;
75
86
  }
76
- out += `# got: ${got}\n`;
77
- out += `# expected: ${want}\n`;
87
+
78
88
  if (typeof this.details.comparitor === S)
79
89
  {
80
90
  out += `# op: ${this.details.comparitor}\n`;
package/lib/test.js CHANGED
@@ -1,10 +1,5 @@
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.types;
2
+ const {types,obj} = core;
8
3
  const {F,S,N,isObj,isArray,needs,def} = types;
9
4
 
10
5
  // We use a separate class to represent test logs.
@@ -13,8 +8,8 @@ const Log = require('./log');
13
8
  // A list of Test methods that return Log objects.
14
9
  const TEST_METHODS =
15
10
  [
16
- 'ok', 'call', 'fail', 'pass', 'dies', 'diesWith', 'lives', 'cmp',
17
- 'is', 'isnt', 'isa', 'nota', 'isJSON', 'isntJSON', 'skip',
11
+ 'ok', 'call', 'callIs', 'fail', 'pass', 'dies', 'diesWith', 'lives', 'cmp',
12
+ 'is', 'isnt', 'isa', 'nota', 'isJSON', 'isntJSON', 'matches', 'skip',
18
13
  ];
19
14
 
20
15
  // A list of other methods to export that are not standard tests.
@@ -45,6 +40,8 @@ function $call (testfunc, args)
45
40
  * Which itself was based on Perl 5's Test::More, and
46
41
  * Raku's Test libraries.
47
42
  *
43
+ * @exports module:@lumjs/tests/test
44
+ *
48
45
  * @property {number} planned - Number of tests planned, `0` if unplanned.
49
46
  * @property {number} failed - Number of tests that failed.
50
47
  * @property {number} skipped - Number of tests that were skipped.
@@ -112,6 +109,9 @@ class Test
112
109
  this.isTop = false;
113
110
  this.harness = null;
114
111
 
112
+ // Methods that can be ran via run().
113
+ this.$testMethods = TEST_METHODS.slice();
114
+
115
115
  if (typeof opts.plan === N)
116
116
  {
117
117
  this.plan(opts.plan);
@@ -137,6 +137,29 @@ class Test
137
137
 
138
138
  }
139
139
 
140
+ /**
141
+ * A static shortcut for creating a new instance.
142
+ *
143
+ * @param {object} [opts] Options to pass to constructor.
144
+ * @returns {module:@lumjs/tests/test}
145
+ */
146
+ static new(opts={})
147
+ {
148
+ return new this(opts);
149
+ }
150
+
151
+ /**
152
+ * A static shortcut for creating a `Functional` API object.
153
+ *
154
+ * @param {object} [opts] Options to pass to constructor.
155
+ * @returns {module:@lumjs/tests/functional.Functional}
156
+ */
157
+ static functional(opts={})
158
+ {
159
+ //console.debug('functional this', this);
160
+ return require('./functional')(opts, this);
161
+ }
162
+
140
163
  // A wrapper around types.stringify()
141
164
  stringify(what)
142
165
  {
@@ -758,7 +781,7 @@ class Test
758
781
  for (const test of tests)
759
782
  {
760
783
  const tt = typeof test;
761
- if (tt === S && TEST_METHODS.includes(test))
784
+ if (tt === S && this.$testMethods.includes(test))
762
785
  { // Set the current test to a built-in.
763
786
  current = test;
764
787
  }
@@ -834,6 +857,16 @@ class Test
834
857
  return out;
835
858
  }
836
859
 
860
+ /**
861
+ * A read-only *accessor* property alias for `tap()`.
862
+ * @returns {string}
863
+ * @see {@link module:@lumjs/tests/test#tap}
864
+ */
865
+ get TAP()
866
+ {
867
+ return this.tap();
868
+ }
869
+
837
870
  /**
838
871
  * A calculated property of the number of tests that were ran.
839
872
  * @type {int}
@@ -895,12 +928,17 @@ def(Test, '$METHODS',
895
928
  {
896
929
  test: TEST_METHODS,
897
930
  meta: META_METHODS,
931
+ $meta:
932
+ [ // A list of properties to skip in `all`.
933
+ '$meta', 'all', 'extend',
934
+ ],
898
935
  get all()
899
936
  {
900
937
  const list = [];
938
+ const skip = this.$meta;
901
939
  for (const name in this)
902
940
  {
903
- if (name === 'all') continue;
941
+ if (skip.includes(name)) continue;
904
942
  const prop = this[name];
905
943
  if (isArray(prop))
906
944
  {
@@ -909,7 +947,36 @@ def(Test, '$METHODS',
909
947
  }
910
948
  return list;
911
949
  },
912
- });
950
+ extend(newClass, opts={})
951
+ {
952
+ const mode = obj.CLONE.DEEP;
953
+ const clone = obj.clone(this, {mode});
954
+
955
+ //console.debug("extend:clone<pre>", clone);
956
+
957
+ if (isObj(opts.add))
958
+ { // Add in the extra properties.
959
+ //console.debug("opts.add", opts.add);
960
+ obj.copyProps(opts.add, clone, opts.addOpts);
961
+ }
962
+
963
+ if (isArray(opts.meta))
964
+ { // Added properties to skip in 'all'.
965
+ for (const val of opts.meta)
966
+ {
967
+ if (!clone.$meta.includes(val))
968
+ {
969
+ clone.$meta.push(val);
970
+ }
971
+ }
972
+ }
973
+
974
+ //console.debug("extend:clone<post>", clone);
975
+
976
+ // Add a new cloned and extended `$METHODS` property.
977
+ def(newClass, '$METHODS', {value: clone});
978
+ }, // extend()
979
+ }); // Test.$METHODS
913
980
 
914
981
  // Export the class
915
982
  module.exports = Test;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumjs/tests",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "main": "lib/index.js",
5
5
  "exports":
6
6
  {
@@ -18,7 +18,7 @@
18
18
  "url": "https://github.com/supernovus/lum.tests.js.git"
19
19
  },
20
20
  "dependencies": {
21
- "@lumjs/core": "^1.1.0"
21
+ "@lumjs/core": "^1.3.0"
22
22
  },
23
23
  "scripts":
24
24
  {