diff --git a/docs/index.rst b/docs/index.rst index 32c130434e4f..f4a7bc4cf449 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -37,6 +37,7 @@ All these exercises are supposed to be run either live in the lecture with insta user/grading user/courses/customizable user/markdown-support + user/integrated-code-lifecycle user/exports user/mobile-applications user/lti diff --git a/docs/user/exercises/programming-repository-access.inc b/docs/user/exercises/programming-repository-access.inc index 45323fced7dd..c4e201d0f4b6 100644 --- a/docs/user/exercises/programming-repository-access.inc +++ b/docs/user/exercises/programming-repository-access.inc @@ -1,3 +1,5 @@ +If you are a student, and want to know how to use the Artemis Version Control for checking out repositories locally, :ref:`checkout this guide.` + The following tables lists the different types of repositories and gives an overview of the access rights different users have. To gain these access rights, a user must assume the indicated role in the course the repository belongs to. diff --git a/docs/user/exercises/programming.rst b/docs/user/exercises/programming.rst index 6f8a8e00782c..61f1731c4dff 100644 --- a/docs/user/exercises/programming.rst +++ b/docs/user/exercises/programming.rst @@ -224,19 +224,5 @@ Each one represents a single test case feedback and should have the format: Integrated Code Lifecycle ------------------------- -The following sections describe programming exercise features that are part of the integrated code lifecycle system. - -Repository View -^^^^^^^^^^^^^^^ - -.. include:: programming-integrated-code-lifecycle-repository-view.inc - -Build Agent View -^^^^^^^^^^^^^^^^ - -.. include:: programming-integrated-code-lifecycle-build-agent-view.inc - -Build Overview View -^^^^^^^^^^^^^^^^^^^ - -.. include:: programming-integrated-code-lifecycle-build-queue-view.inc +The Artemis Integrated Code Lifecycle system allows you to use programming exercises fully integrated within Artemis, without the need of any external tools. +Find more information on it :ref:`here`. diff --git a/docs/user/exercises/programming/build-agent-details.png b/docs/user/exercises/programming/build-agent-details.png deleted file mode 100644 index ae9d8f2561f4..000000000000 Binary files a/docs/user/exercises/programming/build-agent-details.png and /dev/null differ diff --git a/docs/user/exercises/programming/build-agent-summary.png b/docs/user/exercises/programming/build-agent-summary.png deleted file mode 100644 index 414451407f71..000000000000 Binary files a/docs/user/exercises/programming/build-agent-summary.png and /dev/null differ diff --git a/docs/user/exercises/programming/buildQueueCourseManagement.png b/docs/user/exercises/programming/buildQueueCourseManagement.png deleted file mode 100644 index dc16f6dd6a32..000000000000 Binary files a/docs/user/exercises/programming/buildQueueCourseManagement.png and /dev/null differ diff --git a/docs/user/exercises/programming/buildQueueSystemAdministration.png b/docs/user/exercises/programming/buildQueueSystemAdministration.png deleted file mode 100644 index 1a18244e443a..000000000000 Binary files a/docs/user/exercises/programming/buildQueueSystemAdministration.png and /dev/null differ diff --git a/docs/user/exercises/programming/commit-diff-view.png b/docs/user/exercises/programming/commit-diff-view.png deleted file mode 100644 index cfd5cda349cc..000000000000 Binary files a/docs/user/exercises/programming/commit-diff-view.png and /dev/null differ diff --git a/docs/user/exercises/programming/commit-history-view.png b/docs/user/exercises/programming/commit-history-view.png deleted file mode 100644 index ac691c9c3a60..000000000000 Binary files a/docs/user/exercises/programming/commit-history-view.png and /dev/null differ diff --git a/docs/user/exercises/programming/course-management-repositories.png b/docs/user/exercises/programming/course-management-repositories.png deleted file mode 100644 index 47e842da25a5..000000000000 Binary files a/docs/user/exercises/programming/course-management-repositories.png and /dev/null differ diff --git a/docs/user/exercises/programming/current-repository-content-view.png b/docs/user/exercises/programming/current-repository-content-view.png deleted file mode 100644 index 041b6411f6a1..000000000000 Binary files a/docs/user/exercises/programming/current-repository-content-view.png and /dev/null differ diff --git a/docs/user/exercises/programming/finished-build-jobs.png b/docs/user/exercises/programming/finished-build-jobs.png deleted file mode 100644 index 149a7f98819b..000000000000 Binary files a/docs/user/exercises/programming/finished-build-jobs.png and /dev/null differ diff --git a/docs/user/exercises/programming/open-repository-button.png b/docs/user/exercises/programming/open-repository-button.png deleted file mode 100644 index a758454dead7..000000000000 Binary files a/docs/user/exercises/programming/open-repository-button.png and /dev/null differ diff --git a/docs/user/exercises/programming/open-repository-instructor-participations.png b/docs/user/exercises/programming/open-repository-instructor-participations.png deleted file mode 100644 index 03e9e66e3910..000000000000 Binary files a/docs/user/exercises/programming/open-repository-instructor-participations.png and /dev/null differ diff --git a/docs/user/exercises/programming/open-repository-student.png b/docs/user/exercises/programming/open-repository-student.png deleted file mode 100644 index 5685e134d177..000000000000 Binary files a/docs/user/exercises/programming/open-repository-student.png and /dev/null differ diff --git a/docs/user/exercises/programming/queued-build-jobs.png b/docs/user/exercises/programming/queued-build-jobs.png deleted file mode 100644 index eb7165c01436..000000000000 Binary files a/docs/user/exercises/programming/queued-build-jobs.png and /dev/null differ diff --git a/docs/user/exercises/programming/running-build-jobs.png b/docs/user/exercises/programming/running-build-jobs.png deleted file mode 100644 index 08ccfa8856fd..000000000000 Binary files a/docs/user/exercises/programming/running-build-jobs.png and /dev/null differ diff --git a/docs/user/icl/general.rst b/docs/user/icl/general.rst new file mode 100644 index 000000000000..bf0132e6d20e --- /dev/null +++ b/docs/user/icl/general.rst @@ -0,0 +1,12 @@ +.. _icl-general-information: + +General Information +=================== + +Artemis offers the Integrated Code Lifecycle (ICL), a comprehensive feature designed to streamline the development process for programming exercises. +ICL combines version control, secure communication, and continuous integration to provide a seamless experience for students and instructors. +Understanding these components is crucial for effectively using Artemis, especially if you're new to concepts like SSH and Git. The key components of ICL are: + +- :ref:`Local Version Control`: Use the Local Version Control to interact with the repositories of programming exercises. +- :ref:`SSH`: Use SSH to perform Git operations on repositories. +- :ref:`Local Continuous Integration`: Exercise submissions are built and tested by the Local CI system. diff --git a/docs/user/exercises/programming-integrated-code-lifecycle-build-agent-view.inc b/docs/user/icl/local-ci-build-agent-view.inc similarity index 95% rename from docs/user/exercises/programming-integrated-code-lifecycle-build-agent-view.inc rename to docs/user/icl/local-ci-build-agent-view.inc index a59068be8589..b211e879b252 100644 --- a/docs/user/exercises/programming-integrated-code-lifecycle-build-agent-view.inc +++ b/docs/user/icl/local-ci-build-agent-view.inc @@ -5,7 +5,7 @@ The build agent view consists of two parts: the *Build Agent Summary View* and t The **Build Agent Summary View** shows a list of all build agents in the system, along with their status (idle and running), maximum number of concurrent builds, and running builds. The running builds can be canceled individually by clicking the red cancellation button next to the build. An Administrator can also cancel all running builds on a build agent by clicking the '*Cancel All*' button. -.. figure:: programming/build-agent-summary.png +.. figure:: local-ci/build-agent-summary.png :alt: Build Agent Summary View :align: center @@ -20,7 +20,7 @@ the submission time, start time, end time, the duration of the build job, the co The administrator can click on the participation ID to navigate to the participation's submission page. The administrator can also click on the commit hash to navigate to the commits details page and the course ID to navigate to the course management page. -.. figure:: programming/build-agent-details.png +.. figure:: local-ci/build-agent-details.png :alt: Build Agent Details :align: center diff --git a/docs/user/exercises/programming-integrated-code-lifecycle-build-queue-view.inc b/docs/user/icl/local-ci-build-queue-view.inc similarity index 90% rename from docs/user/exercises/programming-integrated-code-lifecycle-build-queue-view.inc rename to docs/user/icl/local-ci-build-queue-view.inc index 2c2470d9561a..7c865758f98c 100644 --- a/docs/user/exercises/programming-integrated-code-lifecycle-build-queue-view.inc +++ b/docs/user/icl/local-ci-build-queue-view.inc @@ -1,7 +1,7 @@ Artemis provides a build overview view that displays all queued, running, and finished build jobs. Access to the system-wide build overview is exclusively available to **Administrators** through the *System Administration* menu. -.. figure:: programming/buildQueueSystemAdministration.png +.. figure:: local-ci/buildQueueSystemAdministration.png :alt: Build Overview System Administration :align: center @@ -10,7 +10,7 @@ exclusively available to **Administrators** through the *System Administration* **Instructors** can access the build overview for a specific course through the *Build Overview* button located in *Course Management*. This view displays only the queued, running, and finished build jobs associated with the selected course. -.. figure:: programming/buildQueueCourseManagement.png +.. figure:: local-ci/buildQueueCourseManagement.png :alt: Build Overview Course Management :align: center @@ -27,7 +27,7 @@ Jobs are dynamically added to and removed from the queue in real-time. Users have the ability to cancel any job in progress. The table provides the following information: -.. figure:: programming/running-build-jobs.png +.. figure:: local-ci/running-build-jobs.png :alt: Running Build Jobs :align: center @@ -43,7 +43,7 @@ Users also have the option to cancel any job that is queued. The table below displays the following information: -.. figure:: programming/queued-build-jobs.png +.. figure:: local-ci/queued-build-jobs.png :alt: Queued Build Jobs :align: center @@ -59,7 +59,7 @@ Instructors can also access build logs with detailed information about the build The table provides the following information: -.. figure:: programming/finished-build-jobs.png +.. figure:: local-ci/finished-build-jobs.png :alt: Finished Build Jobs :align: center diff --git a/docs/user/icl/local-ci/build-agent-details.png b/docs/user/icl/local-ci/build-agent-details.png new file mode 100644 index 000000000000..4b5b8474781a Binary files /dev/null and b/docs/user/icl/local-ci/build-agent-details.png differ diff --git a/docs/user/icl/local-ci/build-agent-summary.png b/docs/user/icl/local-ci/build-agent-summary.png new file mode 100644 index 000000000000..ec11e28a0d1d Binary files /dev/null and b/docs/user/icl/local-ci/build-agent-summary.png differ diff --git a/docs/user/icl/local-ci/buildQueueCourseManagement.png b/docs/user/icl/local-ci/buildQueueCourseManagement.png new file mode 100644 index 000000000000..d4e255f39988 Binary files /dev/null and b/docs/user/icl/local-ci/buildQueueCourseManagement.png differ diff --git a/docs/user/icl/local-ci/buildQueueSystemAdministration.png b/docs/user/icl/local-ci/buildQueueSystemAdministration.png new file mode 100644 index 000000000000..9a857a317ce8 Binary files /dev/null and b/docs/user/icl/local-ci/buildQueueSystemAdministration.png differ diff --git a/docs/user/icl/local-ci/finished-build-jobs.png b/docs/user/icl/local-ci/finished-build-jobs.png new file mode 100644 index 000000000000..eb7b3dda190d Binary files /dev/null and b/docs/user/icl/local-ci/finished-build-jobs.png differ diff --git a/docs/user/icl/local-ci/queued-build-jobs.png b/docs/user/icl/local-ci/queued-build-jobs.png new file mode 100644 index 000000000000..acd382dfe1f8 Binary files /dev/null and b/docs/user/icl/local-ci/queued-build-jobs.png differ diff --git a/docs/user/icl/local-ci/running-build-jobs.png b/docs/user/icl/local-ci/running-build-jobs.png new file mode 100644 index 000000000000..8cc66a2e5c63 Binary files /dev/null and b/docs/user/icl/local-ci/running-build-jobs.png differ diff --git a/docs/user/icl/local-continuous-integration.rst b/docs/user/icl/local-continuous-integration.rst new file mode 100644 index 000000000000..6c3cdd9b8e65 --- /dev/null +++ b/docs/user/icl/local-continuous-integration.rst @@ -0,0 +1,27 @@ +.. _local-ci: + +Continuous Integration +====================== + +Continuous Integration (CI) is a software development practice where developers frequently merge their code changes into a shared repository. Each change is automatically built and tested, which helps to: + +- Detect and address integration issues early +- Ensure code quality and consistency +- Streamline the development process + +Artemis Local CI is our implementation of these CI principles, tailored to support the Artemis learning platform. +It provides tools and views to help users build and test in programming exercises effectively. + +This document will introduce you to the key components of Artemis Local CI: the Build Agent View and the Build Overview View. +These tools will assist you throughout your development workflow on the Artemis platform. + +Build Agent View +^^^^^^^^^^^^^^^^ + +.. include:: local-ci-build-agent-view.inc + + +Build Overview View +^^^^^^^^^^^^^^^^^^^ + +.. include:: local-ci-build-queue-view.inc diff --git a/docs/user/icl/local-vc-authentication.inc b/docs/user/icl/local-vc-authentication.inc new file mode 100644 index 000000000000..6735cd2743df --- /dev/null +++ b/docs/user/icl/local-vc-authentication.inc @@ -0,0 +1,67 @@ +Cloning a repository +^^^^^^^^^^^^^^^^^^^^ + +You can use Sourcetree, git from the terminal, or any client you like to clone your Git repository. +These instructions show you how to clone your repository using Git from the terminal. + +From the exercise view, click the code button to display the Clone dialog. +Copy the clone URL (either the SSH format or the HTTPS, with or without token). +If you are using the SSH protocol, ensure your public key is stored in your Artemis account settings and loaded on the local system to which you are cloning. +From a terminal window, change to the local directory where you want to clone your repository. + +Paste the command you copied from Bitbucket, for example: + +Clone over HTTPS: + +.. code-block:: bash + + git clone https://username@artemis.cit.tum.de/course/documentation-tests.git + + +Clone over HTTPS with access token: + +.. code-block:: bash + + git clone https://username:accessToken@artemis.cit.tum.de/course/documentation-tests.git + + +Clone over SSH: + +.. code-block:: bash + + git clone ssh://git@artemis.cit.tum.de/course/documentation-tests.git + + +If the clone was successful, a new sub-directory appears on your local drive. +This directory has the same name as the repository that you cloned. +The clone contains the files and metadata that Git requires to maintain the changes you make to the source files. + +Choosing between HTTPS and SSH: + +- HTTPS: Easier to set up initially, works through firewalls, but requires entering credentials more frequently. +- SSH: More secure, doesn't require entering passwords for each operation once set up, but initial setup can be more complex. + +Choose HTTPS if you're new to Git or working in an environment with strict firewall rules. +Choose SSH for enhanced security and convenience in long-term development. + +HTTPS access tokens +^^^^^^^^^^^^^^^^^^^ + +Instructors can create HTTP access tokens for repository access in Artemis. +They are created in the account settings and are used in place of passwords for Git over HTTPS. +For every student's exercise, Artemis automatically generates an access token, only associated with the repository of this particular exercise. +You can use these to authenticate to the Artemis Local Version Control. + +Token Creation +"""""""""""""" + +1. Go to Profile > Settings > VCS token. +2. Create a new token + +Using SSH keys to secure Git operations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Artemis provides a simple way for users to connect securely to repositories, using SSH to perform Git operations. +Next is a :ref:`small and basic introduction to SSH`, and if you already know it, :ref:`here is a guide on how to create SSH keys`. +If you already have an SSH key, :ref:`learn how to add it to your Artemis account here`. + diff --git a/docs/user/exercises/programming-integrated-code-lifecycle-repository-view.inc b/docs/user/icl/local-vc-repository-view.inc similarity index 88% rename from docs/user/exercises/programming-integrated-code-lifecycle-repository-view.inc rename to docs/user/icl/local-vc-repository-view.inc index 5273befacd08..aef46936e99a 100644 --- a/docs/user/exercises/programming-integrated-code-lifecycle-repository-view.inc +++ b/docs/user/icl/local-vc-repository-view.inc @@ -3,13 +3,13 @@ These changes are stored in a repository. A repository is a collection of files How to navigate through the repository and view the code is explained in the following sections. This guide is divided into two parts: one for students and one for instructors. It is demonstrated using course programming exercises, but the same principles apply to exams as well. -For Students -"""""""""""" +Access Repositories as a Student +"""""""""""""""""""""""""""""""" As a student, you can use the repository to view your course submissions. To access your submissions, you need to navigate to the exercise, press the '*Code*' button, and click on |open-repository-button|. -.. figure:: programming/open-repository-student.png +.. figure:: local-vc/open-repository-student.png :alt: Opening the repository in the student view :align: center @@ -22,7 +22,7 @@ To the right side of the screen, above the problem statement, you can see the re the '*Code*' button to clone the repository to your local machine and see the full commit history by pressing the '*Open Commit History*' button. Finally, you can download the repository as a ZIP file by pressing the '*Download Repository*' button. -.. figure:: programming/current-repository-content-view.png +.. figure:: local-vc/current-repository-content-view.png :alt: Current Repository Content :align: center @@ -33,7 +33,7 @@ You can see the commit message, the author of the commit, the date of the commit If you created a submission with multiple commits, you can see all of them here but only the last commit has the result of the submission. Lastly, you can also view the code of the commit by pressing on the commit hash. -.. figure:: programming/commit-history-view.png +.. figure:: local-vc/commit-history-view.png :alt: Commit History View :align: center @@ -44,20 +44,20 @@ You can see the changes in the code, the files that have been added, the files t Green color indicates the lines that have been added and red color indicates the lines that have been deleted. You can also see the commit message, the author of the commit, the date of the commit and the commit hash. -.. figure:: programming/commit-diff-view.png +.. figure:: local-vc/commit-diff-view.png :alt: Commit Diff View :align: center Commit Diff View -For Instructors -""""""""""""""" +Access Repositories as an Instructor +"""""""""""""""""""""""""""""""""""" As an instructor, you can use the repository to view the submissions of your students. For this purpose, you need to navigate to the exercise participations page. Here you can see all the students’ participations for the exercise and navigate to the repository of a student by pressing the '*Code*' button and clicking on |open-repository-button|. This will show the repository of the student just like it is shown to the student. -.. figure:: programming/open-repository-instructor-participations.png +.. figure:: local-vc/open-repository-instructor-participations.png :alt: Open Repository Button in Participations Page :align: center @@ -66,11 +66,11 @@ This will show the repository of the student just like it is shown to the studen You can also see the repositories for an exercises **solution**, **template** and **test** repositories on the exercise management page. You can navigate to these repositories by pressing the '*Code*' button and clicking |open-repository-button| as described above. -.. figure:: programming/course-management-repositories.png +.. figure:: local-vc/course-management-repositories.png :alt: Solution, Template and Test Repositories in Exercise Management Page :align: center Solution, Template and Test Repositories in Exercise Management Page -.. |open-repository-button| image:: programming/open-repository-button.png +.. |open-repository-button| image:: local-vc/open-repository-button.png :scale: 50% diff --git a/docs/user/icl/local-vc/commit-diff-view.png b/docs/user/icl/local-vc/commit-diff-view.png new file mode 100644 index 000000000000..19ebb58be3ab Binary files /dev/null and b/docs/user/icl/local-vc/commit-diff-view.png differ diff --git a/docs/user/icl/local-vc/commit-history-view.png b/docs/user/icl/local-vc/commit-history-view.png new file mode 100644 index 000000000000..2dd208d0de16 Binary files /dev/null and b/docs/user/icl/local-vc/commit-history-view.png differ diff --git a/docs/user/icl/local-vc/course-management-repositories.png b/docs/user/icl/local-vc/course-management-repositories.png new file mode 100644 index 000000000000..ab0af10e9103 Binary files /dev/null and b/docs/user/icl/local-vc/course-management-repositories.png differ diff --git a/docs/user/icl/local-vc/current-repository-content-view.png b/docs/user/icl/local-vc/current-repository-content-view.png new file mode 100644 index 000000000000..961e9f17889b Binary files /dev/null and b/docs/user/icl/local-vc/current-repository-content-view.png differ diff --git a/docs/user/icl/local-vc/open-repository-button.png b/docs/user/icl/local-vc/open-repository-button.png new file mode 100644 index 000000000000..b1b4d60873cd Binary files /dev/null and b/docs/user/icl/local-vc/open-repository-button.png differ diff --git a/docs/user/icl/local-vc/open-repository-instructor-participations.png b/docs/user/icl/local-vc/open-repository-instructor-participations.png new file mode 100644 index 000000000000..bf051e6d644d Binary files /dev/null and b/docs/user/icl/local-vc/open-repository-instructor-participations.png differ diff --git a/docs/user/icl/local-vc/open-repository-student.png b/docs/user/icl/local-vc/open-repository-student.png new file mode 100644 index 000000000000..93312d1cab27 Binary files /dev/null and b/docs/user/icl/local-vc/open-repository-student.png differ diff --git a/docs/user/icl/local-vc/open-settings.png b/docs/user/icl/local-vc/open-settings.png new file mode 100644 index 000000000000..84c13407ab74 Binary files /dev/null and b/docs/user/icl/local-vc/open-settings.png differ diff --git a/docs/user/icl/local-vc/ssh-add-public-key.png b/docs/user/icl/local-vc/ssh-add-public-key.png new file mode 100644 index 000000000000..3e4683c09b7e Binary files /dev/null and b/docs/user/icl/local-vc/ssh-add-public-key.png differ diff --git a/docs/user/icl/local-version-control.rst b/docs/user/icl/local-version-control.rst new file mode 100644 index 000000000000..1ca1c1c2c31c --- /dev/null +++ b/docs/user/icl/local-version-control.rst @@ -0,0 +1,16 @@ +.. _local-vc: + +Local Version Control +===================== + +.. contents:: Content of this document + :local: + :depth: 2 + + +Repository View +^^^^^^^^^^^^^^^ + +.. include:: local-vc-repository-view.inc + +.. include:: local-vc-authentication.inc diff --git a/docs/user/icl/ssh-add-key-to-artemis.rst b/docs/user/icl/ssh-add-key-to-artemis.rst new file mode 100644 index 000000000000..0e3425faa501 --- /dev/null +++ b/docs/user/icl/ssh-add-key-to-artemis.rst @@ -0,0 +1,68 @@ +.. _use ssh key: + +Using SSH with Artemis +^^^^^^^^^^^^^^^^^^^^^^ + +.. contents:: Content of this document + :local: + :depth: 1 + +You can use SSH keys to establish a secure connection between your computer and Artemis when you are performing Git operations (pull, clone, push) from your local machine. +Personal keys are linked to your Artemis account, inheriting its permissions and operating under its unique identity. +To use your generated SSH keys with Artemis, you need to add it in the account settings. + + +Add an SSH key to your Artemis account +"""""""""""""""""""""""""""""""""""""" + +**1. Copy your public key** + +On Windows in your command prompt, change directory to your `.ssh` directory, and copy the public key file to your clipboard by running: + +.. code-block:: bash + + cd %userprofile%/.ssh + clip < id_ed25519.pub + +On macOS or Linux simply run the following in a terminal: + +.. _xclip: https://wiki.ubuntuusers.de/xclip/ + +.. code-block:: bash + + pbcopy < ~/.ssh/id_ed25519.pub + +If `pbcopy` isn't working, locate the hidden `.ssh` folder, open the file in a text editor, and copy it to your clipboard. +Note that on Linux, you may need to download and install `xclip`_, then use that, as shown in this code snippet: + +.. code-block:: bash + + sudo apt-get install xclip + xclip -sel clip < ~/.ssh/id_ed25519.pub + +Note that the key's name is not necessarily **id_ed25519.pub**, but can be arbitrary, and depends on how you saved it. + + +**2. Add the key to your Artemis account** + +Open the settings, go to the SSH tab, and select 'New Key'. +Then paste the copied SSH key into the text box. + ++---------------------------------------------------+--------------------------------------------------------------+ +|.. figure:: local-vc/open-settings.png | .. figure:: local-vc/ssh-add-public-key.png | +| :alt: Open account settings | :alt: Add public SSH key to account | +| :align: center | :align: center | +| | | +| Open you Artemis account settings | Add public SSH key to account in account settings | ++---------------------------------------------------+--------------------------------------------------------------+ + +**3. Save the key. You're done!** + +Use SSH to connect to Artemis repositories +"""""""""""""""""""""""""""""""""""""""""" + +After everything is set up, you can go to a programming exercise, and use the SSH clone URL with git to access the repository locally, like this, for example: + +.. code-block:: bash + + git clone ssh://git@artemis.cit.tum.de:7921/git/COURSE/exercise-user_1.git diff --git a/docs/user/icl/ssh-intro.rst b/docs/user/icl/ssh-intro.rst new file mode 100644 index 000000000000..fd41034ebe5d --- /dev/null +++ b/docs/user/icl/ssh-intro.rst @@ -0,0 +1,67 @@ +.. _basic SSH introduction: + +SSH +^^^ + +.. contents:: Content of this document + :local: + :depth: 2 + +Artemis uses SSH as a simple way for users to connect securely to repositories to perform Git operations. + +What is SSH? +"""""""""""" + +.. _SSH (Secure Shell): https://en.wikipedia.org/wiki/Secure_Shell + +`SSH (Secure Shell)`_ is a protocol that allows you to securely connect to another computer over a network. +It’s mostly used by system administrators, developers, and IT professionals to remotely manage servers or computers. +SSH provides a secure and encrypted communication channel between your computer and a remote machine, so any data passed (like passwords or commands) is protected from eavesdropping. +In Artemis you an use SSH to access your repositories with Git. + +Why use SSH? +"""""""""""" + +The main advantage of SSH is security. +When you connect to a remote machine using SSH, all the data exchanged between your computer and the server is encrypted. +This means if someone tries to intercept the communication, they can't read it. It's like sending messages through a locked box that only you and the server can open. + +How does SSH work? +"""""""""""""""""" + +SSH works by using two components: + +- Client: The computer you are using to connect. +- Server: The machine you want to connect to. + +When you want to connect, your SSH client sends a request to the server. +If the connection is successful, you can log in to the server and start working as if you were sitting in front of it. +The connection uses SSH keys for authentication. Although it is also possible to use username and password to connect over SSH, this is discouraged. + +What are SSH Keys? +"""""""""""""""""" + +.. _public-key cryptography: https://en.wikipedia.org/wiki/Public-key_cryptography + + +SSH keys are a more secure alternative to passwords for logging into a server. +They are based on `public-key cryptography`_ and come in pairs: a public key and a private key. + +- Public Key: This key is stored on the server. Think of it like a lock that only you can open. +- Private Key: This key stays on your local machine (never shared!). It’s like the key to that lock. + +When you try to connect to the server, your computer proves it has the private key that matches the server's public key, granting you access. +You can add a personal SSH key to your user account to easily authenticate when performing read operations from your local machine. +An Artemis user can currently add one key to their account. +For instructions on how to add your SSH key to your Artemis account, please refer to :ref:`the relevant documentation`. + +Before you can use SSH keys to secure a connection with Artemis the following must have already been done: + +- SSH is enabled on your university's Artemis instance +- You need an SSH key! See :ref:`Creating SSH keys`. + +.. note:: + + - You can use the same SSH key for multiple repositories or projects. + - An Artemis user can currently only add one key to their account. + - Artemis supports ECDSA, RSA2, and Ed25519 key types. diff --git a/docs/user/icl/ssh-key-creation.rst b/docs/user/icl/ssh-key-creation.rst new file mode 100644 index 000000000000..58e7b01f5a4d --- /dev/null +++ b/docs/user/icl/ssh-key-creation.rst @@ -0,0 +1,161 @@ +.. _create ssh key: + +Creating SSH keys +^^^^^^^^^^^^^^^^^ + +.. contents:: Content of this document + :local: + :depth: 2 + +SSH keys can be used to establish a secure connection with the Artemis Local Version Control, where you are performing Git operations from your local machine. +The SSH key needs to be added to Artemis before you can make use of the key. + +Creating an SSH key on Windows +"""""""""""""""""""""""""""""" + +**1. Check for existing keys** + +You should check for existing SSH keys on your local computer. Open a command prompt, and run: + +.. code-block:: bash + + cd %userprofile%/.ssh + +- If you see "No such file or directory", then there aren't any existing keys: go to step 3. + +- Check to see if you have a key already: + +.. code-block:: bash + + dir id_* + +If there are existing keys, you may want to use those: :ref:`Add your key to Artemis`. + +**2. Back up old SSH keys** + +If you have existing SSH keys, but you don't want to use them when connecting to Bitbucket, you should back those up. +In a command prompt on your local computer, run: + +.. code-block:: bash + + mkdir key_backup + copy * key_backup + +**3. Generate a new SSH key** + +If you don't have an existing SSH key that you wish to use, generate one as follows: +1. Log in to your local computer as an administrator. +2. In a command prompt, run: + +.. _Git (with Git Bash): https://gitforwindows.org/ + + +.. code-block:: bash + + ssh-keygen -t ed25519 -C "your_email@example.com" + +Associating the key with your email address helps you to identify the key later on. +Note that the `ssh-keygen` command is only available if you have already installed `Git (with Git Bash)`_. +You'll see a response similar to this: + +.. code-block:: bash + + C:\Users\artemis>ssh-keygen -t ed25519 -C "your_email@example.com" + Generating public/private ed25519 key pair. + Enter file in which to save the key (/c/Users/artemis/.ssh/id_ed25519): + +3. Just press to accept the default location and file name. If the .ssh directory doesn't exist, the system creates one for you. +4. Enter, and re-enter, a passphrase when prompted. The whole interaction will look similar to this: + +.. code-block:: bash + + C:\Users\artemis>ssh-keygen -t ed25519 -C "your_email@example.com" + Generating public/private ed25519 key pair. + Enter file in which to save the key (/c/Users/artemis/.ssh/id_ed25519): + Created directory '/c/Users/artemis/.ssh'. + Enter passphrase (empty for no passphrase): + Enter same passphrase again: + Your identification has been saved in c/Users/artemis/.ssh/id_ed25519. + Your public key has been saved in c/Users/artemis/.ssh/id_ed25519.pub. + The key fingerprint is: + SHA256:wvaHYeLtY6+DlvV5sFZgDi3abcdefghijklmnopqrstuvw your_email@example.com + +5. You're done and you can now :ref:`add your key to Artemis`. + +Creating an SSH key on Linux & macOS +"""""""""""""""""""""""""""""""""""" + +**1. Check for existing SSH keys** + +You should check for existing SSH keys on your local computer. Open a terminal and run: + +.. code-block:: bash + + cd ~/.ssh + +If you see "No such file or directory, then there aren't any existing keys: go to step 3. +Check to see if you have a key already: + +.. code-block:: bash + + ls id_* + +If there are existing keys, you may want to use those: :ref:`Add your key to Artemis`. + +**2. Back up old SSH keys** + +If you have existing SSH keys, but you don't want to use them when connecting to Bitbucket, you should back those up. +In a command prompt on your local computer, run: + +.. code-block:: bash + + mkdir key_backup + cp * key_backup + +**3. Generate a new SSH key** + +If you don't have an existing SSH key that you wish to use, generate one as follows: + +1. Open a terminal on your local computer and enter the following: + +.. code-block:: bash + + ssh-keygen -t ed25519 -C "your_email@example.com" + +Associating the key with your email address helps you to identify the key later on. You'll see a response similar to this: + +.. code-block:: bash + + artemis@homemac ~ % ssh-keygen -t ed25519 -C artemis@email.com + Generating public/private ed25519 key pair. + Enter file in which to save the key (/Users/artemis/.ssh/id_ed25519): + +2. Just press to accept the default location and file name. If the .ssh directory doesn't exist, the system creates one for you. +3. Enter, and re-enter, a passphrase when prompted. The whole interaction will look similar to this: + +.. code-block:: bash + + artemis@homemac ~ % ssh-keygen -t ed25519 -C artemis@email.com + Generating public/private ed25519 key pair. + Enter file in which to save the key (/Users/artemis/.ssh/id_ed25519): + Enter passphrase (empty for no passphrase): + Enter same passphrase again: + Your identification has been saved in /Users/artemis/.ssh/id_ed25519. + Your public key has been saved in /Users/artemis/.ssh/id_ed25519.pub. + The key fingerprint is: + SHA256:gTVWKbn41z6JgBNu3wYjLC4abcdefghijklmnopqrstuvwxy artemis@email.com + The keys randomart image is: + +--[ED25519 256]--+ + |==+. +o.. | + |.oE. +o.. | + | . ...o | + | .o... | + | oo+S . | + | + ..B = . . | + |.+.+.oo+ * o . | + |o++.o+ . + + | + |B+ o. . . | + +----[SHA256]-----+ + artemis@homemac ~ % + +4. You're done and you can now :ref:`add your key to Artemis`. diff --git a/docs/user/integrated-code-lifecycle.rst b/docs/user/integrated-code-lifecycle.rst new file mode 100644 index 000000000000..9e5ab5231ef0 --- /dev/null +++ b/docs/user/integrated-code-lifecycle.rst @@ -0,0 +1,15 @@ +.. _integrated code lifecycle: + +Integrated Code Lifecycle +========================= + +Artemis' Integrated Code Lifecycle consists of two main components: Local Version Control and Local Continuous Integration. + +.. toctree:: + + icl/general + icl/local-version-control + icl/ssh-intro + icl/ssh-key-creation + icl/ssh-add-key-to-artemis + icl/local-continuous-integration diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/CompetencyInformationDTO.java b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/CompetencyInformationDTO.java index 02e0fc7edeb2..f361bc402718 100644 --- a/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/CompetencyInformationDTO.java +++ b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/CompetencyInformationDTO.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonInclude; +import de.tum.cit.aet.artemis.atlas.domain.competency.Competency; import de.tum.cit.aet.artemis.atlas.domain.competency.CompetencyTaxonomy; /** @@ -19,4 +20,15 @@ */ @JsonInclude(JsonInclude.Include.NON_EMPTY) public record CompetencyInformationDTO(long id, String title, String description, CompetencyTaxonomy taxonomy, ZonedDateTime softDueDate, boolean optional, int masteryThreshold) { + + /** + * Creates a CompetencyInformationDTO from a Competency. + * + * @param competency the Competency to create the DTO from + * @return the created DTO + */ + public static CompetencyInformationDTO of(C competency) { + return new CompetencyInformationDTO(competency.getId(), competency.getTitle(), competency.getDescription(), competency.getTaxonomy(), competency.getSoftDueDate(), + competency.isOptional(), competency.getMasteryThreshold()); + } } diff --git a/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/LectureUnitInformationDTO.java b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/LectureUnitInformationDTO.java index 3a5d9cc8bcb4..8f4016a5f346 100644 --- a/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/LectureUnitInformationDTO.java +++ b/src/main/java/de/tum/cit/aet/artemis/atlas/dto/metrics/LectureUnitInformationDTO.java @@ -18,4 +18,15 @@ */ @JsonInclude(JsonInclude.Include.NON_EMPTY) public record LectureUnitInformationDTO(long id, long lectureId, String lectureTitle, String name, ZonedDateTime releaseDate, Class type) { + + /** + * Creates a LectureUnitInformationDTO from a LectureUnit. + * + * @param lectureUnit the LectureUnit to create the DTO from + * @return the created DTO + */ + public static LectureUnitInformationDTO of(L lectureUnit) { + return new LectureUnitInformationDTO(lectureUnit.getId(), lectureUnit.getLecture().getId(), lectureUnit.getLecture().getTitle(), lectureUnit.getName(), + lectureUnit.getReleaseDate(), lectureUnit.getClass()); + } } diff --git a/src/main/webapp/app/course/learning-paths/pages/learning-path-student-page/learning-path-student-page.component.ts b/src/main/webapp/app/course/learning-paths/pages/learning-path-student-page/learning-path-student-page.component.ts index 8366f6d25e22..7857288daba1 100644 --- a/src/main/webapp/app/course/learning-paths/pages/learning-path-student-page/learning-path-student-page.component.ts +++ b/src/main/webapp/app/course/learning-paths/pages/learning-path-student-page/learning-path-student-page.component.ts @@ -10,13 +10,14 @@ import { LearningPathExerciseComponent } from 'app/course/learning-paths/compone import { LearningPathApiService } from 'app/course/learning-paths/services/learning-path-api.service'; import { LearningPathNavigationService } from 'app/course/learning-paths/services/learning-path-navigation.service'; import { onError } from 'app/shared/util/global.utils'; +import { TranslateDirective } from 'app/shared/language/translate.directive'; @Component({ selector: 'jhi-learning-path-student-page', templateUrl: './learning-path-student-page.component.html', styleUrl: './learning-path-student-page.component.scss', standalone: true, - imports: [LearningPathNavComponent, LearningPathLectureUnitComponent, LearningPathExerciseComponent], + imports: [LearningPathNavComponent, LearningPathLectureUnitComponent, LearningPathExerciseComponent, TranslateDirective], }) export class LearningPathStudentPageComponent { protected readonly LearningObjectType = LearningObjectType; diff --git a/src/main/webapp/app/exam/participate/exercises/file-upload/file-upload-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/file-upload/file-upload-exam-submission.component.html index be5dce5a54a3..be860bc79852 100644 --- a/src/main/webapp/app/exam/participate/exercises/file-upload/file-upload-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/file-upload/file-upload-exam-submission.component.html @@ -15,7 +15,7 @@


