Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
884de68
fix: warn on missing schemas while traversing
pateketrueke Jul 7, 2022
bedea94
Homologate validation
LuisTejedaS Sep 6, 2022
0256d4a
remove console.log
LuisTejedaS Sep 7, 2022
8bfef94
Add last commit homologation, tests for examples
LuisTejedaS Sep 7, 2022
f5b839f
Merge pull request #1 from VShingala/feat/pmH1bdTo509
erfemega Sep 7, 2022
3e36efe
Revert "Homologate from 485b48b to 509ca05"
erfemega Sep 7, 2022
bed8181
Exclusive min and max
LuisTejedaS Sep 7, 2022
f973f37
Merge pull request #2 from VShingala/revert-1-feat/pmH1bdTo509
LuisTejedaS Sep 7, 2022
6135f0e
Merge pull request #3 from VShingala/feat/pmH1bdTo509
erfemega Sep 7, 2022
13110e9
Fix issue in handle max and min
LuisTejedaS Sep 7, 2022
b425576
Merge pull request #4 from VShingala/feat/da4andO4b
erfemega Sep 8, 2022
1e778f6
Homologate commits
erfemega Sep 8, 2022
d2ae569
Adding tests to examples(instead of example) scenarios
erfemega Sep 8, 2022
cbf80ee
Update object.js
LuisTejedaS Sep 8, 2022
6562478
d9b4de9 Adding support to pattern key
LuisTejedaS Sep 8, 2022
23ca5fe
adding test
erfemega Sep 9, 2022
963c0ea
Merge branch 'feat/pmHomologation' into feat/pm5eaTof27
erfemega Sep 9, 2022
f0b61d8
comment test to wait next commits
erfemega Sep 9, 2022
67547dc
Update Container.js
LuisTejedaS Sep 9, 2022
ff03c1f
Merge branch 'feat/pm5eaTof27' into feat72EtoD9B
LuisTejedaS Sep 9, 2022
4de7d01
Merge pull request #5 from VShingala/feat/pm5eaTof27
Carlos-Veloz Sep 9, 2022
d433db0
changes on integration tests
Carlos-Veloz Sep 9, 2022
e377d04
fix error in handle exclusive max and min
LuisTejedaS Sep 9, 2022
a67e006
Merge pull request #6 from VShingala/feat72EtoD9B
erfemega Sep 9, 2022
e941362
Merge pull request #7 from VShingala/fix/FixHandleExclWithmultipleOf
erfemega Sep 9, 2022
6c593a4
Update random.json
LuisTejedaS Sep 9, 2022
8232115
reverting change integration tests
Carlos-Veloz Sep 9, 2022
9b4fb28
Merge pull request #9 from VShingala/intTests
LuisTejedaS Sep 9, 2022
74573b3
Merge pull request #8 from VShingala/fix/failingTests
erfemega Sep 9, 2022
474a605
Merge branch 'develop' into feat/pmHomologation
LuisTejedaS Sep 9, 2022
c5fe5cc
Add changes from reverted commit
LuisTejedaS Sep 9, 2022
8944690
Update index.spec.js
LuisTejedaS Sep 9, 2022
4449320
Injecting validateSchema to traverseCallbacks and Fixiing ignoreUnres…
erfemega Sep 10, 2022
3d8773d
Remove browserify and fixed properties as true
LuisTejedaS Sep 12, 2022
ae15107
Merge pull request #10 from VShingala/browserifyingModule
Carlos-Veloz Sep 12, 2022
a1bf1e3
suport falsy examples
LuisTejedaS Sep 12, 2022
b693367
Add option to pick first element from examples
LuisTejedaS Sep 12, 2022
1f02605
replace script
LuisTejedaS Sep 12, 2022
ce81816
Merge pull request #11 from VShingala/integrationFixes
Carlos-Veloz Sep 13, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export interface JSONSchemaFakerOptions {
optionalsProbability?: number | false;
fixedProbabilities?: boolean;
useExamplesValue?: boolean;
avoidExampleItemsLength?: boolean;
useDefaultValue?: boolean;
requiredOnly?: boolean;
minItems?: number;
Expand All @@ -31,6 +32,7 @@ export interface JSONSchemaFakerOptions {
renderComment?: boolean;
refDepthMax?: number;
refDepthMin?: number;
validationOptions?: object;
}

export type JSONSchemaFakerRefs = Schema[] | { [k: string]: Schema };
Expand Down
14 changes: 8 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"test:schema": "npm run test:run tests/schema --",
"test:integration": "npm run test:run tests/integration --",
"coverage": "nyc --es-modules -x '**/tests/**' -x '**/*.spec.js'",
"coverage:all": "npm run coverage -- npm run test:all",
"coverage:all": "npm run coverage -- npm run test:unit && npm run test:integration && npm run test:schema",
"coverage:unit": "npm run coverage -- npm run test:unit",
"report": "nyc report",
"lint": "eslint --ext js,svelte src tests",
Expand All @@ -37,7 +37,7 @@
"copy:wargs": "concat -o dist/wargs.min.js node_modules/wargs/dist/wargs.min.js",
"entry:cjs": "echo 'module.exports = require(\"./main.cjs.js\").default;' > dist/index.js",
"prepublishOnly": "npm run build -- -f",
"postbuild": "npm run copy:bundle && npm run entry:cjs",
"postbuild": "npm run copy:bundle && npm run entry:cjs && node scripts/replaceConsoleError.js",
"prebuild": "mkdir -p dist && npm run copy:vendor && npm run copy:wargs",
"codecov": "codecov --file=coverage/lcov.info -e TRAVIS_NODE_VERSION"
},
Expand Down Expand Up @@ -87,6 +87,7 @@
"@faker-js/faker": "^5.5.3",
"@types/json-schema": "^7.0.9",
"ajv": "^6.12.6",
"ansi-regex": ">=5.0.1",
"chai": "^4.1.2",
"chance": "^1.0.9",
"clone": "^2.1.2",
Expand All @@ -105,21 +106,21 @@
"is-my-json-valid": "^2.19.0",
"less": "^4.1.1",
"less-plugin-autoprefix": "^2.0.0",
"lodash": "4.17.21",
"mocha": "^7.0.0",
"mockjs": "^1.1.0",
"mortero": "^0.0.43",
"nth-check": ">=2.0.1",
"nyc": "^15.0.0",
"pug": "^3.0.2",
"randexp": "^0.5.3",
"seedrandom": "^3.0.1",
"semver": "^7.1.1",
"set-value": ">=4.0.1",
"sinon": "^11.1.1",
"sinon-chai": "^3.7.0",
"smoo": "^0.0.14",
"svelte": "^3.38.2",
"set-value": ">=4.0.1",
"nth-check": ">=2.0.1",
"ansi-regex": ">=5.0.1",
"tv4": "^1.3.0",
"type-fest": "^2.0.0",
"wargs": "^0.9.2",
Expand All @@ -129,6 +130,7 @@
},
"dependencies": {
"json-schema-ref-parser": "^6.1.0",
"jsonpath-plus": "^5.1.0"
"jsonpath-plus": "^5.1.0",
"lodash": "4.17.21"
}
}
10 changes: 10 additions & 0 deletions scripts/replaceConsoleError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
let fs = require('fs');

