Skip to content

Exam mode: Show a validation message for a missing exam title - #13362

Open
HannesHarbeck wants to merge 8 commits into
developfrom
bugfix/exam-title-required-validation
Open

Exam mode: Show a validation message for a missing exam title#13362
HannesHarbeck wants to merge 8 commits into
developfrom
bugfix/exam-title-required-validation

Conversation

@HannesHarbeck

@HannesHarbeck HannesHarbeck commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

The exam create/edit form now flags an empty title with a red "missing/invalid" message like the date fields, and the server rejects a null or blank exam title with a 400 on create, update and import. This closes two server gaps: an empty-string title was persisted, and a crafted null title threw a 500 while being mapped to the entity.

Checklist

General

Server

  • Important: I implemented the changes with a very good performance and prevented too many (unnecessary) and too complex database calls.
  • I strictly followed the principle of data economy for all database calls.
  • I strictly followed the server coding and design guidelines and the REST API guidelines.
  • I added multiple integration tests (Spring) related to the features (with a high test coverage).
  • I documented the Java code using JavaDoc style.

Client

  • Important: I implemented the changes with a very good performance, prevented too many (unnecessary) REST calls and made sure the UI is responsive, even with large data (e.g. using paging).
  • I strictly followed the principle of data economy for all client-server REST calls.
  • I strictly followed the client coding guidelines.
  • I strictly followed the AET UI-UX guidelines.
  • Following the theming guidelines, I specified colors only in the theming variable files and checked that the changes look consistent in both the light and the dark theme.
  • I added multiple integration tests (Vitest) related to the features (with a high test coverage), while following the test guidelines.
  • I added multiple screenshots/screencasts of my UI changes.
  • I translated all newly inserted strings into English and German.

Motivation and Context

The exam create and edit form only disabled the save button when the title was empty, without the missing/invalid hint shown for the required date fields. A user emptying the title got no visible feedback about why saving was blocked.

On top of that, the server did not enforce the requirement it relies on: the title column is nullable = false, which only catches null, so an empty-string title was persisted, and a crafted request with a null title threw a 500 (NPE) while mapping the DTO to the entity.

