add_thing_notification_test.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. package notification
  2. import (
  3. "context"
  4. "net/http/httptest"
  5. "testing"
  6. "time"
  7. "github.com/brianvoe/gofakeit/v6"
  8. "github.com/gofiber/fiber/v2"
  9. "github.com/gojuno/minimock/v3"
  10. "github.com/lib/pq"
  11. "github.com/stretchr/testify/assert"
  12. "git.dmitriygnatenko.ru/dima/homethings/internal/api/v1/notification/mocks"
  13. "git.dmitriygnatenko.ru/dima/homethings/internal/dto"
  14. "git.dmitriygnatenko.ru/dima/homethings/internal/helpers/test"
  15. "git.dmitriygnatenko.ru/dima/homethings/internal/models"
  16. "git.dmitriygnatenko.ru/dima/homethings/internal/repositories"
  17. )
  18. func TestAddThingNotificationHandler(t *testing.T) {
  19. t.Parallel()
  20. type req struct {
  21. method string
  22. route string
  23. contentType string
  24. body *dto.AddThingNotificationRequest
  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.MethodPost,
  33. route: "/v1/things/notifications",
  34. body: &dto.AddThingNotificationRequest{
  35. ThingID: thingID,
  36. NotificationDate: notificationDate.Format(time.RFC3339),
  37. },
  38. contentType: fiber.MIMEApplicationJSON,
  39. }
  40. repoRes = models.ThingNotification{
  41. ThingID: thingID,
  42. NotificationDate: notificationDate,
  43. CreatedAt: gofakeit.Date(),
  44. UpdatedAt: gofakeit.Date(),
  45. }
  46. expectedRes = dto.ThingNotificationResponse{
  47. ThingID: thingID,
  48. NotificationDate: notificationDate.Format(layout),
  49. CreatedAt: repoRes.CreatedAt.Format(layout),
  50. UpdatedAt: repoRes.UpdatedAt.Format(layout),
  51. }
  52. )
  53. tests := []struct {
  54. name string
  55. req req
  56. resCode int
  57. resBody interface{}
  58. repoMock func(mc *minimock.Controller) ThingNotificationRepository
  59. }{
  60. {
  61. name: "positive case",
  62. req: correctReq,
  63. resCode: fiber.StatusOK,
  64. resBody: expectedRes,
  65. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  66. mock := mocks.NewThingNotificationRepositoryMock(mc)
  67. mock.AddMock.Inspect(func(ctx context.Context, req models.AddThingNotificationRequest) {
  68. assert.Equal(mc, thingID, req.ThingID)
  69. assert.Equal(mc, notificationDate, req.NotificationDate)
  70. }).Return(nil)
  71. mock.GetMock.Inspect(func(ctx context.Context, id uint64) {
  72. assert.Equal(mc, thingID, id)
  73. }).Return(&repoRes, nil)
  74. return mock
  75. },
  76. },
  77. {
  78. name: "negative case - body parse error",
  79. req: req{
  80. method: fiber.MethodPost,
  81. route: "/v1/things/notifications",
  82. },
  83. resCode: fiber.StatusBadRequest,
  84. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  85. return mocks.NewThingNotificationRepositoryMock(mc)
  86. },
  87. },
  88. {
  89. name: "negative case - thing id is empty",
  90. req: req{
  91. method: fiber.MethodPost,
  92. route: "/v1/things/notifications",
  93. body: &dto.AddThingNotificationRequest{
  94. NotificationDate: notificationDate.Format(time.RFC3339),
  95. },
  96. contentType: fiber.MIMEApplicationJSON,
  97. },
  98. resCode: fiber.StatusBadRequest,
  99. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  100. return mocks.NewThingNotificationRepositoryMock(mc)
  101. },
  102. },
  103. {
  104. name: "negative case - incorrect notification date format",
  105. req: req{
  106. method: fiber.MethodPost,
  107. route: "/v1/things/notifications",
  108. body: &dto.AddThingNotificationRequest{
  109. ThingID: thingID,
  110. NotificationDate: notificationDate.String(),
  111. },
  112. contentType: fiber.MIMEApplicationJSON,
  113. },
  114. resCode: fiber.StatusBadRequest,
  115. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  116. return mocks.NewThingNotificationRepositoryMock(mc)
  117. },
  118. },
  119. {
  120. name: "negative case - repository error (add)",
  121. req: correctReq,
  122. resCode: fiber.StatusInternalServerError,
  123. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  124. mock := mocks.NewThingNotificationRepositoryMock(mc)
  125. mock.AddMock.Inspect(func(ctx context.Context, req models.AddThingNotificationRequest) {
  126. assert.Equal(mc, thingID, req.ThingID)
  127. assert.Equal(mc, notificationDate, req.NotificationDate)
  128. }).Return(testError)
  129. return mock
  130. },
  131. },
  132. {
  133. name: "negative case - repository error (duplicate)",
  134. req: correctReq,
  135. resCode: fiber.StatusBadRequest,
  136. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  137. mock := mocks.NewThingNotificationRepositoryMock(mc)
  138. mock.AddMock.Inspect(func(ctx context.Context, req models.AddThingNotificationRequest) {
  139. assert.Equal(mc, thingID, req.ThingID)
  140. assert.Equal(mc, notificationDate, req.NotificationDate)
  141. }).Return(&pq.Error{Code: repositories.DuplicateKeyErrorCode})
  142. return mock
  143. },
  144. },
  145. {
  146. name: "negative case - repository error (get)",
  147. req: correctReq,
  148. resCode: fiber.StatusInternalServerError,
  149. repoMock: func(mc *minimock.Controller) ThingNotificationRepository {
  150. mock := mocks.NewThingNotificationRepositoryMock(mc)
  151. mock.AddMock.Inspect(func(ctx context.Context, req models.AddThingNotificationRequest) {
  152. assert.Equal(mc, thingID, req.ThingID)
  153. assert.Equal(mc, notificationDate, req.NotificationDate)
  154. }).Return(nil)
  155. mock.GetMock.Inspect(func(ctx context.Context, id uint64) {
  156. assert.Equal(mc, thingID, id)
  157. }).Return(nil, testError)
  158. return mock
  159. },
  160. },
  161. }
  162. for _, tt := range tests {
  163. t.Run(tt.name, func(t *testing.T) {
  164. t.Parallel()
  165. mc := minimock.NewController(t)
  166. fiberApp := fiber.New()
  167. fiberApp.Post("/v1/things/notifications", AddThingNotificationHandler(tt.repoMock(mc)))
  168. fiberReq := httptest.NewRequest(tt.req.method, tt.req.route, test.ConvertDataToIOReader(tt.req.body))
  169. fiberReq.Header.Add(fiber.HeaderContentType, tt.req.contentType)
  170. fiberRes, _ := fiberApp.Test(fiberReq, test.TestTimeout)
  171. assert.Equal(t, tt.resCode, fiberRes.StatusCode)
  172. if tt.resBody != nil {
  173. assert.Equal(t, test.MarshalResponse(tt.resBody), test.ConvertBodyToString(fiberRes.Body))
  174. }
  175. })
  176. }
  177. }