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

Development: Add e2e tests for instructors assessing exams in the second round #9863

Merged
merged 5 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ <h4 jhiTranslate="artemisApp.assessmentDashboard.exerciseTable.title"></h4>
<ng-container class="col-lg-3 col-md-6 col-sm-6">
<jhi-second-correction-enable-button
class="me-1 mb-1"
data-testid="toggle-second-correction"
(ngModelChange)="toggleSecondCorrection(exercise.id!)"
[secondCorrectionEnabled]="exercise.secondCorrectionEnabled"
[togglingSecondCorrectionButton]="isTogglingSecondCorrection.get(exercise.id!)!"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
@if (exercise.isAtLeastInstructor && exam?.numberOfCorrectionRoundsInExam && exam?.numberOfCorrectionRoundsInExam! > 1 && isExamMode && !isTestRun) {
<div class="d-inline-block">
<jhi-second-correction-enable-button
data-testid="toggle-second-correction"
(ngModelChange)="toggleSecondCorrection()"
[secondCorrectionEnabled]="secondCorrectionEnabled"
[togglingSecondCorrectionButton]="togglingSecondCorrectionButton"
Expand Down
47 changes: 26 additions & 21 deletions src/test/playwright/e2e/exam/ExamAssessment.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ test.beforeAll('Create course', async ({ browser }) => {

test.describe('Exam assessment', () => {
test.describe.configure({ mode: 'serial' });
let programmingAssessmentSuccessful = false;
let modelingAssessmentSuccessful = false;
let textAssessmentSuccessful = false;

test.describe.serial('Programming exercise assessment', { tag: '@sequential' }, () => {
test.beforeAll('Prepare exam', async ({ browser }) => {
Expand All @@ -76,13 +73,10 @@ test.describe('Exam assessment', () => {
await examAssessment.submit();
await login(studentOne, `/courses/${course.id}/exams/${exam.id}`);
await examParticipation.checkResultScore('66.2%');
programmingAssessmentSuccessful = true;
});

test('Complaints about programming exercises assessment', async ({ examAssessment, page, studentAssessment, examManagement, courseAssessment, exerciseAssessment }) => {
if (programmingAssessmentSuccessful) {
await handleComplaint(course, exam, false, ExerciseType.PROGRAMMING, page, studentAssessment, examManagement, examAssessment, courseAssessment, exerciseAssessment);
}
await handleComplaint(course, exam, false, ExerciseType.PROGRAMMING, page, studentAssessment, examManagement, examAssessment, courseAssessment, exerciseAssessment);
});
});

Expand Down Expand Up @@ -117,21 +111,18 @@ test.describe('Exam assessment', () => {
await login(studentOne, `/courses/${course.id}/exams/${exam.id}`);

await examParticipation.checkResultScore('40%');
modelingAssessmentSuccessful = true;
});

test('Complaints about modeling exercises assessment', async ({ examAssessment, page, studentAssessment, examManagement, courseAssessment, exerciseAssessment }) => {
if (modelingAssessmentSuccessful) {
await handleComplaint(course, exam, true, ExerciseType.MODELING, page, studentAssessment, examManagement, examAssessment, courseAssessment, exerciseAssessment);
}
await handleComplaint(course, exam, true, ExerciseType.MODELING, page, studentAssessment, examManagement, examAssessment, courseAssessment, exerciseAssessment);
});
});

test.describe.serial('Text exercise assessment', { tag: '@slow' }, () => {
test.beforeAll('Prepare exam', async ({ browser }) => {
examEnd = dayjs().add(40, 'seconds');
examEnd = dayjs().add(20, 'seconds');
const page = await newBrowserPage(browser);
await prepareExam(course, examEnd, ExerciseType.TEXT, page);
await prepareExam(course, examEnd, ExerciseType.TEXT, page, 2);
});

test('Assess a text exercise submission', async ({ login, examManagement, examAssessment, examParticipation, courseAssessment, exerciseAssessment }) => {
Expand All @@ -144,13 +135,20 @@ test.describe('Exam assessment', () => {
expect(response.status()).toBe(200);
await login(studentOne, `/courses/${course.id}/exams/${exam.id}`);
await examParticipation.checkResultScore('70%');
textAssessmentSuccessful = true;
});

test('Complaints about text exercises assessment', async ({ examAssessment, page, studentAssessment, examManagement, courseAssessment, exerciseAssessment }) => {
if (textAssessmentSuccessful) {
await handleComplaint(course, exam, false, ExerciseType.TEXT, page, studentAssessment, examManagement, examAssessment, courseAssessment, exerciseAssessment);
}
await handleComplaint(course, exam, true, ExerciseType.TEXT, page, studentAssessment, examManagement, examAssessment, courseAssessment, exerciseAssessment);
});

test('Instructor makes a second round of assessment', async ({ login, examManagement, examAssessment, examParticipation, courseAssessment, exerciseAssessment }) => {
await login(instructor);
await startAssessing(course.id!, exam.id!, 60000, examManagement, courseAssessment, exerciseAssessment, true, false);
await examAssessment.fillFeedback(9, 'Great job');
const response = await examAssessment.submitTextAssessment();
expect(response.status()).toBe(200);
await login(studentOne, `/courses/${course.id}/exams/${exam.id}`);
await examParticipation.checkResultScore('90%');
});
});

Expand Down Expand Up @@ -296,7 +294,7 @@ test.afterAll('Delete course', async ({ browser }) => {
await courseManagementAPIRequests.deleteCourse(course, admin);
});

export async function prepareExam(course: Course, end: dayjs.Dayjs, exerciseType: ExerciseType, page: Page): Promise<Exam> {
export async function prepareExam(course: Course, end: dayjs.Dayjs, exerciseType: ExerciseType, page: Page, numberOfCorrectionRounds: number = 1): Promise<Exam> {
const examAPIRequests = new ExamAPIRequests(page);
const exerciseAPIRequests = new ExerciseAPIRequests(page);
const examExerciseGroupCreation = new ExamExerciseGroupCreationPage(page, examAPIRequests, exerciseAPIRequests);
Expand Down Expand Up @@ -326,7 +324,7 @@ export async function prepareExam(course: Course, end: dayjs.Dayjs, exerciseType
course,
startDate: dayjs(),
endDate: end,
numberOfCorrectionRoundsInExam: 1,
numberOfCorrectionRoundsInExam: numberOfCorrectionRounds,
examStudentReviewStart: resultDate,
examStudentReviewEnd: resultDate.add(1, 'minute'),
publishResultsDate: resultDate,
Expand Down Expand Up @@ -379,10 +377,17 @@ async function startAssessing(
examManagement: ExamManagementPage,
courseAssessment: CourseAssessmentDashboardPage,
exerciseAssessment: ExerciseAssessmentDashboardPage,
toggleSecondRound: boolean = false,
isFirstTimeAssessing: boolean = true,
) {
await examManagement.openAssessmentDashboard(courseID, examID, timeout);
await courseAssessment.clickExerciseDashboardButton();
await exerciseAssessment.clickHaveReadInstructionsButton();
if (toggleSecondRound) {
await exerciseAssessment.toggleSecondCorrectionRound();
}
if (isFirstTimeAssessing) {
await exerciseAssessment.clickHaveReadInstructionsButton();
}
await exerciseAssessment.clickStartNewAssessment();
exerciseAssessment.getLockedMessage();
}
Expand Down Expand Up @@ -421,7 +426,7 @@ async function handleComplaint(
} else {
await examAssessment.acceptComplaint(complaintResponseText, true, exerciseType);
}
if (exerciseType == ExerciseType.MODELING) {
if (exerciseType == ExerciseType.MODELING || reject) {
await examAssessment.checkComplaintMessage('Response to complaint has been submitted');
} else {
await examAssessment.checkComplaintMessage('The assessment was updated successfully.');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export abstract class AbstractExerciseAssessmentPage {

async addNewFeedback(points: number, feedback?: string) {
await this.page.locator('.add-unreferenced-feedback').click();
await this.fillFeedback(points, feedback);
}

async fillFeedback(points: number, feedback?: string) {
const unreferencedFeedback = this.page.locator('.unreferenced-feedback-detail');
await unreferencedFeedback.locator('#feedback-points').clear();
await unreferencedFeedback.locator('#feedback-points').fill(points.toString());
Expand Down Expand Up @@ -61,7 +65,11 @@ export abstract class AbstractExerciseAssessmentPage {
responsePromise = this.page.waitForResponse(`${BASE_API}/programming-submissions/*/assessment-after-complaint`);
break;
case ExerciseType.TEXT:
responsePromise = this.page.waitForResponse(`${BASE_API}/participations/*/submissions/*/text-assessment-after-complaint`);
if (accept) {
responsePromise = this.page.waitForResponse(`${BASE_API}/participations/*/submissions/*/text-assessment-after-complaint`);
} else {
responsePromise = this.page.waitForResponse(`${BASE_API}/complaints/*/response`);
}
break;
case ExerciseType.MODELING:
responsePromise = this.page.waitForResponse(`${BASE_API}/complaints/*/response`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export class ExerciseAssessmentDashboardPage {
await this.page.click('#participate-in-assessment');
}

async clickStartNewAssessment() {
const startAssessingButton = this.page.locator('#start-new-assessment');
async clickStartNewAssessment(assessmentRound: number = 1) {
const startAssessingButton = this.page.locator('#start-new-assessment').nth(assessmentRound - 1);
await Commands.reloadUntilFound(this.page, startAssessingButton);
await startAssessingButton.click();
}
Expand All @@ -38,4 +38,8 @@ export class ExerciseAssessmentDashboardPage {
async checkComplaintText(complaintText: string) {
await expect(this.getComplaintText()).toHaveValue(complaintText);
}

async toggleSecondCorrectionRound() {
await this.page.getByTestId('toggle-second-correction').click();
}
}
Loading