readysite / website / controllers / files_test.go
4.5 KB
files_test.go
package controllers

import (
	"bytes"
	"mime/multipart"
	"net/http"
	"net/http/httptest"
	"testing"

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

// Test database setup is handled by testhelper_test.go

func TestFilesController_Upload_ValidFile(t *testing.T) {
	// Create multipart form
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	// Add a test file
	part, err := writer.CreateFormFile("file", "test.txt")
	if err != nil {
		t.Fatal(err)
	}
	part.Write([]byte("Hello, World!"))
	writer.Close()

	req := httptest.NewRequest("POST", "/admin/files", body)
	req.Header.Set("Content-Type", writer.FormDataContentType())
	w := httptest.NewRecorder()

	_, c := Files()
	handler := c.Handle(req)
	handler.(*FilesController).Upload(w, req)

	// Should redirect on success or render page
	if w.Code != http.StatusSeeOther && w.Code != http.StatusOK {
		t.Errorf("Upload() status = %d, want %d or %d", w.Code, http.StatusSeeOther, http.StatusOK)
	}
}

func TestFilesController_Upload_TooLarge(t *testing.T) {
	// Create a file larger than 10MB
	largeData := make([]byte, 11*1024*1024)

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	part, err := writer.CreateFormFile("file", "large.bin")
	if err != nil {
		t.Fatal(err)
	}
	part.Write(largeData)
	writer.Close()

	req := httptest.NewRequest("POST", "/admin/files", body)
	req.Header.Set("Content-Type", writer.FormDataContentType())
	w := httptest.NewRecorder()

	_, c := Files()
	handler := c.Handle(req)
	handler.(*FilesController).Upload(w, req)

	// Should return error for too large file
	if w.Code == http.StatusSeeOther {
		t.Error("Upload() should reject files over 10MB")
	}
}

func TestFilesController_Upload_DisallowedExtension(t *testing.T) {
	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)

	// Try to upload an executable
	part, err := writer.CreateFormFile("file", "malware.exe")
	if err != nil {
		t.Fatal(err)
	}
	part.Write([]byte("MZ")) // PE header start
	writer.Close()

	req := httptest.NewRequest("POST", "/admin/files", body)
	req.Header.Set("Content-Type", writer.FormDataContentType())
	w := httptest.NewRecorder()

	_, c := Files()
	handler := c.Handle(req)
	handler.(*FilesController).Upload(w, req)

	// Should reject executable files
	if w.Code == http.StatusSeeOther {
		t.Error("Upload() should reject executable files")
	}
}

func TestFilesController_Delete(t *testing.T) {
	// Create a test file record
	file := &models.File{
		Name:     "delete-test.txt",
		MimeType: "text/plain",
		Size:     100,
	}
	file.ID = "delete-file-test"
	models.Files.Insert(file)

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

	_, c := Files()
	handler := c.Handle(req)
	handler.(*FilesController).Delete(w, req)

	// Verify deletion from database
	_, err := models.Files.Get("delete-file-test")
	if err == nil {
		t.Error("File record should be deleted")
	}
}

func TestFilesController_ValidExtensions(t *testing.T) {
	validExtensions := []string{".txt", ".pdf", ".jpg", ".png", ".gif", ".html", ".css", ".js", ".json", ".md"}
	invalidExtensions := []string{".exe", ".bat", ".sh", ".php", ".dll"}

	for _, ext := range validExtensions {
		body := &bytes.Buffer{}
		writer := multipart.NewWriter(body)
		part, _ := writer.CreateFormFile("file", "test"+ext)
		part.Write([]byte("test content"))
		writer.Close()

		req := httptest.NewRequest("POST", "/admin/files", body)
		req.Header.Set("Content-Type", writer.FormDataContentType())
		w := httptest.NewRecorder()

		_, c := Files()
		handler := c.Handle(req)
		handler.(*FilesController).Upload(w, req)

		// Valid extensions should succeed or at least not be rejected for extension
		// (may fail for other reasons like disk write in test)
		if w.Code == http.StatusBadRequest && bytes.Contains(w.Body.Bytes(), []byte("extension")) {
			t.Errorf("Extension %s should be allowed", ext)
		}
	}

	for _, ext := range invalidExtensions {
		body := &bytes.Buffer{}
		writer := multipart.NewWriter(body)
		part, _ := writer.CreateFormFile("file", "test"+ext)
		part.Write([]byte("test content"))
		writer.Close()

		req := httptest.NewRequest("POST", "/admin/files", body)
		req.Header.Set("Content-Type", writer.FormDataContentType())
		w := httptest.NewRecorder()

		_, c := Files()
		handler := c.Handle(req)
		handler.(*FilesController).Upload(w, req)

		// Invalid extensions should be rejected
		if w.Code == http.StatusSeeOther {
			t.Errorf("Extension %s should be blocked", ext)
		}
	}
}
← Back