sabisan/internal/app/handlers_public_test.go
2026-05-17 13:36:50 +01:00

178 lines
5.3 KiB
Go

package app
import (
"io"
"net/http"
"net/http/httptest"
"net/url"
"strconv"
"strings"
"testing"
)
func TestPublicRoutes(t *testing.T) {
srv := newTestServer(t)
handler := srv.Routes()
for _, path := range []string{"/", "/projects", "/about", "/services", "/contact", "/projects/courtyard-house"} {
req := httptest.NewRequest(http.MethodGet, path, nil)
rec := httptest.NewRecorder()
handler.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("%s returned %d", path, rec.Code)
}
}
}
func TestServicesRouteRendersServicesAndFAQs(t *testing.T) {
srv := newTestServer(t)
req := httptest.NewRequest(http.MethodGet, "/services", nil)
rec := httptest.NewRecorder()
srv.Routes().ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected ok, got %d", rec.Code)
}
body, _ := io.ReadAll(rec.Result().Body)
text := string(body)
for _, want := range []string{"Residential architecture", "How projects work", "FAQs", "Start an enquiry"} {
if !strings.Contains(text, want) {
t.Fatalf("services page missing %q: %s", want, text)
}
}
}
func TestHomeRendersPhaseTwoSections(t *testing.T) {
srv := newTestServer(t)
req := httptest.NewRequest(http.MethodGet, "/", nil)
rec := httptest.NewRecorder()
srv.Routes().ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected ok, got %d", rec.Code)
}
body, _ := io.ReadAll(rec.Result().Body)
text := string(body)
for _, want := range []string{"Start an enquiry", "Focused support", "Process", "Studio profile"} {
if !strings.Contains(text, want) {
t.Fatalf("home missing %q: %s", want, text)
}
}
}
func TestStudioRendersExpandedContent(t *testing.T) {
srv := newTestServer(t)
req := httptest.NewRequest(http.MethodGet, "/about", nil)
rec := httptest.NewRecorder()
srv.Routes().ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected ok, got %d", rec.Code)
}
body, _ := io.ReadAll(rec.Result().Body)
text := string(body)
for _, want := range []string{"Philosophy", "Approach", "Experience", "Service area"} {
if !strings.Contains(text, want) {
t.Fatalf("studio missing %q: %s", want, text)
}
}
}
func TestContactSubmissionPersists(t *testing.T) {
srv := newTestServer(t)
form := url.Values{
"name": {"Jane"},
"email": {"jane@example.com"},
"phone": {"123"},
"project_type": {"Renovation or extension"},
"project_location": {"London"},
"budget_range": {"GBP 250k-500k"},
"timeline": {"3-6 months"},
"message": {"New project"},
}
req := httptest.NewRequest(http.MethodPost, "/contact", strings.NewReader(form.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
rec := httptest.NewRecorder()
srv.Routes().ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected ok, got %d", rec.Code)
}
body, _ := io.ReadAll(rec.Result().Body)
if !strings.Contains(string(body), "saved") {
t.Fatalf("expected success message, got %s", body)
}
requests, err := srv.store.ContactRequests(req.Context())
if err != nil {
t.Fatal(err)
}
if len(requests) != 1 || requests[0].Email != "jane@example.com" || requests[0].ProjectType != "Renovation or extension" || requests[0].Status != "new" {
t.Fatalf("unexpected contact requests: %+v", requests)
}
}
func TestContactSubmissionRequiresQualificationFields(t *testing.T) {
srv := newTestServer(t)
form := url.Values{"name": {"Jane"}, "email": {"jane@example.com"}, "message": {"New project"}}
req := httptest.NewRequest(http.MethodPost, "/contact", strings.NewReader(form.Encode()))
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
rec := httptest.NewRecorder()
srv.Routes().ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected ok, got %d", rec.Code)
}
body, _ := io.ReadAll(rec.Result().Body)
if !strings.Contains(string(body), "project type is required") {
t.Fatalf("expected qualification validation message, got %s", body)
}
}
func TestProjectImageOverlay(t *testing.T) {
srv := newTestServer(t)
project, err := srv.store.ProjectBySlug(t.Context(), "courtyard-house")
if err != nil {
t.Fatal(err)
}
if len(project.Images) == 0 {
t.Fatal("expected seeded project images")
}
path := "/projects/" + project.Slug + "/images/" + strconv.FormatInt(project.Images[0].ID, 10) + "/overlay"
req := httptest.NewRequest(http.MethodGet, path, nil)
rec := httptest.NewRecorder()
srv.Routes().ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected ok, got %d", rec.Code)
}
body, _ := io.ReadAll(rec.Result().Body)
if !strings.Contains(string(body), "data-overlay") || !strings.Contains(string(body), project.Images[0].Path) {
t.Fatalf("overlay fragment missing expected content: %s", body)
}
}
func TestProjectDetailRendersDepthFields(t *testing.T) {
srv := newTestServer(t)
req := httptest.NewRequest(http.MethodGet, "/projects/courtyard-house", nil)
rec := httptest.NewRecorder()
srv.Routes().ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected ok, got %d", rec.Code)
}
body, _ := io.ReadAll(rec.Result().Body)
text := string(body)
for _, want := range []string{"Scope", "Completed", "Architecture, interiors, material strategy", "A private house arranged around a quiet internal garden."} {
if !strings.Contains(text, want) {
t.Fatalf("project detail missing %q: %s", want, text)
}
}
}