Skip to content

Commit 25d2765

Browse files
committed
test(developer-apps): added unit tests for developer apps components
1 parent f39947f commit 25d2765

File tree

6 files changed

+172
-9
lines changed

6 files changed

+172
-9
lines changed

jest.config.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ module.exports = {
5353
'<rootDir>/src/app/features/project/',
5454
'<rootDir>/src/app/features/registries/',
5555
'<rootDir>/src/app/features/settings/addons/',
56-
'<rootDir>/src/app/features/settings/developer-apps/',
5756
'<rootDir>/src/app/features/settings/notifications/',
5857
'<rootDir>/src/app/features/settings/settings-container.component.ts',
5958
'<rootDir>/src/app/features/settings/tokens/components/',

src/app/features/settings/developer-apps/components/developer-app-add-edit-form/developer-app-add-edit-form.component.spec.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
import { provideStore } from '@ngxs/store';
22

3-
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
4-
import { MockPipe, MockProvider } from 'ng-mocks';
3+
import { TranslatePipe } from '@ngx-translate/core';
4+
import { MockPipe, MockProviders } from 'ng-mocks';
55

66
import { DynamicDialogRef } from 'primeng/dynamicdialog';
77

88
import { provideHttpClient } from '@angular/common/http';
99
import { provideHttpClientTesting } from '@angular/common/http/testing';
1010
import { ComponentFixture, TestBed } from '@angular/core/testing';
1111

12+
import { TranslateServiceMock } from '@shared/mocks';
13+
import { ToastService } from '@shared/services';
14+
1215
import { DeveloperAppsState } from '../../store';
1316

1417
import { DeveloperAppAddEditFormComponent } from './developer-app-add-edit-form.component';
@@ -24,17 +27,33 @@ describe('CreateDeveloperAppComponent', () => {
2427
provideHttpClient(),
2528
provideHttpClientTesting(),
2629
provideStore([DeveloperAppsState]),
27-
MockProvider(TranslateService),
28-
MockProvider(DynamicDialogRef),
30+
TranslateServiceMock,
31+
MockProviders(DynamicDialogRef, ToastService),
2932
],
3033
}).compileComponents();
3134

3235
fixture = TestBed.createComponent(DeveloperAppAddEditFormComponent);
3336
component = fixture.componentInstance;
37+
3438
fixture.detectChanges();
3539
});
3640

3741
it('should create', () => {
3842
expect(component).toBeTruthy();
3943
});
44+
45+
it('should mark form as touched and dirty when invalid', () => {
46+
const form = component['appForm'];
47+
form.patchValue({
48+
name: '',
49+
});
50+
51+
const markAllAsTouchedSpy = jest.spyOn(form, 'markAllAsTouched');
52+
const markAsDirtySpy = jest.spyOn(form.controls['name'], 'markAsDirty');
53+
54+
component.handleSubmitForm();
55+
56+
expect(markAllAsTouchedSpy).toHaveBeenCalled();
57+
expect(markAsDirtySpy).toHaveBeenCalled();
58+
});
4059
});
Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,88 @@
11
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
22
import { MockPipe, MockProvider } from 'ng-mocks';
33

4+
import { DialogService, DynamicDialogRef } from 'primeng/dynamicdialog';
5+
6+
import { BehaviorSubject, Subject } from 'rxjs';
7+
48
import { ComponentFixture, TestBed } from '@angular/core/testing';
59

10+
import { DeveloperAppAddEditFormComponent } from '@osf/features/settings/developer-apps/components';
11+
import { TranslateServiceMock } from '@shared/mocks';
12+
import { ToastService } from '@shared/services';
13+
import { IS_MEDIUM } from '@shared/utils';
14+
615
import { DeveloperAppsContainerComponent } from './developer-apps-container.component';
716

