Skip to content

Commit

Permalink
Merge branch 'develop' into chore/migrate-tutorial-groups-to-signals
Browse files Browse the repository at this point in the history
  • Loading branch information
az108 authored Dec 4, 2024
2 parents 43b8959 + 0f12a54 commit 8266df5
Show file tree
Hide file tree
Showing 152 changed files with 2,579 additions and 1,610 deletions.
60 changes: 23 additions & 37 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -180,13 +180,13 @@ jacocoTestCoverageVerification {
counter = "INSTRUCTION"
value = "COVEREDRATIO"
// TODO: in the future the following value should become higher than 0.92
minimum = 0.895
minimum = 0.892
}
limit {
counter = "CLASS"
value = "MISSEDCOUNT"
// TODO: in the future the following value should become less than 10
maximum = 60
maximum = 65
}
}
}
Expand All @@ -212,17 +212,16 @@ repositories {
maven {
url "https://build.shibboleth.net/maven/releases"
}
// required for latest jgit 7.0.0 dependency
// TODO: remove this when jgit is available in the official maven repository
// TODO: remove this when spring cloud is available in the official maven repository
maven {
url "https://repo.eclipse.org/content/repositories/jgit-releases"
url "https://repo.spring.io/milestone"
}
}

ext["jackson.version"] = fasterxml_version
ext["junit-jupiter.version"] = junit_version

ext { qDoxVersionReusable = "com.thoughtworks.qdox:qdox:2.1.0" }
ext { qDoxVersionReusable = "com.thoughtworks.qdox:qdox:2.2.0" }
ext { springBootStarterWeb = "org.springframework.boot:spring-boot-starter-web:${spring_boot_version}" }

