github.com/oinume/lekcije@v0.0.0-20231017100347-5b4c5eb6ab24/backend/infrastructure/mysql/lesson_test.go (about) 1 package mysql_test 2 3 import ( 4 "context" 5 "testing" 6 "time" 7 8 "github.com/google/go-cmp/cmp/cmpopts" 9 10 "github.com/oinume/lekcije/backend/domain/config" 11 "github.com/oinume/lekcije/backend/infrastructure/mysql" 12 "github.com/oinume/lekcije/backend/internal/assertion" 13 "github.com/oinume/lekcije/backend/internal/modeltest" 14 "github.com/oinume/lekcije/backend/internal/mysqltest" 15 "github.com/oinume/lekcije/backend/model2" 16 "github.com/oinume/lekcije/backend/randoms" 17 ) 18 19 func Test_lessonRepository_FindAllByTeacherIDAndDatetimeAsMap(t *testing.T) { 20 repo := mysql.NewLessonRepository(helper.DB(t).DB()) 21 repos := mysqltest.NewRepositories(helper.DB(t).DB()) 22 23 type testCase struct { 24 teacherID uint 25 lessonArgs []*model2.Lesson 26 } 27 tests := map[string]struct { 28 setup func(ctx context.Context) *testCase 29 wantErr bool 30 }{ 31 "normal": { 32 setup: func(ctx context.Context) *testCase { 33 //boil.DebugMode = true 34 //boil.DebugWriter = os.Stdout 35 teacher := modeltest.NewTeacher() 36 repos.CreateTeachers(ctx, t, teacher) 37 38 l1 := modeltest.NewLesson(func(l *model2.Lesson) { 39 l.TeacherID = teacher.ID 40 l.Datetime = time.Date(2022, 11, 1, 10, 0, 0, 0, time.UTC) 41 }) 42 l2 := modeltest.NewLesson(func(l *model2.Lesson) { 43 l.TeacherID = teacher.ID 44 l.Datetime = time.Date(2022, 11, 1, 10, 30, 0, 0, time.UTC) 45 }) 46 lessons := []*model2.Lesson{l1, l2} 47 repos.CreateLessons(ctx, t, lessons...) 48 49 return &testCase{ 50 teacherID: teacher.ID, 51 lessonArgs: lessons, 52 } 53 }, 54 }, 55 } 56 for name, tt := range tests { 57 t.Run(name, func(t *testing.T) { 58 ctx := context.Background() 59 tc := tt.setup(ctx) 60 gotLessonsMap, err := repo.FindAllByTeacherIDAndDatetimeAsMap(ctx, tc.teacherID, tc.lessonArgs) 61 if (err != nil) != tt.wantErr { 62 t.Fatalf("FindAllByTeacherIDAndDatetimeAsMap() error = %v, wantErr %v", err, tt.wantErr) 63 } 64 65 assertion.AssertEqual(t, len(tc.lessonArgs), len(gotLessonsMap), "lesson length doesn't match") 66 for _, l := range tc.lessonArgs { 67 datetime := model2.LessonDatetime(l.Datetime).String() 68 _, ok := gotLessonsMap[datetime] 69 if !ok { 70 t.Errorf("key %q must exist in result map", datetime) 71 } 72 } 73 }) 74 } 75 } 76 77 func Test_lessonRepository_FindAllByTeacherIDsDatetimeBetween(t *testing.T) { 78 repo := mysql.NewLessonRepository(helper.DB(t).DB()) 79 repos := mysqltest.NewRepositories(helper.DB(t).DB()) 80 81 type testCase struct { 82 teacherID uint 83 fromDate time.Time 84 toDate time.Time 85 want []*model2.Lesson 86 } 87 modeltest.NewFollowingTeacher() 88 tests := map[string]struct { 89 setup func(ctx context.Context) *testCase 90 wantErr bool 91 }{ 92 "normal": { 93 setup: func(ctx context.Context) *testCase { 94 teacherID := uint(randoms.MustNewInt64(10000000)) 95 l1 := modeltest.NewLesson(func(l *model2.Lesson) { 96 l.TeacherID = teacherID 97 l.Datetime = time.Date(2022, 11, 1, 10, 0, 0, 0, config.DefaultVars.LocalLocation) 98 }) 99 l2 := modeltest.NewLesson(func(l *model2.Lesson) { 100 l.TeacherID = teacherID 101 l.Datetime = time.Date(2022, 11, 2, 10, 30, 0, 0, config.DefaultVars.LocalLocation) 102 }) 103 l3 := modeltest.NewLesson(func(l *model2.Lesson) { 104 l.TeacherID = teacherID 105 l.Datetime = time.Date(2022, 11, 5, 10, 30, 0, 0, config.DefaultVars.LocalLocation) 106 }) 107 lessons := []*model2.Lesson{l1, l2, l3} 108 repos.CreateLessons(ctx, t, lessons...) 109 110 return &testCase{ 111 teacherID: teacherID, 112 fromDate: time.Date(2022, 11, 1, 10, 0, 0, 0, config.DefaultVars.LocalLocation), 113 toDate: time.Date(2022, 11, 2, 10, 30, 0, 0, config.DefaultVars.LocalLocation), 114 want: []*model2.Lesson{l1, l2}, // l3 doesn't hit 115 } 116 }, 117 }, 118 "no records": { 119 setup: func(ctx context.Context) *testCase { 120 teacherID := uint(randoms.MustNewInt64(10000000)) 121 l1 := modeltest.NewLesson(func(l *model2.Lesson) { 122 l.TeacherID = teacherID 123 l.Datetime = time.Date(2022, 11, 1, 10, 0, 0, 0, config.DefaultVars.LocalLocation) 124 }) 125 lessons := []*model2.Lesson{l1} 126 repos.CreateLessons(ctx, t, lessons...) 127 128 return &testCase{ 129 teacherID: teacherID + 1, 130 fromDate: time.Date(2022, 12, 1, 10, 0, 0, 0, config.DefaultVars.LocalLocation), 131 toDate: time.Date(2022, 12, 2, 10, 30, 0, 0, config.DefaultVars.LocalLocation), 132 want: nil, 133 } 134 }, 135 }, 136 } 137 for name, tt := range tests { 138 t.Run(name, func(t *testing.T) { 139 ctx := context.Background() 140 tc := tt.setup(ctx) 141 got, err := repo.FindAllByTeacherIDsDatetimeBetween(ctx, tc.teacherID, tc.fromDate, tc.toDate) 142 if (err != nil) != tt.wantErr { 143 t.Fatalf("FindAllByTeacherIDsDatetimeBetween() error = %v, wantErr %v", err, tt.wantErr) 144 } 145 assertion.AssertEqual(t, len(tc.want), len(got), "length of want and got is not same", cmpopts.EquateApproxTime(10*time.Second)) 146 assertion.AssertEqual(t, tc.want, got, "", cmpopts.EquateApproxTime(10*time.Second)) 147 }) 148 } 149 } 150 151 func Test_lessonRepository_GetNewAvailableLessons(t *testing.T) { 152 repo := mysql.NewLessonRepository(helper.DB(t).DB()) 153 154 type testCase struct { 155 oldLessons []*model2.Lesson 156 newLessons []*model2.Lesson 157 want []*model2.Lesson 158 } 159 tests := map[string]struct { 160 setup func(ctx context.Context) *testCase 161 }{ 162 "one available lessons": { 163 setup: func(ctx context.Context) *testCase { 164 teacherID := uint(randoms.MustNewInt64(100000)) 165 datetime := time.Date(2016, 10, 1, 14, 30, 0, 0, config.LocalLocation()) 166 lessons1 := newLessons(teacherID, datetime, "Reserved", 3) 167 lessons2 := newLessons(teacherID, datetime, "Reserved", 3) 168 lessons2[1].Status = "Available" 169 return &testCase{ 170 oldLessons: lessons1, 171 newLessons: lessons2, 172 want: []*model2.Lesson{ 173 lessons2[1], 174 }, 175 } 176 }, 177 }, 178 "no available lessons": { 179 setup: func(ctx context.Context) *testCase { 180 teacherID := uint(randoms.MustNewInt64(100000)) 181 datetime := time.Date(2016, 10, 1, 14, 30, 0, 0, config.LocalLocation()) 182 lessons1 := newLessons(teacherID, datetime, "Reserved", 3) 183 lessons2 := newLessons(teacherID, datetime, "Reserved", 3) 184 // There are available lessons in old, means no difference between lessons1 and lessons2 185 lessons1[0].Status = "Available" 186 lessons2[0].Status = "Available" 187 return &testCase{ 188 oldLessons: lessons1, 189 newLessons: lessons2, 190 want: []*model2.Lesson{}, 191 } 192 }, 193 }, 194 } 195 for name, tt := range tests { 196 t.Run(name, func(t *testing.T) { 197 ctx := context.Background() 198 tc := tt.setup(ctx) 199 got := repo.GetNewAvailableLessons(ctx, tc.oldLessons, tc.newLessons) 200 assertion.AssertEqual(t, len(tc.want), len(got), "length of lessons doesn't match") 201 assertion.AssertEqual(t, tc.want, got, "") 202 }) 203 } 204 } 205 206 /* TODO: Add test case 207 func TestLessonService_GetNewAvailableLessons1(t *testing.T) { 208 a := assert.New(t) 209 210 datetime := time.Date(2016, 10, 1, 14, 30, 0, 0, config.LocalLocation()) 211 lessons1 := createLessons(1, datetime, "Reserved", 3) 212 lessons2 := createLessons(1, datetime, "Reserved", 3) 213 lessons2[1].Status = "Available" 214 // Test GetNewAvailableLessons returns a lesson when new lesson is "Available" 215 availableLessons := lessonService.GetNewAvailableLessons(context.Background(), lessons1, lessons2) 216 a.Equal(1, len(availableLessons)) 217 a.Equal(datetime.Add(1*time.Hour), availableLessons[0].Datetime) 218 } 219 220 func TestLessonService_GetNewAvailableLessons2(t *testing.T) { 221 a := assert.New(t) 222 223 datetime := time.Date(2016, 10, 1, 14, 30, 0, 0, config.LocalLocation()) 224 lessons1 := createLessons(1, datetime, "Reserved", 3) 225 lessons2 := createLessons(1, datetime, "Reserved", 3) 226 lessons1[0].Status = "Available" 227 lessons2[0].Status = "Available" 228 // Test GetNewAvailableLessons returns nothing when both lessons are "Available" 229 availableLessons := lessonService.GetNewAvailableLessons(context.Background(), lessons1, lessons2) 230 a.Equal(0, len(availableLessons)) 231 } 232 */ 233 234 func newLessons(teacherID uint, baseDatetime time.Time, status string, length int) []*model2.Lesson { 235 lessons := make([]*model2.Lesson, length) 236 now := time.Now().UTC() 237 for i := range lessons { 238 lessons[i] = &model2.Lesson{ 239 TeacherID: teacherID, 240 Datetime: baseDatetime.Add(time.Duration(i) * time.Hour), 241 Status: status, 242 CreatedAt: now, 243 UpdatedAt: now, 244 } 245 } 246 return lessons 247 } 248 249 func Test_lessonRepository_FindOrCreate(t *testing.T) { 250 db := helper.DB(t) 251 repo := mysql.NewLessonRepository(db.DB()) 252 repos := mysqltest.NewRepositories(db.DB()) 253 254 type testCase struct { 255 lesson *model2.Lesson 256 } 257 tests := map[string]struct { 258 setup func(ctx context.Context) *testCase 259 }{ 260 "create new one": { 261 setup: func(ctx context.Context) *testCase { 262 l := modeltest.NewLesson() 263 return &testCase{ 264 lesson: l, 265 } 266 }, 267 }, 268 "exist": { 269 setup: func(ctx context.Context) *testCase { 270 l := modeltest.NewLesson() 271 repos.CreateLessons(ctx, t, l) 272 return &testCase{ 273 lesson: l, 274 } 275 }, 276 }, 277 } 278 for name, tt := range tests { 279 t.Run(name, func(t *testing.T) { 280 ctx := context.Background() 281 tc := tt.setup(ctx) 282 got, err := repo.FindOrCreate(ctx, tc.lesson, true) 283 if err != nil { 284 t.Fatalf("FindOrCreate failed: unexpected error = %v", err) 285 } 286 assertion.AssertEqual(t, tc.lesson, got, "", cmpopts.EquateApproxTime(10*time.Second)) 287 }) 288 } 289 } 290 291 func Test_lessonRepository_UpdateStatus(t *testing.T) { 292 db := helper.DB(t) 293 repo := mysql.NewLessonRepository(db.DB()) 294 repos := mysqltest.NewRepositories(db.DB()) 295 296 type testCase struct { 297 lesson *model2.Lesson 298 newStatus string 299 } 300 tests := map[string]struct { 301 setup func(ctx context.Context) *testCase 302 }{ 303 "normal": { 304 setup: func(ctx context.Context) *testCase { 305 l := modeltest.NewLesson(func(l *model2.Lesson) { 306 l.Status = "available" 307 }) 308 repos.CreateLessons(ctx, t, l) 309 return &testCase{ 310 lesson: l, 311 newStatus: "reserved", 312 } 313 }, 314 }, 315 } 316 for name, tt := range tests { 317 t.Run(name, func(t *testing.T) { 318 ctx := context.Background() 319 tc := tt.setup(ctx) 320 _, err := repo.UpdateStatus(ctx, tc.lesson.ID, tc.newStatus) 321 if err != nil { 322 t.Fatalf("UpdateStatus failed: unexpected error = %v", err) 323 } 324 got, err := repo.FindByID(ctx, tc.lesson.ID) 325 if err != nil { 326 t.Fatalf("FindByID failed: unexpected error = %v", err) 327 } 328 assertion.AssertEqual(t, tc.newStatus, got.Status, "status is not updated") 329 }) 330 } 331 332 }