Skip to content

Commit

Permalink
Merge pull request #60 from calvinmclean/fix/15/get-all-client
Browse files Browse the repository at this point in the history
Add more flexible Client methods and make CLI more generic
  • Loading branch information
calvinmclean committed Apr 24, 2024
2 parents c4d3d70 + ef520d0 commit 86a1c7b
Show file tree
Hide file tree
Showing 11 changed files with 358 additions and 461 deletions.
6 changes: 5 additions & 1 deletion babyapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import (
"github.com/go-chi/render"
)

// MethodGetAll is the same as http.MethodGet, but can be used when setting custom response codes
const MethodGetAll = "GetAll"

// API encapsulates all handlers and other pieces of code required to run the CRUID API based on
// the provided Resource type
type API[T Resource] struct {
Expand Down Expand Up @@ -163,7 +166,8 @@ func (a *API[T]) Name() string {
return a.name
}

// SetCustomResponseCode will override the default response codes for the specified HTTP verb
// SetCustomResponseCode will override the default response codes for the specified HTTP verb. Use MethodGetAll to set the
// response code for listing all resources
func (a *API[T]) SetCustomResponseCode(verb string, code int) *API[T] {
a.panicIfReadOnly()

Expand Down
135 changes: 107 additions & 28 deletions babyapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -449,8 +449,8 @@ func TestCLI(t *testing.T) {
{
"PostError",
[]string{"Albums", "post", "-d", `bad request`},
"error running client from CLI: error running Post: error posting resource: unexpected response with text: Invalid request.",
true,
`{"error":"invalid character 'b' looking for beginning of value","status":"Invalid request."}`,
false,
},
{
"Patch",
Expand All @@ -467,8 +467,8 @@ func TestCLI(t *testing.T) {
{
"PutError",
[]string{"Albums", "put", "cljcqg5o402e9s28rbp0", "-d", `{"title":"NewAlbum"}`},
"error running client from CLI: error running Put: error putting resource: unexpected response with text: Invalid request.",
true,
`{"error":"missing required id field","status":"Invalid request."}`,
false,
},
{
"GetByID",
Expand All @@ -479,7 +479,7 @@ func TestCLI(t *testing.T) {
{
"GetByIDMissingArgs",
[]string{"Albums", "get"},
"error running client from CLI: at least one argument required",
`at least one argument required`,
true,
},
{
Expand Down Expand Up @@ -515,26 +515,26 @@ func TestCLI(t *testing.T) {
{
"DeleteMissingArgs",
[]string{"Albums", "delete"},
"error running client from CLI: at least one argument required",
`at least one argument required`,
true,
},
{
"GetByIDNotFound",
[]string{"Albums", "get", "cljcqg5o402e9s28rbp0"},
"error running client from CLI: error running Get: error getting resource: unexpected response with text: Resource not found.",
true,
`{"status":"Resource not found."}`,
false,
},
{
"DeleteNotFound",
[]string{"Albums", "delete", "cljcqg5o402e9s28rbp0"},
"error running client from CLI: error running Delete: error deleting resource: unexpected response with text: Resource not found.",
true,
`{"status":"Resource not found."}`,
false,
},
{
"PatchNotFound",
[]string{"Albums", "patch", "cljcqg5o402e9s28rbp0", "-d", ""},
"error running client from CLI: error running Patch: error patching resource: unexpected response with text: Resource not found.",
true,
`{"status":"Resource not found."}`,
false,
},
{
"PatchMissingArgs",
Expand Down Expand Up @@ -597,6 +597,12 @@ func TestCLI(t *testing.T) {
})
})

t.Run("RunWithoutAddress", func(t *testing.T) {
out, err := runCommand(api.Command(), []string{"client", "--pretty=false", "--query", "title=New Album", "Albums", "list"})
require.NoError(t, err)
require.Equal(t, `{"items":[{"id":"cljcqg5o402e9s28rbp0","title":"New Album"}]}`, strings.TrimSpace(out))
})

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
baseArgs := []string{"client", "--pretty=false", "--address", address}
Expand All @@ -608,6 +614,9 @@ func TestCLI(t *testing.T) {
require.Equal(t, tt.expectedRegexp, strings.TrimSpace(out))
}
} else {
if err == nil {
fmt.Println(out)
}
require.Error(t, err)
require.Regexp(t, tt.expectedRegexp, err.Error())
}
Expand Down Expand Up @@ -1127,8 +1136,8 @@ func TestRootAPICLI(t *testing.T) {
{
"PostError",
[]string{"MusicVideos", "post", "--data", `bad request`},
"error running client from CLI: error running Post: error posting resource: unexpected response with text: Invalid request.",
true,
`{"error":"invalid character 'b' looking for beginning of value","status":"Invalid request."}`,
false,
},
{
"Patch",
Expand All @@ -1145,8 +1154,8 @@ func TestRootAPICLI(t *testing.T) {
{
"PutError",
[]string{"MusicVideos", "put", "cljcqg5o402e9s28rbp0", "--data", `{"title":"NewMusicVideo"}`},
"error running client from CLI: error running Put: error putting resource: unexpected response with text: Invalid request.",
true,
`{"error":"missing required id field","status":"Invalid request."}`,
false,
},
{
"GetByID",
Expand All @@ -1157,7 +1166,7 @@ func TestRootAPICLI(t *testing.T) {
{
"GetByIDMissingArgs",
[]string{"MusicVideos", "get"},
"error running client from CLI: at least one argument required",
`at least one argument required`,
true,
},
{
Expand Down Expand Up @@ -1187,26 +1196,26 @@ func TestRootAPICLI(t *testing.T) {
{
"DeleteMissingArgs",
[]string{"MusicVideos", "delete"},
"error running client from CLI: at least one argument required",
`at least one argument required`,
true,
},
{
"GetByIDNotFound",
[]string{"MusicVideos", "get", "cljcqg5o402e9s28rbp0"},
"error running client from CLI: error running Get: error getting resource: unexpected response with text: Resource not found.",
true,
`{"status":"Resource not found."}`,
false,
},
{
"DeleteNotFound",
[]string{"MusicVideos", "delete", "cljcqg5o402e9s28rbp0"},
"error running client from CLI: error running Delete: error deleting resource: unexpected response with text: Resource not found.",
true,
`{"status":"Resource not found."}`,
false,
},
{
"PatchNotFound",
[]string{"MusicVideos", "patch", "cljcqg5o402e9s28rbp0", "--data", ""},
"error running client from CLI: error running Patch: error patching resource: unexpected response with text: Resource not found.",
true,
`{"status":"Resource not found."}`,
false,
},
{
"PatchMissingArgs",
Expand Down Expand Up @@ -1377,7 +1386,77 @@ func TestWithContextShutdown(t *testing.T) {
}
}

// func TestInvalidUseOfModifiersReturnsErrorAtStart(t *testing.T) {
// api := babyapi.NewRootAPI[*Album]("Albums", "/albums", func() *Album { return &Album{} })
// api
// }
type AllAlbumsWrapper []*Album

func (AllAlbumsWrapper) Render(http.ResponseWriter, *http.Request) error {
return nil
}

func TestGetAllResponseWrapperWithClient(t *testing.T) {
api := babyapi.NewAPI("Albums", "/albums", func() *Album { return &Album{} })
api.SetGetAllResponseWrapper(func(a []*Album) render.Renderer {
return AllAlbumsWrapper(a)
})

client, stop := babytest.NewTestClient(t, api)
defer stop()

t.Run("CreateAlbum", func(t *testing.T) {
_, err := client.Post(context.Background(), &Album{Title: "Album"})
require.NoError(t, err)
})

t.Run("RegularGetAllRequestErrors", func(t *testing.T) {
_, err := client.GetAll(context.Background(), "")
require.Error(t, err)
})

t.Run("MakeRequestCanBeUsed", func(t *testing.T) {
req, err := client.GetAllRequest(context.Background(), "")
require.NoError(t, err)

resp, err := babyapi.MakeRequest[AllAlbumsWrapper](req, http.DefaultClient, http.StatusOK, nil)
require.NoError(t, err)
require.Equal(t, "Album", resp.Data[0].Title)
})

t.Run("MakeGenericRequestCanBeUsed", func(t *testing.T) {
req, err := client.GetAllRequest(context.Background(), "")
require.NoError(t, err)

var albums AllAlbumsWrapper
err = client.MakeGenericRequest(req, &albums)
require.NoError(t, err)
require.Equal(t, "Album", albums[0].Title)
})

t.Run("GetAllCLI", func(t *testing.T) {
out, err := runCommand(api.Command(), []string{"client", "--pretty=false", "--address", client.Address, "Albums", "list"})
require.NoError(t, err)
require.Regexp(t, `[{"id":"[0-9a-v]{20}","title":"Album"}]`, strings.TrimSpace(out))
})
}

func TestClient(t *testing.T) {
api := babyapi.NewAPI("Albums", "/albums", func() *Album { return &Album{} })
api.SetGetAllResponseWrapper(func(a []*Album) render.Renderer {
return AllAlbumsWrapper(a)
})

client, stop := babytest.NewTestClient(t, api)
defer stop()

t.Run("CustomResponseCodeSuccess", func(t *testing.T) {
client.SetCustomResponseCode(babyapi.MethodGetAll, http.StatusCreated)
resp, err := client.GetAll(context.Background(), "")
require.NoError(t, err)
require.Equal(t, http.StatusCreated, resp.Response.StatusCode)
})

t.Run("SetHTTPClient", func(t *testing.T) {
client.SetHTTPClient(http.DefaultClient)

_, err := client.GetAll(context.Background(), "")
require.NoError(t, err)
})
}

0 comments on commit 86a1c7b

Please sign in to comment.