|
7 | 7 | "context" |
8 | 8 | "errors" |
9 | 9 | "fmt" |
| 10 | + "os" |
| 11 | + "path/filepath" |
10 | 12 | "strings" |
11 | 13 | "testing" |
12 | 14 |
|
@@ -718,3 +720,100 @@ func Test_EnvManager_InstanceCaching(t *testing.T) { |
718 | 720 | localDataStore.AssertNumberOfCalls(t, "Get", 1) // Only initial load, not after Save |
719 | 721 | }) |
720 | 722 | } |
| 723 | + |
| 724 | +func Test_EnvManager_Create_NoPrompt_AutoName(t *testing.T) { |
| 725 | + t.Run("generates name from working directory", func(t *testing.T) { |
| 726 | + mockContext := mocks.NewMockContext(context.Background()) |
| 727 | + mockContext.Console.SetNoPromptMode(true) |
| 728 | + |
| 729 | + // Use a known directory name so we can assert the generated env name |
| 730 | + tmpDir := t.TempDir() |
| 731 | + knownDir := filepath.Join(tmpDir, "my-cool-project") |
| 732 | + require.NoError(t, os.Mkdir(knownDir, 0755)) |
| 733 | + |
| 734 | + azdCtx := azdcontext.NewAzdContextWithDirectory(knownDir) |
| 735 | + localDataStore := NewLocalFileDataStore(azdCtx, config.NewFileConfigManager(config.NewManager())) |
| 736 | + envManager := newManagerForTest(azdCtx, mockContext.Console, localDataStore, nil) |
| 737 | + |
| 738 | + env, err := envManager.Create(*mockContext.Context, Spec{Name: ""}) |
| 739 | + require.NoError(t, err) |
| 740 | + require.NotNil(t, env) |
| 741 | + require.Equal(t, "my-cool-project", env.Name()) |
| 742 | + }) |
| 743 | + |
| 744 | + t.Run("cleans special characters in directory name", func(t *testing.T) { |
| 745 | + mockContext := mocks.NewMockContext(context.Background()) |
| 746 | + mockContext.Console.SetNoPromptMode(true) |
| 747 | + |
| 748 | + tmpDir := t.TempDir() |
| 749 | + knownDir := filepath.Join(tmpDir, "my cool project!") |
| 750 | + require.NoError(t, os.Mkdir(knownDir, 0755)) |
| 751 | + |
| 752 | + azdCtx := azdcontext.NewAzdContextWithDirectory(knownDir) |
| 753 | + localDataStore := NewLocalFileDataStore(azdCtx, config.NewFileConfigManager(config.NewManager())) |
| 754 | + envManager := newManagerForTest(azdCtx, mockContext.Console, localDataStore, nil) |
| 755 | + |
| 756 | + env, err := envManager.Create(*mockContext.Context, Spec{Name: ""}) |
| 757 | + require.NoError(t, err) |
| 758 | + require.NotNil(t, env) |
| 759 | + require.Equal(t, "my-cool-project-", env.Name()) |
| 760 | + }) |
| 761 | + |
| 762 | + t.Run("truncates long directory names", func(t *testing.T) { |
| 763 | + mockContext := mocks.NewMockContext(context.Background()) |
| 764 | + mockContext.Console.SetNoPromptMode(true) |
| 765 | + |
| 766 | + tmpDir := t.TempDir() |
| 767 | + longName := strings.Repeat("a", 100) |
| 768 | + knownDir := filepath.Join(tmpDir, longName) |
| 769 | + require.NoError(t, os.Mkdir(knownDir, 0755)) |
| 770 | + |
| 771 | + azdCtx := azdcontext.NewAzdContextWithDirectory(knownDir) |
| 772 | + localDataStore := NewLocalFileDataStore(azdCtx, config.NewFileConfigManager(config.NewManager())) |
| 773 | + envManager := newManagerForTest(azdCtx, mockContext.Console, localDataStore, nil) |
| 774 | + |
| 775 | + env, err := envManager.Create(*mockContext.Context, Spec{Name: ""}) |
| 776 | + require.NoError(t, err) |
| 777 | + require.NotNil(t, env) |
| 778 | + require.LessOrEqual(t, len(env.Name()), EnvironmentNameMaxLength) |
| 779 | + require.Equal(t, strings.Repeat("a", EnvironmentNameMaxLength), env.Name()) |
| 780 | + }) |
| 781 | + |
| 782 | + t.Run("uses provided name even in no-prompt mode", func(t *testing.T) { |
| 783 | + mockContext := mocks.NewMockContext(context.Background()) |
| 784 | + mockContext.Console.SetNoPromptMode(true) |
| 785 | + |
| 786 | + envManager := createEnvManagerForManagerTest(t, mockContext) |
| 787 | + env, err := envManager.Create(*mockContext.Context, Spec{Name: "my-explicit-env"}) |
| 788 | + require.NoError(t, err) |
| 789 | + require.NotNil(t, env) |
| 790 | + require.Equal(t, "my-explicit-env", env.Name()) |
| 791 | + }) |
| 792 | +} |
| 793 | + |
| 794 | +func Test_CleanName_EdgeCases(t *testing.T) { |
| 795 | + tests := []struct { |
| 796 | + name string |
| 797 | + input string |
| 798 | + expected string |
| 799 | + }{ |
| 800 | + {"simple name", "my-project", "my-project"}, |
| 801 | + {"spaces replaced", "my project", "my-project"}, |
| 802 | + {"special chars replaced", "my@project!v2", "my-project-v2"}, |
| 803 | + {"dots preserved", "my.project", "my.project"}, |
| 804 | + {"underscores preserved", "my_project", "my_project"}, |
| 805 | + {"unicode replaced", "projeçt-naïve", "proje-t-na-ve"}, |
| 806 | + // Note: parentheses are valid in env names per EnvironmentNameRegexp: [a-zA-Z0-9-\(\)_\.] |
| 807 | + {"parens preserved", "my(project)", "my(project)"}, |
| 808 | + {"empty string", "", ""}, |
| 809 | + {"all special chars", "@#$", "---"}, |
| 810 | + {"long name not truncated by CleanName", strings.Repeat("a", 100), strings.Repeat("a", 100)}, |
| 811 | + } |
| 812 | + |
| 813 | + for _, tt := range tests { |
| 814 | + t.Run(tt.name, func(t *testing.T) { |
| 815 | + result := CleanName(tt.input) |
| 816 | + require.Equal(t, tt.expected, result) |
| 817 | + }) |
| 818 | + } |
| 819 | +} |
0 commit comments