mirror of
https://github.com/FH-Complete/FHC-Core.git
synced 2026-07-21 08:52:21 +00:00
WIP: Tempus e2e tests
This commit is contained in:
@@ -208,7 +208,7 @@ class Kalender extends FHCAPI_Controller
|
||||
if (isError($result))
|
||||
$this->terminateWithError(getError($result));
|
||||
|
||||
$this->terminateWithSuccess('Erfolgreich');
|
||||
$this->terminateWithSuccess(getData($result));
|
||||
}
|
||||
|
||||
public function getRaumvorschlag()
|
||||
|
||||
@@ -630,7 +630,7 @@ class KalenderLib
|
||||
if (isError($result)) return $result;
|
||||
}
|
||||
|
||||
return success('Erfolgreich');
|
||||
return success($result);
|
||||
}
|
||||
|
||||
public function updateZeit($kalender_id, $start_date, $end_date)
|
||||
|
||||
@@ -6,8 +6,12 @@ module.exports = defineConfig({
|
||||
|
||||
e2e: {
|
||||
baseUrl: process.env.BASE_URL || "http://localhost:8080",
|
||||
defaultCommandTimeout: 40000,
|
||||
pageLoadTimeout: 20000,
|
||||
defaultCommandTimeout: 20000,
|
||||
pageLoadTimeout: 10000,
|
||||
retries: {
|
||||
runMode: 2, // when running via CLI / CI
|
||||
openMode: 2 // when running in interactive mode
|
||||
}
|
||||
},
|
||||
env: {
|
||||
adminusername: process.env.USER_NAME || "2",
|
||||
|
||||
@@ -1,148 +0,0 @@
|
||||
import { tempusPage } from "../../../support/pages/tempus.po";
|
||||
|
||||
context("Base tempus tests", () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
|
||||
cy.intercept({ method: "GET", url: "**/StgTree" }).as("fetchCourseTree");
|
||||
cy.intercept({ method: "GET", url: /\/tempus\/Kalender\/getPlan(?:\?|$)/ }).as("fetchPlanData");
|
||||
cy.intercept({ method: "GET", url: /\/tempus\/Kalender\/getPlanLecturer(?:\?|$)/ }).as("fetchLecturerPlanData");
|
||||
cy.intercept({ method: "GET", url: /\/tempus\/Kalender\/getPlanStudent(?:\?|$)/ }).as("fetchStudentPlanData");
|
||||
cy.intercept({ method: "GET", url: "**/tempus/Kalender/getHistory**" }).as("fetchEventHistory");
|
||||
cy.intercept({ method: "GET", url: "**/tempus/coursepicker/getByStg**" }).as("fetchCoursePickerCourses");
|
||||
|
||||
tempusPage.visit();
|
||||
|
||||
cy.wait("@fetchCourseTree").its("response.statusCode").should("eq", 200);
|
||||
cy.wait("@fetchPlanData").its("response.statusCode").should("eq", 200);
|
||||
});
|
||||
|
||||
it("can access Tempus page with valid credentials", () => {
|
||||
tempusPage.getTempusOverview().should("be.visible");
|
||||
});
|
||||
|
||||
it ("shows all expected page elements", () => {
|
||||
tempusPage.getTempusOverview().should("be.visible");
|
||||
tempusPage.getSidebarMenu().should("exist");
|
||||
tempusPage.getSlideInCoursesMenu().should("exist");
|
||||
tempusPage.getCalendarSection().should("be.visible");
|
||||
tempusPage.getPreviewRoleOptionsHolder().should("be.visible");
|
||||
});
|
||||
|
||||
it("can open courses menu", () => {
|
||||
tempusPage.getSlideInCoursesMenu().should("exist").should("be.hidden");
|
||||
|
||||
tempusPage.openCoursesMenu();
|
||||
|
||||
tempusPage.getCourseTreeRows().should("have.length.greaterThan", 0);
|
||||
});
|
||||
|
||||
it("can select one course and show preview of its events", () => {
|
||||
tempusPage.getSlideInCoursesMenu().should("exist");
|
||||
tempusPage.getCourseTreeRows().should("have.length.greaterThan", 0);
|
||||
tempusPage.getCoursePicker().should("exist");
|
||||
tempusPage.getCoursePickerRows().should("have.length", 0);
|
||||
|
||||
tempusPage.selectFirstCourse();
|
||||
cy.wait("@fetchCoursePickerCourses").its("response.statusCode").should("eq", 200);
|
||||
|
||||
tempusPage.getCoursePickerRows().should("have.length.greaterThan", 0);
|
||||
});
|
||||
|
||||
it("can search for a course event in the course picker", () => {
|
||||
const searchTerm = "PHY1 SO";
|
||||
|
||||
tempusPage.selectFirstCourse();
|
||||
cy.wait("@fetchCoursePickerCourses").its("response.statusCode").should("eq", 200);
|
||||
|
||||
tempusPage.getCoursePickerRows().should("have.length.greaterThan", 0);
|
||||
|
||||
tempusPage.getCoursePickerSearchInput().type(searchTerm);
|
||||
|
||||
tempusPage.getCoursePickerRows().should("have.length.greaterThan", 0);
|
||||
tempusPage.getCoursePickerRows().first().should("contain.text", searchTerm);
|
||||
});
|
||||
|
||||
it("can drag and drop one course event into the calendar", () => {
|
||||
tempusPage.getCalendarSection().should("exist");
|
||||
|
||||
tempusPage.selectFirstCourse();
|
||||
cy.wait("@fetchCoursePickerCourses").its("response.statusCode").should("eq", 200);
|
||||
|
||||
tempusPage.getCoursePickerRows().first().drag(tempusPage.selectors.calendarSection);
|
||||
|
||||
tempusPage.getCalendarEvents().should("have.length", 1);
|
||||
});
|
||||
|
||||
it("shows the same number of calendar events for all role previews", () => {
|
||||
const rolePreviews = [
|
||||
{ label: "Planer", fetchAlias: "@fetchPlanData" },
|
||||
{ label: "Lektor", fetchAlias: "@fetchLecturerPlanData" },
|
||||
{ label: "Student", fetchAlias: "@fetchStudentPlanData" },
|
||||
];
|
||||
const eventCounts = {};
|
||||
|
||||
cy.wrap(rolePreviews).each((rolePreview) => {
|
||||
tempusPage.selectPreviewRole(rolePreview.label);
|
||||
cy.wait(rolePreview.fetchAlias).its("response.statusCode").should("eq", 200);
|
||||
tempusPage.waitForCalendarToFinishLoading();
|
||||
|
||||
tempusPage.getCalendarEvents().then(($events) => {
|
||||
eventCounts[rolePreview.label] = $events.length;
|
||||
});
|
||||
}).then(() => {
|
||||
const expectedCount = eventCounts[rolePreviews[0].label];
|
||||
|
||||
Object.entries(eventCounts).forEach(([role, count]) => {
|
||||
expect(count, `${role} calendar event count`).to.eq(expectedCount);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("shows event details modal when clicking a calendar event", () => {
|
||||
tempusPage.waitForCalendarToFinishLoading();
|
||||
tempusPage.getCalendarEvents().should("have.length.greaterThan", 0);
|
||||
|
||||
tempusPage.getCalendarEvents().first().click();
|
||||
|
||||
tempusPage.getCalendarEventModal().should("be.visible");
|
||||
});
|
||||
|
||||
it("shows event context menu when right clicking a calendar event", () => {
|
||||
tempusPage.waitForCalendarToFinishLoading();
|
||||
tempusPage.getCalendarEvents().should("have.length.greaterThan", 0);
|
||||
|
||||
tempusPage.getCalendarEvents().first().rightclick();
|
||||
|
||||
tempusPage.getEventContextMenu().should("be.visible");
|
||||
});
|
||||
|
||||
it("shows history modal when selecting History from event context menu", () => {
|
||||
tempusPage.waitForCalendarToFinishLoading();
|
||||
tempusPage.getCalendarEvents().should("have.length.greaterThan", 0);
|
||||
|
||||
tempusPage.getCalendarEvents().first().rightclick();
|
||||
tempusPage.getEventContextMenuOption("History").click();
|
||||
cy.wait("@fetchEventHistory").its("response.statusCode").should("eq", 200);
|
||||
|
||||
tempusPage.getHistoryModal().should("be.visible");
|
||||
});
|
||||
|
||||
it("shows reservation modal when dropping reservation handle on calendar", () => {
|
||||
tempusPage.waitForCalendarToFinishLoading();
|
||||
tempusPage.getCalendarSection().should("be.visible");
|
||||
|
||||
tempusPage.getReservationDragHandle().drag(tempusPage.selectors.calendarSection);
|
||||
|
||||
tempusPage.getReservationModal().should("be.visible");
|
||||
});
|
||||
|
||||
it("can drop event from calendar into parking slot", () => {
|
||||
tempusPage.getEventParkingSlot().should("exist");
|
||||
tempusPage.getParkedEvents().should("have.length", 0);
|
||||
|
||||
tempusPage.getCalendarEvents().first().drag(tempusPage.selectors.parkingSlot);
|
||||
|
||||
tempusPage.getParkedEvents().should("have.length", 1);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,710 @@
|
||||
import { tempusPage } from "../../../../support/pages/tempus.po";
|
||||
|
||||
const PLANER = "Planer";
|
||||
const LEKTOR = "Lektor";
|
||||
const STUDENT = "Student";
|
||||
const SYNC = "Sync";
|
||||
|
||||
const roleFetchAliases = {
|
||||
[PLANER]: "@fetchPlanData",
|
||||
[LEKTOR]: "@fetchLecturerPlanData",
|
||||
[STUDENT]: "@fetchStudentPlanData",
|
||||
};
|
||||
|
||||
const waitForOk = (alias) =>
|
||||
cy.wait(alias).its("response.statusCode").should("eq", 200);
|
||||
|
||||
const syncAndReloadPlanner = () => {
|
||||
tempusPage.selectPreviewRole(SYNC); // ensure all events are loaded
|
||||
waitForOk("@syncCalendar");
|
||||
waitForOk("@fetchPlanData");
|
||||
tempusPage.waitForCalendarToFinishLoading();
|
||||
};
|
||||
|
||||
const selectRoleAndWait = (role) => {
|
||||
tempusPage.selectPreviewRole(role);
|
||||
waitForOk(roleFetchAliases[role]);
|
||||
tempusPage.waitForCalendarToFinishLoading();
|
||||
};
|
||||
|
||||
const formatIsoDateTimeForKalenderApi = (isoDateTime) =>
|
||||
isoDateTime.slice(0, 16).replace("T", " ");
|
||||
|
||||
let eventRestoreOnFailure = null;
|
||||
|
||||
context("Base tempus tests", () => {
|
||||
beforeEach(() => {
|
||||
cy.login();
|
||||
|
||||
cy.intercept({ method: "GET", url: "**/StgTree" }).as("fetchCourseTree");
|
||||
cy.intercept({
|
||||
method: "GET",
|
||||
url: /\/tempus\/Kalender\/getPlan(?:\?|$)/,
|
||||
}).as("fetchPlanData");
|
||||
cy.intercept({
|
||||
method: "GET",
|
||||
url: /\/tempus\/Kalender\/getPlanLecturer(?:\?|$)/,
|
||||
}).as("fetchLecturerPlanData");
|
||||
cy.intercept({
|
||||
method: "GET",
|
||||
url: /\/tempus\/Kalender\/getPlanStudent(?:\?|$)/,
|
||||
}).as("fetchStudentPlanData");
|
||||
cy.intercept({ method: "GET", url: "**/tempus/Kalender/getHistory**" }).as(
|
||||
"fetchEventHistory",
|
||||
);
|
||||
cy.intercept({
|
||||
method: "GET",
|
||||
url: "**/tempus/coursepicker/getByStg**",
|
||||
}).as("fetchCoursePickerCourses");
|
||||
cy.intercept({
|
||||
method: "POST",
|
||||
url: "**/tempus/Kalender/addKalenderEvent**",
|
||||
}).as("addCalendarEvent");
|
||||
cy.intercept({
|
||||
method: "POST",
|
||||
url: "**/tempus/Kalender/updateKalenderEvent**",
|
||||
}).as("updateCalendarEvent");
|
||||
cy.intercept({
|
||||
method: "POST",
|
||||
url: "**/tempus/Kalender/sync**",
|
||||
}).as("syncCalendar");
|
||||
cy.intercept({
|
||||
method: "POST",
|
||||
url: "**/tempus/Kalender/syncToLecturer**",
|
||||
}).as("syncCalendarToLecturer");
|
||||
cy.intercept({
|
||||
method: "POST",
|
||||
url: "**/tempus/Kalender/syncToStudent**",
|
||||
}).as("syncCalendarToStudent");
|
||||
cy.intercept({
|
||||
method: "POST",
|
||||
url: "**/tempus/Kalender/deleteEntry**",
|
||||
}).as("deleteCalendarEvent");
|
||||
|
||||
tempusPage.visit();
|
||||
|
||||
waitForOk("@fetchCourseTree");
|
||||
waitForOk("@fetchPlanData");
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
const eventRestore = eventRestoreOnFailure;
|
||||
eventRestoreOnFailure = null;
|
||||
|
||||
if (this.currentTest.state !== "failed" || !eventRestore) {
|
||||
return;
|
||||
}
|
||||
|
||||
return tempusPage
|
||||
.restoreKalenderEventTime(
|
||||
eventRestore.kalenderId,
|
||||
eventRestore.startTime,
|
||||
eventRestore.endTime,
|
||||
{ failOnStatusCode: false },
|
||||
)
|
||||
.its("status")
|
||||
.should("eq", 200);
|
||||
});
|
||||
|
||||
// it("can access Tempus page with valid credentials", () => {
|
||||
// tempusPage.getTempusOverview().should("be.visible");
|
||||
// });
|
||||
|
||||
// it("shows all expected page elements", () => {
|
||||
// tempusPage.getTempusOverview().should("be.visible");
|
||||
// tempusPage.getSidebarMenu().should("exist");
|
||||
// tempusPage.getSlideInCoursesMenu().should("exist");
|
||||
// tempusPage.getCalendarSection().should("be.visible");
|
||||
// tempusPage.getPreviewRoleOptionsHolder().should("be.visible");
|
||||
// });
|
||||
|
||||
// it("can open courses menu", () => {
|
||||
// tempusPage.getSlideInCoursesMenu().should("exist").should("be.hidden");
|
||||
|
||||
// tempusPage.openCoursesMenu();
|
||||
|
||||
// tempusPage.getCourseTreeRows().should("have.length.greaterThan", 0);
|
||||
// });
|
||||
|
||||
// it("can select one course and show preview of its events", () => {
|
||||
// tempusPage.getSlideInCoursesMenu().should("exist");
|
||||
// tempusPage.getCourseTreeRows().should("have.length.greaterThan", 0);
|
||||
// tempusPage.getCoursePicker().should("exist");
|
||||
// tempusPage.getCoursePickerRows().should("have.length", 0);
|
||||
|
||||
// tempusPage.selectFirstCourse();
|
||||
// waitForOk("@fetchCoursePickerCourses");
|
||||
|
||||
// tempusPage.getCoursePickerRows().should("have.length.greaterThan", 0);
|
||||
// });
|
||||
|
||||
// it("can search for a course event in the course picker", () => {
|
||||
// tempusPage.selectFirstCourse();
|
||||
// waitForOk("@fetchCoursePickerCourses");
|
||||
|
||||
// tempusPage.getCoursePickerRows().should("have.length.greaterThan", 0);
|
||||
|
||||
// tempusPage
|
||||
// .getCoursePickerRows()
|
||||
// .last()
|
||||
// .find("div:first span:first")
|
||||
// .invoke("text")
|
||||
// .as("randomCourseText");
|
||||
|
||||
// cy.get("@randomCourseText").then((randomCourseText) => {
|
||||
// tempusPage.getCoursePickerSearchInput().type(randomCourseText);
|
||||
|
||||
// tempusPage.getCoursePickerRows().should("have.length.greaterThan", 0);
|
||||
// tempusPage
|
||||
// .getCoursePickerRows()
|
||||
// .first()
|
||||
// .should("contain.text", randomCourseText);
|
||||
// });
|
||||
// });
|
||||
|
||||
// it("can drag and drop one course event into the calendar", () => {
|
||||
// tempusPage.getCalendarSection().should("exist");
|
||||
// tempusPage.waitForCalendarToFinishLoading();
|
||||
|
||||
// tempusPage.selectFirstCourse();
|
||||
// waitForOk("@fetchCoursePickerCourses");
|
||||
|
||||
// tempusPage.getCalendarEvents().then(($events) => {
|
||||
// cy.wrap($events.length).as("initialEventCount");
|
||||
// });
|
||||
|
||||
// tempusPage.getCoursePickerRows().should("have.length.greaterThan", 0);
|
||||
// tempusPage.dropCourseOnCalendarPart(0, 10);
|
||||
|
||||
// waitForOk("@addCalendarEvent");
|
||||
// waitForOk("@fetchPlanData");
|
||||
|
||||
// tempusPage.waitForCalendarToFinishLoading();
|
||||
|
||||
// cy.get("@initialEventCount").then((initialEventCount) => {
|
||||
// tempusPage
|
||||
// .getCalendarEvents()
|
||||
// .should("have.length", initialEventCount + 1);
|
||||
// });
|
||||
// });
|
||||
|
||||
// it("shows the same number of calendar events for all role previews", () => {
|
||||
// const rolePreviews = [
|
||||
// { label: PLANER, fetchAlias: roleFetchAliases[PLANER] },
|
||||
// { label: LEKTOR, fetchAlias: roleFetchAliases[LEKTOR] },
|
||||
// { label: STUDENT, fetchAlias: roleFetchAliases[STUDENT] },
|
||||
// ];
|
||||
// const eventCounts = {};
|
||||
|
||||
// syncAndReloadPlanner();
|
||||
|
||||
// cy.wrap(rolePreviews)
|
||||
// .each((rolePreview) => {
|
||||
// selectRoleAndWait(rolePreview.label);
|
||||
|
||||
// tempusPage.getCalendarEvents().then(($events) => {
|
||||
// eventCounts[rolePreview.label] = $events.length;
|
||||
// });
|
||||
// })
|
||||
// .then(() => {
|
||||
// const expectedCount = eventCounts[rolePreviews[0].label];
|
||||
|
||||
// Object.entries(eventCounts).forEach(([role, count]) => {
|
||||
// expect(count, `${role} calendar event count`).to.eq(expectedCount);
|
||||
// });
|
||||
// });
|
||||
// });
|
||||
|
||||
// it("shows event details modal when clicking a calendar event", () => {
|
||||
// tempusPage.waitForCalendarToFinishLoading();
|
||||
// tempusPage.getCalendarEvents().should("have.length.greaterThan", 0);
|
||||
|
||||
// tempusPage.getCalendarEvents().first().click();
|
||||
|
||||
// tempusPage.getCalendarEventModal().should("be.visible");
|
||||
// });
|
||||
|
||||
// it("shows event context menu when right clicking a calendar event", () => {
|
||||
// tempusPage.waitForCalendarToFinishLoading();
|
||||
// tempusPage.getCalendarEvents().should("have.length.greaterThan", 0);
|
||||
|
||||
// tempusPage.getCalendarEvents().first().rightclick();
|
||||
|
||||
// tempusPage.getEventContextMenu().should("be.visible");
|
||||
// });
|
||||
|
||||
// it("shows history modal when selecting History from event context menu", () => {
|
||||
// tempusPage.waitForCalendarToFinishLoading();
|
||||
// tempusPage.getCalendarEvents().should("have.length.greaterThan", 0);
|
||||
|
||||
// tempusPage.getCalendarEvents().first().rightclick();
|
||||
// tempusPage.getEventContextMenuOption("History").click();
|
||||
// waitForOk("@fetchEventHistory");
|
||||
|
||||
// tempusPage.getHistoryModal().should("be.visible");
|
||||
// });
|
||||
|
||||
// it.skip("shows reservation modal when dropping reservation handle on calendar", () => {
|
||||
// tempusPage.waitForCalendarToFinishLoading();
|
||||
// tempusPage.getCalendarBaseGrid().should("be.visible");
|
||||
// cy.wait(1000); // wait for potential animations
|
||||
// tempusPage
|
||||
// .getReservationDragHandle()
|
||||
// .drag(
|
||||
// tempusPage.selectors.calendarBaseGrid + " .part-body:nth-of-type(18)",
|
||||
// {
|
||||
// waitForAnimations: false,
|
||||
// animationDistanceThreshold: 0,
|
||||
// },
|
||||
// );
|
||||
|
||||
// cy.wait(3000); // wait for potential animations
|
||||
// tempusPage.getReservationModal().should("be.visible");
|
||||
// });
|
||||
|
||||
// it("can drop event from calendar into parking slot", () => {
|
||||
// tempusPage.getEventParkingSlot().should("exist");
|
||||
// tempusPage.getParkedEvents().should("have.length", 0);
|
||||
|
||||
// tempusPage
|
||||
// .getCalendarEvents()
|
||||
// .first()
|
||||
// .drag(tempusPage.selectors.parkingSlot);
|
||||
|
||||
// tempusPage.getParkedEvents().should("have.length", 1);
|
||||
// });
|
||||
|
||||
it("on planner event change shows unchanged event on other roles", () => {
|
||||
syncAndReloadPlanner();
|
||||
|
||||
cy.get(".fhc-calendar-base-grid > div")
|
||||
.last()
|
||||
.invoke(
|
||||
"css",
|
||||
"overflow",
|
||||
"hidden",
|
||||
);
|
||||
cy.wait(500); // ensure overflow change is applied before dragging, otherwise the drag can fail due to the calendar scrolling
|
||||
tempusPage
|
||||
.getCalendarEventsByTimeRange("08:00:00", "08:45:00")
|
||||
.first()
|
||||
.invoke("attr", "data-fhc-draggable-value")
|
||||
.then((eventJSON) => {
|
||||
expect(eventJSON).to.exist;
|
||||
|
||||
const eventData = JSON.parse(eventJSON);
|
||||
const originalStartTime = formatIsoDateTimeForKalenderApi(
|
||||
eventData.orig.isostart,
|
||||
);
|
||||
const originalEndTime = formatIsoDateTimeForKalenderApi(
|
||||
eventData.orig.isoend,
|
||||
);
|
||||
let eventId = eventData?.id;
|
||||
expect(eventId).to.exist;
|
||||
|
||||
tempusPage.dropEventOnCalendarPart(eventId, 2);
|
||||
|
||||
cy.wait("@updateCalendarEvent").then((interception) => {
|
||||
expect(interception.response.statusCode).to.eq(200);
|
||||
|
||||
const updatedEventId =
|
||||
interception.response.body.data.retval.kalender_id;
|
||||
|
||||
eventRestoreOnFailure = {
|
||||
kalenderId: updatedEventId,
|
||||
startTime: originalStartTime,
|
||||
endTime: originalEndTime,
|
||||
};
|
||||
|
||||
cy.wrap(updatedEventId).as("updatedEventId");
|
||||
});
|
||||
waitForOk("@fetchPlanData");
|
||||
|
||||
cy.get("@updatedEventId").then((updatedEventId) => {
|
||||
tempusPage.getEventGridRow(updatedEventId).then((gridRowStyle) => {
|
||||
selectRoleAndWait(LEKTOR);
|
||||
tempusPage.getEventGridRow(eventId).then((lecturerGridRow) => {
|
||||
expect(lecturerGridRow).to.not.eq(gridRowStyle);
|
||||
});
|
||||
|
||||
selectRoleAndWait(STUDENT);
|
||||
tempusPage.getEventGridRow(eventId).then((studentGridRow) => {
|
||||
expect(studentGridRow).to.not.eq(gridRowStyle);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
cy.get(".fhc-calendar-base-grid > div:last-child()").invoke(
|
||||
"css",
|
||||
"overflow",
|
||||
"auto",
|
||||
);
|
||||
});
|
||||
|
||||
it("sync after planner preview event change loads event in same way on all previews", () => {
|
||||
syncAndReloadPlanner();
|
||||
|
||||
tempusPage
|
||||
.getCalendarEventsByTimeRange("08:00:00", "08:45:00")
|
||||
.first()
|
||||
.invoke("attr", "data-fhc-draggable-value")
|
||||
.then((eventJSON) => {
|
||||
expect(eventJSON).to.exist;
|
||||
|
||||
const eventData = JSON.parse(eventJSON);
|
||||
const originalStartTime = formatIsoDateTimeForKalenderApi(
|
||||
eventData.orig.isostart,
|
||||
);
|
||||
const originalEndTime = formatIsoDateTimeForKalenderApi(
|
||||
eventData.orig.isoend,
|
||||
);
|
||||
let eventId = eventData?.id;
|
||||
expect(eventId).to.exist;
|
||||
|
||||
tempusPage.dropEventOnCalendarPart(eventId, 3, {
|
||||
scrollIntoView: true,
|
||||
});
|
||||
|
||||
cy.wait("@updateCalendarEvent").then((interception) => {
|
||||
expect(interception.response.statusCode).to.eq(200);
|
||||
|
||||
const updatedEventId =
|
||||
interception.response.body.data.retval.kalender_id;
|
||||
|
||||
eventRestoreOnFailure = {
|
||||
kalenderId: updatedEventId,
|
||||
startTime: originalStartTime,
|
||||
endTime: originalEndTime,
|
||||
};
|
||||
|
||||
cy.wrap(updatedEventId).as("updatedEventId");
|
||||
});
|
||||
waitForOk("@fetchPlanData");
|
||||
|
||||
syncAndReloadPlanner();
|
||||
|
||||
cy.get("@updatedEventId").then((updatedEventId) => {
|
||||
tempusPage.getEventGridRow(updatedEventId).then((gridRowStyle) => {
|
||||
selectRoleAndWait(LEKTOR);
|
||||
tempusPage
|
||||
.getEventGridRow(updatedEventId)
|
||||
.then((lecturerGridRow) => {
|
||||
expect(lecturerGridRow).to.eq(gridRowStyle);
|
||||
});
|
||||
|
||||
selectRoleAndWait(STUDENT);
|
||||
tempusPage
|
||||
.getEventGridRow(updatedEventId)
|
||||
.then((studentGridRow) => {
|
||||
expect(studentGridRow).to.eq(gridRowStyle);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("live unlock after planner preview event change loads event in same way on planner and lektor, but not on student preview", () => {
|
||||
syncAndReloadPlanner();
|
||||
|
||||
tempusPage
|
||||
.getCalendarEventsByTimeRange("08:00:00", "08:45:00")
|
||||
.first()
|
||||
.invoke("attr", "data-fhc-draggable-value")
|
||||
.then((eventJSON) => {
|
||||
expect(eventJSON).to.exist;
|
||||
|
||||
let eventId = JSON.parse(eventJSON)?.id;
|
||||
expect(eventId).to.exist;
|
||||
tempusPage.dropEventOnCalendarPart(eventId, 4, {
|
||||
scrollIntoView: true,
|
||||
});
|
||||
|
||||
cy.wait("@updateCalendarEvent")
|
||||
.its("response.body.data.retval.kalender_id")
|
||||
.as("updatedEventId");
|
||||
waitForOk("@fetchPlanData");
|
||||
|
||||
tempusPage.waitForCalendarToFinishLoading();
|
||||
|
||||
cy.get("@updatedEventId").then((updatedEventId) => {
|
||||
tempusPage
|
||||
.getCalendarEventById(updatedEventId)
|
||||
.should("exist")
|
||||
.rightclick();
|
||||
tempusPage.getEventContextMenuOption("Freischalten für Live").click(); // TODO: Check wether live is for studnet
|
||||
waitForOk("@syncCalendarToStudent");
|
||||
|
||||
tempusPage.getEventGridRow(updatedEventId).then((gridRowStyle) => {
|
||||
selectRoleAndWait(LEKTOR);
|
||||
tempusPage
|
||||
.getEventGridRow(updatedEventId)
|
||||
.then((lecturerGridRow) => {
|
||||
expect(lecturerGridRow).to.eq(gridRowStyle);
|
||||
});
|
||||
|
||||
selectRoleAndWait(STUDENT);
|
||||
tempusPage.getEventGridRow(eventId).then((studentGridRow) => {
|
||||
expect(studentGridRow).to.not.eq(gridRowStyle);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("event change on lector preview is prohibited", () => {
|
||||
syncAndReloadPlanner();
|
||||
|
||||
selectRoleAndWait(LEKTOR);
|
||||
|
||||
tempusPage
|
||||
.getCalendarEventsByTimeRange("08:00:00", "08:45:00")
|
||||
.first()
|
||||
.invoke("attr", "data-fhc-draggable-value")
|
||||
.then((eventJSON) => {
|
||||
expect(eventJSON).to.exist;
|
||||
|
||||
let eventId = JSON.parse(eventJSON)?.id;
|
||||
expect(eventId).to.exist;
|
||||
|
||||
tempusPage.dropEventOnCalendarPart(eventId, 15);
|
||||
|
||||
cy.get("@updateCalendarEvent").should("not.exist");
|
||||
|
||||
tempusPage.getEventGridRow(eventId).then((gridRowStyle) => {
|
||||
selectRoleAndWait(LEKTOR);
|
||||
tempusPage.getEventGridRow(eventId).then((lecturerGridRow) => {
|
||||
expect(lecturerGridRow).to.eq(gridRowStyle);
|
||||
});
|
||||
|
||||
selectRoleAndWait(STUDENT);
|
||||
tempusPage.getEventGridRow(eventId).then((studentGridRow) => {
|
||||
expect(studentGridRow).to.eq(gridRowStyle);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("event change on student preview is prohibited", () => {
|
||||
syncAndReloadPlanner();
|
||||
|
||||
selectRoleAndWait(STUDENT);
|
||||
|
||||
tempusPage
|
||||
.getCalendarEventsByTimeRange("08:00:00", "08:45:00")
|
||||
.first()
|
||||
.invoke("attr", "data-fhc-draggable-value")
|
||||
.then((eventJSON) => {
|
||||
expect(eventJSON).to.exist;
|
||||
|
||||
let eventId = JSON.parse(eventJSON)?.id;
|
||||
expect(eventId).to.exist;
|
||||
|
||||
tempusPage.dropEventOnCalendarPart(eventId, 15);
|
||||
|
||||
cy.get("@updateCalendarEvent").should("not.exist");
|
||||
|
||||
tempusPage.getEventGridRow(eventId).then((gridRowStyle) => {
|
||||
selectRoleAndWait(LEKTOR);
|
||||
tempusPage.getEventGridRow(eventId).then((lecturerGridRow) => {
|
||||
expect(lecturerGridRow).to.eq(gridRowStyle);
|
||||
});
|
||||
|
||||
selectRoleAndWait(STUDENT);
|
||||
tempusPage.getEventGridRow(eventId).then((studentGridRow) => {
|
||||
expect(studentGridRow).to.eq(gridRowStyle);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("event deletion on planner preview preservers event on planner, but shows it as unsynced on lektor and student preview", () => {
|
||||
syncAndReloadPlanner();
|
||||
|
||||
tempusPage
|
||||
.getCalendarEvents()
|
||||
.first()
|
||||
.invoke("attr", "data-fhc-draggable-value")
|
||||
.then((eventJSON) => {
|
||||
expect(eventJSON).to.exist;
|
||||
|
||||
let eventId = JSON.parse(eventJSON)?.id;
|
||||
expect(eventId).to.exist;
|
||||
tempusPage
|
||||
.getCalendarEventById(eventId)
|
||||
.should("be.visible")
|
||||
.rightclick();
|
||||
tempusPage.getEventContextMenuOption("Delete").click();
|
||||
|
||||
cy.wait("@deleteCalendarEvent");
|
||||
waitForOk("@fetchPlanData");
|
||||
|
||||
tempusPage.waitForCalendarToFinishLoading();
|
||||
|
||||
tempusPage.getCalendarEventById(eventId).should("be.visible");
|
||||
|
||||
selectRoleAndWait(LEKTOR);
|
||||
tempusPage.getCalendarEventById(eventId).should("not.exist");
|
||||
|
||||
selectRoleAndWait(STUDENT);
|
||||
tempusPage.getCalendarEventById(eventId).should("not.exist");
|
||||
});
|
||||
});
|
||||
|
||||
it("syncing event deletion on planner preview removes event from other previews", () => {
|
||||
syncAndReloadPlanner();
|
||||
|
||||
tempusPage
|
||||
.getCalendarEvents()
|
||||
.first()
|
||||
.invoke("attr", "data-fhc-draggable-value")
|
||||
.then((eventJSON) => {
|
||||
expect(eventJSON).to.exist;
|
||||
|
||||
let eventId = JSON.parse(eventJSON)?.id;
|
||||
expect(eventId).to.exist;
|
||||
tempusPage
|
||||
.getCalendarEventById(eventId)
|
||||
.should("be.visible")
|
||||
.rightclick();
|
||||
tempusPage.getEventContextMenuOption("Delete").click();
|
||||
|
||||
cy.wait("@deleteCalendarEvent");
|
||||
waitForOk("@fetchPlanData");
|
||||
|
||||
syncAndReloadPlanner();
|
||||
|
||||
tempusPage.getCalendarEventById(eventId).should("not.exist");
|
||||
|
||||
selectRoleAndWait(LEKTOR);
|
||||
tempusPage.getCalendarEventById(eventId).should("not.exist");
|
||||
|
||||
selectRoleAndWait(STUDENT);
|
||||
tempusPage.getCalendarEventById(eventId).should("not.exist");
|
||||
});
|
||||
});
|
||||
|
||||
it("can bottom resize an event on planner preview", () => {
|
||||
tempusPage.getCalendarSection().should("exist");
|
||||
tempusPage.waitForCalendarToFinishLoading();
|
||||
|
||||
tempusPage
|
||||
.getCalendarEventsByStartTime("08:00:00")
|
||||
.first()
|
||||
.invoke("attr", "data-fhc-draggable-value")
|
||||
.then((eventJSON) => {
|
||||
cy.wrap(JSON.parse(eventJSON)).its("id").as("eventId");
|
||||
cy.wrap(JSON.parse(eventJSON).orig)
|
||||
.its("beginn")
|
||||
.as("originalEventStart");
|
||||
cy.wrap(JSON.parse(eventJSON).orig).its("ende").as("originalEventEnd");
|
||||
});
|
||||
|
||||
cy.get("@eventId").then((eventId) => {
|
||||
tempusPage
|
||||
.getCalendarEventById(eventId)
|
||||
.find(".fhc-resize-bar--bottom")
|
||||
.first()
|
||||
.realHover()
|
||||
.realMouseDown("center", {
|
||||
button: "left",
|
||||
})
|
||||
.realMouseMove(0, 120)
|
||||
.realMouseUp();
|
||||
|
||||
cy.wait("@updateCalendarEvent").then((interception) => {
|
||||
expect(interception.response.statusCode).to.eq(200);
|
||||
|
||||
const updatedEventId =
|
||||
interception.response.body.data.retval.kalender_id;
|
||||
|
||||
cy.wrap(updatedEventId).as("updatedEventId");
|
||||
});
|
||||
waitForOk("@fetchPlanData");
|
||||
|
||||
cy.get("@updatedEventId").then((updatedEventId) => {
|
||||
tempusPage
|
||||
.getCalendarEventById(updatedEventId)
|
||||
.invoke("attr", "data-fhc-draggable-value")
|
||||
.then((eventJSON) => {
|
||||
let newEventStart = JSON.parse(eventJSON)?.orig?.beginn;
|
||||
let newEventEnd = JSON.parse(eventJSON)?.orig?.ende;
|
||||
|
||||
cy.get("@originalEventStart").then((originalEventStart) => {
|
||||
expect(newEventStart).to.eq(originalEventStart);
|
||||
});
|
||||
cy.get("@originalEventEnd").then((originalEventEnd) => {
|
||||
expect(newEventEnd).to.not.eq(originalEventEnd);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it("can top resize an event on planner preview", () => {
|
||||
tempusPage.getCalendarSection().should("exist");
|
||||
tempusPage.waitForCalendarToFinishLoading();
|
||||
|
||||
tempusPage
|
||||
.getCalendarEventsByStartTime("09:40:00")
|
||||
.first()
|
||||
.invoke("attr", "data-fhc-draggable-value")
|
||||
.then((eventJSON) => {
|
||||
cy.wrap(JSON.parse(eventJSON)).its("id").as("eventId");
|
||||
cy.wrap(JSON.parse(eventJSON).orig)
|
||||
.its("beginn")
|
||||
.as("originalEventStart");
|
||||
cy.wrap(JSON.parse(eventJSON).orig).its("ende").as("originalEventEnd");
|
||||
});
|
||||
|
||||
cy.get("@eventId").then((eventId) => {
|
||||
tempusPage
|
||||
.getCalendarEventById(eventId)
|
||||
.find(".fhc-resize-bar--top")
|
||||
.first()
|
||||
.realHover()
|
||||
.realMouseDown("center", {
|
||||
button: "left",
|
||||
})
|
||||
.realMouseMove(0, -40)
|
||||
.realMouseUp();
|
||||
|
||||
cy.wait("@updateCalendarEvent").then((interception) => {
|
||||
expect(interception.response.statusCode).to.eq(200);
|
||||
|
||||
const updatedEventId =
|
||||
interception.response.body.data.retval.kalender_id;
|
||||
|
||||
cy.wrap(updatedEventId).as("updatedEventId");
|
||||
});
|
||||
waitForOk("@fetchPlanData");
|
||||
|
||||
cy.get("@updatedEventId").then((updatedEventId) => {
|
||||
tempusPage
|
||||
.getCalendarEventById(updatedEventId)
|
||||
.invoke("attr", "data-fhc-draggable-value")
|
||||
.then((eventJSON) => {
|
||||
let newEventStart = JSON.parse(eventJSON)?.orig?.beginn;
|
||||
let newEventEnd = JSON.parse(eventJSON)?.orig?.ende;
|
||||
|
||||
cy.get("@originalEventStart").then((originalEventStart) => {
|
||||
expect(newEventStart).to.not.eq(originalEventStart);
|
||||
});
|
||||
cy.get("@originalEventEnd").then((originalEventEnd) => {
|
||||
expect(newEventEnd).to.eq(originalEventEnd);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// check live issue -- done
|
||||
// check delete -- DONE
|
||||
// resize - dones
|
||||
// sve al bez stunden raster
|
||||
// course picker search
|
||||
// raumauswal
|
||||
// btn click to current semester
|
||||
// filter za raum und fuer person
|
||||
// filter ode u sidebar
|
||||
});
|
||||
@@ -25,6 +25,7 @@
|
||||
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
|
||||
|
||||
require("@4tw/cypress-drag-drop");
|
||||
require("cypress-real-events")
|
||||
|
||||
Cypress.Commands.add("login", () => {
|
||||
const { adminusername, adminpassword, loginAsUser } = Cypress.env();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
class TempusPage {
|
||||
selectors = {
|
||||
calendarSection: "div[data-cy='tempus'] .fhc-calendar-base",
|
||||
calendarBaseGrid: "div[data-cy='tempus'] .fhc-calendar-base-grid",
|
||||
parkingSlot: "div[data-cy='tempus'] #parkingslot",
|
||||
};
|
||||
|
||||
@@ -14,6 +15,7 @@ class TempusPage {
|
||||
getSlideInCoursesMenu = () => cy.get("div[data-cy='verbandMenu']");
|
||||
getSidebarMenu = () => this.getTempusOverview().find("#sidebarMenu");
|
||||
getCalendarSection = () => this.getTempusOverview().find(".fhc-calendar-base");
|
||||
getCalendarBaseGrid = () => this.getCalendarSection().find(".fhc-calendar-base-grid");
|
||||
getCoursePicker = () => this.getTempusOverview().find(".course-picker");
|
||||
getPreviewRoleOptionsHolder = () => this.getTempusOverview().find("[data-cy='previewRoleOptionsHolder']");
|
||||
getAllCoursesSliderBtn = () => this.getSidebarMenu().find("button[title='Verband']").first();
|
||||
@@ -21,6 +23,76 @@ class TempusPage {
|
||||
getCoursePickerRows = () => this.getCoursePicker().find(".course-picker-row");
|
||||
getCoursePickerSearchInput = () => this.getCoursePicker().find("input");
|
||||
getCalendarEvents = () => this.getCalendarSection().find(".fhc-calendar-base-grid-line-event");
|
||||
|
||||
getCalendarEventById = (id) => this.getCalendarEvents().filter(`div[data-id="event-${id}"]`);
|
||||
getCalendarPartDropTarget = (partIndex) =>
|
||||
`${this.selectors.calendarBaseGrid} .part-body:nth-of-type(${partIndex})`;
|
||||
dropEventOnCalendarPart = (eventId, partIndex, options = {}) => {
|
||||
const { scrollIntoView = false, ...dragOptions } = options;
|
||||
const event = this.getCalendarEventById(eventId);
|
||||
const eventToDrag = scrollIntoView ? event.scrollIntoView() : event;
|
||||
|
||||
return eventToDrag.should("be.visible").focus().drag(
|
||||
this.getCalendarPartDropTarget(partIndex),
|
||||
{
|
||||
waitForAnimations: false,
|
||||
animationDistanceThreshold: 0,
|
||||
scrollBehavior: false,
|
||||
...dragOptions,
|
||||
},
|
||||
);
|
||||
};
|
||||
dropCourseOnCalendarPart = (courseIndex, partIndex, options = {}) => {
|
||||
const { scrollIntoView = false, ...dragOptions } = options;
|
||||
const course = this.getCoursePickerRows().eq(courseIndex);
|
||||
const courseToDrag = scrollIntoView ? course.scrollIntoView() : course;
|
||||
|
||||
return courseToDrag.should("be.visible").drag(
|
||||
this.getCalendarPartDropTarget(partIndex),
|
||||
{
|
||||
waitForAnimations: false,
|
||||
animationDistanceThreshold: 0,
|
||||
...dragOptions,
|
||||
},
|
||||
);
|
||||
};
|
||||
updateKalenderEvent = (kalenderId, updatedInfos, options = {}) =>
|
||||
cy.request({
|
||||
method: "POST",
|
||||
url: "/index.ci.php/api/frontend/v1/tempus/Kalender/updateKalenderEvent",
|
||||
body: {
|
||||
kalender_id: kalenderId,
|
||||
updatedInfos,
|
||||
},
|
||||
...options,
|
||||
});
|
||||
restoreKalenderEventTime = (kalenderId, startTime, endTime, options = {}) =>
|
||||
this.updateKalenderEvent(
|
||||
kalenderId,
|
||||
{
|
||||
start_time: startTime,
|
||||
end_time: endTime,
|
||||
},
|
||||
options,
|
||||
);
|
||||
getEventGridRowFromStyle = (style) =>
|
||||
/grid-row:\s*([^;]+)/.exec(style)?.[1]?.trim();
|
||||
getEventGridRow = (id) =>
|
||||
this.getCalendarEventById(id)
|
||||
.invoke("attr", "style")
|
||||
.then((style) => this.getEventGridRowFromStyle(style));
|
||||
getCalendarEventsByStartTime = (startTime) => this.getCalendarEvents().filter((index, event) => {
|
||||
const eventData = JSON.parse(event.getAttribute("data-fhc-draggable-value"));
|
||||
return eventData?.orig?.beginn === startTime;
|
||||
});
|
||||
getCalendarEventsByEndTime = (endTime) => this.getCalendarEvents().filter((index, event) => {
|
||||
const eventData = JSON.parse(event.getAttribute("data-fhc-draggable-value"));
|
||||
return eventData?.orig?.ende === endTime;
|
||||
});
|
||||
getCalendarEventsByTimeRange = (startTime, endTime) => this.getCalendarEvents().filter((index, event) => {
|
||||
const eventData = JSON.parse(event.getAttribute("data-fhc-draggable-value"));
|
||||
return eventData?.orig?.beginn === startTime && eventData?.orig?.ende === endTime;
|
||||
});
|
||||
getCalendarLoadingEvents = () => this.getCalendarSection().find(".placeholder-glow");
|
||||
getCalendarEventModal = () => this.getCalendarSection().find(".bootstrap-modal.show");
|
||||
getEventContextMenu = () => cy.get("[data-cy='eventContextMenu']");
|
||||
|
||||
Generated
+11
-176
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@
|
||||
"cypress": "^15.11.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"cypress-real-events": "^1.15.0",
|
||||
"dotenv": "^17.4.2"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user