Skip to content

Commit 7b78446

Browse files
committed
Set up Karma for unit testing
1 parent 7f35473 commit 7b78446

File tree

16 files changed

+156
-71
lines changed

16 files changed

+156
-71
lines changed

angular.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@
8888
"styles": [
8989
"src/styles.css"
9090
],
91-
"scripts": []
91+
"scripts": [],
92+
"karmaConfig": "karma.conf.js"
9293
}
9394
},
9495
"deploy": {

karma.conf.js

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Karma configuration file, see link for more information
2+
// https://karma-runner.github.io/1.0/config/configuration-file.html
3+
4+
module.exports = function (config) {
5+
config.set({
6+
basePath: '',
7+
frameworks: ['jasmine', '@angular-devkit/build-angular'],
8+
plugins: [
9+
require('karma-jasmine'),
10+
require('karma-chrome-launcher'),
11+
require('karma-jasmine-html-reporter'),
12+
require('karma-coverage'),
13+
require('@angular-devkit/build-angular/plugins/karma')
14+
],
15+
client: {
16+
jasmine: {
17+
// you can add configuration options for Jasmine here
18+
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
19+
// for example, you can disable the random execution with `random: false`
20+
// or set a specific seed with `seed: 4321`
21+
},
22+
clearContext: false // leave Jasmine Spec Runner output visible in browser
23+
},
24+
jasmineHtmlReporter: {
25+
suppressAll: true // removes the duplicated traces
26+
},
27+
coverageReporter: {
28+
dir: require('path').join(__dirname, './coverage/dockerfiles-website'),
29+
subdir: '.',
30+
reporters: [
31+
{ type: 'html' },
32+
{ type: 'text-summary' }
33+
]
34+
},
35+
reporters: ['progress', 'kjhtml'],
36+
browsers: ['Chrome'],
37+
restartOnFileChange: true
38+
});
39+
};

src/app/app.component.spec.ts

+4-13
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
import { TestBed } from '@angular/core/testing';
22
import { AppComponent } from './app.component';
3+
import { provideRouter } from '@angular/router';
34

45
describe('AppComponent', () => {
56
beforeEach(async () => {
67
await TestBed.configureTestingModule({
78
imports: [AppComponent],
9+
providers: [
10+
provideRouter([]),
11+
],
812
}).compileComponents();
913
});
1014

@@ -13,17 +17,4 @@ describe('AppComponent', () => {
1317
const app = fixture.componentInstance;
1418
expect(app).toBeTruthy();
1519
});
16-
17-
it(`should have the 'dockerfiles-website' title`, () => {
18-
const fixture = TestBed.createComponent(AppComponent);
19-
const app = fixture.componentInstance;
20-
expect(app.title).toEqual('dockerfiles-website');
21-
});
22-
23-
it('should render title', () => {
24-
const fixture = TestBed.createComponent(AppComponent);
25-
fixture.detectChanges();
26-
const compiled = fixture.nativeElement as HTMLElement;
27-
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, dockerfiles-website');
28-
});
2920
});

src/app/app.component.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { RouterOutlet } from '@angular/router';
33
import { HeaderComponent } from './core/layout/header/header.component';
44
import { FooterComponent } from './core/layout/footer/footer.component';
55
import { LandingComponent } from './features/landing/pages/landing/landing.component';
6-
import { debounceTime, fromEvent, map } from 'rxjs';
6+
import { fromEvent, map } from 'rxjs';
77

88
@Component({
99
selector: 'app-root',

src/app/core/layout/header/header.component.spec.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { provideRouter } from '@angular/router';
23

34
import { HeaderComponent } from './header.component';
45

@@ -8,7 +9,10 @@ describe('HeaderComponent', () => {
89

910
beforeEach(async () => {
1011
await TestBed.configureTestingModule({
11-
imports: [HeaderComponent]
12+
imports: [HeaderComponent],
13+
providers: [
14+
provideRouter([])
15+
]
1216
})
1317
.compileComponents();
1418

src/app/core/layout/header/header.component.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { ChangeDetectionStrategy, Component, ElementRef, Renderer2, signal } from '@angular/core';
22
import { NavigationEnd, RouterLink, Router } from '@angular/router';
3-
import { SearchGuidedComponent } from "../../../features/containers/pages/search-guided/search-guided.component";
43
import { ThemeService } from '../../../services/theme.service';
54

65
@Component({
76
selector: 'app-header',
87
standalone: true,
98
templateUrl: './header.component.html',
109
styleUrl: './header.component.css',
11-
imports: [RouterLink, SearchGuidedComponent],
10+
imports: [RouterLink],
1211
host: {'[class.dark]':'isDarkTheme'},
1312
changeDetection: ChangeDetectionStrategy.OnPush,
1413
})

src/app/features/containers/pages/container/container.component.spec.ts

+16-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { provideRouter } from '@angular/router';
3+
import { RouterTestingHarness } from '@angular/router/testing';
4+
import { provideHttpClient } from '@angular/common/http';
5+
import { provideHttpClientTesting } from '@angular/common/http/testing';
26

37
import { ContainerComponent } from './container.component';
48

@@ -8,13 +12,20 @@ describe('ContainerComponent', () => {
812

913
beforeEach(async () => {
1014
await TestBed.configureTestingModule({
11-
imports: [ContainerComponent]
15+
imports: [ContainerComponent],
16+
providers: [
17+
provideHttpClient(),
18+
provideHttpClientTesting(),
19+
provideRouter([
20+
{ path: 'container/:name', component: ContainerComponent }
21+
])
22+
]
1223
})
1324
.compileComponents();
14-
15-
fixture = TestBed.createComponent(ContainerComponent);
16-
component = fixture.componentInstance;
17-
fixture.detectChanges();
25+
26+
const harness = await RouterTestingHarness.create();
27+
component = await harness.navigateByUrl('/container/bedtools', ContainerComponent);
28+
harness.detectChanges();
1829
});
1930

2031
it('should create', () => {

src/app/features/containers/pages/search-guided/search-guided.component.spec.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { provideRouter } from '@angular/router';
3+
import { provideHttpClient } from '@angular/common/http';
4+
import { provideHttpClientTesting } from '@angular/common/http/testing';
5+
import { provideNoopAnimations } from '@angular/platform-browser/animations';
26

37
import { SearchGuidedComponent } from './search-guided.component';
48

@@ -8,7 +12,13 @@ describe('SearchGuidedComponent', () => {
812

913
beforeEach(async () => {
1014
await TestBed.configureTestingModule({
11-
imports: [SearchGuidedComponent]
15+
imports: [SearchGuidedComponent],
16+
providers: [
17+
provideHttpClient(),
18+
provideHttpClientTesting(),
19+
provideNoopAnimations(),
20+
provideRouter([]),
21+
],
1222
})
1323
.compileComponents();
1424

src/app/features/landing/components/contributor-card/contributor-card.component.spec.ts

+14
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,32 @@
11
import { ComponentFixture, TestBed } from '@angular/core/testing';
22

33
import { ContributorCardComponent } from './contributor-card.component';
4+
import { Contributor } from '../../models/contributor.model';
5+
import * as Organization from '../../../../models/organization';
46

57
describe('ContributorCardComponent', () => {
68
let component: ContributorCardComponent;
79
let fixture: ComponentFixture<ContributorCardComponent>;
810

11+
const contributor: Contributor = {
12+
name: 'John Doe',
13+
description: 'A contributor',
14+
photo: 'photo.jpg',
15+
contactInfo: {
16+
17+
orcid: '0000-0000-0000-0000',
18+
},
19+
organizations: [Organization.SING],
20+
};
21+
922
beforeEach(async () => {
1023
await TestBed.configureTestingModule({
1124
imports: [ContributorCardComponent]
1225
})
1326
.compileComponents();
1427

1528
fixture = TestBed.createComponent(ContributorCardComponent);
29+
fixture.componentRef.setInput('contributor', contributor);
1630
component = fixture.componentInstance;
1731
fixture.detectChanges();
1832
});

src/app/features/landing/pages/landing/landing.component.spec.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,20 @@
11
import { ComponentFixture, TestBed } from '@angular/core/testing';
22

33
import { LandingComponent } from './landing.component';
4+
import { provideRouter } from '@angular/router';
45

56
describe('LandingComponent', () => {
67
let component: LandingComponent;
78
let fixture: ComponentFixture<LandingComponent>;
89

910
beforeEach(async () => {
1011
await TestBed.configureTestingModule({
11-
imports: [LandingComponent]
12+
imports: [LandingComponent],
13+
providers: [
14+
provideRouter([
15+
{ path: 'search', component: LandingComponent }
16+
]),
17+
],
1218
})
1319
.compileComponents();
1420

src/app/features/tutorials/pages/tutorial/tutorial.component.spec.ts

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { provideRouter } from '@angular/router';
3+
import { RouterTestingHarness } from '@angular/router/testing';
4+
import { provideHttpClient } from '@angular/common/http';
5+
import { provideHttpClientTesting } from '@angular/common/http/testing';
6+
import { provideMarkdown } from 'ngx-markdown';
27

38
import { TutorialComponent } from './tutorial.component';
49

@@ -8,13 +13,21 @@ describe('TutorialComponent', () => {
813

914
beforeEach(async () => {
1015
await TestBed.configureTestingModule({
11-
imports: [TutorialComponent]
16+
imports: [TutorialComponent],
17+
providers: [
18+
provideHttpClient(),
19+
provideHttpClientTesting(),
20+
provideMarkdown(),
21+
provideRouter([
22+
{ path: 'tutorials/:name', component: TutorialComponent }
23+
])
24+
]
1225
})
1326
.compileComponents();
1427

15-
fixture = TestBed.createComponent(TutorialComponent);
16-
component = fixture.componentInstance;
17-
fixture.detectChanges();
28+
const harness = await RouterTestingHarness.create();
29+
component = await harness.navigateByUrl('/tutorials/docker-in-docker', TutorialComponent);
30+
harness.detectChanges();
1831
});
1932

2033
it('should create', () => {

src/app/features/tutorials/pages/tutorials-landing/tutorials-landing.component.spec.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { provideHttpClient } from '@angular/common/http';
3+
import { provideHttpClientTesting } from '@angular/common/http/testing';
24

35
import { TutorialsLandingComponent } from './tutorials-landing.component';
46

@@ -8,10 +10,14 @@ describe('TutorialsLandingComponent', () => {
810

911
beforeEach(async () => {
1012
await TestBed.configureTestingModule({
11-
imports: [TutorialsLandingComponent]
13+
imports: [TutorialsLandingComponent],
14+
providers: [
15+
provideHttpClient(),
16+
provideHttpClientTesting(),
17+
],
1218
})
1319
.compileComponents();
14-
20+
1521
fixture = TestBed.createComponent(TutorialsLandingComponent);
1622
component = fixture.componentInstance;
1723
fixture.detectChanges();

src/app/search-list/search-list.component.spec.ts

-23
This file was deleted.

src/app/shared/components/reason-card/reason-card.component.spec.ts

+9
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,22 @@ describe('ReasonCardComponent', () => {
66
let component: ReasonCardComponent;
77
let fixture: ComponentFixture<ReasonCardComponent>;
88

9+
const reason = {
10+
icon: 'labs',
11+
title: 'title',
12+
description: 'description'
13+
};
14+
915
beforeEach(async () => {
1016
await TestBed.configureTestingModule({
1117
imports: [ReasonCardComponent]
1218
})
1319
.compileComponents();
1420

1521
fixture = TestBed.createComponent(ReasonCardComponent);
22+
fixture.componentRef.setInput('icon', reason.icon);
23+
fixture.componentRef.setInput('title', reason.title);
24+
fixture.componentRef.setInput('description', reason.description);
1625
component = fixture.componentInstance;
1726
fixture.detectChanges();
1827
});
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,44 @@
11
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { By } from '@angular/platform-browser';
23

34
import { TabsComponent } from './tabs.component';
45

56
describe('TabsComponent', () => {
67
let component: TabsComponent;
78
let fixture: ComponentFixture<TabsComponent>;
89

10+
const tabs = [{ label: 'Tab 1', active: true }, { label: 'Tab 2' }];
11+
912
beforeEach(async () => {
1013
await TestBed.configureTestingModule({
11-
imports: [TabsComponent]
14+
imports: [TabsComponent],
1215
})
1316
.compileComponents();
1417

1518
fixture = TestBed.createComponent(TabsComponent);
19+
fixture.componentRef.setInput('tabs', tabs);
1620
component = fixture.componentInstance;
1721
fixture.detectChanges();
1822
});
1923

2024
it('should create', () => {
2125
expect(component).toBeTruthy();
2226
});
27+
28+
it('should display the tabs', () => {
29+
const tabsRendered = fixture.debugElement.queryAll(By.css('.tab'));
30+
expect(tabsRendered.length).toBe(tabs.length);
31+
});
32+
33+
it('should display the active tab', () => {
34+
const activeTab = fixture.debugElement.query(By.css('input:checked'));
35+
expect(activeTab.nativeElement.id).toContain(tabs[0].label);
36+
});
37+
38+
it('should emit the selected tab on onSelectTab', () => {
39+
spyOn(component.activeTab, 'emit');
40+
const expectedTab = 'Test Tab';
41+
component.onSelectTab(expectedTab);
42+
expect(component.activeTab.emit).toHaveBeenCalledWith(expectedTab);
43+
});
2344
});

0 commit comments

Comments
 (0)