From 859e3d7f6f3860195fd4705476eec4e0eb0dea7b Mon Sep 17 00:00:00 2001 From: Christoph Walther Date: Wed, 3 Jul 2024 16:07:07 +0000 Subject: [PATCH 1/8] Line breaks and automatic labelling in feature_request template --- .gitlab/issue_templates/feature_request.md | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/.gitlab/issue_templates/feature_request.md b/.gitlab/issue_templates/feature_request.md index bbcbbe7..ef73154 100644 --- a/.gitlab/issue_templates/feature_request.md +++ b/.gitlab/issue_templates/feature_request.md @@ -1,20 +1,13 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** +**Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -**Describe the solution you'd like** +**Describe the solution you'd like** A clear and concise description of what you want to happen. -**Describe alternatives you've considered** +**Describe alternatives you've considered** A clear and concise description of any alternative solutions or features you've considered. -**Additional context** +**Additional context** Add any other context or screenshots about the feature request here. + +/label ~feature From fc9372a9ebc95e838a2b22c867b81259f421f190 Mon Sep 17 00:00:00 2001 From: Christoph Walther Date: Wed, 3 Jul 2024 16:08:03 +0000 Subject: [PATCH 2/8] Line breaks and automatic label assignment in bug template --- .gitlab/issue_templates/bug_report.md | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/.gitlab/issue_templates/bug_report.md b/.gitlab/issue_templates/bug_report.md index dd84ea7..1c417a0 100644 --- a/.gitlab/issue_templates/bug_report.md +++ b/.gitlab/issue_templates/bug_report.md @@ -1,38 +1,31 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' - ---- - -**Describe the bug** +**Describe the bug** A clear and concise description of what the bug is. -**To Reproduce** +**To Reproduce** Steps to reproduce the behavior: 1. Go to '...' 2. Click on '....' 3. Scroll down to '....' 4. See error -**Expected behavior** +**Expected behavior** A clear and concise description of what you expected to happen. -**Screenshots** +**Screenshots** If applicable, add screenshots to help explain your problem. -**Desktop (please complete the following information):** +**Desktop (please complete the following information):** - OS: [e.g. iOS] - Browser [e.g. chrome, safari] - Version [e.g. 22] -**Smartphone (please complete the following information):** +**Smartphone (please complete the following information):** - Device: [e.g. iPhone6] - OS: [e.g. iOS8.1] - Browser [e.g. stock browser, safari] - Version [e.g. 22] -**Additional context** +**Additional context** Add any other context about the problem here. + +/label ~bug From a5a8c2a58d6e9b26099e7b659d972fa6155a4057 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Fri, 5 Jul 2024 12:27:23 +0200 Subject: [PATCH 3/8] fix:#46 added delete groups --- services/data-manager/service/db/dbGroups.go | 78 ++++++++----------- .../fetch/v1/fetchSeminarGroupService.go | 34 ++++---- 2 files changed, 47 insertions(+), 65 deletions(-) diff --git a/services/data-manager/service/db/dbGroups.go b/services/data-manager/service/db/dbGroups.go index f4776c3..059fb65 100644 --- a/services/data-manager/service/db/dbGroups.go +++ b/services/data-manager/service/db/dbGroups.go @@ -20,60 +20,46 @@ import ( "github.com/pocketbase/dbx" "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/models" - "htwkalender/data-manager/model" "log/slog" ) -func SaveGroups(seminarGroup []model.SeminarGroup, collection *models.Collection, app *pocketbase.PocketBase) ([]*models.Record, error) { - var savedRecords []*models.Record - var tobeSavedGroups []model.SeminarGroup - var insertRecords []*models.Record - - for _, group := range seminarGroup { - dbGroup, err := FindGroupByCourseAndSemester(group.Course, group.Semester, app) - - if dbGroup == nil && err.Error() == "sql: no rows in result set" { - tobeSavedGroups = append(tobeSavedGroups, group) - } else if err != nil { - return nil, err - } - } - - // create record for each group that's not already in the database - for _, group := range tobeSavedGroups { - record := models.NewRecord(collection) - record.Set("university", group.University) - record.Set("shortcut", group.GroupShortcut) - record.Set("groupId", group.GroupId) - record.Set("course", group.Course) - record.Set("faculty", group.Faculty) - record.Set("facultyId", group.FacultyId) - record.Set("semester", group.Semester) - insertRecords = append(insertRecords, record) - } - - // save all records - for _, record := range insertRecords { - if record != nil { - err := app.Dao().SaveRecord(record) - if err == nil { - savedRecords = append(savedRecords, record) - } else { - return nil, err - } - } - } - - return savedRecords, nil +type SeminarGroup struct { + University string `db:"university" json:"university"` + GroupShortcut string `db:"shortcut" json:"shortcut"` + GroupId string `db:"groupId" json:"groupId"` + Course string `db:"course" json:"course"` + Faculty string `db:"faculty" json:"faculty"` + FacultyId string `db:"facultyId" json:"facultyId"` + Semester string `db:"semester" json:"semester"` + models.BaseModel } -func FindGroupByCourseAndSemester(course string, semester string, app *pocketbase.PocketBase) (*model.SeminarGroup, error) { - var group model.SeminarGroup - err := app.Dao().DB().Select("*").From("groups").Where(dbx.NewExp("course = {:course} AND semester = {:semester}", dbx.Params{"course": course, "semester": semester})).One(&group) +func (s *SeminarGroup) TableName() string { + return "groups" +} + +type SeminarGroups []*SeminarGroup + +func SaveGroups(seminarGroups SeminarGroups, app *pocketbase.PocketBase) (SeminarGroups, error) { + + // delete all groups from the database + execute, err := app.Dao().DB().Delete("groups", dbx.NewExp("1 = 1")).Execute() if err != nil { return nil, err } - return &group, nil + rowCount, _ := execute.RowsAffected() + + savedGroups := SeminarGroups{} + for _, group := range seminarGroups { + saveErr := app.Dao().Save(group) + if saveErr != nil { + return nil, saveErr + } + savedGroups = append(savedGroups, group) + } + slog.Info("Saved all groups to the database", "insert", len(savedGroups), "deleted", rowCount) + + return savedGroups, nil } func GetAllCourses(app *pocketbase.PocketBase) []string { diff --git a/services/data-manager/service/fetch/v1/fetchSeminarGroupService.go b/services/data-manager/service/fetch/v1/fetchSeminarGroupService.go index 32cfff0..316ff57 100644 --- a/services/data-manager/service/fetch/v1/fetchSeminarGroupService.go +++ b/services/data-manager/service/fetch/v1/fetchSeminarGroupService.go @@ -20,7 +20,6 @@ import ( "encoding/xml" "fmt" "github.com/pocketbase/pocketbase" - "github.com/pocketbase/pocketbase/models" "htwkalender/data-manager/model" "htwkalender/data-manager/service/db" "htwkalender/data-manager/service/functions" @@ -58,8 +57,8 @@ func getSeminarHTML(semester string) (string, error) { } -func FetchSeminarGroups(app *pocketbase.PocketBase) ([]*models.Record, error) { - var groups []model.SeminarGroup +func FetchSeminarGroups(app *pocketbase.PocketBase) (db.SeminarGroups, error) { + var groups db.SeminarGroups semesterString := functions.CalculateSemesterList(time.RealClock{}) var results [2]string @@ -77,26 +76,23 @@ func FetchSeminarGroups(app *pocketbase.PocketBase) ([]*models.Record, error) { // filter duplicates groups = removeDuplicates(groups) - collection, dbError := db.FindCollection(app, "groups") + insertedGroups, dbError := db.SaveGroups(groups, app) if dbError != nil { - slog.Error("Error while searching collection groups", "error", dbError) - return nil, err - } - var insertedGroups []*models.Record - - insertedGroups, dbError = db.SaveGroups(groups, collection, app) - if dbError != nil { - slog.Error("Error while saving groups", "error", dbError) + slog.Error("FetchSeminarGroups", "error", dbError) return nil, err } return insertedGroups, nil } -func removeDuplicates(groups []model.SeminarGroup) []model.SeminarGroup { - var uniqueGroups []model.SeminarGroup +func removeDuplicates(groups db.SeminarGroups) db.SeminarGroups { + uniqueGroups := make(db.SeminarGroups, 0, len(groups)) + seen := make(map[string]struct{}) // Use an empty struct to minimize memory usage + for _, group := range groups { - if !contains(uniqueGroups, group) { + key := group.Course + group.Semester + if _, exists := seen[key]; !exists { + seen[key] = struct{}{} uniqueGroups = append(uniqueGroups, group) } } @@ -112,7 +108,7 @@ func contains(groups []model.SeminarGroup, group model.SeminarGroup) bool { return false } -func parseSeminarGroups(result string, semester string) []model.SeminarGroup { +func parseSeminarGroups(result string, semester string) db.SeminarGroups { var studium model.Studium err := xml.Unmarshal([]byte(result), &studium) @@ -120,11 +116,11 @@ func parseSeminarGroups(result string, semester string) []model.SeminarGroup { return nil } - var seminarGroups []model.SeminarGroup + var seminarGroups db.SeminarGroups for _, faculty := range studium.Faculty { for _, Studiengang := range faculty.Studiengang { for _, Studienrichtung := range Studiengang.Semgrp { - seminarGroup := model.SeminarGroup{ + seminarGroup := db.SeminarGroup{ University: "HTWK-Leipzig", GroupShortcut: Studiengang.Name, GroupId: Studiengang.ID, @@ -133,7 +129,7 @@ func parseSeminarGroups(result string, semester string) []model.SeminarGroup { FacultyId: faculty.ID, Semester: semester, } - seminarGroups = append(seminarGroups, seminarGroup) + seminarGroups = append(seminarGroups, &seminarGroup) } } } From ab22364ac82151878f1ff668d1ca2a17dc1ac365 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Fri, 5 Jul 2024 15:23:10 +0200 Subject: [PATCH 4/8] fix:#46 updated fetcher and empty course issue --- services/data-manager/service/addRoute.go | 8 ++- .../service/course/courseFunctions.go | 18 ++++-- services/data-manager/service/db/dbGroups.go | 44 +++++++++---- .../service/events/courseService.go | 3 +- .../service/events/eventService.go | 10 ++- .../fetch/v1/fetchSeminarEventService.go | 62 +++++-------------- .../fetch/v1/fetchSeminarGroupService.go | 3 +- 7 files changed, 76 insertions(+), 72 deletions(-) diff --git a/services/data-manager/service/addRoute.go b/services/data-manager/service/addRoute.go index 8dadd40..9c5c068 100644 --- a/services/data-manager/service/addRoute.go +++ b/services/data-manager/service/addRoute.go @@ -336,8 +336,12 @@ func AddRoutes(app *pocketbase.PocketBase) { courses := events.GetAllCourses(app) return c.JSON(200, courses) } else { - courses := events.GetAllCoursesForSemester(app, semester) - return c.JSON(200, courses) + seminarGroups := events.GetAllCoursesForSemester(app, semester) + courseStringList := make([]string, 0) + for _, seminarGroup := range seminarGroups { + courseStringList = append(courseStringList, seminarGroup.Course) + } + return c.JSON(200, courseStringList) } }, Middlewares: []echo.MiddlewareFunc{ diff --git a/services/data-manager/service/course/courseFunctions.go b/services/data-manager/service/course/courseFunctions.go index 0612d97..22febd4 100644 --- a/services/data-manager/service/course/courseFunctions.go +++ b/services/data-manager/service/course/courseFunctions.go @@ -18,16 +18,26 @@ package course import ( "github.com/pocketbase/pocketbase" + "htwkalender/data-manager/model" "htwkalender/data-manager/service/events" + "htwkalender/data-manager/service/functions" + "htwkalender/data-manager/service/functions/time" "log/slog" ) func UpdateCourse(app *pocketbase.PocketBase) { - courses := events.GetAllCourses(app) - for _, course := range courses { - _, err := events.UpdateModulesForCourse(app, course) + currentSemesters := functions.CalculateSemesterList(time.RealClock{}) + + var seminarGroups []model.SeminarGroup + + for _, semester := range currentSemesters { + seminarGroups = append(seminarGroups, events.GetAllCoursesForSemester(app, semester)...) + } + + for _, seminarGroup := range seminarGroups { + _, err := events.UpdateModulesForCourse(app, seminarGroup) if err != nil { - slog.Warn("Update Course: "+course+" failed:", "error", err) + slog.Warn("Update Course: "+seminarGroup.Course+" failed:", "error", err) } } } diff --git a/services/data-manager/service/db/dbGroups.go b/services/data-manager/service/db/dbGroups.go index 059fb65..5e70e21 100644 --- a/services/data-manager/service/db/dbGroups.go +++ b/services/data-manager/service/db/dbGroups.go @@ -20,6 +20,7 @@ import ( "github.com/pocketbase/dbx" "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/models" + "htwkalender/data-manager/model" "log/slog" ) @@ -38,6 +39,31 @@ func (s *SeminarGroup) TableName() string { return "groups" } +// UniqueKey Should be same as unique constraint in the database +func (s *SeminarGroup) UniqueKey() string { + return s.Course + s.Semester +} + +func (s *SeminarGroup) toSeminarGroupModel() model.SeminarGroup { + return model.SeminarGroup{ + University: s.University, + GroupShortcut: s.GroupShortcut, + GroupId: s.GroupId, + Course: s.Course, + Faculty: s.Faculty, + FacultyId: s.FacultyId, + Semester: s.Semester, + } +} + +func (s *SeminarGroups) toSeminarGroupModels() []model.SeminarGroup { + var seminarGroups []model.SeminarGroup + for _, group := range *s { + seminarGroups = append(seminarGroups, group.toSeminarGroupModel()) + } + return seminarGroups +} + type SeminarGroups []*SeminarGroup func SaveGroups(seminarGroups SeminarGroups, app *pocketbase.PocketBase) (SeminarGroups, error) { @@ -84,26 +110,18 @@ func GetAllCourses(app *pocketbase.PocketBase) []string { return courseArray } -func GetAllCoursesForSemester(app *pocketbase.PocketBase, semester string) []string { +func GetAllCoursesForSemester(app *pocketbase.PocketBase, semester string) []model.SeminarGroup { - var courses []struct { - CourseShortcut string `db:"course" json:"course"` - } + var courses SeminarGroups // get all courses for a specific semester - err := app.Dao().DB().Select("course").From("groups").Where(dbx.NewExp("semester = {:semester}", dbx.Params{"semester": semester})).All(&courses) + err := app.Dao().DB().Select("*").From("groups").Where(dbx.NewExp("semester = {:semester}", dbx.Params{"semester": semester})).All(&courses) if err != nil { slog.Error("Error while getting groups from database: ", "error", err) - return []string{} + return nil } - var courseArray []string - - for _, course := range courses { - courseArray = append(courseArray, course.CourseShortcut) - } - - return courseArray + return courses.toSeminarGroupModels() } diff --git a/services/data-manager/service/events/courseService.go b/services/data-manager/service/events/courseService.go index 389a428..ea291fd 100644 --- a/services/data-manager/service/events/courseService.go +++ b/services/data-manager/service/events/courseService.go @@ -18,6 +18,7 @@ package events import ( "github.com/pocketbase/pocketbase" + "htwkalender/data-manager/model" "htwkalender/data-manager/service/db" "htwkalender/data-manager/service/functions" ) @@ -26,7 +27,7 @@ func GetAllCourses(app *pocketbase.PocketBase) []string { return db.GetAllCourses(app) } -func GetAllCoursesForSemester(app *pocketbase.PocketBase, semester string) []string { +func GetAllCoursesForSemester(app *pocketbase.PocketBase, semester string) []model.SeminarGroup { return db.GetAllCoursesForSemester(app, semester) } diff --git a/services/data-manager/service/events/eventService.go b/services/data-manager/service/events/eventService.go index afa318a..ab82d52 100644 --- a/services/data-manager/service/events/eventService.go +++ b/services/data-manager/service/events/eventService.go @@ -120,14 +120,12 @@ func DeleteAllEvents(app *pocketbase.PocketBase) error { // 3. Save all events for the course and the semester // If the update was successful, nil is returned // If the update was not successful, an error is returned -func UpdateModulesForCourse(app *pocketbase.PocketBase, course string) (model.Events, error) { +func UpdateModulesForCourse(app *pocketbase.PocketBase, seminarGroup model.SeminarGroup) (model.Events, error) { - seminarGroup, err := v1.GetSeminarGroupEventsFromHTML(course) + seminarGroup, err := v1.FetchAndParse(seminarGroup.Semester, seminarGroup.Course) if err != nil { return nil, err } - - seminarGroup = v1.ClearEmptySeminarGroups(seminarGroup) seminarGroup = v1.ReplaceEmptyEventNames(seminarGroup) //check if events in the seminarGroups Events are already in the database @@ -136,7 +134,7 @@ func UpdateModulesForCourse(app *pocketbase.PocketBase, course string) (model.Ev //if there are no events in the database, save the new events //get all events for the course and the semester - dbEvents, err := db.GetAllEventsForCourse(app, course) + dbEvents, err := db.GetAllEventsForCourse(app, seminarGroup.Course) if err != nil { return nil, err } @@ -182,7 +180,7 @@ func UpdateModulesForCourse(app *pocketbase.PocketBase, course string) (model.Ev return nil, err } - slog.Info("Course: " + course + " - Event changes: " + strconv.FormatInt(int64(len(insertList)), 10) + " new events, " + strconv.FormatInt(int64(len(deleteList)), 10) + " deleted events") + slog.Info("Course: " + seminarGroup.Course + " - Event changes: " + strconv.FormatInt(int64(len(insertList)), 10) + " new events, " + strconv.FormatInt(int64(len(deleteList)), 10) + " deleted events") return savedEvents, nil } diff --git a/services/data-manager/service/fetch/v1/fetchSeminarEventService.go b/services/data-manager/service/fetch/v1/fetchSeminarEventService.go index e2a8780..4a02776 100644 --- a/services/data-manager/service/fetch/v1/fetchSeminarEventService.go +++ b/services/data-manager/service/fetch/v1/fetchSeminarEventService.go @@ -41,16 +41,12 @@ func ReplaceEmptyEventNames(group model.SeminarGroup) model.SeminarGroup { return group } -func ClearEmptySeminarGroups(seminarGroup model.SeminarGroup) model.SeminarGroup { - var newSeminarGroup = model.SeminarGroup{} - - if len(seminarGroup.Events) > 0 && seminarGroup.Course != "" { - newSeminarGroup = seminarGroup - } - return newSeminarGroup -} - func fetchHTMLFromURL(semester, seminarGroupLabel string) (string, error) { + // check that semester and seminarGroupLabel are not empty + if semester == "" || seminarGroupLabel == "" { + return "", fmt.Errorf("semester or seminarGroupLabel is empty") + } + url := "https://stundenplan.htwk-leipzig.de/" + semester + "/Berichte/Text-Listen;Studenten-Sets;name;" + seminarGroupLabel + "?template=sws_semgrp&weeks=1-65" result, err := fetch.GetHTML(url) if err != nil { @@ -60,22 +56,6 @@ func fetchHTMLFromURL(semester, seminarGroupLabel string) (string, error) { return result, nil } -func GetSeminarGroupEventsFromHTML(seminarGroupLabel string) (model.SeminarGroup, error) { - var seminarGroup [2]model.SeminarGroup - var errSS, errWS error - - currentMonth := time.Now().Month() - - if isSummerSemester(currentMonth) { - seminarGroup[0], errSS = fetchAndParse("ss", seminarGroupLabel) - } - if isWinterSemester(currentMonth) { - seminarGroup[1], errWS = fetchAndParse("ws", seminarGroupLabel) - } - - return checkForSuccessfulFetch(errSS, errWS, seminarGroup) -} - func isSummerSemester(month time.Month) bool { return month >= 3 && month <= 10 } @@ -84,7 +64,7 @@ func isWinterSemester(month time.Month) bool { return month >= 9 || month <= 4 } -func fetchAndParse(season, label string) (model.SeminarGroup, error) { +func FetchAndParse(season, label string) (model.SeminarGroup, error) { result, err := fetchHTMLFromURL(season, label) if err != nil { return model.SeminarGroup{}, err @@ -92,20 +72,6 @@ func fetchAndParse(season, label string) (model.SeminarGroup, error) { return parseSeminarGroup(result), nil } -func checkForSuccessfulFetch(errSS error, errWS error, seminarGroup [2]model.SeminarGroup) (model.SeminarGroup, error) { - switch { - case errSS != nil && errWS != nil: - return model.SeminarGroup{}, errWS - case errSS != nil: - return seminarGroup[1], nil - case errWS != nil: - return seminarGroup[0], nil - default: - seminarGroup[0].Events = append(seminarGroup[0].Events, seminarGroup[1].Events...) - return seminarGroup[0], nil - } -} - func SplitEventType(events []model.Event) ([]model.Event, error) { re, err := regexp.Compile("^([VPS])([wp])$") if err != nil { @@ -135,15 +101,21 @@ func parseSeminarGroup(result string) model.SeminarGroup { eventTables := getEventTables(doc) allDayLabels := getAllDayLabels(doc) - if eventTables == nil || allDayLabels == nil { - return model.SeminarGroup{} - } course := findFirstSpanWithClass(table, "header-2-0-1").FirstChild.Data + semesterString := findFirstSpanWithClass(table, "header-0-2-0").FirstChild.Data + semester, year := extractSemesterAndYear(semesterString) + + if eventTables == nil || allDayLabels == nil { + return model.SeminarGroup{ + University: findFirstSpanWithClass(table, "header-1-0-0").FirstChild.Data, + Course: course, + Events: []model.Event{}, + } + } + eventsWithCombinedWeeks := toEvents(eventTables, allDayLabels, course) splitEventsByWeekVal := splitEventsByWeek(eventsWithCombinedWeeks) events := splitEventsBySingleWeek(splitEventsByWeekVal) - semesterString := findFirstSpanWithClass(table, "header-0-2-0").FirstChild.Data - semester, year := extractSemesterAndYear(semesterString) events = convertWeeksToDates(events, semester, year) events = generateUUIDs(events, course) events, err = SplitEventType(events) diff --git a/services/data-manager/service/fetch/v1/fetchSeminarGroupService.go b/services/data-manager/service/fetch/v1/fetchSeminarGroupService.go index 316ff57..692847c 100644 --- a/services/data-manager/service/fetch/v1/fetchSeminarGroupService.go +++ b/services/data-manager/service/fetch/v1/fetchSeminarGroupService.go @@ -89,8 +89,9 @@ func removeDuplicates(groups db.SeminarGroups) db.SeminarGroups { uniqueGroups := make(db.SeminarGroups, 0, len(groups)) seen := make(map[string]struct{}) // Use an empty struct to minimize memory usage + // unique Identifier is the course and semester for _, group := range groups { - key := group.Course + group.Semester + key := group.UniqueKey() if _, exists := seen[key]; !exists { seen[key] = struct{}{} uniqueGroups = append(uniqueGroups, group) From 74ad6ad8e3628fdaae2437caed076affa8479299 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Sat, 6 Jul 2024 15:30:01 +0200 Subject: [PATCH 5/8] fix:#41 refactored services --- services/data-manager/main.go | 14 ++- .../model/serviceModel/serviceModel.go | 12 ++ services/data-manager/service/addRoute.go | 108 +++++++++--------- services/data-manager/service/addSchedule.go | 16 +-- .../service/course/courseFunctions.go | 9 +- .../service/course/courseFunctions_test.go | 97 ++++++++++++++++ .../service/events/courseService.go | 43 +++++-- .../service/events/eventService.go | 69 ++++++----- .../service/events/eventService_test.go | 4 +- .../service/events/mock/courseMock.go | 66 +++++++++++ services/go.mod | 5 + services/go.sum | 3 + 12 files changed, 335 insertions(+), 111 deletions(-) create mode 100644 services/data-manager/model/serviceModel/serviceModel.go create mode 100644 services/data-manager/service/course/courseFunctions_test.go create mode 100644 services/data-manager/service/events/mock/courseMock.go diff --git a/services/data-manager/main.go b/services/data-manager/main.go index 1e50b50..a5fbcf6 100644 --- a/services/data-manager/main.go +++ b/services/data-manager/main.go @@ -20,7 +20,9 @@ import ( "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/plugins/migratecmd" _ "htwkalender/data-manager/migrations" + "htwkalender/data-manager/model/serviceModel" "htwkalender/data-manager/service" + "htwkalender/data-manager/service/events" "htwkalender/data-manager/service/grpc" "log/slog" "os" @@ -29,6 +31,14 @@ import ( func setupApp() *pocketbase.PocketBase { app := pocketbase.New() + courseService := events.NewPocketBaseCourseService(app) + eventService := events.NewPocketBaseEventService(app) + + services := serviceModel.Service{ + CourseService: courseService, + EventService: eventService, + App: app, + } // loosely check if it was executed using "go run" isGoRun := strings.HasPrefix(os.Args[0], os.TempDir()) @@ -41,8 +51,8 @@ func setupApp() *pocketbase.PocketBase { // (the isGoRun check is to enable it only during development) Automigrate: isGoRun, }) - service.AddRoutes(app) - service.AddSchedules(app) + service.AddRoutes(services) + service.AddSchedules(services) return app } diff --git a/services/data-manager/model/serviceModel/serviceModel.go b/services/data-manager/model/serviceModel/serviceModel.go new file mode 100644 index 0000000..8e2fe69 --- /dev/null +++ b/services/data-manager/model/serviceModel/serviceModel.go @@ -0,0 +1,12 @@ +package serviceModel + +import ( + "github.com/pocketbase/pocketbase" + "htwkalender/data-manager/service/events" +) + +type Service struct { + App *pocketbase.PocketBase + EventService events.EventService + CourseService events.CourseService +} diff --git a/services/data-manager/service/addRoute.go b/services/data-manager/service/addRoute.go index 8dadd40..c295eaf 100644 --- a/services/data-manager/service/addRoute.go +++ b/services/data-manager/service/addRoute.go @@ -17,8 +17,8 @@ package service import ( + "htwkalender/data-manager/model/serviceModel" "htwkalender/data-manager/service/course" - "htwkalender/data-manager/service/events" "htwkalender/data-manager/service/fetch/sport" v1 "htwkalender/data-manager/service/fetch/v1" v2 "htwkalender/data-manager/service/fetch/v2" @@ -28,19 +28,18 @@ import ( "net/http" "github.com/labstack/echo/v5" - "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/apis" "github.com/pocketbase/pocketbase/core" ) -func AddRoutes(app *pocketbase.PocketBase) { +func AddRoutes(services serviceModel.Service) { - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/fetch/events", Handler: func(c echo.Context) error { - savedEvents, err := v2.ParseEventsFromRemote(app) + savedEvents, err := v2.ParseEventsFromRemote(services.App) if err != nil { slog.Error("Failed to parse events from remote: ", "error", err) return c.JSON(http.StatusBadRequest, "Failed to parse events from remote") @@ -49,7 +48,7 @@ func AddRoutes(app *pocketbase.PocketBase) { } }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), apis.RequireAdminAuth(), }, }) @@ -59,16 +58,16 @@ func AddRoutes(app *pocketbase.PocketBase) { return nil }) - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/fetch/daily/events", Handler: func(c echo.Context) error { - course.UpdateCourse(app) + course.UpdateCourse(services) return c.JSON(http.StatusOK, "Daily events fetched") }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), apis.RequireAdminAuth(), }, }) @@ -78,19 +77,19 @@ func AddRoutes(app *pocketbase.PocketBase) { return nil }) - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/fetch/groups", Handler: func(c echo.Context) error { - groups, err := v1.FetchSeminarGroups(app) + groups, err := v1.FetchSeminarGroups(services.App) if err != nil { return c.JSON(http.StatusBadRequest, "Failed to fetch seminar groups") } return c.JSON(http.StatusOK, groups) }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), apis.RequireAdminAuth(), }, }) @@ -100,20 +99,20 @@ func AddRoutes(app *pocketbase.PocketBase) { return nil }) - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/fetch/sports", Handler: func(c echo.Context) error { - sportEvents, err := sport.FetchAndUpdateSportEvents(app) + sportEvents, err := sport.FetchAndUpdateSportEvents(services.App) if err != nil { return c.JSON(http.StatusBadRequest, "Failed to fetch sport events") } return c.JSON(http.StatusOK, sportEvents) }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), apis.RequireAdminAuth(), }, }) @@ -123,19 +122,19 @@ func AddRoutes(app *pocketbase.PocketBase) { return nil }) - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodDelete, Path: "/api/modules", Handler: func(c echo.Context) error { - err := events.DeleteAllEvents(app) + err := services.EventService.DeleteAllEvents() if err != nil { return c.JSON(http.StatusBadRequest, "Failed to delete events") } return c.JSON(http.StatusOK, "Events deleted") }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), apis.RequireAdminAuth(), }, }) @@ -145,19 +144,19 @@ func AddRoutes(app *pocketbase.PocketBase) { return nil }) - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/rooms", Handler: func(c echo.Context) error { - rooms, err := room.GetRooms(app) + rooms, err := room.GetRooms(services.App) if err != nil { return c.JSON(http.StatusBadRequest, "Failed to get rooms") } return c.JSON(http.StatusOK, rooms) }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), }, }) if err != nil { @@ -167,14 +166,14 @@ func AddRoutes(app *pocketbase.PocketBase) { }) // API Endpoint to get all events for a specific room on a specific day - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/schedule/day", Handler: func(c echo.Context) error { roomParam := c.QueryParam("room") date := c.QueryParam("date") - roomSchedule, err := room.GetRoomScheduleForDay(app, roomParam, date) + roomSchedule, err := room.GetRoomScheduleForDay(services.App, roomParam, date) if err != nil { slog.Error("Failed to get room schedule for day: ", "error", err) return c.JSON(http.StatusBadRequest, "Failed to get room schedule for day") @@ -182,7 +181,7 @@ func AddRoutes(app *pocketbase.PocketBase) { return c.JSON(http.StatusOK, roomSchedule) }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), }, }) if err != nil { @@ -192,7 +191,7 @@ func AddRoutes(app *pocketbase.PocketBase) { }) // API Endpoint to create a new iCal feed - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/schedule", @@ -200,7 +199,7 @@ func AddRoutes(app *pocketbase.PocketBase) { roomParam := c.QueryParam("room") to := c.QueryParam("to") from := c.QueryParam("from") - roomSchedule, err := room.GetRoomSchedule(app, roomParam, from, to) + roomSchedule, err := room.GetRoomSchedule(services.App, roomParam, from, to) if err != nil { slog.Error("Failed to get room schedule:", "error", err) return c.JSON(http.StatusBadRequest, "Failed to get room schedule") @@ -208,7 +207,7 @@ func AddRoutes(app *pocketbase.PocketBase) { return c.JSON(http.StatusOK, roomSchedule) }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), }, }) if err != nil { @@ -218,7 +217,7 @@ func AddRoutes(app *pocketbase.PocketBase) { }) // API Endpoint to get all rooms that have no events in a specific time frame - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/rooms/free", @@ -233,7 +232,7 @@ func AddRoutes(app *pocketbase.PocketBase) { slog.Error("Failed to parse time: ", "error", err) return c.JSON(http.StatusBadRequest, "Failed to parse time") } - rooms, err := room.GetFreeRooms(app, from, to) + rooms, err := room.GetFreeRooms(services.App, from, to) if err != nil { slog.Error("Failed to get free rooms: ", "error", err) return c.JSON(http.StatusBadRequest, "Failed to get free rooms") @@ -241,7 +240,7 @@ func AddRoutes(app *pocketbase.PocketBase) { return c.JSON(http.StatusOK, rooms) }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), }, }) if err != nil { @@ -250,15 +249,14 @@ func AddRoutes(app *pocketbase.PocketBase) { return nil }) - addFeedRoutes(app) + addFeedRoutes(services.App) - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/course/modules", Handler: func(c echo.Context) error { - modules, err := events.GetModulesForCourseDistinct( - app, + modules, err := services.EventService.GetModulesForCourseDistinct( c.QueryParam("course"), c.QueryParam("semester"), ) @@ -271,7 +269,7 @@ func AddRoutes(app *pocketbase.PocketBase) { } }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), }, }) if err != nil { @@ -280,12 +278,12 @@ func AddRoutes(app *pocketbase.PocketBase) { return nil }) - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/modules", Handler: func(c echo.Context) error { - modules, err := events.GetAllModulesDistinct(app) + modules, err := services.EventService.GetAllModulesDistinct() if err != nil { slog.Error("Failed to get modules: ", "error", err) return c.JSON(http.StatusBadRequest, "Failed to get modules") @@ -293,7 +291,7 @@ func AddRoutes(app *pocketbase.PocketBase) { return c.JSON(http.StatusOK, modules) }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), }, }) if err != nil { @@ -302,13 +300,13 @@ func AddRoutes(app *pocketbase.PocketBase) { return nil }) - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/module", Handler: func(c echo.Context) error { requestModule := c.QueryParam("uuid") - module, err := events.GetModuleByUUID(app, requestModule) + module, err := services.EventService.GetModuleByUUID(requestModule) if err != nil { slog.Error("Failed to get module: ", "error", err) return c.JSON(http.StatusBadRequest, "Failed to get module") @@ -317,7 +315,7 @@ func AddRoutes(app *pocketbase.PocketBase) { } }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), }, }) if err != nil { @@ -326,22 +324,22 @@ func AddRoutes(app *pocketbase.PocketBase) { return nil }) - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/courses", Handler: func(c echo.Context) error { semester := c.QueryParam("semester") if semester == "" { - courses := events.GetAllCourses(app) + courses := services.CourseService.GetAllCourses() return c.JSON(200, courses) } else { - courses := events.GetAllCoursesForSemester(app, semester) + courses := services.CourseService.GetAllCoursesForSemester(semester) return c.JSON(200, courses) } }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), }, }) if err != nil { @@ -351,14 +349,13 @@ func AddRoutes(app *pocketbase.PocketBase) { }) // api end point to get all courses for a specific semester with courses that have events - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/courses/events", Handler: func(c echo.Context) error { semester := c.QueryParam("semester") - courses, err := events.GetAllCoursesForSemesterWithEvents(app, semester) - + courses, err := services.CourseService.GetAllCoursesForSemesterWithEvents(semester) if err != nil { slog.Error("Failed to get courses for semester with events: ", "error", err) return c.JSON(http.StatusBadRequest, "Failed to get courses for semester with events") @@ -367,7 +364,7 @@ func AddRoutes(app *pocketbase.PocketBase) { } }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), }, }) if err != nil { @@ -377,12 +374,12 @@ func AddRoutes(app *pocketbase.PocketBase) { }) // API Endpoint to get all eventTypes from the database distinct - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodGet, Path: "/api/events/types", Handler: func(c echo.Context) error { - eventTypes, err := events.GetEventTypes(app) + eventTypes, err := services.EventService.GetEventTypes() if err != nil { slog.Error("Failed to get event types", "error", err) return c.JSON(http.StatusBadRequest, "Failed to get event types") @@ -391,7 +388,7 @@ func AddRoutes(app *pocketbase.PocketBase) { } }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), }, }) if err != nil { @@ -400,13 +397,12 @@ func AddRoutes(app *pocketbase.PocketBase) { return nil }) - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { _, err := e.Router.AddRoute(echo.Route{ Method: http.MethodDelete, Path: "/api/events", Handler: func(c echo.Context) error { - err := events.DeleteAllEventsByCourseAndSemester( - app, + err := services.EventService.DeleteAllEventsByCourseAndSemester( c.QueryParam("course"), c.QueryParam("semester"), ) @@ -418,7 +414,7 @@ func AddRoutes(app *pocketbase.PocketBase) { } }, Middlewares: []echo.MiddlewareFunc{ - apis.ActivityLogger(app), + apis.ActivityLogger(services.App), apis.RequireAdminAuth(), }, }) diff --git a/services/data-manager/service/addSchedule.go b/services/data-manager/service/addSchedule.go index c24f2e1..da0bac4 100644 --- a/services/data-manager/service/addSchedule.go +++ b/services/data-manager/service/addSchedule.go @@ -17,9 +17,9 @@ package service import ( - "github.com/pocketbase/pocketbase" "github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/tools/cron" + "htwkalender/data-manager/model/serviceModel" "htwkalender/data-manager/service/course" "htwkalender/data-manager/service/feed" "htwkalender/data-manager/service/fetch/sport" @@ -30,9 +30,9 @@ import ( "strconv" ) -func AddSchedules(app *pocketbase.PocketBase) { +func AddSchedules(services serviceModel.Service) { - app.OnBeforeServe().Add(func(e *core.ServeEvent) error { + services.App.OnBeforeServe().Add(func(e *core.ServeEvent) error { scheduler := cron.New() // !! IMPORTANT !! CRON is based on UTC time zone so in Germany it is UTC+2 in summer and UTC+1 in winter @@ -40,7 +40,7 @@ func AddSchedules(app *pocketbase.PocketBase) { // Every sunday at 10pm update all courses (5 segments - minute, hour, day, month, weekday) "0 22 * * 0" scheduler.MustAdd("updateCourses", "0 22 * * 0", func() { slog.Info("Started updating courses schedule") - groups, err := v1.FetchSeminarGroups(app) + groups, err := v1.FetchSeminarGroups(services.App) if err != nil { slog.Warn("Failed to fetch seminar groups: ", "error", err) } @@ -51,20 +51,20 @@ func AddSchedules(app *pocketbase.PocketBase) { // In Germany it is 7am and 7pm, syllabus gets updated twice a day at German 5:00 Uhr and 17:00 Uhr scheduler.MustAdd("updateEventsByCourse", "0 5,17 * * *", func() { slog.Info("Started updating courses schedule") - course.UpdateCourse(app) + course.UpdateCourse(services) }) // Every sunday at 1am clean all courses (5 segments - minute, hour, day, month, weekday) "0 3 * * 0" scheduler.MustAdd("cleanFeeds", "0 1 * * 0", func() { // clean feeds older than 6 months slog.Info("Started cleaning feeds schedule") - feed.ClearFeeds(app.Dao(), 6, time.RealClock{}) + feed.ClearFeeds(services.App.Dao(), 6, time.RealClock{}) }) // Every sunday at 3am fetch all sport events (5 segments - minute, hour, day, month, weekday) "0 2 * * 0" scheduler.MustAdd("fetchSportEvents", "0 3 * * 0", func() { slog.Info("Started fetching sport events schedule") - sportEvents, err := sport.FetchAndUpdateSportEvents(app) + sportEvents, err := sport.FetchAndUpdateSportEvents(services.App) if err != nil { slog.Error("Failed to fetch and save sport events:", "error", err) } @@ -73,7 +73,7 @@ func AddSchedules(app *pocketbase.PocketBase) { //fetch all events for semester and delete from remote this should be done every sunday at 2am scheduler.MustAdd("fetchEvents", "0 22 * * 6", func() { - savedEvents, err := v2.FetchAllEventsAndSave(app, time.RealClock{}) + savedEvents, err := v2.FetchAllEventsAndSave(services.App, time.RealClock{}) if err != nil { slog.Error("Failed to fetch and save events: ", "error", err) } else { diff --git a/services/data-manager/service/course/courseFunctions.go b/services/data-manager/service/course/courseFunctions.go index 0612d97..50b3228 100644 --- a/services/data-manager/service/course/courseFunctions.go +++ b/services/data-manager/service/course/courseFunctions.go @@ -17,15 +17,14 @@ package course import ( - "github.com/pocketbase/pocketbase" - "htwkalender/data-manager/service/events" + "htwkalender/data-manager/model/serviceModel" "log/slog" ) -func UpdateCourse(app *pocketbase.PocketBase) { - courses := events.GetAllCourses(app) +func UpdateCourse(service serviceModel.Service) { + courses := service.CourseService.GetAllCourses() for _, course := range courses { - _, err := events.UpdateModulesForCourse(app, course) + _, err := service.EventService.UpdateModulesForCourse(course) if err != nil { slog.Warn("Update Course: "+course+" failed:", "error", err) } diff --git a/services/data-manager/service/course/courseFunctions_test.go b/services/data-manager/service/course/courseFunctions_test.go new file mode 100644 index 0000000..846efcc --- /dev/null +++ b/services/data-manager/service/course/courseFunctions_test.go @@ -0,0 +1,97 @@ +package course + +import ( + "bytes" + "fmt" + "github.com/stretchr/testify/require" + "htwkalender/data-manager/model" + "htwkalender/data-manager/model/serviceModel" + "htwkalender/data-manager/service/events/mock" + "log/slog" + "regexp" + "testing" +) + +// CustomWriter is a custom writer to capture log output +type CustomWriter struct { + Buffer bytes.Buffer +} + +func (w *CustomWriter) Write(p []byte) (n int, err error) { + return w.Buffer.Write(p) +} + +func TestUpdateCourse(t *testing.T) { + // Create mock services + mockCourseService := new(mock.MockCourseService) + mockEventService := new(mock.MockEventService) + + events := model.Events{} + + // Set up expectations + mockCourseService.On("GetAllCourses").Return([]string{"Course1", "Course2"}) + mockEventService.On("UpdateModulesForCourse", "Course1").Return(events, nil) + mockEventService.On("UpdateModulesForCourse", "Course2").Return(events, nil) + + // Inject mocks into the UpdateCourse function + service := serviceModel.Service{ + CourseService: mockCourseService, + EventService: mockEventService, + App: nil, + } + UpdateCourse(service) + + // Assert that the expectations were met + mockCourseService.AssertExpectations(t) + mockEventService.AssertExpectations(t) + + // Assert that the UpdateCourse function was called twice + mockCourseService.AssertNumberOfCalls(t, "GetAllCourses", 1) + mockEventService.AssertNumberOfCalls(t, "UpdateModulesForCourse", 2) + + // Assert that the UpdateCourse function was called with the correct arguments + mockEventService.AssertCalled(t, "UpdateModulesForCourse", "Course1") + mockEventService.AssertCalled(t, "UpdateModulesForCourse", "Course2") +} + +func TestUpdateCourseErr(t *testing.T) { + // Create mock services + mockCourseService := new(mock.MockCourseService) + mockEventService := new(mock.MockEventService) + + events := model.Events{} + + // Set up expectations + mockCourseService.On("GetAllCourses").Return([]string{"Course1", "Course2"}) + mockEventService.On("UpdateModulesForCourse", "Course1").Return(events, fmt.Errorf("error")) + mockEventService.On("UpdateModulesForCourse", "Course2").Return(events, fmt.Errorf("error")) + + // Create a custom writer to capture log output + customWriter := &CustomWriter{} + originalLogger := slog.Default() + defer slog.SetDefault(originalLogger) + + // Replace the default logger with a custom logger + slog.SetDefault(slog.New(slog.NewTextHandler(customWriter, nil))) + + // Inject mocks into the UpdateCourse function + service := serviceModel.Service{ + CourseService: mockCourseService, + EventService: mockEventService, + App: nil, + } + UpdateCourse(service) + + // Assert that the expectations were met + mockCourseService.AssertExpectations(t) + mockEventService.AssertExpectations(t) + + // Assert that the UpdateCourse function was called twice + mockCourseService.AssertNumberOfCalls(t, "GetAllCourses", 1) + mockEventService.AssertNumberOfCalls(t, "UpdateModulesForCourse", 2) + + // Check the captured log output for the expected messages + logOutput := customWriter.Buffer.String() + require.Regexp(t, regexp.MustCompile(`Update Course: Course1 failed:.*error`), logOutput) + require.Regexp(t, regexp.MustCompile(`Update Course: Course2 failed:.*error`), logOutput) +} diff --git a/services/data-manager/service/events/courseService.go b/services/data-manager/service/events/courseService.go index 389a428..c14fe87 100644 --- a/services/data-manager/service/events/courseService.go +++ b/services/data-manager/service/events/courseService.go @@ -22,32 +22,51 @@ import ( "htwkalender/data-manager/service/functions" ) -func GetAllCourses(app *pocketbase.PocketBase) []string { - return db.GetAllCourses(app) +// CourseService defines the methods to be implemented +type CourseService interface { + GetAllCourses() []string + GetAllCoursesForSemester(semester string) []string + GetAllCoursesForSemesterWithEvents(semester string) ([]string, error) } -func GetAllCoursesForSemester(app *pocketbase.PocketBase, semester string) []string { - return db.GetAllCoursesForSemester(app, semester) +// PocketBaseCourseService is a struct that implements the CourseService interface +type PocketBaseCourseService struct { + app *pocketbase.PocketBase } -func GetAllCoursesForSemesterWithEvents(app *pocketbase.PocketBase, semester string) ([]string, error) { - courses, err := db.GetAllCoursesForSemesterWithEvents(app, semester) +// NewPocketBaseCourseService creates a new PocketBaseCourseService +func NewPocketBaseCourseService(app *pocketbase.PocketBase) *PocketBaseCourseService { + return &PocketBaseCourseService{app: app} +} + +// GetAllCourses returns all courses +func (s *PocketBaseCourseService) GetAllCourses() []string { + return db.GetAllCourses(s.app) +} + +// GetAllCoursesForSemester returns all courses for a specific semester +func (s *PocketBaseCourseService) GetAllCoursesForSemester(semester string) []string { + return db.GetAllCoursesForSemester(s.app, semester) +} + +// GetAllCoursesForSemesterWithEvents returns all courses for a specific semester with events +func (s *PocketBaseCourseService) GetAllCoursesForSemesterWithEvents(semester string) ([]string, error) { + courses, err := db.GetAllCoursesForSemesterWithEvents(s.app, semester) if err != nil { return nil, err - } else { - // remove empty courses like " " or "" - courses = removeEmptyCourses(courses) - return courses, nil } + // remove empty courses like " " or "" + courses = removeEmptyCourses(courses) + return courses, nil } // removeEmptyCourses removes empty courses from the list of courses func removeEmptyCourses(courses []string) []string { var filteredCourses []string - for index, course := range courses { + for _, course := range courses { if !functions.OnlyWhitespace(course) || len(course) != 0 { - filteredCourses = append(filteredCourses, courses[index]) + filteredCourses = append(filteredCourses, course) } } return filteredCourses diff --git a/services/data-manager/service/events/eventService.go b/services/data-manager/service/events/eventService.go index afa318a..681efc3 100644 --- a/services/data-manager/service/events/eventService.go +++ b/services/data-manager/service/events/eventService.go @@ -26,9 +26,31 @@ import ( "strconv" ) -func GetModulesForCourseDistinct(app *pocketbase.PocketBase, course string, semester string) (model.Events, error) { +type EventService interface { + GetModulesForCourseDistinct(course string, semester string) (model.Events, error) + GetAllModulesDistinct() ([]model.ModuleDTO, error) + GetModuleByUUID(uuid string) (model.Module, error) + DeleteAllEventsByCourseAndSemester(course string, semester string) error + DeleteAllEvents() error + UpdateModulesForCourse(course string) (model.Events, error) + GetEventTypes() ([]string, error) +} - modules, err := db.GetAllModulesForCourse(app, course, semester) +type Named interface { + GetName() string + SetName(name string) +} + +type PocketBaseEventService struct { + app *pocketbase.PocketBase +} + +func NewPocketBaseEventService(app *pocketbase.PocketBase) *PocketBaseEventService { + return &PocketBaseEventService{app: app} +} + +func (s *PocketBaseEventService) GetModulesForCourseDistinct(course string, semester string) (model.Events, error) { + modules, err := db.GetAllModulesForCourse(s.app, course, semester) // Convert the []model.Module to []Named var namedEvents []Named @@ -40,11 +62,6 @@ func GetModulesForCourseDistinct(app *pocketbase.PocketBase, course string, seme return modules, err } -type Named interface { - GetName() string - SetName(name string) -} - // replaceEmptyEntry replaces an empty entry in a module with a replacement string // If the module is not empty, nothing happens func replaceEmptyEntry(namedList []Named, replacement string) { @@ -57,8 +74,8 @@ func replaceEmptyEntry(namedList []Named, replacement string) { // GetAllModulesDistinct returns all modules distinct by name and course from the database // That means you get all modules with duplicates if they have different courses -func GetAllModulesDistinct(app *pocketbase.PocketBase) ([]model.ModuleDTO, error) { - modules, err := db.GetAllModulesDistinctByNameAndCourse(app) +func (s *PocketBaseEventService) GetAllModulesDistinct() ([]model.ModuleDTO, error) { + modules, err := db.GetAllModulesDistinctByNameAndCourse(s.app) if err != nil { return nil, err } @@ -70,13 +87,13 @@ func GetAllModulesDistinct(app *pocketbase.PocketBase) ([]model.ModuleDTO, error return modules, nil } -func GetModuleByUUID(app *pocketbase.PocketBase, uuid string) (model.Module, error) { - module, findModuleErr := db.FindModuleByUUID(app, uuid) +func (s *PocketBaseEventService) GetModuleByUUID(uuid string) (model.Module, error) { + module, findModuleErr := db.FindModuleByUUID(s.app, uuid) if findModuleErr != nil { return model.Module{}, findModuleErr } - events, findEventsError := db.FindAllEventsByModule(app, module) + events, findEventsError := db.FindAllEventsByModule(s.app, module) if findEventsError != nil || len(events) == 0 { return model.Module{}, findEventsError } else { @@ -94,8 +111,8 @@ func GetModuleByUUID(app *pocketbase.PocketBase, uuid string) (model.Module, err // DeleteAllEventsByCourseAndSemester deletes all events for a course and a semester // If the deletion was successful, nil is returned // If the deletion was not successful, an error is returned -func DeleteAllEventsByCourseAndSemester(app *pocketbase.PocketBase, course string, semester string) error { - err := db.DeleteAllEventsByCourse(app.Dao(), course, semester) +func (s *PocketBaseEventService) DeleteAllEventsByCourseAndSemester(course string, semester string) error { + err := db.DeleteAllEventsByCourse(s.app.Dao(), course, semester) if err != nil { return err } else { @@ -103,8 +120,8 @@ func DeleteAllEventsByCourseAndSemester(app *pocketbase.PocketBase, course strin } } -func DeleteAllEvents(app *pocketbase.PocketBase) error { - err := db.DeleteAllEvents(app) +func (s *PocketBaseEventService) DeleteAllEvents() error { + err := db.DeleteAllEvents(s.app) if err != nil { return err } else { @@ -120,7 +137,7 @@ func DeleteAllEvents(app *pocketbase.PocketBase) error { // 3. Save all events for the course and the semester // If the update was successful, nil is returned // If the update was not successful, an error is returned -func UpdateModulesForCourse(app *pocketbase.PocketBase, course string) (model.Events, error) { +func (s *PocketBaseEventService) UpdateModulesForCourse(course string) (model.Events, error) { seminarGroup, err := v1.GetSeminarGroupEventsFromHTML(course) if err != nil { @@ -136,14 +153,14 @@ func UpdateModulesForCourse(app *pocketbase.PocketBase, course string) (model.Ev //if there are no events in the database, save the new events //get all events for the course and the semester - dbEvents, err := db.GetAllEventsForCourse(app, course) + dbEvents, err := db.GetAllEventsForCourse(s.app, course) if err != nil { return nil, err } //if there are no events in the database, save the new events if len(dbEvents) == 0 { - events, dbError := db.SaveSeminarGroupEvents(seminarGroup, app) + events, dbError := db.SaveSeminarGroupEvents(seminarGroup, s.app) if dbError != nil { return nil, dbError } @@ -156,27 +173,27 @@ func UpdateModulesForCourse(app *pocketbase.PocketBase, course string) (model.Ev // check which events are not already in the database and need to be inserted/saved for _, event := range seminarGroup.Events { - if !ContainsEvent(dbEvents, event) { + if !containsEvent(dbEvents, event) { insertList = append(insertList, event) } } // check which events are in the database but not in the seminarGroup and need to be deleted for _, dbEvent := range dbEvents { - if !ContainsEvent(seminarGroup.Events, dbEvent) { + if !containsEvent(seminarGroup.Events, dbEvent) { deleteList = append(deleteList, dbEvent) } } // delete all events that are in the deleteList - err = db.DeleteEvents(deleteList, app) + err = db.DeleteEvents(deleteList, s.app) if err != nil { slog.Error("Failed to delete events:", "error", err) return nil, err } // save all events that are in the insertList - savedEvents, err := db.SaveEvents(insertList, app.Dao()) + savedEvents, err := db.SaveEvents(insertList, s.app.Dao()) if err != nil { slog.Error("Failed to save events: ", "error", err) return nil, err @@ -186,7 +203,7 @@ func UpdateModulesForCourse(app *pocketbase.PocketBase, course string) (model.Ev return savedEvents, nil } -func ContainsEvent(events model.Events, event model.Event) bool { +func containsEvent(events model.Events, event model.Event) bool { for _, e := range events { if e.Name == event.Name && e.Prof == event.Prof && @@ -201,8 +218,8 @@ func ContainsEvent(events model.Events, event model.Event) bool { return false } -func GetEventTypes(app *pocketbase.PocketBase) ([]string, error) { - dbEventTypes, err := db.GetAllEventTypes(app) +func (s *PocketBaseEventService) GetEventTypes() ([]string, error) { + dbEventTypes, err := db.GetAllEventTypes(s.app) if err != nil { return nil, err } diff --git a/services/data-manager/service/events/eventService_test.go b/services/data-manager/service/events/eventService_test.go index e4f7b68..d64d58c 100644 --- a/services/data-manager/service/events/eventService_test.go +++ b/services/data-manager/service/events/eventService_test.go @@ -50,8 +50,8 @@ func TestContainsEvent(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := ContainsEvent(tt.args.events, tt.args.event); got != tt.want { - t.Errorf("ContainsEvent() = %v, want %v", got, tt.want) + if got := containsEvent(tt.args.events, tt.args.event); got != tt.want { + t.Errorf("containsEvent() = %v, want %v", got, tt.want) } }) } diff --git a/services/data-manager/service/events/mock/courseMock.go b/services/data-manager/service/events/mock/courseMock.go new file mode 100644 index 0000000..d01c113 --- /dev/null +++ b/services/data-manager/service/events/mock/courseMock.go @@ -0,0 +1,66 @@ +package mock + +import ( + "github.com/stretchr/testify/mock" + "htwkalender/data-manager/model" +) + +// MockCourseService is a mock implementation of the CourseService interface +type MockCourseService struct { + mock.Mock +} + +func (m *MockCourseService) GetAllCourses() []string { + args := m.Called() + return args.Get(0).([]string) +} + +func (m *MockCourseService) GetAllCoursesForSemester(semester string) []string { + args := m.Called(semester) + return args.Get(0).([]string) +} + +func (m *MockCourseService) GetAllCoursesForSemesterWithEvents(semester string) ([]string, error) { + args := m.Called(semester) + return args.Get(0).([]string), args.Error(1) +} + +// MockEventService is a mock implementation of the EventService interface +type MockEventService struct { + mock.Mock +} + +func (m *MockEventService) GetModulesForCourseDistinct(course string, semester string) (model.Events, error) { + args := m.Called(course, semester) + return args.Get(0).(model.Events), args.Error(1) +} + +func (m *MockEventService) GetAllModulesDistinct() ([]model.ModuleDTO, error) { + args := m.Called() + return args.Get(0).([]model.ModuleDTO), args.Error(1) +} + +func (m *MockEventService) GetModuleByUUID(uuid string) (model.Module, error) { + args := m.Called(uuid) + return args.Get(0).(model.Module), args.Error(1) +} + +func (m *MockEventService) DeleteAllEventsByCourseAndSemester(course string, semester string) error { + args := m.Called(course, semester) + return args.Error(0) +} + +func (m *MockEventService) DeleteAllEvents() error { + args := m.Called() + return args.Error(0) +} + +func (m *MockEventService) UpdateModulesForCourse(course string) (model.Events, error) { + args := m.Called(course) + return args.Get(0).(model.Events), args.Error(1) +} + +func (m *MockEventService) GetEventTypes() ([]string, error) { + args := m.Called() + return args.Get(0).([]string), args.Error(1) +} diff --git a/services/go.mod b/services/go.mod index 8d8ee37..a8571b7 100644 --- a/services/go.mod +++ b/services/go.mod @@ -12,6 +12,7 @@ require ( github.com/labstack/echo/v5 v5.0.0-20230722203903-ec5b858dab61 github.com/pocketbase/dbx v1.10.1 github.com/pocketbase/pocketbase v0.22.12 + github.com/stretchr/testify v1.9.0 golang.org/x/net v0.26.0 google.golang.org/grpc v1.63.2 google.golang.org/protobuf v1.34.1 @@ -41,6 +42,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.0 // indirect github.com/aws/aws-sdk-go-v2/service/sts v1.28.7 // indirect github.com/aws/smithy-go v1.20.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/disintegration/imaging v1.6.2 // indirect github.com/domodwyer/mailyak/v3 v3.6.2 // indirect github.com/dustin/go-humanize v1.0.1 // indirect @@ -62,10 +64,12 @@ require ( github.com/mattn/go-sqlite3 v1.14.22 // indirect github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect github.com/ncruces/go-strftime v0.1.9 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/cobra v1.8.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/objx v0.5.2 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasthttp v1.52.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect @@ -83,6 +87,7 @@ require ( golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/api v0.180.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240509183442-62759503f434 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/gc/v3 v3.0.0-20240304020402-f0dba7c97c2b // indirect modernc.org/libc v1.50.5 // indirect modernc.org/mathutil v1.6.0 // indirect diff --git a/services/go.sum b/services/go.sum index 50f1700..a97f4be 100644 --- a/services/go.sum +++ b/services/go.sum @@ -218,6 +218,8 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -366,6 +368,7 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= From e802b2c5b407423808e6352ffa062f148e5ea0ff Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Sat, 6 Jul 2024 15:34:31 +0200 Subject: [PATCH 6/8] fix:#41 refactored test names --- .../data-manager/model/eventModel_test.go | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/services/data-manager/model/eventModel_test.go b/services/data-manager/model/eventModel_test.go index 2749143..d67cd00 100644 --- a/services/data-manager/model/eventModel_test.go +++ b/services/data-manager/model/eventModel_test.go @@ -37,25 +37,25 @@ func TestEventsContains(t *testing.T) { want bool }{ { - name: "empty events", + name: "event contains empty events", m: Events{}, args: args{event: Event{}}, want: false, }, { - name: "one event", + name: "event contains one event", m: Events{{Day: "test", Week: "test", Start: specificTime, End: specificTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}}, args: args{event: Event{Day: "test", Week: "test", Start: specificTime, End: specificTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}}, want: true, }, { - name: "two events", + name: "event contains two events", m: Events{{Day: "test", Week: "test", Start: specificTime, End: specificTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}, {Day: "test2", Week: "test2", Start: specificTime, End: specificTime, Name: "test2", Course: "test2", Prof: "test2", Rooms: "test2", EventType: "test2"}}, args: args{event: Event{Day: "test2", Week: "test2", Start: specificTime, End: specificTime, Name: "test2", Course: "test2", Prof: "test2", Rooms: "test2", EventType: "test2"}}, want: true, }, { - name: "two events with different values", + name: "event contains two events with different values", m: Events{{Day: "test", Week: "test", Start: specificTime, End: specificTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test", UUID: "439ßu56rf8u9ijn4f4-2345345"}, {Day: "test2", Week: "test2", Start: specificTime, End: specificTime, Name: "test2", Course: "test2", Prof: "test2", Rooms: "test2", EventType: "test2", UUID: "432a39ßu545349ijn4f4-23dsa45"}}, args: args{event: Event{Day: "test3", Week: "test3", Start: specificTime, End: specificTime, Name: "test3", Course: "test3", Prof: "test3", Rooms: "test3", EventType: "test3", UUID: "934mf43r34f-g68h7655tg3"}}, want: false, @@ -99,25 +99,25 @@ func TestEventEquals(t *testing.T) { want bool }{ { - name: "empty events", + name: "event equals empty events", fields: fields{}, args: args{event: Event{}}, want: true, }, { - name: "one empty one not", + name: "event equals one empty one not", fields: fields{Day: "test", Week: "test", Start: specificTime, End: specificTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}, args: args{event: Event{}}, want: false, }, { - name: "one event", + name: "event equals one event", fields: fields{Day: "test", Week: "test", Start: specificTime, End: specificTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}, args: args{event: Event{Day: "test", Week: "test", Start: specificTime, End: specificTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}}, want: true, }, { - name: "two events", + name: "event equals two events", fields: fields{Day: "test", Week: "test", Start: specificTime, End: specificTime, Name: "test", Course: "test", Prof: "test", Rooms: "test", EventType: "test"}, args: args{event: Event{Day: "test2", Week: "test2", Start: specificTime, End: specificTime, Name: "test2", Course: "test2", Prof: "test2", Rooms: "test2", EventType: "test2"}}, want: false, @@ -172,22 +172,22 @@ func TestEventAnonymizeEvent(t *testing.T) { want AnonymizedEventDTO }{ { - name: "empty event", + name: "event anonymize empty event", fields: fields{}, want: AnonymizedEventDTO{Day: "", Week: "", Start: types.DateTime{}, End: types.DateTime{}, Rooms: "", Free: false}, }, { - name: "one event", + name: "event anonymize one event", fields: fields{Name: "Event", Day: "test", Week: "test", Rooms: "test"}, want: AnonymizedEventDTO{Day: "test", Week: "test", Start: types.DateTime{}, End: types.DateTime{}, Rooms: "test", Free: false}, }, { - name: "one event with free", + name: "event anonymize one event with free", fields: fields{Name: "Räume zur freien Verfügung", Day: "test", Week: "test", Rooms: "test", Course: "test"}, want: AnonymizedEventDTO{Day: "test", Week: "test", Start: types.DateTime{}, End: types.DateTime{}, Rooms: "test", Free: true}, }, { - name: "another free event", + name: "event anonymize another free event", fields: fields{Name: "Zur freien Verfügung", Day: "Montag", Week: "5", Start: types.DateTime{}, End: types.DateTime{}, Rooms: "TR_A1.28-S", Course: "42INM-3"}, want: AnonymizedEventDTO{Day: "Montag", Week: "5", Start: types.DateTime{}, End: types.DateTime{}, Rooms: "TR_A1.28-S", Free: true}, }, @@ -242,12 +242,12 @@ func TestEventGetName(t *testing.T) { want string }{ { - name: "empty event", + name: "event get name - empty event", fields: fields{}, want: "", }, { - name: "one event", + name: "event get name - one event", fields: fields{Name: "Event"}, want: "Event", }, @@ -464,7 +464,7 @@ func TestEventsContains1(t *testing.T) { want bool }{ { - name: "empty events", + name: "event contains - empty events", m: Events{}, args: args{event: Event{}}, want: false, From d44544cf8a4900b5306cf7689cf49ee048757cec Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Sat, 6 Jul 2024 17:18:09 +0200 Subject: [PATCH 7/8] fix:#46 added tests for UpdateCourse --- .../service/course/courseFunctions.go | 5 ++--- .../service/course/courseFunctions_test.go | 20 +++++++++---------- .../service/events/courseService.go | 2 +- .../service/events/mock/courseMock.go | 8 ++++---- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/services/data-manager/service/course/courseFunctions.go b/services/data-manager/service/course/courseFunctions.go index c7cc543..9e761b3 100644 --- a/services/data-manager/service/course/courseFunctions.go +++ b/services/data-manager/service/course/courseFunctions.go @@ -18,10 +18,9 @@ package course import ( "htwkalender/data-manager/model" - "htwkalender/data-manager/service/events" + "htwkalender/data-manager/model/serviceModel" "htwkalender/data-manager/service/functions" "htwkalender/data-manager/service/functions/time" - "htwkalender/data-manager/model/serviceModel" "log/slog" ) @@ -31,7 +30,7 @@ func UpdateCourse(service serviceModel.Service) { var seminarGroups []model.SeminarGroup for _, semester := range currentSemesters { - seminarGroups = append(seminarGroups, service.EventService.GetAllCoursesForSemester(semester)...) + seminarGroups = append(seminarGroups, service.CourseService.GetAllCoursesForSemester(semester)...) } for _, seminarGroup := range seminarGroups { diff --git a/services/data-manager/service/course/courseFunctions_test.go b/services/data-manager/service/course/courseFunctions_test.go index 846efcc..fb0fa9f 100644 --- a/services/data-manager/service/course/courseFunctions_test.go +++ b/services/data-manager/service/course/courseFunctions_test.go @@ -29,9 +29,9 @@ func TestUpdateCourse(t *testing.T) { events := model.Events{} // Set up expectations - mockCourseService.On("GetAllCourses").Return([]string{"Course1", "Course2"}) - mockEventService.On("UpdateModulesForCourse", "Course1").Return(events, nil) - mockEventService.On("UpdateModulesForCourse", "Course2").Return(events, nil) + mockCourseService.On("GetAllCoursesForSemester", "ss").Return([]model.SeminarGroup{{Course: "Course1", Semester: ""}, {Course: "Course2", Semester: ""}}) + mockEventService.On("UpdateModulesForCourse", model.SeminarGroup{Course: "Course1", Semester: ""}).Return(events, nil) + mockEventService.On("UpdateModulesForCourse", model.SeminarGroup{Course: "Course2", Semester: ""}).Return(events, nil) // Inject mocks into the UpdateCourse function service := serviceModel.Service{ @@ -46,12 +46,12 @@ func TestUpdateCourse(t *testing.T) { mockEventService.AssertExpectations(t) // Assert that the UpdateCourse function was called twice - mockCourseService.AssertNumberOfCalls(t, "GetAllCourses", 1) + mockCourseService.AssertNumberOfCalls(t, "GetAllCoursesForSemester", 1) mockEventService.AssertNumberOfCalls(t, "UpdateModulesForCourse", 2) // Assert that the UpdateCourse function was called with the correct arguments - mockEventService.AssertCalled(t, "UpdateModulesForCourse", "Course1") - mockEventService.AssertCalled(t, "UpdateModulesForCourse", "Course2") + mockEventService.AssertCalled(t, "UpdateModulesForCourse", model.SeminarGroup{Course: "Course1", Semester: ""}) + mockEventService.AssertCalled(t, "UpdateModulesForCourse", model.SeminarGroup{Course: "Course2", Semester: ""}) } func TestUpdateCourseErr(t *testing.T) { @@ -62,9 +62,9 @@ func TestUpdateCourseErr(t *testing.T) { events := model.Events{} // Set up expectations - mockCourseService.On("GetAllCourses").Return([]string{"Course1", "Course2"}) - mockEventService.On("UpdateModulesForCourse", "Course1").Return(events, fmt.Errorf("error")) - mockEventService.On("UpdateModulesForCourse", "Course2").Return(events, fmt.Errorf("error")) + mockCourseService.On("GetAllCoursesForSemester", "ss").Return([]model.SeminarGroup{{Course: "Course1", Semester: ""}, {Course: "Course2", Semester: ""}}) + mockEventService.On("UpdateModulesForCourse", model.SeminarGroup{Course: "Course1", Semester: ""}).Return(events, fmt.Errorf("error")) + mockEventService.On("UpdateModulesForCourse", model.SeminarGroup{Course: "Course2", Semester: ""}).Return(events, fmt.Errorf("error")) // Create a custom writer to capture log output customWriter := &CustomWriter{} @@ -87,7 +87,7 @@ func TestUpdateCourseErr(t *testing.T) { mockEventService.AssertExpectations(t) // Assert that the UpdateCourse function was called twice - mockCourseService.AssertNumberOfCalls(t, "GetAllCourses", 1) + mockCourseService.AssertNumberOfCalls(t, "GetAllCoursesForSemester", 1) mockEventService.AssertNumberOfCalls(t, "UpdateModulesForCourse", 2) // Check the captured log output for the expected messages diff --git a/services/data-manager/service/events/courseService.go b/services/data-manager/service/events/courseService.go index 415f8b1..65cc1a8 100644 --- a/services/data-manager/service/events/courseService.go +++ b/services/data-manager/service/events/courseService.go @@ -26,7 +26,7 @@ import ( // CourseService defines the methods to be implemented type CourseService interface { GetAllCourses() []string - GetAllCoursesForSemester(semester string) []string + GetAllCoursesForSemester(semester string) []model.SeminarGroup GetAllCoursesForSemesterWithEvents(semester string) ([]string, error) } diff --git a/services/data-manager/service/events/mock/courseMock.go b/services/data-manager/service/events/mock/courseMock.go index d01c113..80aabce 100644 --- a/services/data-manager/service/events/mock/courseMock.go +++ b/services/data-manager/service/events/mock/courseMock.go @@ -15,9 +15,9 @@ func (m *MockCourseService) GetAllCourses() []string { return args.Get(0).([]string) } -func (m *MockCourseService) GetAllCoursesForSemester(semester string) []string { +func (m *MockCourseService) GetAllCoursesForSemester(semester string) []model.SeminarGroup { args := m.Called(semester) - return args.Get(0).([]string) + return args.Get(0).([]model.SeminarGroup) } func (m *MockCourseService) GetAllCoursesForSemesterWithEvents(semester string) ([]string, error) { @@ -55,8 +55,8 @@ func (m *MockEventService) DeleteAllEvents() error { return args.Error(0) } -func (m *MockEventService) UpdateModulesForCourse(course string) (model.Events, error) { - args := m.Called(course) +func (m *MockEventService) UpdateModulesForCourse(seminarGroup model.SeminarGroup) (model.Events, error) { + args := m.Called(seminarGroup) return args.Get(0).(model.Events), args.Error(1) } From c62c70f27b0933d8962244e2e6f92d0e072ee890 Mon Sep 17 00:00:00 2001 From: Elmar Kresse Date: Sat, 6 Jul 2024 17:33:29 +0200 Subject: [PATCH 8/8] fix:#46 renamed test function names --- services/data-manager/model/feedModel_test.go | 2 +- services/data-manager/model/moduleModel_test.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/services/data-manager/model/feedModel_test.go b/services/data-manager/model/feedModel_test.go index 111d8d1..f2de61b 100644 --- a/services/data-manager/model/feedModel_test.go +++ b/services/data-manager/model/feedModel_test.go @@ -6,7 +6,7 @@ import ( "testing" ) -func TestFeed_SetModules(t *testing.T) { +func TestFeedSetModules(t *testing.T) { type fields struct { Modules string Retrieved types.DateTime diff --git a/services/data-manager/model/moduleModel_test.go b/services/data-manager/model/moduleModel_test.go index b2ebe5d..b0dc7a8 100644 --- a/services/data-manager/model/moduleModel_test.go +++ b/services/data-manager/model/moduleModel_test.go @@ -2,7 +2,7 @@ package model import "testing" -func TestModuleDTO_GetName(t *testing.T) { +func TestModuleDTOGetName(t *testing.T) { type fields struct { UUID string Name string @@ -41,7 +41,7 @@ func TestModuleDTO_GetName(t *testing.T) { } } -func TestModuleDTO_SetName(t *testing.T) { +func TestModuleDTOSetName(t *testing.T) { type fields struct { UUID string Name string @@ -83,7 +83,7 @@ func TestModuleDTO_SetName(t *testing.T) { } } -func TestModule_SetName(t *testing.T) { +func TestModuleSetName(t *testing.T) { type fields struct { UUID string Name string