diff --git a/src/main/webapp/app/exam/participate/summary/exercises/header/exam-result-summary-exercise-card-header.component.html b/src/main/webapp/app/exam/participate/summary/exercises/header/exam-result-summary-exercise-card-header.component.html
index f7e47f016f5a..74dfce8f5638 100644
--- a/src/main/webapp/app/exam/participate/summary/exercises/header/exam-result-summary-exercise-card-header.component.html
+++ b/src/main/webapp/app/exam/participate/summary/exercises/header/exam-result-summary-exercise-card-header.component.html
@@ -17,7 +17,7 @@
}
@if (exerciseInfo?.achievedPercentage !== undefined) {
- {{ exerciseInfo!.achievedPercentage }}%
+ {{ exerciseInfo!.achievedPercentage }}%
}
diff --git a/src/test/playwright/e2e/exam/ExamResults.spec.ts b/src/test/playwright/e2e/exam/ExamResults.spec.ts
index 42ebc5e7bd53..3d772d9cfb41 100644
--- a/src/test/playwright/e2e/exam/ExamResults.spec.ts
+++ b/src/test/playwright/e2e/exam/ExamResults.spec.ts
@@ -1,200 +1,180 @@
import { test } from '../../support/fixtures';
import { Exam } from 'app/entities/exam.model';
import { Commands } from '../../support/commands';
-import { admin, instructor, studentFour, studentOne, studentThree, studentTwo, tutor } from '../../support/users';
+import { admin, instructor, studentOne, tutor } from '../../support/users';
import { Course } from 'app/entities/course.model';
-import dayjs from 'dayjs';
+import dayjs, { Dayjs } from 'dayjs';
import { generateUUID } from '../../support/utils';
import { Exercise, ExerciseType } from '../../support/constants';
import { ExamManagementPage } from '../../support/pageobjects/exam/ExamManagementPage';
import { CourseAssessmentDashboardPage } from '../../support/pageobjects/assessment/CourseAssessmentDashboardPage';
import { ExerciseAssessmentDashboardPage } from '../../support/pageobjects/assessment/ExerciseAssessmentDashboardPage';
-import { ExamAssessmentPage } from '../../support/pageobjects/assessment/ExamAssessmentPage';
import javaPartiallySuccessfulSubmission from '../../fixtures/exercise/programming/java/partially_successful/submission.json';
-import { ExamAPIRequests } from '../../support/requests/ExamAPIRequests';
-import { ExamExerciseGroupCreationPage } from '../../support/pageobjects/exam/ExamExerciseGroupCreationPage';
-import { ExerciseAPIRequests } from '../../support/requests/ExerciseAPIRequests';
-import { ExamParticipationPage } from '../../support/pageobjects/exam/ExamParticipationPage';
import { CourseManagementAPIRequests } from '../../support/requests/CourseManagementAPIRequests';
-import { ExamNavigationBar } from '../../support/pageobjects/exam/ExamNavigationBar';
-import { CourseOverviewPage } from '../../support/pageobjects/course/CourseOverviewPage';
-import { ExamStartEndPage } from '../../support/pageobjects/exam/ExamStartEndPage';
-import { CoursesPage } from '../../support/pageobjects/course/CoursesPage';
-import { ModelingEditor } from '../../support/pageobjects/exercises/modeling/ModelingEditor';
-import { OnlineEditorPage } from '../../support/pageobjects/exercises/programming/OnlineEditorPage';
-import { MultipleChoiceQuiz } from '../../support/pageobjects/exercises/quiz/MultipleChoiceQuiz';
-import { TextEditorPage } from '../../support/pageobjects/exercises/text/TextEditorPage';
-import { ModelingExerciseAssessmentEditor } from '../../support/pageobjects/assessment/ModelingExerciseAssessmentEditor';
import { ProgrammingExerciseTaskStatus } from '../../support/pageobjects/exam/ExamResultsPage';
-
-test.describe.configure({ mode: 'default' });
+import { Page } from '@playwright/test';
test.describe('Exam Results', () => {
let course: Course;
- test.beforeAll('Create course', async ({ browser }) => {
+ test.beforeEach('Create course', async ({ browser }) => {
const page = await browser.newPage();
const courseManagementAPIRequests = new CourseManagementAPIRequests(page);
await Commands.login(page, admin);
course = await courseManagementAPIRequests.createCourse({ customizeGroups: true });
await courseManagementAPIRequests.addStudentToCourse(course, studentOne);
- await courseManagementAPIRequests.addStudentToCourse(course, studentTwo);
- await courseManagementAPIRequests.addStudentToCourse(course, studentThree);
- await courseManagementAPIRequests.addStudentToCourse(course, studentFour);
await courseManagementAPIRequests.addTutorToCourse(course, tutor);
await courseManagementAPIRequests.addInstructorToCourse(course, instructor);
});
+ const testCases = [
+ { exerciseType: ExerciseType.TEXT, resultScore: '70%' },
+ { exerciseType: ExerciseType.PROGRAMMING, resultScore: '46.2%' },
+ { exerciseType: ExerciseType.QUIZ, resultScore: '50%' },
+ { exerciseType: ExerciseType.MODELING, resultScore: '40%' },
+ ];
+
test.describe('Check exam exercise results', () => {
- let exam: Exam;
- let exerciseArray: Array = [];
-
- test.beforeAll('Prepare exam and assess a student submission', async ({ browser }) => {
- const page = await browser.newPage();
- const examAPIRequests = new ExamAPIRequests(page);
- const exerciseAPIRequests = new ExerciseAPIRequests(page);
- const examExerciseGroupCreation = new ExamExerciseGroupCreationPage(page, examAPIRequests, exerciseAPIRequests);
-
- await Commands.login(page, admin);
- const endDate = dayjs().add(1, 'minutes').add(30, 'seconds');
- const examConfig = {
- course,
- title: 'exam' + generateUUID(),
- visibleDate: dayjs().subtract(3, 'minutes'),
- startDate: dayjs().subtract(2, 'minutes'),
- endDate: endDate,
- publishResultsDate: endDate.add(1, 'seconds'),
- examMaxPoints: 40,
- numberOfExercisesInExam: 4,
- };
- exam = await examAPIRequests.createExam(examConfig);
- const textExercise = await examExerciseGroupCreation.addGroupWithExercise(exam, ExerciseType.TEXT, { textFixture: 'loremIpsum.txt' });
- const programmingExercise = await examExerciseGroupCreation.addGroupWithExercise(exam, ExerciseType.PROGRAMMING, { submission: javaPartiallySuccessfulSubmission });
- const quizExercise = await examExerciseGroupCreation.addGroupWithExercise(exam, ExerciseType.QUIZ, { quizExerciseID: 0 });
- const modelingExercise = await examExerciseGroupCreation.addGroupWithExercise(exam, ExerciseType.MODELING);
- exerciseArray = [textExercise, programmingExercise, quizExercise, modelingExercise];
-
- await examAPIRequests.registerStudentForExam(exam, studentOne);
- await examAPIRequests.generateMissingIndividualExams(exam);
- await examAPIRequests.prepareExerciseStartForExam(exam);
- const courseList = new CoursesPage(page);
- const courseOverview = new CourseOverviewPage(page);
-
- const examParticipation = new ExamParticipationPage(
- courseList,
- courseOverview,
- new ExamNavigationBar(page),
- new ExamStartEndPage(page),
- new ModelingEditor(page),
- new OnlineEditorPage(page, courseList, courseOverview),
- new MultipleChoiceQuiz(page),
- new TextEditorPage(page),
- page,
- );
-
- await examParticipation.startParticipation(studentOne, course, exam);
-
- const examNavigation = new ExamNavigationBar(page);
- const examStartEnd = new ExamStartEndPage(page);
-
- for (let j = 0; j < exerciseArray.length; j++) {
- const exercise = exerciseArray[j];
- await examNavigation.openExerciseAtIndex(j);
- await examParticipation.makeSubmission(exercise.id!, exercise.type!, exercise.additionalData);
- }
-
- await examParticipation.handInEarly();
- await examStartEnd.pressShowSummary();
- });
-
- test.beforeAll('Assess student submissions', async ({ browser }) => {
- const page = await browser.newPage();
- const examManagement = new ExamManagementPage(page);
- const examAssessment = new ExamAssessmentPage(page);
- const courseAssessment = new CourseAssessmentDashboardPage(page);
- const exerciseAssessment = new ExerciseAssessmentDashboardPage(page);
- const exerciseAPIRequests = new ExerciseAPIRequests(page);
-
- await Commands.login(page, tutor);
- await startAssessing(course.id!, exam.id!, 0, 60000, examManagement, courseAssessment, exerciseAssessment);
- await examAssessment.addNewFeedback(7, 'Good job');
- await examAssessment.submitTextAssessment();
- await startAssessing(course.id!, exam.id!, 1, 60000, examManagement, courseAssessment, exerciseAssessment);
-
- const modelingExerciseAssessment = new ModelingExerciseAssessmentEditor(page);
- await modelingExerciseAssessment.addNewFeedback(5, 'Good');
- await modelingExerciseAssessment.openAssessmentForComponent(0);
- await modelingExerciseAssessment.assessComponent(-1, 'Wrong');
- await modelingExerciseAssessment.clickNextAssessment();
- await modelingExerciseAssessment.assessComponent(0, 'Neutral');
- await modelingExerciseAssessment.clickNextAssessment();
- await examAssessment.submitModelingAssessment();
- await Commands.login(page, instructor);
- await exerciseAPIRequests.evaluateExamQuizzes(exam);
- });
-
- test('Check exam result overview', async ({ page, login, examAPIRequests, examResultsPage }) => {
- await login(studentOne);
- await page.goto(`/courses/${course.id}/exams/${exam.id}`);
- const gradeSummary = await examAPIRequests.getGradeSummary(exam);
- await examResultsPage.checkGradeSummary(gradeSummary);
- });
-
- test('Check exam text exercise results', async ({ page, login, examParticipation, examResultsPage }) => {
- await login(studentOne);
- await page.goto(`/courses/${course.id}/exams/${exam.id}`);
- const exercise = exerciseArray[0];
- await examParticipation.checkResultScore('70%', exercise.id!);
- await examResultsPage.checkTextExerciseContent(exercise.id!, exercise.additionalData!.textFixture!);
- await examResultsPage.checkAdditionalFeedback(exercise.id!, 7, 'Good job');
- });
-
- test('Check exam programming exercise results', async ({ page, login, examParticipation, examResultsPage }) => {
- test.fixme();
- await login(studentOne);
- await page.goto(`/courses/${course.id}/exams/${exam.id}`);
- const exercise = exerciseArray[1];
- await examParticipation.checkResultScore('46.2%', exercise.id!);
- await examResultsPage.checkProgrammingExerciseAssessments(exercise.id!, 'Wrong', 7);
- await examResultsPage.checkProgrammingExerciseAssessments(exercise.id!, 'Correct', 6);
- const taskStatuses: ProgrammingExerciseTaskStatus[] = [
- ProgrammingExerciseTaskStatus.SUCCESS,
- ProgrammingExerciseTaskStatus.SUCCESS,
- ProgrammingExerciseTaskStatus.SUCCESS,
- ProgrammingExerciseTaskStatus.FAILURE,
- ProgrammingExerciseTaskStatus.FAILURE,
- ProgrammingExerciseTaskStatus.FAILURE,
- ProgrammingExerciseTaskStatus.FAILURE,
- ];
- await examResultsPage.checkProgrammingExerciseTasks(exercise.id!, taskStatuses);
- });
-
- test('Check exam quiz exercise results', async ({ page, login, examParticipation, examResultsPage }) => {
- await login(studentOne);
- await page.goto(`/courses/${course.id}/exams/${exam.id}`);
- const exercise = exerciseArray[2];
- await examParticipation.checkResultScore('50%', exercise.id!);
- await examResultsPage.checkQuizExerciseScore(exercise.id!, 5, 10);
- const studentAnswers = [true, false, true, false];
- const correctAnswers = [true, true, false, false];
- await examResultsPage.checkQuizExerciseAnswers(exercise.id!, studentAnswers, correctAnswers);
- });
-
- test('Check exam modelling exercise results', async ({ page, login, examParticipation, examResultsPage }) => {
- await login(studentOne);
- await page.goto(`/courses/${course.id}/exams/${exam.id}`);
- const exercise = exerciseArray[3];
- await examParticipation.checkResultScore('40%', exercise.id!);
- await examResultsPage.checkAdditionalFeedback(exercise.id!, 5, 'Good');
- await examResultsPage.checkModellingExerciseAssessment(exercise.id!, 'class Class', 'Wrong', -1);
- await examResultsPage.checkModellingExerciseAssessment(exercise.id!, 'abstract class Abstract', 'Neutral', 0);
- });
+ for (const testCase of testCases) {
+ let exam: Exam;
+ let examEndDate: Dayjs;
+ let exercise: Exercise;
+ const exerciseTypeString = testCase.exerciseType.toString().toLowerCase();
+
+ test.describe(`Check exam results for ${exerciseTypeString} exercise`, () => {
+ test.beforeEach('Prepare exam', async ({ login, examAPIRequests }) => {
+ await login(admin);
+
+ if (testCase.exerciseType === ExerciseType.PROGRAMMING) {
+ examEndDate = dayjs().add(1, 'minutes').add(30, 'seconds');
+ } else {
+ examEndDate = dayjs().add(30, 'seconds');
+ }
+ const examConfig = {
+ course,
+ title: 'exam' + generateUUID(),
+ visibleDate: dayjs().subtract(3, 'minutes'),
+ startDate: dayjs().subtract(2, 'minutes'),
+ endDate: examEndDate,
+ publishResultsDate: examEndDate.add(1, 'seconds'),
+ examMaxPoints: 10,
+ numberOfExercisesInExam: 1,
+ };
+ exam = await examAPIRequests.createExam(examConfig);
+ });
+
+ test.beforeEach('Add exercise to exam', async ({ login, examAPIRequests, examExerciseGroupCreation }) => {
+ await login(admin);
+ let additionalData: any;
+ switch (testCase.exerciseType) {
+ case ExerciseType.TEXT:
+ additionalData = { textFixture: 'loremIpsum.txt' };
+ break;
+ case ExerciseType.PROGRAMMING:
+ additionalData = { submission: javaPartiallySuccessfulSubmission };
+ break;
+ case ExerciseType.QUIZ:
+ additionalData = { quizExerciseID: 0 };
+ break;
+ }
+ exercise = await examExerciseGroupCreation.addGroupWithExercise(exam, testCase.exerciseType, additionalData);
+ await examAPIRequests.registerStudentForExam(exam, studentOne);
+ await examAPIRequests.generateMissingIndividualExams(exam);
+ await examAPIRequests.prepareExerciseStartForExam(exam);
+ });
+
+ test.beforeEach('Participate in exam', async ({ login, examParticipation, examNavigation, examStartEnd }) => {
+ await login(admin);
+ await examParticipation.startParticipation(studentOne, course, exam);
+ await examNavigation.openExerciseAtIndex(0);
+ await examParticipation.makeSubmission(exercise.id!, exercise.type!, exercise.additionalData);
+ await examParticipation.handInEarly();
+ await examStartEnd.pressShowSummary();
+ });
+
+ test.beforeEach(
+ 'Assess student submission',
+ async ({ page, login, examManagement, examAssessment, courseAssessment, exerciseAssessment, modelingExerciseAssessment, exerciseAPIRequests }) => {
+ switch (testCase.exerciseType) {
+ case ExerciseType.TEXT:
+ await login(tutor);
+ await startAssessing(course.id!, exam.id!, 0, 60000, examManagement, courseAssessment, exerciseAssessment);
+ await examAssessment.addNewFeedback(7, 'Good job');
+ await examAssessment.submitTextAssessment();
+ break;
+ case ExerciseType.MODELING:
+ await login(tutor);
+ await startAssessing(course.id!, exam.id!, 0, 60000, examManagement, courseAssessment, exerciseAssessment);
+ await modelingExerciseAssessment.addNewFeedback(5, 'Good');
+ await modelingExerciseAssessment.openAssessmentForComponent(0);
+ await modelingExerciseAssessment.assessComponent(-1, 'Wrong');
+ await modelingExerciseAssessment.clickNextAssessment();
+ await modelingExerciseAssessment.assessComponent(0, 'Neutral');
+ await modelingExerciseAssessment.clickNextAssessment();
+ await examAssessment.submitModelingAssessment();
+ break;
+ case ExerciseType.QUIZ:
+ await login(instructor);
+ await waitForExamEnd(examEndDate, page);
+ await exerciseAPIRequests.evaluateExamQuizzes(exam);
+ break;
+ }
+ },
+ );
+
+ test(`Check exam ${exerciseTypeString} exercise results`, async ({ page, login, examParticipation, examResultsPage }) => {
+ await login(studentOne);
+ await waitForExamEnd(examEndDate, page);
+ await page.goto(`/courses/${course.id}/exams/${exam.id}`);
+ await examParticipation.checkResultScore(testCase.resultScore, exercise.id!);
+
+ switch (testCase.exerciseType) {
+ case ExerciseType.TEXT:
+ await examResultsPage.checkTextExerciseContent(exercise.id!, exercise.additionalData!.textFixture!);
+ await examResultsPage.checkAdditionalFeedback(exercise.id!, 7, 'Good job');
+ break;
+ case ExerciseType.PROGRAMMING:
+ await examResultsPage.checkProgrammingExerciseAssessments(exercise.id!, 'Wrong', 7);
+ await examResultsPage.checkProgrammingExerciseAssessments(exercise.id!, 'Correct', 6);
+ const taskStatuses: ProgrammingExerciseTaskStatus[] = [
+ ProgrammingExerciseTaskStatus.SUCCESS,
+ ProgrammingExerciseTaskStatus.SUCCESS,
+ ProgrammingExerciseTaskStatus.SUCCESS,
+ ProgrammingExerciseTaskStatus.FAILURE,
+ ProgrammingExerciseTaskStatus.FAILURE,
+ ProgrammingExerciseTaskStatus.FAILURE,
+ ProgrammingExerciseTaskStatus.FAILURE,
+ ];
+ await examResultsPage.checkProgrammingExerciseTasks(exercise.id!, taskStatuses);
+ break;
+ case ExerciseType.QUIZ:
+ await examResultsPage.checkQuizExerciseScore(exercise.id!, 5, 10);
+ const studentAnswers = [true, false, true, false];
+ const correctAnswers = [true, true, false, false];
+ await examResultsPage.checkQuizExerciseAnswers(exercise.id!, studentAnswers, correctAnswers);
+ break;
+ case ExerciseType.MODELING:
+ await examResultsPage.checkAdditionalFeedback(exercise.id!, 5, 'Good');
+ await examResultsPage.checkModellingExerciseAssessment(exercise.id!, 'class Class', 'Wrong', -1);
+ await examResultsPage.checkModellingExerciseAssessment(exercise.id!, 'abstract class Abstract', 'Neutral', 0);
+ break;
+ }
+ });
+
+ if (testCase.exerciseType === ExerciseType.TEXT) {
+ test('Check exam result overview', async ({ page, login, examAPIRequests, examResultsPage }) => {
+ await login(studentOne);
+ await page.goto(`/courses/${course.id}/exams/${exam.id}`);
+ const gradeSummary = await examAPIRequests.getGradeSummary(exam);
+ await examResultsPage.checkGradeSummary(gradeSummary);
+ });
+ }
+ });
+ }
});
- test.afterAll('Delete course', async ({ browser }) => {
- const page = await browser.newPage();
- const courseManagementAPIRequests = new CourseManagementAPIRequests(page);
+ test.afterEach('Delete course', async ({ courseManagementAPIRequests }) => {
await courseManagementAPIRequests.deleteCourse(course, admin);
});
});
@@ -214,3 +194,10 @@ async function startAssessing(
await exerciseAssessment.clickStartNewAssessment();
exerciseAssessment.getLockedMessage();
}
+
+async function waitForExamEnd(examEndDate: dayjs.Dayjs, page: Page) {
+ if (examEndDate > dayjs()) {
+ const timeToWait = examEndDate.diff(dayjs());
+ await page.waitForTimeout(timeToWait);
+ }
+}
diff --git a/src/test/playwright/e2e/exercise/programming/ProgrammingExerciseParticipation.spec.ts b/src/test/playwright/e2e/exercise/programming/ProgrammingExerciseParticipation.spec.ts
index ea6c63748e8e..e35048615d49 100644
--- a/src/test/playwright/e2e/exercise/programming/ProgrammingExerciseParticipation.spec.ts
+++ b/src/test/playwright/e2e/exercise/programming/ProgrammingExerciseParticipation.spec.ts
@@ -15,7 +15,7 @@ import { Fixtures } from '../../../fixtures/fixtures';
import { createFileWithContent } from '../../../support/utils';
import { ProgrammingExerciseSubmission } from '../../../support/pageobjects/exercises/programming/OnlineEditorPage';
import cAllSuccessful from '../../../fixtures/exercise/programming/c/all_successful/submission.json';
-import { UserCredentials, admin, instructor, studentFour, studentOne, studentThree, studentTwo, tutor } from '../../../support/users';
+import { UserCredentials, admin, instructor, studentFour, studentOne, studentTwo, tutor } from '../../../support/users';
import { Team } from 'app/entities/team.model';
import { ProgrammingExerciseOverviewPage } from '../../../support/pageobjects/exercises/programming/ProgrammingExerciseOverviewPage';
import { Participation } from 'app/entities/participation/participation.model';
@@ -27,6 +27,7 @@ test.describe('Programming exercise participation', () => {
await login(admin, '/');
course = await courseManagementAPIRequests.createCourse({ customizeGroups: true });
await courseManagementAPIRequests.addStudentToCourse(course, studentOne);
+ await courseManagementAPIRequests.addStudentToCourse(course, studentTwo);
});
const testCases = [
@@ -90,7 +91,6 @@ test.describe('Programming exercise participation', () => {
const submissions = [
{ student: studentOne, submission: javaBuildErrorSubmission, commitMessage: 'Initial commit' },
{ student: studentTwo, submission: javaPartiallySuccessfulSubmission, commitMessage: 'Initial implementation' },
- { student: studentThree, submission: javaAllSuccessfulSubmission, commitMessage: 'Implemented all tasks' },
];
test.beforeEach('Create team programming exercise', async ({ login, exerciseAPIRequests }) => {
@@ -107,7 +107,7 @@ test.describe('Programming exercise participation', () => {
test.beforeEach('Create an exercise team', async ({ login, userManagementAPIRequests, exerciseAPIRequests }) => {
await login(admin);
const students = await Promise.all(
- [studentOne, studentTwo, studentThree].map(async (student) => {
+ [studentOne, studentTwo].map(async (student) => {
const response = await userManagementAPIRequests.getUser(student.username);
return response.json();
}),
@@ -182,7 +182,7 @@ test.describe('Programming exercise participation', () => {
});
test.describe('Check team participation', () => {
- test.beforeEach('Each team member makes a submission', async ({ login, exerciseAPIRequests }) => {
+ test.beforeEach('Each team member makes a submission', async ({ login, waitForExerciseBuildToFinish, exerciseAPIRequests }) => {
for (const { student, submission } of submissions) {
await login(student);
const response = await exerciseAPIRequests.startExerciseParticipation(exercise.id!);
@@ -192,6 +192,7 @@ test.describe('Programming exercise participation', () => {
await exerciseAPIRequests.createProgrammingExerciseFile(participation.id!, filename);
}
await exerciseAPIRequests.makeProgrammingExerciseSubmission(participation.id!, submission);
+ await waitForExerciseBuildToFinish(exercise.id!);
}
});
@@ -203,8 +204,6 @@ test.describe('Programming exercise participation', () => {
programmingExerciseRepository,
programmingExerciseParticipations,
}) => {
- // Marked test as slow as there are 3 builds being awaited
- test.slow();
await login(instructor);
await navigationBar.openCourseManagement();
await courseManagement.openExercisesOfCourse(course.id!);
diff --git a/src/test/playwright/support/commands.ts b/src/test/playwright/support/commands.ts
index 9b42d25c8060..cb65a5992985 100644
--- a/src/test/playwright/support/commands.ts
+++ b/src/test/playwright/support/commands.ts
@@ -1,6 +1,8 @@
import { UserCredentials } from './users';
import { BASE_API } from './constants';
import { Locator, Page, expect } from '@playwright/test';
+import { StudentParticipation } from 'app/entities/participation/student-participation.model';
+import { ExerciseAPIRequests } from './requests/ExerciseAPIRequests';
/**
* A class that encapsulates static helper command methods.
@@ -62,4 +64,33 @@ export class Commands {
throw new Error(`Timed out finding an element matching the "${locator}" locator`);
};
+
+ /**
+ * Waits for the build of an exercise to finish.
+ * Throws an error if the build does not finish within the timeout.
+ * @param page - Playwright page object.
+ * @param exerciseAPIRequests - ExerciseAPIRequests object.
+ * @param exerciseId - ID of the exercise to wait for.
+ * @param interval - Interval in milliseconds between checks for the build to finish.
+ * @param timeout - Timeout in milliseconds to wait for the build to finish.
+ */
+ static waitForExerciseBuildToFinish = async (page: Page, exerciseAPIRequests: ExerciseAPIRequests, exerciseId: number, interval: number = 2000, timeout: number = 60000) => {
+ let exerciseParticipation: StudentParticipation;
+ const startTime = Date.now();
+
+ const numberOfBuildResults = (await exerciseAPIRequests.getExerciseParticipation(exerciseId)).results?.length;
+ console.log('Waiting for build of an exercise to finish...');
+
+ while (Date.now() - startTime < timeout) {
+ exerciseParticipation = await exerciseAPIRequests.getExerciseParticipation(exerciseId);
+
+ if (exerciseParticipation.results && exerciseParticipation.results.length > (numberOfBuildResults ?? 0)) {
+ return exerciseParticipation;
+ }
+
+ await new Promise((resolve) => setTimeout(resolve, interval));
+ }
+
+ throw new Error('Timed out while waiting for build to finish.');
+ };
}
diff --git a/src/test/playwright/support/fixtures.ts b/src/test/playwright/support/fixtures.ts
index efdfb8aaff49..dbf28d32cc37 100644
--- a/src/test/playwright/support/fixtures.ts
+++ b/src/test/playwright/support/fixtures.ts
@@ -73,6 +73,7 @@ import { ExamParticipationActions } from './pageobjects/exam/ExamParticipationAc
*/
export type ArtemisCommands = {
login: (credentials: UserCredentials, url?: string) => Promise;
+ waitForExerciseBuildToFinish: (exerciseId: number, interval?: number, timeout?: number) => Promise;
};
export type ArtemisPageObjects = {
@@ -159,6 +160,11 @@ export const test = base.extend {
+ await use(async (exerciseId: number, interval?, timeout?) => {
+ await Commands.waitForExerciseBuildToFinish(page, exerciseAPIRequests, exerciseId, interval, timeout);
+ });
+ },
navigationBar: async ({ page }, use) => {
await use(new NavigationBar(page));
},
diff --git a/src/test/playwright/support/pageobjects/exam/ExamParticipationActions.ts b/src/test/playwright/support/pageobjects/exam/ExamParticipationActions.ts
index ab7616f92a5b..a7be0510b65a 100644
--- a/src/test/playwright/support/pageobjects/exam/ExamParticipationActions.ts
+++ b/src/test/playwright/support/pageobjects/exam/ExamParticipationActions.ts
@@ -30,8 +30,8 @@ export class ExamParticipationActions {
async getResultScore(exerciseID?: number) {
const parentComponent = exerciseID ? getExercise(this.page, exerciseID) : this.page;
- const resultScoreLocator = parentComponent.locator('#exercise-result-score');
- await Commands.reloadUntilFound(this.page, resultScoreLocator);
+ const resultScoreLocator = parentComponent.getByTestId('achieved-percentage');
+ await Commands.reloadUntilFound(this.page, resultScoreLocator, 4000, 60000);
return resultScoreLocator;
}
diff --git a/src/test/playwright/support/pageobjects/exam/ExamResultsPage.ts b/src/test/playwright/support/pageobjects/exam/ExamResultsPage.ts
index 77a78e007fb6..71b2bc814a33 100644
--- a/src/test/playwright/support/pageobjects/exam/ExamResultsPage.ts
+++ b/src/test/playwright/support/pageobjects/exam/ExamResultsPage.ts
@@ -19,12 +19,10 @@ export class ExamResultsPage {
const achievedPoints = Math.floor(exerciseResult.achievedPoints).toString();
const achievablePoints = Math.floor(exerciseResult.maxScore).toString();
const achievedPercentage = exerciseResult.achievedScore.toString();
- const bonusPoints = Math.floor(exercise.bonusPoints).toString();
await expect(exerciseRow.locator('td').nth(1).getByText(achievedPoints)).toBeVisible();
await expect(exerciseRow.locator('td').nth(2).getByText(achievablePoints)).toBeVisible();
await expect(exerciseRow.locator('td').nth(3).getByText(`${achievedPercentage} %`)).toBeVisible();
- await expect(exerciseRow.locator('td').nth(4).getByText(bonusPoints)).toBeVisible();
}
}
diff --git a/src/test/playwright/support/pageobjects/exercises/ExerciseResultPage.ts b/src/test/playwright/support/pageobjects/exercises/ExerciseResultPage.ts
index dc7ba5102921..b662a1adb57f 100644
--- a/src/test/playwright/support/pageobjects/exercises/ExerciseResultPage.ts
+++ b/src/test/playwright/support/pageobjects/exercises/ExerciseResultPage.ts
@@ -26,7 +26,7 @@ export class ExerciseResultPage {
}
async shouldShowScore(percentage: number) {
- await Commands.reloadUntilFound(this.page, this.page.locator('jhi-course-exercise-details #submission-result-graded'));
+ await Commands.reloadUntilFound(this.page, this.page.locator('jhi-course-exercise-details #submission-result-graded'), 4000, 60000);
await expect(this.page.locator('.tab-bar-exercise-details').getByText(`${percentage}%`)).toBeVisible();
}