@unmock/jaymock
Advanced tools
Comparing version 1.0.1 to 1.0.2
194
index.js
@@ -16,3 +16,3 @@ 'use strict' | ||
const isObject = value => isType(value, 'object') | ||
const generateArrayOfLength = length => [...Array(length)] | ||
const generateArrayOfLength = length => [...new Array(length)] | ||
const isObjectKey = (key, object) => Object.keys(object).includes(key) | ||
@@ -30,6 +30,7 @@ | ||
const generateFakerData = (topic, subtopic) => { | ||
if (topic === 'fake') { | ||
return faker[topic](subtopic.slice(1, -1)) | ||
} | ||
return faker[topic][subtopic]() | ||
if (topic === 'fake') { | ||
return faker[topic](subtopic.slice(1, -1)) | ||
} | ||
return faker[topic][subtopic]() | ||
} | ||
@@ -46,14 +47,17 @@ | ||
const parsePayload = payload => { | ||
let topic, subtopic | ||
if (/^fake/.test(payload)) { | ||
topic = 'fake' | ||
subtopic = payload.split(topic)[1] | ||
} else { | ||
[topic, subtopic] = payload.split(/\.(.+)/) | ||
} | ||
return [topic, subtopic] | ||
let topic | ||
let subtopic | ||
payload = String(payload) | ||
if (payload.startsWith('fake')) { | ||
topic = 'fake'; | ||
[, subtopic] = payload.split(topic) | ||
} else { | ||
[topic, subtopic] = payload.split(/\.(.+)/) | ||
} | ||
return [topic, subtopic] | ||
} | ||
/** | ||
* Returns the appropriate fake data | ||
* Returns the appropriate fake data | ||
* (generated using either Faker.js or custom functions). | ||
@@ -68,31 +72,39 @@ * | ||
const fake = (payload, customFunctions) => { | ||
let numOfValues = null | ||
let [topic, subtopic] = parsePayload(payload) | ||
if (subtopic && subtopic.includes('|')) { | ||
[subtopic, numOfValues] = subtopic.split('|') | ||
numOfValues = parseInt(numOfValues) | ||
} else if (!subtopic && topic && topic.includes('|')) { | ||
[topic, numOfValues] = topic.split('|') | ||
numOfValues = parseInt(numOfValues) | ||
} | ||
if (isObjectKey(topic, customFunctions)) { | ||
let func = customFunctions[topic] | ||
if (numOfValues) { | ||
if (func[subtopic] !== undefined) { | ||
return generateArrayOfLength(numOfValues).map(_ => func[subtopic]()) | ||
} | ||
return generateArrayOfLength(numOfValues).map(_ => func()) | ||
} | ||
if (func[subtopic]) { | ||
return func[subtopic]() | ||
} | ||
return func() | ||
} | ||
if ((faker[topic] === undefined || faker[topic][subtopic] === undefined) && !subtopic.includes('.') && !subtopic.includes('|')) { | ||
throw new Error(`Faker function ${JSON.stringify(topic + '.' + subtopic)} does not exist`) | ||
} | ||
if (numOfValues) { | ||
return generateArrayOfLength(numOfValues).map(_ => generateFakerData(topic, subtopic)) | ||
} | ||
return generateFakerData(topic, subtopic) | ||
let numOfValues = null | ||
let [topic, subtopic] = parsePayload(payload) | ||
if (subtopic && subtopic.includes('|')) { | ||
[subtopic, numOfValues] = subtopic.split('|') | ||
numOfValues = parseInt(numOfValues, 10) | ||
} else if (!subtopic && topic && topic.includes('|')) { | ||
[topic, numOfValues] = topic.split('|') | ||
numOfValues = parseInt(numOfValues, 10) | ||
} | ||
if (isObjectKey(topic, customFunctions)) { | ||
const func = customFunctions[topic] | ||
if (numOfValues) { | ||
if (func[subtopic] !== undefined) { | ||
return generateArrayOfLength(numOfValues).map(_ => func[subtopic]()) | ||
} | ||
return generateArrayOfLength(numOfValues).map(_ => func()) | ||
} | ||
if (func[subtopic]) { | ||
return func[subtopic]() | ||
} | ||
return func() | ||
} | ||
if (!subtopic || ((faker[topic] === undefined || faker[topic][subtopic] === undefined) && !subtopic.includes('.') && !subtopic.includes('|'))) { | ||
subtopic = subtopic ? '.' + subtopic : '' | ||
throw new Error(`Function ${JSON.stringify(topic + subtopic)} does not exist`) | ||
} | ||
if (numOfValues) { | ||
return generateArrayOfLength(numOfValues).map(_ => generateFakerData(topic, subtopic)) | ||
} | ||
return generateFakerData(topic, subtopic) | ||
} | ||
@@ -111,32 +123,36 @@ | ||
const populateObject = (object, funcObject, firstRun = true) => { | ||
object = cloneDeep(object) | ||
const repeatParentObject = firstRun && isObjectKey('_repeat', object) && object['_repeat'] !== undefined | ||
for (let [key, value] of Object.entries(object)) { | ||
if (repeatParentObject) { | ||
value = object | ||
} | ||
if (isObject(value)) { | ||
if (value['_repeat'] !== undefined) { | ||
const repeatCount = value['_repeat'] | ||
delete value['_repeat'] | ||
if (repeatParentObject) { | ||
const temp = object | ||
object = [] | ||
for (let j = 0; j < repeatCount; j++) { | ||
object.push(populateObject(temp, funcObject, false)) | ||
} | ||
return object | ||
} | ||
object[key] = [] | ||
for (let j = 0; j < repeatCount; j++) { | ||
object[key].push(populateObject(value, funcObject, false)) | ||
} | ||
} else { | ||
object[key] = populateObject(value, funcObject, false) | ||
} | ||
} else { | ||
object[key] = fake(value, funcObject) | ||
} | ||
} | ||
return object | ||
object = cloneDeep(object) | ||
const repeatParentObject = firstRun && isObjectKey('_repeat', object) && object._repeat !== undefined | ||
for (let [key, value] of Object.entries(object)) { | ||
if (repeatParentObject) { | ||
value = object | ||
} | ||
if (isObject(value)) { | ||
if (value._repeat) { | ||
const repeatCount = value._repeat | ||
delete value._repeat | ||
if (repeatParentObject) { | ||
const temp = object | ||
object = [] | ||
for (let j = 0; j < repeatCount; j++) { | ||
object.push(populateObject(temp, funcObject, false)) | ||
} | ||
return object | ||
} | ||
object[key] = [] | ||
for (let j = 0; j < repeatCount; j++) { | ||
object[key].push(populateObject(value, funcObject, false)) | ||
} | ||
} else { | ||
object[key] = populateObject(value, funcObject, false) | ||
} | ||
} else { | ||
object[key] = fake(value, funcObject) | ||
} | ||
} | ||
return object | ||
} | ||
@@ -160,4 +176,4 @@ | ||
function JayMock() { | ||
this.template = {} | ||
this.functions = {} | ||
this.template = {} | ||
this.functions = {} | ||
} | ||
@@ -174,5 +190,5 @@ | ||
JayMock.prototype.populate = function(template) { | ||
this.template = template | ||
return populateObject(this.template, this.functions) | ||
JayMock.prototype.populate = function (template) { | ||
this.template = template | ||
return populateObject(this.template, this.functions) | ||
} | ||
@@ -189,8 +205,8 @@ | ||
JayMock.prototype.extend = function(funcName, funcBody = null) { | ||
if (isObject(funcName) && funcBody !== null) { | ||
this.functions = funcName | ||
} else { | ||
this.functions[funcName] = funcBody | ||
} | ||
JayMock.prototype.extend = function (funcName, funcBody) { | ||
if (isObject(funcName) && !funcBody) { | ||
this.functions = funcName | ||
} else { | ||
this.functions[funcName] = funcBody | ||
} | ||
} | ||
@@ -206,4 +222,4 @@ | ||
JayMock.prototype.setFakerLocale = function(locale) { | ||
faker.locale = locale | ||
JayMock.prototype.setFakerLocale = function (locale) { | ||
faker.locale = locale | ||
} | ||
@@ -219,4 +235,4 @@ | ||
JayMock.prototype.setFakerSeed = function(seed) { | ||
faker.seed(seed) | ||
} | ||
JayMock.prototype.setFakerSeed = function (seed) { | ||
faker.seed(seed) | ||
} |
{ | ||
"name": "@unmock/jaymock", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"description": "Minimal fake JSON test data generator", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "ava" | ||
"test": "xo && ava" | ||
}, | ||
@@ -13,2 +13,11 @@ "repository": { | ||
}, | ||
"xo": { | ||
"semicolon": false, | ||
"rules": { | ||
"max-depth": [ | ||
"error", | ||
5 | ||
] | ||
} | ||
}, | ||
"author": "unmock", | ||
@@ -25,3 +34,4 @@ "license": "MIT", | ||
"devDependencies": { | ||
"ava": "^2.4.0" | ||
"ava": "^2.4.0", | ||
"xo": "^0.25.3" | ||
}, | ||
@@ -28,0 +38,0 @@ "keywords": [ |
@@ -101,3 +101,3 @@ # jaymock | ||
Adds a custom data generation function that can be called in the `.populate` `template` using the value of `name`. | ||
Adds a custom data generation function that can be called in the [`.populate`](#populatetemplate) `template` using the value of `name`. | ||
@@ -114,3 +114,3 @@ #### name | ||
Adds custom data generation functions that can be called in the `.populate` `template` using the value of each object ke. | ||
Adds custom data generation functions that can be called in the [`.populate`](#populatetemplate) `template` using the value of each object key. | ||
@@ -121,3 +121,3 @@ #### functions | ||
Each object `key` should be the relevant function's name and `value` the function's body (e.g. `{ 'chance', new require('chance')() }`). | ||
Each object `key` should be the relevant function's name and `value` the function's body (e.g. `{ 'chance': new require('chance')() }`). | ||
@@ -142,2 +142,6 @@ ### .setFakerLocale(locale) | ||
## Related | ||
- [micro-jaymock](https://github.com/unmock/micro-jaymock) - Tiny API mocking microservice, which uses jaymock | ||
## Contributing | ||
@@ -151,4 +155,8 @@ | ||
## Credits | ||
- [`Faker.js`](https://github.com/Marak/Faker.js) is used as `jaymock`'s core fake data generator. | ||
## License | ||
MIT © [Meeshkan](http://meeshkan.com/) |
294
test.js
import test from 'ava' | ||
const jaymock = require('./index') | ||
const jaymock = require('.') | ||
const fixtures = { | ||
flat: { | ||
firstName: 'name.firstName', | ||
lastName: 'name.lastName' | ||
}, | ||
nested: { | ||
addresses: { | ||
homeAddress: { | ||
streetAddress: 'address.streetAddress', | ||
city: 'address.city', | ||
zipCode: 'address.zipCode' | ||
}, | ||
workAddress: { | ||
streetAddress: 'address.streetAddress', | ||
city: 'address.city', | ||
zipCode: 'address.zipCode' | ||
} | ||
} | ||
}, | ||
repeat: { | ||
firstName: 'name.firstName', | ||
lastName: 'name.lastName', | ||
_repeat: 5 | ||
}, | ||
repeatNested: { | ||
firstName: 'name.firstName', | ||
lastName: 'name.lastName', | ||
ipAddress: { | ||
ipv4: 'internet.ip', | ||
ipv6: 'internet.ipv6', | ||
_repeat: 3 | ||
} | ||
}, | ||
arrayFunction: { | ||
ipAddress: 'internet.ip|5' | ||
}, | ||
customFunction: { | ||
color: 'hexColor' | ||
}, | ||
customArrayFunction: { | ||
color: 'hexColor|10' | ||
}, | ||
fakerFake: { | ||
fullName: 'fake({{name.lastName}}, {{name.firstName}} {{name.suffix}})' | ||
}, | ||
invalidFakerFunction: { | ||
invalid: 'name.doesnt_exist' | ||
}, | ||
fakerLocale: { | ||
name: 'name.firstName' | ||
}, | ||
fakerSeed: { | ||
number: 'random.number' | ||
} | ||
flat: { | ||
firstName: 'name.firstName', | ||
lastName: 'name.lastName' | ||
}, | ||
nested: { | ||
addresses: { | ||
homeAddress: { | ||
streetAddress: 'address.streetAddress', | ||
city: 'address.city', | ||
zipCode: 'address.zipCode' | ||
}, | ||
workAddress: { | ||
streetAddress: 'address.streetAddress', | ||
city: 'address.city', | ||
zipCode: 'address.zipCode' | ||
} | ||
} | ||
}, | ||
repeat: { | ||
firstName: 'name.firstName', | ||
lastName: 'name.lastName', | ||
_repeat: 5 | ||
}, | ||
repeatNested: { | ||
firstName: 'name.firstName', | ||
lastName: 'name.lastName', | ||
ipAddress: { | ||
ipv4: 'internet.ip', | ||
ipv6: 'internet.ipv6', | ||
_repeat: 3 | ||
} | ||
}, | ||
arrayFunction: { | ||
ipAddress: 'internet.ip|5' | ||
}, | ||
customFunction: { | ||
color: 'hexColor' | ||
}, | ||
customArrayFunction: { | ||
color: 'hexColor|10' | ||
}, | ||
fakerFake: { | ||
fullName: 'fake({{name.lastName}}, {{name.firstName}} {{name.suffix}})' | ||
}, | ||
invalidFakerFunction: { | ||
invalid: 'name.doesnt_exist' | ||
}, | ||
fakerLocale: { | ||
name: 'name.firstName' | ||
}, | ||
fakerSeed: { | ||
number: 'random.number' | ||
} | ||
} | ||
test('flat object', t => { | ||
const data = fixtures.flat | ||
const expectedKeys = Object.keys(data) | ||
const obj = jaymock().populate(data) | ||
const actualKeys = Object.keys(obj) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
actualKeys.forEach(key => { | ||
t.true(obj[key] != undefined && obj[key].length > 0) | ||
}) | ||
const data = fixtures.flat | ||
const expectedKeys = Object.keys(data) | ||
const obj = jaymock().populate(data) | ||
const actualKeys = Object.keys(obj) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
actualKeys.forEach(key => { | ||
t.true(obj[key] !== undefined && obj[key].length > 0) | ||
}) | ||
}) | ||
test('nested object', t => { | ||
const data = fixtures.flat | ||
const expectedKeys = Object.keys(data) | ||
const obj = jaymock().populate(data) | ||
const actualKeys = Object.keys(data) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
actualKeys.forEach(key => { | ||
t.true(obj[key] != undefined && (obj[key].length > 0 || typeof obj[key] === 'object')) | ||
}) | ||
const data = fixtures.flat | ||
const expectedKeys = Object.keys(data) | ||
const obj = jaymock().populate(data) | ||
const actualKeys = Object.keys(data) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
actualKeys.forEach(key => { | ||
t.true(obj[key] !== undefined && (obj[key].length > 0 || typeof obj[key] === 'object')) | ||
}) | ||
}) | ||
test('repeat mother object', t => { | ||
const data = fixtures.repeat | ||
const expectedKeys = Object.keys(data).filter(x => x != '_repeat') | ||
const objects = jaymock().populate(data) | ||
objects.forEach(obj => { | ||
const actualKeys = Object.keys(obj) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
actualKeys.forEach(key => { | ||
t.true(obj[key] != undefined && obj[key].length > 0) | ||
}) | ||
}) | ||
const data = fixtures.repeat | ||
const expectedKeys = Object.keys(data).filter(x => x !== '_repeat') | ||
const objects = jaymock().populate(data) | ||
objects.forEach(obj => { | ||
const actualKeys = Object.keys(obj) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
actualKeys.forEach(key => { | ||
t.true(obj[key] !== undefined && obj[key].length > 0) | ||
}) | ||
}) | ||
}) | ||
test('repeat nested object', t => { | ||
const data = fixtures.repeatNested | ||
const obj = jaymock().populate(data) | ||
Object.keys(obj).forEach(key => { | ||
const value = obj[key] | ||
t.true(value != undefined && value.length > 0) | ||
if (key === 'ipAddress') { | ||
t.true(Array.isArray(value)) | ||
value.forEach(innerObj => { | ||
const expectedKeys = Object.keys(data.ipAddress).filter(x => x != '_repeat') | ||
const actualKeys = Object.keys(innerObj) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
actualKeys.forEach(innerKey => { | ||
t.true(innerObj[innerKey] != undefined && innerObj[innerKey].length > 0) | ||
}) | ||
}) | ||
} | ||
}) | ||
const data = fixtures.repeatNested | ||
const obj = jaymock().populate(data) | ||
Object.keys(obj).forEach(key => { | ||
const value = obj[key] | ||
t.true(value !== undefined && value.length > 0) | ||
if (key === 'ipAddress') { | ||
t.true(Array.isArray(value)) | ||
value.forEach(innerObj => { | ||
const expectedKeys = Object.keys(data.ipAddress).filter(x => x !== '_repeat') | ||
const actualKeys = Object.keys(innerObj) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
actualKeys.forEach(innerKey => { | ||
t.true(innerObj[innerKey] !== undefined && innerObj[innerKey].length > 0) | ||
}) | ||
}) | ||
} | ||
}) | ||
}) | ||
const ipAddressRegex = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/ | ||
const ipAddressRegex = /^(?:\d{1,3}\.){3}\d{1,3}$/ | ||
test('{faker function}|{desired array length}', t => { | ||
const data = fixtures.arrayFunction | ||
const expectedKeys = Object.keys(data) | ||
const obj = jaymock().populate(data) | ||
const actualKeys = Object.keys(obj) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
const actualArray = obj['ipAddress'] | ||
t.true(Array.isArray(actualArray) && actualArray.length === parseInt(data.ipAddress.split('|')[1])) | ||
actualArray.forEach(value => t.true(ipAddressRegex.test(value))) | ||
const data = fixtures.arrayFunction | ||
const expectedKeys = Object.keys(data) | ||
const obj = jaymock().populate(data) | ||
const actualKeys = Object.keys(obj) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
const actualArray = obj.ipAddress | ||
t.true(Array.isArray(actualArray) && actualArray.length === parseInt(data.ipAddress.split('|')[1], 10)) | ||
actualArray.forEach(value => t.regex(value, ipAddressRegex)) | ||
}) | ||
const randomHexColor = () => '#' + ('000000' + Math.floor(Math.random()*16777215).toString(16)).slice(-6) | ||
const randomHexColor = () => '#' + ('000000' + Math.floor(Math.random() * 16777215).toString(16)).slice(-6) | ||
const hexColorRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/ | ||
test('custom data generation function', t => { | ||
const data = fixtures.customFunction | ||
const expectedKeys = Object.keys(data) | ||
const jm = jaymock() | ||
jm.extend('hexColor', () => randomHexColor()) | ||
const obj = jm.populate(data) | ||
const actualKeys = Object.keys(obj) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
t.true(hexColorRegex.test(obj.color)) | ||
const data = fixtures.customFunction | ||
const expectedKeys = Object.keys(data) | ||
const jm = jaymock() | ||
jm.extend('hexColor', () => randomHexColor()) | ||
const obj = jm.populate(data) | ||
const actualKeys = Object.keys(obj) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
t.regex(obj.color, hexColorRegex) | ||
}) | ||
test('{custom function}|{desired array length}', t => { | ||
const data = fixtures.customArrayFunction | ||
const expectedKeys = Object.keys(data) | ||
const jm = jaymock() | ||
jm.extend('hexColor', () => randomHexColor()) | ||
const obj = jm.populate(data) | ||
const actualKeys = Object.keys(obj) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
const actualArray = obj['color'] | ||
t.true(Array.isArray(actualArray) && actualArray.length === parseInt(data.color.split('|')[1])) | ||
actualArray.forEach(value => t.true(hexColorRegex.test(value))) | ||
const data = fixtures.customArrayFunction | ||
const expectedKeys = Object.keys(data) | ||
const jm = jaymock() | ||
jm.extend('hexColor', () => randomHexColor()) | ||
const obj = jm.populate(data) | ||
const actualKeys = Object.keys(obj) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
const actualArray = obj.color | ||
t.true(Array.isArray(actualArray) && actualArray.length === parseInt(data.color.split('|')[1], 10)) | ||
actualArray.forEach(value => t.regex(value, hexColorRegex)) | ||
}) | ||
test('faker.fake() generation function', t => { | ||
const data = fixtures.fakerFake | ||
const expectedKeys = Object.keys(data) | ||
const obj = jaymock().populate(data) | ||
const actualKeys = Object.keys(obj) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
t.true(obj.fullName.split(' ').length > 1) | ||
const data = fixtures.fakerFake | ||
const expectedKeys = Object.keys(data) | ||
const obj = jaymock().populate(data) | ||
const actualKeys = Object.keys(obj) | ||
t.deepEqual(expectedKeys, actualKeys) | ||
t.true(obj.fullName.split(' ').length > 1) | ||
}) | ||
test('invalid function', t => { | ||
const data = fixtures.invalidFakerFunction | ||
const error = t.throws(() => { | ||
jaymock().populate(data) | ||
}, Error); | ||
t.is(error.message, `Faker function ${JSON.stringify(data.invalid)} does not exist`); | ||
const data = fixtures.invalidFakerFunction | ||
const error = t.throws(() => { | ||
jaymock().populate(data) | ||
}, Error) | ||
t.is(error.message, `Function ${JSON.stringify(data.invalid)} does not exist`) | ||
}) | ||
test('faker locale', t => { | ||
const data = fixtures.fakerLocale | ||
const jm = jaymock() | ||
jm.setFakerLocale('ru') | ||
const obj = jm.populate(data) | ||
t.true(/[\w\u0430-\u044f]+/.test(obj[Object.keys(obj)[0]])) | ||
const data = fixtures.fakerLocale | ||
const jm = jaymock() | ||
jm.setFakerLocale('ru') | ||
const obj = jm.populate(data) | ||
t.regex(obj[Object.keys(obj)[0]], /[\w\u0430-\u044F]+/) | ||
}) | ||
test('faker random seed', t => { | ||
const data = fixtures.fakerSeed | ||
const jm = jaymock() | ||
jm.setFakerSeed(1) | ||
const obj = jm.populate(data) | ||
t.deepEqual(obj[Object.keys(obj)[0]], 41702) | ||
}) | ||
const data = fixtures.fakerSeed | ||
const jm = jaymock() | ||
jm.setFakerSeed(1) | ||
const obj = jm.populate(data) | ||
t.is(obj[Object.keys(obj)[0]], 41702) | ||
}) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
362
157
15543
2