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')
							 | 
						||
| 
								 | 
							
								  })
							 | 
						||
| 
								 | 
							
								})
							 |