fix(AppData/Conversion): Improve boolean conversion and mapping evaluation in AppData, ensuring falsy values (like false, 0, and empty strings) are correctly handled and logged. Also, reduce test timeout and add local permissions settings for development.

This commit is contained in:
2025-08-15 18:14:57 +00:00
parent b0df896a14
commit 5f1090dd62
5 changed files with 232 additions and 12 deletions

139
test/test.boolean-false.ts Normal file
View File

@@ -0,0 +1,139 @@
import { expect, tap } from '@git.zone/tstest/tapbundle';
import * as npmextra from '../ts/index.js';
// Test environment variable with boolean false value
tap.test('should handle boolean false values in nested objects correctly', async () => {
// Set up test environment variable
process.env['S3_USESSL'] = 'false';
process.env['S3_ENDPOINT'] = 'https://s3.example.com';
process.env['S3_REGION'] = 'us-east-1';
process.env['S3_ACCESSKEY'] = 'test-key';
process.env['S3_ACCESSSECRET'] = 'test-secret';
// Create AppData with nested object structure similar to CloudlyConfig
const appData = await npmextra.AppData.createAndInit({
ephemeral: true, // Use in-memory storage for testing
envMapping: {
s3Descriptor: {
endpoint: 'S3_ENDPOINT',
region: 'S3_REGION',
accessKey: 'S3_ACCESSKEY',
accessSecret: 'S3_ACCESSSECRET',
useSsl: 'boolean:S3_USESSL'
}
}
});
// Get the kvStore and read the configuration
const kvStore = await appData.getKvStore();
const s3Descriptor = await kvStore.readKey('s3Descriptor');
console.log('\n=== Test Results ===');
console.log('S3 Descriptor:', JSON.stringify(s3Descriptor, null, 2));
console.log('useSsl value:', s3Descriptor?.useSsl);
console.log('useSsl type:', typeof s3Descriptor?.useSsl);
console.log('useSsl === false:', (s3Descriptor?.useSsl as any) === false);
// Verify the values
expect(s3Descriptor).toBeTruthy();
expect(s3Descriptor.endpoint).toEqual('https://s3.example.com');
expect(s3Descriptor.region).toEqual('us-east-1');
expect(s3Descriptor.accessKey).toEqual('test-key');
expect(s3Descriptor.accessSecret).toEqual('test-secret');
// Critical test: useSsl should be false, not undefined
expect(s3Descriptor.useSsl).toEqual(false);
expect(typeof s3Descriptor.useSsl).toEqual('boolean');
expect(s3Descriptor.useSsl).not.toBeUndefined();
});
tap.test('should handle various boolean representations correctly', async () => {
// Test different boolean representations
const testCases = [
{ env: 'false', expected: false },
{ env: 'FALSE', expected: false },
{ env: '0', expected: false },
{ env: 'no', expected: false },
{ env: 'NO', expected: false },
{ env: 'n', expected: false },
{ env: 'off', expected: false },
{ env: 'true', expected: true },
{ env: 'TRUE', expected: true },
{ env: '1', expected: true },
{ env: 'yes', expected: true },
{ env: 'YES', expected: true },
{ env: 'y', expected: true },
{ env: 'on', expected: true },
];
for (const testCase of testCases) {
process.env['TEST_BOOL'] = testCase.env;
const appData = await npmextra.AppData.createAndInit({
ephemeral: true,
envMapping: {
testBool: 'boolean:TEST_BOOL'
}
});
const kvStore = await appData.getKvStore();
const testBool = await kvStore.readKey('testBool');
console.log(`Input "${testCase.env}" => ${testBool} (expected: ${testCase.expected})`);
expect(testBool).toEqual(testCase.expected);
}
});
tap.test('should handle hardcoded boolean false values', async () => {
// Test with hardcoded boolean false value
const appData = await npmextra.AppData.createAndInit({
ephemeral: true,
envMapping: {
boolValue: 'hard_boolean:false'
}
});
const kvStore = await appData.getKvStore();
const boolValue = await kvStore.readKey('boolValue');
console.log('\n=== Hardcoded Boolean Test ===');
console.log('boolValue:', boolValue);
console.log('type:', typeof boolValue);
console.log('is false:', (boolValue as any) === false);
expect(boolValue).toEqual(false);
expect(typeof boolValue).toEqual('boolean');
});
tap.test('should not filter out other falsy values', async () => {
process.env['ZERO_VALUE'] = '0';
process.env['EMPTY_STRING'] = ''; // This should be preserved as empty string
const appData = await npmextra.AppData.createAndInit({
ephemeral: true,
envMapping: {
nested: {
zeroAsNumber: 'ZERO_VALUE', // Should preserve "0" as string
zeroAsBoolean: 'boolean:ZERO_VALUE', // Should convert to false
emptyString: 'EMPTY_STRING', // Should preserve empty string
hardcodedFalse: 'hard_boolean:false', // Should be false
hardcodedZero: 'hard:0', // Should be "0" string
}
}
});
const kvStore = await appData.getKvStore();
const nested = await kvStore.readKey('nested');
console.log('\n=== Falsy Values Test ===');
console.log('nested:', JSON.stringify(nested, null, 2));
expect(nested).toBeTruthy();
expect(nested.zeroAsNumber).toEqual('0');
expect(nested.zeroAsBoolean).toEqual(false);
expect(nested.emptyString).toEqual('');
expect(nested.hardcodedFalse).toEqual(false);
expect(nested.hardcodedZero).toEqual('0');
});
export default tap.start();