@@ -28,6 +28,7 @@ import (
2828 "github.com/slackapi/slack-cli/internal/slackerror"
2929 "github.com/slackapi/slack-cli/internal/slacktrace"
3030 "github.com/slackapi/slack-cli/test/testutil"
31+ "github.com/spf13/afero"
3132 "github.com/spf13/cobra"
3233 "github.com/stretchr/testify/assert"
3334 "github.com/stretchr/testify/mock"
@@ -46,88 +47,22 @@ var mockApp = types.App{
4647
4748func Test_Env_AddCommandPreRun (t * testing.T ) {
4849 tests := map [string ]struct {
49- mockFlagForce bool
50- mockManifestResponse types.SlackYaml
51- mockManifestError error
52- mockManifestSource config.ManifestSource
5350 mockWorkingDirectory string
5451 expectedError error
5552 }{
56- "continues if the application is hosted on slack" : {
57- mockManifestResponse : types.SlackYaml {
58- AppManifest : types.AppManifest {
59- Settings : & types.AppSettings {
60- FunctionRuntime : types .SlackHosted ,
61- },
62- },
63- },
64- mockManifestError : nil ,
65- mockManifestSource : config .ManifestSourceLocal ,
66- mockWorkingDirectory : "/slack/path/to/project" ,
67- expectedError : nil ,
68- },
69- "errors if the application is not hosted on slack" : {
70- mockManifestResponse : types.SlackYaml {
71- AppManifest : types.AppManifest {
72- Settings : & types.AppSettings {
73- FunctionRuntime : types .Remote ,
74- },
75- },
76- },
77- mockManifestError : nil ,
78- mockManifestSource : config .ManifestSourceLocal ,
79- mockWorkingDirectory : "/slack/path/to/project" ,
80- expectedError : slackerror .New (slackerror .ErrAppNotHosted ),
81- },
82- "continues if the force flag is used in a project" : {
83- mockFlagForce : true ,
53+ "continues if the command is run in a project" : {
8454 mockWorkingDirectory : "/slack/path/to/project" ,
8555 expectedError : nil ,
8656 },
87- "errors if the project manifest cannot be retrieved" : {
88- mockManifestResponse : types.SlackYaml {},
89- mockManifestError : slackerror .New (slackerror .ErrSDKHookInvocationFailed ),
90- mockManifestSource : config .ManifestSourceLocal ,
91- mockWorkingDirectory : "/slack/path/to/project" ,
92- expectedError : slackerror .New (slackerror .ErrSDKHookInvocationFailed ),
93- },
9457 "errors if the command is not run in a project" : {
95- mockManifestResponse : types.SlackYaml {},
96- mockManifestError : slackerror .New (slackerror .ErrSDKHookNotFound ),
9758 mockWorkingDirectory : "" ,
9859 expectedError : slackerror .New (slackerror .ErrInvalidAppDirectory ),
9960 },
100- "errors if the manifest source is set to remote" : {
101- mockManifestSource : config .ManifestSourceRemote ,
102- mockWorkingDirectory : "/slack/path/to/project" ,
103- expectedError : slackerror .New (slackerror .ErrAppNotHosted ),
104- },
10561 }
10662 for name , tc := range tests {
10763 t .Run (name , func (t * testing.T ) {
10864 clientsMock := shared .NewClientsMock ()
109- manifestMock := & app.ManifestMockObject {}
110- manifestMock .On (
111- "GetManifestLocal" ,
112- mock .Anything ,
113- mock .Anything ,
114- mock .Anything ,
115- ).Return (
116- tc .mockManifestResponse ,
117- tc .mockManifestError ,
118- )
119- clientsMock .AppClient .Manifest = manifestMock
120- projectConfigMock := config .NewProjectConfigMock ()
121- projectConfigMock .On (
122- "GetManifestSource" ,
123- mock .Anything ,
124- ).Return (
125- tc .mockManifestSource ,
126- nil ,
127- )
128- clientsMock .Config .ProjectConfig = projectConfigMock
12965 clients := shared .NewClientFactory (clientsMock .MockClientFactory (), func (cf * shared.ClientFactory ) {
130- cf .Config .ForceFlag = tc .mockFlagForce
13166 cf .SDKConfig .WorkingDirectory = tc .mockWorkingDirectory
13267 })
13368 cmd := NewEnvAddCommand (clients )
@@ -146,7 +81,7 @@ func Test_Env_AddCommand(t *testing.T) {
14681 "add a variable using arguments" : {
14782 CmdArgs : []string {"ENV_NAME" , "ENV_VALUE" },
14883 Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
149- setupEnvAddCommandMocks (ctx , cm , cf )
84+ setupEnvAddHostedMocks (ctx , cm , cf )
15085 },
15186 ExpectedAsserts : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock ) {
15287 cm .API .AssertCalled (
@@ -170,7 +105,7 @@ func Test_Env_AddCommand(t *testing.T) {
170105 "provide a variable name by argument and value by prompt" : {
171106 CmdArgs : []string {"ENV_NAME" },
172107 Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
173- setupEnvAddCommandMocks (ctx , cm , cf )
108+ setupEnvAddHostedMocks (ctx , cm , cf )
174109 cm .IO .On (
175110 "PasswordPrompt" ,
176111 mock .Anything ,
@@ -201,7 +136,7 @@ func Test_Env_AddCommand(t *testing.T) {
201136 "provide a variable name by argument and value by flag" : {
202137 CmdArgs : []string {"ENV_NAME" , "--value" , "example_value" },
203138 Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
204- setupEnvAddCommandMocks (ctx , cm , cf )
139+ setupEnvAddHostedMocks (ctx , cm , cf )
205140 cm .IO .On (
206141 "PasswordPrompt" ,
207142 mock .Anything ,
@@ -232,7 +167,7 @@ func Test_Env_AddCommand(t *testing.T) {
232167 "provide both variable name and value by prompt" : {
233168 CmdArgs : []string {},
234169 Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
235- setupEnvAddCommandMocks (ctx , cm , cf )
170+ setupEnvAddHostedMocks (ctx , cm , cf )
236171 cm .IO .On (
237172 "InputPrompt" ,
238173 mock .Anything ,
@@ -269,24 +204,108 @@ func Test_Env_AddCommand(t *testing.T) {
269204 )
270205 },
271206 },
207+ "add a numeric variable using prompts to the .env file" : {
208+ CmdArgs : []string {},
209+ Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
210+ setupEnvAddDotenvMocks (ctx , cm , cf )
211+ cm .IO .On (
212+ "InputPrompt" ,
213+ mock .Anything ,
214+ "Variable name" ,
215+ mock .Anything ,
216+ ).Return (
217+ "PORT" ,
218+ nil ,
219+ )
220+ cm .IO .On (
221+ "PasswordPrompt" ,
222+ mock .Anything ,
223+ "Variable value" ,
224+ iostreams .MatchPromptConfig (iostreams.PasswordPromptConfig {
225+ Flag : cm .Config .Flags .Lookup ("value" ),
226+ }),
227+ ).Return (
228+ iostreams.PasswordPromptResponse {
229+ Prompt : true ,
230+ Value : "3000" ,
231+ },
232+ nil ,
233+ )
234+ },
235+ ExpectedAsserts : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock ) {
236+ cm .API .AssertNotCalled (t , "AddVariable" )
237+ content , err := afero .ReadFile (cm .Fs , ".env" )
238+ assert .NoError (t , err )
239+ assert .Equal (t , "PORT=3000\n " , string (content ))
240+ },
241+ },
242+ "add a variable to the .env file for non-hosted app" : {
243+ CmdArgs : []string {"NEW_VAR" , "new_value" },
244+ Setup : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
245+ setupEnvAddDotenvMocks (ctx , cm , cf )
246+ err := afero .WriteFile (cf .Fs , ".env" , []byte ("# Config\n EXISTING=value\n " ), 0600 )
247+ assert .NoError (t , err )
248+ },
249+ ExpectedAsserts : func (t * testing.T , ctx context.Context , cm * shared.ClientsMock ) {
250+ cm .API .AssertNotCalled (t , "AddVariable" )
251+ content , err := afero .ReadFile (cm .Fs , ".env" )
252+ assert .NoError (t , err )
253+ assert .Equal (t , "# Config\n EXISTING=value\n NEW_VAR=\" new_value\" \n " , string (content ))
254+ },
255+ },
272256 }, func (cf * shared.ClientFactory ) * cobra.Command {
273257 cmd := NewEnvAddCommand (cf )
274258 cmd .PreRunE = func (cmd * cobra.Command , args []string ) error { return nil }
275259 return cmd
276260 })
277261}
278262
279- // setupEnvAddCommandMocks prepares common mocks for these tests
280- func setupEnvAddCommandMocks (ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
263+ // setupEnvAddHostedMocks prepares common mocks for hosted app tests
264+ func setupEnvAddHostedMocks (ctx context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
281265 cf .SDKConfig = hooks .NewSDKConfigMock ()
282266 cm .AddDefaultMocks ()
283267 _ = cf .AppClient ().SaveDeployed (ctx , mockApp )
284268
285269 appSelectMock := prompts .NewAppSelectMock ()
286270 appSelectPromptFunc = appSelectMock .AppSelectPrompt
287- appSelectMock .On ("AppSelectPrompt" , mock .Anything , mock .Anything , prompts .ShowHostedOnly , prompts .ShowInstalledAppsOnly ).Return (prompts.SelectedApp {Auth : mockAuth , App : mockApp }, nil )
271+ appSelectMock .On ("AppSelectPrompt" , mock .Anything , mock .Anything , prompts .ShowAllEnvironments , prompts .ShowInstalledAppsOnly ).Return (prompts.SelectedApp {Auth : mockAuth , App : mockApp }, nil )
288272
289273 cm .Config .Flags .String ("value" , "" , "mock value flag" )
290274
291275 cm .API .On ("AddVariable" , mock .Anything , mock .Anything , mock .Anything , mock .Anything , mock .Anything ).Return (nil )
276+
277+ manifestMock := & app.ManifestMockObject {}
278+ manifestMock .On ("GetManifestLocal" , mock .Anything , mock .Anything , mock .Anything ).Return (
279+ types.SlackYaml {
280+ AppManifest : types.AppManifest {
281+ Settings : & types.AppSettings {
282+ FunctionRuntime : types .SlackHosted ,
283+ },
284+ },
285+ },
286+ nil ,
287+ )
288+ cm .AppClient .Manifest = manifestMock
289+ projectConfigMock := config .NewProjectConfigMock ()
290+ projectConfigMock .On ("GetManifestSource" , mock .Anything ).Return (config .ManifestSourceLocal , nil )
291+ cm .Config .ProjectConfig = projectConfigMock
292+ cf .SDKConfig .WorkingDirectory = "/slack/path/to/project"
293+ }
294+
295+ // setupEnvAddDotenvMocks prepares common mocks for non-hosted (dotenv) app tests
296+ func setupEnvAddDotenvMocks (_ context.Context , cm * shared.ClientsMock , cf * shared.ClientFactory ) {
297+ cf .SDKConfig = hooks .NewSDKConfigMock ()
298+ cm .AddDefaultMocks ()
299+
300+ mockDevApp := types.App {
301+ TeamID : "T1" ,
302+ TeamDomain : "team1" ,
303+ AppID : "A0123456789" ,
304+ IsDev : true ,
305+ }
306+ appSelectMock := prompts .NewAppSelectMock ()
307+ appSelectPromptFunc = appSelectMock .AppSelectPrompt
308+ appSelectMock .On ("AppSelectPrompt" , mock .Anything , mock .Anything , prompts .ShowAllEnvironments , prompts .ShowInstalledAppsOnly ).Return (prompts.SelectedApp {Auth : mockAuth , App : mockDevApp }, nil )
309+
310+ cm .Config .Flags .String ("value" , "" , "mock value flag" )
292311}
0 commit comments