Skip to content

Conversation

@HawKhiem
Copy link
Contributor

@HawKhiem HawKhiem commented Nov 13, 2025

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.
  • 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.
  • I documented the TypeScript code using JSDoc style.

Motivation and Context

Students were unable to easily discover newly added FAQ posts in the course FAQ view because posts were displayed in random order (sorted by ID). This made it difficult for students to find recent announcements or answers to new questions. This PR closes issue #9883

Description

This PR implements chronological sorting for FAQ posts in the course FAQ view, displaying the newest posts at the top of the list.

Changes:

  • Server: Added createdDate field to FaqDTO to include creation timestamps in API responses
  • Client Model: Added createdDate property to the Faq model
  • Course FAQ Component: Updated sorting logic to sort by createdDate in descending order (newest first) using dayjs for proper date comparison
  • Sorting Persistence: Ensured sort order is maintained after filtering and searching

Note: This change only affects the student-facing course FAQ view (jhi-course-faq). The instructor FAQ management page remains unchanged.

Steps for Testing

Prerequisites:

  • 1 Instructor
  • 2 Students
  • 1 Course with FAQ enabled
  1. Log in as Instructor
  2. Navigate to Course Management → Communication → FAQs
  3. Create 3-4 FAQ posts with different titles (e.g., "First FAQ", "Second FAQ", "Third FAQ")
  4. Wait a few seconds between creating each FAQ to ensure different timestamps
  5. Log out and log in as Student
  6. Navigate to the course overview and click on "FAQ" in the sidebar
  7. Verify that the FAQs are displayed with the newest post at the top
  8. Create another FAQ as instructor
  9. Refresh the student FAQ view
  10. Verify the newly created FAQ appears at the top of the list
  11. Test filtering by categories (if available) and verify sort order is maintained
  12. Test search functionality and verify sort order is maintained

Review Progress

Performance Review

Code Review

  • Code Review 1
  • Code Review 2

Manual Tests

  • Test 1
  • Test 2

Test Coverage

Screenshots

Summary by CodeRabbit

  • New Features
    • FAQs are now automatically sorted by creation date, with the newest FAQs appearing first throughout the application for improved content discovery.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-project-automation github-project-automation bot moved this to Work In Progress in Artemis Development Nov 13, 2025
@github-actions github-actions bot added server Pull requests that update Java code. (Added Automatically!) client Pull requests that update TypeScript code. (Added Automatically!) communication Pull requests that affect the corresponding module labels Nov 13, 2025
@HawKhiem HawKhiem linked an issue Nov 13, 2025 that may be closed by this pull request
@HawKhiem HawKhiem marked this pull request as ready for review November 13, 2025 10:34
@HawKhiem HawKhiem requested a review from a team as a code owner November 13, 2025 10:34
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 13, 2025

Walkthrough

The changes systematically convert FAQ collections from unordered Sets to ordered Lists throughout the application stack, introduce a createdDate field to the Faq model, and apply descending date-based sorting at the database, service, and UI layers.

Changes

Cohort / File(s) Change Summary
Frontend FAQ sorting
src/main/webapp/app/communication/course-faq/course-faq.component.ts, src/main/webapp/app/communication/course-faq/course-faq.component.spec.ts
Replaced sort-by-id logic with createdDate-based sorting using dayjs; updated test to spy on sortByFunction and verify sortFaqs is called post-refresh
FAQ model
src/main/webapp/app/communication/shared/entities/faq.model.ts
Added optional createdDate?: Date property to Faq class
Repository layer
src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java
Changed return type from Set to List; renamed methods to findAllByCourseIdOrderByCreatedDateDesc and findAllByCourseIdAndFaqStateOrderByCreatedDateDesc with database-level descending ordering
Service layer
src/main/java/de/tum/cit/aet/artemis/communication/service/FaqService.java, src/main/java/de/tum/cit/aet/artemis/core/service/course/CourseService.java
Updated FAQ queries to use new OrderByCreatedDateDesc repository methods for consistent descending date ordering
REST API layer
src/main/java/de/tum/cit/aet/artemis/communication/web/FaqResource.java
Changed response return types from Set<FaqDTO> to List<FaqDTO>; replaced Set-based collection operations with List-based equivalents; updated repository method calls
Domain model
src/main/java/de/tum/cit/aet/artemis/core/domain/Course.java
Changed faqs field from Set<Faq> to List<Faq> initialized with ArrayList; added @OrderBy("createdDate DESC") annotation; updated getter/setter signatures

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Attention areas:
    • Course.java: Verify that changing from HashSet to ArrayList doesn't introduce unintended duplicate FAQs or break any existing code relying on Set semantics (e.g., uniqueness guarantees)
    • FaqRepository.java & FaqResource.java: Confirm that all call sites have been updated to handle List instead of Set return types
    • Sorting consistency: Ensure that the @OrderBy annotation in Course.java, database-level ordering in repository methods, and frontend sorting logic are mutually compatible and don't cause redundant or conflicting sorts
    • API contract changes: FaqResource method signatures now return List instead of Set—verify this doesn't break client expectations or serialization

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.77% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: sorting FAQ posts by creation date in descending order (newest first), which is the primary objective across all modified files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/communication/sort-faq-posts-by-creation-date-newest-first

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2440398 and 165c351.