fs.readFile('dist/bundle.js', 'utf8', (err, data) => {
if (err) {
return console.log(err);
}
fs.writeFile('dist/bundle.js', data.replace(/console.error/g, 'console.warn'), 'utf8', saveErr => {
if (saveErr) return console.log(saveErr);
});
});
6 changes: 5 additions & 1 deletion src/lib/api/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ defaults.failOnInvalidFormat = true;

defaults.alwaysFakeOptionals = false;
defaults.optionalsProbability = null;
defaults.fixedProbabilities = false;
defaults.fixedProbabilities = true;
defaults.useExamplesValue = false;
defaults.avoidExampleItemsLength = false;
defaults.useDefaultValue = false;
defaults.requiredOnly = false;

Expand All @@ -33,3 +34,6 @@ defaults.random = Math.random;
defaults.renderTitle = true;
defaults.renderDescription = true;
defaults.renderComment = false;

defaults.validationOptions = {};
defaults.pickFirstFromExamples = false;
4 changes: 2 additions & 2 deletions src/lib/core/run.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function resolve(obj, data, values, property) {
}

// TODO provide types?
function run(refs, schema, container, synchronous) {
function run(refs, schema, container, synchronous, validateSchema) {
if (Object.prototype.toString.call(schema) !== '[object Object]') {
throw new Error(`Invalid input, expecting object but given ${typeof schema}`);
}
Expand All @@ -100,7 +100,7 @@ function run(refs, schema, container, synchronous) {
refDepthMin,
refDepthMax,
});
const result = traverse(utils.clone(schema), [], resolveSchema);
const result = traverse(utils.clone(schema), [], resolveSchema, undefined, validateSchema);

if (optionAPI('resolveJsonPath')) {
return {
Expand Down
102 changes: 89 additions & 13 deletions src/lib/core/traverse.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import _ from 'lodash';
import utils from './utils';
import random from './random';
import ParseError from './error';
import inferType from './infer';
import types from '../types/index';
import optionAPI from '../api/option';
import ALL_TYPES from './constants';

function getMeta({ $comment: comment, title, description }) {
return Object.entries({ comment, title, description })
Expand All @@ -15,15 +17,15 @@ function getMeta({ $comment: comment, title, description }) {
}

// TODO provide types
function traverse(schema, path, resolve, rootSchema) {
function traverse(schema, path, resolve, rootSchema, validateSchema) {
schema = resolve(schema, null, path);

if (schema && (schema.oneOf || schema.anyOf || schema.allOf)) {
schema = resolve(schema, null, path);
}

if (!schema) {
return;
throw new Error(`Cannot traverse at '${path.join('.')}', given '${JSON.stringify(rootSchema)}'`);
}

const context = {
Expand All @@ -36,19 +38,93 @@ function traverse(schema, path, resolve, rootSchema) {
// example values have highest precedence
if (optionAPI('useExamplesValue') && Array.isArray(schema.examples)) {
// include `default` value as example too
const fixedExamples = schema.examples
.concat('default' in schema ? [schema.default] : []);
let randomExample;
const fixedExamples = schema.examples.concat(
'default' in schema ? [schema.default] : []);
if (optionAPI('pickFirstFromExamples')) {
randomExample = fixedExamples[0];
} else {
randomExample = random.pick(fixedExamples);
}
if (validateSchema) {
let result;
let clonedSchema;

// avoid minItems and maxItems while checking for valid examples
if (optionAPI('avoidExampleItemsLength') && _.get(schema, 'type') === 'array') {
clonedSchema = _.clone(schema);
_.unset(clonedSchema, 'minItems');
_.unset(clonedSchema, 'maxItems');

return { value: utils.typecast(null, schema, () => random.pick(fixedExamples)), context };
result = validateSchema(clonedSchema, randomExample, optionAPI('validationOptions'));
} else {
result = validateSchema(schema, randomExample, optionAPI('validationOptions'));
}

// Use example only if valid
if (result && result.length === 0) {
if (optionAPI('validationOptions') && optionAPI('validationOptions').ignoreUnresolvedVariables) {
return {
value: randomExample,
context,
};
}
return {
value: utils.typecast(null, schema, () => randomExample),
context,
};
}
} else {
console.warn('Taking example from schema without validation');
return {
value: utils.typecast(null, schema, () => randomExample),
context,
};
}
}
// If schema contains single example property
if (optionAPI('useExamplesValue') && schema.example) {
return { value: utils.typecast(null, schema, () => schema.example), context };
if (optionAPI('useExamplesValue') && !_.isNil(schema.example)) {
if (validateSchema) {
let result;
let clonedSchema;

// avoid minItems and maxItems while checking for valid examples
if (optionAPI('avoidExampleItemsLength') && _.get(schema, 'type') === 'array') {
clonedSchema = _.clone(schema);
_.unset(clonedSchema, 'minItems');
_.unset(clonedSchema, 'maxItems');

result = validateSchema(clonedSchema, schema.example, optionAPI('validationOptions'));
} else {
result = validateSchema(schema, schema.example, optionAPI('validationOptions'));
}

// Use example only if valid
if (result && result.length === 0) {
if (optionAPI('validationOptions') && optionAPI('validationOptions').ignoreUnresolvedVariables) {
return {
value: schema.example,
context,
};
}
return {
value: utils.typecast(null, schema, () => schema.example),
context,
};
}
} else {
console.warn('Taking example from schema without validation');
return { value: utils.typecast(null, schema, () => schema.example), context };
}
}

// use default as faked value if found as keyword in schema
if (optionAPI('useDefaultValue') && 'default' in schema) {
if (schema.default !== '' || !optionAPI('replaceEmptyByRandomValue')) {
return { value: schema.default, context };
// to not use default as faked value in case it is actual property of schema
if (!(_.has(schema.default, 'type') && _.includes(ALL_TYPES, schema.default.type))) {
if (schema.default !== '' || !optionAPI('replaceEmptyByRandomValue')) {
return { value: schema.default, context };
}
}
}

Expand All @@ -66,15 +142,15 @@ function traverse(schema, path, resolve, rootSchema) {

// build new object value from not-schema!
if (schema.type && schema.type === 'object') {
const { value, context: innerContext } = traverse(schema, path.concat(['not']), resolve, rootSchema);
const { value, context: innerContext } = traverse(schema, path.concat(['not']), resolve, rootSchema, validateSchema);
return { value: utils.clean(value, schema, false), context: { ...context, items: innerContext } };
}
}

// thunks can return sub-schemas
if (typeof schema.thunk === 'function') {
// result is already cleaned in thunk
const { value, context: innerContext } = traverse(schema.thunk(rootSchema), path, resolve);
const { value, context: innerContext } = traverse(schema.thunk(rootSchema), path, resolve, undefined, validateSchema);
return { value, context: { ...context, items: innerContext } };
}

Expand Down Expand Up @@ -130,7 +206,7 @@ function traverse(schema, path, resolve, rootSchema) {
}
} else {
try {
const innerResult = types[type](schema, path, resolve, traverse);
const innerResult = types[type](schema, path, resolve, validateSchema, traverse);
if (type === 'array') {
return {
value: innerResult.map(({ value }) => value),
Expand Down Expand Up @@ -172,7 +248,7 @@ function traverse(schema, path, resolve, rootSchema) {
Object.keys(schema).forEach(prop => {
if (pruneProperties.includes(prop)) return;
if (typeof schema[prop] === 'object' && prop !== 'definitions') {
const { value, context: innerContext } = traverse(schema[prop], path.concat([prop]), resolve, valueCopy);
const { value, context: innerContext } = traverse(schema[prop], path.concat([prop]), resolve, valueCopy, validateSchema);
valueCopy[prop] = utils.clean(value, schema[prop], false);
contextCopy[prop] = innerContext;
} else {
Expand Down
Loading