@@ -157,6 +157,16 @@ func (c *Client) AddShoppingListIngredients(
return AddShoppingListResult{AddedCount: *response.AddedCount, Ingredients: response.Ingredients}, nil
}
+// RemoveShoppingListProductGroups logs in when needed and removes shopping-list product groups.
+func (c *Client) RemoveShoppingListProductGroups(ctx context.Context, ids []string) error {
+ body, err := json.Marshal(removeShoppingListProductGroupsRequest{IDs: ids})
+ if err != nil {
+ return fmt.Errorf("encode Cooked shopping-list remove request: %w", err)
+ }
+
+ return c.doAuthenticated(ctx, http.MethodDelete, "/api/user/{username}/shopping-list/product-groups", body, nil)
+}
+
// ListRecipes logs in when needed and returns one page of saved recipes.
func (c *Client) ListRecipes(ctx context.Context, page, limit int) ([]RecipeCard, error) {
query := url.Values{}
@@ -408,6 +418,10 @@ type addShoppingListResponse struct {
Ingredients []string `json:"ingredients"`
}
+type removeShoppingListProductGroupsRequest struct {
+ IDs []string `json:"ids"`
+}
+
type recipeListResponse struct {
Recipes []RecipeCard `json:"recipes"`
}
@@ -214,6 +214,21 @@ func TestAddShoppingListIngredientsACIDShoppingListAdd1To4AddsIngredients(t *tes
}
}
+func TestRemoveShoppingListProductGroupsACIDShoppingListRemove1RemovesProductGroups(t *testing.T) {
+ var removeCalls int
+ client, closeServer := newTestClient(t, removeShoppingListProductGroupsTestHandler(t, &removeCalls))
+ defer closeServer()
+
+ err := client.RemoveShoppingListProductGroups(context.Background(), []string{"pasta", "tomato"})
+ if err != nil {
+ t.Fatalf("RemoveShoppingListProductGroups() error = %v", err)
+ }
+
+ if removeCalls != 1 {
+ t.Fatalf("remove calls = %d, want 1", removeCalls)
+ }
+}
+
func TestUserPathEscapesAuthenticatedUsername(t *testing.T) {
client := &Client{authenticatedUsername: "user/name"}
@@ -497,6 +512,39 @@ func writeAddShoppingListIngredientsResponse(t *testing.T, w http.ResponseWriter
}
}
+func removeShoppingListProductGroupsTestHandler(t *testing.T, removeCalls *int) http.HandlerFunc {
+ t.Helper()
+
+ return func(w http.ResponseWriter, r *http.Request) {
+ switch r.URL.EscapedPath() {
+ case "/api/public/login":
+ writeLoginResponse(t, w)
+ case "/api/user/returned-user/shopping-list/product-groups":
+ requireMethod(t, r, http.MethodDelete, "remove shopping-list product groups")
+ requireSessionCookie(t, r)
+ requireRemoveShoppingListProductGroupsRequest(t, r)
+ (*removeCalls)++
+ w.WriteHeader(http.StatusNoContent)
+ default:
+ t.Fatalf("unexpected path %s", r.URL.EscapedPath())
+ }
+ }
+}
+
+func requireRemoveShoppingListProductGroupsRequest(t *testing.T, r *http.Request) {
+ t.Helper()
+
+ var request struct {
+ IDs []string `json:"ids"`
+ }
+ if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
+ t.Fatalf("decode remove shopping-list product groups request: %v", err)
+ }
+ if len(request.IDs) != 2 || request.IDs[0] != "pasta" || request.IDs[1] != "tomato" {
+ t.Fatalf("remove IDs = %#v, want pasta and tomato", request.IDs)
+ }
+}
+
func requirePreviewRecipeTextRequest(t *testing.T, r *http.Request) {
t.Helper()