update_thing_notification_test.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. package notification
  2. import (
  3. "context"
  4. "database/sql"
  5. "net/http/httptest"
  6. "strconv"
  7. "testing"
  8. "time"
  9. "github.com/brianvoe/gofakeit/v6"
  10. "github.com/gofiber/fiber/v2"
  11. "github.com/gojuno/minimock/v3"
  12. "github.com/stretchr/testify/assert"
  13. "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/notification/mocks"
  14. "git.dmitriygnatenko.ru/dima/homethings/internal/dto"
  15. "git.dmitriygnatenko.ru/dima/homethings/internal/helpers/test"
  16. "git.dmitriygnatenko.ru/dima/homethings/internal/models"
  17. )
  18. func TestUpdateThingNotificationHandler(t *testing.T) {
  19. t.Parallel()
  20. type req struct {
  21. method string
  22. route string
  23. contentType string
  24. body *dto.UpdateThingNotificationRequest
  25. }
  26. var (
  27. thingID = uint64(gofakeit.Number(1, 1000))
  28. notificationDate = gofakeit.Date().Truncate(time.Second)
  29. testError = gofakeit.Error()
  30. layout = "2006-01-02 15:04:05"
  31. correctReq = req{
  32. method: fiber.MethodPut,
  33. route: "/v1/things/notifications/" + strconv.FormatUint(thingID, 10),
  34. body: &dto.UpdateThingNotificationRequest{
  35. NotificationDate: notificationDate.Format(time.RFC3339),
  36. },
  37. contentType: fiber.MIMEApplicationJSON,
  38. }
  39. repoRes = models.ThingNotification{
  40. ThingID: thingID,
  41. NotificationDate: notificationDate,
  42. CreatedAt: gofakeit.Date(),
  43. UpdatedAt: gofakeit.Date(),
  44. }
  45. expectedRes = dto.ThingNotificationResponse{
  46. ThingID: thingID,
  47. NotificationDate: notificationDate.Format(layout),
  48. CreatedAt: repoRes.CreatedAt.Format(layout),
  49. UpdatedAt: repoRes.UpdatedAt.Format(layout),
  50. }
  51. )
  52. tests := []struct {
  53. name string
  54. req req
  55. resCode int
  56. resBody interface{}
  57. repoMock func(mc *minimock.Controller) ThingNotificationRepository
  58. }{
  59. {
  60. name: "positive case",
  61. req: correctReq,
  62. resCode: fiber.StatusOK,
  63. resBody: expectedRes,
  64. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  65. mock := mocks.NewThingNotificationRepositoryMock(mc)
  66. mock.UpdateMock.Inspect(func(ctx context.Context, req models.UpdateThingNotificationRequest) {
  67. assert.Equal(mc, thingID, req.ThingID)
  68. assert.Equal(mc, notificationDate, req.NotificationDate)
  69. }).Return(nil)
  70. mock.GetMock.Set(func(ctx context.Context, id uint64) (*models.ThingNotification, error) {
  71. assert.Equal(mc, thingID, id)
  72. if mock.GetAfterCounter() == 0 {
  73. return nil, nil
  74. }
  75. return &repoRes, nil
  76. })
  77. return mock
  78. },
  79. },
  80. {
  81. name: "negative case - bad request",
  82. req: req{
  83. method: fiber.MethodPut,
  84. route: "/v1/things/notifications/" + gofakeit.Word(),
  85. },
  86. resCode: fiber.StatusBadRequest,
  87. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  88. return mocks.NewThingNotificationRepositoryMock(mc)
  89. },
  90. },
  91. {
  92. name: "negative case - body parse error",
  93. req: req{
  94. method: fiber.MethodPut,
  95. route: "/v1/things/notifications/" + strconv.FormatUint(thingID, 10),
  96. },
  97. resCode: fiber.StatusBadRequest,
  98. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  99. return mocks.NewThingNotificationRepositoryMock(mc)
  100. },
  101. },
  102. {
  103. name: "negative case - validate request error",
  104. req: req{
  105. method: fiber.MethodPut,
  106. route: "/v1/things/notifications/" + strconv.FormatUint(thingID, 10),
  107. contentType: fiber.MIMEApplicationJSON,
  108. },
  109. resCode: fiber.StatusBadRequest,
  110. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  111. return mocks.NewThingNotificationRepositoryMock(mc)
  112. },
  113. },
  114. {
  115. name: "negative case - repository error (get)",
  116. req: correctReq,
  117. resCode: fiber.StatusInternalServerError,
  118. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  119. mock := mocks.NewThingNotificationRepositoryMock(mc)
  120. mock.GetMock.Inspect(func(ctx context.Context, id uint64) {
  121. assert.Equal(mc, thingID, id)
  122. }).Return(nil, testError)
  123. return mock
  124. },
  125. },
  126. {
  127. name: "negative case - bad request (notification not found)",
  128. req: correctReq,
  129. resCode: fiber.StatusBadRequest,
  130. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  131. mock := mocks.NewThingNotificationRepositoryMock(mc)
  132. mock.GetMock.Inspect(func(ctx context.Context, id uint64) {
  133. assert.Equal(mc, thingID, id)
  134. }).Return(nil, sql.ErrNoRows)
  135. return mock
  136. },
  137. },
  138. {
  139. name: "negative case - bad request (notification not found)",
  140. req: req{
  141. method: fiber.MethodPut,
  142. route: "/v1/things/notifications/" + strconv.FormatUint(thingID, 10),
  143. body: &dto.UpdateThingNotificationRequest{
  144. NotificationDate: notificationDate.String(),
  145. },
  146. contentType: fiber.MIMEApplicationJSON,
  147. },
  148. resCode: fiber.StatusBadRequest,
  149. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  150. mock := mocks.NewThingNotificationRepositoryMock(mc)
  151. mock.GetMock.Inspect(func(ctx context.Context, id uint64) {
  152. assert.Equal(mc, thingID, id)
  153. }).Return(nil, nil)
  154. return mock
  155. },
  156. },
  157. {
  158. name: "negative case - repository error (update)",
  159. req: correctReq,
  160. resCode: fiber.StatusInternalServerError,
  161. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  162. mock := mocks.NewThingNotificationRepositoryMock(mc)
  163. mock.GetMock.Inspect(func(ctx context.Context, id uint64) {
  164. assert.Equal(mc, thingID, id)
  165. }).Return(nil, nil)
  166. mock.UpdateMock.Inspect(func(ctx context.Context, req models.UpdateThingNotificationRequest) {
  167. assert.Equal(mc, thingID, req.ThingID)
  168. assert.Equal(mc, notificationDate, req.NotificationDate)
  169. }).Return(testError)
  170. return mock
  171. },
  172. },
  173. {
  174. name: "negative case - repository error (get)",
  175. req: correctReq,
  176. resCode: fiber.StatusInternalServerError,
  177. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  178. mock := mocks.NewThingNotificationRepositoryMock(mc)
  179. mock.UpdateMock.Inspect(func(ctx context.Context, req models.UpdateThingNotificationRequest) {
  180. assert.Equal(mc, thingID, req.ThingID)
  181. assert.Equal(mc, notificationDate, req.NotificationDate)
  182. }).Return(nil)
  183. mock.GetMock.Set(func(ctx context.Context, id uint64) (*models.ThingNotification, error) {
  184. assert.Equal(mc, thingID, id)
  185. if mock.GetAfterCounter() == 0 {
  186. return nil, nil
  187. }
  188. return nil, testError
  189. })
  190. return mock
  191. },
  192. },
  193. }
  194. for _, tt := range tests {
  195. t.Run(tt.name, func(t *testing.T) {
  196. t.Parallel()
  197. mc := minimock.NewController(t)
  198. fiberApp := fiber.New()
  199. fiberApp.Put("/v1/things/notifications/:thingId", UpdateThingNotificationHandler(tt.repoMock(mc)))
  200. fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, test.ConvertDataToIOReader(tt.req.body))
  201. fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)
  202. fiberRes, _ := fiberApp.Test(fiberReq, test.TestTimeout)
  203. assert.Equal(t, tt.resCode, fiberRes.StatusCode)
  204. if tt.resBody != nil {
  205. assert.Equal(t, test.MarshalResponse(tt.resBody), test.ConvertBodyToString(fiberRes.Body))
  206. }
  207. })
  208. }
  209. }