server_pagination_test.go

 1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
 2//
 3// SPDX-License-Identifier: LicenseRef-MutuaL-1.2
 4
 5package mcp
 6
 7import (
 8	"context"
 9	"strings"
10	"testing"
11
12	"git.secluded.site/cooked-mcp/internal/cooked"
13)
14
15// recipes.PAGINATION.6 api-client.LIMITS.3
16func TestCallToolACIDRecipesPagination6MentionsNextPageForFullRecipeList(t *testing.T) {
17	backend := &fakeBackend{recipes: []cooked.RecipeCard{
18		{ID: "recipe-1", Title: "Pasta", ThumbnailURL: "https://example.invalid/thumb.jpg"},
19		{ID: "recipe-2", Title: "Soup", ThumbnailURL: "https://example.invalid/thumb2.jpg"},
20	}}
21	server := NewServer(backend, "test")
22
23	result, _, err := server.callReadTool(
24		context.Background(),
25		nil,
26		ReadArguments{Target: "recipes", Page: 2, Limit: 2},
27	)
28	if err != nil {
29		t.Fatalf("callReadTool() error = %v", err)
30	}
31
32	text := requireTextContent(t, result)
33	if !strings.Contains(text, "More recipes may be available") {
34		t.Fatalf("text = %q, want more recipes hint", text)
35	}
36	if !strings.Contains(text, "page 3") || !strings.Contains(text, "limit 2") {
37		t.Fatalf("text = %q, want next page and limit", text)
38	}
39}
40
41// recipes.PAGINATION.6 api-client.LIMITS.3
42func TestCallToolACIDRecipesPagination6MentionsNextPageForTruncatedSearch(t *testing.T) {
43	backend := &fakeBackend{searchRecipes: []cooked.RecipeCard{
44		{ID: "recipe-1", Title: "Pasta", ThumbnailURL: "https://example.invalid/thumb.jpg"},
45		{ID: "recipe-2", Title: "Tomato Pasta", ThumbnailURL: "https://example.invalid/thumb2.jpg"},
46		{ID: "recipe-3", Title: "Pasta Salad", ThumbnailURL: "https://example.invalid/thumb3.jpg"},
47	}}
48	server := NewServer(backend, "test")
49
50	result, output, err := server.callReadTool(
51		context.Background(),
52		nil,
53		ReadArguments{Target: "recipes", Query: " pasta ", Page: 2, Limit: 1},
54	)
55	if err != nil {
56		t.Fatalf("callReadTool() error = %v", err)
57	}
58
59	if len(output.Recipes) != 1 {
60		t.Fatalf("structured recipes = %d, want truncated result length 1", len(output.Recipes))
61	}
62	text := requireTextContent(t, result)
63	if !strings.Contains(text, "More matching recipes may be available") {
64		t.Fatalf("text = %q, want more matching recipes hint", text)
65	}
66	if !strings.Contains(text, `query "pasta"`) {
67		t.Fatalf("text = %q, want preserved search query", text)
68	}
69	if !strings.Contains(text, "page 2") || !strings.Contains(text, "limit 3") {
70		t.Fatalf("text = %q, want same page and increased limit", text)
71	}
72	if !strings.Contains(text, "before trying page 3") {
73		t.Fatalf("text = %q, want next page ordering guidance", text)
74	}
75}