package controller
import (
"errors"
"html/template"
"net/http"
"net/http/httptest"
"strings"
"testing"
"git.aetherial.dev/aeth/keiji/pkg/storage"
"github.com/gin-gonic/gin"
)
type htmlLegacyRepo struct {
storage.DocumentIO
category string
}
func (r *htmlLegacyRepo) GetDocument(storage.Identifier) (storage.Document, error) {
return storage.Document{Title: "post"}, nil
}
func (r *htmlLegacyRepo) GetByCategory(category string) []storage.Document {
r.category = category
return nil
}
func (r *htmlLegacyRepo) GetImagesByCategory(category string) []storage.Image {
r.category = category
return nil
}
func (r *htmlLegacyRepo) GetNavBarLinks() []storage.NavBarItem { return nil }
func (r *htmlLegacyRepo) GetDropdownElements() []storage.LinkPair { return nil }
type htmlErrorRepo struct {
*htmlLegacyRepo
storage.DocumentListReader
fail string
}
func (r *htmlErrorRepo) listError(name string) error {
if r.fail == name {
return errors.New("list failure: " + name)
}
return nil
}
func (r *htmlErrorRepo) GetByCategoryWithError(category string) ([]storage.Document, error) {
r.category = category
return nil, r.listError("documents")
}
func (r *htmlErrorRepo) GetImagesByCategoryWithError(category string) ([]storage.Image, error) {
r.category = category
return nil, r.listError("images")
}
func (r *htmlErrorRepo) GetNavBarLinksWithError() ([]storage.NavBarItem, error) {
return nil, r.listError("navbar")
}
func (r *htmlErrorRepo) GetDropdownElementsWithError() ([]storage.LinkPair, error) {
return nil, r.listError("menu")
}
func htmlTestRouter(repo storage.DocumentIO) *gin.Engine {
r := gin.New()
r.SetHTMLTemplate(template.Must(template.New("test").Parse(`{{define "home"}}{{.default.Body}}{{end}}{{define "writing"}}writing{{end}}{{define "digital_art"}}digital{{end}}{{define "blogpost"}}{{.Title}}{{end}}`)))
c := &Controller{database: repo}
r.GET("/", c.ServeHome)
r.GET("/blog", c.ServeBlog)
r.GET("/creative", c.ServeCreative)
r.GET("/digital", c.ServeDigitalArt)
r.GET("/writing/:id", c.ServePost)
return r
}
func TestHTMLListFailures(t *testing.T) {
gin.SetMode(gin.TestMode)
for _, tc := range []struct{ path, failure string }{
{"/", "documents"}, {"/", "navbar"}, {"/", "menu"},
{"/blog", "documents"}, {"/creative", "documents"},
{"/digital", "images"}, {"/digital", "navbar"}, {"/digital", "menu"},
{"/writing/id", "navbar"}, {"/writing/id", "menu"},
} {
t.Run(tc.path+"/"+tc.failure, func(t *testing.T) {
repo := &htmlErrorRepo{htmlLegacyRepo: &htmlLegacyRepo{}, fail: tc.failure}
response := httptest.NewRecorder()
htmlTestRouter(repo).ServeHTTP(response, httptest.NewRequest(http.MethodGet, tc.path, nil))
if response.Code != http.StatusInternalServerError || !strings.Contains(response.Body.String(), "Could not load content") {
t.Fatalf("got status %d body %q", response.Code, response.Body.String())
}
})
}
}
func TestHTMLListEmptyAndLegacyCompatibility(t *testing.T) {
gin.SetMode(gin.TestMode)
for _, legacy := range []bool{false, true} {
for _, tc := range []struct{ path, category, body string }{
{"/", storage.HOMEPAGE, "Under construction. Sry :("},
{"/blog", storage.BLOG, "writing"}, {"/creative", storage.CREATIVE, "writing"},
{"/digital", storage.DIGITAL_ART, "digital"}, {"/writing/id", "", "post"},
} {
t.Run(tc.path+map[bool]string{true: "/legacy", false: "/error-reader"}[legacy], func(t *testing.T) {
base := &htmlLegacyRepo{}
var repo storage.DocumentIO = base
if !legacy {
repo = &htmlErrorRepo{htmlLegacyRepo: base}
}
response := httptest.NewRecorder()
htmlTestRouter(repo).ServeHTTP(response, httptest.NewRequest(http.MethodGet, tc.path, nil))
if response.Code != http.StatusOK || !strings.Contains(response.Body.String(), tc.body) || base.category != tc.category {
t.Fatalf("got status %d body %q category %q", response.Code, response.Body.String(), base.category)
}
})
}
}
}
func (r *htmlErrorRepo) GetAssetsWithError() ([]storage.Asset, error) {
return nil, r.listError("assets")
}
func (r *htmlLegacyRepo) GetAssets() []storage.Asset { return nil }
func TestAssetListFailureReturns500(t *testing.T) {
gin.SetMode(gin.TestMode)
r := gin.New()
repo := &htmlErrorRepo{htmlLegacyRepo: &htmlLegacyRepo{}, fail: "assets"}
c := &Controller{database: repo}
r.GET("/assets/:file", c.ServeAsset)
rec := httptest.NewRecorder()
r.ServeHTTP(rec, httptest.NewRequest("GET", "/assets/test.png", nil))
if rec.Code != http.StatusInternalServerError || !strings.Contains(rec.Body.String(), "Could not load content") {
t.Fatalf("%d %s", rec.Code, rec.Body.String())
}
}