@@ -13,7 +13,7 @@ import { ActivatedRoute, Router } from '@angular/router';
1313
1414import { TokenCreatedDialogComponent } from '@osf/features/settings/tokens/components' ;
1515import { InputLimits } from '@osf/shared/constants' ;
16- import { MOCK_STORE , TranslateServiceMock } from '@shared/mocks' ;
16+ import { MOCK_SCOPES , MOCK_STORE , MOCK_TOKEN , TranslateServiceMock } from '@shared/mocks' ;
1717import { ToastService } from '@shared/services' ;
1818
1919import { TokenFormControls , TokenModel } from '../../models' ;
@@ -30,29 +30,25 @@ describe('TokenAddEditFormComponent', () => {
3030 let dialogRef : Partial < DynamicDialogRef > ;
3131 let activatedRoute : Partial < ActivatedRoute > ;
3232 let router : Partial < Router > ;
33- let toastService : Partial < ToastService > ;
33+ let toastService : jest . Mocked < ToastService > ;
34+ let translateService : jest . Mocked < TranslateService > ;
3435
35- const MOCK_TOKEN : TokenModel = {
36- id : '1' ,
37- name : 'Test Token' ,
38- scopes : [ 'read' , 'write' ] ,
39- } ;
40-
41- const MOCK_SCOPES = [
42- { id : 'read' , description : 'Read access' } ,
43- { id : 'write' , description : 'Write access' } ,
44- { id : 'delete' , description : 'Delete access' } ,
45- ] ;
36+ const mockTokens : TokenModel [ ] = [ MOCK_TOKEN ] ;
4637
47- const MOCK_TOKENS = [ MOCK_TOKEN ] ;
38+ const fillForm = ( tokenName : string = MOCK_TOKEN . name , scopes : string [ ] = MOCK_TOKEN . scopes ) : void => {
39+ component . tokenForm . patchValue ( {
40+ [ TokenFormControls . TokenName ] : tokenName ,
41+ [ TokenFormControls . Scopes ] : scopes ,
42+ } ) ;
43+ } ;
4844
4945 beforeEach ( async ( ) => {
5046 ( MOCK_STORE . selectSignal as jest . Mock ) . mockImplementation ( ( selector ) => {
5147 if ( selector === TokensSelectors . getScopes ) return ( ) => MOCK_SCOPES ;
5248 if ( selector === TokensSelectors . isTokensLoading ) return ( ) => false ;
53- if ( selector === TokensSelectors . getTokens ) return ( ) => MOCK_TOKENS ;
49+ if ( selector === TokensSelectors . getTokens ) return ( ) => mockTokens ;
5450 if ( selector === TokensSelectors . getTokenById ) {
55- return ( ) => ( id : string ) => MOCK_TOKENS . find ( ( token ) => token . id === id ) ;
51+ return ( ) => ( id : string ) => mockTokens . find ( ( token ) => token . id === id ) ;
5652 }
5753 return ( ) => null ;
5854 } ) ;
@@ -73,11 +69,6 @@ describe('TokenAddEditFormComponent', () => {
7369 navigate : jest . fn ( ) ,
7470 } ;
7571
76- toastService = {
77- showSuccess : jest . fn ( ) ,
78- showError : jest . fn ( ) ,
79- } ;
80-
8172 await TestBed . configureTestingModule ( {
8273 imports : [ TokenAddEditFormComponent , ReactiveFormsModule , OSFTestingStoreModule ] ,
8374 providers : [
@@ -87,28 +78,28 @@ describe('TokenAddEditFormComponent', () => {
8778 MockProvider ( DynamicDialogRef , dialogRef ) ,
8879 MockProvider ( ActivatedRoute , activatedRoute ) ,
8980 MockProvider ( Router , router ) ,
90- MockProvider ( ToastService , toastService ) ,
81+ MockProvider ( ToastService , {
82+ showSuccess : jest . fn ( ) ,
83+ showWarn : jest . fn ( ) ,
84+ showError : jest . fn ( ) ,
85+ } ) ,
9186 ] ,
9287 } ) . compileComponents ( ) ;
9388
9489 fixture = TestBed . createComponent ( TokenAddEditFormComponent ) ;
9590 component = fixture . componentInstance ;
91+
92+ toastService = TestBed . inject ( ToastService ) as jest . Mocked < ToastService > ;
93+ translateService = TestBed . inject ( TranslateService ) as jest . Mocked < TranslateService > ;
94+
9695 fixture . detectChanges ( ) ;
9796 } ) ;
9897
9998 it ( 'should create' , ( ) => {
10099 expect ( component ) . toBeTruthy ( ) ;
101100 } ) ;
102101
103- it ( 'should patch form with initial values when provided' , ( ) => {
104- fixture . componentRef . setInput ( 'initialValues' , MOCK_TOKEN ) ;
105- component . ngOnInit ( ) ;
106-
107- expect ( component . tokenForm . get ( TokenFormControls . TokenName ) ?. value ) . toBe ( MOCK_TOKEN . name ) ;
108- expect ( component . tokenForm . get ( TokenFormControls . Scopes ) ?. value ) . toEqual ( MOCK_TOKEN . scopes ) ;
109- } ) ;
110-
111- it ( 'should call patchValue with initial values on ngOnInit' , ( ) => {
102+ it ( 'should patch form with initial values on init' , ( ) => {
112103 fixture . componentRef . setInput ( 'initialValues' , MOCK_TOKEN ) ;
113104 const patchSpy = jest . spyOn ( component . tokenForm , 'patchValue' ) ;
114105
@@ -120,15 +111,14 @@ describe('TokenAddEditFormComponent', () => {
120111 [ TokenFormControls . Scopes ] : MOCK_TOKEN . scopes ,
121112 } )
122113 ) ;
114+ expect ( component . tokenForm . get ( TokenFormControls . TokenName ) ?. value ) . toBe ( MOCK_TOKEN . name ) ;
115+ expect ( component . tokenForm . get ( TokenFormControls . Scopes ) ?. value ) . toEqual ( MOCK_TOKEN . scopes ) ;
123116 } ) ;
124117
125118 it ( 'should not patch form when initialValues are not provided' , ( ) => {
126119 fixture . componentRef . setInput ( 'initialValues' , null ) ;
127120
128- component . tokenForm . patchValue ( {
129- [ TokenFormControls . TokenName ] : 'Existing Name' ,
130- [ TokenFormControls . Scopes ] : [ 'read' ] ,
131- } ) ;
121+ fillForm ( 'Existing Name' , [ 'read' ] ) ;
132122
133123 component . ngOnInit ( ) ;
134124
@@ -137,10 +127,7 @@ describe('TokenAddEditFormComponent', () => {
137127 } ) ;
138128
139129 it ( 'should not submit when form is invalid' , ( ) => {
140- component . tokenForm . patchValue ( {
141- [ TokenFormControls . TokenName ] : '' ,
142- [ TokenFormControls . Scopes ] : [ ] ,
143- } ) ;
130+ fillForm ( '' , [ ] ) ;
144131
145132 const markAllAsTouchedSpy = jest . spyOn ( component . tokenForm , 'markAllAsTouched' ) ;
146133 const markAsDirtySpy = jest . spyOn ( component . tokenForm . get ( TokenFormControls . TokenName ) ! , 'markAsDirty' ) ;
@@ -155,63 +142,15 @@ describe('TokenAddEditFormComponent', () => {
155142 } ) ;
156143
157144 it ( 'should return early when tokenName is missing' , ( ) => {
158- component . tokenForm . patchValue ( {
159- [ TokenFormControls . TokenName ] : '' ,
160- [ TokenFormControls . Scopes ] : [ 'read' ] ,
161- } ) ;
145+ fillForm ( '' , [ 'read' ] ) ;
162146
163147 component . handleSubmitForm ( ) ;
164148
165149 expect ( MOCK_STORE . dispatch ) . not . toHaveBeenCalled ( ) ;
166150 } ) ;
167151
168152 it ( 'should return early when scopes is missing' , ( ) => {
169- component . tokenForm . patchValue ( {
170- [ TokenFormControls . TokenName ] : 'Test Token' ,
171- [ TokenFormControls . Scopes ] : [ ] ,
172- } ) ;
173-
174- component . handleSubmitForm ( ) ;
175-
176- expect ( MOCK_STORE . dispatch ) . not . toHaveBeenCalled ( ) ;
177- } ) ;
178-
179- it ( 'should early-return when tokenName is falsy even if form is valid' , ( ) => {
180- const tokenNameControl = component . tokenForm . get ( TokenFormControls . TokenName ) ! ;
181- const scopesControl = component . tokenForm . get ( TokenFormControls . Scopes ) ! ;
182-
183- tokenNameControl . clearValidators ( ) ;
184- scopesControl . clearValidators ( ) ;
185- tokenNameControl . updateValueAndValidity ( ) ;
186- scopesControl . updateValueAndValidity ( ) ;
187-
188- component . tokenForm . patchValue ( {
189- [ TokenFormControls . TokenName ] : undefined as unknown as string ,
190- [ TokenFormControls . Scopes ] : [ 'read' ] ,
191- } ) ;
192-
193- expect ( component . tokenForm . valid ) . toBe ( true ) ;
194-
195- component . handleSubmitForm ( ) ;
196-
197- expect ( MOCK_STORE . dispatch ) . not . toHaveBeenCalled ( ) ;
198- } ) ;
199-
200- it ( 'should early-return when scopes is falsy even if form is valid' , ( ) => {
201- const tokenNameControl = component . tokenForm . get ( TokenFormControls . TokenName ) ! ;
202- const scopesControl = component . tokenForm . get ( TokenFormControls . Scopes ) ! ;
203-
204- tokenNameControl . clearValidators ( ) ;
205- scopesControl . clearValidators ( ) ;
206- tokenNameControl . updateValueAndValidity ( ) ;
207- scopesControl . updateValueAndValidity ( ) ;
208-
209- component . tokenForm . patchValue ( {
210- [ TokenFormControls . TokenName ] : 'Test Token' ,
211- [ TokenFormControls . Scopes ] : undefined as unknown as string [ ] ,
212- } ) ;
213-
214- expect ( component . tokenForm . valid ) . toBe ( true ) ;
153+ fillForm ( 'Test Token' , [ ] ) ;
215154
216155 component . handleSubmitForm ( ) ;
217156
@@ -220,10 +159,7 @@ describe('TokenAddEditFormComponent', () => {
220159
221160 it ( 'should create token when not in edit mode' , ( ) => {
222161 fixture . componentRef . setInput ( 'isEditMode' , false ) ;
223- component . tokenForm . patchValue ( {
224- [ TokenFormControls . TokenName ] : 'Test Token' ,
225- [ TokenFormControls . Scopes ] : [ 'read' , 'write' ] ,
226- } ) ;
162+ fillForm ( 'Test Token' , [ 'read' , 'write' ] ) ;
227163
228164 MOCK_STORE . dispatch . mockReturnValue ( of ( undefined ) ) ;
229165
@@ -234,10 +170,7 @@ describe('TokenAddEditFormComponent', () => {
234170
235171 it ( 'should show success toast and close dialog after creating token' , ( ) => {
236172 fixture . componentRef . setInput ( 'isEditMode' , false ) ;
237- component . tokenForm . patchValue ( {
238- [ TokenFormControls . TokenName ] : 'Test Token' ,
239- [ TokenFormControls . Scopes ] : [ 'read' , 'write' ] ,
240- } ) ;
173+ fillForm ( 'Test Token' , [ 'read' , 'write' ] ) ;
241174
242175 MOCK_STORE . dispatch . mockReturnValue ( of ( undefined ) ) ;
243176
@@ -249,10 +182,7 @@ describe('TokenAddEditFormComponent', () => {
249182
250183 it ( 'should open created dialog with new token name and value after create' , ( ) => {
251184 fixture . componentRef . setInput ( 'isEditMode' , false ) ;
252- component . tokenForm . patchValue ( {
253- [ TokenFormControls . TokenName ] : 'Test Token' ,
254- [ TokenFormControls . Scopes ] : [ 'read' , 'write' ] ,
255- } ) ;
185+ fillForm ( 'Test Token' , [ 'read' , 'write' ] ) ;
256186
257187 const showDialogSpy = jest . spyOn ( component , 'showTokenCreatedDialog' ) ;
258188
@@ -265,10 +195,7 @@ describe('TokenAddEditFormComponent', () => {
265195
266196 it ( 'should show success toast and navigate after updating token' , ( ) => {
267197 fixture . componentRef . setInput ( 'isEditMode' , true ) ;
268- component . tokenForm . patchValue ( {
269- [ TokenFormControls . TokenName ] : 'Updated Token' ,
270- [ TokenFormControls . Scopes ] : [ 'read' , 'write' ] ,
271- } ) ;
198+ fillForm ( 'Updated Token' , [ 'read' , 'write' ] ) ;
272199
273200 MOCK_STORE . dispatch . mockReturnValue ( of ( undefined ) ) ;
274201
@@ -301,17 +228,13 @@ describe('TokenAddEditFormComponent', () => {
301228 } ) ;
302229
303230 it ( 'should use TranslateService.instant for dialog header' , ( ) => {
304- const translate = TestBed . inject ( TranslateService ) as unknown as { instant : jest . Mock } ;
305231 component . showTokenCreatedDialog ( 'Name' , 'Value' ) ;
306- expect ( translate . instant ) . toHaveBeenCalledWith ( 'settings.tokens.createdDialog.title' ) ;
232+ expect ( translateService . instant ) . toHaveBeenCalledWith ( 'settings.tokens.createdDialog.title' ) ;
307233 } ) ;
308234
309235 it ( 'should read tokens via selectSignal after create' , ( ) => {
310236 fixture . componentRef . setInput ( 'isEditMode' , false ) ;
311- component . tokenForm . patchValue ( {
312- [ TokenFormControls . TokenName ] : 'Test Token' ,
313- [ TokenFormControls . Scopes ] : [ 'read' ] ,
314- } ) ;
237+ fillForm ( 'Test Token' , [ 'read' ] ) ;
315238
316239 const selectSpy = jest . spyOn ( MOCK_STORE , 'selectSignal' ) ;
317240 MOCK_STORE . dispatch . mockReturnValue ( of ( undefined ) ) ;
@@ -336,10 +259,7 @@ describe('TokenAddEditFormComponent', () => {
336259 } ) ;
337260
338261 it ( 'should be valid when both fields are filled' , ( ) => {
339- component . tokenForm . patchValue ( {
340- [ TokenFormControls . TokenName ] : 'Test Token' ,
341- [ TokenFormControls . Scopes ] : [ 'read' ] ,
342- } ) ;
262+ fillForm ( 'Test Token' , [ 'read' ] ) ;
343263
344264 expect ( component . tokenForm . valid ) . toBe ( true ) ;
345265 } ) ;
@@ -355,22 +275,4 @@ describe('TokenAddEditFormComponent', () => {
355275 it ( 'should expose scopes from store via tokenScopes signal' , ( ) => {
356276 expect ( component . tokenScopes ( ) ) . toEqual ( MOCK_SCOPES ) ;
357277 } ) ;
358-
359- it ( 'should disable form when isLoading is true' , ( ) => {
360- ( MOCK_STORE . selectSignal as jest . Mock ) . mockImplementation ( ( selector ) => {
361- if ( selector === TokensSelectors . getScopes ) return ( ) => MOCK_SCOPES ;
362- if ( selector === TokensSelectors . isTokensLoading ) return ( ) => true ;
363- if ( selector === TokensSelectors . getTokens ) return ( ) => MOCK_TOKENS ;
364- if ( selector === TokensSelectors . getTokenById ) {
365- return ( ) => ( id : string ) => MOCK_TOKENS . find ( ( token ) => token . id === id ) ;
366- }
367- return ( ) => null ;
368- } ) ;
369-
370- const loadingFixture = TestBed . createComponent ( TokenAddEditFormComponent ) ;
371- const loadingComponent = loadingFixture . componentInstance ;
372- loadingFixture . detectChanges ( ) ;
373-
374- expect ( loadingComponent . tokenForm . disabled ) . toBe ( true ) ;
375- } ) ;
376278} ) ;
0 commit comments