package api import ( "net/http" "net/http/httptest" "os" "path/filepath" "strings" "testing" ) func testWebsite(t *testing.T, origin string) *API { t.Helper() dir := t.TempDir() if err := os.WriteFile(filepath.Join(dir, "index.html"), []byte("
"), 0600); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(dir, "favicon.ico"), []byte{0, 0, 1, 0}, 0600); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(dir, "seo-manifest.json"), []byte(`{"siteURL":"`+origin+`","services":[]}`), 0600); err != nil { t.Fatal(err) } a := New(nil, "") if err := a.WithWebsite(dir, origin); err != nil { t.Fatal(err) } return a } func TestCanonicalPagePath(t *testing.T) { for input, expected := range map[string]string{"/": "/", "/contacts": "/contacts/", "/contacts/": "/contacts/", "/services/estetic/rinoplastika": "/services/estetic/rinoplastika/"} { if got := canonicalPagePath(input); got != expected { t.Errorf("%s: %s != %s", input, got, expected) } } } func TestWebsiteStatusCodes(t *testing.T) { a := testWebsite(t, "https://example.org") for _, tc := range []struct { path string status int redirect string }{ {"/", 200, ""}, {"/contacts/", 200, ""}, {"/contacts?utm_source=test", 301, "/contacts/?utm_source=test"}, {"/no-such-page/", 404, ""}, {"/news/", 200, ""}, {"/gallery/", 404, ""}, {"/company/history/", 301, "/company/"}, {"/company/docs/", 301, "/legaldocs/"}, {"/assets/no-such-file.js", 404, ""}, {"/seo-manifest.json", 404, ""}, {"/favicon.ico", 200, ""}, {"/privacy", 301, "/legaldocs/privacy/"}, } { r := httptest.NewRequest(http.MethodGet, tc.path, nil) w := httptest.NewRecorder() a.Routes().ServeHTTP(w, r) if w.Code != tc.status { t.Errorf("%s: status %d, want %d", tc.path, w.Code, tc.status) } if tc.redirect != "" && w.Header().Get("Location") != tc.redirect { t.Errorf("redirect %s", w.Header().Get("Location")) } if w.Code == 404 && tc.path == "/no-such-page/" && w.Header().Get("X-Robots-Tag") != "noindex" { t.Error("404 should be noindex") } } } func TestRobots(t *testing.T) { for _, origin := range []string{"https://example.org", "http://127.0.0.1:8080"} { a := testWebsite(t, origin) w := httptest.NewRecorder() a.Routes().ServeHTTP(w, httptest.NewRequest(http.MethodGet, "/robots.txt", nil)) body := w.Body.String() if a.website.local { if body != "User-agent: *\nDisallow: /\n" { t.Fatal(body) } } else { for _, expected := range []string{"Disallow: /admin", "Disallow: /api/", "Sitemap: https://example.org/sitemap.xml"} { if !strings.Contains(body, expected) { t.Errorf("missing %s", expected) } } } } } func TestWebsiteCanonicalMismatch(t *testing.T) { a := testWebsite(t, "https://example.org") if err := a.WithWebsite(a.website.dir, "https://other.example.org"); err == nil { t.Error("canonical mismatch must fail startup") } } func TestWebsiteInvalidOrigin(t *testing.T) { dir := t.TempDir() _ = os.WriteFile(filepath.Join(dir, "index.html"), []byte("html"), 0600) for _, origin := range []string{"javascript:alert(1)", "https://example.org/path", "https://user:secret@example.org", "https://example.org?q=test"} { if err := New(nil, "").WithWebsite(dir, origin); err == nil { t.Errorf("accepted %s", origin) } } }