From 4d88437d197e8b99b59c223e23cc72c1a4d26e6f Mon Sep 17 00:00:00 2001 From: SakshiKoli-CS Date: Thu, 13 Nov 2025 16:54:08 +0530 Subject: [PATCH] fix: allow --variable-type flag to accept multiple values --- AGENTS.md | 2 +- src/adapters/base-class.test.ts | 129 +++++++++++++++++++++++++++++++- src/commands/launch/index.ts | 5 +- 3 files changed, 131 insertions(+), 5 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 90649ae..d9d125e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,7 +2,7 @@ - Follow the Arrange, Act, Assert structure when writing unit tests. - When writing unit tests, create individual unit tests that cover each logical branching in the code. -- For the happy path, can we have a single unit test where in the all the top level if conditions are executed? Maybe this might help with reducing the number of total unit tests created and still give same test coverage. +- For the happy path, can we have a single unit test where all the top level if conditions are executed? This might help with reducing the number of total unit tests created and still give same test coverage. - For the tests for edge cases do not create separate describe blocks, keep the hierarchy flat. - For the tests for edge cases, do not skip assertions, its still worth adding all assertions similar to the happy paths tests. diff --git a/src/adapters/base-class.test.ts b/src/adapters/base-class.test.ts index 32cb659..009f1e9 100644 --- a/src/adapters/base-class.test.ts +++ b/src/adapters/base-class.test.ts @@ -125,6 +125,120 @@ describe('BaseClass', () => { ); }); + it('should handle two options: Import from stack and Manually add variables', async () => { + baseClass = new BaseClass({ + log: logMock, + exit: exitMock, + config: { + variableType: ['Import variables from a stack', 'Manually add custom variables to the list'], + variablePreparationTypeOptions: config.variablePreparationTypeOptions, + }, + } as any); + + const importEnvFromStackMock = jest.spyOn(baseClass, 'importEnvFromStack').mockResolvedValueOnce(); + const promptForEnvValuesMock = jest.spyOn(baseClass, 'promptForEnvValues').mockResolvedValueOnce(); + + await baseClass.handleEnvImportFlow(); + + expect(importEnvFromStackMock).toHaveBeenCalled(); + expect(promptForEnvValuesMock).toHaveBeenCalled(); + expect(exitMock).not.toHaveBeenCalled(); + }); + + it('should handle two options: Import from stack and Import from .env.local', async () => { + baseClass = new BaseClass({ + log: logMock, + exit: exitMock, + config: { + variableType: ['Import variables from a stack', 'Import variables from the .env.local file'], + variablePreparationTypeOptions: config.variablePreparationTypeOptions, + }, + } as any); + + const importEnvFromStackMock = jest.spyOn(baseClass, 'importEnvFromStack').mockResolvedValueOnce(); + const importVariableFromLocalConfigMock = jest + .spyOn(baseClass, 'importVariableFromLocalConfig') + .mockResolvedValueOnce(); + + await baseClass.handleEnvImportFlow(); + + expect(importEnvFromStackMock).toHaveBeenCalled(); + expect(importVariableFromLocalConfigMock).toHaveBeenCalled(); + expect(exitMock).not.toHaveBeenCalled(); + }); + + it('should handle two options: Manually add and Import from .env.local', async () => { + baseClass = new BaseClass({ + log: logMock, + exit: exitMock, + config: { + variableType: ['Manually add custom variables to the list', 'Import variables from the .env.local file'], + variablePreparationTypeOptions: config.variablePreparationTypeOptions, + }, + } as any); + + const promptForEnvValuesMock = jest.spyOn(baseClass, 'promptForEnvValues').mockResolvedValueOnce(); + const importVariableFromLocalConfigMock = jest + .spyOn(baseClass, 'importVariableFromLocalConfig') + .mockResolvedValueOnce(); + + await baseClass.handleEnvImportFlow(); + + expect(promptForEnvValuesMock).toHaveBeenCalled(); + expect(importVariableFromLocalConfigMock).toHaveBeenCalled(); + expect(exitMock).not.toHaveBeenCalled(); + }); + + it('should handle all three options: Import from stack, Manually add, and Import from .env.local', async () => { + baseClass = new BaseClass({ + log: logMock, + exit: exitMock, + config: { + variableType: [ + 'Import variables from a stack', + 'Manually add custom variables to the list', + 'Import variables from the .env.local file', + ], + variablePreparationTypeOptions: config.variablePreparationTypeOptions, + }, + } as any); + + const importEnvFromStackMock = jest.spyOn(baseClass, 'importEnvFromStack').mockResolvedValueOnce(); + const promptForEnvValuesMock = jest.spyOn(baseClass, 'promptForEnvValues').mockResolvedValueOnce(); + const importVariableFromLocalConfigMock = jest + .spyOn(baseClass, 'importVariableFromLocalConfig') + .mockResolvedValueOnce(); + + await baseClass.handleEnvImportFlow(); + + expect(importEnvFromStackMock).toHaveBeenCalled(); + expect(promptForEnvValuesMock).toHaveBeenCalled(); + expect(importVariableFromLocalConfigMock).toHaveBeenCalled(); + expect(exitMock).not.toHaveBeenCalled(); + }); + + it('should fail when Skip is combined with other options', async () => { + baseClass = new BaseClass({ + log: logMock, + exit: exitMock, + config: { + variableType: ['Skip adding environment variables', 'Import variables from a stack'], + variablePreparationTypeOptions: config.variablePreparationTypeOptions, + }, + } as any); + + const importEnvFromStackMock = jest.spyOn(baseClass, 'importEnvFromStack').mockResolvedValueOnce(undefined); + + await baseClass.handleEnvImportFlow(); + + expect(logMock).toHaveBeenCalledWith( + "The 'Skip adding environment variables' option cannot be combined with other environment variable options. Please choose either 'Skip adding environment variables' or one or more of the other available options.", + 'error', + ); + expect(exitMock).toHaveBeenCalledWith(1); + expect(importEnvFromStackMock).toHaveBeenCalled(); + }); + it('should exit if no options are selected', async () => { (ux.inquire as jest.Mock).mockResolvedValueOnce([]); @@ -138,21 +252,30 @@ describe('BaseClass', () => { }); it('should exit if "Skip adding environment variables" is selected with other options', async () => { + const exitMockWithThrow = jest.fn().mockImplementation(() => { + throw new Error('Exit called'); + }); + baseClass = new BaseClass({ + log: logMock, + exit: exitMockWithThrow, + config: config.variablePreparationTypeOptions, + } as any); + const importEnvFromStackMock = jest.spyOn(baseClass, 'importEnvFromStack').mockResolvedValueOnce(); (ux.inquire as jest.Mock).mockResolvedValueOnce([ 'Skip adding environment variables', 'Import variables from a stack', ]); - await baseClass.handleEnvImportFlow(); + await expect(baseClass.handleEnvImportFlow()).rejects.toThrow('Exit called'); expect(logMock).toHaveBeenCalledWith( "The 'Skip adding environment variables' option cannot be combined with other environment variable options. Please choose either 'Skip adding environment variables' or one or more of the other available options.", 'error', ); - expect(exitMock).toHaveBeenCalledWith(1); - expect(importEnvFromStackMock).toHaveBeenCalled(); + expect(exitMockWithThrow).toHaveBeenCalledWith(1); + expect(importEnvFromStackMock).not.toHaveBeenCalled(); }); it('should call importEnvFromStack if "Import variables from a stack" is selected', async () => { diff --git a/src/commands/launch/index.ts b/src/commands/launch/index.ts index 21b34b7..4ffc745 100755 --- a/src/commands/launch/index.ts +++ b/src/commands/launch/index.ts @@ -29,6 +29,8 @@ export default class Launch extends BaseCommand { '<%= config.bin %> <%= command.id %> --config --type --name= --environment= --branch= --build-command= --framework=