mirror of
https://github.com/jambonz/jambonz-node.git
synced 2025-12-19 05:17:49 +00:00
add support for env schema, allowing users to provide environment variables for an application
This commit is contained in:
5
test/data/invalid/missing-description.json
Normal file
5
test/data/invalid/missing-description.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"text": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
12
test/data/invalid/mixed.json
Normal file
12
test/data/invalid/mixed.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"text": {
|
||||
"type": "string"
|
||||
},
|
||||
"/hello": {
|
||||
"text": {
|
||||
"description": "Welcome message",
|
||||
"type": "invalid_type",
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
}
|
||||
5
test/data/invalid/non-slash.json
Normal file
5
test/data/invalid/non-slash.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"text": {
|
||||
"type": "invalid_type"
|
||||
}
|
||||
}
|
||||
9
test/data/invalid/slash.json
Normal file
9
test/data/invalid/slash.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"/hello": {
|
||||
"text": {
|
||||
"description": "Welcome message",
|
||||
"type": "invalid_type",
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
}
|
||||
13
test/data/valid/mixed.json
Normal file
13
test/data/valid/mixed.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"text": {
|
||||
"description": "Default text property",
|
||||
"type": "string"
|
||||
},
|
||||
"/hello": {
|
||||
"text": {
|
||||
"description": "Welcome message",
|
||||
"type": "string",
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
}
|
||||
12
test/data/valid/non-slash.json
Normal file
12
test/data/valid/non-slash.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"text": {
|
||||
"description": "Welcome message",
|
||||
"type": "string",
|
||||
"required": true
|
||||
},
|
||||
"timeout": {
|
||||
"description": "Timeout in seconds",
|
||||
"type": "number",
|
||||
"default": 30
|
||||
}
|
||||
}
|
||||
16
test/data/valid/obscure.json
Normal file
16
test/data/valid/obscure.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"apiKey": {
|
||||
"description": "API key for the service",
|
||||
"type": "string",
|
||||
"required": true,
|
||||
"obscure": true,
|
||||
"value": "secret123"
|
||||
},
|
||||
"/hello": {
|
||||
"text": {
|
||||
"description": "Welcome message",
|
||||
"type": "string",
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
}
|
||||
9
test/data/valid/slash.json
Normal file
9
test/data/valid/slash.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"/hello": {
|
||||
"text": {
|
||||
"description": "Welcome message",
|
||||
"type": "string",
|
||||
"required": true
|
||||
}
|
||||
}
|
||||
}
|
||||
110
test/getAppConfig.js
Normal file
110
test/getAppConfig.js
Normal file
@@ -0,0 +1,110 @@
|
||||
const test = require('tape');
|
||||
const path = require('path');
|
||||
const { getAppConfig } = require('../lib/validator');
|
||||
|
||||
test('getAppConfig tests', (t) => {
|
||||
// Test case 1: Missing appJsonPath
|
||||
t.test('should return error when appJsonPath is missing', (st) => {
|
||||
const result = getAppConfig({ urlPath: '/test' });
|
||||
st.equal(result.success, false, 'should not be successful');
|
||||
st.equal(result.error, 'appJsonPath is required', 'should return correct error message');
|
||||
st.end();
|
||||
});
|
||||
|
||||
// Test case 2: Non-existent app.json file
|
||||
t.test('should return error when app.json does not exist', (st) => {
|
||||
const result = getAppConfig({
|
||||
urlPath: '/test',
|
||||
appJsonPath: path.join(__dirname, 'data/nonexistent.json')
|
||||
});
|
||||
st.equal(result.success, false, 'should not be successful');
|
||||
st.ok(result.error.includes('app.json file not found'), 'should return file not found error');
|
||||
st.end();
|
||||
});
|
||||
|
||||
// Test case 3: Valid app.json with regular properties
|
||||
t.test('should return regular properties when no path match', (st) => {
|
||||
const result = getAppConfig({
|
||||
urlPath: '/nonexistent',
|
||||
appJsonPath: path.join(__dirname, 'data/valid/non-slash.json')
|
||||
});
|
||||
st.equal(result.success, true, 'should be successful');
|
||||
st.deepEqual(result.config, {
|
||||
text: {
|
||||
description: 'Welcome message',
|
||||
type: 'string',
|
||||
required: true
|
||||
}
|
||||
}, 'should return correct regular properties');
|
||||
st.end();
|
||||
});
|
||||
|
||||
// Test case 4: Valid app.json with path-specific properties
|
||||
t.test('should return path-specific properties when path matches', (st) => {
|
||||
const result = getAppConfig({
|
||||
urlPath: '/hello',
|
||||
appJsonPath: path.join(__dirname, 'data/valid/slash.json')
|
||||
});
|
||||
st.equal(result.success, true, 'should be successful');
|
||||
st.deepEqual(result.config, {
|
||||
'/hello': {
|
||||
text: {
|
||||
description: 'Welcome message',
|
||||
type: 'string',
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}, 'should return correct path-specific properties');
|
||||
st.end();
|
||||
});
|
||||
|
||||
// Test case 5: Valid app.json with mixed properties
|
||||
t.test('should merge regular and path-specific properties', (st) => {
|
||||
const result = getAppConfig({
|
||||
urlPath: '/hello',
|
||||
appJsonPath: path.join(__dirname, 'data/valid/mixed.json')
|
||||
});
|
||||
st.equal(result.success, true, 'should be successful');
|
||||
st.deepEqual(result.config, {
|
||||
text: {
|
||||
type: 'string'
|
||||
},
|
||||
'/hello': {
|
||||
text: {
|
||||
description: 'Welcome message',
|
||||
type: 'string',
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}, 'should return merged properties');
|
||||
st.end();
|
||||
});
|
||||
|
||||
// Test case 6: Obscure property handling
|
||||
t.test('should obscure values when obscure flag is true', (st) => {
|
||||
const result = getAppConfig({
|
||||
urlPath: '/hello',
|
||||
appJsonPath: path.join(__dirname, 'data/valid/obscure.json')
|
||||
});
|
||||
st.equal(result.success, true, 'should be successful');
|
||||
st.deepEqual(result.config, {
|
||||
apiKey: {
|
||||
description: 'API key for the service',
|
||||
type: 'string',
|
||||
required: true,
|
||||
obscure: true,
|
||||
value: '********'
|
||||
},
|
||||
'/hello': {
|
||||
text: {
|
||||
description: 'Welcome message',
|
||||
type: 'string',
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}, 'should obscure sensitive values');
|
||||
st.end();
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
@@ -45,6 +45,8 @@ test('unit tests', (t) => {
|
||||
t.end();
|
||||
});
|
||||
|
||||
// Run validator tests
|
||||
require('./validator');
|
||||
|
||||
const errInvalidInstruction = () => makeTask(logger, require('./data/bad/unknown-instruction'));
|
||||
const errUnknownProperty = () => makeTask(logger, require('./data/bad/unknown-property'));
|
||||
|
||||
64
test/validator.js
Normal file
64
test/validator.js
Normal file
@@ -0,0 +1,64 @@
|
||||
const test = require('tape');
|
||||
const { validateAppConfig } = require('../lib/validator');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Load test data
|
||||
const loadTestData = (category, name) => {
|
||||
const filePath = path.join(__dirname, 'data', category, `${name}.json`);
|
||||
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
||||
};
|
||||
|
||||
test('App Config Validator', (t) => {
|
||||
t.test('Valid Cases', (t) => {
|
||||
// Test valid non-slash properties
|
||||
const validNonSlash = loadTestData('valid', 'non-slash');
|
||||
let result = validateAppConfig(validNonSlash);
|
||||
t.ok(result.isValid, 'valid non-slash properties pass validation');
|
||||
t.equal(result.errors.length, 0, 'no errors for valid non-slash properties');
|
||||
|
||||
// Test valid slash properties
|
||||
const validSlash = loadTestData('valid', 'slash');
|
||||
result = validateAppConfig(validSlash);
|
||||
t.ok(result.isValid, 'valid slash properties pass validation');
|
||||
t.equal(result.errors.length, 0, 'no errors for valid slash properties');
|
||||
|
||||
// Test valid mixed properties
|
||||
const validMixed = loadTestData('valid', 'mixed');
|
||||
result = validateAppConfig(validMixed);
|
||||
t.ok(result.isValid, 'valid mixed properties pass validation');
|
||||
t.equal(result.errors.length, 0, 'no errors for valid mixed properties');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.test('Invalid Cases', (t) => {
|
||||
// Test invalid non-slash properties
|
||||
const invalidNonSlash = loadTestData('invalid', 'non-slash');
|
||||
let result = validateAppConfig(invalidNonSlash);
|
||||
t.notOk(result.isValid, 'invalid non-slash properties fail validation');
|
||||
t.ok(result.errors.length > 0, 'errors reported for invalid non-slash properties');
|
||||
|
||||
// Test invalid slash properties
|
||||
const invalidSlash = loadTestData('invalid', 'slash');
|
||||
result = validateAppConfig(invalidSlash);
|
||||
t.notOk(result.isValid, 'invalid slash properties fail validation');
|
||||
t.ok(result.errors.length > 0, 'errors reported for invalid slash properties');
|
||||
|
||||
// Test invalid mixed properties
|
||||
const invalidMixed = loadTestData('invalid', 'mixed');
|
||||
result = validateAppConfig(invalidMixed);
|
||||
t.notOk(result.isValid, 'invalid mixed properties fail validation');
|
||||
t.ok(result.errors.length > 0, 'errors reported for invalid mixed properties');
|
||||
|
||||
// Test missing description
|
||||
const missingDescription = loadTestData('invalid', 'missing-description');
|
||||
result = validateAppConfig(missingDescription);
|
||||
t.notOk(result.isValid, 'properties without description fail validation');
|
||||
t.ok(result.errors.some(err => err.includes('description')), 'error message mentions missing description');
|
||||
|
||||
t.end();
|
||||
});
|
||||
|
||||
t.end();
|
||||
});
|
||||
Reference in New Issue
Block a user