package controllers_test import ( "fmt" tea "github.com/charmbracelet/bubbletea" "github.com/lmika/awstools/internal/common/ui/events" "github.com/lmika/awstools/internal/dynamo-browse/controllers" "github.com/lmika/awstools/internal/dynamo-browse/providers/dynamo" "github.com/lmika/awstools/internal/dynamo-browse/services/tables" "github.com/lmika/awstools/test/testdynamo" "github.com/stretchr/testify/assert" "os" "strings" "testing" ) func TestTableReadController_InitTable(t *testing.T) { client, cleanupFn := testdynamo.SetupTestTable(t, testData) defer cleanupFn() provider := dynamo.NewProvider(client) service := tables.NewService(provider) t.Run("should prompt for table if no table name provided", func(t *testing.T) { readController := controllers.NewTableReadController(controllers.NewState(), service, "") cmd := readController.Init() event := cmd() assert.IsType(t, controllers.PromptForTableMsg{}, event) }) t.Run("should scan table if table name provided", func(t *testing.T) { readController := controllers.NewTableReadController(controllers.NewState(), service, "") cmd := readController.Init() event := cmd() assert.IsType(t, controllers.PromptForTableMsg{}, event) }) } func TestTableReadController_ListTables(t *testing.T) { client, cleanupFn := testdynamo.SetupTestTable(t, testData) defer cleanupFn() provider := dynamo.NewProvider(client) service := tables.NewService(provider) readController := controllers.NewTableReadController(controllers.NewState(), service, "") t.Run("returns a list of tables", func(t *testing.T) { cmd := readController.ListTables() event := cmd().(controllers.PromptForTableMsg) assert.Equal(t, []string{"alpha-table", "bravo-table"}, event.Tables) selectedCmd := event.OnSelected("alpha-table") selectedEvent := selectedCmd() resultSet := selectedEvent.(controllers.NewResultSet) assert.Equal(t, "alpha-table", resultSet.ResultSet.TableInfo.Name) assert.Equal(t, "pk", resultSet.ResultSet.TableInfo.Keys.PartitionKey) assert.Equal(t, "sk", resultSet.ResultSet.TableInfo.Keys.SortKey) }) } func TestTableReadController_ExportCSV(t *testing.T) { client, cleanupFn := testdynamo.SetupTestTable(t, testData) defer cleanupFn() provider := dynamo.NewProvider(client) service := tables.NewService(provider) readController := controllers.NewTableReadController(controllers.NewState(), service, "alpha-table") t.Run("should export result set to CSV file", func(t *testing.T) { tempFile := tempFile(t) invokeCommand(t, readController.Init()) invokeCommand(t, readController.ExportCSV(tempFile)) bts, err := os.ReadFile(tempFile) assert.NoError(t, err) assert.Equal(t, string(bts), strings.Join([]string{ "pk,sk,alpha,beta,gamma\n", "abc,111,This is some value,,\n", "abc,222,This is another some value,1231,\n", "bbb,131,,2468,foobar\n", }, "")) }) t.Run("should return error if result set is not set", func(t *testing.T) { tempFile := tempFile(t) readController := controllers.NewTableReadController(controllers.NewState(), service, "non-existant-table") invokeCommandExpectingError(t, readController.Init()) invokeCommandExpectingError(t, readController.ExportCSV(tempFile)) }) // Hidden items? } func tempFile(t *testing.T) string { t.Helper() tempFile, err := os.CreateTemp("", "export.csv") assert.NoError(t, err) tempFile.Close() t.Cleanup(func() { os.Remove(tempFile.Name()) }) return tempFile.Name() } func invokeCommand(t *testing.T, cmd tea.Cmd) tea.Msg { msg := cmd() err, isErr := msg.(events.ErrorMsg) if isErr { assert.Fail(t, fmt.Sprintf("expected no error but got one: %v", err)) } return msg } func invokeCommandWithPrompt(t *testing.T, cmd tea.Cmd, promptValue string) { msg := cmd() pi, isPi := msg.(events.PromptForInputMsg) if !isPi { assert.Fail(t, fmt.Sprintf("expected prompt for input but didn't get one")) } invokeCommand(t, pi.OnDone(promptValue)) } func invokeCommandWithPrompts(t *testing.T, cmd tea.Cmd, promptValues ...string) { msg := cmd() for _, promptValue := range promptValues { pi, isPi := msg.(events.PromptForInputMsg) if !isPi { assert.Fail(t, fmt.Sprintf("expected prompt for input but didn't get one")) } msg = invokeCommand(t, pi.OnDone(promptValue)) } } func invokeCommandWithPromptsExpectingError(t *testing.T, cmd tea.Cmd, promptValues ...string) { msg := cmd() for _, promptValue := range promptValues { pi, isPi := msg.(events.PromptForInputMsg) if !isPi { assert.Fail(t, fmt.Sprintf("expected prompt for input but didn't get one")) } msg = invokeCommand(t, pi.OnDone(promptValue)) } _, isErr := msg.(events.ErrorMsg) assert.True(t, isErr) } func invokeCommandExpectingError(t *testing.T, cmd tea.Cmd) { msg := cmd() _, isErr := msg.(events.ErrorMsg) assert.True(t, isErr) } var testData = []testdynamo.TestData{ { TableName: "alpha-table", Data: []map[string]interface{}{ { "pk": "abc", "sk": "111", "alpha": "This is some value", }, { "pk": "abc", "sk": "222", "alpha": "This is another some value", "beta": 1231, }, { "pk": "bbb", "sk": "131", "beta": 2468, "gamma": "foobar", }, }, }, { TableName: "bravo-table", Data: []map[string]interface{}{ { "pk": "foo", "sk": "bar", "alpha": "This is some value", }, { "pk": "abc", "sk": "222", "alpha": "This is another some value", "beta": 1231, }, { "pk": "bbb", "sk": "131", "beta": 2468, "gamma": "foobar", }, }, }, }