- {{ examTimeline ? exercise.title : (exercise?.exerciseGroup?.title ?? '-') }} + {{ examTimeline ? exercise.title : ('artemisApp.exam.yourSolution' | artemisTranslate) }}
@if (isActive && !result && exercise && studentSubmission && !readonly) { diff --git a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html index 273a1acbb8e5..aa3306277c53 100644 --- a/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/modeling/modeling-exam-submission.component.html @@ -16,7 +16,7 @@

- {{ examTimeline ? exercise.title : (exercise?.exerciseGroup?.title ?? '-') }} + {{ examTimeline ? exercise.title : ('artemisApp.exam.yourSolution' | artemisTranslate) }}
diff --git a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html index 653d0f6b0ad5..cc0a6fba438f 100644 --- a/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html +++ b/src/main/webapp/app/exam/participate/exercises/text/text-exam-submission.component.html @@ -16,7 +16,7 @@

- {{ examTimeline ? exercise.title : (exercise?.exerciseGroup?.title ?? '-') }} + {{ examTimeline ? exercise.title : ('artemisApp.exam.yourSolution' | artemisTranslate) }}
diff --git a/src/main/webapp/app/overview/courses.component.html b/src/main/webapp/app/overview/courses.component.html index a9d1655aba7c..5836c04911c3 100644 --- a/src/main/webapp/app/overview/courses.component.html +++ b/src/main/webapp/app/overview/courses.component.html @@ -19,28 +19,32 @@

{{ nextRelevantExam.title }}

} -
-
-

