From 75074877892fa472f091c3f51e9459ec341c292f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ra=C3=BAl=20Barroso?= Date: Thu, 30 Jan 2025 12:50:33 +0100 Subject: [PATCH] test procesor plugins ls --- .../internal/testutils/mock_helpers.go | 27 +--- .../root/processorplugins/describe_test.go | 30 +++- cmd/conduit/root/processorplugins/list.go | 16 +- .../root/processorplugins/list_test.go | 140 ++++++++++++++++++ 4 files changed, 182 insertions(+), 31 deletions(-) diff --git a/cmd/conduit/internal/testutils/mock_helpers.go b/cmd/conduit/internal/testutils/mock_helpers.go index 5b78c4a70..0782bba67 100644 --- a/cmd/conduit/internal/testutils/mock_helpers.go +++ b/cmd/conduit/internal/testutils/mock_helpers.go @@ -93,34 +93,11 @@ func MockGetProcessors(mockService *mock.MockProcessorService, processors []*api }, nil).Times(1) } -func MockGetProcessorPlugins(mockservice *mock.MockProcessorService, name string) { +func MockGetProcessorPlugins(mockservice *mock.MockProcessorService, name string, plugins []*apiv1.ProcessorPluginSpecifications) { mockservice.EXPECT().ListProcessorPlugins(gomock.Any(), &apiv1.ListProcessorPluginsRequest{ Name: name, }).Return(&apiv1.ListProcessorPluginsResponse{ - Plugins: []*apiv1.ProcessorPluginSpecifications{ - { - Name: name, - Summary: "Encode a field to base64", - Description: "The processor will encode the value of the target field to base64 and store the\n" + - "result in the target field. It is not allowed to encode the `.Position` field.\n" + - "If the provided field doesn't exist, the processor will create that field and\n" + - "assign its value. Field is a reference to the target field. " + - "Note that it is not allowed to base64 encode. `.Position` field. ", - Author: "Meroxa, Inc.", - Version: "v0.1.0", - Parameters: map[string]*configv1.Parameter{ - "field": { - Type: configv1.Parameter_Type(apiv1.PluginSpecifications_Parameter_TYPE_STRING), - Description: "Field is a reference to the target field", - Default: "", - Validations: []*configv1.Validation{ - {Type: configv1.Validation_TYPE_REQUIRED}, - {Type: configv1.Validation_TYPE_EXCLUSION}, - }, - }, - }, - }, - }, + Plugins: plugins, }, nil).Times(1) } diff --git a/cmd/conduit/root/processorplugins/describe_test.go b/cmd/conduit/root/processorplugins/describe_test.go index bc6010960..0c601dd67 100644 --- a/cmd/conduit/root/processorplugins/describe_test.go +++ b/cmd/conduit/root/processorplugins/describe_test.go @@ -20,9 +20,11 @@ import ( "strings" "testing" + configv1 "github.com/conduitio/conduit-commons/proto/config/v1" "github.com/conduitio/conduit/cmd/conduit/api" "github.com/conduitio/conduit/cmd/conduit/api/mock" "github.com/conduitio/conduit/cmd/conduit/internal/testutils" + apiv1 "github.com/conduitio/conduit/proto/api/v1" "github.com/conduitio/ecdysis" "github.com/matryer/is" "go.uber.org/mock/gomock" @@ -79,7 +81,33 @@ func TestDescribeCommand_ExecuteWithClient(t *testing.T) { mockProcessorService := mock.NewMockProcessorService(ctrl) - testutils.MockGetProcessorPlugins(mockProcessorService, cmd.args.processorPluginID) + testutils.MockGetProcessorPlugins( + mockProcessorService, + cmd.args.processorPluginID, + []*apiv1.ProcessorPluginSpecifications{ + { + Name: cmd.args.processorPluginID, + Summary: "Encode a field to base64", + Description: "The processor will encode the value of the target field to base64 and store the\n" + + "result in the target field. It is not allowed to encode the `.Position` field.\n" + + "If the provided field doesn't exist, the processor will create that field and\n" + + "assign its value. Field is a reference to the target field. " + + "Note that it is not allowed to base64 encode. `.Position` field. ", + Author: "Meroxa, Inc.", + Version: "v0.1.0", + Parameters: map[string]*configv1.Parameter{ + "field": { + Type: configv1.Parameter_Type(apiv1.PluginSpecifications_Parameter_TYPE_STRING), + Description: "Field is a reference to the target field", + Default: "", + Validations: []*configv1.Validation{ + {Type: configv1.Validation_TYPE_REQUIRED}, + {Type: configv1.Validation_TYPE_EXCLUSION}, + }, + }, + }, + }, + }) client := &api.Client{ ProcessorServiceClient: mockProcessorService, diff --git a/cmd/conduit/root/processorplugins/list.go b/cmd/conduit/root/processorplugins/list.go index 2e44b8474..26f75ee25 100644 --- a/cmd/conduit/root/processorplugins/list.go +++ b/cmd/conduit/root/processorplugins/list.go @@ -31,6 +31,7 @@ var ( _ ecdysis.CommandWithDocs = (*ListCommand)(nil) _ ecdysis.CommandWithFlags = (*ListCommand)(nil) _ cecdysis.CommandWithExecuteWithClient = (*ListCommand)(nil) + _ ecdysis.CommandWithOutput = (*ListCommand)(nil) ) type ListFlags struct { @@ -38,7 +39,12 @@ type ListFlags struct { } type ListCommand struct { - flags ListFlags + flags ListFlags + output ecdysis.Output +} + +func (c *ListCommand) Output(output ecdysis.Output) { + c.output = output } func (c *ListCommand) Flags() []ecdysis.Flag { @@ -71,14 +77,14 @@ func (c *ListCommand) ExecuteWithClient(ctx context.Context, client *api.Client) return resp.Plugins[i].Name < resp.Plugins[j].Name }) - displayProcessorPlugins(resp.Plugins) + c.output.Stdout(getProcessorPluginsTable(resp.Plugins) + "\n") return nil } -func displayProcessorPlugins(processorPlugins []*apiv1.ProcessorPluginSpecifications) { +func getProcessorPluginsTable(processorPlugins []*apiv1.ProcessorPluginSpecifications) string { if len(processorPlugins) == 0 { - return + return "" } table := simpletable.New() @@ -98,5 +104,5 @@ func displayProcessorPlugins(processorPlugins []*apiv1.ProcessorPluginSpecificat table.Body.Cells = append(table.Body.Cells, r) } - fmt.Println(table.String()) + return table.String() } diff --git a/cmd/conduit/root/processorplugins/list_test.go b/cmd/conduit/root/processorplugins/list_test.go index 8e95156f2..da578e6ad 100644 --- a/cmd/conduit/root/processorplugins/list_test.go +++ b/cmd/conduit/root/processorplugins/list_test.go @@ -15,11 +15,19 @@ package processorplugins import ( + "bytes" + "context" + "strings" "testing" + "github.com/conduitio/conduit/cmd/conduit/api" + "github.com/conduitio/conduit/cmd/conduit/api/mock" + "github.com/conduitio/conduit/cmd/conduit/internal/testutils" + apiv1 "github.com/conduitio/conduit/proto/api/v1" "github.com/conduitio/ecdysis" "github.com/matryer/is" "github.com/spf13/pflag" + "go.uber.org/mock/gomock" ) func TestListCommandFlags(t *testing.T) { @@ -54,3 +62,135 @@ func TestListCommandFlags(t *testing.T) { is.Equal(cf.Usage, f.usage) } } + +func TestListCommandExecuteWithClient_WithFlags(t *testing.T) { + is := is.New(t) + + buf := new(bytes.Buffer) + out := &ecdysis.DefaultOutput{} + out.Output(buf, nil) + + cmd := &ListCommand{ + flags: ListFlags{ + Name: "builtin", + }, + } + cmd.Output(out) + + ctx := context.Background() + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockService := mock.NewMockProcessorService(ctrl) + + testutils.MockGetProcessorPlugins( + mockService, + ".*builtin.*", + []*apiv1.ProcessorPluginSpecifications{ + { + Name: "builtin:avro.decode@v0.1.0", + Summary: "Decodes a field's raw data in the Avro format.", + }, + { + Name: "builtin:avro.encode@v0.1.0", + Summary: "Encodes a record's field into the Avro format.", + }, + }) + + client := &api.Client{ProcessorServiceClient: mockService} + + err := cmd.ExecuteWithClient(ctx, client) + is.NoErr(err) + + output := strings.TrimSpace(buf.String()) + is.True(len(output) > 0) + + is.True(strings.Contains(output, ""+ + "+----------------------------+------------------------------------------------+\n"+ + "| NAME | SUMMARY |\n"+ + "+----------------------------+------------------------------------------------+\n"+ + "| builtin:avro.decode@v0.1.0 | Decodes a field's raw data in the Avro format. |\n"+ + "| builtin:avro.encode@v0.1.0 | Encodes a record's field into the Avro format. |\n"+ + "+----------------------------+------------------------------------------------+")) +} + +func TestListCommandExecuteWithClient_NoFlags(t *testing.T) { + is := is.New(t) + + buf := new(bytes.Buffer) + out := &ecdysis.DefaultOutput{} + out.Output(buf, nil) + + cmd := &ListCommand{} + cmd.Output(out) + + ctx := context.Background() + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockService := mock.NewMockProcessorService(ctrl) + + testutils.MockGetProcessorPlugins( + mockService, + ".*.*", + []*apiv1.ProcessorPluginSpecifications{ + { + Name: "builtin:avro.decode@v0.1.0", + Summary: "Decodes a field's raw data in the Avro format.", + }, + { + Name: "builtin:avro.encode@v0.1.0", + Summary: "Encodes a record's field into the Avro format.", + }, + { + Name: "standalone:processor-simple", + Summary: "Example of a standalone processor.", + }, + }) + + client := &api.Client{ProcessorServiceClient: mockService} + + err := cmd.ExecuteWithClient(ctx, client) + is.NoErr(err) + + output := strings.TrimSpace(buf.String()) + is.True(len(output) > 0) + + is.True(strings.Contains(output, ""+ + "+-----------------------------+------------------------------------------------+\n"+ + "| NAME | SUMMARY |\n"+ + "+-----------------------------+------------------------------------------------+\n"+ + "| builtin:avro.decode@v0.1.0 | Decodes a field's raw data in the Avro format. |\n"+ + "| builtin:avro.encode@v0.1.0 | Encodes a record's field into the Avro format. |\n"+ + "| standalone:processor-simple | Example of a standalone processor. |\n"+ + "+-----------------------------+------------------------------------------------+")) +} + +func TestListCommandExecuteWithClient_EmptyResponse(t *testing.T) { + is := is.New(t) + + buf := new(bytes.Buffer) + out := &ecdysis.DefaultOutput{} + out.Output(buf, nil) + + ctx := context.Background() + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockService := mock.NewMockProcessorService(ctrl) + + testutils.MockGetProcessorPlugins( + mockService, + ".*.*", + []*apiv1.ProcessorPluginSpecifications{}) + + client := &api.Client{ProcessorServiceClient: mockService} + cmd := &ListCommand{} + cmd.Output(out) + + err := cmd.ExecuteWithClient(ctx, client) + is.NoErr(err) + + output := strings.TrimSpace(buf.String()) + is.True(len(output) == 0) +}