verify-it 2.3.2 → 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 CHANGED
@@ -1,46 +1,137 @@
1
1
  # `verify-it`
2
2
 
3
- _Randomised test property/data generation for NodeJS._
3
+ [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier)
4
+ [![TypeScript docs verifier](https://img.shields.io/badge/checked_with_%E2%9C%93-TS_docs_verifier-blue.svg?style=flat-square)](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
+ [![Apache 2.0](https://img.shields.io/hexpm/l/plug.svg?style=flat-square)](https://www.apache.org/licenses/LICENSE-2.0)
4
10
 
5
- [![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
6
- [![Build Status](https://travis-ci.org/bbc/verify-it.svg?branch=master)](https://travis-ci.org/bbc/verify-it)
7
- [![dependencies Status](https://david-dm.org/bbc/verify-it/status.svg)](https://david-dm.org/bbc/verify-it)
8
- [![devDependencies Status](https://david-dm.org/bbc/verify-it/dev-status.svg)](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
- * Randomised property inputs for testing (delegating the actual testing to a global `it` or `test` function).
13
- * Global `verify.it` and `verify.test` functions (which are synonyms).
14
- * A global `verify.describe` function (delegating the actual testing to a global `describe` function).
15
- * A series of generator functions that can be used to generate properties.
16
- * Generators are simply functions that produce a value so custom generators are simple to create.
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
- * A property-based testing framework - each test scenario is only run once with the requested randomised inputs.
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
- A global `it` or `test` function is required for `verify-it` to delegate testing to (`it` is used in preference to `test`). 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) or a similar testing framework.
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
- ```javascript
29
- require('mocha')
30
- const { Gen } = require('verify-it')
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('should inject randomised properties',
36
- Gen.string, Gen.object, myGenerator,
37
- (someString, someObject, someCustomValue) => {
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('should allow testing of asynchronous callbacks if the test framework supports it', () => {
43
- Gen.string, Gen.object, myGenerator,
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('allows the same generated value to be shared across multiple tests',
52
- Gen.object, (someOtherObject) => {
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
- * Install dependencies: `yarn install`.
91
- * Run all tests: `yarn test`.
92
- * Check dependencies for security vulnerabilities and licensing issues: `yarn check-dependencies`.
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
- declare var verify: VerifyIt.IVerify
2
-
3
- type VerifyFunction = {
4
- (description: string, callback: (done: VerifyIt.TestDone) => any): any
5
- <T1>(description: string, gen1: () => T1, callback: (value1: T1, done: VerifyIt.TestDone) => any): any
6
- <T1, T2>(description: string, gen1: () => T1, gen2: () => T2, callback: (value1: T1, value2: T2, done: VerifyIt.TestDone) => any): any;
7
- <T1, T2, T3>(description: string, gen1: () => T1, gen2: () => T2, gen3: () => T3, callback: (value1: T1, value2: T2, value3: T3, done: VerifyIt.TestDone) => any): any;
8
- <T1, T2, T3, T4>(description: string, gen1: () => T1, gen2: () => T2, gen3: () => T3, gen4: () => T4, callback: (value1: T1, value2: T2, value3: T3, value4: T4, done: VerifyIt.TestDone) => any): any;
9
- <T1, T2, T3, T4, T5>(description: string, gen1: () => T1, gen2: () => T2, gen3: () => T3, gen4: () => T4, gen5: () => T5, callback: (value1: T1, value2: T2, value3: T3, value4: T4, value5: T5, done: VerifyIt.TestDone) => any): any;
10
- <T1, T2, T3, T4, T5, T6>(description: string, gen1: () => T1, gen2: () => T2, gen3: () => T3, gen4: () => T4, gen5: () => T5, gen6: () => T6, callback: (value1: T1, value2: T2, value3: T3, value4: T4, value5: T5, value6: T6, done: VerifyIt.TestDone) => any): any;
11
- <T1, T2, T3, T4, T5, T6, T7>(description: string, gen1: () => T1, gen2: () => T2, gen3: () => T3, gen4: () => T4, gen5: () => T5, gen6: () => T6, gen7: () => T7, callback: (value1: T1, value2: T2, value3: T3, value4: T4, value5: T5, value6: T6, value7: T7, done: VerifyIt.TestDone) => any): any;
12
- <T1, T2, T3, T4, T5, T6, T7, T8>(description: string, gen1: () => T1, gen2: () => T2, gen3: () => T3, gen4: () => T4, gen5: () => T5, gen6: () => T6, gen7: () => T7, gen8: () => T8, callback: (value1: T1, value2: T2, value3: T3, value4: T4, value5: T5, value6: T6, value7: T7, value8: T8, done: VerifyIt.TestDone) => any): any;
13
- <T1, T2, T3, T4, T5, T6, T7, T8, T9>(description: string, gen1: () => T1, gen2: () => T2, gen3: () => T3, gen4: () => T4, gen5: () => T5, gen6: () => T6, gen7: () => T7, gen8: () => T8, gen9: () => T9, callback: (value1: T1, value2: T2, value3: T3, value4: T4, value5: T5, value6: T6, value7: T7, value8: T8, value9: T9, done: VerifyIt.TestDone) => any): any;
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 VerifyItObject = VerifyFunction & {
17
- only: VerifyFunction
18
- skip: VerifyFunction
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
- declare namespace VerifyIt {
22
- type TestDone = (error?: any) => any
23
-
24
- interface IVerify {
25
- it: VerifyItObject,
26
- test: VerifyItObject,
27
- describe: VerifyItObject
28
- }
29
-
30
- const Gen: {
31
- string: () => string,
32
- stringWithLength: (length: number) => (() => string),
33
- stringNonNumeric: () => string,
34
- integer: () => number,
35
- integerBetween(min: number, max: number): () => number,
36
- float: () => number,
37
- floatBetween(min: number, max: number): () => number,
38
- object: () => object,
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
- declare module 'verify-it' {
50
- export = VerifyIt
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 hasFunction = require('./src/function/hasFunction')
6
+ const getFunction = require('./src/function/getFunction')
7
7
 
8
- const findTestFunction = () => {
9
- if (!hasFunction(global, 'it') && !hasFunction(global, 'test')) {
10
- throw new Error('A global it or test function is required')
8
+ const findTestFunction = (options) => {
9
+ const itFunction = getFunction(options, 'it')
10
+
11
+ if (itFunction) {
12
+ return itFunction
11
13
  }
12
14
 
13
- return global.it || global.test
14
- }
15
+ const testFunction = getFunction(options, 'test')
16
+
17
+ if (testFunction) {
18
+ return testFunction
19
+ }
15
20
 
16
- const testFunction = findTestFunction()
17
- const verifyItFunction = ScenarioRunnerFactory.create(testFunction, ScenarioBuilder, ['only', 'skip'])
18
- global.verify = {
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
- if (hasFunction(global, 'describe')) {
24
- const verifyDescribeFunction = ScenarioRunnerFactory.create(global.describe, ScenarioBuilder, ['only', 'skip'])
25
- global.verify.describe = verifyDescribeFunction
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.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": "JUNIT_REPORT_PATH=test/test-reports/report.xml nyc --all --include=index.js --include=src/*.js --include=src/*/**.js --reporter=html --reporter=text mocha --reporter mocha-jenkins-reporter test/*.js test/**/*.js",
18
- "posttest": "standard",
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,23 +39,14 @@
35
39
  "random-js": "^2.1.0"
36
40
  },
37
41
  "devDependencies": {
38
- "chai": "^4.2.0",
39
- "chai-as-promised": "^7.1.1",
40
- "istanbul": "^0.4.5",
42
+ "@types/mocha": "^10.0.10",
43
+ "@types/node": "^24.10.15",
44
+ "c8": "^11.0.0",
41
45
  "license-checker": "^25.0.1",
42
- "mocha": "^6.1.4",
43
- "mocha-jenkins-reporter": "^0.4.1",
44
- "nyc": "^14.1.1",
45
- "testdouble": "^3.11.0",
46
- "spdx-copyleft": "^0.1.1",
47
- "standard": "^12.0.1"
48
- },
49
- "standard": {
50
- "globals": [
51
- "describe",
52
- "it",
53
- "verify"
54
- ]
46
+ "prettier": "^3.8.1",
47
+ "spdx-copyleft": "^1.0.0",
48
+ "typescript": "^5.9.3",
49
+ "typescript-docs-verifier": "^3.0.1"
55
50
  },
56
51
  "files": [
57
52
  "src",
@@ -2,9 +2,22 @@
2
2
 
3
3
  const createFunctionWithCorrectArgsLength = (numberOfArgs, fn) => {
4
4
  switch (numberOfArgs) {
5
- case 0 : return function () { return fn.apply(this, arguments) }
6
- case 1 : return function (_) { return fn.apply(this, arguments) }
7
- default : throw new Error('Use of more than 1 non-generated scenario arguments is currently unsupported')
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 hasFunction = require('./function/hasFunction')
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.filter((key) => hasFunction(it, key))
26
- .forEach((key) => {
27
- const additionalFunction = it[key]
28
- verifyItFunction[key] = buildDelegatingFunction(additionalFunction, scenarioBuilder)
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((name) => typeof object[name] === 'function')
4
+ return Object.getOwnPropertyNames(object).filter(
5
+ (name) => typeof object[name] === 'function'
6
+ )
5
7
  }
6
8
 
7
9
  module.exports = enumerateFunctions
@@ -0,0 +1,11 @@
1
+ 'use strict'
2
+
3
+ module.exports = (parent, key) => {
4
+ if (parent && parent[key] && typeof parent[key] === 'function') {
5
+ /** @type {typeof parent[key]} */
6
+ const value = parent[key]
7
+ return value
8
+ }
9
+
10
+ return null
11
+ }
@@ -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(`Could not generate distinct values using the provided generator - tried ${maxDistinctRetries} times`)
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 = () => random.integer(Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_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(`Both the minimum and maximum values must be integers. Provided min: ${min}, max: ${max}`)
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(`Minimum value must be greater than ${Number.MIN_SAFE_INTEGER}. Provided min: ${min}, max: ${max}`)
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(`Maximum value must be less than ${Number.MAX_SAFE_INTEGER}. Provided min: ${min}, max: ${max}`)
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(`Minimum value must be less than the maximum value. Provided min: ${min}, max: ${max}`)
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(`Both the minimum and maximum values must be numbers. Provided min: ${min}, max: ${max}`)
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(`Minimum value must be less than the maximum value. Provided min: ${min}, max: ${max}`)
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).fill(1).map(() => wordGenerators.word())
16
+ const propertyNames = new Array(numberOfProperties)
17
+ .fill(1)
18
+ .map(() => wordGenerators.word())
17
19
  return createObject(propertyNames)
18
20
  }
19
21
 
@@ -6,7 +6,7 @@ const SelectionGenerators = function (random) {
6
6
  throw new Error('The options to be picked from must be provided')
7
7
  } else if (!Array.isArray(values)) {
8
8
  throw new Error('The options to be picked from must be an array')
9
- } else if (values.length <= 1) {
9
+ } else if (values.length < 1) {
10
10
  throw new Error('The options array must have at least one entry')
11
11
  }
12
12
 
@@ -875,4 +875,4 @@
875
875
  "action",
876
876
  "tax",
877
877
  "bait"
878
- ]
878
+ ]
@@ -1,3 +0,0 @@
1
- 'use strict'
2
-
3
- module.exports = (parent, key) => !!parent && !!parent[key] && typeof parent[key] === 'function'