-
Notifications
You must be signed in to change notification settings - Fork 303
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
414 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
126 changes: 126 additions & 0 deletions
126
...t/spec/component/competencies/competency-accordion/competency-accordion.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
import { CompetencyAccordionComponent } from 'src/main/webapp/app/course/competencies/competency-accordion/competency-accordion.component'; | ||
import { By } from '@angular/platform-browser'; | ||
import { Competency, CompetencyTaxonomy } from 'app/entities/competency.model'; | ||
import { Router } from '@angular/router'; | ||
import { Course } from 'app/entities/course.model'; | ||
import { ArtemisTestModule } from '../../../test.module'; | ||
import { CourseDashboardComponent } from 'app/overview/course-dashboard/course-dashboard.component'; | ||
import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; | ||
import { ArtemisTimeAgoPipe } from 'app/shared/pipes/artemis-time-ago.pipe'; | ||
import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; | ||
import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; | ||
import { ProgressBarComponent } from 'app/shared/progress-bar/progress-bar.component'; | ||
import { CourseExerciseRowComponent } from 'app/overview/course-exercises/course-exercise-row.component'; | ||
import { SidePanelComponent } from 'app/shared/side-panel/side-panel.component'; | ||
import { TranslateDirective } from 'app/shared/language/translate.directive'; | ||
import { FeatureToggleHideDirective } from 'app/shared/feature-toggle/feature-toggle-hide.directive'; | ||
import { SubmissionResultStatusComponent } from 'app/overview/submission-result-status.component'; | ||
import { MockComponent, MockDirective, MockModule, MockPipe } from 'ng-mocks'; | ||
import { HttpClientTestingModule } from '@angular/common/http/testing'; | ||
import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; | ||
import { CompetencyRingsComponent } from 'app/course/competencies/competency-rings/competency-rings.component'; | ||
|
||
describe('CompetencyAccordionComponent', () => { | ||
let component: CompetencyAccordionComponent; | ||
let fixture: ComponentFixture<CompetencyAccordionComponent>; | ||
let router: Router; | ||
|
||
beforeEach(async () => { | ||
await TestBed.configureTestingModule({ | ||
imports: [ArtemisTestModule, HttpClientTestingModule, MockModule(NgbTooltipModule)], | ||
declarations: [ | ||
CompetencyAccordionComponent, | ||
MockPipe(HtmlForMarkdownPipe), | ||
MockPipe(ArtemisTimeAgoPipe), | ||
MockPipe(ArtemisTranslatePipe), | ||
MockPipe(ArtemisDatePipe), | ||
MockComponent(ProgressBarComponent), | ||
MockComponent(CourseExerciseRowComponent), | ||
MockComponent(SidePanelComponent), | ||
MockDirective(TranslateDirective), | ||
MockDirective(FeatureToggleHideDirective), | ||
MockComponent(SubmissionResultStatusComponent), | ||
MockComponent(CourseDashboardComponent), | ||
MockComponent(CompetencyRingsComponent), | ||
], | ||
providers: [{ provide: Router, useValue: { navigate: jest.fn() } }], | ||
}) | ||
.compileComponents() | ||
.then(() => { | ||
fixture = TestBed.createComponent(CompetencyAccordionComponent); | ||
component = fixture.componentInstance; | ||
router = TestBed.inject(Router); | ||
component.index = 1; | ||
component.openedIndex = 0; | ||
}); | ||
}); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
|
||
it('should render competency title', () => { | ||
component.competency = { title: 'Test Competency' } as Competency; | ||
fixture.detectChanges(); | ||
const titleElement = fixture.debugElement.queryAll(By.css('.competency-accordion-header h3')); | ||
expect(titleElement[1].nativeElement.textContent).toContain('Test Competency'); | ||
}); | ||
|
||
it('should render progress bar', () => { | ||
component.competency = { exercises: [{ completed: true }, { completed: false }] } as Competency; | ||
fixture.detectChanges(); | ||
const progressBarElement = fixture.debugElement.query(By.css('jhi-progress-bar')); | ||
expect(progressBarElement).toBeTruthy(); | ||
}); | ||
|
||
it('should toggle open state when toggle is called', () => { | ||
component.open = false; | ||
component.toggle(); | ||
expect(component.open).toBeTrue(); | ||
component.toggle(); | ||
expect(component.open).toBeFalse(); | ||
}); | ||
|
||
it('should render competency icon', () => { | ||
component.competency = { taxonomy: CompetencyTaxonomy.CREATE } as Competency; | ||
fixture.detectChanges(); | ||
const iconElement = fixture.debugElement.query(By.css('fa-icon')); | ||
expect(iconElement).toBeTruthy(); | ||
}); | ||
|
||
it('should render competency exercises progress bar', () => { | ||
component.competency = { exercises: [{ completed: true }, { completed: false }] } as Competency; | ||
fixture.detectChanges(); | ||
const progressBarElement = fixture.debugElement.query(By.css('jhi-progress-bar')); | ||
expect(progressBarElement).toBeTruthy(); | ||
}); | ||
|
||
it('should render competency lecture units progress bar', () => { | ||
component.competency = { lectureUnits: [{ completed: true }, { completed: false }] } as Competency; | ||
fixture.detectChanges(); | ||
const progressBarElement = fixture.debugElement.query(By.css('jhi-progress-bar')); | ||
expect(progressBarElement).toBeTruthy(); | ||
}); | ||
|
||
it('should render competency rings', () => { | ||
component.competency = { userProgress: [{ progress: 50, confidence: 75 }] } as Competency; | ||
fixture.detectChanges(); | ||
const competencyRingsElement = fixture.debugElement.query(By.css('jhi-competency-rings')); | ||
expect(competencyRingsElement).toBeTruthy(); | ||
}); | ||
|
||
it('should emit accordionToggle event when toggle is called', () => { | ||
const toggleSpy = jest.spyOn(component.accordionToggle, 'emit'); | ||
component.toggle(); | ||
expect(toggleSpy).toHaveBeenCalledWith({ opened: true, index: component.index }); | ||
}); | ||
|
||
it('should navigate to competency detail page when navigateToCompetencyDetailPage is called', () => { | ||
const navigateSpy = jest.spyOn(router, 'navigate'); | ||
component.course = { id: 1 } as Course; | ||
component.competency = { id: 1 } as Competency; | ||
component.navigateToCompetencyDetailPage(new Event('click')); | ||
expect(navigateSpy).toHaveBeenCalledWith(['/courses', component.course.id, 'competencies', component.competency.id]); | ||
}); | ||
}); |
183 changes: 183 additions & 0 deletions
183
...st/javascript/spec/component/overview/course-dashboard/course-dashboard.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
import { CourseStorageService } from 'app/course/manage/course-storage.service'; | ||
import { CompetencyService } from 'app/course/competencies/competency.service'; | ||
import { ActivatedRoute, Router } from '@angular/router'; | ||
import { of } from 'rxjs'; | ||
import { Competency } from 'app/entities/competency.model'; | ||
import { By } from '@angular/platform-browser'; | ||
import { Exercise } from 'app/entities/exercise.model'; | ||
import { HttpResponse } from '@angular/common/http'; | ||
import { CourseDashboardComponent } from 'app/overview/course-dashboard/course-dashboard.component'; | ||
import { HtmlForMarkdownPipe } from 'app/shared/pipes/html-for-markdown.pipe'; | ||
import { ArtemisTimeAgoPipe } from 'app/shared/pipes/artemis-time-ago.pipe'; | ||
import { ArtemisTranslatePipe } from 'app/shared/pipes/artemis-translate.pipe'; | ||
import { ArtemisDatePipe } from 'app/shared/pipes/artemis-date.pipe'; | ||
import { CourseExerciseRowComponent } from 'app/overview/course-exercises/course-exercise-row.component'; | ||
import { SidePanelComponent } from 'app/shared/side-panel/side-panel.component'; | ||
import { TranslateDirective } from 'app/shared/language/translate.directive'; | ||
import { SubmissionResultStatusComponent } from 'app/overview/submission-result-status.component'; | ||
import { MockComponent, MockDirective, MockModule, MockPipe, MockProvider } from 'ng-mocks'; | ||
import { ArtemisTestModule } from '../../../test.module'; | ||
import { HttpClientTestingModule } from '@angular/common/http/testing'; | ||
import { NgbTooltipModule } from '@ng-bootstrap/ng-bootstrap'; | ||
import { Course } from 'app/entities/course.model'; | ||
import { CompetencyAccordionComponent } from 'app/course/competencies/competency-accordion/competency-accordion.component'; | ||
import { ProgressBarComponent } from 'app/shared/progress-bar/progress-bar.component'; | ||
import { FeatureToggleHideDirective } from 'app/shared/feature-toggle/feature-toggle-hide.directive'; | ||
import { CompetencyRingsComponent } from 'app/course/competencies/competency-rings/competency-rings.component'; | ||
|
||
describe('CourseDashboardComponent', () => { | ||
let component: CourseDashboardComponent; | ||
let fixture: ComponentFixture<CourseDashboardComponent>; | ||
let courseStorageService: CourseStorageService; | ||
let competencyService: CompetencyService; | ||
let getAllForCourseStudentDashboardSpy: jest.SpyInstance; | ||
let router: Router; | ||
const mockCourse = { id: 1 } as Course; | ||
const mockRouter = { | ||
navigate: jest.fn(), | ||
}; | ||
|
||
const mockCompetencies = generateMockCompetenciesWithExercises(5); | ||
|
||
beforeEach(async () => { | ||
await TestBed.configureTestingModule({ | ||
imports: [ArtemisTestModule, HttpClientTestingModule, MockModule(NgbTooltipModule)], | ||
declarations: [ | ||
CourseDashboardComponent, | ||
CompetencyAccordionComponent, | ||
MockPipe(HtmlForMarkdownPipe), | ||
MockPipe(ArtemisTimeAgoPipe), | ||
MockPipe(ArtemisTranslatePipe), | ||
MockPipe(ArtemisDatePipe), | ||
MockComponent(ProgressBarComponent), | ||
MockComponent(CourseExerciseRowComponent), | ||
MockComponent(SidePanelComponent), | ||
MockDirective(TranslateDirective), | ||
MockDirective(FeatureToggleHideDirective), | ||
MockComponent(SubmissionResultStatusComponent), | ||
MockComponent(CompetencyRingsComponent), | ||
], | ||
providers: [ | ||
MockProvider(CourseStorageService), | ||
MockProvider(CompetencyService), | ||
{ | ||
provide: ActivatedRoute, | ||
useValue: { | ||
parent: { | ||
parent: { | ||
params: of({ competencyId: '1', courseId: '1' }), | ||
}, | ||
}, | ||
}, | ||
}, | ||
{ provide: Router, useValue: mockRouter }, | ||
], | ||
}) | ||
.compileComponents() | ||
.then(() => { | ||
fixture = TestBed.createComponent(CourseDashboardComponent); | ||
component = fixture.componentInstance; | ||
courseStorageService = TestBed.inject(CourseStorageService); | ||
jest.spyOn(courseStorageService, 'subscribeToCourseUpdates').mockReturnValue(of(mockCourse)); | ||
competencyService = TestBed.inject(CompetencyService); | ||
const mockResponse: HttpResponse<Competency[]> = new HttpResponse({ body: mockCompetencies }); | ||
getAllForCourseStudentDashboardSpy = jest.spyOn(competencyService, 'getAllForCourseStudentDashboard').mockReturnValue(of(mockResponse)); | ||
router = TestBed.inject(Router); | ||
fixture.detectChanges(); | ||
}); | ||
}); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
|
||
it('should set courseId on initialization', () => { | ||
const params = { courseId: 1 }; | ||
component.ngOnInit(); | ||
expect(component.courseId).toEqual(params.courseId); | ||
}); | ||
|
||
it('should call setCourse on initialization', () => { | ||
const getCourseSpy = jest.spyOn(courseStorageService, 'getCourse').mockReturnValue(mockCourse); | ||
component.ngOnInit(); | ||
expect(getCourseSpy).toHaveBeenCalledWith(component.courseId); | ||
expect(component.course).toEqual(mockCourse); | ||
}); | ||
|
||
it('should load competencies on initialization', () => { | ||
component.ngOnInit(); | ||
expect(component.competencies).toEqual(mockCompetencies); | ||
expect(getAllForCourseStudentDashboardSpy).toHaveBeenCalledWith(component.courseId); | ||
}); | ||
|
||
it('should render competency accordions when competencies are loaded', () => { | ||
component.ngOnInit(); | ||
fixture.detectChanges(); | ||
const competencyAccordions = fixture.debugElement.queryAll(By.css('jhi-competency-accordion')); | ||
expect(competencyAccordions).toHaveLength(mockCompetencies.length); | ||
}); | ||
|
||
it('should navigate to learning paths when button is clicked and learning paths are enabled', () => { | ||
component.course = { learningPathsEnabled: true }; | ||
fixture.detectChanges(); | ||
const navigateSpy = jest.spyOn(router, 'navigate'); | ||
const button = fixture.debugElement.query(By.css('.btn')); | ||
button.triggerEventHandler('click', null); | ||
expect(navigateSpy).toHaveBeenCalledWith(['courses', component.courseId, 'learning-path']); | ||
}); | ||
|
||
it('should respond to accordionToggle event from CompetencyAccordionComponent', () => { | ||
component.ngOnInit(); | ||
fixture.detectChanges(); | ||
const competencyAccordions = fixture.debugElement.queryAll(By.css('jhi-competency-accordion')); | ||
const firstAccordionComponent = competencyAccordions[0].componentInstance as CompetencyAccordionComponent; | ||
const toggleSpy = jest.spyOn(firstAccordionComponent.accordionToggle, 'emit'); | ||
firstAccordionComponent.toggle(); | ||
expect(toggleSpy).toHaveBeenCalledWith({ opened: true, index: firstAccordionComponent.index }); | ||
expect(component.openedAccordionIndex).toEqual(firstAccordionComponent.index); | ||
}); | ||
|
||
it('should only allow one accordion to be open at a time', () => { | ||
component.ngOnInit(); | ||
fixture.detectChanges(); | ||
const competencyAccordions = fixture.debugElement.queryAll(By.css('jhi-competency-accordion')); | ||
const firstAccordionComponent = competencyAccordions[0].componentInstance as CompetencyAccordionComponent; | ||
const secondAccordionComponent = competencyAccordions[1].componentInstance as CompetencyAccordionComponent; | ||
|
||
firstAccordionComponent.toggle(); | ||
fixture.detectChanges(); | ||
expect(firstAccordionComponent.open).toBeTrue(); | ||
expect(secondAccordionComponent.open).toBeFalse(); | ||
|
||
secondAccordionComponent.toggle(); | ||
fixture.detectChanges(); | ||
expect(firstAccordionComponent.open).toBeFalse(); | ||
expect(secondAccordionComponent.open).toBeTrue(); | ||
}); | ||
}); | ||
|
||
function generateMockCompetenciesWithExercises(count: number): Competency[] { | ||
const competencies: Competency[] = []; | ||
for (let i = 1; i <= count; i++) { | ||
const competency: Competency = { | ||
id: i, | ||
title: `Competency ${i}`, | ||
description: `Description for Competency ${i}`, | ||
exercises: [ | ||
{ | ||
id: i, | ||
title: `Exercise ${i}`, | ||
} as Exercise, | ||
{ | ||
id: i + 1, | ||
title: `Exercise ${i + 1}`, | ||
// Add other properties as needed | ||
} as Exercise, | ||
], | ||
// Add other properties as needed | ||
}; | ||
competencies.push(competency); | ||
} | ||
return competencies; | ||
} |
Oops, something went wrong.