package main import ( "encoding/json" "net/http/httptest" "strings" "testing" ) func TestCustomSlugCreateAndFetch(t *testing.T) { s := testServer(t) h := s.routes() req := httptest.NewRequest("POST", "/api/pastes", strings.NewReader(`{"content":"x","custom_slug":"release-notes"}`)) rec := httptest.NewRecorder() h.ServeHTTP(rec, req) if rec.Code != 201 { t.Fatalf("create: %d %s", rec.Code, rec.Body.String()) } // fetch by custom slug req = httptest.NewRequest("GET", "/api/pastes/release-notes", nil) rec = httptest.NewRecorder() h.ServeHTTP(rec, req) if rec.Code != 200 { t.Fatalf("fetch by slug: %d", rec.Code) } var got map[string]any json.Unmarshal(rec.Body.Bytes(), &got) if got["content"] != "x" { t.Fatal("content mismatch via custom slug") } } func TestCustomSlugValidation(t *testing.T) { s := testServer(t) h := s.routes() cases := []struct { slug, body string wantCode int }{ {"dup", `{"content":"first","custom_slug":"dup"}`, 201}, {"dup", `{"content":"second","custom_slug":"dup"}`, 400}, {"api", `{"content":"x","custom_slug":"api"}`, 400}, {"raw", `{"content":"x","custom_slug":"raw"}`, 400}, {"bad slug", `{"content":"x","custom_slug":"has space"}`, 400}, {"", `{"content":"x","custom_slug":""}`, 201}, // empty = no custom slug, fine } for i, c := range cases { req := httptest.NewRequest("POST", "/api/pastes", strings.NewReader(c.body)) req.RemoteAddr = "10.7.1." + string(rune('1'+i)) + ":1000" // avoid rate-limit bucket sharing rec := httptest.NewRecorder() h.ServeHTTP(rec, req) if rec.Code != c.wantCode { t.Fatalf("slug %q: got %d want %d: %s", c.slug, rec.Code, c.wantCode, rec.Body.String()) } } } func TestSlugCollisionWithAutoID(t *testing.T) { s := testServer(t) // manually insert a paste, then try to claim its auto ID as a custom slug p, err := s.store.CreatePaste(&Paste{Content: "auto"}) if err != nil { t.Fatal(err) } if taken, _ := s.store.SlugTaken(p.ID); !taken { t.Fatal("auto id should be claimed") } }