Skip to content

Commit d07e4f3

Browse files
authored
Test/395 institutions components (#358)
* test(institutions): tested institutions, institutions-list, institutions-search components * fix(tests): fixed tests
1 parent ede02f8 commit d07e4f3

File tree

7 files changed

+177
-72
lines changed

7 files changed

+177
-72
lines changed

src/app/features/home/pages/dashboard/dashboard.component.spec.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { MockComponents, MockProvider } from 'ng-mocks';
22

3+
import { ConfirmationService } from 'primeng/api';
34
import { TablePageEvent } from 'primeng/table';
45

56
import { of } from 'rxjs';
@@ -41,6 +42,7 @@ describe('DashboardComponent', () => {
4142
{ selector: MyResourcesSelectors.getProjectsLoading, value: false },
4243
],
4344
}),
45+
MockProvider(ConfirmationService, { confirm: jest.fn() }),
4446
MockProvider(Router, routerMock),
4547
MockProvider(IS_MEDIUM, of(false)),
4648
MockProvider(ActivatedRoute, ActivatedRouteMock.withQueryParams({}).build()),

src/app/features/institutions/institutions.component.spec.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
import { By } from '@angular/platform-browser';
23

34
import { InstitutionsComponent } from './institutions.component';
45

@@ -19,4 +20,9 @@ describe('InstitutionsComponent', () => {
1920
it('should create', () => {
2021
expect(component).toBeTruthy();
2122
});
23+
24+
it('should render router outlet', () => {
25+
const routerOutlet = fixture.debugElement.query(By.css('router-outlet'));
26+
expect(routerOutlet).toBeTruthy();
27+
});
2228
});
Lines changed: 97 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,47 @@
1-
import { provideStore } from '@ngxs/store';
1+
import { MockProvider } from 'ng-mocks';
22

3-
import { TranslatePipe } from '@ngx-translate/core';
4-
import { MockComponents, MockPipe } from 'ng-mocks';
3+
import { PaginatorState } from 'primeng/paginator';
54

6-
import { of } from 'rxjs';
7-
8-
import { provideHttpClient } from '@angular/common/http';
9-
import { provideHttpClientTesting } from '@angular/common/http/testing';
105
import { ComponentFixture, TestBed } from '@angular/core/testing';
11-
import { ActivatedRoute } from '@angular/router';
6+
import { ActivatedRoute, Router } from '@angular/router';
127

13-
import {
14-
CustomPaginatorComponent,
15-
LoadingSpinnerComponent,
16-
SearchInputComponent,
17-
SubHeaderComponent,
18-
} from '@shared/components';
19-
import { InstitutionsState } from '@shared/stores/institutions';
8+
import { InstitutionsSelectors } from '@osf/shared/stores/institutions';
9+
import { MOCK_INSTITUTION } from '@shared/mocks/institution.mock';
2010

2111
import { InstitutionsListComponent } from './institutions-list.component';
2212

