You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					347 lines
				
				6.6 KiB
			
		
		
			
		
	
	
					347 lines
				
				6.6 KiB
			| 
											3 years ago
										 | 'use strict' | ||
|  | 
 | ||
|  | const t = require('tap') | ||
|  | const Ajv = require('ajv') | ||
|  | const makeTest = require('./make-test') | ||
|  | const { join } = require('path') | ||
|  | 
 | ||
|  | process.env.VALUE_FROM_ENV = 'pippo' | ||
|  | 
 | ||
|  | const tests = [ | ||
|  |   { | ||
|  |     name: 'empty ok', | ||
|  |     schema: { type: 'object' }, | ||
|  |     data: { }, | ||
|  |     isOk: true, | ||
|  |     confExpected: {} | ||
|  |   }, | ||
|  |   { | ||
|  |     name: 'simple object - ok', | ||
|  |     schema: { | ||
|  |       type: 'object', | ||
|  |       properties: { | ||
|  |         PORT: { | ||
|  |           type: 'string' | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  |     data: { | ||
|  |       PORT: '44' | ||
|  |     }, | ||
|  |     isOk: true, | ||
|  |     confExpected: { | ||
|  |       PORT: '44' | ||
|  |     } | ||
|  |   }, | ||
|  |   { | ||
|  |     name: 'simple object - ok - coerce value', | ||
|  |     schema: { | ||
|  |       type: 'object', | ||
|  |       properties: { | ||
|  |         PORT: { | ||
|  |           type: 'integer' | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  |     data: { | ||
|  |       PORT: '44' | ||
|  |     }, | ||
|  |     isOk: true, | ||
|  |     confExpected: { | ||
|  |       PORT: 44 | ||
|  |     } | ||
|  |   }, | ||
|  |   { | ||
|  |     name: 'simple object - ok - remove additional properties', | ||
|  |     schema: { | ||
|  |       type: 'object', | ||
|  |       properties: { | ||
|  |         PORT: { | ||
|  |           type: 'integer' | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  |     data: { | ||
|  |       PORT: '44', | ||
|  |       ANOTHER_PORT: '55' | ||
|  |     }, | ||
|  |     isOk: true, | ||
|  |     confExpected: { | ||
|  |       PORT: 44 | ||
|  |     } | ||
|  |   }, | ||
|  |   { | ||
|  |     name: 'simple object - ok - use default', | ||
|  |     schema: { | ||
|  |       type: 'object', | ||
|  |       properties: { | ||
|  |         PORT: { | ||
|  |           type: 'integer', | ||
|  |           default: 5555 | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  |     data: { }, | ||
|  |     isOk: true, | ||
|  |     confExpected: { | ||
|  |       PORT: 5555 | ||
|  |     } | ||
|  |   }, | ||
|  |   { | ||
|  |     name: 'simple object - ok - required + default', | ||
|  |     schema: { | ||
|  |       type: 'object', | ||
|  |       required: ['PORT'], | ||
|  |       properties: { | ||
|  |         PORT: { | ||
|  |           type: 'integer', | ||
|  |           default: 6666 | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  |     data: { }, | ||
|  |     isOk: true, | ||
|  |     confExpected: { | ||
|  |       PORT: 6666 | ||
|  |     } | ||
|  |   }, | ||
|  |   { | ||
|  |     name: 'simple object - ok - allow array', | ||
|  |     schema: { | ||
|  |       type: 'object', | ||
|  |       required: ['PORT'], | ||
|  |       properties: { | ||
|  |         PORT: { | ||
|  |           type: 'integer', | ||
|  |           default: 6666 | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  |     data: [{ }], | ||
|  |     isOk: true, | ||
|  |     confExpected: { | ||
|  |       PORT: 6666 | ||
|  |     } | ||
|  |   }, | ||
|  |   { | ||
|  |     name: 'simple object - ok - merge multiple object + env', | ||
|  |     schema: { | ||
|  |       type: 'object', | ||
|  |       required: ['PORT', 'MONGODB_URL'], | ||
|  |       properties: { | ||
|  |         PORT: { | ||
|  |           type: 'integer', | ||
|  |           default: 6666 | ||
|  |         }, | ||
|  |         MONGODB_URL: { | ||
|  |           type: 'string' | ||
|  |         }, | ||
|  |         VALUE_FROM_ENV: { | ||
|  |           type: 'string' | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  |     data: [{ PORT: 3333 }, { MONGODB_URL: 'mongodb://localhost/pippo' }], | ||
|  |     isOk: true, | ||
|  |     confExpected: { | ||
|  |       PORT: 3333, | ||
|  |       MONGODB_URL: 'mongodb://localhost/pippo', | ||
|  |       VALUE_FROM_ENV: 'pippo' | ||
|  |     } | ||
|  |   }, | ||
|  |   { | ||
|  |     name: 'simple object - ok - load only from env', | ||
|  |     schema: { | ||
|  |       type: 'object', | ||
|  |       required: ['VALUE_FROM_ENV'], | ||
|  |       properties: { | ||
|  |         VALUE_FROM_ENV: { | ||
|  |           type: 'string' | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  |     data: undefined, | ||
|  |     isOk: true, | ||
|  |     confExpected: { | ||
|  |       VALUE_FROM_ENV: 'pippo' | ||
|  |     } | ||
|  |   }, | ||
|  |   { | ||
|  |     name: 'simple object - ok - opts override environment', | ||
|  |     schema: { | ||
|  |       type: 'object', | ||
|  |       required: ['VALUE_FROM_ENV'], | ||
|  |       properties: { | ||
|  |         VALUE_FROM_ENV: { | ||
|  |           type: 'string' | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  |     data: { VALUE_FROM_ENV: 'pluto' }, | ||
|  |     isOk: true, | ||
|  |     confExpected: { | ||
|  |       VALUE_FROM_ENV: 'pluto' | ||
|  |     } | ||
|  |   }, | ||
|  |   { | ||
|  |     name: 'simple object - ok - load only from .env', | ||
|  |     schema: { | ||
|  |       type: 'object', | ||
|  |       required: ['VALUE_FROM_DOTENV'], | ||
|  |       properties: { | ||
|  |         VALUE_FROM_DOTENV: { | ||
|  |           type: 'string' | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  |     data: undefined, | ||
|  |     isOk: true, | ||
|  |     dotenv: { path: join(__dirname, '.env') }, | ||
|  |     confExpected: { | ||
|  |       VALUE_FROM_DOTENV: 'look ma' | ||
|  |     } | ||
|  |   }, | ||
|  |   { | ||
|  |     name: 'simple object - KO', | ||
|  |     schema: { | ||
|  |       type: 'object', | ||
|  |       required: ['PORT'], | ||
|  |       properties: { | ||
|  |         PORT: { | ||
|  |           type: 'integer' | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  |     data: { }, | ||
|  |     isOk: false, | ||
|  |     errorMessage: 'env must have required property \'PORT\'' | ||
|  |   }, | ||
|  |   { | ||
|  |     name: 'simple object - invalid data', | ||
|  |     schema: { | ||
|  |       type: 'object', | ||
|  |       required: ['PORT'], | ||
|  |       properties: { | ||
|  |         PORT: { | ||
|  |           type: 'integer' | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  |     data: [], | ||
|  |     isOk: false, | ||
|  |     errorMessage: 'opts/data must NOT have fewer than 1 items, opts/data must be object, opts/data must match exactly one schema in oneOf' | ||
|  |   } | ||
|  | ] | ||
|  | 
 | ||
|  | const ajv = new Ajv({ | ||
|  |   allErrors: true, | ||
|  |   removeAdditional: true, | ||
|  |   useDefaults: true, | ||
|  |   coerceTypes: true, | ||
|  |   allowUnionTypes: true | ||
|  | }) | ||
|  | 
 | ||
|  | tests.forEach(function (testConf) { | ||
|  |   t.test(testConf.name, t => { | ||
|  |     const options = { | ||
|  |       schema: testConf.schema, | ||
|  |       data: testConf.data, | ||
|  |       dotenv: testConf.dotenv, | ||
|  |       dotenvConfig: testConf.dotenvConfig, | ||
|  |       ajv | ||
|  |     } | ||
|  | 
 | ||
|  |     makeTest(t, options, testConf.isOk, testConf.confExpected, testConf.errorMessage) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | const noCoercionTest = { | ||
|  |   name: 'simple object - not ok - should NOT coerce value', | ||
|  |   schema: { | ||
|  |     type: 'object', | ||
|  |     properties: { | ||
|  |       PORT: { | ||
|  |         type: 'integer' | ||
|  |       } | ||
|  |     } | ||
|  |   }, | ||
|  |   data: { | ||
|  |     PORT: '44' | ||
|  |   }, | ||
|  |   isOk: false, | ||
|  |   errorMessage: 'env/PORT must be integer', | ||
|  |   confExpected: { | ||
|  |     PORT: 44 | ||
|  |   } | ||
|  | } | ||
|  | 
 | ||
|  | const strictValidator = new Ajv({ | ||
|  |   allErrors: true, | ||
|  |   removeAdditional: true, | ||
|  |   useDefaults: true, | ||
|  |   coerceTypes: false, | ||
|  |   allowUnionTypes: true | ||
|  | }); | ||
|  | 
 | ||
|  | [noCoercionTest].forEach(function (testConf) { | ||
|  |   t.test(testConf.name, t => { | ||
|  |     const options = { | ||
|  |       schema: testConf.schema, | ||
|  |       data: testConf.data, | ||
|  |       dotenv: testConf.dotenv, | ||
|  |       dotenvConfig: testConf.dotenvConfig, | ||
|  |       ajv: strictValidator | ||
|  |     } | ||
|  | 
 | ||
|  |     makeTest(t, options, testConf.isOk, testConf.confExpected, testConf.errorMessage) | ||
|  |   }) | ||
|  | }) | ||
|  | 
 | ||
|  | t.test('ajv enhancement', t => { | ||
|  |   t.plan(2) | ||
|  |   const testCase = { | ||
|  |     schema: { | ||
|  |       type: 'object', | ||
|  |       required: ['MONGODB_URL'], | ||
|  |       properties: { | ||
|  |         MONGODB_URL: { | ||
|  |           type: 'string', | ||
|  |           format: 'uri' | ||
|  |         } | ||
|  |       } | ||
|  |     }, | ||
|  |     data: [{ PORT: 3333 }, { MONGODB_URL: 'mongodb://localhost/pippo' }], | ||
|  |     isOk: true, | ||
|  |     confExpected: { | ||
|  |       MONGODB_URL: 'mongodb://localhost/pippo' | ||
|  |     } | ||
|  |   } | ||
|  | 
 | ||
|  |   t.test('return', t => { | ||
|  |     const options = { | ||
|  |       schema: testCase.schema, | ||
|  |       data: testCase.data, | ||
|  |       ajv: { | ||
|  |         customOptions (ajvInstance) { | ||
|  |           require('ajv-formats')(ajvInstance) | ||
|  |           return ajvInstance | ||
|  |         } | ||
|  |       } | ||
|  |     } | ||
|  |     makeTest(t, options, testCase.isOk, testCase.confExpected) | ||
|  |   }) | ||
|  | 
 | ||
|  |   t.test('no return', t => { | ||
|  |     const options = { | ||
|  |       schema: testCase.schema, | ||
|  |       data: testCase.data, | ||
|  |       ajv: { | ||
|  |         customOptions (ajvInstance) { | ||
|  |           // do nothing
 | ||
|  |         } | ||
|  |       } | ||
|  |     } | ||
|  |     makeTest(t, options, false, undefined, 'customOptions function must return an instance of Ajv') | ||
|  |   }) | ||
|  | }) |