Skip to content

Commit 44a8f3f

Browse files
authored
[ENG-9897] Unit tests: add coverage for the missing components. (#799)
- Ticket: [ENG-9897] - Feature flag: n/a ## Purpose Increase coverage. ## Summary of Changes 1. Added new unit tests.
1 parent f7f40a5 commit 44a8f3f

File tree

54 files changed

+2767
-995
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+2767
-995
lines changed

jest.config.js

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ module.exports = {
5454
extensionsToTreatAsEsm: ['.ts'],
5555
coverageThreshold: {
5656
global: {
57-
branches: 28.0,
58-
functions: 32.0,
59-
lines: 60.28,
60-
statements: 60.77,
57+
branches: 31.0,
58+
functions: 35.0,
59+
lines: 64.0,
60+
statements: 64.0,
6161
},
6262
},
6363
watchPathIgnorePatterns: [
@@ -70,19 +70,9 @@ module.exports = {
7070
],
7171
testPathIgnorePatterns: [
7272
'<rootDir>/src/environments',
73-
'<rootDir>/src/app/app.config.ts',
7473
'<rootDir>/src/app/features/files/pages/file-detail',
7574
'<rootDir>/src/app/features/project/addons/',
76-
'<rootDir>/src/app/features/project/registrations',
77-
'<rootDir>/src/app/features/project/wiki',
78-
'<rootDir>/src/app/features/registry/components',
79-
'<rootDir>/src/app/features/registry/pages/registry-wiki/registry-wiki',
8075
'<rootDir>/src/app/features/settings/addons/',
8176
'<rootDir>/src/app/features/settings/tokens/store/',
82-
'<rootDir>/src/app/shared/components/file-menu/',
83-
'<rootDir>/src/app/shared/components/line-chart/',
84-
'<rootDir>/src/app/shared/components/pie-chart/',
85-
'<rootDir>/src/app/shared/components/reusable-filter/',
86-
'<rootDir>/src/app/shared/components/wiki/edit-section/',
8777
],
8878
};

setup-jest.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ Object.defineProperty(window, 'ResizeObserver', {
3838
value: ResizeObserver,
3939
});
4040

41+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
42+
(global as any).ace = {
43+
define: jest.fn(),
44+
require: jest.fn().mockReturnValue({
45+
snippetCompleter: {},
46+
}),
47+
};
48+
4149
jest.mock('@newrelic/browser-agent/loaders/browser-agent', () => ({
4250
BrowserAgent: jest.fn().mockImplementation(() => ({
4351
start: jest.fn(),

src/app/features/analytics/components/view-duplicates/view-duplicates.component.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
Signal,
2020
signal,
2121
} from '@angular/core';
22-
import { toSignal } from '@angular/core/rxjs-interop';
22+
import { takeUntilDestroyed, toSignal } from '@angular/core/rxjs-interop';
2323
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
2424

2525
import { UserSelectors } from '@core/store/user';
@@ -75,7 +75,6 @@ export class ViewDuplicatesComponent {
7575
isAuthenticated = select(UserSelectors.isAuthenticated);
7676

7777
readonly pageSize = 10;
78-
readonly UserPermissions = UserPermissions;
7978

8079
currentPage = signal<number>(1);
8180
firstIndex = computed(() => (this.currentPage() - 1) * this.pageSize);
@@ -180,7 +179,8 @@ export class ViewDuplicatesComponent {
180179
resourceType: this.resourceType(),
181180
},
182181
})
183-
.onClose.subscribe((result) => {
182+
.onClose.pipe(takeUntilDestroyed(this.destroyRef))
183+
.subscribe((result) => {
184184
if (result?.success) {
185185
this.actions.getDuplicates(currentResource.id, currentResource.type, this.currentPage(), this.pageSize);
186186
}
@@ -224,7 +224,8 @@ export class ViewDuplicatesComponent {
224224
pageSize: this.pageSize,
225225
},
226226
})
227-
.onClose.subscribe((result) => {
227+
.onClose.pipe(takeUntilDestroyed(this.destroyRef))
228+
.subscribe((result) => {
228229
if (result?.success) {
229230
const resource = this.currentResource();
230231
if (resource) {

src/app/features/collections/components/add-to-collection/add-to-collection.component.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,11 @@ import { CanDeactivateComponent } from '@shared/models/can-deactivate.interface'
3434
import { CollectionsSelectors, GetCollectionProvider } from '@shared/stores/collections';
3535
import { ProjectsSelectors } from '@shared/stores/projects/projects.selectors';
3636

37-
import {
38-
AddToCollectionConfirmationDialogComponent,
39-
CollectionMetadataStepComponent,
40-
ProjectContributorsStepComponent,
41-
ProjectMetadataStepComponent,
42-
SelectProjectStepComponent,
43-
} from './index';
37+
import { AddToCollectionConfirmationDialogComponent } from './add-to-collection-confirmation-dialog/add-to-collection-confirmation-dialog.component';
38+
import { CollectionMetadataStepComponent } from './collection-metadata-step/collection-metadata-step.component';
39+
import { ProjectContributorsStepComponent } from './project-contributors-step/project-contributors-step.component';
40+
import { ProjectMetadataStepComponent } from './project-metadata-step/project-metadata-step.component';
41+
import { SelectProjectStepComponent } from './select-project-step/select-project-step.component';
4442

4543
@Component({
4644
selector: 'osf-add-to-collection-form',
Lines changed: 112 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,145 @@
1-
import { TranslatePipe } from '@ngx-translate/core';
2-
import { MockComponents } from 'ng-mocks';
1+
import { MockComponents, MockProvider } from 'ng-mocks';
32

3+
import { signal } from '@angular/core';
44
import { ComponentFixture, TestBed } from '@angular/core/testing';
5-
import { FormsModule } from '@angular/forms';
5+
import { ActivatedRoute, Router } from '@angular/router';
66

7+
import { ENVIRONMENT } from '@core/provider/environment.provider';
78
import { CustomPaginatorComponent } from '@osf/shared/components/custom-paginator/custom-paginator.component';
89
import { LoadingSpinnerComponent } from '@osf/shared/components/loading-spinner/loading-spinner.component';
910
import { RegistrationCardComponent } from '@osf/shared/components/registration-card/registration-card.component';
1011
import { SubHeaderComponent } from '@osf/shared/components/sub-header/sub-header.component';
12+
import { CurrentResourceSelectors } from '@shared/stores/current-resource';
1113

1214
import { RegistrationsComponent } from './registrations.component';
15+
import { GetRegistrations, RegistrationsSelectors } from './store';
16+
17+
import { MOCK_REGISTRATION } from '@testing/mocks/registration.mock';
18+
import { OSFTestingModule } from '@testing/osf.testing.module';
19+
import { ActivatedRouteMockBuilder } from '@testing/providers/route-provider.mock';
20+
import { RouterMockBuilder } from '@testing/providers/router-provider.mock';
21+
import { provideMockStore } from '@testing/providers/store-provider.mock';
1322

1423
describe('RegistrationsComponent', () => {
1524
let component: RegistrationsComponent;
1625
let fixture: ComponentFixture<RegistrationsComponent>;
26+
let routerMock: ReturnType<RouterMockBuilder['build']>;
27+
let activatedRouteMock: ReturnType<ActivatedRouteMockBuilder['build']>;
28+
let storeDispatchSpy: jest.SpyInstance;
29+
30+
const mockProjectId = 'project-123';
31+
const mockRegistrations = [MOCK_REGISTRATION];
32+
const mockEnvironment = {
33+
defaultProvider: 'test-provider',
34+
};
1735

1836
beforeEach(async () => {
37+
routerMock = RouterMockBuilder.create().build();
38+
activatedRouteMock = ActivatedRouteMockBuilder.create().withParams({ id: mockProjectId }).build();
39+
40+
const mockStore = provideMockStore({
41+
signals: [
42+
{ selector: CurrentResourceSelectors.hasAdminAccess, value: signal(true) },
43+
{ selector: RegistrationsSelectors.getRegistrations, value: signal(mockRegistrations) },
44+
{ selector: RegistrationsSelectors.getRegistrationsTotalCount, value: signal(10) },
45+
{ selector: RegistrationsSelectors.isRegistrationsLoading, value: signal(false) },
46+
],
47+
});
48+
49+
storeDispatchSpy = jest.spyOn(mockStore.useValue, 'dispatch');
50+
1951
await TestBed.configureTestingModule({
2052
imports: [
2153
RegistrationsComponent,
54+
OSFTestingModule,
2255
...MockComponents(
2356
RegistrationCardComponent,
2457
SubHeaderComponent,
25-
FormsModule,
26-
TranslatePipe,
2758
LoadingSpinnerComponent,
2859
CustomPaginatorComponent
2960
),
3061
],
62+
providers: [
63+
MockProvider(Router, routerMock),
64+
MockProvider(ActivatedRoute, activatedRouteMock),
65+
MockProvider(ENVIRONMENT, mockEnvironment),
66+
mockStore,
67+
],
3168
}).compileComponents();
3269

3370
fixture = TestBed.createComponent(RegistrationsComponent);
3471
component = fixture.componentInstance;
35-
fixture.detectChanges();
3672
});
3773

38-
it('should create', () => {
39-
expect(component).toBeTruthy();
74+
it('should have default values', () => {
75+
expect(component.itemsPerPage).toBe(10);
76+
expect(component.first).toBe(0);
77+
});
78+
79+
it('should initialize projectId from route params', () => {
80+
expect(component.projectId()).toBe(mockProjectId);
81+
});
82+
83+
it('should dispatch getRegistrations action on ngOnInit', () => {
84+
component.ngOnInit();
85+
86+
expect(storeDispatchSpy).toHaveBeenCalledWith(
87+
expect.objectContaining({
88+
projectId: mockProjectId,
89+
page: 1,
90+
pageSize: 10,
91+
})
92+
);
93+
expect(storeDispatchSpy).toHaveBeenCalledWith(expect.any(GetRegistrations));
94+
});
95+
96+
it('should navigate to registries route when addRegistration is called', () => {
97+
const navigateSpy = jest.spyOn(routerMock, 'navigate');
98+
99+
component.addRegistration();
100+
101+
expect(navigateSpy).toHaveBeenCalledWith([`registries/${mockEnvironment.defaultProvider}/new`], {
102+
queryParams: { projectId: mockProjectId },
103+
});
104+
});
105+
106+
it('should dispatch getRegistrations and update first on page change', () => {
107+
const mockPaginatorState = {
108+
page: 2,
109+
first: 20,
110+
rows: 10,
111+
pageCount: 5,
112+
} as any;
113+
114+
component.onPageChange(mockPaginatorState);
115+
116+
expect(storeDispatchSpy).toHaveBeenCalledWith(
117+
expect.objectContaining({
118+
projectId: mockProjectId,
119+
page: 3,
120+
pageSize: 10,
121+
})
122+
);
123+
expect(component.first).toBe(20);
124+
});
125+
126+
it('should handle page change with page 0', () => {
127+
const mockPaginatorState = {
128+
page: 0,
129+
first: 0,
130+
rows: 10,
131+
pageCount: 5,
132+
} as any;
133+
134+
component.onPageChange(mockPaginatorState);
135+
136+
expect(storeDispatchSpy).toHaveBeenCalledWith(
137+
expect.objectContaining({
138+
projectId: mockProjectId,
139+
page: 1,
140+
pageSize: 10,
141+
})
142+
);
143+
expect(component.first).toBe(0);
40144
});
41145
});

0 commit comments

Comments
 (0)