Skip to content

Commit

Permalink
feat: support env vars (#171)
Browse files Browse the repository at this point in the history
Support environment variables instead of flags for setting required command values. These are lower precedence than flags.
  • Loading branch information
dbolson authored Apr 15, 2024
1 parent 785e4f1 commit b0380ca
Show file tree
Hide file tree
Showing 11 changed files with 201 additions and 29 deletions.
12 changes: 12 additions & 0 deletions cmd/cmdtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"bytes"
"io"
"os"
"testing"

"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -47,3 +48,14 @@ func CallCmd(

return out, nil
}

// SetupTestEnvVars sets up and tears down tests for checking that environment variables are set.
func SetupTestEnvVars(_ *testing.T) func(t *testing.T) {
os.Setenv("LD_ACCESS_TOKEN", "testAccessToken")
os.Setenv("LD_BASE_URI", "http://test.com")

return func(t *testing.T) {
os.Unsetenv("LD_ACCESS_TOKEN")
os.Unsetenv("LD_BASE_URI")
}
}
26 changes: 24 additions & 2 deletions cmd/environments/get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,39 @@ func TestGet(t *testing.T) {
errorHelp := ". See `ldcli environments get --help` for supported flags and usage."
mockArgs := []interface{}{
"testAccessToken",
"https://app.launchdarkly.com",
"http://test.com",
"test-env",
"test-proj",
}
t.Run("with valid environments calls projects API", func(t *testing.T) {

t.Run("with valid environments calls API", func(t *testing.T) {
client := environments.MockClient{}
client.
On("Get", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
args := []string{
"environments", "get",
"--access-token", "testAccessToken",
"--base-uri", "http://test.com",
"--environment", "test-env",
"--project", "test-proj",
}

output, err := cmd.CallCmd(t, &client, nil, nil, nil, args)

require.NoError(t, err)
assert.JSONEq(t, `{"valid": true}`, string(output))
})

t.Run("with valid flags from environment variables calls API", func(t *testing.T) {
teardownTest := cmd.SetupTestEnvVars(t)
defer teardownTest(t)
client := environments.MockClient{}
client.
On("Get", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
args := []string{
"environments", "get",
"--environment", "test-env",
"--project", "test-proj",
}
Expand All @@ -45,6 +66,7 @@ func TestGet(t *testing.T) {
args := []string{
"environments", "get",
"--access-token", "testAccessToken",
"--base-uri", "http://test.com",
"--environment", "test-env",
"--project", "test-proj",
}
Expand Down
24 changes: 22 additions & 2 deletions cmd/flags/create_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package flags_test

import (
"ldcli/cmd"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"ldcli/cmd"
"ldcli/internal/errors"
"ldcli/internal/flags"
)
Expand All @@ -20,7 +20,8 @@ func TestCreate(t *testing.T) {
"test-key",
"test-proj-key",
}
t.Run("with valid flags calls projects API", func(t *testing.T) {

t.Run("with valid flags calls API", func(t *testing.T) {
client := flags.MockClient{}
client.
On("Create", mockArgs...).
Expand All @@ -39,6 +40,25 @@ func TestCreate(t *testing.T) {
assert.JSONEq(t, `{"valid": true}`, string(output))
})

t.Run("with valid flags from environment variables calls API", func(t *testing.T) {
teardownTest := cmd.SetupTestEnvVars(t)
defer teardownTest(t)
client := flags.MockClient{}
client.
On("Create", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
args := []string{
"flags", "create",
"-d", `{"key": "test-key", "name": "test-name"}`,
"--project", "test-proj-key",
}

output, err := cmd.CallCmd(t, nil, &client, nil, nil, args)

require.NoError(t, err)
assert.JSONEq(t, `{"valid": true}`, string(output))
})

t.Run("with an error response is an error", func(t *testing.T) {
client := flags.MockClient{}
client.
Expand Down
24 changes: 22 additions & 2 deletions cmd/flags/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestUpdate(t *testing.T) {
},
},
}
t.Run("with valid flags calls projects API", func(t *testing.T) {
t.Run("with valid flags calls API", func(t *testing.T) {
client := flags.MockClient{}
client.
On("Update", mockArgs...).
Expand All @@ -46,6 +46,26 @@ func TestUpdate(t *testing.T) {
assert.JSONEq(t, `{"valid": true}`, string(output))
})

t.Run("with valid flags from environment variables calls API", func(t *testing.T) {
teardownTest := cmd.SetupTestEnvVars(t)
defer teardownTest(t)
client := flags.MockClient{}
client.
On("Update", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
args := []string{
"flags", "update",
"-d", `[{"op": "replace", "path": "/name", "value": "new-name"}]`,
"--flag", "test-key",
"--project", "test-proj-key",
}

output, err := cmd.CallCmd(t, nil, &client, nil, nil, args)

require.NoError(t, err)
assert.JSONEq(t, `{"valid": true}`, string(output))
})

t.Run("with an error response is an error", func(t *testing.T) {
client := flags.MockClient{}
client.
Expand Down Expand Up @@ -105,7 +125,7 @@ func TestToggle(t *testing.T) {
},
},
}
t.Run("with valid flags calls projects API", func(t *testing.T) {
t.Run("with valid flags calls API", func(t *testing.T) {
client := flags.MockClient{}
client.
On("Update", mockArgs...).
Expand Down
36 changes: 28 additions & 8 deletions cmd/members/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ func TestCreate(t *testing.T) {
"http://test.com",
[]members.MemberInput{{Email: "testemail@test.com", Role: role}},
}

t.Run("with valid flags calls members API", func(t *testing.T) {
client := members.MockClient{}
client.
Expand All @@ -27,10 +28,31 @@ func TestCreate(t *testing.T) {
args := []string{
"members",
"create",
"--access-token",
"testAccessToken",
"--base-uri",
"http://test.com",
"--access-token", "testAccessToken",
"--base-uri", "http://test.com",
"-d",
`[{"email": "testemail@test.com", "role": "writer"}]`,
}

output, err := cmd.CallCmd(t, nil, nil, &client, nil, args)

require.NoError(t, err)
assert.JSONEq(t, `{"valid": true}`, string(output))
})

t.Run("with valid flags from environment variables calls API", func(t *testing.T) {
teardownTest := cmd.SetupTestEnvVars(t)
defer teardownTest(t)
client := members.MockClient{}
client.
On("Update", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
client.
On("Create", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
args := []string{
"members",
"create",
"-d",
`[{"email": "testemail@test.com", "role": "writer"}]`,
}
Expand All @@ -49,10 +71,8 @@ func TestCreate(t *testing.T) {
args := []string{
"members",
"create",
"--access-token",
"testAccessToken",
"--base-uri",
"http://test.com",
"--access-token", "testAccessToken",
"--base-uri", "http://test.com",
"-d",
`[{"email": "testemail@test.com", "role": "writer"}]`,
}
Expand Down
37 changes: 29 additions & 8 deletions cmd/members/invite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func TestInvite(t *testing.T) {
{Email: "testemail2@test.com", Role: readerRole},
},
}

t.Run("with valid flags calls members API", func(t *testing.T) {
client := members.MockClient{}
client.
Expand All @@ -30,10 +31,31 @@ func TestInvite(t *testing.T) {
args := []string{
"members",
"invite",
"--access-token",
"testAccessToken",
"--base-uri",
"http://test.com",
"--access-token", "testAccessToken",
"--base-uri", "http://test.com",
"-e",
`testemail1@test.com,testemail2@test.com`,
}

output, err := cmd.CallCmd(t, nil, nil, &client, nil, args)

require.NoError(t, err)
assert.JSONEq(t, `{"valid": true}`, string(output))
})

t.Run("with valid flags from environment variables calls API", func(t *testing.T) {
teardownTest := cmd.SetupTestEnvVars(t)
defer teardownTest(t)
client := members.MockClient{}
client.
On("Update", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
client.
On("Create", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
args := []string{
"members",
"invite",
"-e",
`testemail1@test.com,testemail2@test.com`,
}
Expand All @@ -52,10 +74,8 @@ func TestInvite(t *testing.T) {
args := []string{
"members",
"invite",
"--access-token",
"testAccessToken",
"--base-uri",
"http://test.com",
"--access-token", "testAccessToken",
"--base-uri", "http://test.com",
"-e",
`testemail1@test.com,testemail2@test.com`,
}
Expand Down Expand Up @@ -99,6 +119,7 @@ func TestInviteWithOptionalRole(t *testing.T) {
{Email: "testemail2@test.com", Role: writerRole},
},
}

t.Run("with valid optional long form flag calls members API", func(t *testing.T) {
client := members.MockClient{}
client.
Expand Down
29 changes: 24 additions & 5 deletions cmd/projects/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,37 @@ func TestCreate(t *testing.T) {
"test-name",
"test-key",
}
t.Run("with valid flags calls projects API", func(t *testing.T) {

t.Run("with valid flags calls API", func(t *testing.T) {
client := projects.MockClient{}
client.
On("Create", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
args := []string{
"projects",
"create",
"--access-token", "testAccessToken",
"--base-uri", "http://test.com",
"-d",
`{"key": "test-key", "name": "test-name"}`,
}

output, err := cmd.CallCmd(t, nil, nil, nil, &client, args)

require.NoError(t, err)
assert.JSONEq(t, `{"valid": true}`, string(output))
})

t.Run("with valid flags from environment variables calls API", func(t *testing.T) {
teardownTest := cmd.SetupTestEnvVars(t)
defer teardownTest(t)
client := projects.MockClient{}
client.
On("Create", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
args := []string{
"projects",
"create",
"--access-token",
"testAccessToken",
"--base-uri",
"http://test.com",
"-d",
`{"key": "test-key", "name": "test-name"}`,
}
Expand Down
20 changes: 19 additions & 1 deletion cmd/projects/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestList(t *testing.T) {
"testAccessToken",
"http://test.com",
}
t.Run("with valid flags calls projects API", func(t *testing.T) {
t.Run("with valid flags calls API", func(t *testing.T) {
client := projects.MockClient{}
client.
On("List", mockArgs...).
Expand All @@ -34,6 +34,24 @@ func TestList(t *testing.T) {
assert.JSONEq(t, `{"valid": true}`, string(output))
})

t.Run("with valid flags from environment variables calls API", func(t *testing.T) {
teardownTest := cmd.SetupTestEnvVars(t)
defer teardownTest(t)
client := projects.MockClient{}
client.
On("List", mockArgs...).
Return([]byte(cmd.ValidResponse), nil)
args := []string{
"projects",
"list",
}

output, err := cmd.CallCmd(t, nil, nil, nil, &client, args)

require.NoError(t, err)
assert.JSONEq(t, `{"valid": true}`, string(output))
})

t.Run("with an error response is an error", func(t *testing.T) {
client := projects.MockClient{}
client.
Expand Down
2 changes: 2 additions & 0 deletions cmd/quickstart.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/spf13/viper"

"ldcli/cmd/cliflags"
"ldcli/cmd/validators"
"ldcli/internal/environments"
"ldcli/internal/flags"
"ldcli/internal/quickstart"
Expand All @@ -20,6 +21,7 @@ func NewQuickStartCmd(
flagsClient flags.Client,
) *cobra.Command {
return &cobra.Command{
Args: validators.Validate(),
Long: "",
RunE: runQuickStart(environmentsClient, flagsClient),
Short: "Setup guide to create your first feature flag",
Expand Down
Loading

0 comments on commit b0380ca

Please sign in to comment.