8-
describe('DeveloperAppsComponent', () => {
17+
describe('DeveloperAppsContainerComponent', () => {
918
let component: DeveloperAppsContainerComponent;
1019
let fixture: ComponentFixture<DeveloperAppsContainerComponent>;
20+
let isMedium: BehaviorSubject<boolean>;
21+
let translateService: TranslateService;
22+
let dialogRefMock: Partial<DynamicDialogRef>;
23+
let dialogService: DialogService;
24+
let openSpy: jest.SpyInstance;
25+
let translateSpy: jest.SpyInstance;
1126

1227
beforeEach(async () => {
28+
isMedium = new BehaviorSubject<boolean>(false);
29+
dialogRefMock = { onClose: new Subject<void>() };
30+
1331
await TestBed.configureTestingModule({
1432
imports: [DeveloperAppsContainerComponent, MockPipe(TranslatePipe)],
15-
providers: [MockProvider(TranslateService)],
33+
providers: [
34+
MockProvider(DialogService),
35+
MockProvider(IS_MEDIUM, isMedium),
36+
MockProvider(ToastService),
37+
TranslateServiceMock,
38+
],
1639
}).compileComponents();
1740

1841
fixture = TestBed.createComponent(DeveloperAppsContainerComponent);
1942
component = fixture.componentInstance;
43+
44+
translateService = TestBed.inject(TranslateService);
45+
dialogService = fixture.debugElement.injector.get(DialogService);
46+
47+
openSpy = jest.spyOn(dialogService, 'open').mockReturnValue(dialogRefMock as DynamicDialogRef);
48+
translateSpy = jest.spyOn(translateService, 'instant').mockReturnValue('Create Developer App');
49+
2050
fixture.detectChanges();
2151
});
2252

2353
it('should create', () => {
2454
expect(component).toBeTruthy();
2555
});
56+
57+
it('should open dialog with 340px width when isMedium returns false', () => {
58+
(component as any).isMedium = jest.fn().mockReturnValue(false);
59+
60+
component.createDeveloperApp();
61+
62+
expect(openSpy).toHaveBeenCalledWith(DeveloperAppAddEditFormComponent, {
63+
width: '340px',
64+
focusOnShow: false,
65+
header: 'Create Developer App',
66+
closeOnEscape: true,
67+
modal: true,
68+
closable: true,
69+
});
70+
expect(translateSpy).toHaveBeenCalledWith('settings.developerApps.form.createTitle');
71+
});
72+
73+
it('should open dialog with 500px width when isMedium returns true', () => {
74+
(component as any).isMedium = jest.fn().mockReturnValue(true);
75+
76+
component.createDeveloperApp();
77+
78+
expect(openSpy).toHaveBeenCalledWith(DeveloperAppAddEditFormComponent, {
79+
width: '500px',
80+
focusOnShow: false,
81+
header: 'Create Developer App',
82+
closeOnEscape: true,
83+
modal: true,
84+
closable: true,
85+
});
86+
expect(translateSpy).toHaveBeenCalledWith('settings.developerApps.form.createTitle');
87+
});
2688
});

src/app/features/settings/developer-apps/pages/developer-app-details/developer-app-details.component.spec.ts

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ import { of } from 'rxjs';
1010
import { provideHttpClient } from '@angular/common/http';
1111
import { provideHttpClientTesting } from '@angular/common/http/testing';
1212
import { ComponentFixture, TestBed } from '@angular/core/testing';
13-
import { ActivatedRoute } from '@angular/router';
13+
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
14+
15+
import { CustomConfirmationService } from '@osf/shared/services';
16+
import { IS_XSMALL } from '@osf/shared/utils';
1417

1518
import { DeveloperAppsState } from '../../store';
1619

@@ -19,6 +22,13 @@ import { DeveloperAppDetailsComponent } from './developer-app-details.component'
1922
describe('DeveloperAppDetailsComponent', () => {
2023
let component: DeveloperAppDetailsComponent;
2124
let fixture: ComponentFixture<DeveloperAppDetailsComponent>;
25+
let router: Router;
26+
let customConfirmationService: CustomConfirmationService;
27+
28+
const mockRouter = {
29+
url: '/test/path',
30+
events: of(new NavigationEnd(1, '/test/path', '/test/path')),
31+
};
2232

2333
beforeEach(async () => {
2434
await TestBed.configureTestingModule({
@@ -29,16 +39,57 @@ describe('DeveloperAppDetailsComponent', () => {
2939
provideHttpClientTesting(),
3040
provideStore([DeveloperAppsState]),
3141
MockProvider(TranslateService),
32-
MockProvider(ActivatedRoute, { params: of({}) }),
42+
MockProvider(ActivatedRoute, { params: of({ id: 'test-client-id' }) }),
43+
MockProvider(Router, mockRouter),
44+
MockProvider(CustomConfirmationService),
45+
MockProvider(IS_XSMALL, of(false)),
3346
],
3447
}).compileComponents();
3548

3649
fixture = TestBed.createComponent(DeveloperAppDetailsComponent);
3750
component = fixture.componentInstance;
51+
52+
customConfirmationService = TestBed.inject(CustomConfirmationService);
53+
router = TestBed.inject(Router);
54+
3855
fixture.detectChanges();
3956
});
4057

4158
it('should create', () => {
4259
expect(component).toBeTruthy();
4360
});
61+
62+
it('should not dispatch delete when user cancels confirmation', () => {
63+
const navigateSpy = jest.spyOn(router, 'navigate');
64+
65+
jest.spyOn(customConfirmationService, 'confirmDelete').mockImplementation(() => {
66+
// Simulate cancelling the confirmation
67+
});
68+
69+
component.deleteApp();
70+
71+
expect(customConfirmationService.confirmDelete).toHaveBeenCalledWith({
72+
headerKey: 'settings.developerApps.confirmation.delete.title',
73+
headerParams: { name: undefined },
74+
messageKey: 'settings.developerApps.confirmation.delete.message',
75+
onConfirm: expect.any(Function),
76+
});
77+
expect(navigateSpy).not.toHaveBeenCalled();
78+
});
79+
80+
it('should not dispatch resetClientSecret when user cancels confirmation', () => {
81+
jest.spyOn(customConfirmationService, 'confirmDelete').mockImplementation(() => {
82+
// Simulate cancelling the confirmation
83+
});
84+
85+
component.resetClientSecret();
86+
87+
expect(customConfirmationService.confirmDelete).toHaveBeenCalledWith({
88+
headerKey: 'settings.developerApps.confirmation.resetSecret.title',
89+
headerParams: { name: undefined },
90+
messageKey: 'settings.developerApps.confirmation.resetSecret.message',
91+
acceptLabelKey: 'settings.developerApps.details.clientSecret.reset',
92+
onConfirm: expect.any(Function),
93+
});
94+
});
4495
});

src/app/features/settings/developer-apps/pages/developer-apps-list/developer-apps-list.component.spec.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@ import { provideHttpClient } from '@angular/common/http';
99
import { provideHttpClientTesting } from '@angular/common/http/testing';
1010
import { ComponentFixture, TestBed } from '@angular/core/testing';
1111

12+
import { CustomConfirmationService } from '@osf/shared/services';
13+
import { MOCK_DEVELOPER_APP } from '@shared/mocks/developer-app.mock';
14+
1215
import { DeveloperAppsState } from '../../store';
1316

1417
import { DeveloperAppsListComponent } from './developer-apps-list.component';
1518

1619
describe('DeveloperApplicationsListComponent', () => {
1720
let component: DeveloperAppsListComponent;
1821
let fixture: ComponentFixture<DeveloperAppsListComponent>;
22+
let customConfirmationService: CustomConfirmationService;
1923

2024
beforeEach(async () => {
2125
await TestBed.configureTestingModule({
@@ -26,15 +30,32 @@ describe('DeveloperApplicationsListComponent', () => {
2630
provideHttpClientTesting(),
2731
MockProvider(ConfirmationService),
2832
MockProvider(TranslateService),
33+
MockProvider(CustomConfirmationService),
2934
],
3035
}).compileComponents();
3136

3237
fixture = TestBed.createComponent(DeveloperAppsListComponent);
3338
component = fixture.componentInstance;
39+
customConfirmationService = TestBed.inject(CustomConfirmationService);
3440
fixture.detectChanges();
3541
});
3642

3743
it('should create', () => {
3844
expect(component).toBeTruthy();
3945
});
46+
47+
it('should not dispatch delete when user cancels confirmation', () => {
48+
jest.spyOn(customConfirmationService, 'confirmDelete').mockImplementation(() => {
49+
// Simulate cancelling the confirmation
50+
});
51+
52+
component.deleteApp(MOCK_DEVELOPER_APP);
53+
54+
expect(customConfirmationService.confirmDelete).toHaveBeenCalledWith({
55+
headerKey: 'settings.developerApps.confirmation.delete.title',
56+
headerParams: { name: 'Test App' },
57+
messageKey: 'settings.developerApps.confirmation.delete.message',
58+
onConfirm: expect.any(Function),
59+
});
60+
});
4061
});
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { DeveloperApp } from '@osf/features/settings/developer-apps/models';
2+
3+
export const MOCK_DEVELOPER_APP: DeveloperApp = {
4+
id: 'test-id',
5+
name: 'Test App',
6+
description: 'This is a test application',
7+
projHomePageUrl: 'https://example.com',
8+
authorizationCallbackUrl: 'https://example.com/callback',
9+
clientId: 'test-client-id',
10+
clientSecret: 'test-secret',
11+
};

0 commit comments

Comments
 (0)