readysite / website / controllers / collections_test.go
6.3 KB
collections_test.go
package controllers

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

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

// Test database setup is handled by testhelper_test.go

func TestCollectionsController_Create(t *testing.T) {
	tests := []struct {
		name       string
		formData   url.Values
		wantStatus int
	}{
		{
			name: "valid collection",
			formData: url.Values{
				"name":        {"Blog Posts"},
				"slug":        {"blog-posts"},
				"description": {"A collection of blog posts"},
				"schema":      {`[{"name":"title","type":"text","required":true}]`},
			},
			wantStatus: http.StatusSeeOther,
		},
		{
			name: "missing name",
			formData: url.Values{
				"slug":        {"no_name"},
				"description": {"Missing name"},
			},
			wantStatus: http.StatusOK, // error page
		},
	}

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

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

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

func TestCollectionsController_CreateDocument(t *testing.T) {
	// Create a collection first
	col := &models.Collection{
		Name:   "Test Collection",
		Schema: `[{"name":"title","type":"text","required":true}]`,
	}
	col.ID = "test-col"
	models.Collections.Insert(col)

	tests := []struct {
		name       string
		formData   url.Values
		wantStatus int
	}{
		{
			name: "valid document",
			formData: url.Values{
				"title": {"Test Document"},
			},
			wantStatus: http.StatusSeeOther,
		},
		{
			name: "missing required field",
			formData: url.Values{
				"other": {"value"},
			},
			wantStatus: http.StatusOK, // validation error
		},
	}

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

			c := testCollectionsController()
			handler := c.Handle(req)
			handler.(*CollectionsController).CreateDocument(w, req)

			if w.Code != tt.wantStatus {
				t.Errorf("CreateDocument() status = %d, want %d, body: %s", w.Code, tt.wantStatus, w.Body.String())
			}
		})
	}
}

func TestCollectionsController_UpdateDocument(t *testing.T) {
	// Create collection and document with unique IDs
	col := &models.Collection{
		Name:   "Update Test Collection",
		Schema: `[{"name":"title","type":"text","required":true}]`,
	}
	col.ID = "update-col-unique"
	models.Collections.Insert(col)

	doc := &models.Document{
		CollectionID: "update-col-unique",
		Data:         `{"title":"Original"}`,
	}
	doc.ID = "update-doc-unique"
	models.Documents.Insert(doc)

	// Re-fetch to get the correct UpdatedAt timestamp
	doc, _ = models.Documents.Get("update-doc-unique")

	formData := url.Values{
		"title":   {"Updated Title"},
		"version": {doc.UpdatedAt.Format("2006-01-02T15:04:05")},
	}

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

	c := testCollectionsController()
	handler := c.Handle(req)
	handler.(*CollectionsController).UpdateDocument(w, req)

	if w.Code != http.StatusSeeOther {
		t.Errorf("UpdateDocument() status = %d, want %d, body: %s", w.Code, http.StatusSeeOther, w.Body.String())
	}

	// Verify update
	updated, _ := models.Documents.Get("update-doc-unique")
	if updated.GetString("title") != "Updated Title" {
		t.Error("Document not updated correctly")
	}
}

func TestCollectionsController_DeleteDocument(t *testing.T) {
	// Create collection and document with unique IDs
	col := &models.Collection{
		Name: "Delete Test Collection",
	}
	col.ID = "delete-col-unique"
	models.Collections.Insert(col)

	doc := &models.Document{
		CollectionID: "delete-col-unique",
		Data:         `{"title":"To Delete"}`,
	}
	doc.ID = "delete-doc-unique"
	models.Documents.Insert(doc)

	req := httptest.NewRequest("DELETE", "/admin/collections/delete-col-unique/documents/delete-doc-unique", nil)
	req.SetPathValue("id", "delete-col-unique")
	req.SetPathValue("doc", "delete-doc-unique")
	authenticateRequest(req)
	w := httptest.NewRecorder()

	c := testCollectionsController()
	handler := c.Handle(req)
	handler.(*CollectionsController).DeleteDocument(w, req)

	// Verify deletion
	_, err := models.Documents.Get("delete-doc-unique")
	if err == nil {
		t.Error("Document should be deleted")
	}
}

func TestCollectionsController_SchemaValidation(t *testing.T) {
	// Create collection with typed schema
	col := &models.Collection{
		Name:   "Typed Collection",
		Schema: `[{"name":"count","type":"number","required":true},{"name":"email","type":"email","required":true}]`,
	}
	col.ID = "typed-col"
	models.Collections.Insert(col)

	tests := []struct {
		name       string
		formData   url.Values
		wantStatus int
	}{
		{
			name: "valid typed data",
			formData: url.Values{
				"count": {"42"},
				"email": {"test@example.com"},
			},
			wantStatus: http.StatusSeeOther,
		},
		{
			name: "invalid email",
			formData: url.Values{
				"count": {"42"},
				"email": {"not-an-email"},
			},
			wantStatus: http.StatusOK, // validation error
		},
	}

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

			c := testCollectionsController()
			handler := c.Handle(req)
			handler.(*CollectionsController).CreateDocument(w, req)

			if w.Code != tt.wantStatus {
				t.Errorf("CreateDocument() with %s: status = %d, want %d, body: %s", tt.name, w.Code, tt.wantStatus, w.Body.String())
			}
		})
	}
}
← Back