article_test.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. package handler
  2. import (
  3. "context"
  4. "database/sql"
  5. "net/http/httptest"
  6. "testing"
  7. "github.com/brianvoe/gofakeit/v6"
  8. "github.com/gofiber/fiber/v2"
  9. "github.com/gojuno/minimock/v3"
  10. "github.com/stretchr/testify/assert"
  11. "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/helpers/test"
  12. "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/models"
  13. "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/services/handler/mocks"
  14. )
  15. func TestArticleHandler(t *testing.T) {
  16. t.Parallel()
  17. type req struct {
  18. method string
  19. route string
  20. }
  21. var (
  22. articleID = gofakeit.Uint64()
  23. articleURL = gofakeit.Word()
  24. publishTime = gofakeit.Date()
  25. internalErr = gofakeit.Error()
  26. article = models.Article{
  27. ID: articleID,
  28. URL: articleURL,
  29. Title: gofakeit.Phrase(),
  30. Text: gofakeit.Phrase(),
  31. PublishTime: publishTime,
  32. PreviewText: sql.NullString{Valid: true, String: gofakeit.Phrase()},
  33. Image: sql.NullString{Valid: true, String: gofakeit.URL()},
  34. IsActive: true,
  35. Language: models.LangRu,
  36. }
  37. notActiveArticle = models.Article{
  38. ID: articleID,
  39. URL: articleURL,
  40. Title: gofakeit.Phrase(),
  41. Text: gofakeit.Phrase(),
  42. PublishTime: publishTime,
  43. PreviewText: sql.NullString{Valid: true, String: gofakeit.Phrase()},
  44. Image: sql.NullString{Valid: true, String: gofakeit.URL()},
  45. Language: models.LangRu,
  46. }
  47. _ = internalErr
  48. _ = article
  49. _ = notActiveArticle
  50. tags = []models.Tag{
  51. {
  52. ID: gofakeit.Uint64(),
  53. Tag: gofakeit.Word(),
  54. URL: gofakeit.Word(),
  55. },
  56. {
  57. ID: gofakeit.Uint64(),
  58. Tag: gofakeit.Word(),
  59. URL: gofakeit.Word(),
  60. },
  61. }
  62. _ = tags
  63. previewArticles = []models.ArticlePreview{
  64. {
  65. ID: gofakeit.Uint64(),
  66. URL: gofakeit.URL(),
  67. Title: gofakeit.Phrase(),
  68. PublishTime: publishTime,
  69. PreviewText: sql.NullString{Valid: true, String: gofakeit.Phrase()},
  70. Image: sql.NullString{Valid: true, String: gofakeit.URL()},
  71. },
  72. {
  73. ID: gofakeit.Uint64(),
  74. URL: gofakeit.URL(),
  75. Title: gofakeit.Phrase(),
  76. PublishTime: publishTime,
  77. PreviewText: sql.NullString{Valid: true, String: gofakeit.Phrase()},
  78. Image: sql.NullString{Valid: true, String: gofakeit.URL()},
  79. },
  80. {
  81. ID: gofakeit.Uint64(),
  82. URL: gofakeit.URL(),
  83. Title: gofakeit.Phrase(),
  84. PublishTime: publishTime,
  85. PreviewText: sql.NullString{Valid: true, String: gofakeit.Phrase()},
  86. Image: sql.NullString{Valid: true, String: gofakeit.URL()},
  87. },
  88. {
  89. ID: gofakeit.Uint64(),
  90. URL: gofakeit.URL(),
  91. Title: gofakeit.Phrase(),
  92. PublishTime: publishTime,
  93. PreviewText: sql.NullString{Valid: true, String: gofakeit.Phrase()},
  94. Image: sql.NullString{Valid: true, String: gofakeit.URL()},
  95. },
  96. }
  97. _ = previewArticles
  98. )
  99. tests := []struct {
  100. name string
  101. req req
  102. res int
  103. err error
  104. cacheMock func(mc *minimock.Controller) CacheService
  105. tagMock func(mc *minimock.Controller) TagRepository
  106. articleMock func(mc *minimock.Controller) ArticleRepository
  107. }{
  108. // {
  109. // name: "positive case",
  110. // req: req{
  111. // method: fiber.MethodGet,
  112. // route: "/article/" + articleURL,
  113. // },
  114. // res: fiber.StatusOK,
  115. // err: nil,
  116. // cacheMock: func(mc *minimock.Controller) CacheService {
  117. // mock := mocks.NewCacheServiceMock(mc)
  118. // mock.GetMock.Return(nil, false)
  119. // mock.SetMock.Return()
  120. // return mock
  121. // },
  122. // tagMock: func(mc *minimock.Controller) TagRepository {
  123. // mock := mocks.NewTagRepositoryMock(mc)
  124. // mock.GetAllUsedMock.Return(tags, nil)
  125. // return mock
  126. // },
  127. // articleMock: func(mc *minimock.Controller) ArticleRepository {
  128. // mock := mocks.NewArticleRepositoryMock(mc)
  129. //
  130. // mock.GetByURLMock.Inspect(func(ctx context.Context, url string, lang models.Language) {
  131. // assert.Equal(mc, articleURL, url)
  132. // assert.Equal(mc, models.LangRu, lang)
  133. // }).Return(&article, nil)
  134. //
  135. // mock.GetAllPreviewMock.Return(previewArticles, nil)
  136. //
  137. // return mock
  138. // },
  139. // },
  140. {
  141. name: "negative case - article not found",
  142. req: req{
  143. method: fiber.MethodGet,
  144. route: "/article/" + articleURL,
  145. },
  146. res: fiber.StatusNotFound,
  147. err: nil,
  148. cacheMock: func(mc *minimock.Controller) CacheService {
  149. mock := mocks.NewCacheServiceMock(mc)
  150. mock.GetMock.Return(nil, false)
  151. return mock
  152. },
  153. tagMock: func(mc *minimock.Controller) TagRepository {
  154. mock := mocks.NewTagRepositoryMock(mc)
  155. return mock
  156. },
  157. articleMock: func(mc *minimock.Controller) ArticleRepository {
  158. mock := mocks.NewArticleRepositoryMock(mc)
  159. mock.GetByURLMock.Inspect(func(ctx context.Context, url string, lang models.Language) {
  160. assert.Equal(mc, articleURL, url)
  161. assert.Equal(mc, models.LangRu, lang)
  162. }).Return(nil, sql.ErrNoRows)
  163. return mock
  164. },
  165. },
  166. // {
  167. // name: "negative case - article repository error",
  168. // req: req{
  169. // method: fiber.MethodGet,
  170. // route: "/article/" + articleURL,
  171. // },
  172. // res: fiber.StatusInternalServerError,
  173. // err: nil,
  174. // cacheMock: func(mc *minimock.Controller) CacheService {
  175. // mock := mocks.NewCacheServiceMock(mc)
  176. // mock.GetMock.Return(nil, false)
  177. // return mock
  178. // },
  179. // tagMock: func(mc *minimock.Controller) TagRepository {
  180. // return mocks.NewTagRepositoryMock(mc)
  181. // },
  182. // articleMock: func(mc *minimock.Controller) ArticleRepository {
  183. // mock := mocks.NewArticleRepositoryMock(mc)
  184. // mock.GetByURLMock.Inspect(func(ctx context.Context, url string, lang models.Language) {
  185. // assert.Equal(mc, articleURL, url)
  186. // assert.Equal(mc, models.LangRu, lang)
  187. // }).Return(nil, internalErr)
  188. //
  189. // return mock
  190. // },
  191. // },
  192. // {
  193. // name: "negative case - article not active",
  194. // req: req{
  195. // method: fiber.MethodGet,
  196. // route: "/article/" + articleURL,
  197. // },
  198. // res: fiber.StatusNotFound,
  199. // err: nil,
  200. // cacheMock: func(mc *minimock.Controller) CacheService {
  201. // mock := mocks.NewCacheServiceMock(mc)
  202. // mock.GetMock.Return(nil, false)
  203. // return mock
  204. // },
  205. // tagMock: func(mc *minimock.Controller) TagRepository {
  206. // return mocks.NewTagRepositoryMock(mc)
  207. // },
  208. // articleMock: func(mc *minimock.Controller) ArticleRepository {
  209. // mock := mocks.NewArticleRepositoryMock(mc)
  210. // mock.GetByURLMock.Inspect(func(ctx context.Context, url string, lang models.Language) {
  211. // assert.Equal(mc, articleURL, url)
  212. // assert.Equal(mc, models.LangRu, lang)
  213. // }).Return(&notActiveArticle, nil)
  214. //
  215. // return mock
  216. // },
  217. // },
  218. // {
  219. // name: "negative case - tags repository error",
  220. // req: req{
  221. // method: fiber.MethodGet,
  222. // route: "/article/" + articleURL,
  223. // },
  224. // res: fiber.StatusInternalServerError,
  225. // err: nil,
  226. // cacheMock: func(mc *minimock.Controller) CacheService {
  227. // mock := mocks.NewCacheServiceMock(mc)
  228. // // mock.GetMock.Return(nil, false)
  229. //
  230. // return mock
  231. // },
  232. // tagMock: func(mc *minimock.Controller) TagRepository {
  233. // mock := mocks.NewTagRepositoryMock(mc)
  234. // mock.GetAllUsedMock.Return(nil, internalErr)
  235. // return mock
  236. // },
  237. // articleMock: func(mc *minimock.Controller) ArticleRepository {
  238. // mock := mocks.NewArticleRepositoryMock(mc)
  239. //
  240. // mock.GetByURLMock.Inspect(func(ctx context.Context, url string, lang models.Language) {
  241. // assert.Equal(mc, articleURL, url)
  242. // assert.Equal(mc, models.LangRu, lang)
  243. // }).Return(&article, nil)
  244. //
  245. // return mock
  246. // },
  247. // },
  248. // {
  249. // name: "negative case - articles repository error",
  250. // req: req{
  251. // method: fiber.MethodGet,
  252. // route: "/article/" + articleURL,
  253. // },
  254. // res: fiber.StatusInternalServerError,
  255. // err: nil,
  256. // cacheMock: func(mc *minimock.Controller) CacheService {
  257. // mock := mocks.NewCacheServiceMock(mc)
  258. // mock.GetMock.Return(nil, false)
  259. //
  260. // return mock
  261. // },
  262. // tagMock: func(mc *minimock.Controller) TagRepository {
  263. // mock := mocks.NewTagRepositoryMock(mc)
  264. // mock.GetAllUsedMock.Return(tags, nil)
  265. //
  266. // return mock
  267. // },
  268. // articleMock: func(mc *minimock.Controller) ArticleRepository {
  269. // mock := mocks.NewArticleRepositoryMock(mc)
  270. //
  271. // mock.GetByURLMock.Inspect(func(ctx context.Context, url string, lang models.Language) {
  272. // assert.Equal(mc, articleURL, url)
  273. // assert.Equal(mc, models.LangRu, lang)
  274. // }).Return(&article, nil)
  275. //
  276. // mock.GetAllPreviewMock.Return(nil, internalErr)
  277. //
  278. // return mock
  279. // },
  280. // },
  281. }
  282. for _, tt := range tests {
  283. t.Run(tt.name, func(t *testing.T) {
  284. t.Parallel()
  285. mc := minimock.NewController(t)
  286. fiberApp := fiber.New(test.GetFiberTestConfig())
  287. fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, nil)
  288. fiberApp.Get("/article/:article", ArticleHandler(
  289. tt.cacheMock(mc),
  290. tt.articleMock(mc),
  291. tt.tagMock(mc),
  292. ))
  293. fiberRes, fiberErr := fiberApp.Test(fiberReq)
  294. assert.Equal(t, tt.res, fiberRes.StatusCode)
  295. assert.Equal(t, tt.err, fiberErr)
  296. })
  297. }
  298. }