Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/admin dashboard event visualization 407 #431

3 changes: 0 additions & 3 deletions client/src/contexts/AuthContext/useProvideAuth.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ const useProvideAuth = () => {
DataService.getCurrentUser().then(response => {
console.log(response.data);
setUser(response.data);
if (response.data instanceof Object) {
navigate("/calendar");
}
});
}, []);

Expand Down
59 changes: 57 additions & 2 deletions client/src/pages/AdminDashboard.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,63 @@
import React from "react";
import { useEffect, useState } from "react";
import "index.css";
import DataService from "services/dataService";

export const AdminDashboard = () => {
const [allEvents, setAllEvents] = useState({});
const [loading, setLoading] = useState(false);

const handleGetAllEvents = async () => {
setLoading(true);
const response = await DataService.getAll();
setAllEvents(response.data);
setLoading(false);
};

// Load all events on initial page render
useEffect(() => {
const fetch = async () => await handleGetAllEvents();
fetch();
}, []);

let eventStatus = loading ? "LOADING..." : Object.keys(allEvents).length;
return (
<div>
<h1>You have made it to admin dashboard</h1>
<div className="flex flex-col h-100 min-h-screen w-full p-4 bg-primary">
<div className="border-b-2 border-mainOrange border-dotted flex justify-between py-2">
<h1 className="font-bold font-inconsolata text-3xl md:text-4xl lg:text-5xl text-mainOrange">
Admin Dashboard (<span className="event-count">{eventStatus}</span>)
</h1>
{/* Button to trigger refresh of event list after initial page load */}
<button
onClick={handleGetAllEvents}
className="refresh-btn bg-white border-2 border-black flex flex-col justify-center items-center px-4"
>
🗘 Refresh Events
</button>
</div>
<div id="events" className="h-full mt-2">
{/* Display all events in an unordered list when the data is finished loading */}
{loading ||
Object.keys(allEvents).map(key => {
return (
<div
key={allEvents[key].id}
className="event bg-primary my-4 p-4 rounded-xl"
>
<ul className="font-inconsolata">
<li className="text-2xl md:text-3xl lg:text-4xl font-bold">
{allEvents[key].title}
</li>
<li className="text-mainBlue">
{allEvents[key].description}
</li>
<hr className="border-teal-light" />
<li>Scheduled by: {allEvents[key].user.displayName}</li>
</ul>
</div>
);
})}
</div>
</div>
);
};
154 changes: 154 additions & 0 deletions cypress/e2e/admin-dashboard.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/// <reference types="cypress" />

import tgt from "../support/tgt";

// Generate test event
const TEST_EVENT_AUTHOR = "100_DEVER";
const TEST_EVENT_GROUP_ID = "admin_text_event_id";
const TEST_EVENTS = [
{
title: "1st EVENT",
description: "1st Description",
location: "1st Location",
groupId: TEST_EVENT_GROUP_ID,
startAt: Date.now(),
endAt: Date.now() + 3600,
},
{
title: "2nd EVENT",
description: "2nd Description",
location: "2nd Location",
groupId: TEST_EVENT_GROUP_ID,
startAt: Date.now(),
endAt: Date.now() + 3600,
},
];

const addTestEvents = (test_events = TEST_EVENTS) => {
cy.url().then(return_url => {
cy.visit("/");

// Generate test events
cy.createOwnEvents(TEST_EVENT_AUTHOR, ...test_events);

// Close event creation modal
tgt.modal.close();

// Return to original URL
cy.visit(return_url);
});
};

