Skip to content

Commit

Permalink
test: Methods related to config updates
Browse files Browse the repository at this point in the history
  • Loading branch information
alexluong committed Oct 15, 2024
1 parent 5006f6c commit d5e33d0
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 8 deletions.
15 changes: 8 additions & 7 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,12 @@ func (c *Config) InitConfig() {
}

// Read config file
if err := c.viper.ReadInConfig(); err == nil {
log.WithFields(log.Fields{
"prefix": "config.Config.InitConfig",
"path": c.viper.ConfigFileUsed(),
}).Debug("Reading config file")
log.WithFields(log.Fields{
"prefix": "config.Config.InitConfig",
"path": c.viper.ConfigFileUsed(),
}).Debug("Reading config file")
if err := c.viper.ReadInConfig(); err != nil {
log.Fatal(err)
}

// Construct the config struct
Expand Down Expand Up @@ -175,8 +176,8 @@ func (c *Config) writeConfig() error {
}

log.WithFields(log.Fields{
"prefix": "config.Config.WriteConfig",
"path": c.viper.WriteConfig(),
"prefix": "config.Config.writeConfig",
"path": c.viper.ConfigFileUsed(),
}).Debug("Writing config")

return c.viper.WriteConfig()
Expand Down
131 changes: 131 additions & 0 deletions pkg/config/config_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package config

import (
"io"
"io/ioutil"
"os"
"path/filepath"
"testing"
Expand Down Expand Up @@ -220,6 +222,135 @@ func TestInitConfig(t *testing.T) {
})
}

func TestWriteConfig(t *testing.T) {
t.Parallel()

t.Run("save profile", func(t *testing.T) {
t.Parallel()

// Arrange
c := Config{LogLevel: "info"}
c.ConfigFileFlag = setupTempConfig(t, "./testdata/default-profile.toml")
c.InitConfig()

// Act
c.Profile.TeamMode = "new_team_mode"
err := c.Profile.SaveProfile()

// Assert
assert.NoError(t, err)
contentBytes, _ := ioutil.ReadFile(c.viper.ConfigFileUsed())
assert.Contains(t, string(contentBytes), `workspace_mode = "new_team_mode"`)
})

t.Run("use project", func(t *testing.T) {
t.Parallel()

// Arrange
c := Config{LogLevel: "info"}
c.ConfigFileFlag = setupTempConfig(t, "./testdata/default-profile.toml")
c.InitConfig()

// Act
err := c.UseProject("new_team_id", "new_team_mode")

// Assert
assert.NoError(t, err)
contentBytes, _ := ioutil.ReadFile(c.viper.ConfigFileUsed())
assert.Contains(t, string(contentBytes), `workspace_id = "new_team_id"`)
})

t.Run("use profile", func(t *testing.T) {
t.Parallel()

// Arrange
c := Config{LogLevel: "info"}
c.ConfigFileFlag = setupTempConfig(t, "./testdata/multiple-profiles.toml")
c.InitConfig()

// Act
c.Profile.Name = "account_3"
err := c.Profile.UseProfile()

// Assert
assert.NoError(t, err)
contentBytes, _ := ioutil.ReadFile(c.viper.ConfigFileUsed())
assert.Contains(t, string(contentBytes), `profile = "account_3"`)
})

t.Run("remove profile", func(t *testing.T) {
t.Parallel()

// Arrange
c := Config{LogLevel: "info"}
c.ConfigFileFlag = setupTempConfig(t, "./testdata/multiple-profiles.toml")
c.InitConfig()

// Act
err := c.Profile.RemoveProfile()

// Assert
assert.NoError(t, err)
contentBytes, _ := ioutil.ReadFile(c.viper.ConfigFileUsed())
assert.NotContains(t, string(contentBytes), "account_2", `default profile "account_2" should be cleared`)
assert.NotContains(t, string(contentBytes), `profile =`, `profile key should be cleared`)
})

t.Run("remove profile multiple times", func(t *testing.T) {
t.Parallel()

// Arrange
c := Config{LogLevel: "info"}
c.ConfigFileFlag = setupTempConfig(t, "./testdata/multiple-profiles.toml")
c.InitConfig()

// Act
err := c.Profile.RemoveProfile()

// Assert
assert.NoError(t, err)
contentBytes, _ := ioutil.ReadFile(c.viper.ConfigFileUsed())
assert.NotContains(t, string(contentBytes), "account_2", `default profile "account_2" should be cleared`)
assert.NotContains(t, string(contentBytes), `profile =`, `profile key should be cleared`)

// Remove profile again

c2 := Config{LogLevel: "info"}
c2.ConfigFileFlag = c.ConfigFileFlag
c2.InitConfig()
err = c2.Profile.RemoveProfile()

contentBytes, _ = ioutil.ReadFile(c2.viper.ConfigFileUsed())
assert.NoError(t, err)
assert.NotContains(t, string(contentBytes), "[default]", `default profile "default" should be cleared`)
assert.NotContains(t, string(contentBytes), `api_key = "test_api_key"`, `default profile "default" should be cleared`)

// Now even though there are some profiles (account_1, account_3), when reading config
// we won't register any profile.
// TODO: Consider this case. It's not great UX. This may be an edge case only power users run into
// given it requires users to be using multiple profiles.

c3 := Config{LogLevel: "info"}
c3.ConfigFileFlag = c.ConfigFileFlag
c3.InitConfig()
assert.Equal(t, "default", c3.Profile.Name, `profile should be "default"`)
assert.Equal(t, "", c3.Profile.APIKey, "api key should be empty even though there are other profiles")
})
}

// ===== Test helpers =====

func setupTempConfig(t *testing.T, sourceConfigPath string) string {
dir := t.TempDir()
configPath := filepath.Join(dir, "config.toml")
srcFile, _ := os.Open(sourceConfigPath)
defer srcFile.Close()
destFile, _ := os.Create(configPath)
defer destFile.Close()
io.Copy(destFile, srcFile)
return configPath
}

// ===== Mock FS =====

// Mock fs where there's no config file, whether global or local
Expand Down
4 changes: 3 additions & 1 deletion pkg/config/profile.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package config

import "github.com/hookdeck/hookdeck-cli/pkg/validators"
import (
"github.com/hookdeck/hookdeck-cli/pkg/validators"
)

type Profile struct {
Name string // profile name
Expand Down

0 comments on commit d5e33d0

Please sign in to comment.