Skip to content
This repository has been archived by the owner on Dec 3, 2021. It is now read-only.

Commit

Permalink
feat(string): add better support format and pattern keywords (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
sixaphone authored and derevnjuk committed Nov 2, 2019
1 parent 9317160 commit 5e18fd6
Show file tree
Hide file tree
Showing 8 changed files with 162 additions and 107 deletions.
32 changes: 29 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@
"vinyl-source-stream": "^2.0.0"
},
"dependencies": {
"json-pointer": "^0.6.0"
"faker": "^4.1.0",
"json-pointer": "^0.6.0",
"randexp": "^0.5.3"
},
"husky": {
"hooks": {
Expand Down
6 changes: 6 additions & 0 deletions release.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ module.exports = {
}
}
],
[
'@semantic-release/npm',
{
npmPublish: false
}
],
[
'@semantic-release/github',
{
Expand Down
54 changes: 43 additions & 11 deletions src/samplers/string.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
'use strict';

import { ensureMinLength, toRFCDateTime } from '../utils';
import {ensureMinLength, isBlank, toRFCDateTime} from '../utils';
import faker from 'faker';
import randexp from 'randexp';

const passwordSymbols = 'qwerty!@#$%^123456';

function emailSample() {
return '[email protected]';
return faker.internet.email().toLowerCase();
}

function passwordSample(min, max) {
let res = 'pa$$word';
let res = faker.internet.password();
if (min > res.length) {
res += '_';
res += ensureMinLength(passwordSymbols, min - res.length).substring(0, min - res.length);
Expand Down Expand Up @@ -37,27 +39,53 @@ function dateSample(min, max) {
}

function defaultSample(min, max) {
let res = ensureMinLength('string', min);
let res = ensureMinLength(faker.lorem.word(), min);
if (max && res.length > max) {
res = res.substring(0, max);
}
return res;
}

function ipv4Sample() {
return '192.168.0.1';
return faker.internet.ip();
}

function ipv6Sample() {
return '2001:0db8:85a3:0000:0000:8a2e:0370:7334';
return faker.internet.ipv6();
}

function hostnameSample() {
return 'example.com';
return faker.internet.domainName();
}

function uriSample() {
return 'http://example.com';
return faker.internet.url();
}

function byteSample() {
return Buffer.from(faker.lorem.word()).toString('base64');
}

function binarySample() {
return Buffer.from(faker.lorem.word());
}

function uuidSample() {
return faker.random.uuid();
}

function patternSample(min, max, pattern) {
let res = new randexp(pattern).gen();

if (res.length < min) {
throw new Error(`Using minLength = ${min} is incorrect with pattern ${pattern}`);
}

if (max && res.length > max) {
throw new Error(`Using maxLength = ${max} is incorrect with pattern ${pattern}`);
}

return res;
}

const stringFormats = {
Expand All @@ -69,11 +97,15 @@ const stringFormats = {
'ipv6': ipv6Sample,
'hostname': hostnameSample,
'uri': uriSample,
'byte': byteSample,
'binary': binarySample,
'uuid': uuidSample,
'pattern': patternSample,
'default': defaultSample
};

export function sampleString(schema) {
let format = schema.format || 'default';
let sampler = stringFormats[format] || defaultSample;
return sampler(schema.minLength | 0, schema.maxLength);
let format = schema.pattern ? 'pattern' : schema.format || 'default';
let sampler = stringFormats[format] || defaultSample;
return sampler(schema.minLength | 0, schema.maxLength, schema.pattern);
}
78 changes: 28 additions & 50 deletions test/integration.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ describe('Integration', function() {
};
result = OpenAPISampler.sample(schema);
expected = 'string';
expect(result).to.deep.equal(expected);
expect(typeof result).to.deep.equal(expected);
});

it('should sample number', function() {
schema = {
'type': 'number'
};
result = OpenAPISampler.sample(schema);
expected = 0;
expect(result).to.deep.equal(expected);
expected = 'number';
expect(typeof result).to.deep.equal(expected);
});

it('should sample boolean', function() {
Expand Down Expand Up @@ -73,10 +73,7 @@ describe('Integration', function() {
}
};
result = OpenAPISampler.sample(schema);
expected = {
'title': 'string'
};
expect(result).to.deep.equal(expected);
expect(typeof result.title).to.deep.equal('string');
});

it('should sample object with property with default value', function() {
Expand Down Expand Up @@ -132,11 +129,12 @@ describe('Integration', function() {
};
result = OpenAPISampler.sample(schema);
expected = {
test: 'string',
property1: 0,
property2: 0
};
expect(result).to.deep.equal(expected);
expect(typeof result.test).to.equal('string');
expect(typeof result.property1).to.equal('number');
expect(typeof result.property2).to.equal('number');
});
});

Expand All @@ -148,7 +146,8 @@ describe('Integration', function() {
'type': 'object',
'properties': {
'title': {
'type': 'string'
'type': 'string',
'default': 'string'
}
}
},
Expand Down Expand Up @@ -232,7 +231,7 @@ describe('Integration', function() {
]
};
const result = OpenAPISampler.sample(schema);
expect(result).to.deep.equal(expected);
expect(Array.isArray(result.arr)).to.equal(true);
});

it('should not be confused by subschema without type', function() {
Expand All @@ -246,7 +245,7 @@ describe('Integration', function() {
};
result = OpenAPISampler.sample(schema);
expected = 'string';
expect(result).to.equal(expected);
expect(typeof result).to.equal(expected);
});

it('should not throw for array allOf', function() {
Expand All @@ -269,7 +268,8 @@ describe('Integration', function() {
schema = {
'properties': {
'title': {
'type': 'string'
'type': 'string',
'default': 'string'
}
},
'allOf': [
Expand All @@ -295,7 +295,8 @@ describe('Integration', function() {
'type': 'object',
'properties': {
'title': {
'type': 'string'
'type': 'string',
'default': 'string'
}
},
'allOf': [
Expand All @@ -310,11 +311,8 @@ describe('Integration', function() {
]
};
result = OpenAPISampler.sample(schema);
expected = {
'title': 'string',
'amount': 1
};
expect(result).to.deep.equal(expected);
expect(typeof result.title).to.equal('string');
expect(result.amount).to.equal(1);
});

it('should merge deep properties', function() {
Expand Down Expand Up @@ -350,16 +348,10 @@ describe('Integration', function() {
]
};

expected = {
parent: {
child1: 'string',
child2: 0
}
};

result = OpenAPISampler.sample(schema);

expect(result).to.deep.equal(expected);
expect(typeof result.parent.child1).to.equal('string');
expect(typeof result.parent.child2).to.equal('number');
});
});

Expand Down Expand Up @@ -416,11 +408,8 @@ describe('Integration', function() {
}
};
result = OpenAPISampler.sample(schema);
expected = {
a: 10,
b: 'string'
};
expect(result).to.deep.equal(expected);
expect(result.a).to.deep.equal(10);
expect(typeof result.b).to.equal('string');
});
});

Expand All @@ -438,7 +427,7 @@ describe('Integration', function() {
};
result = OpenAPISampler.sample(schema);
expected = 'string';
expect(result).to.equal(expected);
expect(typeof result).to.equal(expected);
});

it('should support anyOf', function() {
Expand All @@ -454,7 +443,7 @@ describe('Integration', function() {
};
result = OpenAPISampler.sample(schema);
expected = 'string';
expect(result).to.equal(expected);
expect(typeof result).to.equal(expected);
});

it('should prefer oneOf if anyOf and oneOf are on the same level ', function() {
Expand All @@ -471,8 +460,7 @@ describe('Integration', function() {
]
};
result = OpenAPISampler.sample(schema);
expected = 0;
expect(result).to.equal(expected);
expect(typeof result).to.equal('number');
});
});

Expand All @@ -494,10 +482,7 @@ describe('Integration', function() {
}
};
result = OpenAPISampler.sample(schema, {}, spec);
expected = {
a: 'string'
};
expect(result).to.deep.equal(expected);
expect(typeof result.a).to.equal('string');
});

it('should not follow circular $ref', function() {
Expand All @@ -523,11 +508,8 @@ describe('Integration', function() {
}
};
result = OpenAPISampler.sample(schema, {}, spec);
expected = {
a: 'string',
b: {}
};
expect(result).to.deep.equal(expected);
expect(result.b).to.deep.equal({});
expect(typeof result.a).to.equal('string');
});

it('should not follow circular $ref if more than one in properties', function() {
Expand Down Expand Up @@ -591,12 +573,8 @@ describe('Integration', function() {
}
};

expected = {
b: 'string'
};

result = OpenAPISampler.sample(schema, {skipReadOnly: true}, spec);
expect(result).to.deep.equal(expected);
expect(typeof result.b).to.deep.equal('string');
});
});
});
Loading

0 comments on commit 5e18fd6

Please sign in to comment.