describe("Admin Dashboard", () => {
const aliasHeaderEventCount = alias_name => {
cy.get("h1 .event-count")
.invoke("text")
.should("not.contain", "LOADING")
.then(parseInt)
.as(alias_name);
};

it("Admin Dashboard displays admin dashboard header", () => {
cy.visit("/admindashboard");
cy.get("h1").contains("Admin Dashboard");
});

describe("Add Events", () => {
before(() => {
// Navigate to admin dashboard
cy.visit("/admindashboard");
cy.get("#events").should("exist");

// Create alias for initial event count
aliasHeaderEventCount("initialEventCount");
});
beforeEach(() => {
// Add test events
addTestEvents(TEST_EVENTS);

// Navigate to admin dashboard
cy.visit("/admindashboard");
});

it("Event titles and descriptions", () => {
TEST_EVENTS.forEach((test_event, i) => {
// Ensure test events rendered with correct title
cy.get("#events")
.find(`.event:nth-of-type(${i + 1}) li:nth-of-type(1)`)
.invoke("text")
.should("contain", test_event.title);

// Ensure test event rendered with correct description
cy.get("#events")
.find(`.event:nth-of-type(${i + 1}) li:nth-of-type(2)`)
.invoke("text")
.should("contain", test_event.description);
});
});

it("Event Counts", () => {
// TODO: there should be a better way to wait for a React re-render to update the
// event count, but a manual wait works currently
cy.wait(100);

// Create alias for updated event count
aliasHeaderEventCount("newEventCount");

cy.get("h1")
.should("be.visible")
.should("not.contain", "LOADING")
.then(function () {
// Ensure updated event count is 1 greater then initial event count
expect(this.newEventCount).to.eq(
this.initialEventCount + TEST_EVENTS.length
);
});
});
});

describe("Page updates when events change", () => {
describe("Delete Events", () => {
before(() => {});
beforeEach(() => {
// Add test events
addTestEvents(TEST_EVENTS);

// Reload page and navigate to admin dashboard
// cy.reload();
cy.visit("/admindashboard");
cy.wait(100);

// Create alias for initial event count
aliasHeaderEventCount("initialEventCount");
});

it("Event Counts", () => {
// TODO: there should be a better way to wait for a React re-render to update the
// event count, but a manual wait works currently
cy.wait(100);

cy.deleteOwnGroupEvents(TEST_EVENT_AUTHOR, TEST_EVENT_GROUP_ID);

// Create alias for updated event count
aliasHeaderEventCount("newEventCount");

cy.visit("/admindashboard");
cy.get("h1")
.should("be.visible")
.should("not.contain", "LOADING")
.then(function () {
// Ensure updated event count matches initial count minus deleted events
expect(this.newEventCount).to.eq(
this.initialEventCount - TEST_EVENTS.length
);
});
});

it("Event titles and descriptions no longer exist", () => {
cy.deleteOwnGroupEvents(TEST_EVENT_AUTHOR, TEST_EVENT_GROUP_ID);
// Ensure all events were deleted
cy.get("#events").not("be.visible");
});
});
});
});
2 changes: 2 additions & 0 deletions cypress/e2e/auth.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ describe("Discord OAuth works", () => {
it("100Dever is allowed in & back", () => {
cy.login("100_DEVER", true);
tgt.auth.button.login().should("not.exist");
tgt.landing.button.calendar().click();
tgt.calendar.currentMonthAndYear().contains(getMonthAndYear());

tgt.auth.button.logout().click();
cy.login("100_DEVER");

tgt.auth.button.login().should("not.exist");
tgt.landing.button.calendar().click();
tgt.calendar.currentMonthAndYear().contains(getMonthAndYear());
});

Expand Down
1 change: 1 addition & 0 deletions cypress/e2e/calendar.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ describe("Calendar", () => {
const monthAndYear = getMonthAndYear(now);
const nextMonthAndYear = getMonthAndYear(nextMonth);
tgt.modal.close();
tgt.landing.button.calendar().click();
tgt.calendar.currentMonthAndYear().contains(monthAndYear);
cy.contains("Test Title").should("not.exist");

Expand Down
2 changes: 2 additions & 0 deletions cypress/e2e/create-event-form.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ describe("Event Creation Form", () => {
cy.visit("/");

cy.login("100_DEVER", true);
tgt.landing.button.calendar().click();
tgt.calendar.button.addEvent().click();

fillOutFirstPage();
Expand Down Expand Up @@ -209,6 +210,7 @@ describe("Event Creation Form", () => {
cy.visit("/");

cy.login("100_DEVER", true);
tgt.landing.button.calendar().click();
tgt.calendar.button.addEvent().click();

fillOutFirstPage();
Expand Down
5 changes: 0 additions & 5 deletions cypress/e2e/landing.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@ describe("Landing", () => {
cy.url().should("eq", Cypress.config().baseUrl + "/calendar");
});

it("Admin Dashboard displays admin dashboard", () => {
cy.visit("/admindashboard");
cy.get("h1").contains("You have made it to admin dashboard");
});

it("Hamburger Menu", () => {
cy.viewport("iphone-6");
tgt.nav.hamburger.toggle().click();
Expand Down
7 changes: 6 additions & 1 deletion cypress/e2e/view-event-modal.cy.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ describe("View Event Modal", () => {
.should(by ? "exist" : "not.exist");
};

tgt.landing.button.calendar().click();
cy.contains("button", "Test Title").each(($el, i) => {
const [starts, ends] = dates[i];
cy.wrap($el).click();
Expand All @@ -90,6 +91,7 @@ describe("View Event Modal", () => {

tgt.auth.button.logout().click();
cy.login("SECOND_100_DEVER", true);
tgt.landing.button.calendar().click();
cy.contains("button", "Test Title").first().click();
eventModalShown(false, tomorrow, tomorrowAndAnHour);
});
Expand Down Expand Up @@ -153,11 +155,15 @@ describe("View Event Modal", () => {
cy.contains("button", "Close").click();

cy.log("Deleting just Recurring #1");
tgt.landing.button.calendar().click();
cy.contains("button", "Test Recurring Title #1").first().click();
cy.contains("button", "Delete Specific Event").click();

cy.contains("button", "Test Recurring Title #1").should("not.exist");
tgt.modal.get().should("not.exist");

cy.get("Test Recurring Title #1").should("not.exist");
tgt.modal.get().should("not.exist");
cy.contains("button", "Test Recurring Title #2").should("exist");
cy.contains("button", "Test Recurring Title #3").should("exist");
cy.contains("button", "Test Single Title #1").should("exist");
Expand All @@ -166,7 +172,6 @@ describe("View Event Modal", () => {
cy.log("Deleting all recurring #2");
cy.contains("button", "Test Recurring Title #3").first().click();
cy.contains("button", "Delete All Events").click();
tgt.modal.get().should("not.exist");
cy.get("Test Recurring Title #2").should("not.exist");
cy.get("Test Recurring Title #3").should("not.exist");
cy.contains("button", "Test Single Title #1").should("exist");
Expand Down
8 changes: 8 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,11 @@ Cypress.Commands.add("createOwnEvents", (userCode, ...events) => {
});
cy.reload();
});

Cypress.Commands.add("deleteOwnGroupEvents", (userCode, groupId) => {
if (groupId) {
cy.request("DELETE", `/events/deleteAllEvents/${groupId}`);
}

cy.reload();
});
Loading