fix: Deprecation warning logged at server launch for nested Parse Server option even if option is explicitly set (#9934)
This commit is contained in:
@@ -45,4 +45,29 @@ describe('Deprecator', () => {
|
||||
`DeprecationWarning: ${options.usage} is deprecated and will be removed in a future version. ${options.solution}`
|
||||
);
|
||||
});
|
||||
|
||||
it('logs deprecation for nested option key with dot notation', async () => {
|
||||
deprecations = [{ optionKey: 'databaseOptions.allowPublicExplain', changeNewDefault: 'false' }];
|
||||
|
||||
spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations);
|
||||
const logger = require('../lib/logger').logger;
|
||||
const logSpy = spyOn(logger, 'warn').and.callFake(() => {});
|
||||
|
||||
await reconfigureServer();
|
||||
expect(logSpy.calls.all()[0].args[0]).toEqual(
|
||||
`DeprecationWarning: The Parse Server option '${deprecations[0].optionKey}' default will change to '${deprecations[0].changeNewDefault}' in a future version.`
|
||||
);
|
||||
});
|
||||
|
||||
it('does not log deprecation for nested option key if option is set manually', async () => {
|
||||
deprecations = [{ optionKey: 'databaseOptions.allowPublicExplain', changeNewDefault: 'false' }];
|
||||
|
||||
spyOn(Deprecator, '_getDeprecations').and.callFake(() => deprecations);
|
||||
const logSpy = spyOn(Deprecator, '_logOption').and.callFake(() => {});
|
||||
const Config = require('../lib/Config');
|
||||
const config = Config.get('test');
|
||||
// Directly test scanParseServerOptions with nested option set
|
||||
Deprecator.scanParseServerOptions({ databaseOptions: { allowPublicExplain: true } });
|
||||
expect(logSpy).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -122,4 +122,55 @@ describe('Utils', () => {
|
||||
expect(result).toBe('{"name":"test","number":42,"nested":{"key":"value"}}');
|
||||
});
|
||||
});
|
||||
|
||||
describe('getNestedProperty', () => {
|
||||
it('should get top-level property', () => {
|
||||
const obj = { foo: 'bar' };
|
||||
expect(Utils.getNestedProperty(obj, 'foo')).toBe('bar');
|
||||
});
|
||||
|
||||
it('should get nested property with dot notation', () => {
|
||||
const obj = { database: { options: { enabled: true } } };
|
||||
expect(Utils.getNestedProperty(obj, 'database.options.enabled')).toBe(true);
|
||||
});
|
||||
|
||||
it('should return undefined for non-existent property', () => {
|
||||
const obj = { foo: 'bar' };
|
||||
expect(Utils.getNestedProperty(obj, 'baz')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return undefined for non-existent nested property', () => {
|
||||
const obj = { database: { options: {} } };
|
||||
expect(Utils.getNestedProperty(obj, 'database.options.enabled')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return undefined when path traverses non-object', () => {
|
||||
const obj = { database: 'string' };
|
||||
expect(Utils.getNestedProperty(obj, 'database.options.enabled')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return undefined for null object', () => {
|
||||
expect(Utils.getNestedProperty(null, 'foo')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return undefined for empty path', () => {
|
||||
const obj = { foo: 'bar' };
|
||||
expect(Utils.getNestedProperty(obj, '')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should handle value of 0', () => {
|
||||
const obj = { database: { timeout: 0 } };
|
||||
expect(Utils.getNestedProperty(obj, 'database.timeout')).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle value of false', () => {
|
||||
const obj = { database: { enabled: false } };
|
||||
expect(Utils.getNestedProperty(obj, 'database.enabled')).toBe(false);
|
||||
});
|
||||
|
||||
it('should handle value of empty string', () => {
|
||||
const obj = { database: { name: '' } };
|
||||
expect(Utils.getNestedProperty(obj, 'database.name')).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import logger from '../logger';
|
||||
import Deprecations from './Deprecations';
|
||||
import Utils from '../Utils';
|
||||
|
||||
/**
|
||||
* The deprecator class.
|
||||
@@ -21,7 +22,7 @@ class Deprecator {
|
||||
const changeNewDefault = deprecation.changeNewDefault;
|
||||
|
||||
// If default will change, only throw a warning if option is not set
|
||||
if (changeNewDefault != null && options[optionKey] == null) {
|
||||
if (changeNewDefault != null && Utils.getNestedProperty(options, optionKey) == null) {
|
||||
Deprecator._logOption({ optionKey, changeNewDefault, solution });
|
||||
}
|
||||
}
|
||||
|
||||
25
src/Utils.js
25
src/Utils.js
@@ -444,6 +444,31 @@ class Utils {
|
||||
return value;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a nested property value from an object using dot notation.
|
||||
* @param {Object} obj The object to get the property from.
|
||||
* @param {String} path The property path in dot notation, e.g. 'databaseOptions.allowPublicExplain'.
|
||||
* @returns {any} The property value or undefined if not found.
|
||||
* @example
|
||||
* const obj = { database: { options: { enabled: true } } };
|
||||
* Utils.getNestedProperty(obj, 'database.options.enabled');
|
||||
* // Output: true
|
||||
*/
|
||||
static getNestedProperty(obj, path) {
|
||||
if (!obj || !path) {
|
||||
return undefined;
|
||||
}
|
||||
const keys = path.split('.');
|
||||
let current = obj;
|
||||
for (const key of keys) {
|
||||
if (current == null || typeof current !== 'object') {
|
||||
return undefined;
|
||||
}
|
||||
current = current[key];
|
||||
}
|
||||
return current;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Utils;
|
||||
|
||||
Reference in New Issue
Block a user