readysite / website / controllers / pages_test.go
4.8 KB
pages_test.go
package controllers

import (
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"testing"

	"github.com/readysite/readysite/website/internal/content"
	"github.com/readysite/readysite/website/models"
)

// Test database setup is handled by testhelper_test.go

func TestPagesController_Create(t *testing.T) {
	// Create controller
	_, c := Pages()
	c.Setup(nil)

	tests := []struct {
		name       string
		formData   url.Values
		wantStatus int
	}{
		{
			name: "valid page creation",
			formData: url.Values{
				"title": {"Test Page"},
				"slug":  {"test-page"},
				"html":  {"<h1>Hello</h1>"},
			},
			wantStatus: http.StatusSeeOther, // redirect on success
		},
		{
			name: "missing title",
			formData: url.Values{
				"slug": {"no-title"},
				"html": {"<p>Content</p>"},
			},
			wantStatus: http.StatusOK, // error rendered as HTML
		},
		{
			name: "invalid slug with spaces",
			formData: url.Values{
				"title": {"Bad Slug"},
				"slug":  {"bad slug"},
				"html":  {"<p>Content</p>"},
			},
			wantStatus: http.StatusOK, // validation error
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			req := httptest.NewRequest("POST", "/admin/pages", strings.NewReader(tt.formData.Encode()))
			req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
			w := httptest.NewRecorder()

			handler := c.Handle(req)
			handler.(*PagesController).Create(w, req)

			if w.Code != tt.wantStatus {
				t.Errorf("Create() status = %d, want %d", w.Code, tt.wantStatus)
			}
		})
	}
}

func TestPagesController_SlugValidation(t *testing.T) {
	tests := []struct {
		slug  string
		valid bool
	}{
		{"valid-slug", true},
		{"another123", true},
		{"has space", false},
		{"has/slash", false},
		{"UPPERCASE", false},
		{"special!char", false},
		{"admin", false}, // reserved
		{"api", false},   // reserved
	}

	for _, tt := range tests {
		t.Run(tt.slug, func(t *testing.T) {
			// Test validation through form submission
			formData := url.Values{
				"title": {"Test"},
				"slug":  {tt.slug},
				"html":  {"<p>Test</p>"},
			}

			req := httptest.NewRequest("POST", "/admin/pages", strings.NewReader(formData.Encode()))
			req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
			w := httptest.NewRecorder()

			_, c := Pages()
			handler := c.Handle(req)
			handler.(*PagesController).Create(w, req)

			isRedirect := w.Code == http.StatusSeeOther
			if isRedirect != tt.valid {
				t.Errorf("slug %q: got redirect=%v, want valid=%v (status=%d)", tt.slug, isRedirect, tt.valid, w.Code)
			}
		})
	}
}

func TestPagesController_Update(t *testing.T) {
	// Create a test page first
	page := &models.Page{
		ParentID: "",
	}
	page.ID = "update-test"
	models.Pages.Insert(page)
	content.SavePageContent(page, "Original Title", "Original desc", "<h1>Original</h1>", "", models.StatusDraft)

	// Update the page
	formData := url.Values{
		"title":       {"Updated Title"},
		"description": {"Updated description"},
	}

	req := httptest.NewRequest("PUT", "/admin/pages/update-test", strings.NewReader(formData.Encode()))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	req.SetPathValue("id", "update-test")
	w := httptest.NewRecorder()

	_, c := Pages()
	handler := c.Handle(req)
	handler.(*PagesController).Update(w, req)

	if w.Code != http.StatusSeeOther {
		t.Errorf("Update() status = %d, want %d", w.Code, http.StatusSeeOther)
	}

	// Verify update
	updated, _ := models.Pages.Get("update-test")
	content := updated.LatestContent()
	if content == nil || content.Title != "Updated Title" {
		t.Errorf("Page not updated correctly")
	}
}

func TestPagesController_Delete(t *testing.T) {
	// Create a test page
	page := &models.Page{}
	page.ID = "delete-test"
	models.Pages.Insert(page)

	req := httptest.NewRequest("DELETE", "/admin/pages/delete-test", nil)
	req.SetPathValue("id", "delete-test")
	w := httptest.NewRecorder()

	_, c := Pages()
	handler := c.Handle(req)
	handler.(*PagesController).Delete(w, req)

	if w.Code != http.StatusSeeOther {
		t.Errorf("Delete() status = %d, want %d", w.Code, http.StatusSeeOther)
	}

	// Verify deletion
	_, err := models.Pages.Get("delete-test")
	if err == nil {
		t.Error("Page should be deleted")
	}
}

func TestPagesController_TogglePublish(t *testing.T) {
	// Create an unpublished page with draft content
	page := &models.Page{}
	page.ID = "publish-test"
	models.Pages.Insert(page)
	content.SavePageContent(page, "Test Page", "Description", "<h1>Test</h1>", "", models.StatusDraft)

	req := httptest.NewRequest("POST", "/admin/pages/publish-test/publish", nil)
	req.SetPathValue("id", "publish-test")
	w := httptest.NewRecorder()

	_, c := Pages()
	handler := c.Handle(req)
	handler.(*PagesController).TogglePublish(w, req)

	// Verify toggle - page should now have published content
	toggled, _ := models.Pages.Get("publish-test")
	if !toggled.IsPublished() {
		t.Error("Page should be published after toggle")
	}
}
← Back