From a50ee869404ea9a805d79f463b2a583ae2dce49f Mon Sep 17 00:00:00 2001 From: Ivymaster Date: Wed, 8 Jul 2026 15:33:33 +0200 Subject: [PATCH] BUG: fix for failing tests due to ended semester --- public/js/components/Calendar/Base/Grid.js | 5 +- .../Calendar/Base/Grid/Line/Event.js | 1 + .../Calendar/Base/Grid/Line/EventCard.js | 1 + .../Stv/Studentenverwaltung/Verband.js | 2 + .../Renderer/Lehreinheit/calendarEvent.js | 2 +- .../Renderer/Reservierungen/calendarEvent.js | 2 +- system/seeders/001_helper_functions.sql | 10 +- system/seeders/013_studiengang_5.sql | 15 ++- system/seeders/015_kalender.sql | 6 +- tests/cypress/.gitignore | 4 +- .../specs/api/tempus/tempus.collisions.cy.js | 80 ++++--------- .../ui/tempus/tempus.course-picker.cy.js | 12 +- .../e2e/specs/ui/tempus/tempus.events.cy.js | 112 +++--------------- .../e2e/specs/ui/tempus/tempus.filters.cy.js | 2 +- .../e2e/specs/ui/tempus/tempus.roles.cy.js | 9 +- .../e2e/specs/ui/tempus/tempus.smoke.cy.js | 4 +- .../cypress/cypress/support/api/tempusApi.js | 74 ++++++++++++ .../cypress/support/helpers/tempusTestData.js | 35 ++++++ .../cypress/support/pages/tempus.po.js | 74 +++++++++--- 19 files changed, 246 insertions(+), 204 deletions(-) create mode 100644 tests/cypress/cypress/support/helpers/tempusTestData.js diff --git a/public/js/components/Calendar/Base/Grid.js b/public/js/components/Calendar/Base/Grid.js index a670ad4d1..58db5108b 100644 --- a/public/js/components/Calendar/Base/Grid.js +++ b/public/js/components/Calendar/Base/Grid.js @@ -479,6 +479,7 @@ export default { class="fhc-calendar-base-grid" style="display:grid;width:100%;height:100%;overflow:auto" :style="'grid-template-' + axisRow + 's:auto' + (allDayEvents ? ' auto ' : ' ') + '1fr;grid-template-' + axisCol + 's:auto ' + styleGridCols" + data-cy="calendar-base-grid" >
` -} \ No newline at end of file +} diff --git a/public/js/components/Calendar/Base/Grid/Line/Event.js b/public/js/components/Calendar/Base/Grid/Line/Event.js index 6c401a2eb..9b9b40bac 100644 --- a/public/js/components/Calendar/Base/Grid/Line/Event.js +++ b/public/js/components/Calendar/Base/Grid/Line/Event.js @@ -116,6 +116,7 @@ export default { v-draggable:move.noimage="draggable ? dragKalenderCollection : {}" v-cal-click:event="isHeaderOrFooter ? event : event.orig" @contextmenu.prevent="onRightClick" + data-cy="calendar-event" >
{{ event.orig.topic || event.orig.titel || event.orig.lehrfach }} diff --git a/public/js/components/Stv/Studentenverwaltung/Verband.js b/public/js/components/Stv/Studentenverwaltung/Verband.js index 11fdc19d4..20ad01ab6 100644 --- a/public/js/components/Stv/Studentenverwaltung/Verband.js +++ b/public/js/components/Stv/Studentenverwaltung/Verband.js @@ -360,6 +360,7 @@ export default { :title="node.data.studiengang_kz" v-drag-click="() => toggleTreeNode(node)" v-drop:link-strict.student-collection="(evt, students) => dropStudents(node, students)" + data-cy="course-tree-row" > {{ node.data.name }} @@ -368,6 +369,7 @@ export default { :data-tree-item-key="node.key" :title="node.data.studiengang_kz" v-drag-click="() => toggleTreeNode(node)" + data-cy="course-tree-row" > {{ node.data.name }} diff --git a/public/js/components/Tempus/Renderer/Lehreinheit/calendarEvent.js b/public/js/components/Tempus/Renderer/Lehreinheit/calendarEvent.js index da149d5ab..51cd5ba8f 100644 --- a/public/js/components/Tempus/Renderer/Lehreinheit/calendarEvent.js +++ b/public/js/components/Tempus/Renderer/Lehreinheit/calendarEvent.js @@ -81,7 +81,7 @@ export default {
{{ event.topic }} - {{ event.ort_kurzbz }} + {{ event.ort_kurzbz }} ... +{{ event.lektor.length - 3 }} - {{ event.ort_kurzbz }} + {{ event.ort_kurzbz }}
`, diff --git a/system/seeders/001_helper_functions.sql b/system/seeders/001_helper_functions.sql index 4ee526b6b..b1ed6d484 100644 --- a/system/seeders/001_helper_functions.sql +++ b/system/seeders/001_helper_functions.sql @@ -25,4 +25,12 @@ DECLARE res varchar(32); SELECT studiensemester_kurzbz into res FROM public.tbl_studiensemester WHERE start<=now() AND ende>=now() ORDER BY start DESC LIMIT 1; return res; END; -$$ LANGUAGE plpgsql; \ No newline at end of file +$$ LANGUAGE plpgsql; + +CREATE OR REPLACE FUNCTION LastActiveSemester() RETURNS varchar(32) AS $$ +DECLARE res varchar(32); + BEGIN + SELECT studiensemester_kurzbz into res FROM public.tbl_studiensemester WHERE start<=now() ORDER BY start DESC LIMIT 1; + return res; + END; +$$ LANGUAGE plpgsql; diff --git a/system/seeders/013_studiengang_5.sql b/system/seeders/013_studiengang_5.sql index 7503ee2e0..682ff9325 100644 --- a/system/seeders/013_studiengang_5.sql +++ b/system/seeders/013_studiengang_5.sql @@ -122,7 +122,7 @@ INSERT INTO lehre.tbl_studienplan_semester (studienplan_id, studiensemester_kurz INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, anmerkung, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht) -VALUES(51001, 5221, CurrentSemester(), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5221, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5221, 1); +VALUES(51001, 5221, COALESCE(CurrentSemester(), LastActiveSemester()), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5221, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5221, 1); INSERT INTO lehre.tbl_lehreinheitgruppe (lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id) @@ -137,7 +137,7 @@ INSERT INTO lehre.tbl_lehreinheitmitarbeiter VALUES(51001, 'demolektor1', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'oesi', NULL, 0.00, NULL, NULL); INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, anmerkung, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht) -VALUES(51002, 5121, CurrentSemester(), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5121, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5121, 1); +VALUES(51002, 5121, COALESCE(CurrentSemester(), LastActiveSemester()), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5121, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5121, 1); INSERT INTO lehre.tbl_lehreinheitgruppe (lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id) @@ -148,7 +148,7 @@ INSERT INTO lehre.tbl_lehreinheitmitarbeiter VALUES(51002, 'demolektor2', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'oesi', NULL, 0.00, NULL, NULL); INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, anmerkung, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht) -VALUES(51003, 5141, CurrentSemester(), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5141, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5141, 1); +VALUES(51003, 5141, COALESCE(CurrentSemester(), LastActiveSemester()), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5141, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5141, 1); INSERT INTO lehre.tbl_lehreinheitgruppe (lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id) @@ -159,7 +159,7 @@ INSERT INTO lehre.tbl_lehreinheitmitarbeiter VALUES(51003, 'demolektor3', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'oesi', NULL, 0.00, NULL, NULL); INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, anmerkung, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht) -VALUES(51004, 5211, CurrentSemester(), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5211, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5211, 1); +VALUES(51004, 5211, COALESCE(CurrentSemester(), LastActiveSemester()), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5211, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5211, 1); INSERT INTO lehre.tbl_lehreinheitgruppe (lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id) @@ -170,7 +170,7 @@ INSERT INTO lehre.tbl_lehreinheitmitarbeiter VALUES(51004, 'demolektor4', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'oesi', NULL, 0.00, NULL, NULL); INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, anmerkung, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht) -VALUES(51005, 5311, CurrentSemester(), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5311, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5311, 1); +VALUES(51005, 5311, COALESCE(CurrentSemester(), LastActiveSemester()), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5311, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5311, 1); INSERT INTO lehre.tbl_lehreinheitgruppe (lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id) @@ -181,7 +181,7 @@ INSERT INTO lehre.tbl_lehreinheitmitarbeiter VALUES(51005, 'demolektor4', 'Lektor', 0, NULL, 1.00, NULL, true, NULL, NULL, '2023-08-24 14:58:40.000', 'oesi', NULL, 0.00, NULL, NULL); INSERT INTO lehre.tbl_lehreinheit (lehreinheit_id, lehrveranstaltung_id, studiensemester_kurzbz, lehrfach_id_old, lehrform_kurzbz, stundenblockung, wochenrythmus, start_kw, raumtyp, raumtypalternativ, sprache, lehre, anmerkung, unr, lvnr, updateamum, updatevon, insertamum, insertvon, ext_id, lehrfach_id, gewicht) -VALUES(51006, 5321, CurrentSemester(), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5321, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5321, 1); +VALUES(51006, 5321, COALESCE(CurrentSemester(), LastActiveSemester()), NULL, 'VO', 2, 1, NULL, 'Dummy', 'Dummy', 'German', true, NULL, 5321, NULL, '2023-08-24 14:54:43.000', 'oesi', '2023-08-24 14:54:43.000', 'oesi', NULL, 5321, 1); INSERT INTO lehre.tbl_lehreinheitgruppe (lehreinheit_id, studiengang_kz, semester, verband, gruppe, gruppe_kurzbz, updateamum, updatevon, insertamum, insertvon, ext_id) @@ -210,7 +210,7 @@ VALUES(510021, 31002, 31002, 5, 1, 'B', '', NULL, 'demolektor1', 'EG04', '2025-0 INSERT INTO public.tbl_studentlehrverband (student_uid, studiensemester_kurzbz, studiengang_kz, semester, verband, gruppe, updateamum, updatevon, insertamum, insertvon, ext_id) -VALUES('s125b101', 'SS2026', 5, 2, ' ', ' ', NULL, NULL, '2026-06-11 14:33:58.403', 'auto', NULL); +VALUES('s125b101', LastActiveSemester(), 5, 2, ' ', ' ', NULL, NULL, '2026-06-11 14:33:58.403', 'auto', NULL); INSERT INTO public.tbl_gruppe (gruppe_kurzbz, studiengang_kz, semester, bezeichnung, beschreibung, sichtbar, lehre, aktiv, sort, mailgrp, generiert, updateamum, updatevon, insertamum, insertvon, ext_id, orgform_kurzbz, content_visible, gesperrt, direktinskription, zutrittssystem, aufnahmegruppe) VALUES ('GRP_51003', 5, 2, 'BS5 2 ENG', null, false, false, true, NULL, false, false, now(), 'demoadmin', now(), 'demoadmin', NULL, NULL, true, false, true, false, false), @@ -229,4 +229,3 @@ INSERT INTO public.tbl_benutzergruppe (uid, gruppe_kurzbz, updateamum, updatevon ('s125b101', 'GRP_51003', now(), 'demoadmin', now(), 'demoadmin', NULL, NULL), ('s125b101', 'GRP_51004', now(), 'demoadmin', now(), 'demoadmin', NULL, NULL) ; - \ No newline at end of file diff --git a/system/seeders/015_kalender.sql b/system/seeders/015_kalender.sql index 0a525bd59..345e003a3 100644 --- a/system/seeders/015_kalender.sql +++ b/system/seeders/015_kalender.sql @@ -177,9 +177,9 @@ VALUES (51006, 31), (51004, 32); -INSERT INTO public.tbl_variablenname -(name, defaultwert) -VALUES('ignore_resources_collisions', 'false'); +-- INSERT INTO public.tbl_variablenname +-- (name, defaultwert) +-- VALUES('ignore_resources_collisions', 'false'); INSERT INTO public.tbl_variable (name, uid, wert) diff --git a/tests/cypress/.gitignore b/tests/cypress/.gitignore index 48e0213b8..a685d5fcd 100644 --- a/tests/cypress/.gitignore +++ b/tests/cypress/.gitignore @@ -1,4 +1,6 @@ node_modules .env .env.* -!.env.example \ No newline at end of file +!.env.example +/cypress/screenshots +/cypress/videos \ No newline at end of file diff --git a/tests/cypress/cypress/e2e/specs/api/tempus/tempus.collisions.cy.js b/tests/cypress/cypress/e2e/specs/api/tempus/tempus.collisions.cy.js index ae00b672c..bc997a90a 100644 --- a/tests/cypress/cypress/e2e/specs/api/tempus/tempus.collisions.cy.js +++ b/tests/cypress/cypress/e2e/specs/api/tempus/tempus.collisions.cy.js @@ -1,68 +1,34 @@ import { tempusApi } from "../../../../support/api/tempusApi"; import { getDateForDay } from "../../../../support/helpers/date"; +import { + getTempusTestSemester, + TEMPUS_TEST_STUDY_PLAN_SHORT_CODE, +} from "../../../../support/helpers/tempusTestData"; -const TARGETED_STUDY_PLAN_SHORT_CODE = "STG5"; - -const resetEventsBeforeTest = () => { - tempusApi - .getPlannerEvents(getDateForDay("monday"), getDateForDay("monday")) - .then((events) => { - events.forEach((event) => { - tempusApi.deleteKalenderEvent(event.kalender_id); - }); - }); - tempusApi - .getPlannerEvents(getDateForDay("tuesday"), getDateForDay("tuesday")) - .then((events) => { - events.forEach((event) => { - if ( - event.type === "lehreinheit" && - event.beginn === "20:15:00" && - event.ende === "21:00:00" - ) { - tempusApi.updateKalenderEvent( - event.kalender_id, - `${event.datum} 19:30`, - `${event.datum} 20:15`, - ); - } - }); - }); - tempusApi - .getPlannerEvents(getDateForDay("sunday"), getDateForDay("sunday")) - .then((events) => { - events.forEach((event) => { - if ( - event.type === "lehreinheit" && - event.beginn === "18:35:00" && - event.ende === "19:20:00" && - event.lektor.some((lector) => lector.kurzbz === "DemoLKT1") - ) { - tempusApi.updateKalenderEvent( - event.kalender_id, - `${event.datum} 17:50`, - `${event.datum} 18:35`, - ); - } - }); - }); -}; +let TEMPUS_TEST_SEMESTER; describe("Tempus Kalender API", () => { + before(() => { + cy.login(); + getTempusTestSemester().then((semester) => { + TEMPUS_TEST_SEMESTER = semester; + }); + }); + beforeEach(() => { cy.login(); - resetEventsBeforeTest(); + tempusApi.resetTempusScenario(); }); it("event creation works for non collision case", () => { tempusApi.getStudyPlansTree().then((stgTree) => { let studyPlan = stgTree.find((plan) => - plan.name.includes(TARGETED_STUDY_PLAN_SHORT_CODE), + plan.name.includes(TEMPUS_TEST_STUDY_PLAN_SHORT_CODE), ); expect(studyPlan, "study plan for test event creation").to.exist; tempusApi - .getCoursesByStudyPlan(studyPlan.studiengang_kz, "SS2026") + .getCoursesByStudyPlan(studyPlan.studiengang_kz, TEMPUS_TEST_SEMESTER) .then((courses) => { let course = courses.find((course) => course.lehrfach === "MAT"); expect(course, "course for test event creation").to.exist; @@ -94,12 +60,12 @@ describe("Tempus Kalender API", () => { it("prohibited event creation due to zeitsperre collision", () => { tempusApi.getStudyPlansTree().then((stgTree) => { let studyPlan = stgTree.find((plan) => - plan.name.includes(TARGETED_STUDY_PLAN_SHORT_CODE), + plan.name.includes(TEMPUS_TEST_STUDY_PLAN_SHORT_CODE), ); expect(studyPlan, "study plan for test event creation").to.exist; tempusApi - .getCoursesByStudyPlan(studyPlan.studiengang_kz, "SS2026") + .getCoursesByStudyPlan(studyPlan.studiengang_kz, TEMPUS_TEST_SEMESTER) .then((courses) => { let course = courses.find((course) => course.lektoren.some((lector) => lector.kurzbz === "DemoLKT1"), @@ -142,12 +108,12 @@ describe("Tempus Kalender API", () => { it("prohibited event creation due to student group collision", () => { tempusApi.getStudyPlansTree().then((stgTree) => { let studyPlan = stgTree.find((plan) => - plan.name.includes(TARGETED_STUDY_PLAN_SHORT_CODE), + plan.name.includes(TEMPUS_TEST_STUDY_PLAN_SHORT_CODE), ); expect(studyPlan, "study plan for test event creation").to.exist; tempusApi - .getCoursesByStudyPlan(studyPlan.studiengang_kz, "SS2026") + .getCoursesByStudyPlan(studyPlan.studiengang_kz, TEMPUS_TEST_SEMESTER) .then((courses) => { let course = courses.find( (course) => @@ -194,12 +160,12 @@ describe("Tempus Kalender API", () => { tempusApi.getStudyPlansTree().then((stgTree) => { let studyPlan = stgTree.find((plan) => - plan.name.includes(TARGETED_STUDY_PLAN_SHORT_CODE), + plan.name.includes(TEMPUS_TEST_STUDY_PLAN_SHORT_CODE), ); expect(studyPlan, "study plan for test event creation").to.exist; tempusApi - .getCoursesByStudyPlan(studyPlan.studiengang_kz, "SS2026") + .getCoursesByStudyPlan(studyPlan.studiengang_kz, TEMPUS_TEST_SEMESTER) .then((courses) => { let course = courses.find( (course) => @@ -252,12 +218,12 @@ describe("Tempus Kalender API", () => { it("prohibited event creation due to lector collision", () => { tempusApi.getStudyPlansTree().then((stgTree) => { let studyPlan = stgTree.find((plan) => - plan.name.includes(TARGETED_STUDY_PLAN_SHORT_CODE), + plan.name.includes(TEMPUS_TEST_STUDY_PLAN_SHORT_CODE), ); expect(studyPlan, "study plan for test event creation").to.exist; tempusApi - .getCoursesByStudyPlan(studyPlan.studiengang_kz, "SS2026") + .getCoursesByStudyPlan(studyPlan.studiengang_kz, TEMPUS_TEST_SEMESTER) .then((courses) => { let course = courses.find((course) => course.lektoren.some((lector) => lector.kurzbz === "DemoLKT4"), diff --git a/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.course-picker.cy.js b/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.course-picker.cy.js index 7d967d1a0..1d5764976 100644 --- a/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.course-picker.cy.js +++ b/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.course-picker.cy.js @@ -1,19 +1,9 @@ import { waitForOk } from "../../../../support/helpers/network"; -import { getDateForDay } from "../../../../support/helpers/date"; import { tempusPage } from "../../../../support/pages/tempus.po"; import { tempusApi } from "../../../../support/api/tempusApi"; const TARGETED_STUDY_PLAN_SHORT_CODE = "STG5"; -const deleteMondayEvents = () => - tempusApi - .getPlannerEvents(getDateForDay("monday"), getDateForDay("monday")) - .then((events) => { - events.forEach((event) => { - tempusApi.deleteKalenderEvent(event.kalender_id); - }); - }); - context("Tempus course picker tests", () => { before(() => { tempusPage.visitAndWaitForPlanner(); @@ -61,7 +51,7 @@ context("Tempus course picker tests", () => { }); it("can drag and drop one course event into the calendar", () => { - deleteMondayEvents(); + tempusApi.deletePlannerEventsForDay("monday"); tempusPage.getCalendarSection().should("exist"); tempusPage.waitForCalendarToFinishLoading(); diff --git a/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.events.cy.js b/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.events.cy.js index cae3fe3df..1ee24af16 100644 --- a/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.events.cy.js +++ b/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.events.cy.js @@ -1,5 +1,4 @@ import { waitForOk } from "../../../../support/helpers/network"; -import { getDateForDay } from "../../../../support/helpers/date"; import { tempusApi } from "../../../../support/api/tempusApi"; import { LEKTOR, @@ -13,13 +12,7 @@ context("Tempus event mutation tests", () => { beforeEach(() => { tempusPage.visitAndWaitForPlanner(); - tempusApi - .getPlannerEvents(getDateForDay("monday"), getDateForDay("monday")) - .then((events) => { - events.forEach((event) => { - tempusApi.deleteKalenderEvent(event.kalender_id); - }); - }); + tempusApi.deletePlannerEventsForDay("monday"); }); it("room change on planner preview updates planner event, but keeps original room on other previews", () => { @@ -51,52 +44,16 @@ context("Tempus event mutation tests", () => { tempusPage.expectCalendarEventRoom(eventId, originalRoom); - tempusPage - .getCalendarEventById(eventId) - .should("be.visible") - .rightclick(); - tempusPage.getEventContextMenuOption("Raumauswahl").click({ force: true }); - waitForOk("@fetchRoomSuggestions"); + tempusPage.changeEventRoom(eventId, originalRoom).then((result) => { + const { newRoom, updatedEventId } = result; - tempusPage - .getRaumauswahlRoomOptions() - .should("have.length.greaterThan", 0) - .then(($roomOptions) => { - const roomOption = [...$roomOptions].find((option) => { - const room = option.innerText.trim(); + tempusPage.expectCalendarEventRoom(updatedEventId, newRoom); - return room && room !== originalRoom; - }); + tempusPage.selectRoleAndWait(LEKTOR); + tempusPage.expectCalendarEventRoom(eventId, originalRoom); - expect(roomOption, "different room suggestion").to.exist; - - cy.wrap(roomOption.innerText.trim()).as("newRoom"); - cy.wrap(roomOption).click(); - }); - - cy.wait("@updateCalendarEvent").then((interception) => { - expect(interception.response.statusCode).to.eq(200); - - const updatedEventId = tempusPage.getUpdatedKalenderId(interception); - expect(updatedEventId, "updated planner event id").to.exist; - - cy.wrap(updatedEventId).as("updatedEventId"); - }); - waitForOk("@fetchPlanData"); - tempusPage.waitForCalendarToFinishLoading(); - - cy.get("@newRoom").then((newRoom) => { - console.log(eventId) - console.log(newRoom) - cy.get("@updatedEventId").then((updatedEventId) => { - tempusPage.expectCalendarEventRoom(updatedEventId, newRoom); - - tempusPage.selectRoleAndWait(LEKTOR); - tempusPage.expectCalendarEventRoom(eventId, originalRoom); - - tempusPage.selectRoleAndWait(STUDENT); - tempusPage.expectCalendarEventRoom(eventId, originalRoom); - }); + tempusPage.selectRoleAndWait(STUDENT); + tempusPage.expectCalendarEventRoom(eventId, originalRoom); }); }); }); @@ -128,54 +85,19 @@ context("Tempus event mutation tests", () => { expect(originalRoom, "original event room").to.be.a("string").and.not.be .empty; - tempusPage - .getCalendarEventById(eventId) - .scrollIntoView() - .should("be.visible") - .rightclick(); - tempusPage.getEventContextMenuOption("Raumauswahl").click({ force: true }); - waitForOk("@fetchRoomSuggestions"); + tempusPage.changeEventRoom(eventId, originalRoom).then((result) => { + const { newRoom, updatedEventId } = result; - tempusPage - .getRaumauswahlRoomOptions() - .should("have.length.greaterThan", 0) - .then(($roomOptions) => { - const roomOption = [...$roomOptions].find((option) => { - const room = option.innerText.trim(); + tempusPage.expectCalendarEventRoom(updatedEventId, newRoom); - return room && room !== originalRoom; - }); + tempusPage.syncAndReloadPlanner(); + tempusPage.expectCalendarEventRoom(updatedEventId, newRoom); - expect(roomOption, "different room suggestion").to.exist; + tempusPage.selectRoleAndWait(LEKTOR); + tempusPage.expectCalendarEventRoom(updatedEventId, newRoom); - cy.wrap(roomOption.innerText.trim()).as("newRoom"); - cy.wrap(roomOption).click(); - }); - - cy.wait("@updateCalendarEvent").then((interception) => { - expect(interception.response.statusCode).to.eq(200); - - const updatedEventId = tempusPage.getUpdatedKalenderId(interception); - expect(updatedEventId, "updated planner event id").to.exist; - - cy.wrap(updatedEventId).as("updatedEventId"); - }); - waitForOk("@fetchPlanData"); - tempusPage.waitForCalendarToFinishLoading(); - - cy.get("@newRoom").then((newRoom) => { - cy.get("@updatedEventId").then((updatedEventId) => { - tempusPage.expectCalendarEventRoom(updatedEventId, newRoom); - - tempusPage.syncAndReloadPlanner(); - tempusPage.expectCalendarEventRoom(updatedEventId, newRoom); - - tempusPage.selectRoleAndWait(LEKTOR); - tempusPage.expectCalendarEventRoom(updatedEventId, newRoom); - - tempusPage.selectRoleAndWait(STUDENT); - tempusPage.expectCalendarEventRoom(updatedEventId, newRoom); - }); + tempusPage.selectRoleAndWait(STUDENT); + tempusPage.expectCalendarEventRoom(updatedEventId, newRoom); }); }); }); diff --git a/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.filters.cy.js b/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.filters.cy.js index a6f0c0c3a..e13f793c5 100644 --- a/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.filters.cy.js +++ b/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.filters.cy.js @@ -45,7 +45,7 @@ context("Tempus filter tests", () => { selectedRoom, ); cy.wrap($event) - .find(".event-place") + .find("[data-cy='calendar-event-room']") .invoke("text") .then((eventPlace) => { expect(eventPlace.trim(), "event body room").to.eq(selectedRoom); diff --git a/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.roles.cy.js b/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.roles.cy.js index fb4d0d943..6783467d3 100644 --- a/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.roles.cy.js +++ b/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.roles.cy.js @@ -1,5 +1,4 @@ import { waitForOk } from "../../../../support/helpers/network"; -import { getDateForDay } from "../../../../support/helpers/date"; import { tempusApi } from "../../../../support/api/tempusApi"; import { LEKTOR, @@ -12,13 +11,7 @@ context("Tempus role preview tests", () => { beforeEach(() => { tempusPage.visitAndWaitForPlanner(); - tempusApi - .getPlannerEvents(getDateForDay("monday"), getDateForDay("monday")) - .then((events) => { - events.forEach((event) => { - tempusApi.deleteKalenderEvent(event.kalender_id); - }); - }); + tempusApi.deletePlannerEventsForDay("monday"); }); it("shows the same number of calendar events for all role previews", () => { diff --git a/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.smoke.cy.js b/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.smoke.cy.js index 4da45a1d1..454c8686a 100644 --- a/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.smoke.cy.js +++ b/tests/cypress/cypress/e2e/specs/ui/tempus/tempus.smoke.cy.js @@ -44,7 +44,7 @@ context("Tempus smoke tests", () => { tempusPage.getEventContextMenu().should("be.visible"); }); - it("shows Raumauswahl modal when selecting Raumauswahl from event context menu", () => { + it("shows room selection modal when selecting 'room selection' from event context menu", () => { tempusPage.waitForCalendarToFinishLoading(); tempusPage .getCalendarEventsWithLehreinheit() @@ -54,7 +54,7 @@ context("Tempus smoke tests", () => { tempusPage.getEventContextMenuOption("Raumauswahl").click({ force: true }); waitForOk("@fetchRoomSuggestions"); - tempusPage.getRaumauswahlModal().should("be.visible"); + tempusPage.getRoomSelectionModal().should("be.visible"); }); it("shows resources modal when selecting Ressourcen zuordnen from event context menu", () => { diff --git a/tests/cypress/cypress/support/api/tempusApi.js b/tests/cypress/cypress/support/api/tempusApi.js index 8ef542303..ea252d098 100644 --- a/tests/cypress/cypress/support/api/tempusApi.js +++ b/tests/cypress/cypress/support/api/tempusApi.js @@ -1,5 +1,25 @@ +import { getDateForDay } from "../helpers/date"; + const KALENDER_API = "/index.ci.php/api/frontend/v1/tempus"; +const updatePlannerEventsForDay = (day, predicate, startTime, endTime) => { + const date = getDateForDay(day); + + return tempusApi.getPlannerEvents(date, date).then((events) => + cy.wrap(events).each((event) => { + if (!predicate(event)) { + return null; + } + + return tempusApi.updateKalenderEvent( + event.kalender_id, + `${event.datum} ${startTime}`, + `${event.datum} ${endTime}`, + ); + }), + ); +}; + export const tempusApi = { getStudyPlansTree: () => cy @@ -15,6 +35,23 @@ export const tempusApi = { return response.body.data; }), + getStudySemesters: () => + cy + .request({ + method: "GET", + url: `/index.ci.php/api/frontend/v1/organisation/Studiensemester/getAll`, + qs: { + order: "DESC", + }, + }) + .then((response) => { + expect(response.status).to.eq(200); + expect(response.body).to.have.nested.property("meta.status", "success"); + expect(response.body.data).to.be.an("array"); + + return response.body.data; + }), + getCoursesByStudyPlan: (studyPlanId, semesterShortCode) => cy .request({ @@ -51,6 +88,43 @@ export const tempusApi = { return response.body.data; }), + deletePlannerEventsForDay: (day) => { + const date = getDateForDay(day); + + return tempusApi.getPlannerEvents(date, date).then((events) => + cy.wrap(events).each((event) => + tempusApi.deleteKalenderEvent(event.kalender_id), + ), + ); + }, + + resetTempusScenario: () => + tempusApi + .deletePlannerEventsForDay("monday") + .then(() => + updatePlannerEventsForDay( + "tuesday", + (event) => + event.type === "lehreinheit" && + event.beginn === "20:15:00" && + event.ende === "21:00:00", + "19:30", + "20:15", + ), + ) + .then(() => + updatePlannerEventsForDay( + "sunday", + (event) => + event.type === "lehreinheit" && + event.beginn === "18:35:00" && + event.ende === "19:20:00" && + event.lektor?.some((lector) => lector.kurzbz === "DemoLKT1"), + "17:50", + "18:35", + ), + ), + createKalenderEvent: (lehreinheitId, startDateTime, endDateTime) => cy.request({ method: "POST", diff --git a/tests/cypress/cypress/support/helpers/tempusTestData.js b/tests/cypress/cypress/support/helpers/tempusTestData.js new file mode 100644 index 000000000..a43eee4ce --- /dev/null +++ b/tests/cypress/cypress/support/helpers/tempusTestData.js @@ -0,0 +1,35 @@ +import { tempusApi } from "../api/tempusApi"; + +export const TEMPUS_TEST_STUDY_PLAN_SHORT_CODE = "STG5"; + +const getLocalDateString = () => { + const today = new Date(); + const year = today.getFullYear(); + const month = String(today.getMonth() + 1).padStart(2, "0"); + const day = String(today.getDate()).padStart(2, "0"); + + return `${year}-${month}-${day}`; +}; + +const getSemesterStartDate = (semester) => semester.start?.slice(0, 10); + +export const getTempusTestSemester = () => + tempusApi.getStudySemesters().then((semesters) => { + const today = getLocalDateString(); + const activeSemester = semesters + .filter((semester) => { + const startDate = getSemesterStartDate(semester); + + return startDate && startDate <= today; + }) + .sort((a, b) => + getSemesterStartDate(b).localeCompare(getSemesterStartDate(a)), + )[0]; + + expect( + activeSemester, + `Tempus test semester starting on or before ${today}`, + ).to.exist; + + return activeSemester.studiensemester_kurzbz; + }); diff --git a/tests/cypress/cypress/support/pages/tempus.po.js b/tests/cypress/cypress/support/pages/tempus.po.js index bc01d0acd..458899508 100644 --- a/tests/cypress/cypress/support/pages/tempus.po.js +++ b/tests/cypress/cypress/support/pages/tempus.po.js @@ -22,7 +22,7 @@ const roleFetchAliases = { class TempusPage { selectors = { - calendarBaseGrid: "div[data-cy='tempus'] .fhc-calendar-base-grid", + calendarBaseGrid: "div[data-cy='tempus'] [data-cy='calendar-base-grid']", parkingSlot: "div[data-cy='tempus'] #parkingslot", }; @@ -108,22 +108,26 @@ class TempusPage { getCalendarSection = () => this.getTempusOverview().find(".fhc-calendar-base"); getCalendarBaseGrid = () => - this.getCalendarSection().find(".fhc-calendar-base-grid"); + this.getCalendarSection().find("[data-cy='calendar-base-grid']"); getCoursePicker = () => this.getTempusOverview().find(".course-picker"); getPreviewRoleOptionsHolder = () => this.getTempusOverview().find("[data-cy='previewRoleOptionsHolder']"); getAllCoursesSliderBtn = () => this.getSidebarMenu().find("button[title='Verband']").first(); getCourseTreeRows = () => - this.getSlideInCoursesMenu().find(".p-treetable-tbody tr"); + this.getSlideInCoursesMenu() + .find("[data-cy='course-tree-row']") + .closest("[role='row']"); + getCourseTreeRowByName = (courseShortName) => + this.getSlideInCoursesMenu() + .contains("[data-cy='course-tree-row']", courseShortName) + .closest("[role='row']"); getCoursePickerRows = () => this.getCoursePicker().find(".course-picker-row"); getCoursePickerSearchInput = () => this.getCoursePicker().find("input"); getCalendarEventsPerWeekHolders = () => this.getCalendarBaseGrid().find(".fhc-calendar-base-grid-line"); getCalendarEvents = () => - this.getCalendarSection().then(($calendar) => { - return $calendar.find(".fhc-calendar-base-grid-line-event"); - }); + this.getCalendarSection().find("[data-cy='calendar-event']"); getLecturerWishOverlays = () => this.getCalendarSection().find(".bg-lecturer-wish"); getCalendarEventsWithRoom = () => @@ -195,7 +199,7 @@ class TempusPage { getCalendarEventById = (id) => this.getCalendarEvents().filter(`div[data-id="event-${id}"]`); getCalendarPartDropTarget = (partIndex) => - `${this.selectors.calendarBaseGrid} .part-body:nth-of-type(${partIndex})`; + `${this.selectors.calendarBaseGrid} [data-cy='calendar-grid-part'][data-drop-index='${partIndex}']`; getEventGridRowFromStyle = (style) => /grid-row:\s*([^;]+)/.exec(style)?.[1]?.trim(); getEventGridRow = (id) => @@ -205,7 +209,7 @@ class TempusPage { getCalendarEventsByWeekday = (weekday) => this.getCalendarEventsPerWeekHolders() .eq(weekdayToGridRowMap[weekday] - 1) - .find(".fhc-calendar-base-grid-line-event"); + .find("[data-cy='calendar-event']"); getCalendarEventsByStartTime = (startTime) => this.getCalendarEvents().filter((index, event) => { const eventData = JSON.parse( @@ -262,12 +266,54 @@ class TempusPage { return retval?.kalender_id ?? retval; }; + chooseDifferentRoomForEvent = (eventId, originalRoom) => { + this.getCalendarEventById(eventId) + .scrollIntoView() + .should("be.visible") + .rightclick(); + this.getEventContextMenuOption("Raumauswahl").click({ force: true }); + waitForOk("@fetchRoomSuggestions"); + + return this.getRaumauswahlRoomOptions() + .should("have.length.greaterThan", 0) + .then(($roomOptions) => { + const roomOption = [...$roomOptions].find((option) => { + const room = option.innerText.trim(); + + return room && room !== originalRoom; + }); + + expect(roomOption, "different room suggestion").to.exist; + + const newRoom = roomOption.innerText.trim(); + + return cy.wrap(roomOption).click().then(() => newRoom); + }); + }; + waitForUpdatedEventId = () => + cy.wait("@updateCalendarEvent").then((interception) => { + expect(interception.response.statusCode).to.eq(200); + + const updatedEventId = this.getUpdatedKalenderId(interception); + expect(updatedEventId, "updated planner event id").to.exist; + + return updatedEventId; + }); + changeEventRoom = (eventId, originalRoom) => + this.chooseDifferentRoomForEvent(eventId, originalRoom).then((newRoom) => + this.waitForUpdatedEventId().then((updatedEventId) => { + waitForOk("@fetchPlanData"); + this.waitForCalendarToFinishLoading(); + + return cy.wrap({ newRoom, updatedEventId }); + }), + ); getMondayFirstColumnEventData = ($body) => [ ...$body .find(`${this.selectors.calendarBaseGrid} .fhc-calendar-base-grid-line`) .first() - .find(".fhc-calendar-base-grid-line-event"), + .find("[data-cy='calendar-event']"), ] .map((event) => { const eventJSON = event.getAttribute("data-fhc-draggable-value"); @@ -286,18 +332,18 @@ class TempusPage { getEventContextMenu = () => cy.get("[data-cy='eventContextMenu']"); getEventContextMenuOption = (option) => this.getEventContextMenu().contains("button", option); - getRaumauswahlModal = () => + getRoomSelectionModal = () => cy .contains(".bootstrap-modal.show .modal-title", "Raumauswahl") .closest(".bootstrap-modal.show"); getRaumauswahlRoomOptions = () => - this.getRaumauswahlModal().find(".list-group-item span"); + this.getRoomSelectionModal().find(".list-group-item span"); getResourcesModal = () => cy .get("[data-cy='resourcesAssignmentModal']") .closest(".bootstrap-modal.show"); getCalendarEventRoom = (id) => - this.getCalendarEventById(id).find(".event-place"); + this.getCalendarEventById(id).find("[data-cy='calendar-event-room']"); getStundenrasterToggle = () => cy.contains(".form-check-label", "Stundenraster").parent(); getHistoryModal = () => cy.get("[data-cy='historyModal']"); @@ -305,7 +351,7 @@ class TempusPage { getReservationModal = () => cy.get("[data-cy='reservationModal']"); getEventParkingSlot = () => this.getSidebarMenu().find("#parkingslot"); getParkedEvents = () => - this.getEventParkingSlot().find(".fhc-calendar-base-grid-line-event"); + this.getEventParkingSlot().find("[data-cy='calendar-event']"); getPreviewRoleButton = (role) => this.getPreviewRoleOptionsHolder().contains("button", role); @@ -324,7 +370,7 @@ class TempusPage { selectCourseByName = (courseShortName) => { this.openCoursesMenu(); - this.getCourseTreeRows().contains(courseShortName).click(); + this.getCourseTreeRowByName(courseShortName).click(); }; selectPreviewRole = (role) => {