Skip to content

Commit

Permalink
add pss request feedback command, update output to serialize pss mode…
Browse files Browse the repository at this point in the history
…ls (#106)
  • Loading branch information
0x4c6565 committed Jun 17, 2021
1 parent 6e73ea6 commit 35d3c21
Show file tree
Hide file tree
Showing 7 changed files with 328 additions and 51 deletions.
53 changes: 5 additions & 48 deletions cmd/pss/output.go
Original file line number Diff line number Diff line change
@@ -1,61 +1,18 @@
package pss

import (
"strconv"

"github.com/ukfast/cli/internal/pkg/output"
"github.com/ukfast/sdk-go/pkg/service/pss"
)

func OutputPSSRequestsProvider(requests []pss.Request) output.OutputHandlerDataProvider {
return output.NewGenericOutputHandlerDataProvider(
output.WithData(requests),
output.WithFieldDataFunc(func() ([]*output.OrderedFields, error) {
var data []*output.OrderedFields
for _, request := range requests {
fields := output.NewOrderedFields()
fields.Set("id", output.NewFieldValue(strconv.Itoa(request.ID), true))
fields.Set("author_id", output.NewFieldValue(strconv.Itoa(request.Author.ID), false))
fields.Set("author_name", output.NewFieldValue(request.Author.Name, true))
fields.Set("type", output.NewFieldValue(request.Type, true))
fields.Set("secure", output.NewFieldValue(strconv.FormatBool(request.Secure), false))
fields.Set("subject", output.NewFieldValue(request.Subject, true))
fields.Set("created_at", output.NewFieldValue(request.CreatedAt.String(), true))
fields.Set("priority", output.NewFieldValue(request.Priority.String(), false))
fields.Set("archived", output.NewFieldValue(strconv.FormatBool(request.Archived), false))
fields.Set("status", output.NewFieldValue(request.Status.String(), true))
fields.Set("request_sms", output.NewFieldValue(strconv.FormatBool(request.RequestSMS), false))
fields.Set("version", output.NewFieldValue(strconv.Itoa(request.Version), false))
fields.Set("customer_reference", output.NewFieldValue(request.CustomerReference, false))
fields.Set("last_replied_at", output.NewFieldValue(request.LastRepliedAt.String(), true))
fields.Set("product_id", output.NewFieldValue(strconv.Itoa(request.Product.ID), false))
fields.Set("product_name", output.NewFieldValue(request.Product.Name, false))
fields.Set("product_type", output.NewFieldValue(request.Product.Type, false))

data = append(data, fields)
}

return data, nil
}),
)
return output.NewSerializedOutputHandlerDataProvider(requests).WithDefaultFields([]string{"id", "author_name", "type", "subject", "status", "last_replied_at", "created_at"})
}

func OutputPSSRepliesProvider(replies []pss.Reply) output.OutputHandlerDataProvider {
return output.NewGenericOutputHandlerDataProvider(
output.WithData(replies),
output.WithFieldDataFunc(func() ([]*output.OrderedFields, error) {
var data []*output.OrderedFields
for _, reply := range replies {
fields := output.NewOrderedFields()
fields.Set("id", output.NewFieldValue(reply.ID, true))
fields.Set("author_name", output.NewFieldValue(reply.Author.Name, true))
fields.Set("description", output.NewFieldValue(reply.Description, false))
fields.Set("created_at", output.NewFieldValue(reply.CreatedAt.String(), true))

data = append(data, fields)
}
return output.NewSerializedOutputHandlerDataProvider(replies).WithDefaultFields([]string{"id", "author_name", "created_at"})
}

return data, nil
}),
)
func OutputPSSFeedbackProvider(feedback []pss.Feedback) output.OutputHandlerDataProvider {
return output.NewSerializedOutputHandlerDataProvider(feedback).WithDefaultFields([]string{"id", "score", "created_at"})
}
1 change: 1 addition & 0 deletions cmd/pss/pss_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ func pssRequestRootCmd(f factory.ClientFactory) *cobra.Command {

// Child root commands
cmd.AddCommand(pssRequestReplyRootCmd(f))
cmd.AddCommand(pssRequestFeedbackRootCmd(f))

return cmd
}
Expand Down
133 changes: 133 additions & 0 deletions cmd/pss/pss_request_feedback.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package pss

import (
"errors"
"fmt"
"strconv"

"github.com/spf13/cobra"
"github.com/ukfast/cli/internal/pkg/factory"
"github.com/ukfast/cli/internal/pkg/output"
"github.com/ukfast/sdk-go/pkg/service/pss"
)

func pssRequestFeedbackRootCmd(f factory.ClientFactory) *cobra.Command {
cmd := &cobra.Command{
Use: "feedback",
Short: "sub-commands relating to request feedback",
}

// Child commands
cmd.AddCommand(pssRequestFeedbackShowCmd(f))
cmd.AddCommand(pssRequestFeedbackCreateCmd(f))

return cmd
}

func pssRequestFeedbackShowCmd(f factory.ClientFactory) *cobra.Command {
return &cobra.Command{
Use: "show <request: id>...",
Short: "Shows feedback for a request",
Long: "This command shows feedback for one or more requests",
Example: "ukfast pss request feedback show 123",
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return errors.New("Missing request")
}

return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
c, err := f.NewClient()
if err != nil {
return err
}

return pssRequestFeedbackShow(c.PSSService(), cmd, args)
},
}
}