Description

  • Client: the exam form now renders a red "'Title' is missing/invalid" message under the title field while the title is empty, mirroring the date fields' behaviour and reusing the same text-state-danger styling.
  • Server: ExamResource rejects a null or blank title with 400 examTitleEmpty on create, update and import, validated on the request before it is mapped to an entity (so the null case can no longer NPE in Exam#setTitle).

Steps for Testing

Prerequisites:

  • 1 Instructor
  • 1 Course
  1. Log in as the instructor and open Exam Management for the course.
  2. Click "Create a new exam".
  3. Leave the Title empty. A red "'Title' is missing/invalid" message appears under the title field, just like the date fields (German: "'Titel' fehlt/ungültig").
  4. Type a title. The message disappears, and once the required dates are valid, saving works.
  5. Delete the title again. The message reappears and the save button is disabled.

Note: this PR only changes the instructor-facing exam configuration form and the server-side validation. The student exam-taking UI (exam mode) is not affected.

Testserver States

You can manage test servers using Helios. Check environment statuses in the environment list. To deploy to a test server, go to the CI/CD page, find your PR or branch, and trigger the deployment.

Review Progress

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Test Coverage

Client

Class/File Line Coverage Lines Expects Ratio
exam-update.component.ts 92.26% 430 203 47.2

Server

Class/File Line Coverage Lines
ExamResource.java 97.54% 877

Last updated: 2026-08-24 13:20:53 UTC

Screenshots

To be added: the exam create form with an empty title showing the red "'Title' is missing/invalid" message (light and dark theme).

Summary by CodeRabbit

Summary by CodeRabbit

  • Bug Fixes

    • Exam creation, updates, and imports now reject missing or blank titles with a clear validation error.
    • Added inline feedback when an exam title is missing or invalid.
    • Saving is disabled until the exam title contains valid text.
    • Added English and German translations for the title validation message.
  • Tests

    • Added coverage for title validation in the exam interface and backend, including missing and whitespace-only titles.
image image image

…eject blank titles

The exam create and edit form only disabled the save button when the title was
empty, without the missing/invalid hint shown for the required date fields. Add a
red validation message under the title field so an empty title is flagged like the
dates.

Mirror the requirement on the server: reject a null or blank title with a 400 on
create, update and import before the request is mapped to an entity. This closes
two gaps where the server persisted an empty-string title and threw a 500 while
mapping a null title.
@github-project-automation github-project-automation Bot moved this to Work In Progress in Artemis Development Jul 31, 2026
@HannesHarbeck HannesHarbeck changed the title Exam mode: Show a validation message for a missing exam title and r… Exam mode: Show a validation message for a missing exam title Jul 31, 2026
@github-actions github-actions Bot added tests server Pull requests that update Java code. (Added Automatically!) client Pull requests that update TypeScript code. (Added Automatically!) exam Pull requests that affect the corresponding module labels Jul 31, 2026
@HannesHarbeck
HannesHarbeck marked this pull request as ready for review July 31, 2026 09:19
@HannesHarbeck
HannesHarbeck requested a review from krusche as a code owner July 31, 2026 09:19
@coderabbitai

coderabbitai Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Exam title validation now rejects null or whitespace-only values in exam creation, update, and import endpoints. The exam update form validates titles, displays localized feedback, and disables saving for invalid titles. Backend and frontend tests cover the behavior.

Changes

Exam title validation

Layer / File(s) Summary
Server-side title validation
src/main/java/de/tum/cit/aet/artemis/exam/web/ExamResource.java
Exam creation, update, and import reject null or blank titles with examTitleEmpty.
Server validation coverage
src/test/java/de/tum/cit/aet/artemis/core/util/RequestUtilService.java, src/test/java/de/tum/cit/aet/artemis/exam/ExamIntegrationTest.java
Parameterized tests verify BAD_REQUEST responses for null, empty, and whitespace-only titles.
Client-side title validation and feedback
src/main/webapp/app/exam/manage/exams/update/exam-update.component.ts, src/main/webapp/app/exam/manage/exams/update/exam-update.component.html, src/main/webapp/app/exam/manage/exams/update/exam-update.component.spec.ts, src/main/webapp/i18n/en/exam.json, src/main/webapp/i18n/de/exam.json
The exam update form validates trimmed titles, displays localized feedback, and keeps the save button disabled for invalid titles. Component tests cover these states.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • ls1intum/Artemis#13116: Both changes modify exam title validation in the resource, component, and integration tests.
  • ls1intum/Artemis#13124: Both changes add exam-input validation in the resource, component, tests, and translations.

Suggested labels: bug, user interface, user-experience

Suggested reviewers: krusche

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.11% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the missing exam-title validation message, which is a central part of the client and server changes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bugfix/exam-title-required-validation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/main/webapp/app/exam/manage/exams/update/exam-update.component.spec.ts (1)

154-154: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use deepClone for the exam copy.

Line [154] uses cloneDeep from lodash-es. Use deepClone from app/foundation/util/deep-clone.util for entity-like objects and update the import.

As per coding guidelines, copy entity-like objects with deepClone from app/foundation/util/deep-clone.util.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/webapp/app/exam/manage/exams/update/exam-update.component.spec.ts`
at line 154, Replace the cloneDeep usage in the examWithTitle setup with
deepClone from app/foundation/util/deep-clone.util, and update the corresponding
import while preserving the existing copied-exam behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/test/java/de/tum/cit/aet/artemis/exam/ExamIntegrationTest.java`:
- Around line 681-699: Strengthen the exam title validation tests around
testCreateExam_failsWithBlankTitle and testCreateExam_failsWithMissingTitle by
asserting the response contains the required examTitleEmpty error key, not only
BAD_REQUEST. Add equivalent blank and null title cases for exam update (PUT) and
import endpoints, using the project’s specific response assertions and
preserving the expected BAD_REQUEST status.

---

Nitpick comments:
In `@src/main/webapp/app/exam/manage/exams/update/exam-update.component.spec.ts`:
- Line 154: Replace the cloneDeep usage in the examWithTitle setup with
deepClone from app/foundation/util/deep-clone.util, and update the corresponding
import while preserving the existing copied-exam behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 92a3d761-2bb1-473b-af83-79fb0493712f

📥 Commits

Reviewing files that changed from the base of the PR and between b19e2a5 and 1e2f7fb.

📒 Files selected for processing (6)
  • src/main/java/de/tum/cit/aet/artemis/exam/web/ExamResource.java
  • src/main/webapp/app/exam/manage/exams/update/exam-update.component.html
  • src/main/webapp/app/exam/manage/exams/update/exam-update.component.spec.ts
  • src/main/webapp/i18n/de/exam.json
  • src/main/webapp/i18n/en/exam.json
  • src/test/java/de/tum/cit/aet/artemis/exam/ExamIntegrationTest.java

Comment thread src/test/java/de/tum/cit/aet/artemis/exam/ExamIntegrationTest.java Outdated
@github-project-automation github-project-automation Bot moved this from Work In Progress to Ready For Review in Artemis Development Jul 31, 2026
@HannesHarbeck
HannesHarbeck temporarily deployed to playwright-e2e-tests July 31, 2026 09:27 — with GitHub Actions Inactive
@github-actions

github-actions Bot commented Jul 31, 2026

Copy link
Copy Markdown

End-to-End Test Results

Phase Status Details
Phase 1 (Relevant) ❌ Failed
TestsPassed ☑️SkippedFailed ❌️Time ⏱
Phase 1: E2E Test Report105 ran104 passed0 skipped1 failed17m 10s
Phase 2 (Remaining) ⏭ Skipped (no remaining tests)
❌ Failed Tests (Phase 1)
  • Exam submission recovery after a failed save › restores and re-sends a not-yet-saved quiz answer after a failed save and reload (4m 44s)

Test Strategy: Two-phase execution

  • Phase 1: e2e/Login.spec.ts e2e/Logout.spec.ts e2e/SystemHealth.spec.ts e2e/exam/
  • Phase 2: e2e/Passkey.spec.ts e2e/PasskeyReminderPersistence.spec.ts e2e/admin/ e2e/atlas/ e2e/course/ e2e/exercise/ExerciseImport.spec.ts e2e/exercise/file-upload/ e2e/exercise/modeling/ e2e/exercise/programming/ e2e/exercise/quiz-exercise/ e2e/exercise/text/ e2e/iris/ e2e/lecture/ e2e/shared/

Overall: ❌ E2E: real (non-flaky) test failure

🔗 Workflow Run · 📊 Test Report Phase 1

… import in the exam title tests

Address the review feedback on the exam title validation tests: assert the specific
examTitleEmpty error key instead of only the 400 status, and cover the update and
import endpoints in addition to create.

Add a reusable RequestUtilService#postAndExpectError mirroring putAndExpectError, and
replace the two create-only tests with three parameterised tests (create, update,
import) that each check a null, empty and whitespace-only title.
@github-actions github-actions Bot added the core Pull requests that affect the corresponding module label Jul 31, 2026
coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 31, 2026
@HannesHarbeck
HannesHarbeck temporarily deployed to playwright-e2e-tests July 31, 2026 10:37 — with GitHub Actions Inactive

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HannesHarbeck The title validation is consistently applied to create, update, and import and has focused client and server coverage. However, the required All required CI Passed check is failing because E2E / Report E2E Overall Status failed; please investigate the E2E failure and restore the required check before approval.

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HannesHarbeck Required CI now passes, and the server validation covers create, update, and import. One client-side gap remains: a whitespace-only title displays the invalid message but leaves Save enabled, resulting in a rejected server request instead of preventing submission.

A whitespace-only title showed the missing/invalid message but left the save button
enabled, because Angular's required validator accepts a non-empty whitespace string and
the save validity check did not consider the title. The request then reached the server
and was rejected with a 400 instead of being prevented on the client.

Include the trimmed-title check in isValidConfiguration, which the save button is already
disabled by, and add a test asserting that a whitespace-only title disables saving.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/main/webapp/app/exam/manage/exams/update/exam-update.component.spec.ts (1)

154-156: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the repository deepClone helper for the copied Exam fixture.

component.exam is an entity-like object. Replace cloneDeep with deepClone from app/foundation/util/deep-clone.util and update the import.

Proposed change
-            const examWithBlankTitle = cloneDeep(component.exam);
+            const examWithBlankTitle = deepClone(component.exam);

As per coding guidelines, copy entity-like objects with deepClone from app/foundation/util/deep-clone.util.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/webapp/app/exam/manage/exams/update/exam-update.component.spec.ts`
around lines 154 - 156, Replace the cloneDeep call used to copy component.exam
in the examWithBlankTitle fixture with the repository deepClone helper, and
update the import to use app/foundation/util/deep-clone.util. Preserve the
existing fixture mutation and test behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/main/webapp/app/exam/manage/exams/update/exam-update.component.spec.ts`:
- Around line 154-156: Replace the cloneDeep call used to copy component.exam in
the examWithBlankTitle fixture with the repository deepClone helper, and update
the import to use app/foundation/util/deep-clone.util. Preserve the existing
fixture mutation and test behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a986876d-bb0e-4783-a478-2848b6d19f50

📥 Commits

Reviewing files that changed from the base of the PR and between b960d68 and a550e89.

📒 Files selected for processing (2)
  • src/main/webapp/app/exam/manage/exams/update/exam-update.component.spec.ts
  • src/main/webapp/app/exam/manage/exams/update/exam-update.component.ts

@MarkusPaulsen
MarkusPaulsen temporarily deployed to playwright-e2e-tests August 7, 2026 02:47 — with GitHub Actions Inactive
@SultanTheHL

SultanTheHL commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Tested locally and works as described.
image

However, I think it would look better if the error message was closer to the input field(like with the dates)

@SultanTheHL
SultanTheHL self-requested a review August 7, 2026 11:24

@SultanTheHL SultanTheHL left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

comment above

…title field

Reduce the gap between the title field and its "missing/invalid" message by replacing
the top margin with a small negative one, so the message sits directly under the field
like the date field messages. Layout only, no behaviour change.
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 8, 2026

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HannesHarbeck The server consistently rejects null, empty, and whitespace-only exam titles across create, update, and import, with focused contract tests. The client applies the same trimmed-title rule to its message and Save-button state, and the latest layout adjustment uses an available spacing utility. The snapshot lists no required checks and no completed failing checks.

@HannesHarbeck
HannesHarbeck temporarily deployed to playwright-e2e-tests August 8, 2026 14:32 — with GitHub Actions Inactive
@HannesHarbeck

Copy link
Copy Markdown
Contributor Author

@SultanTheHL I adjusted the layout accordingly

SedaOran
SedaOran previously approved these changes Aug 10, 2026

@SedaOran SedaOran left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now UI works well and It's aligned. Approving.
Image

WoH
WoH previously approved these changes Aug 10, 2026

@WoH WoH left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tested commit 2b13db6. setup: local dev, e2e seed, instructor artemis_test_user_16, course 9023 E2E Exam Management Course.

  1. create exam, leave title empty, red 'Title' is missing/invalid message under the field like the date fields: yes
pr13362-03-empty-title-message
  1. type a title, message disappears, save enabled once dates valid too: yes, per-keystroke, no fill()
pr13362-06-valid-title-save-enabled
  1. delete the title again, message reappears, save disabled: yes, tested on both create and the edit form (step not in your list but same code path)
pr13362-08-edit-save-disabled pr13362-07-edit-title-cleared
pr13362-v01-create-exam-title-validation.webm
pr13362-v02-edit-exam-clear-title.webm

also checked:

  • whitespace-only title (3 spaces, real keystrokes + blur): native required reports the field valid (green border) but your trim check still shows the message and blocks save. isolated it by filling all three dates first so title was the only failing field. this is the actual bug the PR fixes, good catch.
pr13362-04-whitespace-title pr13362-05-dates-filled-title-blank
  • full create round trip: POST /api/exam/courses/9023/exams -> 201, title matches in request/response/UI, no console errors, no toast

  • crafted PUT with title:null on the saved exam -> 400, error.examTitleEmpty, exam title unchanged after (confirmed by reload). see inline comment, this error key has no en/de translation, unlike its neighbors

*/
private void checkExamTitleIsPresentElseThrow(String title) {
if (title == null || title.isBlank()) {
throw new BadRequestAlertException("The exam title must not be empty.", ENTITY_NAME, "examTitleEmpty");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

examTitleEmpty has no error.json entry in en or de.

checkExamTitleLengthElseThrow right above this (examTitleTooLong) has both, and so does every other exam validation error in this class (noCourse, wrongCourseId, examTimes, negativePoints, correctionRoundViolation, attendanceCheckViolation).

confirmed at runtime: fetch('/i18n/en.json') and de.json both lack error.examTitleEmpty while error.examTitleTooLong is present in both. means a crafted request or any non-UI caller gets the raw english exception title in the toast, untranslated for german users. two-line fix, same pattern as examTitleTooLong.

@github-actions

Copy link
Copy Markdown

There hasn't been any activity on this pull request recently. Therefore, this pull request has been automatically marked as stale and will be closed if no further activity occurs within seven days. Thank you for your contributions.

develop replaced the manual exam conduction date chain with the
timeline status signal (#13473). Keep that check and combine it with
the new title validation instead of the removed date getters.

develop also replaced lodash cloneDeep with deepClone (#13351), so the
two new spec call sites use deepClone as well.

@Claudia-Anthropica Claudia-Anthropica left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@HannesHarbeck The exact head consistently rejects null/blank titles for create, update, and import, while the client blocks whitespace-only titles with focused coverage. The failed E2E test concerns post-reload quiz-answer re-sending; its only call through the changed create endpoint uses a valid title, so this change does not reach the failed behavior. Test / Server Tests (PostgreSQL) and therefore All required CI Passed remain red, but the captured server evidence names no failing test or compiler error, so that failure cannot be attributed. The existing unresolved thread identifies one [low] localization gap: error.examTitleEmpty is absent from the English and German error.json, leaving the raw English fallback for non-UI invalid requests.

@ShudongCai ShudongCai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally, works as expected

Image Image

@MarkusPaulsen
MarkusPaulsen temporarily deployed to playwright-e2e-tests August 24, 2026 12:58 — with GitHub Actions Inactive

@SedaOran SedaOran left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally, works as expected. Approved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

client Pull requests that update TypeScript code. (Added Automatically!) core Pull requests that affect the corresponding module exam Pull requests that affect the corresponding module server Pull requests that update Java code. (Added Automatically!) tests

Projects

Status: Ready For Review

Development

Successfully merging this pull request may close these issues.

7 participants