diff --git a/src/main/webapp/app/exam/exam-scores/exam-scores-average-scores-graph.component.html b/src/main/webapp/app/exam/exam-scores/exam-scores-average-scores-graph.component.html
index 35ab48c1854a..958122437f2b 100644
--- a/src/main/webapp/app/exam/exam-scores/exam-scores-average-scores-graph.component.html
+++ b/src/main/webapp/app/exam/exam-scores/exam-scores-average-scores-graph.component.html
@@ -1,6 +1,6 @@
-
+
();
+ course = input.required();
courseId: number;
examId: number;
@@ -39,14 +49,6 @@ export class ExamScoresAverageScoresGraphComponent implements OnInit {
xScaleMax = 100;
lookup: NameToValueMap = {};
- constructor(
- private navigationUtilService: ArtemisNavigationUtilService,
- private activatedRoute: ActivatedRoute,
- private service: StatisticsService,
- private translateService: TranslateService,
- private localeConversionService: LocaleConversionService,
- ) {}
-
ngOnInit(): void {
this.activatedRoute.params.subscribe((params) => {
this.courseId = +params['courseId'];
@@ -56,12 +58,12 @@ export class ExamScoresAverageScoresGraphComponent implements OnInit {
}
private initializeChart(): void {
- this.lookup[this.averageScores.title] = { absoluteValue: this.averageScores.averagePoints! };
- const exerciseGroupAverage = this.averageScores.averagePercentage ? this.averageScores.averagePercentage : 0;
- this.ngxData.push({ name: this.averageScores.title, value: exerciseGroupAverage });
+ this.lookup[this.averageScores().title] = { absoluteValue: this.averageScores().averagePoints! };
+ const exerciseGroupAverage = this.averageScores().averagePercentage ?? 0;
+ this.ngxData.push({ name: this.averageScores().title, value: exerciseGroupAverage });
this.ngxColor.domain.push(this.determineColor(true, exerciseGroupAverage));
this.xScaleMax = this.xScaleMax > exerciseGroupAverage ? this.xScaleMax : exerciseGroupAverage;
- this.averageScores.exerciseResults.forEach((exercise) => {
+ this.averageScores().exerciseResults.forEach((exercise) => {
const exerciseAverage = exercise.averagePercentage ?? 0;
this.xScaleMax = this.xScaleMax > exerciseAverage ? this.xScaleMax : exerciseAverage;
this.ngxData.push({ name: exercise.exerciseId + ' ' + exercise.title, value: exerciseAverage });
@@ -77,14 +79,14 @@ export class ExamScoresAverageScoresGraphComponent implements OnInit {
}
roundAndPerformLocalConversion(points: number | undefined) {
- return this.localeConversionService.toLocaleString(roundValueSpecifiedByCourseSettings(points, this.course), this.course!.accuracyOfScores!);
+ return this.localeConversionService.toLocaleString(roundValueSpecifiedByCourseSettings(points, this.course()), this.course()!.accuracyOfScores!);
}
/**
* We navigate to the exercise scores page when the user clicks on a data point
*/
navigateToExercise(exerciseId: number, exerciseType: ExerciseType) {
- navigateToExamExercise(this.navigationUtilService, this.courseId, this.examId, this.averageScores.exerciseGroupId, exerciseType, exerciseId, 'scores');
+ navigateToExamExercise(this.navigationUtilService, this.courseId, this.examId, this.averageScores().exerciseGroupId, exerciseType, exerciseId, 'scores');
}
/**
diff --git a/src/main/webapp/app/exam/exam-scores/exam-scores.component.ts b/src/main/webapp/app/exam/exam-scores/exam-scores.component.ts
index 94a6f375b3b7..3c09d79156e4 100644
--- a/src/main/webapp/app/exam/exam-scores/exam-scores.component.ts
+++ b/src/main/webapp/app/exam/exam-scores/exam-scores.component.ts
@@ -1,8 +1,8 @@
-import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
+import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnDestroy, OnInit, inject } from '@angular/core';
import { Subscription, forkJoin, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { ExamManagementService } from 'app/exam/manage/exam-management.service';
-import { ActivatedRoute } from '@angular/router';
+import { ActivatedRoute, RouterLink } from '@angular/router';
import { SortService } from 'app/shared/service/sort.service';
import { download, generateCsv, mkConfig } from 'export-to-csv';
import {
@@ -58,6 +58,14 @@ import {
USERNAME_KEY,
} from 'app/shared/export/export-constants';
import { BonusStrategy } from 'app/entities/bonus.model';
+import { FaIconComponent } from '@fortawesome/angular-fontawesome';
+import { TranslateDirective } from '../../shared/language/translate.directive';
+import { ExportModule } from '../../shared/export/export.module';
+import { NgStyle } from '@angular/common';
+import { ArtemisParticipantScoresModule } from '../../shared/participant-scores/participant-scores.module';
+import { ExamScoresAverageScoresGraphComponent } from './exam-scores-average-scores-graph.component';
+import { ArtemisSharedComponentModule } from '../../shared/components/shared-component.module';
+import { ArtemisSharedCommonModule } from '../../shared/shared-common.module';
export enum MedianType {
PASSED,
@@ -70,8 +78,31 @@ export enum MedianType {
templateUrl: './exam-scores.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
styleUrls: ['./exam-scores.component.scss', '../../shared/chart/vertical-bar-chart.scss'],
+ standalone: true,
+ imports: [
+ FaIconComponent,
+ TranslateDirective,
+ ExportModule,
+ RouterLink,
+ NgStyle,
+ ArtemisParticipantScoresModule,
+ ExamScoresAverageScoresGraphComponent,
+ ArtemisSharedComponentModule,
+ ArtemisSharedCommonModule,
+ ],
})
export class ExamScoresComponent implements OnInit, OnDestroy {
+ private route = inject(ActivatedRoute);
+ private examService = inject(ExamManagementService);
+ private sortService = inject(SortService);
+ private alertService = inject(AlertService);
+ private changeDetector = inject(ChangeDetectorRef);
+ private languageHelper = inject(JhiLanguageHelper);
+ private localeConversionService = inject(LocaleConversionService);
+ private participantScoresService = inject(ParticipantScoresService);
+ private gradingSystemService = inject(GradingSystemService);
+ private courseManagementService = inject(CourseManagementService);
+
public examScoreDTO: ExamScoreDTO;
public exerciseGroups: ExerciseGroup[];
public studentResults: StudentResult[];
@@ -130,18 +161,6 @@ export class ExamScoresComponent implements OnInit, OnDestroy {
faExclamationTriangle = faExclamationTriangle;
private languageChangeSubscription?: Subscription;
- constructor(
- private route: ActivatedRoute,
- private examService: ExamManagementService,
- private sortService: SortService,
- private alertService: AlertService,
- private changeDetector: ChangeDetectorRef,
- private languageHelper: JhiLanguageHelper,
- private localeConversionService: LocaleConversionService,
- private participantScoresService: ParticipantScoresService,
- private gradingSystemService: GradingSystemService,
- private courseManagementService: CourseManagementService,
- ) {}
ngOnInit() {
this.route.params.subscribe((params) => {
diff --git a/src/main/webapp/app/exam/exam-scores/exam-scores.module.ts b/src/main/webapp/app/exam/exam-scores/exam-scores.module.ts
index e439030cb776..fc4d3df9b992 100644
--- a/src/main/webapp/app/exam/exam-scores/exam-scores.module.ts
+++ b/src/main/webapp/app/exam/exam-scores/exam-scores.module.ts
@@ -12,7 +12,6 @@ import { ArtemisParticipantScoresModule } from 'app/shared/participant-scores/pa
import { ExportModule } from 'app/shared/export/export.module';
@NgModule({
- declarations: [ExamScoresComponent, ExamScoresAverageScoresGraphComponent],
imports: [
ArtemisSharedModule,
ArtemisExamScoresRoutingModule,
@@ -23,6 +22,8 @@ import { ExportModule } from 'app/shared/export/export.module';
BarChartModule,
ArtemisParticipantScoresModule,
ExportModule,
+ ExamScoresComponent,
+ ExamScoresAverageScoresGraphComponent,
],
})
export class ArtemisExamScoresModule {}
diff --git a/src/test/javascript/spec/component/exam/exam-scores/exam-scores-average-scores-graph.component.spec.ts b/src/test/javascript/spec/component/exam/exam-scores/exam-scores-average-scores-graph.component.spec.ts
index f962626e8e37..49da1a162d28 100644
--- a/src/test/javascript/spec/component/exam/exam-scores/exam-scores-average-scores-graph.component.spec.ts
+++ b/src/test/javascript/spec/component/exam/exam-scores/exam-scores-average-scores-graph.component.spec.ts
@@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { TranslateService } from '@ngx-translate/core';
-import { MockDirective, MockModule, MockPipe, MockProvider } from 'ng-mocks';
+import { MockDirective, MockModule, MockProvider } from 'ng-mocks';
import { of } from 'rxjs';
import { HttpResponse } from '@angular/common/http';
import { ExamScoresAverageScoresGraphComponent } from 'app/exam/exam-scores/exam-scores-average-scores-graph.component';
@@ -9,7 +9,6 @@ import { MockTranslateService } from '../../../helpers/mocks/service/mock-transl
import { AggregatedExerciseGroupResult, AggregatedExerciseResult } from 'app/exam/exam-scores/exam-score-dtos.model';
import { CourseManagementService } from 'app/course/manage/course-management.service';
import { BarChartModule } from '@swimlane/ngx-charts';
-import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe';
import { GraphColors } from 'app/entities/statistics.model';
import { NgxChartsSingleSeriesDataEntry } from 'app/shared/chart/ngx-charts-datatypes';
import { ExerciseType } from 'app/entities/exercise.model';
@@ -56,7 +55,7 @@ describe('ExamScoresAverageScoresGraphComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ArtemisTestModule, MockModule(BarChartModule), RouterModule.forRoot([])],
- declarations: [ExamScoresAverageScoresGraphComponent, MockPipe(ArtemisTranslatePipe), MockDirective(TranslateDirective)],
+ declarations: [ExamScoresAverageScoresGraphComponent, MockDirective(TranslateDirective)],
providers: [
MockProvider(CourseManagementService, {
find: () => {
@@ -70,16 +69,14 @@ describe('ExamScoresAverageScoresGraphComponent', () => {
}),
{ provide: TranslateService, useClass: MockTranslateService },
],
- })
- .compileComponents()
- .then(() => {
- fixture = TestBed.createComponent(ExamScoresAverageScoresGraphComponent);
- component = fixture.componentInstance;
- navigateToExerciseMock = jest.spyOn(component, 'navigateToExercise').mockImplementation();
-
- component.averageScores = returnValue;
- fixture.detectChanges();
- });
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(ExamScoresAverageScoresGraphComponent);
+ component = fixture.componentInstance;
+ navigateToExerciseMock = jest.spyOn(component, 'navigateToExercise').mockImplementation();
+
+ fixture.componentRef.setInput('averageScores', returnValue);
+ fixture.detectChanges();
});
it('should set ngx data objects and bar colors correctly', () => {
@@ -99,8 +96,9 @@ describe('ExamScoresAverageScoresGraphComponent', () => {
});
const adaptExpectedData = (averagePoints: number, newColor: string, expectedColorDomain: string[], expectedData: NgxChartsSingleSeriesDataEntry[]) => {
- component.averageScores.averagePoints = averagePoints;
- component.averageScores.averagePercentage = averagePoints * 10;
+ component.averageScores().averagePoints = averagePoints;
+ component.averageScores().averagePercentage = averagePoints * 10;
+
expectedColorDomain[0] = newColor;
expectedData[0].value = averagePoints * 10;
component.ngxColor.domain = [];
@@ -146,7 +144,10 @@ describe('ExamScoresAverageScoresGraphComponent', () => {
it('should look up absolute value', () => {
const roundAndPerformLocalConversionSpy = jest.spyOn(component, 'roundAndPerformLocalConversion');
- component.course = { accuracyOfScores: 2 };
+ const updatedCourse = {
+ accuracyOfScores: 2,
+ };
+ fixture.componentRef.setInput('course', updatedCourse);
component.lookup['test'] = { absoluteValue: 40 };
const result = component.lookupAbsoluteValue('test');
diff --git a/src/test/javascript/spec/component/exam/exam-scores/exam-scores.component.spec.ts b/src/test/javascript/spec/component/exam/exam-scores/exam-scores.component.spec.ts
index df9ddaa86480..3d82fa3ba673 100644
--- a/src/test/javascript/spec/component/exam/exam-scores/exam-scores.component.spec.ts
+++ b/src/test/javascript/spec/component/exam/exam-scores/exam-scores.component.spec.ts
@@ -1,5 +1,6 @@
-import { HttpResponse } from '@angular/common/http';
+import { HttpResponse, provideHttpClient } from '@angular/common/http';
import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { provideHttpClientTesting } from '@angular/common/http/testing';
import { ActivatedRoute, Router } from '@angular/router';
import { FaIconComponent } from '@fortawesome/angular-fontawesome';
import { TranslateService } from '@ngx-translate/core';
@@ -14,15 +15,14 @@ import {
ExerciseResult,
StudentResult,
} from 'app/exam/exam-scores/exam-score-dtos.model';
+import { MockComponent, MockDirective, MockModule, MockPipe, MockProvider } from 'ng-mocks';
+import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ExamScoresComponent, MedianType } from 'app/exam/exam-scores/exam-scores.component';
import { ExamManagementService } from 'app/exam/manage/exam-management.service';
-import { HelpIconComponent } from 'app/shared/components/help-icon.component';
-import { DeleteButtonDirective } from 'app/shared/delete-dialog/delete-button.directive';
import { ParticipantScoresService, ScoresDTO } from 'app/shared/participant-scores/participant-scores.service';
import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe';
import { SortService } from 'app/shared/service/sort.service';
import { cloneDeep } from 'lodash-es';
-import { MockComponent, MockDirective, MockPipe, MockProvider } from 'ng-mocks';
import { EMPTY, of } from 'rxjs';
import { GradingSystemService } from 'app/grading-system/grading-system.service';
import { GradingScale } from 'app/entities/grading-scale.model';
@@ -35,7 +35,6 @@ import { CourseManagementService } from 'app/course/manage/course-management.ser
import { MockRouter } from '../../../helpers/mocks/mock-router';
import { AccountService } from 'app/core/auth/account.service';
import { MockRouterLinkDirective } from '../../../helpers/mocks/directive/mock-router-link.directive';
-import { ParticipantScoresDistributionComponent } from 'app/shared/participant-scores/participant-scores-distribution/participant-scores-distribution.component';
import { LocaleConversionService } from 'app/shared/service/locale-conversion.service';
import { ArtemisNavigationUtilService } from 'app/utils/navigation.utils';
import { CsvDecimalSeparator, CsvExportOptions, CsvFieldSeparator, CsvQuoteStrings } from 'app/shared/export/export-modal.component';
@@ -55,9 +54,9 @@ import {
REGISTRATION_NUMBER_KEY,
USERNAME_KEY,
} from 'app/shared/export/export-constants';
-import { ExportButtonComponent } from 'app/shared/export/export-button.component';
import { PlagiarismVerdict } from 'app/exercises/shared/plagiarism/types/PlagiarismVerdict';
import { BonusStrategy } from 'app/entities/bonus.model';
+import { MockTranslateService } from '../../../helpers/mocks/service/mock-translate.service';
describe('ExamScoresComponent', () => {
let fixture: ComponentFixture;
@@ -276,30 +275,28 @@ describe('ExamScoresComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
+ imports: [MockModule(BrowserAnimationsModule)],
declarations: [
ExamScoresComponent,
MockPipe(ArtemisTranslatePipe),
MockComponent(FaIconComponent),
- MockComponent(HelpIconComponent),
- MockComponent(ExportButtonComponent),
MockDirective(TranslateDirective),
MockDirective(SortByDirective),
MockDirective(SortDirective),
- MockDirective(DeleteButtonDirective),
MockComponent(ExamScoresAverageScoresGraphComponent),
MockRouterLinkDirective,
- MockComponent(ParticipantScoresDistributionComponent),
],
providers: [
{ provide: ActivatedRoute, useValue: { params: of({ courseId: 1, examId: 1 }) } },
{ provide: Router, useClass: MockRouter },
+ { provide: TranslateService, useClass: MockTranslateService },
+ provideHttpClient(),
+ provideHttpClientTesting(),
MockProvider(AccountService),
MockProvider(ArtemisNavigationUtilService),
- MockProvider(TranslateService),
MockProvider(ExamManagementService),
MockProvider(SortService),
MockProvider(AlertService),
- MockProvider(ParticipantScoresService),
MockProvider(GradingSystemService, {
findGradingScaleForExam: () => {
return of(
@@ -328,18 +325,16 @@ describe('ExamScoresComponent', () => {
},
}),
],
- })
- .compileComponents()
- .then(() => {
- fixture = TestBed.createComponent(ExamScoresComponent);
- comp = fixture.componentInstance;
- examService = fixture.debugElement.injector.get(ExamManagementService);
- gradingSystemService = fixture.debugElement.injector.get(GradingSystemService);
- const participationScoreService = fixture.debugElement.injector.get(ParticipantScoresService);
- findExamScoresSpy = jest
- .spyOn(participationScoreService, 'findExamScores')
- .mockReturnValue(of(new HttpResponse({ body: [examScoreStudent1, examScoreStudent2, examScoreStudent3] })));
- });
+ }).compileComponents();
+
+ fixture = TestBed.createComponent(ExamScoresComponent);
+ comp = fixture.componentInstance;
+ examService = fixture.debugElement.injector.get(ExamManagementService);
+ gradingSystemService = fixture.debugElement.injector.get(GradingSystemService);
+ const participationScoreService = fixture.debugElement.injector.get(ParticipantScoresService);
+ findExamScoresSpy = jest
+ .spyOn(participationScoreService, 'findExamScores')
+ .mockReturnValue(of(new HttpResponse({ body: [examScoreStudent1, examScoreStudent2, examScoreStudent3] })));
});
afterEach(() => {