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: testRecipeID}}
 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 != testRecipeID || 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	draftID := "draft-1"
 62	backend := &fakeBackend{
 63		importRecipeURLResult: cooked.RecipeURLImport{DraftID: draftID},
 64		recipeMetadata:        cooked.RecipeMetadata{Title: "Pasta"},
 65		recipeContent:         cooked.RecipeContent{Content: "# Pasta\n\n1. Boil pasta.", Portions: 2},
 66	}
 67	server := NewServer(backend, "test")
 68
 69	_, output, err := server.callSaveRecipeTool(
 70		context.Background(),
 71		nil,
 72		SaveRecipeArguments{Source: "url", URL: " https://example.invalid/pasta "},
 73	)
 74	if err != nil {
 75		t.Fatalf("callSaveRecipeTool() error = %v", err)
 76	}
 77
 78	if backend.importRecipeURLCalls != 1 {
 79		t.Fatalf("import calls = %d, want 1", backend.importRecipeURLCalls)
 80	}
 81	if backend.importURL != "https://example.invalid/pasta" {
 82		t.Fatalf("backend import URL = %q, want trimmed URL", backend.importURL)
 83	}
 84	if backend.metadataRecipeID != draftID || backend.contentRecipeID != draftID {
 85		t.Fatalf(
 86			"draft read IDs = metadata %q content %q, want draft ID",
 87			backend.metadataRecipeID,
 88			backend.contentRecipeID,
 89		)
 90	}
 91	if backend.metadataCalls != 1 || backend.contentCalls != 1 {
 92		t.Fatalf("draft read calls = metadata %d content %d, want 1/1", backend.metadataCalls, backend.contentCalls)
 93	}
 94	if output.RecipeID != "" || output.DraftID != draftID || output.Title != "Pasta" {
 95		t.Fatalf("draft output identity = %#v, want draft ID Pasta with no recipe ID", output)
 96	}
 97	if output.Markdown != "# Pasta\n\n1. Boil pasta." || output.Portions != 2 {
 98		t.Fatalf("draft output content = %q/%g, want markdown/2", output.Markdown, output.Portions)
 99	}
100	if backend.saveCalls != 0 || backend.updateCalls != 0 {
101		t.Fatalf("save/update calls = %d/%d, want none", backend.saveCalls, backend.updateCalls)
102	}
103}