summaryrefslogtreecommitdiff
path: root/packages/cli/src/config/settings.test.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/cli/src/config/settings.test.ts')
-rw-r--r--packages/cli/src/config/settings.test.ts160
1 files changed, 160 insertions, 0 deletions
diff --git a/packages/cli/src/config/settings.test.ts b/packages/cli/src/config/settings.test.ts
index c6943dbe..350c5d33 100644
--- a/packages/cli/src/config/settings.test.ts
+++ b/packages/cli/src/config/settings.test.ts
@@ -322,6 +322,166 @@ describe('Settings Loading and Merging', () => {
consoleErrorSpy.mockRestore();
});
+
+ it('should resolve environment variables in user settings', () => {
+ process.env.TEST_API_KEY = 'user_api_key_from_env';
+ const userSettingsContent = {
+ apiKey: '$TEST_API_KEY',
+ someUrl: 'https://test.com/${TEST_API_KEY}',
+ };
+ (mockFsExistsSync as Mock).mockImplementation(
+ (p: fs.PathLike) => p === USER_SETTINGS_PATH,
+ );
+ (fs.readFileSync as Mock).mockImplementation(
+ (p: fs.PathOrFileDescriptor) => {
+ if (p === USER_SETTINGS_PATH)
+ return JSON.stringify(userSettingsContent);
+ return '{}';
+ },
+ );
+
+ const settings = loadSettings(MOCK_WORKSPACE_DIR);
+ expect(settings.user.settings.apiKey).toBe('user_api_key_from_env');
+ expect(settings.user.settings.someUrl).toBe(
+ 'https://test.com/user_api_key_from_env',
+ );
+ expect(settings.merged.apiKey).toBe('user_api_key_from_env');
+ delete process.env.TEST_API_KEY;
+ });
+
+ it('should resolve environment variables in workspace settings', () => {
+ process.env.WORKSPACE_ENDPOINT = 'workspace_endpoint_from_env';
+ const workspaceSettingsContent = {
+ endpoint: '${WORKSPACE_ENDPOINT}/api',
+ nested: { value: '$WORKSPACE_ENDPOINT' },
+ };
+ (mockFsExistsSync as Mock).mockImplementation(
+ (p: fs.PathLike) => p === MOCK_WORKSPACE_SETTINGS_PATH,
+ );
+ (fs.readFileSync as Mock).mockImplementation(
+ (p: fs.PathOrFileDescriptor) => {
+ if (p === MOCK_WORKSPACE_SETTINGS_PATH)
+ return JSON.stringify(workspaceSettingsContent);
+ return '{}';
+ },
+ );
+
+ const settings = loadSettings(MOCK_WORKSPACE_DIR);
+ expect(settings.workspace.settings.endpoint).toBe(
+ 'workspace_endpoint_from_env/api',
+ );
+ expect(settings.workspace.settings.nested.value).toBe(
+ 'workspace_endpoint_from_env',
+ );
+ expect(settings.merged.endpoint).toBe('workspace_endpoint_from_env/api');
+ delete process.env.WORKSPACE_ENDPOINT;
+ });
+
+ it('should prioritize workspace env variables over user env variables if keys clash after resolution', () => {
+ const userSettingsContent = { configValue: '$SHARED_VAR' };
+ const workspaceSettingsContent = { configValue: '$SHARED_VAR' };
+
+ (mockFsExistsSync as Mock).mockReturnValue(true);
+ const originalSharedVar = process.env.SHARED_VAR;
+ // Temporarily delete to ensure a clean slate for the test's specific manipulations
+ delete process.env.SHARED_VAR;
+
+ (fs.readFileSync as Mock).mockImplementation(
+ (p: fs.PathOrFileDescriptor) => {
+ if (p === USER_SETTINGS_PATH) {
+ process.env.SHARED_VAR = 'user_value_for_user_read'; // Set for user settings read
+ return JSON.stringify(userSettingsContent);
+ }
+ if (p === MOCK_WORKSPACE_SETTINGS_PATH) {
+ process.env.SHARED_VAR = 'workspace_value_for_workspace_read'; // Set for workspace settings read
+ return JSON.stringify(workspaceSettingsContent);
+ }
+ return '{}';
+ },
+ );
+
+ const settings = loadSettings(MOCK_WORKSPACE_DIR);
+
+ expect(settings.user.settings.configValue).toBe(
+ 'user_value_for_user_read',
+ );
+ expect(settings.workspace.settings.configValue).toBe(
+ 'workspace_value_for_workspace_read',
+ );
+ // Merged should take workspace's resolved value
+ expect(settings.merged.configValue).toBe(
+ 'workspace_value_for_workspace_read',
+ );
+
+ // Restore original environment variable state
+ if (originalSharedVar !== undefined) {
+ process.env.SHARED_VAR = originalSharedVar;
+ } else {
+ delete process.env.SHARED_VAR; // Ensure it's deleted if it wasn't there before
+ }
+ });
+
+ it('should leave unresolved environment variables as is', () => {
+ const userSettingsContent = { apiKey: '$UNDEFINED_VAR' };
+ (mockFsExistsSync as Mock).mockImplementation(
+ (p: fs.PathLike) => p === USER_SETTINGS_PATH,
+ );
+ (fs.readFileSync as Mock).mockImplementation(
+ (p: fs.PathOrFileDescriptor) => {
+ if (p === USER_SETTINGS_PATH)
+ return JSON.stringify(userSettingsContent);
+ return '{}';
+ },
+ );
+
+ const settings = loadSettings(MOCK_WORKSPACE_DIR);
+ expect(settings.user.settings.apiKey).toBe('$UNDEFINED_VAR');
+ expect(settings.merged.apiKey).toBe('$UNDEFINED_VAR');
+ });
+
+ it('should resolve multiple environment variables in a single string', () => {
+ process.env.VAR_A = 'valueA';
+ process.env.VAR_B = 'valueB';
+ const userSettingsContent = { path: '/path/$VAR_A/${VAR_B}/end' };
+ (mockFsExistsSync as Mock).mockImplementation(
+ (p: fs.PathLike) => p === USER_SETTINGS_PATH,
+ );
+ (fs.readFileSync as Mock).mockImplementation(
+ (p: fs.PathOrFileDescriptor) => {
+ if (p === USER_SETTINGS_PATH)
+ return JSON.stringify(userSettingsContent);
+ return '{}';
+ },
+ );
+ const settings = loadSettings(MOCK_WORKSPACE_DIR);
+ expect(settings.user.settings.path).toBe('/path/valueA/valueB/end');
+ delete process.env.VAR_A;
+ delete process.env.VAR_B;
+ });
+
+ it('should resolve environment variables in arrays', () => {
+ process.env.ITEM_1 = 'item1_env';
+ process.env.ITEM_2 = 'item2_env';
+ const userSettingsContent = { list: ['$ITEM_1', '${ITEM_2}', 'literal'] };
+ (mockFsExistsSync as Mock).mockImplementation(
+ (p: fs.PathLike) => p === USER_SETTINGS_PATH,
+ );
+ (fs.readFileSync as Mock).mockImplementation(
+ (p: fs.PathOrFileDescriptor) => {
+ if (p === USER_SETTINGS_PATH)
+ return JSON.stringify(userSettingsContent);
+ return '{}';
+ },
+ );
+ const settings = loadSettings(MOCK_WORKSPACE_DIR);
+ expect(settings.user.settings.list).toEqual([
+ 'item1_env',
+ 'item2_env',
+ 'literal',
+ ]);
+ delete process.env.ITEM_1;
+ delete process.env.ITEM_2;
+ });
});
describe('LoadedSettings class', () => {