1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: LicenseRef-MutuaL-1.2
4
5package cooked
6
7import (
8 "context"
9 "net/http"
10 "strings"
11 "testing"
12)
13
14func TestListRecipesACIDAPIClientResponses1AcceptsEmptyRecipesList(t *testing.T) {
15 client, closeServer := newTestClient(t, rawRecipeListTestHandler(
16 t,
17 "/api/user/returned-user/recipes",
18 `[]`,
19 ))
20 defer closeServer()
21
22 recipes, err := client.ListRecipes(context.Background(), 1, 10)
23 if err != nil {
24 t.Fatalf("ListRecipes() error = %v", err)
25 }
26 if len(recipes) != 0 {
27 t.Fatalf("recipes length = %d, want 0", len(recipes))
28 }
29}
30
31func TestListRecipesACIDAPIClientResponses1RejectsNullRecipesList(t *testing.T) {
32 client, closeServer := newTestClient(t, rawRecipeListTestHandler(
33 t,
34 "/api/user/returned-user/recipes",
35 `null`,
36 ))
37 defer closeServer()
38
39 _, err := client.ListRecipes(context.Background(), 1, 10)
40 if err == nil {
41 t.Fatal("ListRecipes() error = nil, want missing recipes error")
42 }
43}
44
45func TestSearchRecipesACIDAPIClientResponses1RejectsRecipeCardsWithoutIDOrTitle(t *testing.T) {
46 tests := []struct {
47 name string
48 body string
49 }{
50 {name: "missing id", body: `[{"title":"Pasta"}]`},
51 {name: "blank title", body: `[{"id":"recipe-1","title":" "}]`},
52 }
53
54 for _, tt := range tests {
55 t.Run(tt.name, func(t *testing.T) {
56 client, closeServer := newTestClient(t, rawRecipeListTestHandler(
57 t,
58 "/api/user/returned-user/recipes/search",
59 tt.body,
60 ))
61 defer closeServer()
62
63 _, err := client.SearchRecipes(context.Background(), "pasta", 1)
64 if err == nil {
65 t.Fatal("SearchRecipes() error = nil, want invalid recipe card error")
66 }
67 })
68 }
69}
70
71// api-client.RESPONSES.1 recipes.SAVE.7 recipes.SAVE.9
72func TestSaveRecipeDraftACIDAPIClientResponses1RejectsMissingRecipeID(t *testing.T) {
73 var saveCalls int
74 client, closeServer := newTestClient(t, rawSaveRecipeDraftTestHandler(t, &saveCalls, `{}`))
75 defer closeServer()
76
77 _, err := client.SaveRecipeDraft(
78 context.Background(),
79 "draft/with space",
80 "# Pasta\n\n1. Boil pasta.",
81 4,
82 )
83 if err == nil {
84 t.Fatal("SaveRecipeDraft() error = nil, want missing recipe ID error")
85 }
86 if !strings.Contains(err.Error(), "missing recipe ID") {
87 t.Fatalf("SaveRecipeDraft() error = %v, want missing recipe ID error", err)
88 }
89 if saveCalls != 1 {
90 t.Fatalf("save calls = %d, want 1", saveCalls)
91 }
92}
93
94func rawRecipeListTestHandler(t *testing.T, path, body string) http.HandlerFunc {
95 t.Helper()
96
97 return func(w http.ResponseWriter, r *http.Request) {
98 switch r.URL.Path {
99 case "/api/public/login":
100 writeLoginResponse(t, w)
101 case path:
102 w.Header().Set("Content-Type", "application/json")
103 if _, err := w.Write([]byte(body)); err != nil {
104 t.Fatalf("write raw recipe list response: %v", err)
105 }
106 default:
107 t.Fatalf("unexpected path %s", r.URL.Path)
108 }
109 }
110}
111
112func rawSaveRecipeDraftTestHandler(t *testing.T, saveCalls *int, body string) http.HandlerFunc {
113 t.Helper()
114
115 return func(w http.ResponseWriter, r *http.Request) {
116 switch r.URL.EscapedPath() {
117 case "/api/public/login":
118 writeLoginResponse(t, w)
119 case "/api/extract/draft%2Fwith%20space/save":
120 requireMethod(t, r, http.MethodPost, "save recipe draft")
121 requireSessionCookie(t, r)
122 requireRecipeContentRequest(t, r, "draft save")
123 (*saveCalls)++
124 w.Header().Set("Content-Type", "application/json")
125 if _, err := w.Write([]byte(body)); err != nil {
126 t.Fatalf("write raw save draft response: %v", err)
127 }
128 default:
129 t.Fatalf("unexpected path %s", r.URL.EscapedPath())
130 }
131 }
132}