server_save_url_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	"testing"
 10
 11	"git.secluded.site/cooked-mcp/internal/cooked"
 12)
 13
 14// recipes.SAVE.3 recipes.SAVE.4 recipes.SAVE.9 tools.SAVE_RECIPE_TOOL.1
 15func TestCallToolACIDRecipesSave3And4And9ImportsURLSavedRecipe(t *testing.T) {
 16	backend := &fakeBackend{importRecipeURLResult: cooked.RecipeURLImport{RecipeID: "recipe-1"}}
 17	server := NewServer(backend, "test")
 18
 19	_, output, err := server.callSaveRecipeTool(
 20		context.Background(),
 21		nil,
 22		SaveRecipeArguments{Source: " url ", URL: " https://example.invalid/recipe "},
 23	)
 24	if err != nil {
 25		t.Fatalf("callSaveRecipeTool() error = %v", err)
 26	}
 27
 28	if backend.importRecipeURLCalls != 1 {
 29		t.Fatalf("import calls = %d, want 1", backend.importRecipeURLCalls)
 30	}
 31	if backend.importURL != "https://example.invalid/recipe" {
 32		t.Fatalf("backend import URL = %q, want trimmed URL", backend.importURL)
 33	}
 34	if output.RecipeID != "recipe-1" || output.DraftID != "" {
 35		t.Fatalf("save output = %#v, want recipe_id only", output)
 36	}
 37	if backend.metadataCalls != 0 || backend.contentCalls != 0 {
 38		t.Fatalf("draft read calls = metadata %d content %d, want none", backend.metadataCalls, backend.contentCalls)
 39	}
 40	if backend.saveCalls != 0 || backend.updateCalls != 0 {
 41		t.Fatalf("save/update calls = %d/%d, want none", backend.saveCalls, backend.updateCalls)
 42	}
 43}
 44
 45// recipes.SAVE.3-1 tools.SAVE_RECIPE_TOOL.4
 46func TestCallToolACIDRecipesSave3_1AndToolsSaveRecipeTool4RequiresURL(t *testing.T) {
 47	backend := &fakeBackend{}
 48	server := NewServer(backend, "test")
 49
 50	_, _, err := server.callSaveRecipeTool(context.Background(), nil, SaveRecipeArguments{Source: "url", URL: "   "})
 51	if err == nil {
 52		t.Fatal("callSaveRecipeTool() error = nil, want missing URL error")
 53	}
 54	if backend.importRecipeURLCalls != 0 {
 55		t.Fatalf("import calls = %d, want none", backend.importRecipeURLCalls)
 56	}
 57}
 58
 59// recipes.SAVE.5 recipes.SAVE.6 recipes.SAVE.12 recipes.SAVE.14 recipes.SAVE.15 recipes.SAVE.16
 60func TestCallToolACIDRecipesSave5And12And14And15ReturnsURLImportDraft(t *testing.T) {
 61	backend := &fakeBackend{
 62		importRecipeURLResult: cooked.RecipeURLImport{DraftID: "draft-1"},
 63		recipeMetadata:        cooked.RecipeMetadata{Title: "Pasta"},
 64		recipeContent:         cooked.RecipeContent{Content: "# Pasta\n\n1. Boil pasta.", Portions: 2},
 65	}
 66	server := NewServer(backend, "test")
 67
 68	_, output, err := server.callSaveRecipeTool(
 69		context.Background(),
 70		nil,
 71		SaveRecipeArguments{Source: "url", URL: " https://example.invalid/pasta "},
 72	)
 73	if err != nil {
 74		t.Fatalf("callSaveRecipeTool() error = %v", err)
 75	}
 76
 77	if backend.importRecipeURLCalls != 1 {
 78		t.Fatalf("import calls = %d, want 1", backend.importRecipeURLCalls)
 79	}
 80	if backend.importURL != "https://example.invalid/pasta" {
 81		t.Fatalf("backend import URL = %q, want trimmed URL", backend.importURL)
 82	}
 83	if backend.metadataRecipeID != "draft-1" || backend.contentRecipeID != "draft-1" {
 84		t.Fatalf(
 85			"draft read IDs = metadata %q content %q, want draft-1",
 86			backend.metadataRecipeID,
 87			backend.contentRecipeID,
 88		)
 89	}
 90	if backend.metadataCalls != 1 || backend.contentCalls != 1 {
 91		t.Fatalf("draft read calls = metadata %d content %d, want 1/1", backend.metadataCalls, backend.contentCalls)
 92	}
 93	if output.RecipeID != "" || output.DraftID != "draft-1" || output.Title != "Pasta" {
 94		t.Fatalf("draft output identity = %#v, want draft-1 Pasta with no recipe ID", output)
 95	}
 96	if output.Markdown != "# Pasta\n\n1. Boil pasta." || output.Portions != 2 {
 97		t.Fatalf("draft output content = %q/%d, want markdown/2", output.Markdown, output.Portions)
 98	}
 99	if backend.saveCalls != 0 || backend.updateCalls != 0 {
100		t.Fatalf("save/update calls = %d/%d, want none", backend.saveCalls, backend.updateCalls)
101	}
102}