aboutsummaryrefslogtreecommitdiffstats
path: root/internal/web/web_test.go
diff options
context:
space:
mode:
authorgrm <grm@eyesin.space>2026-09-16 00:00:57 +0300
committergrm <grm@eyesin.space>2026-09-16 00:00:57 +0300
commit839343a3108734a15e331b542a20ed9c77ef582b (patch)
treea6aabc8719c16398bf1ccd874a7efe865b364a9e /internal/web/web_test.go
parent628dcb814ece6335667e2b719049728aa161d8c9 (diff)
downloadblogspace-839343a3108734a15e331b542a20ed9c77ef582b.tar.gz
blogspace-839343a3108734a15e331b542a20ed9c77ef582b.tar.bz2
blogspace-839343a3108734a15e331b542a20ed9c77ef582b.zip
Add a search box module and a search page
Readers had no way to find a post. The new "search" module goes in the header (a bar under the nav) or a side column (a box with a heading) and is a plain GET form to /search, so it works without JavaScript. The results page lists the published posts of every page whose title or Markdown body matches the query — case-insensitive, each word literal, spaces meaning "anything in between", in order — as title, date and a short snippet with the match marked, 20 per page. modules.kind is a CHECK constraint, so a migration widens it; "search" becomes a reserved page slug so the literal route keeps winning over /{page}. moduleHasSettings now takes the module: a header search box has no heading, hence nothing to edit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A
Diffstat (limited to 'internal/web/web_test.go')
-rw-r--r--internal/web/web_test.go7
1 files changed, 4 insertions, 3 deletions
diff --git a/internal/web/web_test.go b/internal/web/web_test.go
index afb289a..b803003 100644
--- a/internal/web/web_test.go
+++ b/internal/web/web_test.go
@@ -74,7 +74,7 @@ func TestRootRoutePrecedence(t *testing.T) {
t.Errorf("%s: got %d, want %d", path, rec.Code, want)
}
}
- for _, slug := range []string{"webadmin", "admin", "b", "media", "feed.xml", "favicon.ico", "tag"} {
+ for _, slug := range []string{"webadmin", "admin", "b", "media", "feed.xml", "favicon.ico", "tag", "search"} {
if !reservedPageSlugs[slug] {
t.Errorf("page slug %q should be reserved", slug)
}
@@ -192,7 +192,8 @@ func TestModuleKinds(t *testing.T) {
if !allowedKind("header", "menu") || allowedKind("header", "archive") || allowedKind("above", "menu") || allowedKind("attic", "html") {
t.Error("allowedKind")
}
- if !moduleHasSettings("html") || moduleHasSettings("rss") {
+ if !moduleHasSettings(store.Module{Kind: "html"}) || moduleHasSettings(store.Module{Kind: "rss"}) ||
+ !moduleHasSettings(store.Module{Kind: "search", Area: "left"}) || moduleHasSettings(store.Module{Kind: "search", Area: "header"}) {
t.Error("moduleHasSettings")
}
if got := moduleSummary("en", store.Module{Kind: "recent", Count: 5, Title: "Fresh"}); got != "5 posts, heading “Fresh”" {
@@ -379,7 +380,7 @@ func TestAllTemplatesParse(t *testing.T) {
for _, name := range []string{"auth/login.html", "dashboard/overview.html", "dashboard/pages.html", "dashboard/page_form.html",
"dashboard/posts.html", "dashboard/post_form.html", "dashboard/design.html", "dashboard/files.html", "dashboard/settings.html",
"dashboard/password.html", "dashboard/confirm.html", "dashboard/sections.html", "dashboard/section_form.html", "dashboard/layout.html", "dashboard/module_form.html", "admin/index.html", "admin/new_user.html", "admin/delete_user.html",
- "blog/page.html", "blog/post.html", "blog/tag.html", "blog/404.html"} {
+ "blog/page.html", "blog/post.html", "blog/tag.html", "blog/search.html", "blog/404.html"} {
for _, l := range i18n.Languages() {
if _, err := tpl.get(l.Code, name); err != nil {
t.Errorf("%s (%s): %v", name, l.Code, err)