2026-05-16 23:03:50 +00:00
package app
import (
"net/http"
"net/http/httptest"
"net/url"
"strings"
"testing"
)
func TestAdminMutationsRedirectToOwningTabs ( t * testing . T ) {
srv := newTestServer ( t )
handler := srv . Routes ( )
cookie := loginCookie ( t , handler )
for _ , test := range [ ] struct {
path string
form url . Values
want string
} {
{
path : "/admin/contact-details" ,
form : url . Values { "email" : { "studio@example.com" } , "phone" : { "123" } , "location" : { "London" } } ,
want : "/admin/contact-details?ok=contact+details+saved" ,
} ,
{
path : "/admin/content" ,
form : url . Values {
"hero_title" : { "Hero" } , "hero_subtitle" : { "Subtitle" } , "intro_title" : { "Intro" } , "intro_text" : { "Text" } ,
"about_name" : { "Name" } , "about_role" : { "Role" } , "about_bio" : { "Bio" } ,
2026-05-17 12:36:50 +00:00
"positioning" : { "Residential architect in London" } , "hero_cta_label" : { "Enquire" } , "hero_cta_url" : { "/contact" } ,
"secondary_cta_label" : { "Projects" } , "secondary_cta_url" : { "/projects" } ,
"service_one_title" : { "Homes" } , "service_one_text" : { "Home text" } ,
"service_two_title" : { "Interiors" } , "service_two_text" : { "Interior text" } ,
"service_three_title" : { "Consulting" } , "service_three_text" : { "Consulting text" } ,
"process_one_title" : { "Listen" } , "process_one_text" : { "Listen text" } ,
"process_two_title" : { "Shape" } , "process_two_text" : { "Shape text" } ,
"process_three_title" : { "Refine" } , "process_three_text" : { "Refine text" } ,
"studio_philosophy" : { "Philosophy" } , "studio_approach" : { "Approach" } , "studio_credentials" : { "Credentials" } , "service_area" : { "London" } ,
2026-05-16 23:03:50 +00:00
"hero_image_current" : { "/static/placeholders/hero.svg" } , "about_image_current" : { "/static/placeholders/about.svg" } ,
} ,
want : "/admin/main?ok=content+saved" ,
} ,
} {
req := httptest . NewRequest ( http . MethodPost , test . path , strings . NewReader ( test . form . Encode ( ) ) )
req . Header . Set ( "Content-Type" , "application/x-www-form-urlencoded" )
req . AddCookie ( cookie )
rec := httptest . NewRecorder ( )
handler . ServeHTTP ( rec , req )
if rec . Code != http . StatusSeeOther || rec . Header ( ) . Get ( "Location" ) != test . want {
t . Fatalf ( "%s expected redirect %q, got %d %q" , test . path , test . want , rec . Code , rec . Header ( ) . Get ( "Location" ) )
}
}
}
func TestAdminProjectValidation ( t * testing . T ) {
srv := newTestServer ( t )
handler := srv . Routes ( )
cookie := loginCookie ( t , handler )
2026-05-17 12:36:50 +00:00
form := url . Values { "title" : { " " } , "location" : { "London" } , "year" : { "2026" } , "category" : { "Residential" } , "summary" : { "Summary" } , "scope" : { "Scope" } , "status" : { "Completed" } , "description" : { "Text" } }
2026-05-16 23:03:50 +00:00
req := httptest . NewRequest ( http . MethodPost , "/admin/projects" , strings . NewReader ( form . Encode ( ) ) )
req . Header . Set ( "Content-Type" , "application/x-www-form-urlencoded" )
req . AddCookie ( cookie )
rec := httptest . NewRecorder ( )
handler . ServeHTTP ( rec , req )
if rec . Code != http . StatusSeeOther {
t . Fatalf ( "expected redirect, got %d" , rec . Code )
}
if location := rec . Header ( ) . Get ( "Location" ) ; ! strings . Contains ( location , "/admin/projects?err=" ) || ! strings . Contains ( location , "project+title+is+required" ) {
t . Fatalf ( "expected validation error redirect, got %q" , location )
}
}
2026-05-17 12:36:50 +00:00
func TestAdminProjectCreatePersistsDepthFields ( t * testing . T ) {
srv := newTestServer ( t )
handler := srv . Routes ( )
cookie := loginCookie ( t , handler )
form := url . Values {
"title" : { "Garden Studio" } ,
"location" : { "London" } ,
"year" : { "2026" } ,
"category" : { "Residential" } ,
"summary" : { "A compact studio in a rear garden." } ,
"scope" : { "Architecture, interiors" } ,
"status" : { "In progress" } ,
"position" : { "12" } ,
"description" : { "A small project with careful storage and daylight." } ,
"featured" : { "on" } ,
}
req := httptest . NewRequest ( http . MethodPost , "/admin/projects" , strings . NewReader ( form . Encode ( ) ) )
req . Header . Set ( "Content-Type" , "application/x-www-form-urlencoded" )
req . AddCookie ( cookie )
rec := httptest . NewRecorder ( )
handler . ServeHTTP ( rec , req )
if rec . Code != http . StatusSeeOther || rec . Header ( ) . Get ( "Location" ) != "/admin/projects?ok=project+created" {
t . Fatalf ( "expected create redirect, got %d %q" , rec . Code , rec . Header ( ) . Get ( "Location" ) )
}
project , err := srv . store . ProjectBySlug ( t . Context ( ) , "garden-studio" )
if err != nil {
t . Fatal ( err )
}
if project . Summary != "A compact studio in a rear garden." || project . Scope != "Architecture, interiors" || project . Status != "In progress" || project . Position != 12 {
t . Fatalf ( "unexpected project depth fields: %+v" , project )
}
}
func TestAdminServiceAndFAQMutations ( t * testing . T ) {
srv := newTestServer ( t )
handler := srv . Routes ( )
cookie := loginCookie ( t , handler )
serviceForm := url . Values {
"title" : { "Planning advice" } ,
"summary" : { "Early advice for planning routes." } ,
"details" : { "Detailed planning route guidance." } ,
"position" : { "8" } ,
"active" : { "on" } ,
}
req := httptest . NewRequest ( http . MethodPost , "/admin/services" , strings . NewReader ( serviceForm . Encode ( ) ) )
req . Header . Set ( "Content-Type" , "application/x-www-form-urlencoded" )
req . AddCookie ( cookie )
rec := httptest . NewRecorder ( )
handler . ServeHTTP ( rec , req )
if rec . Code != http . StatusSeeOther || rec . Header ( ) . Get ( "Location" ) != "/admin/services?ok=service+created" {
t . Fatalf ( "expected service redirect, got %d %q" , rec . Code , rec . Header ( ) . Get ( "Location" ) )
}
faqForm := url . Values {
"question" : { "Can you help before purchase?" } ,
"answer" : { "Yes, early consultation can clarify feasibility." } ,
"position" : { "9" } ,
"active" : { "on" } ,
}
req = httptest . NewRequest ( http . MethodPost , "/admin/faqs" , strings . NewReader ( faqForm . Encode ( ) ) )
req . Header . Set ( "Content-Type" , "application/x-www-form-urlencoded" )
req . AddCookie ( cookie )
rec = httptest . NewRecorder ( )
handler . ServeHTTP ( rec , req )
if rec . Code != http . StatusSeeOther || rec . Header ( ) . Get ( "Location" ) != "/admin/services?ok=FAQ+created" {
t . Fatalf ( "expected FAQ redirect, got %d %q" , rec . Code , rec . Header ( ) . Get ( "Location" ) )
}
services , err := srv . store . Services ( t . Context ( ) , false )
if err != nil {
t . Fatal ( err )
}
faqs , err := srv . store . FAQs ( t . Context ( ) , false )
if err != nil {
t . Fatal ( err )
}
if len ( services ) < 5 || len ( faqs ) < 4 {
t . Fatalf ( "expected created service and FAQ, got services=%d faqs=%d" , len ( services ) , len ( faqs ) )
}
}