23-
describe.skip('InstitutionsListComponent', () => {
13+
import { OSFTestingModule } from '@testing/osf.testing.module';
14+
import { ActivatedRouteMockBuilder } from '@testing/providers/route-provider.mock';
15+
import { RouterMockBuilder } from '@testing/providers/router-provider.mock';
16+
import { provideMockStore } from '@testing/providers/store-provider.mock';
17+
18+
describe('InstitutionsListComponent', () => {
2419
let component: InstitutionsListComponent;
2520
let fixture: ComponentFixture<InstitutionsListComponent>;
21+
let routerMock: ReturnType<RouterMockBuilder['build']>;
22+
let activatedRouteMock: ReturnType<ActivatedRouteMockBuilder['build']>;
23+
24+
const mockInstitutions = [MOCK_INSTITUTION];
25+
const mockTotalCount = 2;
2626

2727
beforeEach(async () => {
28+
routerMock = RouterMockBuilder.create().build();
29+
activatedRouteMock = ActivatedRouteMockBuilder.create()
30+
.withQueryParams({ page: '1', size: '10', search: '' })
31+
.build();
32+
2833
await TestBed.configureTestingModule({
29-
imports: [
30-
InstitutionsListComponent,
31-
...MockComponents(SubHeaderComponent, SearchInputComponent, CustomPaginatorComponent, LoadingSpinnerComponent),
32-
MockPipe(TranslatePipe),
33-
],
34+
imports: [InstitutionsListComponent, OSFTestingModule],
3435
providers: [
35-
{
36-
provide: ActivatedRoute,
37-
useValue: {
38-
snapshot: { paramMap: { get: () => '1' } },
39-
queryParams: of({}),
40-
},
41-
},
42-
provideStore([InstitutionsState]),
43-
provideHttpClient(),
44-
provideHttpClientTesting(),
36+
provideMockStore({
37+
signals: [
38+
{ selector: InstitutionsSelectors.getInstitutions, value: mockInstitutions },
39+
{ selector: InstitutionsSelectors.getInstitutionsTotalCount, value: mockTotalCount },
40+
{ selector: InstitutionsSelectors.isInstitutionsLoading, value: false },
41+
],
42+
}),
43+
MockProvider(Router, routerMock),
44+
MockProvider(ActivatedRoute, activatedRouteMock),
4545
],
4646
}).compileComponents();
4747

@@ -53,4 +53,70 @@ describe.skip('InstitutionsListComponent', () => {
5353
it('should create', () => {
5454
expect(component).toBeTruthy();
5555
});
56+
57+
it('should update currentPage, first, and call updateQueryParams when page is provided', () => {
58+
const paginatorEvent: PaginatorState = {
59+
page: 1,
60+
first: 20,
61+
rows: 10,
62+
pageCount: 5,
63+
};
64+
65+
component.onPageChange(paginatorEvent);
66+
67+
expect(component.currentPage()).toBe(2);
68+
expect(component.first()).toBe(20);
69+
expect(routerMock.navigate).toHaveBeenCalledWith([], {
70+
relativeTo: expect.any(Object),
71+
queryParams: {
72+
page: '2',
73+
size: '10',
74+
},
75+
queryParamsHandling: 'merge',
76+
});
77+
});
78+
79+
it('should set currentPage to 1 when page is not provided', () => {
80+
const paginatorEvent: PaginatorState = {
81+
page: undefined,
82+
first: 0,
83+
rows: 20,
84+
pageCount: 3,
85+
};
86+
87+
component.onPageChange(paginatorEvent);
88+
89+
expect(component.currentPage()).toBe(1);
90+
expect(component.first()).toBe(0);
91+
expect(routerMock.navigate).toHaveBeenCalledWith([], {
92+
relativeTo: expect.any(Object),
93+
queryParams: {
94+
page: '1',
95+
size: '20',
96+
},
97+
queryParamsHandling: 'merge',
98+
});
99+
});
100+
101+
it('should handle first being undefined', () => {
102+
const paginatorEvent: PaginatorState = {
103+
page: 2,
104+
first: undefined,
105+
rows: 15,
106+
pageCount: 4,
107+
};
108+
109+
component.onPageChange(paginatorEvent);
110+
111+
expect(component.currentPage()).toBe(2);
112+
expect(component.first()).toBe(0);
113+
expect(routerMock.navigate).toHaveBeenCalledWith([], {
114+
relativeTo: expect.any(Object),
115+
queryParams: {
116+
page: '2',
117+
size: '15',
118+
},
119+
queryParamsHandling: 'merge',
120+
});
121+
});
56122
});
Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,80 @@
1-
import { TranslatePipe } from '@ngx-translate/core';
2-
import { MockComponents, MockPipes } from 'ng-mocks';
1+
import { Store } from '@ngxs/store';
32

4-
import { SafeHtmlPipe } from 'primeng/menu';
3+
import { MockComponents, MockProvider } from 'ng-mocks';
4+
5+
import { of } from 'rxjs';
56

67
import { ComponentFixture, TestBed } from '@angular/core/testing';
8+
import { ActivatedRoute } from '@angular/router';
79

8-
import {
9-
FilterChipsComponent,
10-
ReusableFilterComponent,
11-
SearchHelpTutorialComponent,
12-
SearchInputComponent,
13-
SearchResultsContainerComponent,
14-
} from '@shared/components';
10+
import { SetDefaultFilterValue } from '@osf/shared/stores/global-search';
11+
import { FetchInstitutionById, InstitutionsSearchSelectors } from '@osf/shared/stores/institutions-search';
12+
import { GlobalSearchComponent, LoadingSpinnerComponent } from '@shared/components';
13+
import { MOCK_INSTITUTION } from '@shared/mocks';
1514

1615
import { InstitutionsSearchComponent } from './institutions-search.component';
1716

18-
describe.skip('InstitutionsSearchComponent', () => {
17+
import { OSFTestingModule } from '@testing/osf.testing.module';
18+
import { ActivatedRouteMockBuilder } from '@testing/providers/route-provider.mock';
19+
import { provideMockStore } from '@testing/providers/store-provider.mock';
20+
21+
describe('InstitutionsSearchComponent', () => {
1922
let component: InstitutionsSearchComponent;
2023
let fixture: ComponentFixture<InstitutionsSearchComponent>;
24+
let activatedRouteMock: ReturnType<ActivatedRouteMockBuilder['build']>;
25+
let store: jest.Mocked<Store>;
2126

2227
beforeEach(async () => {
28+
activatedRouteMock = ActivatedRouteMockBuilder.create().build();
29+
2330
await TestBed.configureTestingModule({
2431
imports: [
2532
InstitutionsSearchComponent,
26-
...MockComponents(
27-
ReusableFilterComponent,
28-
SearchResultsContainerComponent,
29-
FilterChipsComponent,
30-
SearchHelpTutorialComponent,
31-
SearchInputComponent
32-
),
33-
MockPipes(TranslatePipe, SafeHtmlPipe),
33+
...MockComponents(LoadingSpinnerComponent, GlobalSearchComponent),
34+
OSFTestingModule,
35+
],
36+
providers: [
37+
MockProvider(ActivatedRoute, activatedRouteMock),
38+
provideMockStore({
39+
signals: [
40+
{ selector: InstitutionsSearchSelectors.getInstitution, value: MOCK_INSTITUTION },
41+
{ selector: InstitutionsSearchSelectors.getInstitutionLoading, value: false },
42+
],
43+
}),
3444
],
35-
providers: [],
3645
}).compileComponents();
3746

3847
fixture = TestBed.createComponent(InstitutionsSearchComponent);
3948
component = fixture.componentInstance;
49+
50+
store = TestBed.inject(Store) as jest.Mocked<Store>;
51+
store.dispatch = jest.fn().mockReturnValue(of(undefined));
52+
4053
fixture.detectChanges();
4154
});
4255

4356
it('should create', () => {
4457
expect(component).toBeTruthy();
4558
});
59+
60+
it('should fetch institution and set default filter value on ngOnInit when institution-id is provided', () => {
61+
activatedRouteMock.snapshot!.params = { 'institution-id': MOCK_INSTITUTION.id };
62+
63+
store.dispatch.mockReturnValue(of(undefined));
64+
65+
component.ngOnInit();
66+
67+
expect(store.dispatch).toHaveBeenCalledWith(new FetchInstitutionById(MOCK_INSTITUTION.id));
68+
expect(store.dispatch).toHaveBeenCalledWith(
69+
new SetDefaultFilterValue('affiliation', MOCK_INSTITUTION.iris.join(','))
70+
);
71+
});
72+
73+
it('should not fetch institution on ngOnInit when institution-id is not provided', () => {
74+
activatedRouteMock.snapshot!.params = {};
75+
76+
component.ngOnInit();
77+
78+
expect(store.dispatch).not.toHaveBeenCalled();
79+
});
4680
});

src/app/features/my-projects/components/create-project-dialog/create-project-dialog.component.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,12 @@ describe('CreateProjectDialogComponent', () => {
7979
fillValidForm('Title', 'Desc', 'Tpl', 'Storage', ['a1']);
8080

8181
(MOCK_STORE.dispatch as jest.Mock).mockReturnValue(of(undefined));
82+
(MOCK_STORE.selectSnapshot as jest.Mock).mockReturnValue([{ id: 'new-project-id' }]);
8283

8384
component.submitForm();
8485

8586
expect(MOCK_STORE.dispatch).toHaveBeenCalledWith(new CreateProject('Title', 'Desc', 'Tpl', 'Storage', ['a1']));
8687
expect(MOCK_STORE.dispatch).toHaveBeenCalledWith(new GetMyProjects(1, MY_PROJECTS_TABLE_PARAMS.rows, {}));
87-
expect((dialogRef as any).close).toHaveBeenCalled();
88+
expect((dialogRef as any).close).toHaveBeenCalledWith({ project: { id: 'new-project-id' } });
8889
});
8990
});

0 commit comments

Comments
 (0)