Skip to content

Commit

Permalink
Fix error for invalid number of parent IDs
Browse files Browse the repository at this point in the history
  • Loading branch information
calvinmclean committed Dec 2, 2023
1 parent 7da692a commit ec19bb4
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 41 deletions.
83 changes: 51 additions & 32 deletions babyapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,19 @@ func TestBabyAPI(t *testing.T) {
})

t.Run("ActionRoute", func(t *testing.T) {
req, err := http.NewRequest(http.MethodGet, client.URL("")+"/teapot", http.NoBody)
address, err := client.URL("")
require.NoError(t, err)
req, err := http.NewRequest(http.MethodGet, address+"/teapot", http.NoBody)
require.NoError(t, err)
_, err = client.MakeRequest(req, http.StatusTeapot)
require.NoError(t, err)
})

t.Run("ActionIDRoute", func(t *testing.T) {
t.Run("Successful", func(t *testing.T) {
req, err := http.NewRequest(http.MethodGet, client.URL(album1.GetID())+"/teapot", http.NoBody)
address, err := client.URL(album1.GetID())
require.NoError(t, err)
req, err := http.NewRequest(http.MethodGet, address+"/teapot", http.NoBody)
require.NoError(t, err)
_, err = client.MakeRequest(req, http.StatusTeapot)
require.NoError(t, err)
Expand Down Expand Up @@ -322,7 +326,7 @@ func TestNestedAPI(t *testing.T) {
})

t.Run("SuccessfulParsedAsSongResponse", func(t *testing.T) {
req, err := http.NewRequest(http.MethodGet, songClient.URL(song1Response.GetID(), artist1.GetID(), album1.GetID()), http.NoBody)
req, err := songClient.NewRequestWithParentIDs(context.Background(), http.MethodGet, http.NoBody, song1Response.GetID(), artist1.GetID(), album1.GetID())
require.NoError(t, err)

resp, err := songClient.MakeRequest(req, http.StatusOK)
Expand Down Expand Up @@ -379,139 +383,151 @@ func TestCLI(t *testing.T) {
name string
args []string
expectedRegexp string
expectedErr string
expectedErr bool
}{
{
"MissingTargetAPIArg",
[]string{},
``,
"at least one argument required",
true,
},
{
"InvalidTargetAPIArg",
[]string{"bad", "bad"},
``,
"invalid API \"bad\". valid options are: [Albums Songs]",
`invalid API \"bad\". valid options are: (\[Albums Songs\]|\[Songs Albums\])`,
true,
},
{
"MissingArgs",
[]string{"Albums"},
``,
"at least two arguments required",
true,
},
{
"GetAll",
[]string{"list", "Albums"},
`\[\{"id":"cljcqg5o402e9s28rbp0","title":"NewAlbum"\}\]`,
"",
false,
},
{
"Post",
[]string{"post", "Albums", `{"title": "OtherNewAlbum"}`},
`\{"id":"[0-9a-v]{20}","title":"OtherNewAlbum"\}`,
"",
false,
},
{
"PostIncorrectParentArgs",
[]string{"post", "Albums", `{"title": "OtherNewAlbum"}`, "ExtraID"},
"error running client from CLI: error running Post: error creating request: error creating target URL: expected 0 parentIDs",
true,
},
{
"PostMissingArgs",
[]string{"post", "Albums"},
``,
"error running client from CLI: at least one argument required",
true,
},
{
"PostError",
[]string{"post", "Albums", `bad request`},
``,
"error running client from CLI: error running Post: error posting resource: unexpected response with text: Invalid request.",
true,
},
{
"Patch",
[]string{"patch", "Albums", "cljcqg5o402e9s28rbp0", `{"title":"NewTitle"}`},
`\{"id":"cljcqg5o402e9s28rbp0","title":"NewTitle"\}`,
"",
false,
},
{
"Put",
[]string{"put", "Albums", "cljcqg5o402e9s28rbp0", `{"id":"cljcqg5o402e9s28rbp0","title":"NewAlbum"}`},
``,
"",
`null`,
false,
},
{
"PutError",
[]string{"put", "Albums", "cljcqg5o402e9s28rbp0", `{"title":"NewAlbum"}`},
``,
"error running client from CLI: error running Put: error putting resource: unexpected response with text: Invalid request.",
true,
},
{
"GetByID",
[]string{"get", "Albums", "cljcqg5o402e9s28rbp0"},
`\{"id":"cljcqg5o402e9s28rbp0","title":"NewAlbum"\}`,
"",
false,
},
{
"GetByIDMissingArgs",
[]string{"get", "Albums"},
``,
"error running client from CLI: at least one argument required",
true,
},
{
"GetAllSongs",
[]string{"list", "Songs", "cljcqg5o402e9s28rbp0"},
``,
"",
`\[{"id":"clknc0do4023onrn3bqg","title":"NewSong"}\]`,
false,
},
{
"GetSongByID",
[]string{"get", "Songs", "clknc0do4023onrn3bqg", "cljcqg5o402e9s28rbp0"},
``,
"",
`{"id":"clknc0do4023onrn3bqg","title":"NewSong"}`,
false,
},
{
"GetSongByIDMissingParentID",
[]string{"get", "Songs", "clknc0do4023onrn3bqg"},
"error running client from CLI: error running Get: error creating request: error creating target URL: expected 1 parentIDs",
true,
},
{
"PostSong",
[]string{"post", "Songs", `{"title": "new song"}`, "cljcqg5o402e9s28rbp0"},
`\{"id":"[0-9a-v]{20}","title":"new song"\}`,
"",
false,
},
{
"Delete",
[]string{"delete", "Albums", "cljcqg5o402e9s28rbp0"},
`null`,
"",
false,
},
{
"DeleteMissingArgs",
[]string{"delete", "Albums"},
``,
"error running client from CLI: at least one argument required",
true,
},
{
"GetByIDNotFound",
[]string{"get", "Albums", "cljcqg5o402e9s28rbp0"},
``,
"error running client from CLI: error running Get: error getting resource: unexpected response with text: Resource not found.",
true,
},
{
"DeleteNotFound",
[]string{"delete", "Albums", "cljcqg5o402e9s28rbp0"},
``,
"error running client from CLI: error running Delete: error deleting resource: unexpected response with text: Resource not found.",
true,
},
{
"PatchNotFound",
[]string{"patch", "Albums", "cljcqg5o402e9s28rbp0", ""},
``,
"error running client from CLI: error running Patch: error patching resource: unexpected response with text: Resource not found.",
true,
},
{
"PatchMissingArgs",
[]string{"patch", "Albums"},
``,
"error running client from CLI: at least two arguments required",
true,
},
{
"PutMissingArgs",
[]string{"put", "Albums"},
``,
"error running client from CLI: at least two arguments required",
true,
},
}

Expand Down Expand Up @@ -547,12 +563,15 @@ func TestCLI(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
var out bytes.Buffer
err := api.RunWithArgs(&out, tt.args, 0, address, false)
if tt.expectedErr == "" {
if !tt.expectedErr {
require.NoError(t, err)
require.Regexp(t, tt.expectedRegexp, strings.TrimSpace(out.String()))
if tt.expectedRegexp == "" {
require.Equal(t, tt.expectedRegexp, strings.TrimSpace(out.String()))
}
} else {
require.Error(t, err)
require.Equal(t, tt.expectedErr, err.Error())
require.Regexp(t, tt.expectedRegexp, err.Error())
}
})
}
Expand Down
28 changes: 19 additions & 9 deletions client.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (c *Client[T]) SetRequestEditor(requestEditor RequestEditor) {

// Get will get a resource by ID
func (c *Client[T]) Get(ctx context.Context, id string, parentIDs ...string) (T, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, c.URL(id, parentIDs...), http.NoBody)
req, err := c.NewRequestWithParentIDs(ctx, http.MethodGet, http.NoBody, id, parentIDs...)
if err != nil {
return *new(T), fmt.Errorf("error creating request: %w", err)
}
Expand All @@ -67,7 +67,7 @@ func (c *Client[T]) Get(ctx context.Context, id string, parentIDs ...string) (T,

// GetAll gets all resources from the API
func (c *Client[T]) GetAll(ctx context.Context, query url.Values, parentIDs ...string) (*ResourceList[T], error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, c.URL("", parentIDs...), http.NoBody)
req, err := c.NewRequestWithParentIDs(ctx, http.MethodGet, http.NoBody, "", parentIDs...)
if err != nil {
return nil, fmt.Errorf("error creating request: %w", err)
}
Expand Down Expand Up @@ -105,7 +105,7 @@ func (c *Client[T]) PutRaw(ctx context.Context, id, body string, parentIDs ...st
}

func (c *Client[T]) put(ctx context.Context, id string, body io.Reader, parentIDs ...string) error {
req, err := http.NewRequestWithContext(ctx, http.MethodPut, c.URL(id, parentIDs...), body)
req, err := c.NewRequestWithParentIDs(ctx, http.MethodPut, body, id, parentIDs...)
if err != nil {
return fmt.Errorf("error creating request: %w", err)
}
Expand Down Expand Up @@ -135,7 +135,7 @@ func (c *Client[T]) PostRaw(ctx context.Context, body string, parentIDs ...strin
}

func (c *Client[T]) post(ctx context.Context, body io.Reader, parentIDs ...string) (T, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodPost, c.URL("", parentIDs...), body)
req, err := c.NewRequestWithParentIDs(ctx, http.MethodPost, body, "", parentIDs...)
if err != nil {
return *new(T), fmt.Errorf("error creating request: %w", err)
}
Expand Down Expand Up @@ -165,7 +165,7 @@ func (c *Client[T]) PatchRaw(ctx context.Context, id, body string, parentIDs ...
}

func (c *Client[T]) patch(ctx context.Context, id string, body io.Reader, parentIDs ...string) (T, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodPatch, c.URL(id, parentIDs...), body)
req, err := c.NewRequestWithParentIDs(ctx, http.MethodPatch, body, id, parentIDs...)
if err != nil {
return *new(T), fmt.Errorf("error creating request: %w", err)
}
Expand All @@ -186,7 +186,7 @@ func (c *Client[T]) patch(ctx context.Context, id string, body io.Reader, parent

// Delete makes a DELETE request to delete a resource by ID
func (c *Client[T]) Delete(ctx context.Context, id string, parentIDs ...string) error {
req, err := http.NewRequestWithContext(ctx, http.MethodDelete, c.URL(id, parentIDs...), http.NoBody)
req, err := c.NewRequestWithParentIDs(ctx, http.MethodDelete, http.NoBody, id, parentIDs...)
if err != nil {
return fmt.Errorf("error creating request: %w", err)
}
Expand All @@ -199,10 +199,20 @@ func (c *Client[T]) Delete(ctx context.Context, id string, parentIDs ...string)
return nil
}

// NewRequestWithParentIDs uses http.NewRequestWithContext to create a new request using the URL created from the provided ID and parent IDs
func (c *Client[T]) NewRequestWithParentIDs(ctx context.Context, method string, body io.Reader, id string, parentIDs ...string) (*http.Request, error) {
address, err := c.URL(id, parentIDs...)
if err != nil {
return nil, fmt.Errorf("error creating target URL: %w", err)
}

return http.NewRequestWithContext(ctx, method, address, body)
}

// URL gets the URL based on provided ID and optional parent IDs
func (c *Client[T]) URL(id string, parentIDs ...string) string {
func (c *Client[T]) URL(id string, parentIDs ...string) (string, error) {
if len(parentIDs) != len(c.parentPaths) {
panic("incorrect number of parent IDs provided")
return "", fmt.Errorf("expected %d parentIDs", len(c.parentPaths))
}

path := c.addr
Expand All @@ -216,7 +226,7 @@ func (c *Client[T]) URL(id string, parentIDs ...string) string {
path += fmt.Sprintf("/%s", id)
}

return path
return path, nil
}

// MakeRequest generically sends an HTTP request after calling the request editor and checks the response code
Expand Down

0 comments on commit ec19bb4

Please sign in to comment.