1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: LicenseRef-MutuaL-1.2
4
5package mcp
6
7import (
8 "context"
9 "testing"
10
11 "git.secluded.site/cooked-mcp/internal/cooked"
12)
13
14func TestCallToolACIDToolsSurface1ReadsShoppingList(t *testing.T) {
15 backend := &fakeBackend{shoppingList: cooked.ShoppingList{
16 Aisles: []cooked.Aisle{{
17 ID: "pantry",
18 Name: "Pantry",
19 ProductGroups: []cooked.ProductGroup{{
20 ID: "pasta",
21 Name: "Pasta",
22 Quantity: "200g",
23 }},
24 }},
25 }}
26 server := NewServer(backend, "test")
27
28 output, err := server.CallReadTool(context.Background(), ReadArguments{Target: "shopping_list"})
29 if err != nil {
30 t.Fatalf("CallReadTool() error = %v", err)
31 }
32
33 if len(output.Aisles) != 1 {
34 t.Fatalf("structured aisles = %d, want 1", len(output.Aisles))
35 }
36 if output.Aisles[0].ProductGroups[0].Name != "Pasta" {
37 t.Fatalf("first item = %q, want Pasta", output.Aisles[0].ProductGroups[0].Name)
38 }
39}
40
41func TestCallToolACIDRecipesRead1ListsRecipes(t *testing.T) {
42 backend := &fakeBackend{recipes: []cooked.RecipeCard{{ID: "recipe-1", Title: "Pasta", ThumbnailURL: "https://example.invalid/thumb.jpg"}}}
43 server := NewServer(backend, "test")
44
45 output, err := server.CallReadTool(context.Background(), ReadArguments{Target: "recipes", Page: 2, Limit: 5})
46 if err != nil {
47 t.Fatalf("CallReadTool() error = %v", err)
48 }
49
50 if backend.page != 2 {
51 t.Fatalf("backend page = %d, want 2", backend.page)
52 }
53 if backend.limit != 5 {
54 t.Fatalf("backend limit = %d, want 5", backend.limit)
55 }
56 if len(output.Recipes) != 1 {
57 t.Fatalf("structured recipes = %d, want 1", len(output.Recipes))
58 }
59 if output.Recipes[0].ID != "recipe-1" || output.Recipes[0].Title != "Pasta" {
60 t.Fatalf("first recipe = %#v, want recipe-1 Pasta", output.Recipes[0])
61 }
62}
63
64func TestCallToolACIDRecipesPagination4DefaultsAndCapsRecipeLimit(t *testing.T) {
65 backend := &fakeBackend{}
66 server := NewServer(backend, "test")
67
68 _, err := server.CallReadTool(context.Background(), ReadArguments{Target: "recipes", Limit: 99})
69 if err != nil {
70 t.Fatalf("CallReadTool() error = %v", err)
71 }
72
73 if backend.page != 1 {
74 t.Fatalf("backend page = %d, want default page 1", backend.page)
75 }
76 if backend.limit != 30 {
77 t.Fatalf("backend limit = %d, want capped limit 30", backend.limit)
78 }
79}
80
81type fakeBackend struct {
82 shoppingList cooked.ShoppingList
83 recipes []cooked.RecipeCard
84 page int
85 limit int
86}
87
88func (f *fakeBackend) ReadShoppingList(context.Context) (cooked.ShoppingList, error) {
89 return f.shoppingList, nil
90}
91
92func (f *fakeBackend) ListRecipes(_ context.Context, page, limit int) ([]cooked.RecipeCard, error) {
93 f.page = page
94 f.limit = limit
95
96 return f.recipes, nil
97}