You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

322 lines
7.1 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. // Copyright 2018 Lars Hoogestraat
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package handler_test
  5. import (
  6. "fmt"
  7. "net/http/httptest"
  8. "net/url"
  9. "strings"
  10. "strconv"
  11. "testing"
  12. "git.hoogi.eu/snafu/go-blog/handler"
  13. "git.hoogi.eu/snafu/go-blog/models"
  14. )
  15. func TestArticleWorkflow(t *testing.T) {
  16. setup(t)
  17. defer teardown()
  18. artID, err := doAdminCreateArticleRequest(rAdminUser, getSampleArticle())
  19. if err != nil {
  20. t.Fatal(err)
  21. }
  22. rcvArticle, err2 := doAdminGetArticleByIDRequest(rAdminUser, artID)
  23. if err2 != nil {
  24. t.Fatal(err)
  25. }
  26. if err = checkArticle(rcvArticle, getSampleArticle()); err != nil {
  27. t.Fatal(err)
  28. }
  29. updatedArticle := &models.Article{
  30. ID: artID,
  31. Slug: rcvArticle.Slug,
  32. Headline: "a new headline",
  33. Teaser: "A sample teaser",
  34. Content: "A new h1 header\n============\nthis is sample new content...",
  35. }
  36. if err := doAdminEditArticleRequest(rAdminUser, artID, updatedArticle); err != nil {
  37. t.Fatal(err)
  38. }
  39. rcvArticle, err = doAdminGetArticleByIDRequest(rAdminUser, artID)
  40. if err != nil {
  41. t.Fatal(err)
  42. }
  43. //Guest user should not see unpublished articles
  44. rcvArticle, err = doGetArticleByIDRequest(rGuest, artID)
  45. if err == nil {
  46. t.Fatal(err)
  47. }
  48. err = doAdminPublishArticleRequest(rAdminUser, artID)
  49. if err != nil {
  50. t.Fatal(err)
  51. }
  52. rcvArticle, err = doGetArticleByIDRequest(rAdminUser, artID)
  53. if err != nil {
  54. t.Fatal(err)
  55. }
  56. updatedArticle.Published = true
  57. if err = checkArticle(rcvArticle, updatedArticle); err != nil {
  58. t.Fatal(err)
  59. }
  60. err = doAdminRemoveArticleRequest(rAdminUser, artID)
  61. if err != nil {
  62. t.Fatal(err)
  63. }
  64. rcvArticle, err = doGetArticleByIDRequest(rAdminUser, artID)
  65. if err == nil {
  66. t.Fatalf("removed article, but got a category %v", rcvArticle)
  67. }
  68. }
  69. func checkArticle(article *models.Article, expectedArticle *models.Article) error {
  70. if article.Headline != expectedArticle.Headline {
  71. return fmt.Errorf("got an unexpected headline. expected: %s, actual: %s", expectedArticle.Headline, article.Headline)
  72. }
  73. if article.Content != expectedArticle.Content {
  74. return fmt.Errorf("got an unexpected content. expected: %s, actual: %s", expectedArticle.Content, article.Content)
  75. }
  76. if article.Published != expectedArticle.Published {
  77. return fmt.Errorf("the article published differs. expected: %t, actual: %t", expectedArticle.Published, article.Published)
  78. }
  79. if article.Author.ID != dummyAdminUser().ID {
  80. return fmt.Errorf("the author id is wrong. expected: %d, actual: %d", expectedArticle.Author.ID, article.Author.ID)
  81. }
  82. return nil
  83. }
  84. func getSampleArticle() *models.Article {
  85. return &models.Article{
  86. Headline: "a sample headline",
  87. Teaser: "A sample teaser",
  88. Content: "An h1 header\n============\nthis is sample content...",
  89. Author: dummyAdminUser(),
  90. }
  91. }
  92. func doGetArticleBySlugRequest(user reqUser, article *models.Article) (*models.Article, error) {
  93. split := strings.Split(article.Slug, "/")
  94. if len(split) != 3 {
  95. return nil, fmt.Errorf("invalid slug length %v", article.Slug)
  96. }
  97. r := request{
  98. url: "/articles/" + split[0] + "/" + split[1] + "/" + split[2] + "/",
  99. method: "GET",
  100. pathVar: []pathVar{
  101. pathVar{
  102. key: "year",
  103. value: split[0],
  104. }, pathVar{
  105. key: "month",
  106. value: split[1],
  107. }, pathVar{
  108. key: "slug",
  109. value: split[2],
  110. },
  111. },
  112. }
  113. rw := httptest.NewRecorder()
  114. tpl := handler.GetArticleHandler(ctx, rw, r.buildRequest())
  115. if tpl.Err != nil {
  116. return nil, tpl.Err
  117. }
  118. return tpl.Data["article"].(*models.Article), nil
  119. }
  120. func doGetArticleByIDRequest(user reqUser, articleID int) (*models.Article, error) {
  121. r := request{
  122. url: "/article/by-id/" + strconv.Itoa(articleID),
  123. method: "GET",
  124. user: user,
  125. pathVar: []pathVar{
  126. pathVar{
  127. key: "articleID",
  128. value: strconv.Itoa(articleID),
  129. },
  130. },
  131. }
  132. rw := httptest.NewRecorder()
  133. tpl := handler.GetArticleByIDHandler(ctx, rw, r.buildRequest())
  134. if tpl.Err != nil {
  135. return nil, tpl.Err
  136. }
  137. return tpl.Data["article"].(*models.Article), nil
  138. }
  139. func doAdminEditArticleRequest(user reqUser, articleID int, article *models.Article) error {
  140. values := url.Values{}
  141. addValue(values, "headline", article.Headline)
  142. addValue(values, "teaser", article.Teaser)
  143. addValue(values, "content", article.Content)
  144. r := request{
  145. url: "/admin/article/edit/" + strconv.Itoa(articleID),
  146. user: user,
  147. method: "POST",
  148. values: values,
  149. pathVar: []pathVar{
  150. pathVar{
  151. key: "articleID",
  152. value: strconv.Itoa(articleID),
  153. },
  154. },
  155. }
  156. rw := httptest.NewRecorder()
  157. tpl := handler.AdminArticleEditPostHandler(ctx, rw, r.buildRequest())
  158. if tpl.Err != nil {
  159. return tpl.Err
  160. }
  161. if len(tpl.SuccessMsg) == 0 {
  162. return fmt.Errorf("The success message is empty")
  163. }
  164. return nil
  165. }
  166. func doAdminCreateArticleRequest(user reqUser, article *models.Article) (int, error) {
  167. values := url.Values{}
  168. addValue(values, "headline", article.Headline)
  169. addValue(values, "teaser", article.Teaser)
  170. addValue(values, "content", article.Content)
  171. r := request{
  172. url: "/admin/article/new",
  173. user: user,
  174. method: "POST",
  175. values: values,
  176. }
  177. rw := httptest.NewRecorder()
  178. tpl := handler.AdminArticleNewPostHandler(ctx, rw, r.buildRequest())
  179. if tpl.Err != nil {
  180. return 0, tpl.Err
  181. }
  182. if len(tpl.SuccessMsg) == 0 {
  183. return -1, fmt.Errorf("there is no success message returned")
  184. }
  185. return tpl.Data["articleID"].(int), nil
  186. }
  187. func doAdminGetArticleByIDRequest(user reqUser, articleID int) (*models.Article, error) {
  188. r := request{
  189. url: "/admin/article" + strconv.Itoa(articleID),
  190. method: "GET",
  191. user: user,
  192. pathVar: []pathVar{
  193. pathVar{
  194. key: "articleID",
  195. value: strconv.Itoa(articleID),
  196. },
  197. },
  198. }
  199. rw := httptest.NewRecorder()
  200. tpl := handler.AdminPreviewArticleByIDHandler(ctx, rw, r.buildRequest())
  201. if tpl.Err != nil {
  202. return nil, tpl.Err
  203. }
  204. return tpl.Data["article"].(*models.Article), nil
  205. }
  206. func doAdminListArticleRequest(user reqUser) ([]models.Article, error) {
  207. r := request{
  208. url: "/admin/articles",
  209. user: user,
  210. method: "GET",
  211. }
  212. rw := httptest.NewRecorder()
  213. tpl := handler.AdminListArticlesHandler(ctx, rw, r.buildRequest())
  214. if tpl.Err != nil {
  215. return nil, tpl.Err
  216. }
  217. return tpl.Data["articles"].([]models.Article), nil
  218. }
  219. func doAdminPublishArticleRequest(user reqUser, articleID int) error {
  220. r := request{
  221. url: "/admin/article/publish/" + strconv.Itoa(articleID),
  222. user: user,
  223. method: "GET",
  224. pathVar: []pathVar{
  225. pathVar{
  226. key: "articleID",
  227. value: strconv.Itoa(articleID),
  228. },
  229. },
  230. }
  231. rw := httptest.NewRecorder()
  232. tpl := handler.AdminArticlePublishPostHandler(ctx, rw, r.buildRequest())
  233. if tpl.Err != nil {
  234. return tpl.Err
  235. }
  236. return nil
  237. }
  238. func doAdminRemoveArticleRequest(user reqUser, articleID int) error {
  239. r := request{
  240. url: "/admin/article/remove/" + strconv.Itoa(articleID),
  241. user: user,
  242. method: "POST",
  243. pathVar: []pathVar{
  244. pathVar{
  245. key: "articleID",
  246. value: strconv.Itoa(articleID),
  247. },
  248. },
  249. }
  250. rw := httptest.NewRecorder()
  251. tpl := handler.AdminArticleDeletePostHandler(ctx, rw, r.buildRequest())
  252. if tpl.Err != nil {
  253. return tpl.Err
  254. }
  255. return nil
  256. }