From 91400966edc4e39c9b9d4fbfedde521af6683b1f Mon Sep 17 00:00:00 2001 From: Javier Cejudo <javier@javiercejudo.com> Date: Wed, 26 Jul 2017 07:36:54 +1000 Subject: [PATCH] Feat: add option to override random generation (#307) --- README.md | 1 + package.json | 1 + spec/schema/core/option/random.js | 9 ++++++++ spec/schema/core/option/random.json | 35 +++++++++++++++++++++++++++++ ts/class/Container.ts | 4 ++++ ts/class/OptionRegistry.ts | 3 ++- ts/core/random.ts | 8 ++++--- ts/generators/boolean.ts | 4 +++- ts/types/string.ts | 2 +- 9 files changed, 61 insertions(+), 6 deletions(-) create mode 100644 spec/schema/core/option/random.js create mode 100644 spec/schema/core/option/random.json diff --git a/README.md b/README.md index d60b334f..de3406fd 100644 --- a/README.md +++ b/README.md @@ -415,6 +415,7 @@ You may define following options for `jsf` that alter its behavior: - `defaultInvalidTypeProduct`: - default value generated for a schema with invalid type (works only if `failOnInvalidTypes` is set to `false`) - `maxItems`: number - Configure a maximum amount of items to generate in an array. This will override the maximum items found inside a JSON Schema. - `maxLength`: number - Configure a maximum length to allow generating strings for. This will override the maximum length found inside a JSON Schema. +- `random`: Function - a replacement for `Math.random` to support pseudorandom number generation. Set options just as below: diff --git a/package.json b/package.json index e6b8d695..e4fce361 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "jasmine-node": "2.0.0-beta4", "jayschema": "^0.3.1", "lodash.template": "^4.4.0", + "seedrandom": "^2.4.3", "semver": "^5.3.0", "tslint": "^4.0.2", "tv4": "^1.2.7", diff --git a/spec/schema/core/option/random.js b/spec/schema/core/option/random.js new file mode 100644 index 00000000..d53558ac --- /dev/null +++ b/spec/schema/core/option/random.js @@ -0,0 +1,9 @@ +const seedrandom = require('seedrandom'); + +module.exports = { + register: function(jsf) { + return jsf.option({ + random: seedrandom('some seed') + }); + } +}; diff --git a/spec/schema/core/option/random.json b/spec/schema/core/option/random.json new file mode 100644 index 00000000..6670a301 --- /dev/null +++ b/spec/schema/core/option/random.json @@ -0,0 +1,35 @@ +[ + { + "description": "random option", + "tests": [ + { + "description": "should allow pseudorandom value generation", + "schema": { + "type": "object", + "properties": { + "a": { + "type": "integer", + "minimum": 0, + "maximum": 100 + }, + "b": { + "type": "string" + }, + "c": { + "pattern": "^[a-z]{2}[0-9]{3}$" + } + }, + "required": ["a", "b", "c"] + }, + "valid": true, + "equal": { + "a": 39, + "b": "dolore et qui ex", + "c": "hv837" + }, + "repeat": 1, + "require": "core/option/random" + } + ] + } +] diff --git a/ts/class/Container.ts b/ts/class/Container.ts index af41152e..58bfb96b 100644 --- a/ts/class/Container.ts +++ b/ts/class/Container.ts @@ -4,6 +4,10 @@ import option = require('../api/option'); // set maximum default, see #193 RandExp.prototype.max = 10; +// same implementation as the original except using our random +RandExp.prototype.randInt = (a, b) => + a + Math.floor(option('random')() * (1 + b - a)); + type Dependency = any; /** diff --git a/ts/class/OptionRegistry.ts b/ts/class/OptionRegistry.ts index e1dd9f87..ee2ade10 100644 --- a/ts/class/OptionRegistry.ts +++ b/ts/class/OptionRegistry.ts @@ -1,6 +1,6 @@ import Registry = require('./Registry'); -type Option = boolean|number; +type Option = boolean|number|Function; /** * This class defines a registry for custom formats used within JSF. @@ -18,6 +18,7 @@ class OptionRegistry extends Registry<Option> { this.data['defaultMinItems'] = 0; this.data['defaultRandExpMax'] = 10; this.data['alwaysFakeOptionals'] = false; + this.data['random'] = Math.random; } } diff --git a/ts/core/random.ts b/ts/core/random.ts index 7332f3fa..e67dbe3f 100644 --- a/ts/core/random.ts +++ b/ts/core/random.ts @@ -1,5 +1,7 @@ /// <reference path="../index.d.ts" /> +var option = require('../api/option'); + /** * Returns random element of a collection * @@ -7,7 +9,7 @@ * @returns {T} */ function pick<T>(collection: T[]): T { - return collection[Math.floor(Math.random() * collection.length)]; + return collection[Math.floor(option('random')() * collection.length)]; } /** @@ -23,7 +25,7 @@ function shuffle<T>(collection: T[]): T[] { length: number = collection.length; for (; length > 0;) { - key = Math.floor(Math.random() * length); + key = Math.floor(option('random')() * length); // swap tmp = copy[--length]; copy[length] = copy[key]; @@ -48,7 +50,7 @@ var MIN_NUMBER = -100, * @see http://stackoverflow.com/a/1527820/769384 */ function getRandomInt(min: number, max: number): number { - return Math.floor(Math.random() * (max - min + 1)) + min; + return Math.floor(option('random')() * (max - min + 1)) + min; } /** diff --git a/ts/generators/boolean.ts b/ts/generators/boolean.ts index 49980060..9c74a156 100644 --- a/ts/generators/boolean.ts +++ b/ts/generators/boolean.ts @@ -1,10 +1,12 @@ +var option = require('../api/option'); + /** * Generates randomized boolean value. * * @returns {boolean} */ function booleanGenerator(): boolean { - return Math.random() > 0.5; + return option('random')() > 0.5; } export = booleanGenerator; diff --git a/ts/types/string.ts b/ts/types/string.ts index 39d5f7ec..2dfa3cab 100644 --- a/ts/types/string.ts +++ b/ts/types/string.ts @@ -55,7 +55,7 @@ var stringType: FTypeGenerator = function stringType(value: IStringSchema): stri } while (output.length < minLength) { - output += Math.random() > 0.7 ? thunk() : randexp('.+'); + output += option('random')() > 0.7 ? thunk() : randexp('.+'); } if (output.length > maxLength) { -- GitLab