Skip to content

Commit 5bb1c44

Browse files
authored
[ENG-10255] Part 1: Added unit tests for pages components in registries (#879)
- Ticket: [ENG-10255] - Feature flag: n/a ## Summary of Changes 1. Added unit tests for pages components in registries
1 parent 571ea01 commit 5bb1c44

20 files changed

Lines changed: 690 additions & 493 deletions

src/app/features/registries/constants/registrations-tabs.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { TabOption } from '@osf/shared/models/tab-option.model';
1+
import { CustomOption } from '@osf/shared/models/select-option.model';
22

33
import { RegistrationTab } from '../enums';
44

5-
export const REGISTRATIONS_TABS: TabOption[] = [
5+
export const REGISTRATIONS_TABS: CustomOption<string>[] = [
66
{
77
label: 'common.labels.drafts',
88
value: RegistrationTab.Drafts,
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
export enum RegistrationTab {
2-
Drafts,
3-
Submitted,
2+
Drafts = 'drafts',
3+
Submitted = 'submitted',
44
}
Lines changed: 54 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -1,142 +1,107 @@
11
import { Store } from '@ngxs/store';
22

3-
import { MockComponent, MockProvider } from 'ng-mocks';
4-
5-
import { of } from 'rxjs';
3+
import { MockComponent } from 'ng-mocks';
64

75
import { ComponentFixture, TestBed } from '@angular/core/testing';
8-
import { ActivatedRoute, Router } from '@angular/router';
96

10-
import { DraftRegistrationAttributesJsonApi } from '@osf/shared/models/registration/registration-json-api.model';
7+
import { RegistriesSelectors, UpdateDraft } from '@osf/features/registries/store';
8+
import { DraftRegistrationModel } from '@osf/shared/models/registration/draft-registration.model';
119

1210
import { CustomStepComponent } from '../../components/custom-step/custom-step.component';
13-
import { RegistriesSelectors, UpdateDraft } from '../../store';
1411

1512
import { DraftRegistrationCustomStepComponent } from './draft-registration-custom-step.component';
1613

17-
import { OSFTestingModule } from '@testing/osf.testing.module';
18-
import { ActivatedRouteMockBuilder } from '@testing/providers/route-provider.mock';
19-
import { RouterMockBuilder } from '@testing/providers/router-provider.mock';
14+
import { MOCK_REGISTRIES_PAGE } from '@testing/mocks/registries.mock';
15+
import { provideOSFCore } from '@testing/osf.testing.provider';
16+
import { ActivatedRouteMockBuilder, provideActivatedRouteMock } from '@testing/providers/route-provider.mock';
17+
import { provideRouterMock, RouterMockBuilder, RouterMockType } from '@testing/providers/router-provider.mock';
2018
import { provideMockStore } from '@testing/providers/store-provider.mock';
2119

20+
const MOCK_DRAFT: Partial<DraftRegistrationModel> = {
21+
id: 'draft-1',
22+
providerId: 'prov-1',
23+
branchedFrom: { id: 'node-1', filesLink: '/files' },
24+
};
25+
const MOCK_STEPS_DATA: Record<string, string> = { 'question-1': 'answer-1' };
26+
2227
describe('DraftRegistrationCustomStepComponent', () => {
2328
let component: DraftRegistrationCustomStepComponent;
2429
let fixture: ComponentFixture<DraftRegistrationCustomStepComponent>;
2530
let store: Store;
26-
let mockRouter: ReturnType<RouterMockBuilder['build']>;
27-
let mockActivatedRoute: ReturnType<ActivatedRouteMockBuilder['build']>;
28-
29-
const mockStepsData = { stepKey: { field: 'value' } };
30-
const mockDraftRegistration = {
31-
id: 'draft-1',
32-
providerId: 'prov-1',
33-
branchedFrom: { id: 'proj-1', filesLink: '/project/proj-1/files/' },
34-
};
35-
36-
beforeEach(async () => {
37-
mockRouter = RouterMockBuilder.create().build();
38-
mockActivatedRoute = ActivatedRouteMockBuilder.create().withParams({ id: 'draft-1' }).build();
39-
40-
await TestBed.configureTestingModule({
41-
imports: [DraftRegistrationCustomStepComponent, OSFTestingModule, MockComponent(CustomStepComponent)],
31+
let mockRouter: RouterMockType;
32+
33+
function setup(
34+
draft: Partial<DraftRegistrationModel> | null = MOCK_DRAFT,
35+
stepsData: Record<string, string> = MOCK_STEPS_DATA
36+
) {
37+
const mockRoute = ActivatedRouteMockBuilder.create().withParams({ id: 'draft-1', step: '1' }).build();
38+
mockRouter = RouterMockBuilder.create().withUrl('/registries/prov-1/draft/draft-1/custom').build();
39+
40+
TestBed.configureTestingModule({
41+
imports: [DraftRegistrationCustomStepComponent, MockComponent(CustomStepComponent)],
4242
providers: [
43-
MockProvider(Router, mockRouter),
44-
MockProvider(ActivatedRoute, mockActivatedRoute),
43+
provideOSFCore(),
44+
provideActivatedRouteMock(mockRoute),
45+
provideRouterMock(mockRouter),
4546
provideMockStore({
4647
signals: [
47-
{ selector: RegistriesSelectors.getStepsData, value: mockStepsData },
48-
{ selector: RegistriesSelectors.getDraftRegistration, value: mockDraftRegistration },
48+
{ selector: RegistriesSelectors.getStepsData, value: stepsData },
49+
{ selector: RegistriesSelectors.getDraftRegistration, value: draft },
50+
{ selector: RegistriesSelectors.getPagesSchema, value: [MOCK_REGISTRIES_PAGE] },
51+
{ selector: RegistriesSelectors.getStepsState, value: { 1: { invalid: false } } },
4952
],
5053
}),
5154
],
52-
}).compileComponents();
55+
});
5356

5457
fixture = TestBed.createComponent(DraftRegistrationCustomStepComponent);
5558
component = fixture.componentInstance;
5659
store = TestBed.inject(Store);
57-
(store.dispatch as jest.Mock).mockReturnValue(of(void 0));
5860
fixture.detectChanges();
59-
});
61+
}
6062

6163
it('should create', () => {
64+
setup();
6265
expect(component).toBeTruthy();
6366
});
6467

65-
it('should return stepsData and draftRegistration from store', () => {
66-
expect(component.stepsData()).toEqual(mockStepsData);
67-
expect(component.draftRegistration()).toEqual(mockDraftRegistration);
68-
});
69-
70-
it('should compute filesLink from draftRegistration branchedFrom', () => {
71-
expect(component.filesLink()).toBe('/project/proj-1/files/');
72-
});
73-
74-
it('should compute provider from draftRegistration providerId', () => {
68+
it('should compute inputs from draft registration', () => {
69+
setup();
70+
expect(component.filesLink()).toBe('/files');
7571
expect(component.provider()).toBe('prov-1');
72+
expect(component.projectId()).toBe('node-1');
7673
});
7774

78-
it('should compute projectId from draftRegistration branchedFrom id', () => {
79-
expect(component.projectId()).toBe('proj-1');
75+
it('should return empty strings when draftRegistration is null', () => {
76+
setup(null, {});
77+
expect(component.filesLink()).toBe('');
78+
expect(component.provider()).toBe('');
79+
expect(component.projectId()).toBe('');
8080
});
8181

82-
it('should dispatch UpdateDraft with id and registration_responses payload on onUpdateAction', () => {
83-
const attributes: Partial<DraftRegistrationAttributesJsonApi> = {
84-
registration_responses: { field1: 'value1' },
85-
};
86-
(store.dispatch as jest.Mock).mockClear();
87-
88-
component.onUpdateAction(attributes);
89-
90-
expect(store.dispatch).toHaveBeenCalledWith(expect.any(UpdateDraft));
91-
const call = (store.dispatch as jest.Mock).mock.calls.find((c) => c[0] instanceof UpdateDraft);
92-
expect(call[0].draftId).toBe('draft-1');
93-
expect(call[0].attributes).toEqual({ registration_responses: { registration_responses: { field1: 'value1' } } });
82+
it('should dispatch updateDraft with wrapped registration_responses', () => {
83+
setup();
84+
component.onUpdateAction({ field1: 'value1', field2: ['a', 'b'] } as any);
85+
expect(store.dispatch).toHaveBeenCalledWith(
86+
new UpdateDraft('draft-1', { registration_responses: { field1: 'value1', field2: ['a', 'b'] } })
87+
);
9488
});
9589

96-
it('should navigate to ../metadata on onBack', () => {
90+
it('should navigate back to metadata on onBack', () => {
91+
setup();
9792
component.onBack();
9893
expect(mockRouter.navigate).toHaveBeenCalledWith(
9994
['../', 'metadata'],
10095
expect.objectContaining({ relativeTo: expect.anything() })
10196
);
10297
});
10398

104-
it('should navigate to ../review on onNext', () => {
99+
it('should navigate to review on onNext', () => {
100+
setup();
105101
component.onNext();
106102
expect(mockRouter.navigate).toHaveBeenCalledWith(
107103
['../', 'review'],
108104
expect.objectContaining({ relativeTo: expect.anything() })
109105
);
110106
});
111107
});
112-
113-
describe('DraftRegistrationCustomStepComponent when no draft registration', () => {
114-
let component: DraftRegistrationCustomStepComponent;
115-
let fixture: ComponentFixture<DraftRegistrationCustomStepComponent>;
116-
117-
beforeEach(async () => {
118-
await TestBed.configureTestingModule({
119-
imports: [DraftRegistrationCustomStepComponent, OSFTestingModule, MockComponent(CustomStepComponent)],
120-
providers: [
121-
MockProvider(Router, RouterMockBuilder.create().build()),
122-
MockProvider(ActivatedRoute, ActivatedRouteMockBuilder.create().withParams({ id: 'draft-1' }).build()),
123-
provideMockStore({
124-
signals: [
125-
{ selector: RegistriesSelectors.getStepsData, value: {} },
126-
{ selector: RegistriesSelectors.getDraftRegistration, value: null },
127-
],
128-
}),
129-
],
130-
}).compileComponents();
131-
132-
fixture = TestBed.createComponent(DraftRegistrationCustomStepComponent);
133-
component = fixture.componentInstance;
134-
fixture.detectChanges();
135-
});
136-
137-
it('should compute empty filesLink provider and projectId', () => {
138-
expect(component.filesLink()).toBe('');
139-
expect(component.provider()).toBe('');
140-
expect(component.projectId()).toBe('');
141-
});
142-
});

0 commit comments

Comments
 (0)