func pssRequestFeedbackShow(service pss.PSSService, cmd *cobra.Command, args []string) error {
var feedbacks []pss.Feedback
for _, arg := range args {
requestID, err := strconv.Atoi(arg)
if err != nil {
output.OutputWithErrorLevelf("Invalid request ID [%s]", arg)
continue
}

feedback, err := service.GetRequestFeedback(requestID)
if err != nil {
output.OutputWithErrorLevelf("Error retrieving feedback for request [%s]: %s", arg, err)
continue
}

feedbacks = append(feedbacks, feedback)
}

return output.CommandOutput(cmd, OutputPSSFeedbackProvider(feedbacks))
}

func pssRequestFeedbackCreateCmd(f factory.ClientFactory) *cobra.Command {
cmd := &cobra.Command{
Use: "create <request: id>",
Short: "Creates feedback for a request",
Long: "This command creates feedback for a request",
Example: "ukfast pss request feedback create 123",
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return errors.New("Missing request")
}

return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
c, err := f.NewClient()
if err != nil {
return err
}

return pssRequestFeedbackCreate(c.PSSService(), cmd, args)
},
}

cmd.Flags().Int("contact", 0, "Specifies contact ID")
cmd.MarkFlagRequired("contact")
cmd.Flags().Int("score", 0, "Specifies feedback score")
cmd.Flags().String("comment", "", "Specifies feedback comment")
cmd.Flags().Int("speed-resolved", 0, "Specifies feedback speed resolved score")
cmd.Flags().Int("quality", 0, "Specifies feedback quality")
cmd.Flags().Int("nps-score", 0, "Specifies feedback NPS score")
cmd.Flags().Bool("thirdparty-consent", false, "Specifies feedback third party consent")

return cmd
}

func pssRequestFeedbackCreate(service pss.PSSService, cmd *cobra.Command, args []string) error {
requestID, err := strconv.Atoi(args[0])
if err != nil {
return fmt.Errorf("Invalid request ID [%s]", args[0])
}

createRequest := pss.CreateFeedbackRequest{}
createRequest.ContactID, _ = cmd.Flags().GetInt("contact")
createRequest.Score, _ = cmd.Flags().GetInt("score")
createRequest.Comment, _ = cmd.Flags().GetString("comment")
createRequest.SpeedResolved, _ = cmd.Flags().GetInt("speed-resolved")
createRequest.Quality, _ = cmd.Flags().GetInt("quality")
createRequest.NPSScore, _ = cmd.Flags().GetInt("nps-score")
createRequest.ThirdPartyConsent, _ = cmd.Flags().GetBool("thirdparty-consent")

_, err = service.CreateRequestFeedback(requestID, createRequest)
if err != nil {
return fmt.Errorf("Error creating feedback for request: %s", err)
}

feedback, err := service.GetRequestFeedback(requestID)
if err != nil {
return fmt.Errorf("Error retrieving new feedback for request: %s", err)
}

return output.CommandOutput(cmd, OutputPSSFeedbackProvider([]pss.Feedback{feedback}))
}
156 changes: 156 additions & 0 deletions cmd/pss/pss_request_feedback_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package pss

import (
"errors"
"testing"

gomock "github.com/golang/mock/gomock"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/ukfast/cli/test/mocks"
"github.com/ukfast/cli/test/test_output"
"github.com/ukfast/sdk-go/pkg/service/pss"
)

func Test_pssRequestFeedbackShowCmd_Args(t *testing.T) {
t.Run("ValidArgs_NoError", func(t *testing.T) {
err := pssRequestFeedbackShowCmd(nil).Args(nil, []string{"123"})

assert.Nil(t, err)
})

t.Run("InvalidArgs_Error", func(t *testing.T) {
err := pssRequestFeedbackShowCmd(nil).Args(nil, []string{})

assert.NotNil(t, err)
assert.Equal(t, "Missing request", err.Error())
})
}