📒 Files selected for processing (5)
  • src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/service/FaqService.java (1 hunks)
  • src/main/java/de/tum/cit/aet/artemis/communication/web/FaqResource.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/domain/Course.java (3 hunks)
  • src/main/java/de/tum/cit/aet/artemis/core/service/course/CourseService.java (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/**/*.java

⚙️ CodeRabbit configuration file

naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports

Files:

  • src/main/java/de/tum/cit/aet/artemis/communication/web/FaqResource.java
  • src/main/java/de/tum/cit/aet/artemis/communication/service/FaqService.java
  • src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java
  • src/main/java/de/tum/cit/aet/artemis/core/domain/Course.java
  • src/main/java/de/tum/cit/aet/artemis/core/service/course/CourseService.java
🧠 Learnings (14)
📚 Learning: 2025-08-08T08:50:28.791Z
Learnt from: tobias-lippert
Repo: ls1intum/Artemis PR: 11248
File: src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingExerciseParticipationService.java:401-402
Timestamp: 2025-08-08T08:50:28.791Z
Learning: In src/main/java/de/tum/cit/aet/artemis/programming/service/ProgrammingExerciseParticipationService.java, method findStudentParticipationWithLatestSubmissionResultAndFeedbacksElseThrow(long), using List.of() for latestSubmission.setResults(...) is acceptable because the results list is not mutated afterward and is only returned to the client; no follow-up code appends to it.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/communication/web/FaqResource.java
  • src/main/java/de/tum/cit/aet/artemis/core/domain/Course.java
📚 Learning: 2025-09-20T16:43:32.823Z
Learnt from: MoritzSpengler
Repo: ls1intum/Artemis PR: 11382
File: src/main/java/de/tum/cit/aet/artemis/quiz/service/QuizQuestionProgressService.java:130-137
Timestamp: 2025-09-20T16:43:32.823Z
Learning: The findAllDueQuestions method exists in QuizQuestionRepository and accepts Set<Long> ids, Long courseId, and Pageable parameters, returning Page<QuizQuestion>. This method is properly implemented and available for use in QuizQuestionProgressService.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/communication/web/FaqResource.java
  • src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java
  • src/main/java/de/tum/cit/aet/artemis/core/service/course/CourseService.java
📚 Learning: 2025-09-20T16:43:32.823Z
Learnt from: MoritzSpengler
Repo: ls1intum/Artemis PR: 11382
File: src/main/java/de/tum/cit/aet/artemis/quiz/service/QuizQuestionProgressService.java:130-137
Timestamp: 2025-09-20T16:43:32.823Z
Learning: The findAllDueQuestions method exists in QuizQuestionRepository and accepts Set<Long> ids, Long courseId, and Pageable parameters, returning Page<QuizQuestion>. The method has a Query annotation that filters by courseId, isOpenForPractice = TRUE, and excludes questions with IDs in the provided set using NOT IN.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/communication/web/FaqResource.java
  • src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java
  • src/main/java/de/tum/cit/aet/artemis/core/service/course/CourseService.java
📚 Learning: 2025-09-20T16:47:54.380Z
Learnt from: MoritzSpengler
Repo: ls1intum/Artemis PR: 11382
File: src/main/java/de/tum/cit/aet/artemis/quiz/service/QuizTrainingService.java:43-54
Timestamp: 2025-09-20T16:47:54.380Z
Learning: In QuizTrainingService.submitForTraining, cross-course mismatch protection is handled through PreAuthorize("hasAccessToCourse(#courseId)") authorization at the REST layer, ensuring users can only submit for courses they have access to, rather than through explicit courseId validation in the service method.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/communication/web/FaqResource.java
  • src/main/java/de/tum/cit/aet/artemis/core/service/course/CourseService.java
📚 Learning: 2024-06-10T19:44:09.116Z
Learnt from: pzdr7
Repo: ls1intum/Artemis PR: 8703
File: src/main/java/de/tum/in/www1/artemis/web/rest/QuizParticipationResource.java:39-39
Timestamp: 2024-06-10T19:44:09.116Z
Learning: The `Profile(PROFILE_CORE)` annotation in `QuizParticipationResource.java` is used to ensure that all nodes, not just those with the scheduling profile, can handle quiz participations.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java
📚 Learning: 2025-09-05T09:12:34.098Z
Learnt from: jfr2102
Repo: ls1intum/Artemis PR: 11330
File: src/main/java/de/tum/cit/aet/artemis/programming/service/localci/LocalCIMissingJobService.java:111-128
Timestamp: 2025-09-05T09:12:34.098Z
Learning: In Artemis deployments, services with Profile("localci & scheduling") run only on a single designated scheduling node per deployment, preventing race conditions in scheduled tasks like LocalCIMissingJobService.retryMissingJobs().

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java
📚 Learning: 2025-08-08T08:56:49.931Z
Learnt from: tobias-lippert
Repo: ls1intum/Artemis PR: 11248
File: src/main/java/de/tum/cit/aet/artemis/programming/web/repository/RepositoryResource.java:288-291
Timestamp: 2025-08-08T08:56:49.931Z
Learning: In the Artemis codebase, the LocalCI profile is only active when LocalVC is active (LocalCI ⇒ LocalVC). Therefore, in RepositoryResource.commitChanges, guarding the LocalVCServletService invocation with profileService.isLocalCIActive() is correct and guarantees the bean’s presence.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java
📚 Learning: 2025-09-05T15:13:32.171Z
Learnt from: MoritzSpengler
Repo: ls1intum/Artemis PR: 11345
File: src/main/java/de/tum/cit/aet/artemis/quiz/repository/QuizTrainingLeaderboardRepository.java:22-23
Timestamp: 2025-09-05T15:13:32.171Z
Learning: The derived query method name `findByLeagueAndCourseIdOrderByScoreDescUserAscId` in QuizTrainingLeaderboardRepository correctly references the `user` entity field directly in the OrderBy clause, not requiring `userId`. Spring Data JPA supports sorting by entity references directly in derived query method names.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java
📚 Learning: 2025-05-24T16:06:41.454Z
Learnt from: tobias-lippert
Repo: ls1intum/Artemis PR: 10812
File: src/main/java/de/tum/cit/aet/artemis/atlas/repository/CompetencyRepository.java:70-88
Timestamp: 2025-05-24T16:06:41.454Z
Learning: In CompetencyRepository JPQL queries that join from LearningPath to course competencies, DISTINCT is not necessary because a learning path belongs to exactly one course, preventing duplicate competencies in the result set.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java
📚 Learning: 2025-09-18T20:55:38.115Z
Learnt from: marlonnienaber
Repo: ls1intum/Artemis PR: 11350
File: src/main/java/de/tum/cit/aet/artemis/tutorialgroup/repository/TutorialGroupRepository.java:145-168
Timestamp: 2025-09-18T20:55:38.115Z
Learning: In tutorial groups, every TutorialGroup is guaranteed to have a teachingAssistant (non-null constraint), so teaching assistant associations don't require LEFT JOINs in JPQL queries. Only optional associations like tutorialGroupSchedule and tutorialGroupChannel need LEFT JOINs.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/core/domain/Course.java
📚 Learning: 2024-10-08T15:35:42.972Z
Learnt from: Strohgelaender
Repo: ls1intum/Artemis PR: 8574
File: src/main/java/de/tum/in/www1/artemis/service/tutorialgroups/TutorialGroupService.java:0-0
Timestamp: 2024-10-08T15:35:42.972Z
Learning: The `tryToFindMatchingUsers` method in `TutorialGroupService.java` has been updated to skip registrations without a student, enhancing the method's robustness. This change was implemented in commit `bef30f9751de0913143e8cb28cc0088264052261`.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/core/service/course/CourseService.java
📚 Learning: 2025-09-20T16:47:54.380Z
Learnt from: MoritzSpengler
Repo: ls1intum/Artemis PR: 11382
File: src/main/java/de/tum/cit/aet/artemis/quiz/service/QuizTrainingService.java:43-54
Timestamp: 2025-09-20T16:47:54.380Z
Learning: In QuizTrainingService.submitForTraining, cross-course validation is handled by the REST layer through authCheckService.checkHasAtLeastRoleInCourseElseThrow() which validates user access to the course before the service method is called, eliminating the need for additional courseId validation in the service layer.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/core/service/course/CourseService.java
📚 Learning: 2024-06-10T19:44:09.116Z
Learnt from: jakubriegel
Repo: ls1intum/Artemis PR: 8050
File: src/test/java/de/tum/in/www1/artemis/plagiarism/PlagiarismUtilService.java:62-66
Timestamp: 2024-06-10T19:44:09.116Z
Learning: The `createCourseWithUsers` method in `PlagiarismUtilService.java` uses fixed inputs as it is designed to be a test helper method for simplifying the setup of courses and users in tests.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/core/service/course/CourseService.java
📚 Learning: 2025-09-20T16:45:43.715Z
Learnt from: MoritzSpengler
Repo: ls1intum/Artemis PR: 11382
File: src/main/java/de/tum/cit/aet/artemis/quiz/repository/QuizQuestionRepository.java:77-77
Timestamp: 2025-09-20T16:45:43.715Z
Learning: In QuizQuestionProgressService.areQuestionsDue method, the implementation calls quizQuestionRepository.countAllPracticeQuizQuestionsByCourseId(courseId) to get the total count of practice questions and compares it with notDueCount parameter to determine if questions are due for practice.

Applied to files:

  • src/main/java/de/tum/cit/aet/artemis/core/service/course/CourseService.java
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: client-style
  • GitHub Check: client-tests-selected
  • GitHub Check: server-style
  • GitHub Check: server-tests
  • GitHub Check: client-tests
  • GitHub Check: Build and Push Docker Image / Build linux/arm64 Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build linux/amd64 Docker Image for ls1intum/artemis
  • GitHub Check: Build .war artifact
  • GitHub Check: bean-instantiation-check
  • GitHub Check: Analyse
🔇 Additional comments (8)
src/main/java/de/tum/cit/aet/artemis/core/service/course/CourseService.java (1)

203-205: LGTM! Consistent ordering applied.

The FAQ retrieval now uses the ordered repository method findAllByCourseIdAndFaqStateOrderByCreatedDateDesc, ensuring FAQs are retrieved in descending creation date order. This aligns with the PR objective to display newest FAQs first in the student view.

src/main/java/de/tum/cit/aet/artemis/communication/repository/FaqRepository.java (2)

44-44: Consistent ordering applied.

This method follows the same pattern as findAllByCourseIdOrderByCreatedDateDesc, ensuring consistent descending date ordering across all FAQ retrieval paths.


28-28: The review comment is incorrect and should be dismissed.

The createdDate field is properly defined in the Faq entity through inheritance from AbstractAuditingEntity (line 33 of AbstractAuditingEntity.java). It is annotated with @CreatedDate and @Column, initialized to Instant.now(), ensuring it is always non-null. The derived query method findAllByCourseIdOrderByCreatedDateDesc is valid and correctly references this field. Additionally, the same field is already used elsewhere in the codebase (e.g., Course.java line 237 uses @OrderBy("createdDate DESC") on the faqs list).

Likely an incorrect or invalid review comment.

src/main/java/de/tum/cit/aet/artemis/communication/service/FaqService.java (1)

51-51: LGTM! Consistent with repository updates.

The method now uses findAllByCourseIdAndFaqStateOrderByCreatedDateDesc, ensuring FAQs are ingested into Pyris in a consistent order (newest first). This aligns with the broader PR changes.

src/main/java/de/tum/cit/aet/artemis/communication/web/FaqResource.java (2)

189-194: LGTM! Consistent List-based API with ordering.

The endpoint now returns List<FaqDTO> instead of Set<FaqDTO>, using ordered repository methods and .toList() for mapping. This ensures FAQs are consistently ordered by creation date descending in the response.

Note: This is a breaking API change as the return type changed from Set to List. While JSON arrays handle both similarly, any client code expecting Set semantics (uniqueness without order) should be updated. This appears intentional per the PR objectives.


206-211: Consistent with the getFaqsForCourse changes.

This method applies the same List-based ordering pattern, ensuring all FAQ retrieval endpoints return consistently ordered results.

src/main/java/de/tum/cit/aet/artemis/core/domain/Course.java (2)

1009-1015: Consistent getter/setter for List-based FAQs.

The getter and setter are correctly updated to use List<Faq>, aligning with the entity field type change. This maintains consistency across the domain model.


237-239: Defensive ordering with @orderby annotation is valid.

The @OrderBy("createdDate DESC") annotation correctly references the createdDate field inherited from AbstractAuditingEntity, which is properly defined with the @CreatedDate annotation for automatic timestamp management.


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 and usage tips.

coderabbitai[bot]
coderabbitai bot previously approved these changes Nov 13, 2025
@github-actions
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report205 ran200 passed3 skipped2 failed1h 15m 20s 793ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exercise/quiz-exercise/QuizExerciseDropLocation.spec.ts
ts.Quiz Exercise Drop Location Spec › DnD Quiz drop locations › Checks drop locations❌ failure2m 3s 502ms
e2e/exam/test-exam/TestExamParticipation.spec.ts
ts.Test exam participation › Early Hand-in › Using exercise overview to navigate within exam❌ failure3m 43s 582ms

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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/communication/course-faq/course-faq.component.spec.ts (1)

23-30: Add createdDate to test FAQ objects for realistic test data.

The createFaq helper should include the createdDate property to reflect the updated FAQ model. While the current unit test mocks the sort service, having test FAQs with createdDate values will make the tests more representative of production behavior and enable future integration tests to verify actual date-based sorting.

Apply this diff to add createdDate to the helper:

 function createFaq(id: number, category: string, color: string): Faq {
     const faq = new Faq();
     faq.id = id;
     faq.questionTitle = 'questionTitle ' + id;
     faq.questionAnswer = 'questionAnswer ' + id;
     faq.categories = [new FaqCategory(category, color)];
+    faq.createdDate = new Date(2025, 0, id); // Different dates for sorting tests
     return faq;
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4e10d75 and 2440398.

📒 Files selected for processing (1)
  • src/main/webapp/app/communication/course-faq/course-faq.component.spec.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/webapp/**/*.ts

⚙️ CodeRabbit configuration file

angular_style:https://angular.io/guide/styleguide;methods_in_html:false;lazy_loading:true;code_reuse:true;tests:meaningful;types:PascalCase;enums:PascalCase;funcs:camelCase;props:camelCase;no_priv_prefix:true;strings:single_quotes;localize:true;btns:functionality;links:navigation;icons_text:newline;labels:associate;code_style:arrow_funcs,curly_braces,open_braces_same_line,indent_4;memory_leak_prevention:true;routes:naming_schema;chart_framework:ngx-charts;responsive_layout:true

Files:

  • src/main/webapp/app/communication/course-faq/course-faq.component.spec.ts
🧠 Learnings (7)
📚 Learning: 2024-10-10T11:42:23.069Z
Learnt from: pzdr7
Repo: ls1intum/Artemis PR: 9443
File: src/test/javascript/spec/component/hestia/git-diff-report/git-diff-modal.component.spec.ts:55-60
Timestamp: 2024-10-10T11:42:23.069Z
Learning: In `git-diff-report-modal.component.spec.ts`, using `fakeAsync` and `tick` does not work for handling asynchronous operations in the tests; alternative methods are needed.

Applied to files:

  • src/main/webapp/app/communication/course-faq/course-faq.component.spec.ts
📚 Learning: 2025-08-21T17:30:20.530Z
Learnt from: MoritzSpengler
Repo: ls1intum/Artemis PR: 11297
File: src/main/webapp/app/quiz/shared/questions/drag-and-drop-question/drag-and-drop-question.component.spec.ts:34-34
Timestamp: 2025-08-21T17:30:20.530Z
Learning: FitTextDirective in src/main/webapp/app/quiz/shared/fit-text/fit-text.directive.ts is a standalone directive marked with standalone: true, so it should be imported in TestBed imports array, not declarations array.

Applied to files:

  • src/main/webapp/app/communication/course-faq/course-faq.component.spec.ts
📚 Learning: 2024-10-13T12:03:02.430Z
Learnt from: pzdr7
Repo: ls1intum/Artemis PR: 9463
File: src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.service.spec.ts:50-55
Timestamp: 2024-10-13T12:03:02.430Z
Learning: In `src/test/javascript/spec/component/shared/monaco-editor/monaco-editor.service.spec.ts`, when a function is called multiple times in a test, use `toHaveBeenCalledTimes` and `toHaveBeenNthCalledWith` assertions instead of `toHaveBeenCalledExactlyOnceWith`.

Applied to files:

  • src/main/webapp/app/communication/course-faq/course-faq.component.spec.ts
📚 Learning: 2025-09-01T10:20:40.706Z
Learnt from: Michael-Breu-UIbk
Repo: ls1intum/Artemis PR: 10989
File: src/main/webapp/app/programming/manage/detail/programming-exercise-detail.component.with-sharing.spec.ts:132-149
Timestamp: 2025-09-01T10:20:40.706Z
Learning: In the Artemis codebase, Angular component test files for ProgrammingExerciseDetailComponent follow a pattern where the component is imported but not explicitly declared in TestBed.configureTestingModule(), yet TestBed.createComponent() still works successfully. This pattern is consistently used across test files like programming-exercise-detail.component.spec.ts and programming-exercise-detail.component.with-sharing.spec.ts.

Applied to files:

  • src/main/webapp/app/communication/course-faq/course-faq.component.spec.ts
📚 Learning: 2024-10-20T22:00:52.335Z
Learnt from: pzdr7
Repo: ls1intum/Artemis PR: 9505
File: src/test/javascript/spec/integration/code-editor/code-editor-container.integration.spec.ts:179-181
Timestamp: 2024-10-20T22:00:52.335Z
Learning: In `src/test/javascript/spec/integration/code-editor/code-editor-container.integration.spec.ts`, `ResizeObserver` is mocked within the `beforeEach` block.

Applied to files:

  • src/main/webapp/app/communication/course-faq/course-faq.component.spec.ts
📚 Learning: 2025-09-01T13:47:02.624Z
Learnt from: Michael-Breu-UIbk
Repo: ls1intum/Artemis PR: 10989
File: src/main/webapp/app/programming/manage/detail/programming-exercise-detail.component.with-sharing.spec.ts:167-169
Timestamp: 2025-09-01T13:47:02.624Z
Learning: In Jest tests, prefer using jest.spyOn() over direct method assignment for mocking service methods, as spies are automatically restored by Jest's cleanup mechanisms (jest.restoreAllMocks()), while direct assignment bypasses this system and can lead to test pollution where mocked methods affect subsequent tests.

Applied to files:

  • src/main/webapp/app/communication/course-faq/course-faq.component.spec.ts
📚 Learning: 2024-07-09T19:09:34.276Z
Learnt from: florian-glombik
Repo: ls1intum/Artemis PR: 8858
File: src/test/javascript/spec/component/shared/sidebar/sidebar-accordion.component.spec.ts:91-96
Timestamp: 2024-07-09T19:09:34.276Z
Learning: For the PR ls1intum/Artemis#8858, avoid suggesting to change `expect(component.expandAll).toHaveBeenCalledOnce()` to `expect(component.expandAll).toHaveBeenCalledTimes(1)`.

Applied to files:

  • src/main/webapp/app/communication/course-faq/course-faq.component.spec.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: Build and Push Docker Image / Build linux/arm64 Docker Image for ls1intum/artemis
  • GitHub Check: Build and Push Docker Image / Build linux/amd64 Docker Image for ls1intum/artemis
  • GitHub Check: Build .war artifact
  • GitHub Check: client-style
  • GitHub Check: client-tests
  • GitHub Check: client-tests-selected
  • GitHub Check: server-tests
  • GitHub Check: server-style
  • GitHub Check: bean-instantiation-check
  • GitHub Check: Analyse

Comment on lines 157 to 163
it('should call sortService when sortFaqs is called', () => {
courseFaqComponent.filteredFaqs = [faq1, faq2, faq3];
const sortByFunctionSpy = jest.spyOn(sortService, 'sortByFunction').mockReturnValue([faq3, faq2, faq1]);
courseFaqComponent.sortFaqs();
expect(sortService.sortByProperty).toHaveBeenCalledOnce();
expect(sortByFunctionSpy).toHaveBeenCalledOnce();
expect(sortByFunctionSpy).toHaveBeenCalledWith([faq1, faq2, faq3], expect.any(Function), false);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Verify that filteredFaqs is updated with the sorted result.

The test verifies that sortByFunction is called but doesn't check whether filteredFaqs is updated with the sorted result. Add an assertion to ensure the component properly updates filteredFaqs after sorting.

Apply this diff to add the missing assertion:

     it('should call sortService when sortFaqs is called', () => {
         courseFaqComponent.filteredFaqs = [faq1, faq2, faq3];
         const sortByFunctionSpy = jest.spyOn(sortService, 'sortByFunction').mockReturnValue([faq3, faq2, faq1]);
         courseFaqComponent.sortFaqs();
         expect(sortByFunctionSpy).toHaveBeenCalledOnce();
         expect(sortByFunctionSpy).toHaveBeenCalledWith([faq1, faq2, faq3], expect.any(Function), false);
+        expect(courseFaqComponent.filteredFaqs).toEqual([faq3, faq2, faq1]);
     });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it('should call sortService when sortFaqs is called', () => {
courseFaqComponent.filteredFaqs = [faq1, faq2, faq3];
const sortByFunctionSpy = jest.spyOn(sortService, 'sortByFunction').mockReturnValue([faq3, faq2, faq1]);
courseFaqComponent.sortFaqs();
expect(sortService.sortByProperty).toHaveBeenCalledOnce();
expect(sortByFunctionSpy).toHaveBeenCalledOnce();
expect(sortByFunctionSpy).toHaveBeenCalledWith([faq1, faq2, faq3], expect.any(Function), false);
});
it('should call sortService when sortFaqs is called', () => {
courseFaqComponent.filteredFaqs = [faq1, faq2, faq3];
const sortByFunctionSpy = jest.spyOn(sortService, 'sortByFunction').mockReturnValue([faq3, faq2, faq1]);
courseFaqComponent.sortFaqs();
expect(sortByFunctionSpy).toHaveBeenCalledOnce();
expect(sortByFunctionSpy).toHaveBeenCalledWith([faq1, faq2, faq3], expect.any(Function), false);
expect(courseFaqComponent.filteredFaqs).toEqual([faq3, faq2, faq1]);
});
🤖 Prompt for AI Agents
In src/main/webapp/app/communication/course-faq/course-faq.component.spec.ts
around lines 157 to 163, the test checks that sortService.sortByFunction is
called but does not assert that courseFaqComponent.filteredFaqs was updated with
the returned sorted array; update the test to assert that after
courseFaqComponent.sortFaqs() completes, courseFaqComponent.filteredFaqs equals
the mocked sorted result (e.g., [faq3, faq2, faq1]) so the component's state is
validated in addition to the service call.

@github-project-automation github-project-automation bot moved this from Work In Progress to Ready For Review in Artemis Development Nov 13, 2025
@github-actions
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report205 ran200 passed3 skipped2 failed1h 16m 29s 701ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exercise/quiz-exercise/QuizExerciseDropLocation.spec.ts
ts.Quiz Exercise Drop Location Spec › DnD Quiz drop locations › Checks drop locations❌ failure2m 3s 748ms
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure2m 39s 790ms

Copy link
Contributor

@Anishyou Anishyou left a comment

Choose a reason for hiding this comment

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

code lgtm, I added a comment. I think test can be better but it is optional. Let me know

@helios-aet helios-aet bot temporarily deployed to artemis-test1.artemis.cit.tum.de November 18, 2025 13:56 Inactive
Copy link

@FullbusterSteve FullbusterSteve left a comment

Choose a reason for hiding this comment

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

I tested this PR on TS1.

It works as expected.

atharvamp
atharvamp previously approved these changes Nov 18, 2025
Copy link

@atharvamp atharvamp left a comment

Choose a reason for hiding this comment

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

Tested on ts1. Creation of FAQs maintains order across instructors and students. Searching through FAQs maintains order of creation in the search results and seems to use both FAQ title and FAQ description for searching.

sortFaqs() {
this.sortService.sortByProperty(this.filteredFaqs, 'id', true);
// Sort by createdDate descending (newest first)
this.sortService.sortByFunction(this.filteredFaqs, (faq) => (faq.createdDate ? dayjs(faq.createdDate) : undefined), false);
Copy link
Member

Choose a reason for hiding this comment

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

Just curious, is there a reason you're filtering on the client side and not on the GET faq endpoint on the server? Like this we'd need to implement sorting on both mobile apps too.

Copy link
Contributor Author

@HawKhiem HawKhiem Nov 23, 2025

Choose a reason for hiding this comment

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

You're right! I initially thought I could simply modify the existing client-side sorting logic (which was sorting by ID) to sort by creation date instead. I've now moved the sorting mechanism to the server side as you suggested. I implemented it at the repository layer. This way, the sorting happens at the database level, which is more efficient in terms of CPU and memory usage.

Copy link
Member

@anian03 anian03 left a comment

Choose a reason for hiding this comment

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

Nice implementation in general, but please consider if it makes sense to move the sorting logic to the server. We could already sort the results in the database query, and it would eliminate the need to implement this logic in both mobile app clients too

@helios-aet helios-aet bot temporarily deployed to artemis-test4.artemis.cit.tum.de November 18, 2025 15:04 Inactive
kaleliguray
kaleliguray previously approved these changes Nov 18, 2025
Copy link

@kaleliguray kaleliguray left a comment

Choose a reason for hiding this comment

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

I tested the PR related to the FAQ. I followed every step as mentioned.

Result:

I created some FAQ, and they were listed as expected like in order. I controlled from a student account and confirmed. Additionally, by using the search bar, I could manage to filter based on typing; however, the filtering feature has not been active yet.

Test Account:

Role: Instructor | Student

Account: artemis_test_user_17 | artemis_test_user_5

ScreenShots:

Screen Shot 2025-11-18 at 16 13 30 PM Screen Shot 2025-11-18 at 16 15 37 PM Screen Shot 2025-11-18 at 16 24 03 PM Screen Shot 2025-11-18 at 16 16 38 PM Screen Shot 2025-11-18 at 16 16 54 PM

@github-actions
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ✅Skipped ⚠️FailedTime ⏱
End-to-End (E2E) Test Report205 ran202 passed3 skipped0 failed1h 9m 28s 292ms
TestResultTime ⏱
No test annotations available

@github-actions
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ✅Skipped ⚠️FailedTime ⏱
End-to-End (E2E) Test Report205 ran202 passed3 skipped0 failed1h 7m 34s 178ms
TestResultTime ⏱
No test annotations available

@github-actions
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report215 ran211 passed3 skipped1 failed1h 23m 24s 424ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exam/test-exam/TestExamStudentExams.spec.ts
ts.Test Exam - student exams › Check exam participants and their submissions › Open the list of exam students❌ failure6m 9s 95ms

@HawKhiem HawKhiem requested a review from krusche as a code owner November 23, 2025 21:17
@github-actions github-actions bot added tests core Pull requests that affect the corresponding module labels Nov 23, 2025
@github-actions
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report215 ran211 passed3 skipped1 failed1h 19m 53s 456ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exam/ExamDateVerification.spec.ts
ts.Exam date verification › Exam timing › Student can start after start Date❌ failure2m 3s 871ms

@github-actions
Copy link

End-to-End (E2E) Test Results Summary

TestsPassed ☑️Skipped ⚠️Failed ❌️Time ⏱
End-to-End (E2E) Test Report215 ran211 passed3 skipped1 failed1h 14m 45s 60ms
TestResultTime ⏱
End-to-End (E2E) Test Report
e2e/exercise/programming/ProgrammingExerciseStaticCodeAnalysis.spec.ts
ts.Static code analysis tests › Configures SCA grading and makes a successful submission with SCA errors❌ failure2m 38s 264ms

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!) communication Pull requests that affect the corresponding module core Pull requests that affect the corresponding module ready for review 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.

FAQ: Sort the FAQ page

7 participants