admin_list_errors_test.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package controller
  2. import (
  3. "errors"
  4. "html/template"
  5. "net/http"
  6. "net/http/httptest"
  7. "strings"
  8. "testing"
  9. "git.aetherial.dev/aeth/keiji/pkg/auth"
  10. "git.aetherial.dev/aeth/keiji/pkg/storage"
  11. "github.com/gin-gonic/gin"
  12. )
  13. type adminLegacyListRepo struct{ *htmlLegacyRepo }
  14. func (r *adminLegacyListRepo) GetAdminTables() storage.AdminPage { return storage.AdminPage{} }
  15. func (r *adminLegacyListRepo) GetAllImages() []storage.Image { return nil }
  16. type adminErrorListRepo struct {
  17. *adminLegacyListRepo
  18. storage.DocumentListReader
  19. fail string
  20. }
  21. func (r *adminErrorListRepo) failure(name string) error {
  22. if r.fail == name {
  23. return errors.New("list failure: " + name)
  24. }
  25. return nil
  26. }
  27. func (r *adminErrorListRepo) GetAdminTablesWithError() (storage.AdminPage, error) {
  28. return storage.AdminPage{}, r.failure("tables")
  29. }
  30. func (r *adminErrorListRepo) GetAllImagesWithError() ([]storage.Image, error) {
  31. return nil, r.failure("all images")
  32. }
  33. func (r *adminErrorListRepo) GetImagesByCategoryWithError(category string) ([]storage.Image, error) {
  34. r.category = category
  35. return nil, r.failure("images")
  36. }
  37. func (r *adminErrorListRepo) GetByCategoryWithError(category string) ([]storage.Document, error) {
  38. r.category = category
  39. return nil, r.failure("documents")
  40. }
  41. func (r *adminErrorListRepo) GetNavBarLinksWithError() ([]storage.NavBarItem, error) {
  42. return nil, r.failure("navbar")
  43. }
  44. func (r *adminErrorListRepo) GetDropdownElementsWithError() ([]storage.LinkPair, error) {
  45. return nil, r.failure("menu")
  46. }
  47. type adminListAuth struct{}
  48. func (adminListAuth) AdminUsername() string { return "user" }
  49. func (adminListAuth) AdminPassword() string { return "pass" }
  50. func adminListRouter(repo storage.DocumentIO) *gin.Engine {
  51. r := gin.New()
  52. r.SetHTMLTemplate(template.Must(template.New("test").Parse(`{{define "admin"}}admin {{range index .Tables "modify"}}{{.DisplayName}}{{end}}{{end}}{{define "blogpost_editor"}}editor{{end}}{{define "navbar_editor"}}navbar editor{{end}}{{define "upload"}}upload{{end}}{{define "digital_art_admin_list"}}digital list{{end}}`)))
  53. c := &Controller{database: repo, Cache: auth.NewCache(), AuthSource: adminListAuth{}}
  54. r.POST("/login", c.Auth)
  55. r.GET("/panel", c.AdminPanel)
  56. r.GET("/navbar", c.ServeNavbarModify)
  57. r.GET("/blog", c.ServeBlogDirectory)
  58. r.GET("/editor/:id", c.GetBlogPostEditor)
  59. r.GET("/new-blog", c.ServeNewBlogPage)
  60. r.GET("/new-navbar", c.ServeNewNavbarItem)
  61. r.GET("/upload", c.ServeFileUpload)
  62. r.GET("/digital", c.ListDigitalArt)
  63. return r
  64. }
  65. func adminListRequest(r *gin.Engine, path string) *httptest.ResponseRecorder {
  66. method, body := http.MethodGet, ""
  67. if path == "/login" {
  68. method, body = http.MethodPost, "username=user&password=pass"
  69. }
  70. req := httptest.NewRequest(method, path, strings.NewReader(body))
  71. if method == http.MethodPost {
  72. req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  73. }
  74. response := httptest.NewRecorder()
  75. r.ServeHTTP(response, req)
  76. return response
  77. }
  78. func TestAdminListFailures(t *testing.T) {
  79. gin.SetMode(gin.TestMode)
  80. for _, tc := range []struct{ path, failure string }{
  81. {"/login", "tables"}, {"/login", "navbar"}, {"/login", "menu"},
  82. {"/panel", "tables"}, {"/panel", "navbar"}, {"/panel", "menu"},
  83. {"/navbar", "navbar"}, {"/navbar", "menu"},
  84. {"/blog", "documents"}, {"/blog", "navbar"}, {"/blog", "menu"},
  85. {"/editor/id", "all images"}, {"/editor/id", "navbar"}, {"/editor/id", "menu"},
  86. {"/new-blog", "all images"}, {"/new-blog", "navbar"}, {"/new-blog", "menu"},
  87. {"/new-navbar", "navbar"}, {"/new-navbar", "menu"},
  88. {"/upload", "navbar"}, {"/upload", "menu"}, {"/digital", "images"},
  89. } {
  90. t.Run(tc.path+"/"+tc.failure, func(t *testing.T) {
  91. repo := &adminErrorListRepo{adminLegacyListRepo: &adminLegacyListRepo{&htmlLegacyRepo{}}, fail: tc.failure}
  92. response := adminListRequest(adminListRouter(repo), tc.path)
  93. if response.Code != http.StatusInternalServerError || !strings.Contains(response.Body.String(), "Could not load content") {
  94. t.Fatalf("got status %d body %q", response.Code, response.Body.String())
  95. }
  96. if tc.path == "/login" && len(response.Result().Cookies()) != 0 {
  97. t.Fatal("failed login response set a cookie")
  98. }
  99. })
  100. }
  101. }
  102. func TestAdminListEmptyAndLegacyCompatibility(t *testing.T) {
  103. gin.SetMode(gin.TestMode)
  104. for _, legacy := range []bool{false, true} {
  105. for _, tc := range []struct{ path, body string }{
  106. {"/login", "Digital Art"}, {"/panel", "Digital Art"}, {"/navbar", "admin"}, {"/blog", "admin"},
  107. {"/editor/id", "editor"}, {"/new-blog", "editor"}, {"/new-navbar", "navbar editor"}, {"/upload", "upload"}, {"/digital", "digital list"},
  108. } {
  109. t.Run(tc.path+map[bool]string{true: "/legacy", false: "/error-reader"}[legacy], func(t *testing.T) {
  110. base := &adminLegacyListRepo{&htmlLegacyRepo{}}
  111. var repo storage.DocumentIO = base
  112. if !legacy {
  113. repo = &adminErrorListRepo{adminLegacyListRepo: base}
  114. }
  115. response := adminListRequest(adminListRouter(repo), tc.path)
  116. if response.Code != http.StatusOK || !strings.Contains(response.Body.String(), tc.body) {
  117. t.Fatalf("got status %d body %q", response.Code, response.Body.String())
  118. }
  119. if tc.path == "/digital" && base.category != storage.DIGITAL_ART {
  120. t.Fatalf("category = %q", base.category)
  121. }
  122. if tc.path == "/login" && len(response.Result().Cookies()) == 0 {
  123. t.Fatal("successful login did not set a cookie")
  124. }
  125. })
  126. }
  127. }
  128. }