func Test_pssRequestFeedbackShow(t *testing.T) {
t.Run("SingleRequest", func(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

service := mocks.NewMockPSSService(mockCtrl)

service.EXPECT().GetRequestFeedback(123).Return(pss.Feedback{}, nil).Times(1)

pssRequestFeedbackShow(service, &cobra.Command{}, []string{"123"})
})

t.Run("MultipleRequests", func(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

service := mocks.NewMockPSSService(mockCtrl)

gomock.InOrder(
service.EXPECT().GetRequestFeedback(123).Return(pss.Feedback{}, nil),
service.EXPECT().GetRequestFeedback(456).Return(pss.Feedback{}, nil),
)

pssRequestFeedbackShow(service, &cobra.Command{}, []string{"123", "456"})
})

t.Run("GetRequestID_OutputsError", func(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

service := mocks.NewMockPSSService(mockCtrl)

test_output.AssertErrorOutput(t, "Invalid request ID [abc]\n", func() {
pssRequestFeedbackShow(service, &cobra.Command{}, []string{"abc"})
})
})

t.Run("GetRequestError_OutputsError", func(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

service := mocks.NewMockPSSService(mockCtrl)

service.EXPECT().GetRequestFeedback(123).Return(pss.Feedback{}, errors.New("test error"))

test_output.AssertErrorOutput(t, "Error retrieving feedback for request [123]: test error\n", func() {
pssRequestFeedbackShow(service, &cobra.Command{}, []string{"123"})
})
})
}

func Test_pssRequestFeedbackCreateCmd_Args(t *testing.T) {
t.Run("ValidArgs_NoError", func(t *testing.T) {
err := pssRequestFeedbackCreateCmd(nil).Args(nil, []string{"123"})

assert.Nil(t, err)
})

t.Run("InvalidArgs_Error", func(t *testing.T) {
err := pssRequestFeedbackCreateCmd(nil).Args(nil, []string{})

assert.NotNil(t, err)
assert.Equal(t, "Missing request", err.Error())
})
}

func Test_pssRequestFeedbackCreate(t *testing.T) {
t.Run("DefaultCreate", func(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

service := mocks.NewMockPSSService(mockCtrl)
cmd := pssRequestFeedbackCreateCmd(nil)
cmd.ParseFlags([]string{"--contact=1"})

expectedRequest := pss.CreateFeedbackRequest{
ContactID: 1,
}

gomock.InOrder(
service.EXPECT().CreateRequestFeedback(123, gomock.Eq(expectedRequest)).Return(123, nil),
service.EXPECT().GetRequestFeedback(123).Return(pss.Feedback{}, nil),
)

pssRequestFeedbackCreate(service, cmd, []string{"123"})
})

t.Run("InvalidRequestID_ReturnsError", func(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

service := mocks.NewMockPSSService(mockCtrl)
cmd := pssRequestFeedbackCreateCmd(nil)

err := pssRequestFeedbackCreate(service, cmd, []string{"invalid"})
assert.Contains(t, err.Error(), "Invalid request ID [invalid]")
})

t.Run("CreateRequestFeedbackError_ReturnsError", func(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

service := mocks.NewMockPSSService(mockCtrl)
cmd := pssRequestFeedbackCreateCmd(nil)

service.EXPECT().CreateRequestFeedback(123, gomock.Any()).Return(0, errors.New("test error")).Times(1)

err := pssRequestFeedbackCreate(service, cmd, []string{"123"})
assert.Equal(t, "Error creating feedback for request: test error", err.Error())
})

t.Run("GetRequestError_ReturnsError", func(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()

service := mocks.NewMockPSSService(mockCtrl)
cmd := pssRequestFeedbackCreateCmd(nil)

gomock.InOrder(
service.EXPECT().CreateRequestFeedback(123, gomock.Any()).Return(123, nil),
service.EXPECT().GetRequestFeedback(123).Return(pss.Feedback{}, errors.New("test error")),
)

err := pssRequestFeedbackCreate(service, cmd, []string{"123"})
assert.Equal(t, "Error retrieving new feedback for request: test error", err.Error())
})
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ require (
github.com/spf13/cobra v0.0.5
github.com/spf13/viper v1.3.2
github.com/stretchr/testify v1.6.1
github.com/ukfast/sdk-go v1.4.4
github.com/ukfast/sdk-go v1.4.5
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b // indirect
gopkg.in/go-playground/assert.v1 v1.2.1
k8s.io/client-go v11.0.0+incompatible
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ github.com/tcnksm/go-gitconfig v0.1.2/go.mod h1:/8EhP4H7oJZdIPyT+/UIsG87kTzrzM4U
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ukfast/go-durationstring v1.0.0 h1:kgPuA7XjLjgLDfkG8j0MpolxcZh/eMdiVoOIFD/uc5I=
github.com/ukfast/go-durationstring v1.0.0/go.mod h1:Ci81n51kfxlKUIaLY9cINIKRO94VTqV+iCGbOMTb0V8=
github.com/ukfast/sdk-go v1.4.4 h1:z/B6mM3RezDi9+BWQuZ4LXrhvWPta1vsa+KSTXtuCIo=
github.com/ukfast/sdk-go v1.4.4/go.mod h1:tspweEP77MHhVEYgEEieKAKGITFgwkYl1q5fLh4HZAo=
github.com/ukfast/sdk-go v1.4.5 h1:O2VvIMulQ1P3KL3xzg7INpmwuCWtLB4NBdqDf14gn00=
github.com/ukfast/sdk-go v1.4.5/go.mod h1:tspweEP77MHhVEYgEEieKAKGITFgwkYl1q5fLh4HZAo=
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
Expand Down
Loading

0 comments on commit 35d3c21

Please sign in to comment.