github.com/quickfeed/quickfeed@v0.0.0-20240507093252-ed8ca812a09c/public/src/__tests__/updateEnrollment.test.tsx (about) 1 import { Enrollment, Enrollment_UserStatus, Enrollments, User } from "../../proto/qf/types_pb" 2 import { createOvermindMock } from "overmind" 3 import { config } from "../overmind" 4 import { createMemoryHistory } from "history" 5 import React from "react" 6 import Members from "../components/Members" 7 import { Route, Router } from "react-router" 8 import { Provider } from "overmind-react" 9 import { render, screen } from "@testing-library/react" 10 import { MockData } from "./mock_data/mockData" 11 import { Void } from "../../proto/qf/requests_pb" 12 import { initializeOvermind, mock } from "./TestHelpers" 13 import { ApiClient } from "../overmind/effects" 14 import { Timestamp } from "@bufbuild/protobuf" 15 16 17 describe("UpdateEnrollment", () => { 18 const api = new ApiClient() 19 api.client = { 20 ...api.client, 21 getEnrollments: mock("getEnrollments", async (request) => { 22 const enrollments: Enrollment[] = [] 23 MockData.mockedEnrollments().enrollments.forEach(e => { 24 if (request.FetchMode?.case === "courseID") { 25 if (e.courseID === request.FetchMode.value) { 26 enrollments.push(e) 27 } 28 } else if (request.FetchMode?.case === "userID") { 29 if (e.userID === request.FetchMode.value) { 30 enrollments.push(e) 31 } 32 } else { 33 enrollments.push(e) 34 } 35 }) 36 return { message: new Enrollments({ enrollments }), error: null } 37 }), 38 updateEnrollments: mock("updateEnrollments", async (request) => { 39 const enrollments = request.enrollments ?? [] 40 if (enrollments.length === 0) { 41 return { message: new Void(), error: null } 42 } 43 enrollments.forEach(e => { 44 const enrollment = MockData.mockedEnrollments().enrollments.find(en => en.ID === e.ID) 45 if (!enrollment || e.status === undefined) { 46 return 47 } 48 enrollment.status = e.status 49 }) 50 return { message: new Void(), error: null } 51 }), 52 } 53 const mockedOvermind = initializeOvermind({}, api) 54 55 const updateEnrollmentTests: { desc: string, courseID: bigint, userID: bigint, want: Enrollment_UserStatus }[] = [ 56 // Refer to addLocalCourseStudent() in MockGRPCManager.ts for a list of available enrollments 57 { desc: "Pending student gets accepted", courseID: BigInt(2), userID: BigInt(2), want: Enrollment_UserStatus.STUDENT }, 58 { desc: "Demote teacher to student", courseID: BigInt(2), userID: BigInt(1), want: Enrollment_UserStatus.STUDENT }, 59 { desc: "Promote student to teacher", courseID: BigInt(1), userID: BigInt(2), want: Enrollment_UserStatus.TEACHER }, 60 ] 61 62 63 64 beforeAll(async () => { 65 // mock getEnrollmentsByCourse() to load enrollments into state 66 // Load enrollments into state before running tests 67 await mockedOvermind.actions.getEnrollmentsByCourse({ courseID: BigInt(2), statuses: [] }) 68 await mockedOvermind.actions.getEnrollmentsByCourse({ courseID: BigInt(1), statuses: [] }) 69 }) 70 71 test.each(updateEnrollmentTests)(`$desc`, async (test) => { 72 const enrollment = mockedOvermind.state.courseEnrollments[test.courseID.toString()].find(e => e.userID === test.userID) 73 if (!enrollment) { 74 throw new Error(`No enrollment found for user ${test.userID} in course ${test.courseID}`) 75 } 76 mockedOvermind.actions.setActiveCourse(test.courseID) 77 window.confirm = jest.fn(() => true) 78 await mockedOvermind.actions.updateEnrollment({ enrollment, status: test.want }) 79 expect(enrollment.status).toEqual(test.want) 80 }) 81 }) 82 83 describe("UpdateEnrollment in webpage", () => { 84 it("If status is teacher, button should display demote", () => { 85 const user = new User({ ID: BigInt(1), Name: "Test User", StudentID: "6583969706", Email: "test@gmail.com" }) 86 const enrollment = new Enrollment({ 87 ID: BigInt(2), 88 courseID: BigInt(1), 89 status: 3, 90 user, 91 slipDaysRemaining: 3, 92 lastActivityDate: Timestamp.fromDate(new Date(2022, 3, 10)), 93 totalApproved: BigInt(0), 94 }) 95 96 const mockedOvermind = createOvermindMock(config, (state) => { 97 state.self = user 98 state.activeCourse = BigInt(1) 99 state.courseEnrollments = { "1": [enrollment] } 100 }) 101 const history = createMemoryHistory() 102 history.push("/course/1/members") 103 104 render( 105 <Provider value={mockedOvermind}> 106 <Router history={history} > 107 <Route path="/course/:id/members" component={Members} /> 108 </Router> 109 </Provider> 110 ) 111 112 const editButton = screen.getByText("Edit") 113 editButton.click() 114 115 expect(screen.getByText("Demote")).toBeTruthy() 116 expect(screen.queryByText("Promote")).toBeFalsy() 117 }) 118 119 it("If status is student, button should display promote", () => { 120 const user = new User({ 121 ID: BigInt(1), 122 Name: "Test User", 123 StudentID: "6583969706", 124 Email: "test@gmail.com" 125 }) 126 const enrollment = new Enrollment({ 127 ID: BigInt(2), 128 courseID: BigInt(1), 129 status: 2, 130 user, 131 slipDaysRemaining: 3, 132 lastActivityDate: Timestamp.fromDate(new Date(2022, 3, 10)), 133 totalApproved: BigInt(0), 134 }) 135 const mockedOvermind = createOvermindMock(config, (state) => { 136 state.self = user 137 state.activeCourse = BigInt(1) 138 state.courseEnrollments = { "1": [enrollment] } 139 }) 140 const history = createMemoryHistory() 141 history.push("/course/1/members") 142 143 render( 144 <Provider value={mockedOvermind}> 145 <Router history={history} > 146 <Route path="/course/:id/members" component={Members} /> 147 </Router> 148 </Provider> 149 ) 150 151 const editButton = screen.getByText("Edit") 152 editButton.click() 153 154 expect(screen.getByText("Promote")).toBeTruthy() 155 expect(screen.queryByText("Demote")).toBeFalsy() 156 }) 157 })