Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementation of a new feature: support loading of map like objects #395

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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: 1 addition & 1 deletion packages/convict/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ function isObj(o) {
function overlay(from, to, schema) {
Object.keys(from).forEach(function(k) {
// leaf
if (Array.isArray(from[k]) || !isObj(from[k]) || !schema || schema.format === 'object') {
if (Array.isArray(from[k]) || !isObj(from[k]) || !schema || schema.format === 'object' || schema.children != null) {
to[k] = coerce(k, from[k], schema)
} else {
if (!isObj(to[k])) {
Expand Down
58 changes: 58 additions & 0 deletions packages/convict/test/format.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,4 +296,62 @@ describe('convict formats', function() {
})
})

describe('map like object support - must return schema in second argument', function() {
const schema = {
myMap: {
doc: 'this is a key value map, where the value object can be validated by a child schema',
default: {},
format: 'map',
children: {
prop: {
doc: 'a property of the value object',
default: null,
format: String
}
}
}
}

const configWithoutErrors = {
myMap: {
someKey: {prop: 'this belongs to the someKey value object'},
someOtherKey: {prop: 'this belongs to the someOtherKey value object'}
}
}

const configWithErrors = {
myMap: {
someKey: {notDefinedInChildSchema: 'this belongs to the someKey value object'}
}
}

test('must parse a config specification', function() {
convict.addFormat({
name: 'map',
validate: function(theMap, schema) {
if (typeof theMap !== 'object' || theMap == null) {
throw new Error('must be an non-empty (map like) object')
}
// iterate each key in the map
for (const key of Object.keys(theMap)) {
// perform validation on the key's value against the child schema
convict(schema.children).load(theMap[key]).validate()
}
}
})
})

test('must validate children (map) value without throwing an Error', function() {
expect(function() {
convict(schema).load(configWithoutErrors).validate()
}).not.toThrow()
})

test('fails to validate incorrect children (map) values', function() {
expect(function() {
convict(schema).load(configWithErrors).validate()
}).toThrow('myMap: prop: must be of type String: value was {"someKey":{"notDefinedInChildSchema":"this belongs to the someKey value object"}}')
})
})

})