mirror of
https://gitlab.dit.htwk-leipzig.de/htwk-software/htwkalender.git
synced 2025-07-16 09:38:49 +02:00
fix:#25 added tests and schedule updates
This commit is contained in:
@ -79,7 +79,7 @@ func (e *Event) SetCourse(course string) Event {
|
||||
return *e
|
||||
}
|
||||
|
||||
// Creates an AnonymizedEventDTO from an Event hiding all sensitive data
|
||||
// AnonymizeEvent Creates an AnonymizedEventDTO from an Event hiding all sensitive data
|
||||
func (e *Event) AnonymizeEvent() AnonymizedEventDTO {
|
||||
return AnonymizedEventDTO{
|
||||
Day: e.Day,
|
||||
|
@ -217,3 +217,264 @@ func TestEvent_AnonymizeEvent(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvent_GetName(t *testing.T) {
|
||||
type fields struct {
|
||||
UUID string
|
||||
Day string
|
||||
Week string
|
||||
Start types.DateTime
|
||||
End types.DateTime
|
||||
Name string
|
||||
EventType string
|
||||
Compulsory string
|
||||
Prof string
|
||||
Rooms string
|
||||
Notes string
|
||||
BookedAt string
|
||||
Course string
|
||||
Semester string
|
||||
BaseModel models.BaseModel
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "empty event",
|
||||
fields: fields{},
|
||||
want: "",
|
||||
},
|
||||
{
|
||||
name: "one event",
|
||||
fields: fields{Name: "Event"},
|
||||
want: "Event",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
e := &Event{
|
||||
UUID: tt.fields.UUID,
|
||||
Day: tt.fields.Day,
|
||||
Week: tt.fields.Week,
|
||||
Start: tt.fields.Start,
|
||||
End: tt.fields.End,
|
||||
Name: tt.fields.Name,
|
||||
EventType: tt.fields.EventType,
|
||||
Compulsory: tt.fields.Compulsory,
|
||||
Prof: tt.fields.Prof,
|
||||
Rooms: tt.fields.Rooms,
|
||||
Notes: tt.fields.Notes,
|
||||
BookedAt: tt.fields.BookedAt,
|
||||
Course: tt.fields.Course,
|
||||
Semester: tt.fields.Semester,
|
||||
BaseModel: tt.fields.BaseModel,
|
||||
}
|
||||
if got := e.GetName(); got != tt.want {
|
||||
t.Errorf("GetName() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvent_SetCourse(t *testing.T) {
|
||||
type fields struct {
|
||||
UUID string
|
||||
Day string
|
||||
Week string
|
||||
Start types.DateTime
|
||||
End types.DateTime
|
||||
Name string
|
||||
EventType string
|
||||
Compulsory string
|
||||
Prof string
|
||||
Rooms string
|
||||
Notes string
|
||||
BookedAt string
|
||||
Course string
|
||||
Semester string
|
||||
BaseModel models.BaseModel
|
||||
}
|
||||
type args struct {
|
||||
course string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
want Event
|
||||
}{
|
||||
{
|
||||
name: "set course",
|
||||
fields: fields{},
|
||||
args: args{course: "test"},
|
||||
want: Event{Course: "test"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
e := &Event{
|
||||
UUID: tt.fields.UUID,
|
||||
Day: tt.fields.Day,
|
||||
Week: tt.fields.Week,
|
||||
Start: tt.fields.Start,
|
||||
End: tt.fields.End,
|
||||
Name: tt.fields.Name,
|
||||
EventType: tt.fields.EventType,
|
||||
Compulsory: tt.fields.Compulsory,
|
||||
Prof: tt.fields.Prof,
|
||||
Rooms: tt.fields.Rooms,
|
||||
Notes: tt.fields.Notes,
|
||||
BookedAt: tt.fields.BookedAt,
|
||||
Course: tt.fields.Course,
|
||||
Semester: tt.fields.Semester,
|
||||
BaseModel: tt.fields.BaseModel,
|
||||
}
|
||||
if got := e.SetCourse(tt.args.course); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("SetCourse() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvent_SetName(t *testing.T) {
|
||||
type fields struct {
|
||||
UUID string
|
||||
Day string
|
||||
Week string
|
||||
Start types.DateTime
|
||||
End types.DateTime
|
||||
Name string
|
||||
EventType string
|
||||
Compulsory string
|
||||
Prof string
|
||||
Rooms string
|
||||
Notes string
|
||||
BookedAt string
|
||||
Course string
|
||||
Semester string
|
||||
BaseModel models.BaseModel
|
||||
}
|
||||
type args struct {
|
||||
name string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
}{
|
||||
{
|
||||
name: "set name",
|
||||
fields: fields{
|
||||
Name: "name",
|
||||
},
|
||||
args: args{
|
||||
name: "name",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
e := &Event{
|
||||
UUID: tt.fields.UUID,
|
||||
Day: tt.fields.Day,
|
||||
Week: tt.fields.Week,
|
||||
Start: tt.fields.Start,
|
||||
End: tt.fields.End,
|
||||
Name: tt.fields.Name,
|
||||
EventType: tt.fields.EventType,
|
||||
Compulsory: tt.fields.Compulsory,
|
||||
Prof: tt.fields.Prof,
|
||||
Rooms: tt.fields.Rooms,
|
||||
Notes: tt.fields.Notes,
|
||||
BookedAt: tt.fields.BookedAt,
|
||||
Course: tt.fields.Course,
|
||||
Semester: tt.fields.Semester,
|
||||
BaseModel: tt.fields.BaseModel,
|
||||
}
|
||||
e.SetName(tt.args.name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvent_TableName(t *testing.T) {
|
||||
type fields struct {
|
||||
UUID string
|
||||
Day string
|
||||
Week string
|
||||
Start types.DateTime
|
||||
End types.DateTime
|
||||
Name string
|
||||
EventType string
|
||||
Compulsory string
|
||||
Prof string
|
||||
Rooms string
|
||||
Notes string
|
||||
BookedAt string
|
||||
Course string
|
||||
Semester string
|
||||
BaseModel models.BaseModel
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "table name",
|
||||
fields: fields{},
|
||||
want: "events",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
e := &Event{
|
||||
UUID: tt.fields.UUID,
|
||||
Day: tt.fields.Day,
|
||||
Week: tt.fields.Week,
|
||||
Start: tt.fields.Start,
|
||||
End: tt.fields.End,
|
||||
Name: tt.fields.Name,
|
||||
EventType: tt.fields.EventType,
|
||||
Compulsory: tt.fields.Compulsory,
|
||||
Prof: tt.fields.Prof,
|
||||
Rooms: tt.fields.Rooms,
|
||||
Notes: tt.fields.Notes,
|
||||
BookedAt: tt.fields.BookedAt,
|
||||
Course: tt.fields.Course,
|
||||
Semester: tt.fields.Semester,
|
||||
BaseModel: tt.fields.BaseModel,
|
||||
}
|
||||
if got := e.TableName(); got != tt.want {
|
||||
t.Errorf("TableName() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvents_Contains1(t *testing.T) {
|
||||
type args struct {
|
||||
event Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
m Events
|
||||
args args
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "empty events",
|
||||
m: Events{},
|
||||
args: args{event: Event{}},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := tt.m.Contains(tt.args.event); got != tt.want {
|
||||
t.Errorf("Contains() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
45
backend/model/feedModel_test.go
Normal file
45
backend/model/feedModel_test.go
Normal file
@ -0,0 +1,45 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
"github.com/pocketbase/pocketbase/tools/types"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFeed_SetModules(t *testing.T) {
|
||||
type fields struct {
|
||||
Modules string
|
||||
Retrieved types.DateTime
|
||||
BaseModel models.BaseModel
|
||||
}
|
||||
type args struct {
|
||||
modules string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
}{
|
||||
{
|
||||
name: "set modules",
|
||||
fields: fields{
|
||||
Modules: "",
|
||||
Retrieved: types.DateTime{},
|
||||
BaseModel: models.BaseModel{},
|
||||
},
|
||||
args: args{
|
||||
modules: "modules",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
f := &Feed{
|
||||
Modules: tt.fields.Modules,
|
||||
Retrieved: tt.fields.Retrieved,
|
||||
BaseModel: tt.fields.BaseModel,
|
||||
}
|
||||
f.SetModules(tt.args.modules)
|
||||
})
|
||||
}
|
||||
}
|
126
backend/model/moduleModel_test.go
Normal file
126
backend/model/moduleModel_test.go
Normal file
@ -0,0 +1,126 @@
|
||||
package model
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestModuleDTO_GetName(t *testing.T) {
|
||||
type fields struct {
|
||||
UUID string
|
||||
Name string
|
||||
Prof string
|
||||
Course string
|
||||
Semester string
|
||||
EventType string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "get name",
|
||||
fields: fields{
|
||||
Name: "name",
|
||||
},
|
||||
want: "name",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := &ModuleDTO{
|
||||
UUID: tt.fields.UUID,
|
||||
Name: tt.fields.Name,
|
||||
Prof: tt.fields.Prof,
|
||||
Course: tt.fields.Course,
|
||||
Semester: tt.fields.Semester,
|
||||
EventType: tt.fields.EventType,
|
||||
}
|
||||
if got := m.GetName(); got != tt.want {
|
||||
t.Errorf("GetName() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestModuleDTO_SetName(t *testing.T) {
|
||||
type fields struct {
|
||||
UUID string
|
||||
Name string
|
||||
Prof string
|
||||
Course string
|
||||
Semester string
|
||||
EventType string
|
||||
}
|
||||
type args struct {
|
||||
name string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
}{
|
||||
{
|
||||
name: "set name",
|
||||
fields: fields{
|
||||
Name: "name",
|
||||
},
|
||||
args: args{
|
||||
name: "name",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := &ModuleDTO{
|
||||
UUID: tt.fields.UUID,
|
||||
Name: tt.fields.Name,
|
||||
Prof: tt.fields.Prof,
|
||||
Course: tt.fields.Course,
|
||||
Semester: tt.fields.Semester,
|
||||
EventType: tt.fields.EventType,
|
||||
}
|
||||
m.SetName(tt.args.name)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestModule_SetName(t *testing.T) {
|
||||
type fields struct {
|
||||
UUID string
|
||||
Name string
|
||||
Prof string
|
||||
Course string
|
||||
Semester string
|
||||
Events Events
|
||||
}
|
||||
type args struct {
|
||||
name string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
args args
|
||||
}{
|
||||
{
|
||||
name: "set name",
|
||||
fields: fields{
|
||||
Name: "name",
|
||||
},
|
||||
args: args{
|
||||
name: "name",
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := &Module{
|
||||
UUID: tt.fields.UUID,
|
||||
Name: tt.fields.Name,
|
||||
Prof: tt.fields.Prof,
|
||||
Course: tt.fields.Course,
|
||||
Semester: tt.fields.Semester,
|
||||
Events: tt.fields.Events,
|
||||
}
|
||||
m.SetName(tt.args.name)
|
||||
})
|
||||
}
|
||||
}
|
@ -22,7 +22,6 @@ import (
|
||||
v1 "htwkalender/service/fetch/v1"
|
||||
v2 "htwkalender/service/fetch/v2"
|
||||
"htwkalender/service/functions/time"
|
||||
"htwkalender/service/ical"
|
||||
"htwkalender/service/room"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
@ -380,29 +379,4 @@ func AddRoutes(app *pocketbase.PocketBase) {
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
||||
_, err := e.Router.AddRoute(echo.Route{
|
||||
Method: http.MethodGet,
|
||||
Path: "/api/feeds/migrate",
|
||||
Handler: func(c echo.Context) error {
|
||||
err := ical.MigrateFeedJson(app)
|
||||
|
||||
if err != nil {
|
||||
slog.Error("Failed to migrate feeds: %v", err)
|
||||
return c.JSON(http.StatusInternalServerError, "Failed to migrate feeds")
|
||||
} else {
|
||||
return c.JSON(http.StatusOK, "Migrated")
|
||||
}
|
||||
},
|
||||
Middlewares: []echo.MiddlewareFunc{
|
||||
apis.ActivityLogger(app),
|
||||
apis.RequireAdminAuth(),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"htwkalender/service/course"
|
||||
"htwkalender/service/feed"
|
||||
"htwkalender/service/fetch/sport"
|
||||
v1 "htwkalender/service/fetch/v1"
|
||||
v2 "htwkalender/service/fetch/v2"
|
||||
"htwkalender/service/functions/time"
|
||||
"log/slog"
|
||||
@ -34,10 +35,21 @@ func AddSchedules(app *pocketbase.PocketBase) {
|
||||
app.OnBeforeServe().Add(func(e *core.ServeEvent) error {
|
||||
scheduler := cron.New()
|
||||
|
||||
// Every hour update all courses (5 segments - minute, hour, day, month, weekday) "0 * * * *"
|
||||
// Every three hours update all courses (5 segments - minute, hour, day, month, weekday) "0 */3 * * *"
|
||||
// Every 10 minutes update all courses (5 segments - minute, hour, day, month, weekday) "*/10 * * * *"
|
||||
scheduler.MustAdd("updateCourse", "0 */3 * * *", func() {
|
||||
// !! IMPORTANT !! CRON is based on UTC time zone so in Germany it is UTC+2 in summer and UTC+1 in winter
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
slog.Warn("Failed to fetch seminar groups: %v", err)
|
||||
}
|
||||
slog.Info("Successfully fetched " + strconv.FormatInt(int64(len(groups)), 10) + " seminar groups")
|
||||
})
|
||||
|
||||
// Every day at 5am and 5pm update all courses (5 segments - minute, hour, day, month, weekday) "0 5,17 * * *"
|
||||
// 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)
|
||||
})
|
||||
@ -60,7 +72,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 2 * * 0", func() {
|
||||
scheduler.MustAdd("fetchEvents", "0 22 * * 6", func() {
|
||||
savedEvents, err := v2.FetchAllEventsAndSave(app, time.RealClock{})
|
||||
if err != nil {
|
||||
slog.Error("Failed to fetch and save events: %v", err)
|
||||
|
58
backend/service/events/eventService_test.go
Normal file
58
backend/service/events/eventService_test.go
Normal file
@ -0,0 +1,58 @@
|
||||
package events
|
||||
|
||||
import (
|
||||
"htwkalender/model"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestContainsEvent(t *testing.T) {
|
||||
type args struct {
|
||||
events model.Events
|
||||
event model.Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "contains event",
|
||||
args: args{
|
||||
events: model.Events{
|
||||
{
|
||||
UUID: "934807509832475",
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
event: model.Event{
|
||||
UUID: "934807509832475",
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "contains no event",
|
||||
args: args{
|
||||
events: model.Events{
|
||||
{
|
||||
UUID: "9991929292921912343534",
|
||||
Name: "Name1",
|
||||
},
|
||||
},
|
||||
event: model.Event{
|
||||
UUID: "1111112312312312",
|
||||
Name: "Name2",
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ import (
|
||||
"htwkalender/model"
|
||||
"htwkalender/service/db"
|
||||
"htwkalender/service/functions"
|
||||
clock "htwkalender/service/functions/time"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
@ -81,7 +82,7 @@ func FetchAndUpdateSportEvents(app *pocketbase.PocketBase) ([]model.Event, error
|
||||
}
|
||||
|
||||
// @TODO: delete and save events in one transaction and it only should delete events that are not in the new events list and save events that are not in the database
|
||||
err = db.DeleteAllEventsByCourse(app, "Sport", functions.GetCurrentSemesterString())
|
||||
err = db.DeleteAllEventsByCourse(app, "Sport", functions.GetCurrentSemesterString(clock.RealClock{}))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -23,6 +23,8 @@ import (
|
||||
"github.com/pocketbase/pocketbase/models"
|
||||
"htwkalender/model"
|
||||
"htwkalender/service/db"
|
||||
"htwkalender/service/functions"
|
||||
"htwkalender/service/functions/time"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
@ -59,23 +61,19 @@ func getSeminarHTML(semester string) (string, error) {
|
||||
func FetchSeminarGroups(app *pocketbase.PocketBase) ([]*models.Record, error) {
|
||||
var groups []model.SeminarGroup
|
||||
|
||||
resultSummer, err := getSeminarHTML("ss")
|
||||
semesterString := functions.CalculateSemesterList(time.RealClock{})
|
||||
var results [2]string
|
||||
var err error
|
||||
|
||||
if err != nil {
|
||||
slog.Error("Error while fetching seminar groups for winter semester", err)
|
||||
return nil, err
|
||||
for i, semester := range semesterString {
|
||||
results[i], err = getSeminarHTML(semester)
|
||||
if err != nil {
|
||||
slog.Error("Error while fetching seminar groups for: "+semester, err)
|
||||
return nil, err
|
||||
}
|
||||
groups = append(groups, parseSeminarGroups(results[i], semester)...)
|
||||
}
|
||||
|
||||
resultWinter, _ := getSeminarHTML("ws")
|
||||
|
||||
if err != nil {
|
||||
slog.Error("Error while fetching seminar groups for summer semester", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
groups = parseSeminarGroups(resultSummer, "ss")
|
||||
groups = append(groups, parseSeminarGroups(resultWinter, "ws")...)
|
||||
|
||||
// filter duplicates
|
||||
groups = removeDuplicates(groups)
|
||||
|
||||
|
@ -25,10 +25,10 @@ import (
|
||||
"htwkalender/service/db"
|
||||
"htwkalender/service/fetch"
|
||||
v1 "htwkalender/service/fetch/v1"
|
||||
"htwkalender/service/functions"
|
||||
localTime "htwkalender/service/functions/time"
|
||||
"log/slog"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func ParseEventsFromRemote(app *pocketbase.PocketBase) (model.Events, error) {
|
||||
@ -70,7 +70,7 @@ func FetchAllEventsAndSave(app *pocketbase.PocketBase, clock localTime.Clock) ([
|
||||
}
|
||||
|
||||
// Fetch and save events for all semesters
|
||||
for _, semester := range calculateSemesterList(clock) {
|
||||
for _, semester := range functions.CalculateSemesterList(clock) {
|
||||
events, fetchErr := fetchAndSaveAllEventsForSemester(app, semester, stubUrl)
|
||||
if fetchErr != nil {
|
||||
return nil, fmt.Errorf("failed to fetch and save events for "+semester+": %w", err)
|
||||
@ -104,25 +104,6 @@ func fetchAndSaveAllEventsForSemester(
|
||||
return savedRecords, err
|
||||
}
|
||||
|
||||
func calculateSemesterList(clock localTime.Clock) []string {
|
||||
summerSemester := clock.Now().Month() >= time.March && clock.Now().Month() <= time.September
|
||||
winterSemester := clock.Now().Month() <= time.March || clock.Now().Month() >= time.September
|
||||
|
||||
if summerSemester && winterSemester {
|
||||
return []string{"ss", "ws"}
|
||||
}
|
||||
|
||||
if summerSemester {
|
||||
return []string{"ss"}
|
||||
}
|
||||
|
||||
if winterSemester {
|
||||
return []string{"ws"}
|
||||
}
|
||||
|
||||
return []string{"ss", "ws"}
|
||||
}
|
||||
|
||||
func parseEventForOneSemester(url string) ([]model.Event, error) {
|
||||
// Fetch Webpage from URL
|
||||
webpage, err := fetch.GetHTML(url)
|
||||
|
@ -18,10 +18,8 @@ package v2
|
||||
|
||||
import (
|
||||
"htwkalender/model"
|
||||
mockTime "htwkalender/service/functions/time"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_switchNameAndNotesForExam(t *testing.T) {
|
||||
@ -99,49 +97,3 @@ func Test_switchNameAndNotesForExam(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_calculateSemesterList(t *testing.T) {
|
||||
type args struct {
|
||||
clock mockTime.Clock
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "is summer semester",
|
||||
args: args{
|
||||
clock: mockTime.MockClock{
|
||||
NowTime: time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
want: []string{"ss"},
|
||||
},
|
||||
{
|
||||
name: "is winter semester",
|
||||
args: args{
|
||||
clock: mockTime.MockClock{
|
||||
NowTime: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
want: []string{"ws"},
|
||||
},
|
||||
{
|
||||
name: "is in both",
|
||||
args: args{
|
||||
clock: mockTime.MockClock{
|
||||
NowTime: time.Date(2024, 3, 22, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
want: []string{"ss", "ws"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := calculateSemesterList(tt.args.clock); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("calculateSemesterList() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -16,15 +16,32 @@
|
||||
|
||||
package functions
|
||||
|
||||
import "time"
|
||||
import (
|
||||
localTime "htwkalender/service/functions/time"
|
||||
"time"
|
||||
)
|
||||
|
||||
// GetCurrentSemesterString returns the current semester as string
|
||||
// if current month is between 10 and 03 -> winter semester "ws"
|
||||
func GetCurrentSemesterString() string {
|
||||
|
||||
if time.Now().Month() >= 10 || time.Now().Month() <= 3 {
|
||||
func GetCurrentSemesterString(localeTime localTime.Clock) string {
|
||||
if localeTime.Now().Month() >= 10 || localeTime.Now().Month() <= 3 {
|
||||
return "ws"
|
||||
} else {
|
||||
return "ss"
|
||||
}
|
||||
}
|
||||
|
||||
func CalculateSemesterList(clock localTime.Clock) []string {
|
||||
summerSemester := clock.Now().Month() >= time.March && clock.Now().Month() <= time.September
|
||||
winterSemester := clock.Now().Month() <= time.March || clock.Now().Month() >= time.September
|
||||
|
||||
if summerSemester && !winterSemester {
|
||||
return []string{"ss"}
|
||||
}
|
||||
|
||||
if !summerSemester && winterSemester {
|
||||
return []string{"ws"}
|
||||
}
|
||||
|
||||
return []string{"ss", "ws"}
|
||||
}
|
||||
|
91
backend/service/functions/semester_test.go
Normal file
91
backend/service/functions/semester_test.go
Normal file
@ -0,0 +1,91 @@
|
||||
package functions
|
||||
|
||||
import (
|
||||
mockTime "htwkalender/service/functions/time"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_calculateSemesterList(t *testing.T) {
|
||||
type args struct {
|
||||
clock mockTime.Clock
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "is summer semester",
|
||||
args: args{
|
||||
clock: mockTime.MockClock{
|
||||
NowTime: time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
want: []string{"ss"},
|
||||
},
|
||||
{
|
||||
name: "is winter semester",
|
||||
args: args{
|
||||
clock: mockTime.MockClock{
|
||||
NowTime: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
want: []string{"ws"},
|
||||
},
|
||||
{
|
||||
name: "is in both",
|
||||
args: args{
|
||||
clock: mockTime.MockClock{
|
||||
NowTime: time.Date(2024, 3, 22, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
want: []string{"ss", "ws"},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := CalculateSemesterList(tt.args.clock); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("calculateSemesterList() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetCurrentSemesterString(t *testing.T) {
|
||||
type args struct {
|
||||
localeTime mockTime.Clock
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "is winter semester",
|
||||
args: args{
|
||||
localeTime: mockTime.MockClock{
|
||||
NowTime: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
want: "ws",
|
||||
},
|
||||
{
|
||||
name: "is summer semester",
|
||||
args: args{
|
||||
localeTime: mockTime.MockClock{
|
||||
NowTime: time.Date(2024, 6, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
want: "ss",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := GetCurrentSemesterString(tt.args.localeTime); got != tt.want {
|
||||
t.Errorf("GetCurrentSemesterString() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -48,13 +48,6 @@ func Contains(s []string, e string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func ReplaceEmptyString(word string, replacement string) string {
|
||||
if OnlyWhitespace(word) {
|
||||
return replacement
|
||||
}
|
||||
return word
|
||||
}
|
||||
|
||||
func HashString(s string) string {
|
||||
hash := sha256.New()
|
||||
hash.Write([]byte(s))
|
||||
|
@ -17,6 +17,7 @@
|
||||
package functions
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@ -96,3 +97,49 @@ func TestIsSeparator(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestContains(t *testing.T) {
|
||||
type args struct {
|
||||
s []string
|
||||
e string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want bool
|
||||
}{
|
||||
{"empty slice", args{[]string{}, "a"}, false},
|
||||
{"slice with one element equal", args{[]string{"a"}, "a"}, true},
|
||||
{"slice with one element different", args{[]string{"a"}, "b"}, false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := Contains(tt.args.s, tt.args.e); got != tt.want {
|
||||
t.Errorf("Contains() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSeperateRoomString(t *testing.T) {
|
||||
type args struct {
|
||||
rooms string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []string
|
||||
}{
|
||||
{"empty string", args{""}, []string{}},
|
||||
{"one room", args{"a"}, []string{"a"}},
|
||||
{"two rooms", args{"a,b"}, []string{"a", "b"}},
|
||||
{"two rooms with whitespace", args{"a, b"}, []string{"a", "b"}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := SeperateRoomString(tt.args.rooms); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("SeperateRoomString() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1,74 +0,0 @@
|
||||
//Calendar implementation for the HTWK Leipzig timetable. Evaluation and display of the individual dates in iCal format.
|
||||
//Copyright (C) 2024 HTWKalender support@htwkalender.de
|
||||
|
||||
//This program is free software: you can redistribute it and/or modify
|
||||
//it under the terms of the GNU Affero General Public License as published by
|
||||
//the Free Software Foundation, either version 3 of the License, or
|
||||
//(at your option) any later version.
|
||||
|
||||
//This program is distributed in the hope that it will be useful,
|
||||
//but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
//GNU Affero General Public License for more details.
|
||||
|
||||
//You should have received a copy of the GNU Affero General Public License
|
||||
//along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package ical
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase"
|
||||
"htwkalender/model"
|
||||
)
|
||||
|
||||
//update ical feed json
|
||||
//add uuid field
|
||||
//remove module name field
|
||||
|
||||
func MigrateFeedJson(app *pocketbase.PocketBase) error {
|
||||
|
||||
records, err := app.Dao().FindRecordsByFilter("feeds", "1=1", "-created", 0, 0)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, feed := range records {
|
||||
|
||||
var modules []model.FeedCollection
|
||||
|
||||
err := json.Unmarshal([]byte(feed.GetString("modules")), &modules)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var uuidFeedCollections []model.FeedCollection
|
||||
|
||||
for _, module := range modules {
|
||||
uuid := searchUUIDForModule(app, module)
|
||||
|
||||
if uuid != "" {
|
||||
uuidFeedCollections = append(uuidFeedCollections, model.FeedCollection{UUID: uuid, Name: module.Name, Course: module.Course, UserDefinedName: module.UserDefinedName})
|
||||
}
|
||||
}
|
||||
|
||||
jsonModules, _ := json.Marshal(uuidFeedCollections)
|
||||
feed.Set("modules", string(jsonModules))
|
||||
|
||||
err = app.Dao().SaveRecord(feed)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func searchUUIDForModule(app *pocketbase.PocketBase, module model.FeedCollection) string {
|
||||
var event model.Event
|
||||
err := app.Dao().DB().Select("*").From("events").Where(dbx.NewExp("Name = {:name} AND course = {:course}", dbx.Params{"name": module.Name, "course": module.Course})).One(&event)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
return event.UUID
|
||||
}
|
@ -74,6 +74,7 @@ func GetFreeRooms(app *pocketbase.PocketBase, from time.Time, to time.Time) ([]s
|
||||
return freeRooms, nil
|
||||
}
|
||||
|
||||
// Remove all rooms from the list that have events in the given time range
|
||||
func removeRoomsThatHaveEvents(rooms []string, schedule []model.Event) []string {
|
||||
var freeRooms []string
|
||||
for _, room := range rooms {
|
||||
@ -84,6 +85,7 @@ func removeRoomsThatHaveEvents(rooms []string, schedule []model.Event) []string
|
||||
return freeRooms
|
||||
}
|
||||
|
||||
// Check if a room is in the schedule
|
||||
func isRoomInSchedule(room string, schedule []model.Event) bool {
|
||||
for _, event := range schedule {
|
||||
if event.Course != "Sport" {
|
||||
|
@ -191,6 +191,50 @@ func Test_isRoomInSchedule(t *testing.T) {
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "schedule event.Course is sport",
|
||||
args: args{
|
||||
room: "Klettergerüst",
|
||||
schedule: []model.Event{
|
||||
{
|
||||
UUID: "903784265784639527",
|
||||
Day: "Montag",
|
||||
Week: "52",
|
||||
Start: types.DateTime{},
|
||||
End: types.DateTime{},
|
||||
Name: "Hampelmann",
|
||||
EventType: "S",
|
||||
Prof: "Prof. Dr. Bewegung",
|
||||
Rooms: "Klettergerüst",
|
||||
Notes: "A apple a day keeps the doctor away",
|
||||
Course: "Sport",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "schedule event.Course is sport with different room",
|
||||
args: args{
|
||||
room: "HTWK Sportplatz",
|
||||
schedule: []model.Event{
|
||||
{
|
||||
UUID: "903784265784639527",
|
||||
Day: "Montag",
|
||||
Week: "52",
|
||||
Start: types.DateTime{},
|
||||
End: types.DateTime{},
|
||||
Name: "Hampelmann",
|
||||
EventType: "S",
|
||||
Prof: "Prof. Dr. Bewegung",
|
||||
Rooms: "Klettergerüst",
|
||||
Notes: "A apple a day keeps the doctor away",
|
||||
Course: "Sport",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
@ -23,8 +23,8 @@ services:
|
||||
context: ./backend
|
||||
target: dev # prod
|
||||
command: "--http=0.0.0.0:8090 --dir=/htwkalender/data/pb_data"
|
||||
#ports:
|
||||
# - "8090:8090"
|
||||
ports:
|
||||
- "8090:8090"
|
||||
volumes:
|
||||
- pb_data:/htwkalender/data # for production with volume
|
||||
# - ./backend:/htwkalender/data # for development with bind mount from project directory
|
||||
|
Reference in New Issue
Block a user