@@ -25,7 +25,9 @@ import (
2525
2626// setupInitAction creates an initAction wired with mocks that pass git-install checks.
2727// The working directory is changed to a temp dir so that .env loading and azdcontext work.
28- func setupInitAction (t * testing.T , mockContext * mocks.MockContext , flags * initFlags ) * initAction {
28+ func setupInitAction (
29+ t * testing.T , mockContext * mocks.MockContext , flags * initFlags , args ... string ,
30+ ) * initAction {
2931 t .Helper ()
3032
3133 // Work in a temp directory so os.Getwd / godotenv.Overload operate in isolation.
@@ -50,6 +52,7 @@ func setupInitAction(t *testing.T, mockContext *mocks.MockContext, flags *initFl
5052 cmdRun : mockContext .CommandRunner ,
5153 gitCli : gitCli ,
5254 flags : flags ,
55+ args : args ,
5356 featuresManager : alpha .NewFeaturesManagerWithConfig (config .NewEmptyConfig ()),
5457 }
5558}
@@ -231,3 +234,195 @@ func TestInitFailFastMissingEnvNonInteractive(t *testing.T) {
231234 }
232235 })
233236}
237+
238+ func TestInitResolveTargetDirectory (t * testing.T ) {
239+ t .Run ("DotArgUsesCwd" , func (t * testing.T ) {
240+ mockContext := mocks .NewMockContext (context .Background ())
241+ flags := & initFlags {
242+ templatePath : "owner/repo" ,
243+ global : & internal.GlobalCommandOptions {},
244+ }
245+ action := setupInitAction (t , mockContext , flags , "." )
246+
247+ wd , err := os .Getwd ()
248+ require .NoError (t , err )
249+
250+ result , err := action .resolveTargetDirectory (wd )
251+ require .NoError (t , err )
252+ require .Equal (t , wd , result )
253+ })
254+
255+ t .Run ("ExplicitDirectoryUsesArg" , func (t * testing.T ) {
256+ mockContext := mocks .NewMockContext (context .Background ())
257+ flags := & initFlags {
258+ templatePath : "owner/repo" ,
259+ global : & internal.GlobalCommandOptions {},
260+ }
261+ action := setupInitAction (t , mockContext , flags , "my-project" )
262+
263+ wd , err := os .Getwd ()
264+ require .NoError (t , err )
265+
266+ result , err := action .resolveTargetDirectory (wd )
267+ require .NoError (t , err )
268+ require .Equal (t , filepath .Join (wd , "my-project" ), result )
269+ })
270+
271+ t .Run ("NoArgDerivesFromTemplatePath" , func (t * testing.T ) {
272+ mockContext := mocks .NewMockContext (context .Background ())
273+ flags := & initFlags {
274+ templatePath : "Azure-Samples/todo-nodejs-mongo" ,
275+ global : & internal.GlobalCommandOptions {},
276+ }
277+ action := setupInitAction (t , mockContext , flags )
278+
279+ wd , err := os .Getwd ()
280+ require .NoError (t , err )
281+
282+ result , err := action .resolveTargetDirectory (wd )
283+ require .NoError (t , err )
284+ require .Equal (t , filepath .Join (wd , "todo-nodejs-mongo" ), result )
285+ })
286+
287+ t .Run ("NoArgWithFilterTagsUsesCwd" , func (t * testing.T ) {
288+ mockContext := mocks .NewMockContext (context .Background ())
289+ flags := & initFlags {
290+ templateTags : []string {"python" },
291+ global : & internal.GlobalCommandOptions {},
292+ }
293+ action := setupInitAction (t , mockContext , flags )
294+
295+ wd , err := os .Getwd ()
296+ require .NoError (t , err )
297+
298+ result , err := action .resolveTargetDirectory (wd )
299+ require .NoError (t , err )
300+ require .Equal (t , wd , result )
301+ })
302+
303+ t .Run ("TemplateWithDotGitSuffix" , func (t * testing.T ) {
304+ mockContext := mocks .NewMockContext (context .Background ())
305+ flags := & initFlags {
306+ templatePath : "https://github.com/Azure-Samples/todo-nodejs-mongo.git" ,
307+ global : & internal.GlobalCommandOptions {},
308+ }
309+ action := setupInitAction (t , mockContext , flags )
310+
311+ wd , err := os .Getwd ()
312+ require .NoError (t , err )
313+
314+ result , err := action .resolveTargetDirectory (wd )
315+ require .NoError (t , err )
316+ require .Equal (t , filepath .Join (wd , "todo-nodejs-mongo" ), result )
317+ })
318+ }
319+
320+ func TestInitValidateTargetDirectory (t * testing.T ) {
321+ t .Run ("NonExistentDirectoryIsValid" , func (t * testing.T ) {
322+ mockContext := mocks .NewMockContext (context .Background ())
323+ flags := & initFlags {
324+ templatePath : "owner/repo" ,
325+ global : & internal.GlobalCommandOptions {},
326+ }
327+ action := setupInitAction (t , mockContext , flags )
328+
329+ err := action .validateTargetDirectory (
330+ * mockContext .Context , filepath .Join (t .TempDir (), "nonexistent" ))
331+ require .NoError (t , err )
332+ })
333+
334+ t .Run ("EmptyDirectoryIsValid" , func (t * testing.T ) {
335+ mockContext := mocks .NewMockContext (context .Background ())
336+ flags := & initFlags {
337+ templatePath : "owner/repo" ,
338+ global : & internal.GlobalCommandOptions {},
339+ }
340+ action := setupInitAction (t , mockContext , flags )
341+
342+ emptyDir := t .TempDir ()
343+ err := action .validateTargetDirectory (* mockContext .Context , emptyDir )
344+ require .NoError (t , err )
345+ })
346+
347+ t .Run ("NonEmptyDirectoryErrorsInNoPromptMode" , func (t * testing.T ) {
348+ mockContext := mocks .NewMockContext (context .Background ())
349+ mockContext .Console .SetNoPromptMode (true )
350+ flags := & initFlags {
351+ templatePath : "owner/repo" ,
352+ global : & internal.GlobalCommandOptions {NoPrompt : true },
353+ }
354+ action := setupInitAction (t , mockContext , flags )
355+
356+ nonEmptyDir := t .TempDir ()
357+ require .NoError (t , os .WriteFile (
358+ filepath .Join (nonEmptyDir , "existing.txt" ), []byte ("content" ), 0600 ))
359+
360+ err := action .validateTargetDirectory (* mockContext .Context , nonEmptyDir )
361+ require .Error (t , err )
362+ require .Contains (t , err .Error (), "already exists and is not empty" )
363+ })
364+ }
365+
366+ func TestInitCreatesProjectDirectory (t * testing.T ) {
367+ t .Run ("TemplateInitCreatesDirectory" , func (t * testing.T ) {
368+ mockContext := mocks .NewMockContext (context .Background ())
369+ mockContext .Console .SetNoPromptMode (true )
370+ flags := & initFlags {
371+ templatePath : "Azure-Samples/todo-nodejs-mongo" ,
372+ global : & internal.GlobalCommandOptions {NoPrompt : true },
373+ }
374+ flags .EnvironmentName = "testenv"
375+ action := setupInitAction (t , mockContext , flags )
376+
377+ wd , err := os .Getwd ()
378+ require .NoError (t , err )
379+
380+ expectedDir := filepath .Join (wd , "todo-nodejs-mongo" )
381+ require .NoDirExists (t , expectedDir )
382+
383+ // Run will panic or error later due to missing template mocks,
384+ // but the directory should be created before that point.
385+ _ = runActionSafe (* mockContext .Context , action )
386+ require .DirExists (t , expectedDir )
387+ })
388+
389+ t .Run ("DotArgDoesNotCreateDirectory" , func (t * testing.T ) {
390+ mockContext := mocks .NewMockContext (context .Background ())
391+ mockContext .Console .SetNoPromptMode (true )
392+ flags := & initFlags {
393+ templatePath : "Azure-Samples/todo-nodejs-mongo" ,
394+ global : & internal.GlobalCommandOptions {NoPrompt : true },
395+ }
396+ flags .EnvironmentName = "testenv"
397+ action := setupInitAction (t , mockContext , flags , "." )
398+
399+ wd , err := os .Getwd ()
400+ require .NoError (t , err )
401+
402+ // Should NOT create a todo-nodejs-mongo subdirectory
403+ _ = runActionSafe (* mockContext .Context , action )
404+
405+ derivedDir := filepath .Join (wd , "todo-nodejs-mongo" )
406+ require .NoDirExists (t , derivedDir )
407+ })
408+
409+ t .Run ("ExplicitDirArgCreatesNamedDirectory" , func (t * testing.T ) {
410+ mockContext := mocks .NewMockContext (context .Background ())
411+ mockContext .Console .SetNoPromptMode (true )
412+ flags := & initFlags {
413+ templatePath : "Azure-Samples/todo-nodejs-mongo" ,
414+ global : & internal.GlobalCommandOptions {NoPrompt : true },
415+ }
416+ flags .EnvironmentName = "testenv"
417+ action := setupInitAction (t , mockContext , flags , "my-custom-project" )
418+
419+ wd , err := os .Getwd ()
420+ require .NoError (t , err )
421+
422+ expectedDir := filepath .Join (wd , "my-custom-project" )
423+ require .NoDirExists (t , expectedDir )
424+
425+ _ = runActionSafe (* mockContext .Context , action )
426+ require .DirExists (t , expectedDir )
427+ })
428+ }
0 commit comments