- @if (regularCourses.length) { -
- +
+
+

{{ 'artemisApp.studentDashboard.title' | artemisTranslate }} ({{ regularCourses.length + recentlyAccessedCourses.length }})

+
+ - } + + @if (regularCourses.length) { + + } +
@if (recentlyAccessedCourses.length) {

-
-
- @for (course of recentlyAccessedCourses; track course) { -
- -
- } -
-
+ @if (regularCourses.length) {

@@ -55,18 +59,26 @@

+ } +

+ + + @if ((courses | searchFilter: ['title'] : searchCourseText).length > 0) {
-
- @for (course of regularCourses; track course) { +
+ @for (course of courses | searchFilter: ['title'] : searchCourseText; track course) {
- +
}
+ } @else { + @if (coursesLoaded) { +
+ +
+ } } -
- - - diff --git a/src/main/webapp/app/overview/courses.component.ts b/src/main/webapp/app/overview/courses.component.ts index fad63ba437cb..2ad16cae7fcd 100644 --- a/src/main/webapp/app/overview/courses.component.ts +++ b/src/main/webapp/app/overview/courses.component.ts @@ -10,7 +10,7 @@ import { JhiWebsocketService } from 'app/core/websocket/websocket.service'; import dayjs from 'dayjs/esm'; import { Exam } from 'app/entities/exam/exam.model'; import { Router } from '@angular/router'; -import { faPenAlt } from '@fortawesome/free-solid-svg-icons'; +import { faArrowDownAZ, faArrowUpAZ, faDoorOpen, faPenAlt } from '@fortawesome/free-solid-svg-icons'; import { CourseAccessStorageService } from 'app/course/course-access-storage.service'; import { CourseForDashboardDTO } from 'app/course/manage/course-for-dashboard-dto'; import { sortCourses } from 'app/shared/util/course.util'; @@ -21,6 +21,11 @@ import { sortCourses } from 'app/shared/util/course.util'; styleUrls: ['./courses.component.scss'], }) export class CoursesComponent implements OnInit, OnDestroy { + protected readonly faPenAlt = faPenAlt; + protected readonly faArrowDownAZ = faArrowDownAZ; + protected readonly faArrowUpAZ = faArrowUpAZ; + protected readonly faDoorOpen = faDoorOpen; + courses: Course[]; public nextRelevantCourse?: Course; nextRelevantCourseForExam?: Course; @@ -31,11 +36,10 @@ export class CoursesComponent implements OnInit, OnDestroy { courseForGuidedTour?: Course; quizExercisesChannels: string[] = []; - - // Icons - faPenAlt = faPenAlt; + searchCourseText = ''; coursesLoaded = false; + isSortAscending = true; constructor( private courseService: CourseManagementService, @@ -125,4 +129,19 @@ export class CoursesComponent implements OnInit, OnDestroy { openExam(): void { this.router.navigate(['courses', this.nextRelevantCourseForExam?.id, 'exams', this.nextRelevantExam!.id]); } + + setSearchValue(searchValue: string): void { + this.searchCourseText = searchValue; + } + + /** + * Sorts the courses in alphabetical order + */ + onSort(): void { + if (this.courses) { + this.isSortAscending = !this.isSortAscending; + this.regularCourses = [...sortCourses(this.regularCourses, this.isSortAscending)]; + this.recentlyAccessedCourses = [...sortCourses(this.recentlyAccessedCourses, this.isSortAscending)]; + } + } } diff --git a/src/main/webapp/app/shared/util/course.util.ts b/src/main/webapp/app/shared/util/course.util.ts index ae49c6318b8c..ce1d2f00c2af 100644 --- a/src/main/webapp/app/shared/util/course.util.ts +++ b/src/main/webapp/app/shared/util/course.util.ts @@ -4,8 +4,12 @@ import { Course } from 'app/entities/course.model'; * Sorts an array of Course objects alphabetically by their title. * * @param {Course[]} courses - The array of Course objects to be sorted. + * @param {boolean} isSortAscending - Sort direction, it is ascending by default. * @returns {Course[]} The sorted array of Course objects. */ -export function sortCourses(courses: Course[]): Course[] { - return courses.sort((courseA, courseB) => (courseA.title ?? '').localeCompare(courseB.title ?? '')); +export function sortCourses(courses: Course[], isSortAscending: boolean = true): Course[] { + return courses.sort((courseA, courseB) => { + const sortOrder = (courseA.title ?? '').localeCompare(courseB.title ?? ''); + return isSortAscending ? sortOrder : -sortOrder; + }); } diff --git a/src/main/webapp/i18n/de/exam.json b/src/main/webapp/i18n/de/exam.json index a528405b3451..ff6b4685e0f5 100644 --- a/src/main/webapp/i18n/de/exam.json +++ b/src/main/webapp/i18n/de/exam.json @@ -150,6 +150,7 @@ "falseName": "Der angegebene Name ist nicht korrekt. Bitte versuche es erneut!", "notSet": "Nicht gesetzt", "startExamToolTip": "Button wird 5 Minuten vor der Klausur aktiviert.", + "yourSolution": "Deine Lösung", "cleanup": { "title": "Aufräumen", "question": "Möchtest du die Prüfung {{title}} wirklich bereinigen? Dadurch werden alle Studierenden-Repositories in der Prüfung gelöscht. Diese Aktion kann NICHT rückgängig gemacht werden!" diff --git a/src/main/webapp/i18n/de/student-dashboard.json b/src/main/webapp/i18n/de/student-dashboard.json index cb10f2199d96..5906220b4d8a 100644 --- a/src/main/webapp/i18n/de/student-dashboard.json +++ b/src/main/webapp/i18n/de/student-dashboard.json @@ -4,6 +4,7 @@ "title": "Deine aktuellen Kurse", "recentlyAccessed": "Zuletzt besuchte Kurse", "otherCourses": "Andere Kurse", + "sort": "Sortieren", "noCourses": "Du bist in keinem Kurs eingeschrieben. Schreibe dich manuell ein oder kontaktiere die Lehrenden.", "exerciseTitle": "Aktuelle aktive Übung von \"{{ course }}\"", "exerciseTitleWithoutDueDate": "Aktuelle Übung von \"{{ course }}\":", @@ -15,6 +16,7 @@ "points": "{{ totalAbsoluteScore }} / {{ totalReachableScore }} Punkte", "cardScore": "Punktzahl", "cardManageCourse": "Kurs Verwalten", + "noCoursesFound": "Keine Kurse gefunden", "enroll": { "title": "Kurseinschreibung", "enrollSuccessful": "Einschreibung erfolgreich", diff --git a/src/main/webapp/i18n/en/exam.json b/src/main/webapp/i18n/en/exam.json index 4ed4737897a0..713a9a92fd1a 100644 --- a/src/main/webapp/i18n/en/exam.json +++ b/src/main/webapp/i18n/en/exam.json @@ -150,6 +150,7 @@ "falseName": "Entered name is incorrect. Please try again!", "notSet": "Not set", "startExamToolTip": "Button will be activated 5 minutes before the exam start.", + "yourSolution": "Your Solution", "cleanup": { "title": "Cleanup", "question": "Are you sure you want to clean up the exam {{ title }}? This will delete all student programming exercise repositories in the exam. This action can NOT be undone!" diff --git a/src/main/webapp/i18n/en/student-dashboard.json b/src/main/webapp/i18n/en/student-dashboard.json index 8660888fb761..b9eddb4ecfa3 100644 --- a/src/main/webapp/i18n/en/student-dashboard.json +++ b/src/main/webapp/i18n/en/student-dashboard.json @@ -5,6 +5,7 @@ "recentlyAccessed": "Recently accessed courses", "otherCourses": "Other courses", "noCourses": "You are not enrolled in any courses. Enroll manually or contact your course instructor.", + "sort": "Sort", "exerciseTitle": "Current active exercise in \"{{ course }}\"", "exerciseTitleWithoutDueDate": "Current exercise in \"{{ course }}\":", "examTitle": "Current exam in \"{{ course }}\":", @@ -15,6 +16,7 @@ "points": "{{ totalAbsoluteScore }} / {{ totalReachableScore }} Points", "cardScore": "Score", "cardManageCourse": "Manage Course", + "noCoursesFound": "No Courses Found", "enroll": { "title": "Course Enrollment", "enrollSuccessful": "Enrollment successful", diff --git a/src/test/java/de/tum/cit/aet/artemis/assessment/service/CourseScoreCalculationServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/assessment/service/CourseScoreCalculationServiceTest.java index 89d594d99982..f6c323c8e798 100644 --- a/src/test/java/de/tum/cit/aet/artemis/assessment/service/CourseScoreCalculationServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/assessment/service/CourseScoreCalculationServiceTest.java @@ -35,7 +35,6 @@ import de.tum.cit.aet.artemis.exercise.domain.IncludedInOverallScore; import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository; import de.tum.cit.aet.artemis.plagiarism.domain.PlagiarismVerdict; import de.tum.cit.aet.artemis.quiz.domain.QuizExercise; @@ -45,9 +44,6 @@ class CourseScoreCalculationServiceTest extends AbstractSpringIntegrationIndepen private static final String TEST_PREFIX = "cscservicetest"; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private StudentParticipationTestRepository studentParticipationRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/assessment/util/StudentScoreUtilService.java b/src/test/java/de/tum/cit/aet/artemis/assessment/util/StudentScoreUtilService.java index 409c18fdc45d..a2e9aeee3da1 100644 --- a/src/test/java/de/tum/cit/aet/artemis/assessment/util/StudentScoreUtilService.java +++ b/src/test/java/de/tum/cit/aet/artemis/assessment/util/StudentScoreUtilService.java @@ -34,6 +34,23 @@ public void createStudentScore(Exercise exercise, User user, double score) { studentScoreRepository.save(studentScore); } + /** + * Creates rated and normal score (which are set equal) for given exercise and user. + * + * @param exercise the exercise to link the student score to + * @param user the user that is linked to the score + * @param score the score and rated score that the specified user has reached for the given exercise + */ + public void createRatedStudentScore(Exercise exercise, User user, double score) { + final var studentScore = new StudentScore(); + studentScore.setExercise(exercise); + studentScore.setUser(user); + studentScore.setLastScore(score); + studentScore.setLastPoints(exercise.getMaxPoints() * score / 100); + studentScore.setLastRatedScore(score); + studentScoreRepository.save(studentScore); + } + /** * Creates student score for given exercise and user. * diff --git a/src/test/java/de/tum/cit/aet/artemis/atlas/competency/util/CompetencyUtilService.java b/src/test/java/de/tum/cit/aet/artemis/atlas/competency/util/CompetencyUtilService.java index 411228bd332a..bca2072b19d0 100644 --- a/src/test/java/de/tum/cit/aet/artemis/atlas/competency/util/CompetencyUtilService.java +++ b/src/test/java/de/tum/cit/aet/artemis/atlas/competency/util/CompetencyUtilService.java @@ -18,7 +18,7 @@ import de.tum.cit.aet.artemis.core.domain.Course; import de.tum.cit.aet.artemis.core.domain.User; import de.tum.cit.aet.artemis.exercise.domain.Exercise; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.lecture.domain.LectureUnit; import de.tum.cit.aet.artemis.lecture.repository.LectureUnitRepository; @@ -35,7 +35,7 @@ public class CompetencyUtilService { private LectureUnitRepository lectureUnitRepository; @Autowired - private ExerciseRepository exerciseRepository; + private ExerciseTestRepository exerciseRepository; @Autowired private CompetencyRelationRepository competencyRelationRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/atlas/service/LearningPathServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/atlas/service/LearningPathServiceTest.java index 6717bbd6b508..65143ebdf769 100644 --- a/src/test/java/de/tum/cit/aet/artemis/atlas/service/LearningPathServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/atlas/service/LearningPathServiceTest.java @@ -41,7 +41,6 @@ import de.tum.cit.aet.artemis.core.util.CourseUtilService; import de.tum.cit.aet.artemis.exercise.domain.DifficultyLevel; import de.tum.cit.aet.artemis.exercise.domain.Exercise; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.lecture.domain.Lecture; import de.tum.cit.aet.artemis.lecture.domain.LectureUnit; import de.tum.cit.aet.artemis.lecture.repository.LectureUnitRepository; @@ -80,9 +79,6 @@ class LearningPathServiceTest extends AbstractSpringIntegrationIndependentTest { @Autowired private CompetencyProgressUtilService competencyProgressUtilService; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private StudentScoreUtilService studentScoreUtilService; diff --git a/src/test/java/de/tum/cit/aet/artemis/communication/notification/GroupNotificationServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/communication/notification/GroupNotificationServiceTest.java index 88dbd05d6ccb..4ccf0116d463 100644 --- a/src/test/java/de/tum/cit/aet/artemis/communication/notification/GroupNotificationServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/communication/notification/GroupNotificationServiceTest.java @@ -61,7 +61,6 @@ import de.tum.cit.aet.artemis.exam.repository.ExamRepository; import de.tum.cit.aet.artemis.exam.util.ExamUtilService; import de.tum.cit.aet.artemis.exercise.domain.Exercise; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.lecture.domain.Attachment; import de.tum.cit.aet.artemis.lecture.domain.Lecture; import de.tum.cit.aet.artemis.programming.domain.ProgrammingExercise; @@ -82,9 +81,6 @@ class GroupNotificationServiceTest extends AbstractSpringIntegrationIndependentT @Autowired private NotificationSettingRepository notificationSettingRepository; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private ExamRepository examRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationScheduleServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationScheduleServiceTest.java index f3dc650315c9..21b6a8abdaed 100644 --- a/src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationScheduleServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/communication/notification/NotificationScheduleServiceTest.java @@ -32,7 +32,6 @@ import de.tum.cit.aet.artemis.core.util.CourseUtilService; import de.tum.cit.aet.artemis.exercise.domain.Exercise; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationLocalCILocalVCTest; import de.tum.cit.aet.artemis.text.domain.TextSubmission; import de.tum.cit.aet.artemis.text.util.TextExerciseFactory; @@ -44,9 +43,6 @@ class NotificationScheduleServiceTest extends AbstractSpringIntegrationLocalCILo @Autowired private InstanceMessageReceiveService instanceMessageReceiveService; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private NotificationRepository notificationRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java index 9faaf7d03bc3..9a3f7db09aff 100644 --- a/src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/communication/notification/SingleUserNotificationServiceTest.java @@ -90,7 +90,6 @@ import de.tum.cit.aet.artemis.core.util.CourseUtilService; import de.tum.cit.aet.artemis.exercise.domain.Exercise; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.fileupload.domain.FileUploadExercise; import de.tum.cit.aet.artemis.fileupload.util.FileUploadExerciseUtilService; import de.tum.cit.aet.artemis.lecture.domain.Lecture; @@ -118,9 +117,6 @@ class SingleUserNotificationServiceTest extends AbstractSpringIntegrationIndepen @Autowired private NotificationSettingRepository notificationSettingRepository; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private ResultTestRepository resultRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/communication/service/EmailSummaryServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/communication/service/EmailSummaryServiceTest.java index 3e83e09a225c..4a42a5a826a5 100644 --- a/src/test/java/de/tum/cit/aet/artemis/communication/service/EmailSummaryServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/communication/service/EmailSummaryServiceTest.java @@ -29,7 +29,6 @@ import de.tum.cit.aet.artemis.core.util.CourseUtilService; import de.tum.cit.aet.artemis.exercise.domain.DifficultyLevel; import de.tum.cit.aet.artemis.exercise.domain.Exercise; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationIndependentTest; import de.tum.cit.aet.artemis.text.util.TextExerciseFactory; @@ -40,9 +39,6 @@ class EmailSummaryServiceTest extends AbstractSpringIntegrationIndependentTest { @Autowired private EmailSummaryService weeklyEmailSummaryService; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private NotificationSettingRepository notificationSettingRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/communication/util/ConversationUtilService.java b/src/test/java/de/tum/cit/aet/artemis/communication/util/ConversationUtilService.java index 46a2adbe005e..1d581ffc7c66 100644 --- a/src/test/java/de/tum/cit/aet/artemis/communication/util/ConversationUtilService.java +++ b/src/test/java/de/tum/cit/aet/artemis/communication/util/ConversationUtilService.java @@ -37,7 +37,7 @@ import de.tum.cit.aet.artemis.core.user.util.UserUtilService; import de.tum.cit.aet.artemis.core.util.CourseFactory; import de.tum.cit.aet.artemis.core.util.CourseUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.exercise.util.ExerciseUtilService; import de.tum.cit.aet.artemis.lecture.domain.Lecture; import de.tum.cit.aet.artemis.lecture.repository.LectureRepository; @@ -64,7 +64,7 @@ public class ConversationUtilService { private CourseTestRepository courseRepo; @Autowired - private ExerciseRepository exerciseRepo; + private ExerciseTestRepository exerciseRepo; @Autowired private LectureRepository lectureRepo; diff --git a/src/test/java/de/tum/cit/aet/artemis/connectors/Lti13ServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/connectors/Lti13ServiceTest.java index b1c21105fbb9..5fc135207c5f 100644 --- a/src/test/java/de/tum/cit/aet/artemis/connectors/Lti13ServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/connectors/Lti13ServiceTest.java @@ -55,7 +55,7 @@ import de.tum.cit.aet.artemis.core.test_repository.UserTestRepository; import de.tum.cit.aet.artemis.exercise.domain.Exercise; import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.lti.config.Lti13TokenRetriever; import de.tum.cit.aet.artemis.lti.domain.LtiPlatformConfiguration; import de.tum.cit.aet.artemis.lti.domain.LtiResourceLaunch; @@ -78,7 +78,7 @@ class Lti13ServiceTest { private UserTestRepository userRepository; @Mock - private ExerciseRepository exerciseRepository; + private ExerciseTestRepository exerciseRepository; @Mock private CourseTestRepository courseRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/core/MetricsIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/core/MetricsIntegrationTest.java index aa126be537b7..2b1b73492764 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/MetricsIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/MetricsIntegrationTest.java @@ -1,20 +1,20 @@ package de.tum.cit.aet.artemis.core; +import static de.tum.cit.aet.artemis.core.config.Constants.MIN_SCORE_GREEN; import static de.tum.cit.aet.artemis.core.util.TimeUtil.toRelativeTime; import static org.assertj.core.api.Assertions.assertThat; -import static org.awaitility.Awaitility.await; import java.time.Instant; import java.util.Comparator; import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.function.Function; import java.util.stream.Collectors; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -22,15 +22,25 @@ import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.util.ReflectionTestUtils; -import de.tum.cit.aet.artemis.assessment.domain.Result; +import de.tum.cit.aet.artemis.assessment.domain.ParticipantScore; +import de.tum.cit.aet.artemis.assessment.repository.StudentScoreRepository; import de.tum.cit.aet.artemis.assessment.service.ParticipantScoreScheduleService; +import de.tum.cit.aet.artemis.assessment.util.StudentScoreUtilService; +import de.tum.cit.aet.artemis.atlas.competency.util.CompetencyUtilService; +import de.tum.cit.aet.artemis.atlas.dto.metrics.CompetencyInformationDTO; +import de.tum.cit.aet.artemis.atlas.dto.metrics.LectureUnitInformationDTO; import de.tum.cit.aet.artemis.atlas.dto.metrics.ResourceTimestampDTO; import de.tum.cit.aet.artemis.atlas.dto.metrics.StudentMetricsDTO; +import de.tum.cit.aet.artemis.atlas.repository.CompetencyRepository; import de.tum.cit.aet.artemis.core.domain.Course; import de.tum.cit.aet.artemis.exercise.domain.Exercise; import de.tum.cit.aet.artemis.exercise.domain.Submission; import de.tum.cit.aet.artemis.exercise.dto.ExerciseInformationDTO; import de.tum.cit.aet.artemis.exercise.repository.ExerciseMetricsRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; +import de.tum.cit.aet.artemis.lecture.repository.LectureUnitRepository; +import de.tum.cit.aet.artemis.lecture.service.LectureUnitService; +import de.tum.cit.aet.artemis.lecture.util.LectureUtilService; import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationIndependentTest; class MetricsIntegrationTest extends AbstractSpringIntegrationIndependentTest { @@ -40,14 +50,40 @@ class MetricsIntegrationTest extends AbstractSpringIntegrationIndependentTest { @Autowired private ExerciseMetricsRepository exerciseMetricsRepository; + @Autowired + private CompetencyRepository competencyRepository; + + @Autowired + private ExerciseTestRepository exerciseTestRepository; + + @Autowired + private LectureUnitRepository lectureUnitRepository; + + @Autowired + private StudentScoreRepository studentScoreRepository; + + @Autowired + protected StudentScoreUtilService studentScoreUtilService; + + @Autowired + protected LectureUtilService lectureUtilService; + + @Autowired + protected CompetencyUtilService competencyUtilService; + + @Autowired + protected LectureUnitService lectureUnitService; + private Course course; private Course courseWithTestRuns; + private long userID; + private static final String STUDENT_OF_COURSE = TEST_PREFIX + "student1"; @BeforeEach - void setupTestScenario() { + void setupTestScenario() throws Exception { // Prevents the ParticipantScoreScheduleService from scheduling tasks related to prior results ReflectionTestUtils.setField(participantScoreScheduleService, "lastScheduledRun", Optional.of(Instant.now())); ParticipantScoreScheduleService.DEFAULT_WAITING_TIME_FOR_SCHEDULED_TASKS = 100; @@ -59,6 +95,7 @@ void setupTestScenario() { courseWithTestRuns = courseUtilService.createCourseWithAllExerciseTypesAndParticipationsAndSubmissionsAndResultsAndTestRunsAndTwoUsers(TEST_PREFIX, true); userUtilService.createAndSaveUser(TEST_PREFIX + "user1337"); + userID = userUtilService.getUserByLogin(TEST_PREFIX + "student1").getId(); } @AfterEach @@ -94,25 +131,56 @@ void shouldReturnExerciseInformation() throws Exception { assertThat(exerciseInformation).allSatisfy((id, dto) -> assertThat(id).isEqualTo(dto.id())); } - @Disabled // TODO: reduce jacoco missing by one after enabled @Test @WithMockUser(username = STUDENT_OF_COURSE, roles = "USER") - void shouldReturnAverageScores() throws Exception { - // Wait for the scheduler to execute its task - participantScoreScheduleService.executeScheduledTasks(); - await().until(() -> participantScoreScheduleService.isIdle()); + void shouldReturnCategories() throws Exception { + final var result = request.get("/api/metrics/course/" + course.getId() + "/student", HttpStatus.OK, StudentMetricsDTO.class); + assertThat(result).isNotNull(); + assertThat(result.exerciseMetrics()).isNotNull(); + final var categories = result.exerciseMetrics().categories(); + + final var expectedCategories = exerciseTestRepository.findAllWithCategoriesByCourseId(course.getId()).stream() + .collect(Collectors.toMap(Exercise::getId, Exercise::getCategories)); + + assertThat(categories).isEqualTo(expectedCategories); + } + @Test + @WithMockUser(username = STUDENT_OF_COURSE, roles = "USER") + void shouldReturnAverageScores() throws Exception { + final var exercises = exerciseTestRepository.findAllExercisesByCourseIdWithEagerParticipation(course.getId()); + exercises.forEach(exercise -> studentScoreUtilService.createRatedStudentScore(exercise, userUtilService.getUserByLogin(STUDENT_OF_COURSE), 5)); final var result = request.get("/api/metrics/course/" + course.getId() + "/student", HttpStatus.OK, StudentMetricsDTO.class); assertThat(result).isNotNull(); assertThat(result.exerciseMetrics()).isNotNull(); final var averageScores = result.exerciseMetrics().averageScore(); + final var expectedAverageScores = exercises.stream().collect(Collectors.toMap(Exercise::getId, + exercise -> exercise.getStudentParticipations().stream().flatMap(participation -> participation.getStudents().stream()).mapToDouble( + student -> studentScoreRepository.findByExercise_IdAndUser_Id(exercise.getId(), student.getId()).map(ParticipantScore::getLastRatedScore).orElse(0.0)) + .average().orElse(0.0))); + + assertThat(averageScores).isEqualTo(expectedAverageScores); + } + + @Test + @WithMockUser(username = STUDENT_OF_COURSE, roles = "USER") + void shouldReturnScore() throws Exception { final var exercises = exerciseRepository.findAllExercisesByCourseId(course.getId()); - final var expectedMap = exercises.stream().map(Exercise::getId).collect( - Collectors.toMap(Function.identity(), id -> resultRepository.findAllByParticipationExerciseId(id).stream().mapToDouble(Result::getScore).average().orElse(0))); + exercises.forEach(exercise -> studentScoreUtilService.createRatedStudentScore(exercise, userUtilService.getUserByLogin(STUDENT_OF_COURSE), 0.5)); - assertThat(averageScores).isEqualTo(expectedMap); + final var result = request.get("/api/metrics/course/" + course.getId() + "/student", HttpStatus.OK, StudentMetricsDTO.class); + assertThat(result).isNotNull(); + assertThat(result.exerciseMetrics()).isNotNull(); + final var score = result.exerciseMetrics().score(); + + var expectedScores = exercises.stream() + .map(exercise -> studentScoreRepository.findByExercise_IdAndUser_Id(exercise.getId(), userID) + .map(studentScore -> Map.entry(exercise.getId(), studentScore.getLastRatedScore()))) + .filter(Optional::isPresent).map(Optional::get).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + + assertThat(score).isEqualTo(expectedScores); } @Test @@ -196,5 +264,72 @@ void shouldFindLatestSubmissionDatesByUser() throws Exception { Set result = exerciseMetricsRepository.findLatestSubmissionDatesForUser(exerciseIds, userID); assertThat(result).isEqualTo(expectedSet); } + + @Test + @WithMockUser(username = STUDENT_OF_COURSE, roles = "USER") + void shouldReturnCompleted() throws Exception { + final var exercises = exerciseRepository.findAllExercisesByCourseId(course.getId()); + exercises.forEach(exercise -> studentScoreUtilService.createRatedStudentScore(exercise, userUtilService.getUserByLogin(STUDENT_OF_COURSE), MIN_SCORE_GREEN)); + + final var result = request.get("/api/metrics/course/" + course.getId() + "/student", HttpStatus.OK, StudentMetricsDTO.class); + assertThat(result).isNotNull(); + assertThat(result.exerciseMetrics()).isNotNull(); + final var completed = result.exerciseMetrics().completed(); + + final var expectedCompleted = exercises.stream().map(Exercise::getId).filter( + id -> studentScoreRepository.findByExercise_IdAndUser_Id(id, userID).map(studentScore -> studentScore.getLastRatedScore() >= MIN_SCORE_GREEN).orElse(false)) + .collect(Collectors.toSet()); + + assertThat(completed).isEqualTo(expectedCompleted); + } + } + + @Nested + class CompetencyMetrics { + + @Test + @WithMockUser(username = STUDENT_OF_COURSE, roles = "USER") + void shouldReturnCompetencyInformation() throws Exception { + course.setCompetencies(Set.of(competencyUtilService.createCompetency(course))); + + final var result = request.get("/api/metrics/course/" + course.getId() + "/student", HttpStatus.OK, StudentMetricsDTO.class); + assertThat(result).isNotNull(); + assertThat(result.competencyMetrics()).isNotNull(); + + final var competencyInformation = result.competencyMetrics().competencyInformation(); + + final var competencies = competencyRepository.findAllForCourseWithExercisesAndLectureUnitsAndLecturesAndAttachments(course.getId()); + final var expectedDTOs = competencies.stream().map(CompetencyInformationDTO::of).collect(Collectors.toSet()); + + assertThat(competencyInformation.values()).containsExactlyInAnyOrderElementsOf(expectedDTOs); + assertThat(competencyInformation).allSatisfy((id, dto) -> assertThat(id).isEqualTo(dto.id())); + } + } + + @Nested + class LectureMetrics { + + @Test + @WithMockUser(username = STUDENT_OF_COURSE, roles = "USER") + void shouldReturnLectureUnitInformation() throws Exception { + + final var lectureUnit = lectureUtilService.createTextUnit(); + lectureUnitService.linkLectureUnitsToCompetency(competencyUtilService.createCompetency(course), Set.of(lectureUnit), Set.of()); + + final var testLecture = lectureUtilService.createLecture(course, null); + lectureUtilService.addLectureUnitsToLecture(testLecture, List.of(lectureUnit)); + course.addLectures(testLecture); + + final var result = request.get("/api/metrics/course/" + course.getId() + "/student", HttpStatus.OK, StudentMetricsDTO.class); + assertThat(result).isNotNull(); + assertThat(result.lectureUnitStudentMetricsDTO()).isNotNull(); + final var lectureUnitInformation = result.lectureUnitStudentMetricsDTO().lectureUnitInformation(); + + final var lectureUnits = lectureUnitRepository.findAllById(Set.of(lectureUnit.getId())); + final var expectedDTOs = lectureUnits.stream().map(LectureUnitInformationDTO::of).collect(Collectors.toSet()); + + assertThat(lectureUnitInformation.values()).containsExactlyInAnyOrderElementsOf(expectedDTOs); + assertThat(lectureUnitInformation).allSatisfy((id, dto) -> assertThat(id).isEqualTo(dto.id())); + } } } diff --git a/src/test/java/de/tum/cit/aet/artemis/core/config/MetricsBeanTest.java b/src/test/java/de/tum/cit/aet/artemis/core/config/MetricsBeanTest.java index 969dcba1d7f8..f2f97b9ffe74 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/config/MetricsBeanTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/config/MetricsBeanTest.java @@ -24,7 +24,6 @@ import de.tum.cit.aet.artemis.exercise.domain.ExerciseType; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationFactory; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.exercise.test_repository.SubmissionTestRepository; import de.tum.cit.aet.artemis.exercise.util.ExerciseUtilService; import de.tum.cit.aet.artemis.quiz.domain.QuizExercise; @@ -70,9 +69,6 @@ class MetricsBeanTest extends AbstractSpringIntegrationIndependentTest { @Autowired private UserTestRepository userRepository; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private ExamUserRepository examUserRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/core/service/AssessmentServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/core/service/AssessmentServiceTest.java index 673f3c13f07c..07be65439250 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/service/AssessmentServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/service/AssessmentServiceTest.java @@ -30,7 +30,6 @@ import de.tum.cit.aet.artemis.exercise.domain.participation.Participation; import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.exercise.test_repository.ParticipationTestRepository; import de.tum.cit.aet.artemis.exercise.util.ExerciseUtilService; import de.tum.cit.aet.artemis.fileupload.domain.FileUploadExercise; @@ -49,9 +48,6 @@ class AssessmentServiceTest extends AbstractSpringIntegrationIndependentTest { private static final String TEST_PREFIX = "assessmentservice"; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private ResultTestRepository resultRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/core/service/CourseExamExportServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/core/service/CourseExamExportServiceTest.java index 719f1b47a0d9..77915abba5d3 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/service/CourseExamExportServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/service/CourseExamExportServiceTest.java @@ -20,7 +20,6 @@ import de.tum.cit.aet.artemis.core.user.util.UserUtilService; import de.tum.cit.aet.artemis.core.util.CourseUtilService; import de.tum.cit.aet.artemis.exam.repository.ExamRepository; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationIndependentTest; class CourseExamExportServiceTest extends AbstractSpringIntegrationIndependentTest { @@ -39,9 +38,6 @@ class CourseExamExportServiceTest extends AbstractSpringIntegrationIndependentTe @Autowired private UserUtilService userUtilService; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private UserTestRepository userRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/core/service/CourseServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/core/service/CourseServiceTest.java index b6483580a761..65e9c93d3cec 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/service/CourseServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/service/CourseServiceTest.java @@ -29,7 +29,6 @@ import de.tum.cit.aet.artemis.core.user.util.UserUtilService; import de.tum.cit.aet.artemis.core.util.CourseUtilService; import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository; import de.tum.cit.aet.artemis.exercise.test_repository.SubmissionTestRepository; import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationLocalCILocalVCTest; @@ -52,9 +51,6 @@ class CourseServiceTest extends AbstractSpringIntegrationLocalCILocalVCTest { @Autowired private StudentParticipationTestRepository studentParticipationRepo; - @Autowired - private ExerciseRepository exerciseRepo; - @Autowired private UserUtilService userUtilService; @@ -79,7 +75,7 @@ void testGetActiveStudents(long weeks) { var course = courseUtilService.addEmptyCourse(); var exercise = TextExerciseFactory.generateTextExercise(date, date, date, course); course.addExercises(exercise); - exercise = exerciseRepo.save(exercise); + exercise = exerciseRepository.save(exercise); var student1 = userUtilService.getUserByLogin(TEST_PREFIX + "student1"); var participation1 = new StudentParticipation(); @@ -140,7 +136,7 @@ void testGetActiveStudents_UTCConversion() { var course = courseUtilService.addEmptyCourse(); var exercise = TextExerciseFactory.generateTextExercise(date, date, date, course); course.addExercises(exercise); - exercise = exerciseRepo.save(exercise); + exercise = exerciseRepository.save(exercise); var student1 = userUtilService.getUserByLogin(TEST_PREFIX + "student1"); var participation1 = new StudentParticipation(); diff --git a/src/test/java/de/tum/cit/aet/artemis/core/service/DataExportCreationServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/core/service/DataExportCreationServiceTest.java index d4f16c93604a..73382100b910 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/service/DataExportCreationServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/service/DataExportCreationServiceTest.java @@ -67,7 +67,6 @@ import de.tum.cit.aet.artemis.exam.util.ExamUtilService; import de.tum.cit.aet.artemis.exercise.domain.Exercise; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.exercise.util.ExerciseUtilService; import de.tum.cit.aet.artemis.fileupload.util.ZipFileTestUtilService; import de.tum.cit.aet.artemis.modeling.domain.ModelingExercise; @@ -118,9 +117,6 @@ class DataExportCreationServiceTest extends AbstractSpringIntegrationJenkinsGitl @Autowired private StudentExamTestRepository studentExamRepository; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private DataExportTestRepository dataExportRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/core/service/TitleCacheEvictionServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/core/service/TitleCacheEvictionServiceTest.java index f9991fa36fc4..30f880543785 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/service/TitleCacheEvictionServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/service/TitleCacheEvictionServiceTest.java @@ -15,7 +15,6 @@ import de.tum.cit.aet.artemis.core.util.Tuple; import de.tum.cit.aet.artemis.exam.repository.ExamRepository; import de.tum.cit.aet.artemis.exam.util.ExamUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.lecture.repository.LectureRepository; import de.tum.cit.aet.artemis.lecture.util.LectureUtilService; import de.tum.cit.aet.artemis.modeling.domain.DiagramType; @@ -39,9 +38,6 @@ class TitleCacheEvictionServiceTest extends AbstractSpringIntegrationIndependent @Autowired private CacheManager cacheManager; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private LectureRepository lectureRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/core/util/CourseTestService.java b/src/test/java/de/tum/cit/aet/artemis/core/util/CourseTestService.java index c3c68e44b5e5..3b8ce269954b 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/util/CourseTestService.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/util/CourseTestService.java @@ -126,7 +126,7 @@ import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationFactory; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.exercise.service.ParticipationService; import de.tum.cit.aet.artemis.exercise.team.TeamUtilService; import de.tum.cit.aet.artemis.exercise.test_repository.ParticipationTestRepository; @@ -175,7 +175,7 @@ public class CourseTestService { private CourseTestRepository courseRepo; @Autowired - private ExerciseRepository exerciseRepo; + private ExerciseTestRepository exerciseRepo; @Autowired private LectureRepository lectureRepo; diff --git a/src/test/java/de/tum/cit/aet/artemis/core/util/CourseUtilService.java b/src/test/java/de/tum/cit/aet/artemis/core/util/CourseUtilService.java index 02d8d55a6231..93e7856af38e 100644 --- a/src/test/java/de/tum/cit/aet/artemis/core/util/CourseUtilService.java +++ b/src/test/java/de/tum/cit/aet/artemis/core/util/CourseUtilService.java @@ -49,7 +49,7 @@ import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationFactory; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository; import de.tum.cit.aet.artemis.exercise.test_repository.SubmissionTestRepository; import de.tum.cit.aet.artemis.exercise.util.ExerciseUtilService; @@ -110,7 +110,7 @@ public class CourseUtilService { private AttachmentRepository attachmentRepo; @Autowired - private ExerciseRepository exerciseRepo; + private ExerciseTestRepository exerciseRepository; @Autowired private TutorParticipationTestRepository tutorParticipationRepo; @@ -390,12 +390,12 @@ public List createCoursesWithExercisesAndLectures(String userPrefix, boo attachmentRepo.save(attachment1); attachmentRepo.save(attachment2); - modelingExercise = exerciseRepo.save(modelingExercise); - textExercise = exerciseRepo.save(textExercise); - exerciseRepo.save(fileUploadExercise); + modelingExercise = exerciseRepository.save(modelingExercise); + textExercise = exerciseRepository.save(textExercise); + exerciseRepository.save(fileUploadExercise); programmingExercise.setBuildConfig(programmingExerciseBuildConfigRepository.save(programmingExercise.getBuildConfig())); - exerciseRepo.save(programmingExercise); - exerciseRepo.save(quizExercise); + exerciseRepository.save(programmingExercise); + exerciseRepository.save(quizExercise); if (withParticipations) { @@ -521,12 +521,12 @@ public Course createCourseWithAllExerciseTypesAndParticipationsAndSubmissionsAnd // Save course and exercises to database Course courseSaved = courseRepo.save(course); - modelingExercise = exerciseRepo.save(modelingExercise); - textExercise = exerciseRepo.save(textExercise); - fileUploadExercise = exerciseRepo.save(fileUploadExercise); + modelingExercise = exerciseRepository.save(modelingExercise); + textExercise = exerciseRepository.save(textExercise); + fileUploadExercise = exerciseRepository.save(fileUploadExercise); programmingExercise.setBuildConfig(programmingExerciseBuildConfigRepository.save(programmingExercise.getBuildConfig())); - programmingExercise = exerciseRepo.save(programmingExercise); - quizExercise = exerciseRepo.save(quizExercise); + programmingExercise = exerciseRepository.save(programmingExercise); + quizExercise = exerciseRepository.save(quizExercise); // Get user and setup participations User user = (userRepo.findOneByLogin(userPrefix + "student1")).orElseThrow(); @@ -630,11 +630,11 @@ public Course createCourseWithAllExerciseTypesAndParticipationsAndSubmissionsAnd programmingSubmission = submissionRepository.save(programmingSubmission); // Save exercises - exerciseRepo.save(modelingExercise); - exerciseRepo.save(textExercise); - exerciseRepo.save(fileUploadExercise); - exerciseRepo.save(programmingExercise); - exerciseRepo.save(quizExercise); + exerciseRepository.save(modelingExercise); + exerciseRepository.save(textExercise); + exerciseRepository.save(fileUploadExercise); + exerciseRepository.save(programmingExercise); + exerciseRepository.save(quizExercise); // Connect participations with submissions participationModeling.setSubmissions(Set.of(modelingSubmission)); @@ -687,12 +687,12 @@ public Course createCourseWithAllExerciseTypesAndParticipationsAndSubmissionsAnd // Save course and exercises to database Course courseSaved = courseRepo.save(course); - modelingExercise = exerciseRepo.save(modelingExercise); - textExercise = exerciseRepo.save(textExercise); - fileUploadExercise = exerciseRepo.save(fileUploadExercise); + modelingExercise = exerciseRepository.save(modelingExercise); + textExercise = exerciseRepository.save(textExercise); + fileUploadExercise = exerciseRepository.save(fileUploadExercise); programmingExercise.setBuildConfig(programmingExerciseBuildConfigRepository.save(programmingExercise.getBuildConfig())); - programmingExercise = exerciseRepo.save(programmingExercise); - quizExercise = exerciseRepo.save(quizExercise); + programmingExercise = exerciseRepository.save(programmingExercise); + quizExercise = exerciseRepository.save(quizExercise); // Get user and setup participations User user = (userRepo.findOneByLogin(userPrefix + "student1")).orElseThrow(); @@ -811,11 +811,11 @@ public Course createCourseWithAllExerciseTypesAndParticipationsAndSubmissionsAnd programmingSubmission = submissionRepository.save(programmingSubmission); // Save exercises - exerciseRepo.save(modelingExercise); - exerciseRepo.save(textExercise); - exerciseRepo.save(fileUploadExercise); - exerciseRepo.save(programmingExercise); - exerciseRepo.save(quizExercise); + exerciseRepository.save(modelingExercise); + exerciseRepository.save(textExercise); + exerciseRepository.save(fileUploadExercise); + exerciseRepository.save(programmingExercise); + exerciseRepository.save(quizExercise); // Connect participations with submissions participationModeling.setSubmissions(Set.of(modelingSubmission)); @@ -898,7 +898,7 @@ else if ("Text".equals(title)) { textExercise.setTitle("Text"); course.addExercises(textExercise); courseRepo.save(course); - exerciseRepo.save(textExercise); + exerciseRepository.save(textExercise); } else if (title.startsWith("ClassDiagram")) { ModelingExercise modelingExercise = ModelingExerciseFactory.generateModelingExercise(PAST_TIMESTAMP, FUTURE_TIMESTAMP, FUTURE_FUTURE_TIMESTAMP, @@ -906,7 +906,7 @@ else if (title.startsWith("ClassDiagram")) { modelingExercise.setTitle(title); course.addExercises(modelingExercise); courseRepo.save(course); - exerciseRepo.save(modelingExercise); + exerciseRepository.save(modelingExercise); } return course; @@ -927,8 +927,8 @@ public Course addCourseWithModelingAndTextExercise() { textExercise.setTitle("Text"); course.addExercises(textExercise); course = courseRepo.save(course); - exerciseRepo.save(modelingExercise); - exerciseRepo.save(textExercise); + exerciseRepository.save(modelingExercise); + exerciseRepository.save(textExercise); return course; } @@ -954,9 +954,9 @@ public Course addCourseWithModelingAndTextAndFileUploadExercise() { course.addExercises(fileUploadExercise); course = courseRepo.save(course); - exerciseRepo.save(modelingExercise); - exerciseRepo.save(textExercise); - exerciseRepo.save(fileUploadExercise); + exerciseRepository.save(modelingExercise); + exerciseRepository.save(textExercise); + exerciseRepository.save(fileUploadExercise); return course; } @@ -1056,7 +1056,7 @@ public Course addCourseWithExercisesAndSubmissions(String courseShortName, Strin ModelingExercise modelingExercise = ModelingExerciseFactory.generateModelingExercise(releaseDate, dueDate, assessmentDueDate, DiagramType.ClassDiagram, course); modelingExercise.setTitle("Modeling" + i); modelingExercise.setCourse(course); - modelingExercise = exerciseRepo.save(modelingExercise); + modelingExercise = exerciseRepository.save(modelingExercise); course.addExercises(modelingExercise); for (int j = 1; j <= numberOfSubmissionPerExercise; j++) { StudentParticipation participation = participationUtilService.createAndSaveParticipationForExercise(modelingExercise, userPrefix + "student" + j); @@ -1079,7 +1079,7 @@ else if ((i % 3) == 1) { TextExercise textExercise = TextExerciseFactory.generateTextExercise(releaseDate, dueDate, assessmentDueDate, course); textExercise.setTitle("Text" + i); textExercise.setCourse(course); - textExercise = exerciseRepo.save(textExercise); + textExercise = exerciseRepository.save(textExercise); course.addExercises(textExercise); for (int j = 1; j <= numberOfSubmissionPerExercise; j++) { TextSubmission submission = ParticipationFactory.generateTextSubmission("submissionText", Language.ENGLISH, true); @@ -1097,7 +1097,7 @@ else if ((i % 3) == 1) { FileUploadExercise fileUploadExercise = FileUploadExerciseFactory.generateFileUploadExercise(releaseDate, dueDate, assessmentDueDate, "png,pdf", course); fileUploadExercise.setTitle("FileUpload" + i); fileUploadExercise.setCourse(course); - fileUploadExercise = exerciseRepo.save(fileUploadExercise); + fileUploadExercise = exerciseRepository.save(fileUploadExercise); course.addExercises(fileUploadExercise); for (int j = 1; j <= numberOfSubmissionPerExercise; j++) { FileUploadSubmission submission = ParticipationFactory.generateFileUploadSubmissionWithFile(true, null); @@ -1175,7 +1175,7 @@ public Course createCourseWithExamExercisesAndSubmissions(String userPrefix) thr // Create a file upload exercise with a dummy submission file var exerciseGroup1 = exerciseGroupRepository.save(new ExerciseGroup()); var fileUploadExercise = FileUploadExerciseFactory.generateFileUploadExerciseForExam(".png", exerciseGroup1); - fileUploadExercise = exerciseRepo.save(fileUploadExercise); + fileUploadExercise = exerciseRepository.save(fileUploadExercise); fileUploadExerciseUtilService.createFileUploadSubmissionWithFile(userPrefix, fileUploadExercise, "uploaded-file.png"); exerciseGroup1.addExercise(fileUploadExercise); exerciseGroup1 = exerciseGroupRepository.save(exerciseGroup1); @@ -1183,7 +1183,7 @@ public Course createCourseWithExamExercisesAndSubmissions(String userPrefix) thr // Create a text exercise with a dummy submission file var exerciseGroup2 = exerciseGroupRepository.save(new ExerciseGroup()); var textExercise = TextExerciseFactory.generateTextExerciseForExam(exerciseGroup2); - textExercise = exerciseRepo.save(textExercise); + textExercise = exerciseRepository.save(textExercise); var textSubmission = ParticipationFactory.generateTextSubmission("example text", Language.ENGLISH, true); textExerciseUtilService.saveTextSubmission(textExercise, textSubmission, userPrefix + "student1"); exerciseGroup2.addExercise(textExercise); @@ -1192,7 +1192,7 @@ public Course createCourseWithExamExercisesAndSubmissions(String userPrefix) thr // Create a modeling exercise with a dummy submission file var exerciseGroup3 = exerciseGroupRepository.save(new ExerciseGroup()); var modelingExercise = ModelingExerciseFactory.generateModelingExerciseForExam(DiagramType.ClassDiagram, exerciseGroup2); - modelingExercise = exerciseRepo.save(modelingExercise); + modelingExercise = exerciseRepository.save(modelingExercise); String emptyActivityModel = TestResourceUtils.loadFileFromResources("test-data/model-submission/empty-activity-diagram.json"); var modelingSubmission = ParticipationFactory.generateModelingSubmission(emptyActivityModel, true); participationUtilService.addSubmission(modelingExercise, modelingSubmission, userPrefix + "student1"); diff --git a/src/test/java/de/tum/cit/aet/artemis/exam/ExamStartTest.java b/src/test/java/de/tum/cit/aet/artemis/exam/ExamStartTest.java index 60aad76d09b3..399cb4306f6d 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exam/ExamStartTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/exam/ExamStartTest.java @@ -42,7 +42,6 @@ import de.tum.cit.aet.artemis.exercise.domain.Exercise; import de.tum.cit.aet.artemis.exercise.domain.participation.Participation; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.exercise.test_repository.ParticipationTestRepository; import de.tum.cit.aet.artemis.modeling.domain.DiagramType; import de.tum.cit.aet.artemis.modeling.domain.ModelingExercise; @@ -65,9 +64,6 @@ class ExamStartTest extends AbstractSpringIntegrationLocalCILocalVCTest { private static final String TEST_PREFIX = "examstarttest"; - @Autowired - private ExerciseRepository exerciseRepo; - @Autowired private ExamRepository examRepository; @@ -153,7 +149,7 @@ void testStartExercisesWithTextExercise() throws Exception { TextExercise textExercise = TextExerciseFactory.generateTextExerciseForExam(exerciseGroup); exerciseGroup.addExercise(textExercise); exerciseGroupRepository.save(exerciseGroup); - textExercise = exerciseRepo.save(textExercise); + textExercise = exerciseRepository.save(textExercise); createStudentExams(textExercise); @@ -176,7 +172,7 @@ void testStartExercisesWithModelingExercise() throws Exception { ModelingExercise modelingExercise = ModelingExerciseFactory.generateModelingExerciseForExam(DiagramType.ClassDiagram, exam.getExerciseGroups().getFirst()); exam.getExerciseGroups().getFirst().addExercise(modelingExercise); exerciseGroupRepository.save(exam.getExerciseGroups().getFirst()); - modelingExercise = exerciseRepo.save(modelingExercise); + modelingExercise = exerciseRepository.save(modelingExercise); createStudentExams(modelingExercise); @@ -271,7 +267,7 @@ private void createStudentExams(Exercise exercise) { private ProgrammingExercise createProgrammingExercise() { ProgrammingExercise programmingExercise = ProgrammingExerciseFactory.generateProgrammingExerciseForExam(exam.getExerciseGroups().getFirst()); programmingExercise.setBuildConfig(programmingExerciseBuildConfigRepository.save(programmingExercise.getBuildConfig())); - programmingExercise = exerciseRepo.save(programmingExercise); + programmingExercise = exerciseRepository.save(programmingExercise); programmingExercise = programmingExerciseUtilService.addTemplateParticipationForProgrammingExercise(programmingExercise); exam.getExerciseGroups().getFirst().addExercise(programmingExercise); exerciseGroupRepository.save(exam.getExerciseGroups().getFirst()); diff --git a/src/test/java/de/tum/cit/aet/artemis/exam/ExerciseGroupIntegrationJenkinsGitlabTest.java b/src/test/java/de/tum/cit/aet/artemis/exam/ExerciseGroupIntegrationJenkinsGitlabTest.java index 108eef0bb76f..cca6fc1591e2 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exam/ExerciseGroupIntegrationJenkinsGitlabTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/exam/ExerciseGroupIntegrationJenkinsGitlabTest.java @@ -29,7 +29,6 @@ import de.tum.cit.aet.artemis.exam.util.ExamFactory; import de.tum.cit.aet.artemis.exam.util.ExamUtilService; import de.tum.cit.aet.artemis.exercise.domain.Exercise; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.programming.domain.ProgrammingExercise; import de.tum.cit.aet.artemis.programming.domain.ProgrammingLanguage; import de.tum.cit.aet.artemis.programming.repository.ProgrammingExerciseBuildConfigRepository; @@ -47,9 +46,6 @@ class ExerciseGroupIntegrationJenkinsGitlabTest extends AbstractSpringIntegratio @Autowired private TextExerciseRepository textExerciseRepository; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private ProgrammingExerciseBuildConfigRepository programmingExerciseBuildConfigRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/exam/service/ExamServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/exam/service/ExamServiceTest.java index 140deeae34c1..860576490fb0 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exam/service/ExamServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/exam/service/ExamServiceTest.java @@ -28,7 +28,6 @@ import de.tum.cit.aet.artemis.exam.util.ExamUtilService; import de.tum.cit.aet.artemis.exercise.domain.IncludedInOverallScore; import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository; import de.tum.cit.aet.artemis.quiz.domain.QuizExercise; import de.tum.cit.aet.artemis.shared.base.AbstractSpringIntegrationIndependentTest; @@ -47,9 +46,6 @@ class ExamServiceTest extends AbstractSpringIntegrationIndependentTest { @Autowired private StudentParticipationTestRepository studentParticipationRepository; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private CourseUtilService courseUtilService; diff --git a/src/test/java/de/tum/cit/aet/artemis/exam/util/ExamUtilService.java b/src/test/java/de/tum/cit/aet/artemis/exam/util/ExamUtilService.java index ba1fe0c84b8f..0d6c8a6899c1 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exam/util/ExamUtilService.java +++ b/src/test/java/de/tum/cit/aet/artemis/exam/util/ExamUtilService.java @@ -44,7 +44,7 @@ import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationFactory; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository; import de.tum.cit.aet.artemis.exercise.test_repository.SubmissionTestRepository; import de.tum.cit.aet.artemis.fileupload.domain.FileUploadExercise; @@ -94,7 +94,7 @@ public class ExamUtilService { private ExamRepository examRepository; @Autowired - private ExerciseRepository exerciseRepo; + private ExerciseTestRepository exerciseRepo; @Autowired private ProgrammingExerciseBuildConfigRepository programmingExerciseBuildConfigRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/exercise/participation/util/ParticipationUtilService.java b/src/test/java/de/tum/cit/aet/artemis/exercise/participation/util/ParticipationUtilService.java index 13f049125c0a..ff3ab5f260e6 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exercise/participation/util/ParticipationUtilService.java +++ b/src/test/java/de/tum/cit/aet/artemis/exercise/participation/util/ParticipationUtilService.java @@ -47,7 +47,7 @@ import de.tum.cit.aet.artemis.exercise.domain.participation.Participant; import de.tum.cit.aet.artemis.exercise.domain.participation.Participation; import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.exercise.repository.TeamRepository; import de.tum.cit.aet.artemis.exercise.service.ParticipationService; import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository; @@ -91,7 +91,7 @@ public class ParticipationUtilService { private ParticipationVcsAccessTokenService participationVCSAccessTokenService; @Autowired - private ExerciseRepository exerciseRepo; + private ExerciseTestRepository exerciseRepository; @Autowired private SubmissionTestRepository submissionRepository; @@ -177,14 +177,14 @@ public Result addProgrammingParticipationWithResultForExercise(ProgrammingExerci * @return The created Result */ public Result createParticipationSubmissionAndResult(long exerciseId, Participant participant, Double points, Double bonusPoints, long scoreAwarded, boolean rated) { - Exercise exercise = exerciseRepo.findById(exerciseId).orElseThrow(); + Exercise exercise = exerciseRepository.findById(exerciseId).orElseThrow(); if (!exercise.getMaxPoints().equals(points)) { exercise.setMaxPoints(points); } if (!exercise.getBonusPoints().equals(bonusPoints)) { exercise.setBonusPoints(bonusPoints); } - exercise = exerciseRepo.saveAndFlush(exercise); + exercise = exerciseRepository.saveAndFlush(exercise); StudentParticipation studentParticipation = participationService.startExercise(exercise, participant, false); return createSubmissionAndResult(studentParticipation, scoreAwarded, rated); } diff --git a/src/test/java/de/tum/cit/aet/artemis/exercise/repository/ExerciseTestRepository.java b/src/test/java/de/tum/cit/aet/artemis/exercise/repository/ExerciseTestRepository.java new file mode 100644 index 000000000000..03332b2f6fc5 --- /dev/null +++ b/src/test/java/de/tum/cit/aet/artemis/exercise/repository/ExerciseTestRepository.java @@ -0,0 +1,31 @@ +package de.tum.cit.aet.artemis.exercise.repository; + +import java.util.List; +import java.util.Set; + +import org.springframework.context.annotation.Primary; +import org.springframework.data.jpa.repository.EntityGraph; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import de.tum.cit.aet.artemis.exercise.domain.Exercise; + +/** + * Spring Data JPA repository for the Exercise entity for Tests. + */ +@Primary +@Repository +public interface ExerciseTestRepository extends ExerciseRepository { + + @EntityGraph(attributePaths = { "studentParticipations", "studentParticipations.student", "studentParticipations.submissions" }) + @Query(""" + SELECT e + FROM Exercise e + WHERE e.course.id = :courseId + """) + Set findAllExercisesByCourseIdWithEagerParticipation(@Param("courseId") Long courseId); + + @EntityGraph(attributePaths = "categories") + List findAllWithCategoriesByCourseId(Long courseId); +} diff --git a/src/test/java/de/tum/cit/aet/artemis/exercise/service/PresentationPointsCalculationServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/exercise/service/PresentationPointsCalculationServiceTest.java index 0592824c6ad7..56aded0df2ae 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exercise/service/PresentationPointsCalculationServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/exercise/service/PresentationPointsCalculationServiceTest.java @@ -17,7 +17,6 @@ import de.tum.cit.aet.artemis.exercise.domain.IncludedInOverallScore; import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository; import de.tum.cit.aet.artemis.programming.domain.ProgrammingExercise; import de.tum.cit.aet.artemis.programming.util.ProgrammingExerciseUtilService; @@ -27,9 +26,6 @@ class PresentationPointsCalculationServiceTest extends AbstractSpringIntegration private static final String TEST_PREFIX = "ppcservicetest"; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private StudentParticipationTestRepository studentParticipationRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/exercise/service/TeamWebsocketServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/exercise/service/TeamWebsocketServiceTest.java index b73dc55fe396..0e9bca57e218 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exercise/service/TeamWebsocketServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/exercise/service/TeamWebsocketServiceTest.java @@ -24,7 +24,6 @@ import de.tum.cit.aet.artemis.exercise.domain.Team; import de.tum.cit.aet.artemis.exercise.dto.TeamAssignmentPayload; import de.tum.cit.aet.artemis.exercise.dto.TeamImportStrategyType; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.exercise.repository.TeamRepository; import de.tum.cit.aet.artemis.exercise.team.TeamUtilService; import de.tum.cit.aet.artemis.modeling.domain.ModelingExercise; @@ -38,9 +37,6 @@ class TeamWebsocketServiceTest extends AbstractSpringIntegrationIndependentTest @Autowired private UserTestRepository userRepo; - @Autowired - private ExerciseRepository exerciseRepo; - @Autowired private TeamRepository teamRepository; @@ -77,11 +73,11 @@ void init() { for (Exercise exercise : course.getExercises()) { if (exercise instanceof ModelingExercise) { exercise.setMode(ExerciseMode.TEAM); - modelingExercise = (ModelingExercise) exerciseRepo.save(exercise); + modelingExercise = (ModelingExercise) exerciseRepository.save(exercise); } if (exercise instanceof TextExercise) { exercise.setMode(ExerciseMode.TEAM); - textExercise = (TextExercise) exerciseRepo.save(exercise); + textExercise = (TextExercise) exerciseRepository.save(exercise); } } assertThat(modelingExercise).isNotNull(); diff --git a/src/test/java/de/tum/cit/aet/artemis/exercise/util/ExerciseUtilService.java b/src/test/java/de/tum/cit/aet/artemis/exercise/util/ExerciseUtilService.java index fa04fd24ca0d..db92da355b2f 100644 --- a/src/test/java/de/tum/cit/aet/artemis/exercise/util/ExerciseUtilService.java +++ b/src/test/java/de/tum/cit/aet/artemis/exercise/util/ExerciseUtilService.java @@ -38,7 +38,7 @@ import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationFactory; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository; import de.tum.cit.aet.artemis.exercise.test_repository.SubmissionTestRepository; import de.tum.cit.aet.artemis.fileupload.domain.FileUploadExercise; @@ -65,7 +65,7 @@ public class ExerciseUtilService { @Autowired - private ExerciseRepository exerciseRepo; + private ExerciseTestRepository exerciseTestRepository; @Autowired private StudentParticipationTestRepository studentParticipationRepo; @@ -122,7 +122,7 @@ public Exercise addMaxScoreAndBonusPointsToExercise(Exercise exercise) { exercise.setIncludedInOverallScore(IncludedInOverallScore.INCLUDED_COMPLETELY); exercise.setMaxPoints(100.0); exercise.setBonusPoints(10.0); - return exerciseRepo.save(exercise); + return exerciseTestRepository.save(exercise); } /** @@ -222,7 +222,7 @@ public Course addCourseWithOneExerciseAndSubmissions(String userPrefix, String e switch (exerciseType) { case "modeling" -> { course = modelingExerciseUtilService.addCourseWithOneModelingExercise(); - exercise = exerciseRepo.findAllExercisesByCourseId(course.getId()).iterator().next(); + exercise = exerciseTestRepository.findAllExercisesByCourseId(course.getId()).iterator().next(); for (int j = 1; j <= numberOfSubmissions; j++) { StudentParticipation participation = participationUtilService.createAndSaveParticipationForExercise(exercise, userPrefix + "student" + j); assertThat(modelForModelingExercise).isNotEmpty(); @@ -235,7 +235,7 @@ public Course addCourseWithOneExerciseAndSubmissions(String userPrefix, String e } case "programming" -> { course = programmingExerciseUtilService.addCourseWithOneProgrammingExercise(); - exercise = exerciseRepo.findAllExercisesByCourseId(course.getId()).iterator().next(); + exercise = exerciseTestRepository.findAllExercisesByCourseId(course.getId()).iterator().next(); for (int j = 1; j <= numberOfSubmissions; j++) { ProgrammingSubmission submission = new ProgrammingSubmission(); programmingExerciseUtilService.addProgrammingSubmission((ProgrammingExercise) exercise, submission, userPrefix + "student" + j); @@ -244,7 +244,7 @@ public Course addCourseWithOneExerciseAndSubmissions(String userPrefix, String e } case "text" -> { course = textExerciseUtilService.addCourseWithOneFinishedTextExercise(); - exercise = exerciseRepo.findAllExercisesByCourseId(course.getId()).iterator().next(); + exercise = exerciseTestRepository.findAllExercisesByCourseId(course.getId()).iterator().next(); for (int j = 1; j <= numberOfSubmissions; j++) { TextSubmission textSubmission = ParticipationFactory.generateTextSubmission("Text" + j + j, null, true); textExerciseUtilService.saveTextSubmission((TextExercise) exercise, textSubmission, userPrefix + "student" + j); @@ -253,7 +253,7 @@ public Course addCourseWithOneExerciseAndSubmissions(String userPrefix, String e } case "file-upload" -> { course = fileUploadExerciseUtilService.addCourseWithFileUploadExercise(); - exercise = exerciseRepo.findAllExercisesByCourseId(course.getId()).iterator().next(); + exercise = exerciseTestRepository.findAllExercisesByCourseId(course.getId()).iterator().next(); for (int j = 1; j <= numberOfSubmissions; j++) { FileUploadSubmission submission = ParticipationFactory.generateFileUploadSubmissionWithFile(true, "path/to/file.pdf"); fileUploadExerciseUtilService.saveFileUploadSubmission((FileUploadExercise) exercise, submission, userPrefix + "student" + j); @@ -313,12 +313,13 @@ public void addAssessmentToExercise(Exercise exercise, User assessor) { * @param newDueDate The new due date of the exercise. */ public void updateExerciseDueDate(long exerciseId, ZonedDateTime newDueDate) { - Exercise exercise = exerciseRepo.findById(exerciseId).orElseThrow(() -> new IllegalArgumentException("Exercise with given ID " + exerciseId + " could not be found")); + Exercise exercise = exerciseTestRepository.findById(exerciseId) + .orElseThrow(() -> new IllegalArgumentException("Exercise with given ID " + exerciseId + " could not be found")); exercise.setDueDate(newDueDate); if (exercise instanceof ProgrammingExercise) { ((ProgrammingExercise) exercise).setBuildAndTestStudentSubmissionsAfterDueDate(newDueDate); } - exerciseRepo.save(exercise); + exerciseTestRepository.save(exercise); } /** @@ -328,9 +329,10 @@ public void updateExerciseDueDate(long exerciseId, ZonedDateTime newDueDate) { * @param newDueDate The new assessment due date of the exercise. */ public void updateAssessmentDueDate(long exerciseId, ZonedDateTime newDueDate) { - Exercise exercise = exerciseRepo.findById(exerciseId).orElseThrow(() -> new IllegalArgumentException("Exercise with given ID " + exerciseId + " could not be found")); + Exercise exercise = exerciseTestRepository.findById(exerciseId) + .orElseThrow(() -> new IllegalArgumentException("Exercise with given ID " + exerciseId + " could not be found")); exercise.setAssessmentDueDate(newDueDate); - exerciseRepo.save(exercise); + exerciseTestRepository.save(exercise); } /** diff --git a/src/test/java/de/tum/cit/aet/artemis/fileupload/util/FileUploadExerciseUtilService.java b/src/test/java/de/tum/cit/aet/artemis/fileupload/util/FileUploadExerciseUtilService.java index 4b6084891726..c85b0c3df488 100644 --- a/src/test/java/de/tum/cit/aet/artemis/fileupload/util/FileUploadExerciseUtilService.java +++ b/src/test/java/de/tum/cit/aet/artemis/fileupload/util/FileUploadExerciseUtilService.java @@ -26,7 +26,7 @@ import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationFactory; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository; import de.tum.cit.aet.artemis.exercise.test_repository.SubmissionTestRepository; import de.tum.cit.aet.artemis.fileupload.domain.FileUploadExercise; @@ -45,9 +45,6 @@ public class FileUploadExerciseUtilService { private static final ZonedDateTime FUTURE_FUTURE_TIMESTAMP = ZonedDateTime.now().plusDays(2); - @Autowired - private ExerciseRepository exerciseRepo; - @Autowired private CourseTestRepository courseRepo; @@ -72,6 +69,9 @@ public class FileUploadExerciseUtilService { @Autowired private UserUtilService userUtilService; + @Autowired + private ExerciseTestRepository exerciseRepository; + /** * Creates and saves a new Course and an Exam with one mandatory FileUploadExercise. * @@ -82,7 +82,7 @@ public class FileUploadExerciseUtilService { public FileUploadExercise addCourseExamExerciseGroupWithOneFileUploadExercise(boolean startDateBeforeCurrentTime) { ExerciseGroup exerciseGroup = examUtilService.addExerciseGroupWithExamAndCourse(true, startDateBeforeCurrentTime); FileUploadExercise fileUploadExercise = FileUploadExerciseFactory.generateFileUploadExerciseForExam("pdf", exerciseGroup); - return exerciseRepo.save(fileUploadExercise); + return exerciseRepository.save(fileUploadExercise); } /** @@ -118,10 +118,10 @@ public List createFileUploadExercisesWithCourse() { public Course addCourseWithThreeFileUploadExercise() { var fileUploadExercises = createFileUploadExercisesWithCourse(); assertThat(fileUploadExercises).as("created three exercises").hasSize(3); - exerciseRepo.saveAll(fileUploadExercises); + exerciseRepository.saveAll(fileUploadExercises); long courseId = fileUploadExercises.getFirst().getCourseViaExerciseGroupOrCourseMember().getId(); Course course = courseRepo.findByIdWithEagerExercisesElseThrow(courseId); - List exercises = exerciseRepo.findAllExercisesByCourseId(courseId).stream().toList(); + List exercises = exerciseRepository.findAllExercisesByCourseId(courseId).stream().toList(); assertThat(exercises).as("three exercises got stored").hasSize(3); assertThat(course.getExercises()).as("course contains the exercises").containsExactlyInAnyOrder(exercises.toArray(new Exercise[] {})); return course; @@ -152,7 +152,7 @@ public Course addCourseWithFourFileUploadExercise() { fileUploadExercises.add(finishedFileUploadExercise); fileUploadExercises.add(assessedFileUploadExercise); fileUploadExercises.add(noDueDateFileUploadExercise); - exerciseRepo.saveAll(fileUploadExercises); + exerciseRepository.saveAll(fileUploadExercises); return courseRepo.findByIdWithEagerExercisesElseThrow(course.getId()); } @@ -168,7 +168,7 @@ public Course addCourseWithFileUploadExercise() { assessedFileUploadExercise.setTitle("assessed"); course.addExercises(assessedFileUploadExercise); courseRepo.save(course); - exerciseRepo.save(assessedFileUploadExercise); + exerciseRepository.save(assessedFileUploadExercise); return course; } diff --git a/src/test/java/de/tum/cit/aet/artemis/lti/service/LtiDeepLinkingServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/lti/service/LtiDeepLinkingServiceTest.java index de205dc54fb1..9c597bbc1cbd 100644 --- a/src/test/java/de/tum/cit/aet/artemis/lti/service/LtiDeepLinkingServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/lti/service/LtiDeepLinkingServiceTest.java @@ -35,7 +35,7 @@ import de.tum.cit.aet.artemis.core.domain.Course; import de.tum.cit.aet.artemis.core.exception.BadRequestAlertException; import de.tum.cit.aet.artemis.exercise.domain.Exercise; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.lti.config.Lti13TokenRetriever; import de.tum.cit.aet.artemis.lti.domain.OnlineCourseConfiguration; import de.tum.cit.aet.artemis.text.domain.TextExercise; @@ -44,7 +44,7 @@ class LtiDeepLinkingServiceTest { @Mock - private ExerciseRepository exerciseRepository; + private ExerciseTestRepository exerciseRepository; @Mock private Lti13TokenRetriever tokenRetriever; diff --git a/src/test/java/de/tum/cit/aet/artemis/modeling/util/ModelingExerciseUtilService.java b/src/test/java/de/tum/cit/aet/artemis/modeling/util/ModelingExerciseUtilService.java index 8b8c4c18be85..2fe018ff8f5f 100644 --- a/src/test/java/de/tum/cit/aet/artemis/modeling/util/ModelingExerciseUtilService.java +++ b/src/test/java/de/tum/cit/aet/artemis/modeling/util/ModelingExerciseUtilService.java @@ -36,7 +36,7 @@ import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationFactory; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository; import de.tum.cit.aet.artemis.modeling.domain.DiagramType; import de.tum.cit.aet.artemis.modeling.domain.ModelingExercise; @@ -62,9 +62,6 @@ public class ModelingExerciseUtilService { @Autowired private CourseTestRepository courseRepo; - @Autowired - private ExerciseRepository exerciseRepo; - @Autowired private ModelingExerciseRepository modelingExerciseRepository; @@ -98,6 +95,9 @@ public class ModelingExerciseUtilService { @Autowired private ModelingSubmissionService modelSubmissionService; + @Autowired + private ExerciseTestRepository exerciseRepository; + /** * Creates and saves a Course with a ModelingExercise. The ModelingExercise's DiagramType is set to ClassDiagram. * @@ -112,7 +112,7 @@ public Course addCourseWithOneModelingExercise(String title) { course.addExercises(modelingExercise); course.setMaxComplaintTimeDays(14); course = courseRepo.save(course); - modelingExercise = exerciseRepo.save(modelingExercise); + modelingExercise = exerciseRepository.save(modelingExercise); assertThat(course.getExercises()).as("course contains the exercise").containsExactlyInAnyOrder(modelingExercise); assertThat(modelingExercise.getPresentationScoreEnabled()).as("presentation score is enabled").isTrue(); return course; @@ -219,17 +219,17 @@ public Course addCourseWithDifferentModelingExercises() { course.addExercises(finishedExercise); course = courseRepo.save(course); - exerciseRepo.save(classExercise); - exerciseRepo.save(activityExercise); - exerciseRepo.save(objectExercise); - exerciseRepo.save(useCaseExercise); - exerciseRepo.save(communicationExercise); - exerciseRepo.save(componentExercise); - exerciseRepo.save(deploymentExercise); - exerciseRepo.save(petriNetExercise); - exerciseRepo.save(syntaxTreeExercise); - exerciseRepo.save(flowchartExercise); - exerciseRepo.save(finishedExercise); + exerciseRepository.save(classExercise); + exerciseRepository.save(activityExercise); + exerciseRepository.save(objectExercise); + exerciseRepository.save(useCaseExercise); + exerciseRepository.save(communicationExercise); + exerciseRepository.save(componentExercise); + exerciseRepository.save(deploymentExercise); + exerciseRepository.save(petriNetExercise); + exerciseRepository.save(syntaxTreeExercise); + exerciseRepository.save(flowchartExercise); + exerciseRepository.save(finishedExercise); Course storedCourse = courseRepo.findByIdWithExercisesAndExerciseDetailsAndLecturesElseThrow(course.getId()); Set exercises = storedCourse.getExercises(); assertThat(exercises).as("eleven exercises got stored").hasSize(11); diff --git a/src/test/java/de/tum/cit/aet/artemis/plagiarism/ContinuousPlagiarismControlServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/plagiarism/ContinuousPlagiarismControlServiceTest.java index bba2832d362d..1986d792856d 100644 --- a/src/test/java/de/tum/cit/aet/artemis/plagiarism/ContinuousPlagiarismControlServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/plagiarism/ContinuousPlagiarismControlServiceTest.java @@ -25,7 +25,7 @@ import de.tum.cit.aet.artemis.core.domain.User; import de.tum.cit.aet.artemis.exercise.domain.Exercise; import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.fileupload.domain.FileUploadExercise; import de.tum.cit.aet.artemis.modeling.domain.ModelingExercise; import de.tum.cit.aet.artemis.plagiarism.domain.PlagiarismCase; @@ -51,7 +51,7 @@ class ContinuousPlagiarismControlServiceTest { - private final ExerciseRepository exerciseRepository = mock(); + private final ExerciseTestRepository exerciseRepository = mock(); private final PlagiarismDetectionService plagiarismChecksService = mock(); diff --git a/src/test/java/de/tum/cit/aet/artemis/plagiarism/PlagiarismUtilService.java b/src/test/java/de/tum/cit/aet/artemis/plagiarism/PlagiarismUtilService.java index 67208a1bfabe..d08bda49304e 100644 --- a/src/test/java/de/tum/cit/aet/artemis/plagiarism/PlagiarismUtilService.java +++ b/src/test/java/de/tum/cit/aet/artemis/plagiarism/PlagiarismUtilService.java @@ -21,7 +21,7 @@ import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationFactory; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.exercise.team.TeamUtilService; import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository; import de.tum.cit.aet.artemis.exercise.test_repository.SubmissionTestRepository; @@ -47,7 +47,7 @@ public class PlagiarismUtilService { private CourseTestRepository courseRepo; @Autowired - private ExerciseRepository exerciseRepo; + private ExerciseTestRepository exerciseRepository; @Autowired private StudentParticipationTestRepository studentParticipationRepo; @@ -76,7 +76,7 @@ private TextExercise createTextExercise(String userPrefix, int studentsAmount, E exercise.setMode(mode); course.addExercises(exercise); courseRepo.save(course); - return exerciseRepo.save(exercise); + return exerciseRepository.save(exercise); } private ModelingExercise createModelingExercise(String userPrefix, int studentsAmount, ExerciseMode mode) { @@ -85,7 +85,7 @@ private ModelingExercise createModelingExercise(String userPrefix, int studentsA exercise.setMode(mode); course.addExercises(exercise); courseRepo.save(course); - return exerciseRepo.save(exercise); + return exerciseRepository.save(exercise); } private StudentParticipation saveParticipationAndAddSubmission(StudentParticipation participation, Submission submission) { @@ -115,7 +115,7 @@ public long createTextExerciseAndSimilarSubmissions(String userPrefix, String si saveParticipationAndAddSubmission(participation, submission); exercise.addParticipation(participation); } - exerciseRepo.save(exercise); + exerciseRepository.save(exercise); return exercise.getId(); } @@ -137,7 +137,7 @@ public long createTeamTextExerciseAndSimilarSubmissions(String userPrefix, Strin saveParticipationAndAddSubmission(participation, submission); exercise.addParticipation(participation); } - exerciseRepo.save(exercise); + exerciseRepository.save(exercise); return exercise.getId(); } @@ -159,7 +159,7 @@ public long createModelingExerciseAndSimilarSubmissionsToTheCourse(String userPr saveParticipationAndAddSubmission(participation, submission); exercise.addParticipation(participation); } - exerciseRepo.save(exercise); + exerciseRepository.save(exercise); return exercise.getId(); } @@ -181,7 +181,7 @@ public long createTeamModelingExerciseAndSimilarSubmissionsToTheCourse(String us saveParticipationAndAddSubmission(participation, submission); exercise.addParticipation(participation); } - exerciseRepo.save(exercise); + exerciseRepository.save(exercise); return exercise.getId(); } diff --git a/src/test/java/de/tum/cit/aet/artemis/programming/ProgrammingExerciseGradingServiceTest.java b/src/test/java/de/tum/cit/aet/artemis/programming/ProgrammingExerciseGradingServiceTest.java index 3b7b0bad36c8..b38a7248ae5f 100644 --- a/src/test/java/de/tum/cit/aet/artemis/programming/ProgrammingExerciseGradingServiceTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/programming/ProgrammingExerciseGradingServiceTest.java @@ -47,7 +47,6 @@ import de.tum.cit.aet.artemis.exercise.domain.participation.Participation; import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository; import de.tum.cit.aet.artemis.exercise.util.ExerciseUtilService; import de.tum.cit.aet.artemis.programming.domain.ProgrammingExercise; @@ -84,9 +83,6 @@ abstract class ProgrammingExerciseGradingServiceTest extends AbstractSpringInteg @Autowired private ProgrammingExerciseTestCaseTestRepository testCaseRepository; - @Autowired - private ExerciseRepository exerciseRepository; - @Autowired private StudentParticipationTestRepository studentParticipationRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/quiz/util/QuizExerciseUtilService.java b/src/test/java/de/tum/cit/aet/artemis/quiz/util/QuizExerciseUtilService.java index 261ac6f912b0..2c378bb69fe9 100644 --- a/src/test/java/de/tum/cit/aet/artemis/quiz/util/QuizExerciseUtilService.java +++ b/src/test/java/de/tum/cit/aet/artemis/quiz/util/QuizExerciseUtilService.java @@ -31,7 +31,7 @@ import de.tum.cit.aet.artemis.exercise.domain.TeamAssignmentConfig; import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.exercise.repository.TeamRepository; import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository; import de.tum.cit.aet.artemis.quiz.domain.DragAndDropMapping; @@ -70,7 +70,7 @@ public class QuizExerciseUtilService { private CourseTestRepository courseRepo; @Autowired - private ExerciseRepository exerciseRepo; + private ExerciseTestRepository exerciseRepository; @Autowired private QuizSubmissionTestRepository quizSubmissionRepository; @@ -137,7 +137,7 @@ public Course addCourseWithOneQuizExercise(String title) { assertThat(quizExercise.isValid()).isTrue(); course.addExercises(quizExercise); course = courseRepo.save(course); - quizExercise = exerciseRepo.save(quizExercise); + quizExercise = exerciseRepository.save(quizExercise); assertThat(courseRepo.findWithEagerExercisesById(course.getId()).getExercises()).as("course contains the exercise").contains(quizExercise); return course; } diff --git a/src/test/java/de/tum/cit/aet/artemis/shared/base/AbstractArtemisIntegrationTest.java b/src/test/java/de/tum/cit/aet/artemis/shared/base/AbstractArtemisIntegrationTest.java index 57706d00e482..4157341a3deb 100644 --- a/src/test/java/de/tum/cit/aet/artemis/shared/base/AbstractArtemisIntegrationTest.java +++ b/src/test/java/de/tum/cit/aet/artemis/shared/base/AbstractArtemisIntegrationTest.java @@ -51,7 +51,7 @@ import de.tum.cit.aet.artemis.core.util.RequestUtilService; import de.tum.cit.aet.artemis.core.util.ThrowingProducer; import de.tum.cit.aet.artemis.exam.service.ExamAccessService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.exercise.util.ExerciseUtilService; import de.tum.cit.aet.artemis.lti.service.Lti13Service; import de.tum.cit.aet.artemis.modeling.service.ModelingSubmissionService; @@ -186,7 +186,7 @@ public abstract class AbstractArtemisIntegrationTest implements MockDelegate { protected UserTestRepository userTestRepository; @Autowired - protected ExerciseRepository exerciseRepository; + protected ExerciseTestRepository exerciseRepository; @Autowired protected ResultTestRepository resultRepository; diff --git a/src/test/java/de/tum/cit/aet/artemis/text/util/TextExerciseUtilService.java b/src/test/java/de/tum/cit/aet/artemis/text/util/TextExerciseUtilService.java index a143f0ffec31..dff71d5bc7d2 100644 --- a/src/test/java/de/tum/cit/aet/artemis/text/util/TextExerciseUtilService.java +++ b/src/test/java/de/tum/cit/aet/artemis/text/util/TextExerciseUtilService.java @@ -35,7 +35,7 @@ import de.tum.cit.aet.artemis.exercise.domain.participation.StudentParticipation; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationFactory; import de.tum.cit.aet.artemis.exercise.participation.util.ParticipationUtilService; -import de.tum.cit.aet.artemis.exercise.repository.ExerciseRepository; +import de.tum.cit.aet.artemis.exercise.repository.ExerciseTestRepository; import de.tum.cit.aet.artemis.exercise.test_repository.ParticipationTestRepository; import de.tum.cit.aet.artemis.exercise.test_repository.StudentParticipationTestRepository; import de.tum.cit.aet.artemis.exercise.test_repository.SubmissionTestRepository; @@ -63,7 +63,7 @@ public class TextExerciseUtilService { private static final ZonedDateTime futureFutureTimestamp = ZonedDateTime.now().plusDays(2); @Autowired - private ExerciseRepository exerciseRepo; + private ExerciseTestRepository exerciseRepository; @Autowired private CourseTestRepository courseRepo; @@ -195,7 +195,7 @@ public TextExercise createIndividualTextExercise(Course course, ZonedDateTime re TextExercise textExercise = TextExerciseFactory.generateTextExercise(releaseDate, dueDate, assessmentDueDate, course); textExercise.setMaxPoints(10.0); textExercise.setBonusPoints(0.0); - return exerciseRepo.save(textExercise); + return exerciseRepository.save(textExercise); } /** @@ -212,7 +212,7 @@ public TextExercise createTeamTextExercise(Course course, ZonedDateTime releaseD teamTextExercise.setMaxPoints(10.0); teamTextExercise.setBonusPoints(0.0); teamTextExercise.setMode(ExerciseMode.TEAM); - return exerciseRepo.save(teamTextExercise); + return exerciseRepository.save(teamTextExercise); } /** @@ -227,7 +227,7 @@ public Course addCourseWithOneReleasedTextExercise(String title) { textExercise.setTitle(title); course.addExercises(textExercise); course = courseRepo.save(course); - textExercise = exerciseRepo.save(textExercise); + textExercise = exerciseRepository.save(textExercise); assertThat(courseRepo.findWithEagerExercisesById(course.getId()).getExercises()).as("course contains the exercise").contains(textExercise); assertThat(textExercise.getPresentationScoreEnabled()).as("presentation score is enabled").isTrue(); @@ -269,7 +269,7 @@ public TextExercise addCourseExamExerciseGroupWithOneTextExercise(String title) if (title != null) { textExercise.setTitle(title); } - return exerciseRepo.save(textExercise); + return exerciseRepository.save(textExercise); } /** @@ -289,7 +289,7 @@ public TextExercise addCourseExamExerciseGroupWithOneTextExercise() { public TextExercise addCourseExamWithReviewDatesExerciseGroupWithOneTextExercise() { ExerciseGroup exerciseGroup = examUtilService.addExerciseGroupWithExamWithReviewDatesAndCourse(true); TextExercise textExercise = TextExerciseFactory.generateTextExerciseForExam(exerciseGroup); - return exerciseRepo.save(textExercise); + return exerciseRepository.save(textExercise); } /** @@ -545,7 +545,7 @@ public Course addCourseWithOneFinishedTextExercise() { finishedTextExercise.setTitle("Finished"); course.addExercises(finishedTextExercise); course = courseRepo.save(course); - exerciseRepo.save(finishedTextExercise); + exerciseRepository.save(finishedTextExercise); return course; } diff --git a/src/test/javascript/spec/component/course/course.component.spec.ts b/src/test/javascript/spec/component/course/course.component.spec.ts index ad867798e564..925a54864297 100644 --- a/src/test/javascript/spec/component/course/course.component.spec.ts +++ b/src/test/javascript/spec/component/course/course.component.spec.ts @@ -33,6 +33,8 @@ import { of } from 'rxjs'; import dayjs from 'dayjs/esm'; import { Exam } from 'app/entities/exam/exam.model'; import { CourseAccessStorageService } from 'app/course/course-access-storage.service'; +import { SearchFilterPipe } from 'app/shared/pipes/search-filter.pipe'; +import { SearchFilterComponent } from 'app/shared/search-filter/search-filter.component'; const endDate1 = dayjs().add(1, 'days'); const visibleDate1 = dayjs().subtract(1, 'days'); @@ -100,10 +102,12 @@ describe('CoursesComponent', () => { MockDirective(SortDirective), MockDirective(SortByDirective), MockPipe(ArtemisDatePipe), + MockPipe(SearchFilterPipe), MockComponent(CourseExerciseRowComponent), MockComponent(CourseExercisesComponent), MockComponent(CourseRegistrationComponent), MockComponent(CourseCardComponent), + MockComponent(SearchFilterComponent), ], providers: [ { provide: LocalStorageService, useClass: MockSyncStorage }, diff --git a/src/test/javascript/spec/component/exam/participate/exercises/file-upload-exam-submission.component.spec.ts b/src/test/javascript/spec/component/exam/participate/exercises/file-upload-exam-submission.component.spec.ts index 83319f461faf..9c10ec5ca996 100644 --- a/src/test/javascript/spec/component/exam/participate/exercises/file-upload-exam-submission.component.spec.ts +++ b/src/test/javascript/spec/component/exam/participate/exercises/file-upload-exam-submission.component.spec.ts @@ -77,10 +77,9 @@ describe('FileUploadExamSubmissionComponent', () => { expect(FileUploadExamSubmissionComponent).not.toBeNull(); }); - it('should show exercise group title', () => { - comp.exercise.exerciseGroup = { title: 'Test Group' } as ExerciseGroup; + it('should show static text in header', () => { fixture.detectChanges(); - const el = fixture.debugElement.query((de) => de.nativeElement.textContent === comp.exercise.exerciseGroup?.title); + const el = fixture.debugElement.query((de) => de.nativeElement.textContent === 'artemisApp.exam.yourSolution'); expect(el).not.toBeNull(); }); diff --git a/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts b/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts index 1277bc869032..60731362866e 100644 --- a/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts +++ b/src/test/javascript/spec/component/exam/participate/exercises/modeling-exam-submission.component.spec.ts @@ -16,7 +16,6 @@ import { ArtemisTestModule } from '../../../../test.module'; import { IncludedInScoreBadgeComponent } from 'app/exercises/shared/exercise-headers/included-in-score-badge.component'; import { ExamExerciseUpdateHighlighterComponent } from 'app/exam/participate/exercises/exam-exercise-update-highlighter/exam-exercise-update-highlighter.component'; import { NgbTooltipMocksModule } from '../../../../helpers/mocks/directive/ngbTooltipMocks.module'; -import { ExerciseGroup } from 'app/entities/exercise-group.model'; import { SubmissionVersion } from 'app/entities/submission-version.model'; describe('ModelingExamSubmissionComponent', () => { @@ -69,10 +68,9 @@ describe('ModelingExamSubmissionComponent', () => { expect(ModelingExamSubmissionComponent).not.toBeNull(); }); - it('should show exercise group title', () => { - comp.exercise.exerciseGroup = { title: 'Test Group' } as ExerciseGroup; + it('should show static text in header', () => { fixture.detectChanges(); - const el = fixture.debugElement.query((de) => de.nativeElement.textContent === comp.exercise.exerciseGroup?.title); + const el = fixture.debugElement.query((de) => de.nativeElement.textContent === 'artemisApp.exam.yourSolution'); expect(el).not.toBeNull(); });