Skip to content

Commit

Permalink
Merge 6c96e62 into 270511e
Browse files Browse the repository at this point in the history
  • Loading branch information
faboulaws committed Aug 31, 2019
2 parents 270511e + 6c96e62 commit 6c6648e
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 30 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ const mock = blogFactory.generate({
}
```

# Define options for nested properties
# Define options for nested properties

To define options for nested a property use the nested property path (property names sperated by a dot).
Example:
Expand Down
31 changes: 30 additions & 1 deletion lib/mocker.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,38 @@ const generators = {
},
};

const getPropertyByPath = (object, path) => get(object, path);

const getPropertyByName = (object, propName) => object[propName];

const propertyIsSkipped = (path, options) => {
const fieldOptions = getPropertyByName(options, path) || getPropertyByPath(options, path) || {};
return fieldOptions.skip === true;
};

const propertyParentIsSkipped = (path, options) => {
const pathProps = path.split('.');
if (pathProps.length > 1) {
let parentPath = '';
// eslint-disable-next-line no-restricted-syntax
for (const pathProp of pathProps) {
parentPath = parentPath.length === 0 ? pathProp : `${parentPath}.${pathProp}`;
const parentObject = getPropertyByPath(options, parentPath) ||
getPropertyByName(options, parentPath) || {};
if (parentObject.skip === true) {
return true;
}
}
}
return false;
};

const shouldSkipProperty = (path, options) =>
propertyIsSkipped(path, options) || propertyParentIsSkipped(path, options);

function populateField(mockObject, schema, path, options, staticValue) {
const fieldOptions = options[path] || {};
if (!fieldOptions.skip) {
if (!shouldSkipProperty(path, options)) {
let value;
const pathDef = schema.path(path);

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"eslint": "^4.18.1",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-import": "^2.9.0",
"flat": "^4.1.0",
"husky": "^3.0.3",
"mocha": "^6.2.0",
"mocha-lcov-reporter": "^1.3.0",
Expand Down
145 changes: 117 additions & 28 deletions test/mocker.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const mongoose = require('mongoose');
const { expect } = require('chai');
const get = require('lodash.get');
const { unflatten } = require('flat');
const mocker = require('../');

const { Schema } = mongoose;
Expand Down Expand Up @@ -174,9 +175,9 @@ describe('mocker test', () => {
}
});

describe('static values', () => {
describe('generate(staticFields)', () => {
const embed = new Schema({ name: String });
const stringShema = new Schema({
const thingShema = new Schema({
str: { type: String },
nested: { name: String },
doubleNested: {
Expand Down Expand Up @@ -206,10 +207,8 @@ describe('mocker test', () => {
ofEmbedded: [{ name: 'ofEmbedded' }, { name: 'ofEmbedded' }],
};

const StringThing = mongoose.model('SomeThing', stringShema);

it('should use static value', () => {
const thingMocker = mocker(StringThing);
const thingMocker = mocker(thingShema);
const mock = thingMocker.generate(staticFields);
// expect(mock).to.deep.include(staticFields);
const paths = [
Expand All @@ -226,35 +225,50 @@ describe('mocker test', () => {
expect(get(mock, path)).to.eql(get(staticFields, path));
});
});

});

describe('value overrides via options', () => {
const stringShema = new Schema({ firstName: String, username: String, lastName: String });
const StringThing = mongoose.model('StrThing', stringShema);
describe('options.<propertyName>.value', () => {
describe('value', () => {
it('should use static value - at root', () => {
const userSchema = new Schema({ firstName: String, username: String, lastName: String });
const thingMocker = mocker(userSchema, { firstName: { value: 'blabla' } });
const mock = thingMocker.generate();
expect(mock.firstName).to.eql('blabla');
});

it('should use static value - at root', () => {
const thingMocker = mocker(StringThing, { firstName: { value: 'blabla' } });
const mock = thingMocker.generate();
expect(mock.firstName).to.eql('blabla');
it('should use static value - at leaf', () => {
const theShema = new Schema({ root: { levelOne: { firstName: String, username: String, lastName: String } } });
const thingMocker = mocker(theShema, { 'root.levelOne.firstName': { value: 'blabla' } });
const mock = thingMocker.generate();
expect(mock.root.levelOne.firstName).to.eql('blabla');
});
});

it('should use static value - at leaf', () => {
const theShema = new Schema({ root: { levelOne: { firstName: String, username: String, lastName: String } } });
const thingMocker = mocker(theShema, { 'root.levelOne.firstName': { value: 'blabla' } });
const mock = thingMocker.generate();
expect(mock.root.levelOne.firstName).to.eql('blabla');
describe('value()', () => {
it('at root', () => {
const userSchema = new Schema({ firstName: String, username: String, lastName: String });
const thingMocker = mocker(userSchema, {
firstName: { value: () => 'John' },
username: {
value: (object) => `${object.firstName}.${object.lastName}`
}
});
const mock = thingMocker.generate({ lastName: 'Doe' });
expect(mock.firstName).to.eql('John');
expect(mock.username).to.eql('John.Doe');
});

it.skip('TODO: at leaf');
});
});

it('should use function value - root', () => {
const thingMocker = mocker(stringShema, {
firstName: { value: () => 'John' },
username: {
value: (object) => `${object.firstName}.${object.lastName}`
}
});
const mock = thingMocker.generate({ lastName: 'Doe' });
expect(mock.firstName).to.eql('John');
expect(mock.username).to.eql('John.Doe');
describe('options.<propertyName>.skip', () => {
it('value at root', () => {
const stringShema = new Schema({ firstName: String, username: String, lastName: String });
const thingMocker = mocker(stringShema, { username: { skip: true } });
const mock = thingMocker.generate();
expect(mock).not.to.have.property('username');
});

it('should use function value - nested', () => {
Expand All @@ -271,7 +285,8 @@ describe('mocker test', () => {
});

it('skip value - root', () => {
const thingMocker = mocker(StringThing, { username: { skip: true } });
const theSchema = new Schema({ firstName: String, lastName: String, username: String });
const thingMocker = mocker(theSchema, { username: { skip: true } });
const mock = thingMocker.generate();
expect(mock).not.to.have.property('username');
});
Expand All @@ -286,6 +301,80 @@ describe('mocker test', () => {
expect(mock.user).to.have.property('lastName');
expect(mock.user).not.to.have.property('username');
});

it('values from root level', () => {
const sschema = new Schema({ root: { name: String, nickname: String }, other: { name: String } });
const thingMocker = mocker(sschema, { root: { skip: true } });
const mock = thingMocker.generate();
expect(mock).not.to.have.property('root');
expect(mock).to.have.property('other');
});

describe('value leaf level', () => {
const directOptions = { "root.name": { skip: true } };
it('nested path options', () => {
const sschema = new Schema({ root: { name: String, nickname: String }, other: { name: String } });
const options = unflatten(directOptions);
const thingMocker = mocker(sschema, options);
const mock = thingMocker.generate();
expect(mock).to.have.property('root');
expect(mock.root).to.have.property('nickname');
expect(mock.root).not.to.have.property('name');
});

it('direct path options', () => {
const sschema = new Schema({ root: { name: String, nickname: String }, other: { name: String } });
const options = directOptions;
const thingMocker = mocker(sschema, options);
const mock = thingMocker.generate();
expect(mock).to.have.property('root');
expect(mock.root).to.have.property('nickname');
expect(mock.root).not.to.have.property('name');
});
});

describe('value sub level nested', () => {
const sschema = new Schema({
root: {
levelOne: {
name: String,
nickname: String
},
level1: {
other: {
name: String
}
}
}
});

const directOptions = {
"root.level1": { skip: true },
"root.levelOne.name": { skip: true },
}

it('nested options', () => {
const options = unflatten(directOptions);
const thingMocker = mocker(sschema, options);
const mock = thingMocker.generate();
expect(mock, 'Must have root').to.have.property('root');
expect(mock.root, 'Root must have levelOne').to.have.property('levelOne');
expect(mock.root, 'Root must not have level1').not.to.have.property('level1');
expect(mock.root.levelOne).not.to.have.property('name');
expect(mock.root.levelOne).to.have.property('nickname');
});

it('direct options', () => {
const options = directOptions;
const thingMocker = mocker(sschema, options);
const mock = thingMocker.generate();
expect(mock, 'Must have root').to.have.property('root');
expect(mock.root, 'Root must have levelOne').to.have.property('levelOne');
expect(mock.root, 'Root must not have level1').not.to.have.property('level1');
expect(mock.root.levelOne).not.to.have.property('name');
expect(mock.root.levelOne).to.have.property('nickname');
});
});
});

describe('options', () => {
Expand Down

0 comments on commit 6c6648e

Please sign in to comment.