dependencies {
Expand All @@ -231,9 +230,8 @@ dependencies {
// implementation "com.offbytwo.jenkins:jenkins-client:0.3.8"
implementation files("libs/jenkins-client-0.4.1.jar")
// The following 4 dependencies are explicitly integrated as transitive dependencies of jenkins-client-0.4.0.jar
// NOTE: we cannot upgrade to the latest version for org.apache.httpcomponents because of exceptions in Docker Java
implementation "org.apache.httpcomponents.client5:httpclient5:5.3.1" // also used by Docker Java
implementation "org.apache.httpcomponents.core5:httpcore5:5.2.5"
implementation "org.apache.httpcomponents.client5:httpclient5:5.4.1"
implementation "org.apache.httpcomponents.core5:httpcore5:5.3.1"
implementation "org.apache.httpcomponents:httpmime:4.5.14"
implementation("org.dom4j:dom4j:2.1.4") {
// Note: avoid org.xml.sax.SAXNotRecognizedException: unrecognized feature http://xml.org/sax/features/external-general-entities
Expand All @@ -246,7 +244,7 @@ dependencies {
exclude module: "jaxb-api"
}

implementation "org.gitlab4j:gitlab4j-api:6.0.0-rc.6"
implementation "org.gitlab4j:gitlab4j-api:6.0.0-rc.7"

implementation "de.jplag:jplag:${jplag_version}"

Expand All @@ -268,7 +266,7 @@ dependencies {
implementation "org.apache.lucene:lucene-queryparser:${lucene_version}"
implementation "org.apache.lucene:lucene-core:${lucene_version}"
implementation "org.apache.lucene:lucene-analyzers-common:${lucene_version}"
implementation "com.google.protobuf:protobuf-java:4.28.3"
implementation "com.google.protobuf:protobuf-java:4.29.0"

// we have to override those values to use the latest version
implementation "org.slf4j:jcl-over-slf4j:${slf4j_version}"
Expand All @@ -279,7 +277,7 @@ dependencies {
}
}

implementation "org.apache.logging.log4j:log4j-to-slf4j:2.24.1"
implementation "org.apache.logging.log4j:log4j-to-slf4j:2.24.2"

// Note: spring-security-lti13 does not work with jakarta yet, so we built our own custom version and declare its transitive dependencies below
// implementation "uk.ac.ox.ctl:spring-security-lti13:0.1.11"
Expand Down Expand Up @@ -327,24 +325,26 @@ dependencies {
// required by Saml2
implementation "org.apache.santuario:xmlsec:4.0.3"

implementation "org.jsoup:jsoup:1.18.1"
implementation "org.jsoup:jsoup:1.18.3"
implementation "commons-codec:commons-codec:1.17.1" // needed for spring security saml2

// TODO: decide if we want to use OpenAPI and Swagger v3
// implementation 'io.swagger.core.v3:swagger-annotations:2.2.23'
// implementation "org.springdoc:springdoc-openapi-ui:1.8.0"

// use the latest version to avoid security vulnerabilities
implementation "org.springframework:spring-webmvc:6.1.14"
implementation "org.springframework:spring-webmvc:${spring_framework_version}"

implementation "com.vdurmont:semver4j:3.1.0"

implementation "com.github.docker-java:docker-java-core:${docker_java_version}"
implementation "com.github.docker-java:docker-java-transport-httpclient5:${docker_java_version}"
// Note: we explicitly use docker-java-transport-zerodep, because docker-java-transport-httpclient5 uses an outdated http5 version which is not compatible with Spring Boot >= 3.4.0
implementation "com.github.docker-java:docker-java-transport-zerodep:${docker_java_version}"

// use newest version of commons-compress to avoid security issues through outdated dependencies
implementation "org.apache.commons:commons-compress:1.27.1"


// import JHipster dependencies BOM
implementation platform("tech.jhipster:jhipster-dependencies:${jhipster_dependencies_version}")

Expand Down Expand Up @@ -403,32 +403,26 @@ dependencies {
implementation "org.springframework.boot:spring-boot-starter-oauth2-client:${spring_boot_version}"

implementation "org.springframework.ldap:spring-ldap-core:3.2.8"
implementation "org.springframework.data:spring-data-ldap:3.3.5"
implementation "org.springframework.data:spring-data-ldap:3.4.0"

implementation("org.springframework.cloud:spring-cloud-starter-netflix-eureka-client:4.1.3") {
implementation("org.springframework.cloud:spring-cloud-starter-netflix-eureka-client:${spring_cloud_version}") {
// NOTE: these modules contain security vulnerabilities and are not needed
exclude module: "commons-jxpath"
exclude module: "woodstox-core"
}
implementation "org.springframework.cloud:spring-cloud-starter-config:4.1.3"
implementation "org.springframework.cloud:spring-cloud-commons:4.1.4"
implementation "org.springframework.cloud:spring-cloud-starter-config:${spring_cloud_version}"
implementation "org.springframework.cloud:spring-cloud-commons:${spring_cloud_version}"

implementation "io.netty:netty-all:4.1.115.Final"
implementation "io.projectreactor.netty:reactor-netty:1.2.0"
implementation("io.netty:netty-common") {
version {
strictly netty_version
}
}

implementation "org.springframework:spring-messaging:6.1.14"
implementation "org.springframework:spring-messaging:${spring_framework_version}"
implementation "org.springframework.retry:spring-retry:2.0.10"

implementation "org.springframework.security:spring-security-config:${spring_security_version}"
implementation "org.springframework.security:spring-security-data:${spring_security_version}"
implementation "org.springframework.security:spring-security-core:${spring_security_version}"
implementation "org.springframework.security:spring-security-oauth2-core:${spring_security_version}"
implementation "org.springframework.security:spring-security-oauth2-client:${spring_security_version}"
implementation "org.springframework.security:spring-security-oauth2-resource-server:${spring_security_version}"
// use newest version of nimbus-jose-jwt to avoid security issues through outdated dependencies
implementation "com.nimbusds:nimbus-jose-jwt:9.47"

Expand Down Expand Up @@ -547,18 +541,10 @@ dependencies {
testImplementation "org.gradle:gradle-tooling-api:8.11.1"
testImplementation "org.apache.maven.surefire:surefire-report-parser:3.5.2"
testImplementation "com.opencsv:opencsv:5.9"
testImplementation("io.zonky.test:embedded-database-spring-test:2.5.1") {
testImplementation("io.zonky.test:embedded-database-spring-test:2.6.0") {
exclude group: "org.testcontainers", module: "mariadb"
exclude group: "org.testcontainers", module: "mssqlserver"
}
testImplementation "org.testcontainers:testcontainers:${testcontainer_version}"
testImplementation "org.testcontainers:mysql:${testcontainer_version}"
testImplementation "org.testcontainers:postgresql:${testcontainer_version}"
testImplementation "org.testcontainers:testcontainers:${testcontainer_version}"
testImplementation "org.testcontainers:junit-jupiter:${testcontainer_version}"
testImplementation "org.testcontainers:jdbc:${testcontainer_version}"
testImplementation "org.testcontainers:database-commons:${testcontainer_version}"

testImplementation "com.tngtech.archunit:archunit:1.3.0"
testImplementation("org.skyscreamer:jsonassert:1.5.3") {
exclude module: "android-json"
Expand Down Expand Up @@ -634,7 +620,7 @@ tasks.withType(Test).configureEach {
}

wrapper {
gradleVersion = "8.11"
gradleVersion = "8.11.1"
}

tasks.register("stage") {
Expand Down
80 changes: 40 additions & 40 deletions docs/dev/guidelines/client-tests.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ The most basic test looks similar to this:
let someComponentFixture: ComponentFixture<SomeComponent>;
let someComponent: SomeComponent;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [],
declarations: [
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
SomeComponent,
MockPipe(SomePipeUsedInTemplate),
MockComponent(SomeComponentUsedInTemplate),
Expand All @@ -31,11 +30,10 @@ The most basic test looks similar to this:
MockProvider(SomeServiceUsedInComponent),
],
})
.compileComponents()
.then(() => {
someComponentFixture = TestBed.createComponent(SomeComponent);
someComponent = someComponentFixture.componentInstance;
});
.compileComponents();
someComponentFixture = TestBed.createComponent(SomeComponent);
someComponent = someComponentFixture.componentInstance;
});
afterEach(() => {
Expand All @@ -60,24 +58,25 @@ Some guidelines:
describe('ParticipationSubmissionComponent', () => {
...
beforeEach(() => {
return TestBed.configureTestingModule({
imports: [ArtemisTestModule, NgxDatatableModule, ArtemisResultModule, ArtemisSharedModule, TranslateModule.forRoot(), RouterTestingModule],
declarations: [
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
ArtemisTestModule,
NgxDatatableModule,
ArtemisResultModule,
ArtemisSharedModule,
TranslateModule.forRoot(),
ParticipationSubmissionComponent,
MockComponent(UpdatingResultComponent),
MockComponent(AssessmentDetailComponent),
MockComponent(ComplaintsForTutorComponent),
],
providers: [
...
provideRouter([]),
],
})
.overrideModule(ArtemisTestModule, { set: { declarations: [], exports: [] } })
.compileComponents()
.then(() => {
...
});
.compileComponents();
});
});
Expand All @@ -94,10 +93,12 @@ Some guidelines:
describe('ParticipationSubmissionComponent', () => {
...
beforeEach(() => {
return TestBed.configureTestingModule({
imports: [ArtemisTestModule, RouterTestingModule, NgxDatatableModule],
declarations: [
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [
ArtemisTestModule,
RouterTestingModule,
NgxDatatableModule,
ParticipationSubmissionComponent,
MockComponent(UpdatingResultComponent),
MockComponent(AssessmentDetailComponent),
Expand All @@ -110,13 +111,10 @@ Some guidelines:
MockComponent(ResultComponent),
],
providers: [
...
provideRouter([]),
],
})
.compileComponents()
.then(() => {
...
});
.compileComponents();
});
});
Expand Down Expand Up @@ -158,11 +156,16 @@ Some guidelines:

.. code:: ts
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting, HttpTestingController } from '@angular/common/http/testing';
describe('SomeComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
imports: [...],
providers: [
provideHttpClient(),
provideHttpClientTesting(),
],
});
...
Expand Down Expand Up @@ -221,21 +224,18 @@ Some guidelines:
let someComponentFixture: ComponentFixture<SomeComponent>;
let someComponent: SomeComponent;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [],
declarations: [
SomeComponent,
],
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [SomeComponent],
providers: [
...
],
})
.overrideTemplate(SomeComponent, '') // DO NOT DO THIS
.compileComponents()
.then(() => {
someComponentFixture = TestBed.createComponent(SomeComponent);
someComponent = someComponentFixture.componentInstance;
});
.compileComponents();
someComponentFixture = TestBed.createComponent(SomeComponent);
someComponent = someComponentFixture.componentInstance;
});
});
Expand Down
14 changes: 7 additions & 7 deletions docs/dev/guidelines/server-tests.rst
Original file line number Diff line number Diff line change
Expand Up @@ -151,19 +151,19 @@ Follow these tips to write performant tests:
* Limit object creation in tests and the test setup.


6. Avoid using @MockBean
=========================
6. Avoid using @MockitoBean
===========================

Do not use the ``@SpyBean`` or ``@MockBean`` annotation unless absolutely necessary or possibly in an abstract Superclass. `Here <https://www.baeldung.com/spring-tests>`__ you can see why in more detail.
Whenever``@MockBean`` appears in a class, the application context cache gets marked as dirty, meaning the runner will clean the cache after finishing the test class. The application context is restarted, which leads to an additional server start with runtime overhead.
Do not use the ``@MockitoSpyBean`` or ``@MockitoBean`` annotation unless absolutely necessary or possibly in an abstract Superclass. `Here <https://www.baeldung.com/spring-tests>`__ you can see why in more detail.
Whenever``@MockitoBean`` appears in a class, the application context cache gets marked as dirty, meaning the runner will clean the cache after finishing the test class. The application context is restarted, which leads to an additional server start with runtime overhead.
We want to keep the number of server starts minimal.

Below is an example of how to replace a ``@SpyBean``. To test an edge case where an ``IOException`` is thrown, we mocked the service method so it threw an Exception.
Below is an example of how to replace a ``@MockitoSpyBean``. To test an edge case where an ``IOException`` is thrown, we mocked the service method so it threw an Exception.

.. code-block:: java
class TestExport extends AbstractSpringIntegrationIndependentTest {
@SpyBean
@MockitoSpyBean
private FileUploadSubmissionExportService fileUploadSubmissionExportService;
@Test
Expand All @@ -174,7 +174,7 @@ Below is an example of how to replace a ``@SpyBean``. To test an edge case where
}
}
To avoid new SpyBeans, we now use `static mocks <https://asolntsev.github.io/en/2020/07/11/mockito-static-methods/>`__. Upon examining the ``export()`` method, we find a ``File.newOutputStream(..)`` call.
To avoid new MockitoSpyBeans, we now use `static mocks <https://asolntsev.github.io/en/2020/07/11/mockito-static-methods/>`__. Upon examining the ``export()`` method, we find a ``File.newOutputStream(..)`` call.
Now, instead of mocking the whole service, we can mock the static method:

.. code-block:: java
Expand Down
6 changes: 4 additions & 2 deletions docs/user/adaptive-learning/adaptive-learning-instructor.rst
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,10 @@ Learning Paths

Instructors can enable learning paths for their courses either by editing the course or on the dedicated learning path management page. This will generate individualized learning paths for all course participants.

Once the feature is enabled, instructors get access to each student's learning path. Instructors can search for students by login or name and view their respective learning path graph.

Once the feature is enabled, instructors gain access to the Learning Paths Management page, where they can view an overview of the status of the learning paths feature.
For example, if competencies have not yet been created or relationships between them are missing, the State panel will notify instructors of these issues.
Instructors can also review the individual learning paths of students. The table on this page displays each student's login, name, and progress within their learning path. By clicking on a student's progress, the instructor can open the learning path graph, which illustrates the relationships between competencies and prerequisites and shows the student's mastery level for each.
At the bottom of the page, instructors can find generalized information about the learning paths of all students. This includes a graph that presents the average mastery level for each competency or prerequisite across the entire class.
|instructors-learning-path-management|

.. |instructor-competency-management| image:: instructor/manage-competencies.png
Expand Down
Loading

0 comments on commit 8266df5

Please sign in to comment.