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  })