verify-it 2.3.3 → 2.4.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/README.md +134 -41
- package/index.d.ts +209 -44
- package/index.js +63 -15
- package/package.json +13 -16
- package/src/ScenarioBuilder.js +16 -3
- package/src/ScenarioRunnerFactory.js +10 -6
- package/src/function/enumerateFunctions.js +3 -1
- package/src/function/getFunction.js +11 -0
- package/src/generators/CombinationGenerators.js +3 -1
- package/src/generators/NumericGenerators.js +20 -7
- package/src/generators/ObjectGenerators.js +3 -1
- package/src/generators/nouns.json +1 -1
- package/src/function/hasFunction.js +0 -3
package/README.md
CHANGED
|
@@ -1,46 +1,137 @@
|
|
|
1
1
|
# `verify-it`
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/prettier/prettier)
|
|
4
|
+
[](https://github.com/bbc/typescript-docs-verifier)
|
|
5
|
+
<a href="https://www.npmjs.com/package/verify-it">
|
|
6
|
+
<img alt="npm version" src="https://img.shields.io/npm/v/verify-it.svg?style=flat-square"></a>
|
|
7
|
+
<a href="https://www.npmjs.com/package/verify-it">
|
|
8
|
+
<img alt="weekly downloads from npm" src="https://img.shields.io/npm/dw/verify-it.svg?style=flat-square"></a>
|
|
9
|
+
[](https://www.apache.org/licenses/LICENSE-2.0)
|
|
4
10
|
|
|
5
|
-
|
|
6
|
-
[](https://travis-ci.org/bbc/verify-it)
|
|
7
|
-
[](https://david-dm.org/bbc/verify-it)
|
|
8
|
-
[](https://david-dm.org/bbc/verify-it?type=dev)
|
|
11
|
+
_Randomised test property/data generation for NodeJS._
|
|
9
12
|
|
|
10
13
|
This module provides:
|
|
11
14
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
- Randomised property inputs for testing (delegating the actual testing to a global or provided `it` or `test` function).
|
|
16
|
+
- `verify.it` and `verify.test` functions (which are synonyms).
|
|
17
|
+
- A `verify.describe` function (delegating the actual testing to a global or provided `describe` function).
|
|
18
|
+
- A series of generator functions that can be used to generate properties.
|
|
19
|
+
- Generators are simply functions that produce a value so custom generators are simple to create.
|
|
17
20
|
|
|
18
21
|
What it is not:
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
- A property-based testing framework - each test scenario is only run once with the requested randomised inputs.
|
|
21
24
|
|
|
22
25
|
## Usage
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
### Library initialisation
|
|
28
|
+
|
|
29
|
+
As of version 2.4.0, use of the global `verify` object is deprecated in favour of explicit initialisation of this library. The `verify` global will be removed in a future version of this library. Previously the preferred usage pattern was:
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { Gen } from 'verify-it'
|
|
33
|
+
|
|
34
|
+
// `verify` is still available as a global but is deprecated
|
|
35
|
+
verify.it('does something', Gen.string, (someValue) => {
|
|
36
|
+
// Write tests here.
|
|
37
|
+
})
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Now, explicit initialisation is preferred:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { it, describe } from 'node:test'
|
|
44
|
+
import { init, Gen } from 'verify-it'
|
|
45
|
+
|
|
46
|
+
// Initialise with node:test, mocha, jest, vitest etc.
|
|
47
|
+
const verify = init({ it, describe })
|
|
48
|
+
|
|
49
|
+
verify.it('does something', Gen.string, (someValue, t) => {
|
|
50
|
+
// Write tests here
|
|
51
|
+
})
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
This is to allow better support for the built-in [`node:test`](https://nodejs.org/api/test.html) library and other frameworks that do not automatically inject `it`, `test`, and `describe` globals.
|
|
55
|
+
|
|
56
|
+
### Examples
|
|
57
|
+
|
|
58
|
+
#### Using the built-in `node:test` library:
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import test, { describe } from 'node:test'
|
|
62
|
+
import { init, Gen } from 'verify-it'
|
|
63
|
+
|
|
64
|
+
const verify = init(test)
|
|
65
|
+
|
|
66
|
+
const myGenerator = () => `My custom generated value: ${Math.random()}`
|
|
67
|
+
|
|
68
|
+
describe('The verify-it library', () => {
|
|
69
|
+
verify.it(
|
|
70
|
+
'should inject randomised properties',
|
|
71
|
+
Gen.string,
|
|
72
|
+
Gen.object,
|
|
73
|
+
myGenerator,
|
|
74
|
+
async (someString, someObject, someCustomValue, t) => {
|
|
75
|
+
// Write your tests here in the usual way using the supplied randomised values...
|
|
76
|
+
t.assert.equal(true, true)
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
verify.it(
|
|
81
|
+
'should allow testing of asynchronous callbacks if the test framework supports it',
|
|
82
|
+
Gen.string,
|
|
83
|
+
Gen.object,
|
|
84
|
+
myGenerator,
|
|
85
|
+
(someString, someObject, someCustomValue, t, done) => {
|
|
86
|
+
// Write some more tests here but call the done function when finished
|
|
87
|
+
t.assert.equal(true, true)
|
|
88
|
+
done()
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
verify.describe('when verify.describe is used', Gen.object, (someObject) => {
|
|
93
|
+
verify.it(
|
|
94
|
+
'allows the same generated value to be shared across multiple tests',
|
|
95
|
+
Gen.object,
|
|
96
|
+
(someOtherObject, t) => {
|
|
97
|
+
// Write your tests here using both someObject and someOtherObject
|
|
98
|
+
t.assert.equal(true, true)
|
|
99
|
+
}
|
|
100
|
+
)
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### Other testing libraries
|
|
106
|
+
|
|
107
|
+
An `it` or `test` testing function is required for `verify-it` to delegate testing to. This could be provided by [mocha](https://www.npmjs.com/package/mocha), [jest](https://www.npmjs.com/package/jest), [jasmine](https://www.npmjs.com/package/jasmine), [vitest](https://vitest.dev/) or a similar testing framework.
|
|
25
108
|
|
|
26
109
|
A simple `mocha` example would be:
|
|
27
110
|
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
|
|
111
|
+
```ts
|
|
112
|
+
import mocha, { describe } from 'mocha'
|
|
113
|
+
import { Gen, init } from 'verify-it'
|
|
114
|
+
|
|
115
|
+
const verify = init(mocha)
|
|
31
116
|
|
|
32
117
|
const myGenerator = () => `My custom generated value: ${Math.random()}`
|
|
33
118
|
|
|
34
119
|
describe('The verify-it library', () => {
|
|
35
|
-
verify.it(
|
|
36
|
-
|
|
37
|
-
|
|
120
|
+
verify.it(
|
|
121
|
+
'should inject randomised properties',
|
|
122
|
+
Gen.string,
|
|
123
|
+
Gen.object,
|
|
124
|
+
myGenerator,
|
|
125
|
+
async (someString, someObject, someCustomValue) => {
|
|
38
126
|
// Write your tests here in the usual way using the supplied randomised values...
|
|
39
127
|
}
|
|
40
128
|
)
|
|
41
129
|
|
|
42
|
-
verify.it(
|
|
43
|
-
|
|
130
|
+
verify.it(
|
|
131
|
+
'should allow testing of asynchronous callbacks if the test framework supports it',
|
|
132
|
+
Gen.string,
|
|
133
|
+
Gen.object,
|
|
134
|
+
myGenerator,
|
|
44
135
|
(someString, someObject, someCustomValue, done) => {
|
|
45
136
|
// Write some more tests here but call the done function when finished
|
|
46
137
|
done()
|
|
@@ -48,8 +139,10 @@ describe('The verify-it library', () => {
|
|
|
48
139
|
)
|
|
49
140
|
|
|
50
141
|
verify.describe('when verify.describe is used', Gen.object, (someObject) => {
|
|
51
|
-
verify.it(
|
|
52
|
-
|
|
142
|
+
verify.it(
|
|
143
|
+
'allows the same generated value to be shared across multiple tests',
|
|
144
|
+
Gen.object,
|
|
145
|
+
(someOtherObject) => {
|
|
53
146
|
// Write your tests here using both someObject and someOtherObject
|
|
54
147
|
}
|
|
55
148
|
)
|
|
@@ -67,29 +160,29 @@ Generators are simply functions that produce a value. Several built-in generator
|
|
|
67
160
|
const { Gen } = require('verify-it')
|
|
68
161
|
```
|
|
69
162
|
|
|
70
|
-
| Function | Produces | Notes
|
|
71
|
-
|
|
72
|
-
| `Gen.word` | `string` | Produces an english word picked at random from a word list.
|
|
73
|
-
| `Gen.string` | `string` | Produces a random string between 1 and 100 characters in length.
|
|
74
|
-
| `Gen.stringWithLength(length)` | `string` | Produces a random string with a fixed length.
|
|
75
|
-
| `Gen.stringNonNumeric` | `string` | Produces a random string that does not contain numeric characters between 1 and 100 characters in length.
|
|
76
|
-
| `Gen.integer` | `number` | Produces a random integer in the inclusive range between `Number.MIN_SAFE_INTEGER` and `Number.MAX_SAFE_INTEGER`.
|
|
77
|
-
| `Gen.integerBetween(min, max)` | `number` | Produces a random integer in the inclusive range between `min` and `max`.
|
|
78
|
-
| `Gen.float` | `number` | Produces a random number in the inclusive range between `-1E10` and `1E10`
|
|
79
|
-
| `Gen.floatBetween(min, max)` | `number` | Produces a random number in the inclusive range between `min` and `max`
|
|
80
|
-
| `Gen.object` | `Object` | Produces an object with random word keys and randomised string values.
|
|
81
|
-
| `Gen.objectWith(...keys)` | `Object` | Produces an object with the supplied keys and randomised string values.
|
|
82
|
-
| `Gen.error` | `Error` | Produces an `Error` with a random message string.
|
|
83
|
-
| `Gen.boolean` | `boolean` | Produces a random boolean value
|
|
84
|
-
| `Gen.array(generator, length)` | `Array` | Produces an array with `length` elements (or between 1 and 100 elements if `length` is omitted) generated using `generator`. e.g. `Gen.array(Gen.string)` will produce an array of strings.
|
|
163
|
+
| Function | Produces | Notes |
|
|
164
|
+
| --------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
165
|
+
| `Gen.word` | `string` | Produces an english word picked at random from a word list. |
|
|
166
|
+
| `Gen.string` | `string` | Produces a random string between 1 and 100 characters in length. |
|
|
167
|
+
| `Gen.stringWithLength(length)` | `string` | Produces a random string with a fixed length. |
|
|
168
|
+
| `Gen.stringNonNumeric` | `string` | Produces a random string that does not contain numeric characters between 1 and 100 characters in length. |
|
|
169
|
+
| `Gen.integer` | `number` | Produces a random integer in the inclusive range between `Number.MIN_SAFE_INTEGER` and `Number.MAX_SAFE_INTEGER`. |
|
|
170
|
+
| `Gen.integerBetween(min, max)` | `number` | Produces a random integer in the inclusive range between `min` and `max`. |
|
|
171
|
+
| `Gen.float` | `number` | Produces a random number in the inclusive range between `-1E10` and `1E10` |
|
|
172
|
+
| `Gen.floatBetween(min, max)` | `number` | Produces a random number in the inclusive range between `min` and `max` |
|
|
173
|
+
| `Gen.object` | `Object` | Produces an object with random word keys and randomised string values. |
|
|
174
|
+
| `Gen.objectWith(...keys)` | `Object` | Produces an object with the supplied keys and randomised string values. |
|
|
175
|
+
| `Gen.error` | `Error` | Produces an `Error` with a random message string. |
|
|
176
|
+
| `Gen.boolean` | `boolean` | Produces a random boolean value |
|
|
177
|
+
| `Gen.array(generator, length)` | `Array` | Produces an array with `length` elements (or between 1 and 100 elements if `length` is omitted) generated using `generator`. e.g. `Gen.array(Gen.string)` will produce an array of strings. |
|
|
85
178
|
| `Gen.distinct(generator, length)` | `Array` | Produces an array of length `length` with distinct values generated using `generator`. Equality is based on `===`. If distinct values cannot be generated after 10 generation attempts, an error will be thrown. |
|
|
86
|
-
| `Gen.pick(values)` | `any` | Picks a random element from the supplied `values` array.
|
|
179
|
+
| `Gen.pick(values)` | `any` | Picks a random element from the supplied `values` array. |
|
|
87
180
|
|
|
88
181
|
## Development
|
|
89
182
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
183
|
+
- Install dependencies: `npm install`.
|
|
184
|
+
- Run all tests: `npm test`.
|
|
185
|
+
- Check dependencies for security vulnerabilities and licensing issues: `npm run check-dependencies`.
|
|
93
186
|
|
|
94
187
|
## Contributing
|
|
95
188
|
|
package/index.d.ts
CHANGED
|
@@ -1,51 +1,216 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
<T1
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
import type { TestFn as NativeTestFn } from 'node:test'
|
|
2
|
+
|
|
3
|
+
type LibraryTestFn = (done: TestDone) => any
|
|
4
|
+
type DescribeFn = (description: string, callback?: () => void) => void
|
|
5
|
+
type TestCallbackFn = NativeTestFn | LibraryTestFn
|
|
6
|
+
|
|
7
|
+
type VerifyFunction<F extends TestCallbackFn> = {
|
|
8
|
+
(description: string, callback: F): any
|
|
9
|
+
<T1>(
|
|
10
|
+
description: string,
|
|
11
|
+
gen1: () => T1,
|
|
12
|
+
callback: (value1: T1, ...args: Parameters<F>) => any
|
|
13
|
+
): any
|
|
14
|
+
<T1, T2>(
|
|
15
|
+
description: string,
|
|
16
|
+
gen1: () => T1,
|
|
17
|
+
gen2: () => T2,
|
|
18
|
+
callback: (value1: T1, value2: T2, ...args: Parameters<F>) => any
|
|
19
|
+
): any
|
|
20
|
+
<T1, T2, T3>(
|
|
21
|
+
description: string,
|
|
22
|
+
gen1: () => T1,
|
|
23
|
+
gen2: () => T2,
|
|
24
|
+
gen3: () => T3,
|
|
25
|
+
callback: (
|
|
26
|
+
value1: T1,
|
|
27
|
+
value2: T2,
|
|
28
|
+
value3: T3,
|
|
29
|
+
...args: Parameters<F>
|
|
30
|
+
) => any
|
|
31
|
+
): any
|
|
32
|
+
<T1, T2, T3, T4>(
|
|
33
|
+
description: string,
|
|
34
|
+
gen1: () => T1,
|
|
35
|
+
gen2: () => T2,
|
|
36
|
+
gen3: () => T3,
|
|
37
|
+
gen4: () => T4,
|
|
38
|
+
callback: (
|
|
39
|
+
value1: T1,
|
|
40
|
+
value2: T2,
|
|
41
|
+
value3: T3,
|
|
42
|
+
value4: T4,
|
|
43
|
+
...args: Parameters<F>
|
|
44
|
+
) => any
|
|
45
|
+
): any
|
|
46
|
+
<T1, T2, T3, T4, T5>(
|
|
47
|
+
description: string,
|
|
48
|
+
gen1: () => T1,
|
|
49
|
+
gen2: () => T2,
|
|
50
|
+
gen3: () => T3,
|
|
51
|
+
gen4: () => T4,
|
|
52
|
+
gen5: () => T5,
|
|
53
|
+
callback: (
|
|
54
|
+
value1: T1,
|
|
55
|
+
value2: T2,
|
|
56
|
+
value3: T3,
|
|
57
|
+
value4: T4,
|
|
58
|
+
value5: T5,
|
|
59
|
+
...args: Parameters<F>
|
|
60
|
+
) => any
|
|
61
|
+
): any
|
|
62
|
+
<T1, T2, T3, T4, T5, T6>(
|
|
63
|
+
description: string,
|
|
64
|
+
gen1: () => T1,
|
|
65
|
+
gen2: () => T2,
|
|
66
|
+
gen3: () => T3,
|
|
67
|
+
gen4: () => T4,
|
|
68
|
+
gen5: () => T5,
|
|
69
|
+
gen6: () => T6,
|
|
70
|
+
callback: (
|
|
71
|
+
value1: T1,
|
|
72
|
+
value2: T2,
|
|
73
|
+
value3: T3,
|
|
74
|
+
value4: T4,
|
|
75
|
+
value5: T5,
|
|
76
|
+
value6: T6,
|
|
77
|
+
...args: Parameters<F>
|
|
78
|
+
) => any
|
|
79
|
+
): any
|
|
80
|
+
<T1, T2, T3, T4, T5, T6, T7>(
|
|
81
|
+
description: string,
|
|
82
|
+
gen1: () => T1,
|
|
83
|
+
gen2: () => T2,
|
|
84
|
+
gen3: () => T3,
|
|
85
|
+
gen4: () => T4,
|
|
86
|
+
gen5: () => T5,
|
|
87
|
+
gen6: () => T6,
|
|
88
|
+
gen7: () => T7,
|
|
89
|
+
callback: (
|
|
90
|
+
value1: T1,
|
|
91
|
+
value2: T2,
|
|
92
|
+
value3: T3,
|
|
93
|
+
value4: T4,
|
|
94
|
+
value5: T5,
|
|
95
|
+
value6: T6,
|
|
96
|
+
value7: T7,
|
|
97
|
+
...args: Parameters<F>
|
|
98
|
+
) => any
|
|
99
|
+
): any
|
|
100
|
+
<T1, T2, T3, T4, T5, T6, T7, T8>(
|
|
101
|
+
description: string,
|
|
102
|
+
gen1: () => T1,
|
|
103
|
+
gen2: () => T2,
|
|
104
|
+
gen3: () => T3,
|
|
105
|
+
gen4: () => T4,
|
|
106
|
+
gen5: () => T5,
|
|
107
|
+
gen6: () => T6,
|
|
108
|
+
gen7: () => T7,
|
|
109
|
+
gen8: () => T8,
|
|
110
|
+
callback: (
|
|
111
|
+
value1: T1,
|
|
112
|
+
value2: T2,
|
|
113
|
+
value3: T3,
|
|
114
|
+
value4: T4,
|
|
115
|
+
value5: T5,
|
|
116
|
+
value6: T6,
|
|
117
|
+
value7: T7,
|
|
118
|
+
value8: T8,
|
|
119
|
+
...args: Parameters<F>
|
|
120
|
+
) => any
|
|
121
|
+
): any
|
|
122
|
+
<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
|
|
123
|
+
description: string,
|
|
124
|
+
gen1: () => T1,
|
|
125
|
+
gen2: () => T2,
|
|
126
|
+
gen3: () => T3,
|
|
127
|
+
gen4: () => T4,
|
|
128
|
+
gen5: () => T5,
|
|
129
|
+
gen6: () => T6,
|
|
130
|
+
gen7: () => T7,
|
|
131
|
+
gen8: () => T8,
|
|
132
|
+
gen9: () => T9,
|
|
133
|
+
callback: (
|
|
134
|
+
value1: T1,
|
|
135
|
+
value2: T2,
|
|
136
|
+
value3: T3,
|
|
137
|
+
value4: T4,
|
|
138
|
+
value5: T5,
|
|
139
|
+
value6: T6,
|
|
140
|
+
value7: T7,
|
|
141
|
+
value8: T8,
|
|
142
|
+
value9: T9,
|
|
143
|
+
...args: Parameters<F>
|
|
144
|
+
) => any
|
|
145
|
+
): any
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
type VerifyItObject<F extends TestCallbackFn> = VerifyFunction<F> & {
|
|
149
|
+
only: VerifyFunction<F>
|
|
150
|
+
skip: VerifyFunction<F>
|
|
14
151
|
}
|
|
15
152
|
|
|
16
|
-
type
|
|
17
|
-
|
|
18
|
-
|
|
153
|
+
type TestDone = (error?: any) => any
|
|
154
|
+
|
|
155
|
+
interface IVerify<T extends TestCallbackFn> {
|
|
156
|
+
it: VerifyItObject<T>
|
|
157
|
+
test: VerifyItObject<T>
|
|
158
|
+
describe: VerifyItObject<() => void>
|
|
19
159
|
}
|
|
20
160
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
objectWith(...keys: string[]): () => object,
|
|
40
|
-
error: () => Error,
|
|
41
|
-
array<T>(generator: () => T, length: number): (() => T[]),
|
|
42
|
-
distinct<T>(generator: () => T, length: number): (() => T[]),
|
|
43
|
-
pick<T>(values: T[]): () => T,
|
|
44
|
-
word: () => string,
|
|
45
|
-
boolean: () => boolean
|
|
46
|
-
}
|
|
161
|
+
export const Gen: {
|
|
162
|
+
string: () => string
|
|
163
|
+
stringWithLength: (length: number) => () => string
|
|
164
|
+
stringNonNumeric: () => string
|
|
165
|
+
integer: () => number
|
|
166
|
+
integerBetween(min: number, max: number): () => number
|
|
167
|
+
float: () => number
|
|
168
|
+
floatBetween(min: number, max: number): () => number
|
|
169
|
+
object: () => Record<string, string>
|
|
170
|
+
objectWith<Keys extends string[]>(
|
|
171
|
+
...keys: Keys
|
|
172
|
+
): () => Record<Keys[number], string>
|
|
173
|
+
error: () => Error
|
|
174
|
+
array<T>(generator: () => T, length: number): () => T[]
|
|
175
|
+
distinct<T>(generator: () => T, length: number): () => T[]
|
|
176
|
+
pick<T>(values: T[]): () => T
|
|
177
|
+
word: () => string
|
|
178
|
+
boolean: () => boolean
|
|
47
179
|
}
|
|
48
180
|
|
|
49
|
-
|
|
50
|
-
|
|
181
|
+
type Init<T extends TestCallbackFn> =
|
|
182
|
+
| {
|
|
183
|
+
it: (description: string, callback: T) => void
|
|
184
|
+
}
|
|
185
|
+
| {
|
|
186
|
+
test: (description: string, callback: T) => void
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
type InitDescribe = { describe: DescribeFn }
|
|
190
|
+
|
|
191
|
+
type InitFunction = {
|
|
192
|
+
<T extends Init<NativeTestFn> | (Init<NativeTestFn> & InitDescribe)>(
|
|
193
|
+
options: T
|
|
194
|
+
): T extends InitDescribe
|
|
195
|
+
? IVerify<NativeTestFn>
|
|
196
|
+
: Omit<IVerify<NativeTestFn>, 'describe'>
|
|
197
|
+
|
|
198
|
+
<T extends Init<LibraryTestFn> | (Init<LibraryTestFn> & InitDescribe)>(
|
|
199
|
+
options: T
|
|
200
|
+
): T extends InitDescribe
|
|
201
|
+
? IVerify<LibraryTestFn>
|
|
202
|
+
: Omit<IVerify<LibraryTestFn>, 'describe'>
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export const init: InitFunction
|
|
206
|
+
|
|
207
|
+
declare global {
|
|
208
|
+
/**
|
|
209
|
+
* @deprecated Please use explicit initialisation using the `init()` function instead.
|
|
210
|
+
*
|
|
211
|
+
* The `verify` object provides a type-safe interface for defining tests with generators.
|
|
212
|
+
* Only available as a global if there is a global `test` or `it` function otherwise an error
|
|
213
|
+
* will be thrown at runtime.
|
|
214
|
+
*/
|
|
215
|
+
const verify: IVerify<LibraryTestFn>
|
|
51
216
|
}
|
package/index.js
CHANGED
|
@@ -3,28 +3,76 @@
|
|
|
3
3
|
const ScenarioBuilder = require('./src/ScenarioBuilder')
|
|
4
4
|
const ScenarioRunnerFactory = require('./src/ScenarioRunnerFactory')
|
|
5
5
|
const Generators = require('./src/Generators')
|
|
6
|
-
const
|
|
6
|
+
const getFunction = require('./src/function/getFunction')
|
|
7
7
|
|
|
8
|
-
const findTestFunction = () => {
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
const findTestFunction = (options) => {
|
|
9
|
+
const itFunction = getFunction(options, 'it')
|
|
10
|
+
|
|
11
|
+
if (itFunction) {
|
|
12
|
+
return itFunction
|
|
11
13
|
}
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
const testFunction = getFunction(options, 'test')
|
|
16
|
+
|
|
17
|
+
if (testFunction) {
|
|
18
|
+
return testFunction
|
|
19
|
+
}
|
|
15
20
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
it: verifyItFunction,
|
|
20
|
-
test: verifyItFunction
|
|
21
|
+
throw new Error(
|
|
22
|
+
'verify-it must be initialised with an it or test function, either by passing it to the init function or by defining a global it or test function'
|
|
23
|
+
)
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
+
const init = (options) => {
|
|
27
|
+
const testFunction = findTestFunction(options)
|
|
28
|
+
|
|
29
|
+
const verifyItFunction = ScenarioRunnerFactory.create(
|
|
30
|
+
testFunction,
|
|
31
|
+
ScenarioBuilder,
|
|
32
|
+
['only', 'skip']
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
const verify = {
|
|
36
|
+
it: verifyItFunction,
|
|
37
|
+
test: verifyItFunction
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const describeFunction = getFunction(options, 'describe')
|
|
41
|
+
if (describeFunction) {
|
|
42
|
+
const verifyDescribeFunction = ScenarioRunnerFactory.create(
|
|
43
|
+
describeFunction,
|
|
44
|
+
ScenarioBuilder,
|
|
45
|
+
['only', 'skip']
|
|
46
|
+
)
|
|
47
|
+
verify.describe = verifyDescribeFunction
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return verify
|
|
26
51
|
}
|
|
27
52
|
|
|
53
|
+
let globalVerify = null
|
|
54
|
+
|
|
55
|
+
const SUPPORTED_PROPERTIES = ['it', 'test', 'describe']
|
|
56
|
+
|
|
57
|
+
global.verify = new Proxy(
|
|
58
|
+
{},
|
|
59
|
+
{
|
|
60
|
+
has: (_, prop) => SUPPORTED_PROPERTIES.includes(prop),
|
|
61
|
+
set: () => false,
|
|
62
|
+
deleteProperty: () => false,
|
|
63
|
+
get: (_, prop) => {
|
|
64
|
+
if (SUPPORTED_PROPERTIES.includes(prop)) {
|
|
65
|
+
if (!globalVerify) {
|
|
66
|
+
globalVerify = init(global)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return globalVerify[prop]
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
)
|
|
74
|
+
|
|
28
75
|
module.exports = {
|
|
29
|
-
Gen: Generators
|
|
76
|
+
Gen: Generators,
|
|
77
|
+
init
|
|
30
78
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "verify-it",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Randomised test property/data generation for NodeJS",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"testing",
|
|
@@ -13,9 +13,13 @@
|
|
|
13
13
|
"generator"
|
|
14
14
|
],
|
|
15
15
|
"main": "index.js",
|
|
16
|
+
"types": "index.d.ts",
|
|
16
17
|
"scripts": {
|
|
17
|
-
"test": "
|
|
18
|
-
"
|
|
18
|
+
"test": "npm run test:unit && npm run test:format && npm run test:types && npm run test:docs && npm run check-dependencies",
|
|
19
|
+
"test:unit": "c8 --reporter=text --reporter=html --report-dir=coverage node --test 'test/**/*Spec.js'",
|
|
20
|
+
"test:format": "prettier --write .",
|
|
21
|
+
"test:types": "tsc",
|
|
22
|
+
"test:docs": "typescript-docs-verifier",
|
|
19
23
|
"check-dependencies": "scripts/spdx-non-copyleft.js"
|
|
20
24
|
},
|
|
21
25
|
"repository": {
|
|
@@ -35,21 +39,14 @@
|
|
|
35
39
|
"random-js": "^2.1.0"
|
|
36
40
|
},
|
|
37
41
|
"devDependencies": {
|
|
38
|
-
"
|
|
39
|
-
"
|
|
42
|
+
"@types/mocha": "^10.0.10",
|
|
43
|
+
"@types/node": "^24.10.15",
|
|
44
|
+
"c8": "^11.0.0",
|
|
40
45
|
"license-checker": "^25.0.1",
|
|
41
|
-
"
|
|
42
|
-
"nyc": "^17.1.0",
|
|
46
|
+
"prettier": "^3.8.1",
|
|
43
47
|
"spdx-copyleft": "^1.0.0",
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
},
|
|
47
|
-
"standard": {
|
|
48
|
-
"globals": [
|
|
49
|
-
"describe",
|
|
50
|
-
"it",
|
|
51
|
-
"verify"
|
|
52
|
-
]
|
|
48
|
+
"typescript": "^5.9.3",
|
|
49
|
+
"typescript-docs-verifier": "^3.0.1"
|
|
53
50
|
},
|
|
54
51
|
"files": [
|
|
55
52
|
"src",
|
package/src/ScenarioBuilder.js
CHANGED
|
@@ -2,9 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
const createFunctionWithCorrectArgsLength = (numberOfArgs, fn) => {
|
|
4
4
|
switch (numberOfArgs) {
|
|
5
|
-
case 0
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
case 0:
|
|
6
|
+
return function () {
|
|
7
|
+
return fn.apply(this, arguments)
|
|
8
|
+
}
|
|
9
|
+
case 1:
|
|
10
|
+
return function (_) {
|
|
11
|
+
return fn.apply(this, arguments)
|
|
12
|
+
}
|
|
13
|
+
case 2:
|
|
14
|
+
return function (_, __) {
|
|
15
|
+
return fn.apply(this, arguments)
|
|
16
|
+
}
|
|
17
|
+
default:
|
|
18
|
+
throw new Error(
|
|
19
|
+
'Use of more than 2 non-generated scenario arguments is currently unsupported'
|
|
20
|
+
)
|
|
8
21
|
}
|
|
9
22
|
}
|
|
10
23
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const getFunction = require('./function/getFunction')
|
|
4
4
|
|
|
5
5
|
const buildDelegatingFunction = (it, scenarioBuilder) => {
|
|
6
6
|
return function () {
|
|
@@ -22,11 +22,15 @@ const buildDelegatingFunction = (it, scenarioBuilder) => {
|
|
|
22
22
|
const ScenarioRunnerFactory = {
|
|
23
23
|
create: (it, scenarioBuilder, additionalFunctionNames = []) => {
|
|
24
24
|
const verifyItFunction = buildDelegatingFunction(it, scenarioBuilder)
|
|
25
|
-
additionalFunctionNames.
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
verifyItFunction[key] = buildDelegatingFunction(
|
|
29
|
-
|
|
25
|
+
additionalFunctionNames.forEach((key) => {
|
|
26
|
+
const additionalFunction = getFunction(it, key)
|
|
27
|
+
if (additionalFunction) {
|
|
28
|
+
verifyItFunction[key] = buildDelegatingFunction(
|
|
29
|
+
additionalFunction,
|
|
30
|
+
scenarioBuilder
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
})
|
|
30
34
|
return verifyItFunction
|
|
31
35
|
}
|
|
32
36
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const enumerateFunctions = (object) => {
|
|
4
|
-
return Object.getOwnPropertyNames(object).filter(
|
|
4
|
+
return Object.getOwnPropertyNames(object).filter(
|
|
5
|
+
(name) => typeof object[name] === 'function'
|
|
6
|
+
)
|
|
5
7
|
}
|
|
6
8
|
|
|
7
9
|
module.exports = enumerateFunctions
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
const CombinationGenerators = function (random, maxDistinctRetries) {
|
|
4
4
|
const generateDistinct = (generator, existing, remainingRetries) => {
|
|
5
5
|
if (remainingRetries === 0) {
|
|
6
|
-
throw new Error(
|
|
6
|
+
throw new Error(
|
|
7
|
+
`Could not generate distinct values using the provided generator - tried ${maxDistinctRetries} times`
|
|
8
|
+
)
|
|
7
9
|
}
|
|
8
10
|
|
|
9
11
|
const newValue = generator()
|
|
@@ -4,23 +4,32 @@ const NumericGenerators = function (random) {
|
|
|
4
4
|
const MaxRealValue = Number('1E10')
|
|
5
5
|
const MinRealValue = Number('-1E10')
|
|
6
6
|
|
|
7
|
-
this.integer = () =>
|
|
7
|
+
this.integer = () =>
|
|
8
|
+
random.integer(Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER)
|
|
8
9
|
|
|
9
10
|
this.integerBetween = (min, max) => {
|
|
10
11
|
if (!Number.isInteger(min) || !Number.isInteger(max)) {
|
|
11
|
-
throw new Error(
|
|
12
|
+
throw new Error(
|
|
13
|
+
`Both the minimum and maximum values must be integers. Provided min: ${min}, max: ${max}`
|
|
14
|
+
)
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
if (min < Number.MIN_SAFE_INTEGER) {
|
|
15
|
-
throw new Error(
|
|
18
|
+
throw new Error(
|
|
19
|
+
`Minimum value must be greater than ${Number.MIN_SAFE_INTEGER}. Provided min: ${min}, max: ${max}`
|
|
20
|
+
)
|
|
16
21
|
}
|
|
17
22
|
|
|
18
23
|
if (max > Number.MAX_SAFE_INTEGER) {
|
|
19
|
-
throw new Error(
|
|
24
|
+
throw new Error(
|
|
25
|
+
`Maximum value must be less than ${Number.MAX_SAFE_INTEGER}. Provided min: ${min}, max: ${max}`
|
|
26
|
+
)
|
|
20
27
|
}
|
|
21
28
|
|
|
22
29
|
if (min > max) {
|
|
23
|
-
throw new Error(
|
|
30
|
+
throw new Error(
|
|
31
|
+
`Minimum value must be less than the maximum value. Provided min: ${min}, max: ${max}`
|
|
32
|
+
)
|
|
24
33
|
}
|
|
25
34
|
|
|
26
35
|
return () => random.integer(min, max)
|
|
@@ -30,11 +39,15 @@ const NumericGenerators = function (random) {
|
|
|
30
39
|
|
|
31
40
|
this.floatBetween = (min, max) => {
|
|
32
41
|
if (!Number.isFinite(min) || !Number.isFinite(max)) {
|
|
33
|
-
throw new Error(
|
|
42
|
+
throw new Error(
|
|
43
|
+
`Both the minimum and maximum values must be numbers. Provided min: ${min}, max: ${max}`
|
|
44
|
+
)
|
|
34
45
|
}
|
|
35
46
|
|
|
36
47
|
if (min > max) {
|
|
37
|
-
throw new Error(
|
|
48
|
+
throw new Error(
|
|
49
|
+
`Minimum value must be less than the maximum value. Provided min: ${min}, max: ${max}`
|
|
50
|
+
)
|
|
38
51
|
}
|
|
39
52
|
|
|
40
53
|
return () => random.real(min, max, true)
|
|
@@ -13,7 +13,9 @@ const ObjectGenerators = function (random, wordGenerators) {
|
|
|
13
13
|
|
|
14
14
|
this.object = () => {
|
|
15
15
|
const numberOfProperties = random.integer(1, 10)
|
|
16
|
-
const propertyNames = new Array(numberOfProperties)
|
|
16
|
+
const propertyNames = new Array(numberOfProperties)
|
|
17
|
+
.fill(1)
|
|
18
|
+
.map(() => wordGenerators.word())
|
|
17
19
|
return createObject(propertyNames)
|
|
18
20
|
}
|
|
19
21
|
|