@@ -9,46 +9,61 @@ import { UserSelectors } from '@core/store/user';
99import { CreateDraft , GetProjects , GetProviderSchemas , RegistriesSelectors } from '@osf/features/registries/store' ;
1010import { SubHeaderComponent } from '@osf/shared/components/sub-header/sub-header.component' ;
1111import { ToastService } from '@osf/shared/services/toast.service' ;
12- import { GetRegistryProvider } from '@shared/stores/registration-provider' ;
12+ import { GetRegistryProvider , RegistrationProviderSelectors } from '@shared/stores/registration-provider' ;
1313
1414import { NewRegistrationComponent } from './new-registration.component' ;
1515
1616import { MOCK_PROVIDER_SCHEMAS } from '@testing/mocks/registries.mock' ;
1717import { provideOSFCore } from '@testing/osf.testing.provider' ;
1818import { ActivatedRouteMockBuilder } from '@testing/providers/route-provider.mock' ;
1919import { RouterMockBuilder , RouterMockType } from '@testing/providers/router-provider.mock' ;
20- import { provideMockStore } from '@testing/providers/store-provider.mock' ;
20+ import {
21+ BaseSetupOverrides ,
22+ mergeSignalOverrides ,
23+ provideMockStore ,
24+ SignalOverride ,
25+ } from '@testing/providers/store-provider.mock' ;
26+ import { ToastServiceMock , ToastServiceMockType } from '@testing/providers/toast-provider.mock' ;
2127
2228describe ( 'NewRegistrationComponent' , ( ) => {
2329 let component : NewRegistrationComponent ;
2430 let fixture : ComponentFixture < NewRegistrationComponent > ;
2531 let store : Store ;
2632 let mockRouter : RouterMockType ;
27-
28- beforeEach ( ( ) => {
33+ let toastService : ToastServiceMockType ;
34+
35+ interface SetupOverrides extends BaseSetupOverrides {
36+ selectorOverrides ?: SignalOverride [ ] ;
37+ }
38+
39+ const defaultSignals : SignalOverride [ ] = [
40+ { selector : RegistriesSelectors . getProjects , value : [ { id : 'p1' , title : 'P1' } ] } ,
41+ { selector : RegistriesSelectors . getProviderSchemas , value : MOCK_PROVIDER_SCHEMAS } ,
42+ { selector : RegistriesSelectors . isDraftSubmitting , value : false } ,
43+ { selector : RegistriesSelectors . getDraftRegistration , value : { id : 'draft-1' } } ,
44+ { selector : RegistriesSelectors . isProvidersLoading , value : false } ,
45+ { selector : RegistriesSelectors . isProjectsLoading , value : false } ,
46+ { selector : UserSelectors . getCurrentUser , value : { id : 'user-1' } } ,
47+ { selector : RegistrationProviderSelectors . getBrandedProvider , value : { id : 'prov-1' , allowSubmissions : true } } ,
48+ ] ;
49+
50+ const setup = ( overrides ?: SetupOverrides ) => {
2951 const mockActivatedRoute = ActivatedRouteMockBuilder . create ( )
30- . withParams ( { providerId : 'prov-1' } )
52+ . withParams ( overrides ?. routeParams || { providerId : 'prov-1' } )
3153 . withQueryParams ( { projectId : 'proj-1' } )
3254 . build ( ) ;
3355 mockRouter = RouterMockBuilder . create ( ) . withUrl ( '/x' ) . build ( ) ;
56+ toastService = ToastServiceMock . simple ( ) ;
3457
3558 TestBed . configureTestingModule ( {
3659 imports : [ NewRegistrationComponent , MockComponent ( SubHeaderComponent ) ] ,
3760 providers : [
3861 provideOSFCore ( ) ,
3962 MockProvider ( ActivatedRoute , mockActivatedRoute ) ,
40- MockProvider ( ToastService ) ,
63+ MockProvider ( ToastService , toastService ) ,
4164 MockProvider ( Router , mockRouter ) ,
4265 provideMockStore ( {
43- signals : [
44- { selector : RegistriesSelectors . getProjects , value : [ { id : 'p1' , title : 'P1' } ] } ,
45- { selector : RegistriesSelectors . getProviderSchemas , value : MOCK_PROVIDER_SCHEMAS } ,
46- { selector : RegistriesSelectors . isDraftSubmitting , value : false } ,
47- { selector : RegistriesSelectors . getDraftRegistration , value : { id : 'draft-1' } } ,
48- { selector : RegistriesSelectors . isProvidersLoading , value : false } ,
49- { selector : RegistriesSelectors . isProjectsLoading , value : false } ,
50- { selector : UserSelectors . getCurrentUser , value : { id : 'user-1' } } ,
51- ] ,
66+ signals : mergeSignalOverrides ( defaultSignals , overrides ?. selectorOverrides ) ,
5267 } ) ,
5368 ] ,
5469 } ) ;
@@ -57,31 +72,69 @@ describe('NewRegistrationComponent', () => {
5772 fixture = TestBed . createComponent ( NewRegistrationComponent ) ;
5873 component = fixture . componentInstance ;
5974 fixture . detectChanges ( ) ;
60- } ) ;
75+ } ;
6176
6277 it ( 'should create' , ( ) => {
78+ setup ( ) ;
6379 expect ( component ) . toBeTruthy ( ) ;
6480 } ) ;
6581
82+ it ( 'should allow submissions when provider allows it' , ( ) => {
83+ setup ( ) ;
84+ expect ( component . canShowForm ( ) ) . toBe ( true ) ;
85+ expect ( toastService . showError ) . not . toHaveBeenCalled ( ) ;
86+ expect ( mockRouter . navigate ) . not . toHaveBeenCalled ( ) ;
87+ } ) ;
88+
89+ it ( 'should redirect and show error when submissions are not allowed' , ( ) => {
90+ setup ( {
91+ selectorOverrides : [
92+ {
93+ selector : RegistrationProviderSelectors . getBrandedProvider ,
94+ value : { id : 'prov-1' , allowSubmissions : false } ,
95+ } ,
96+ ] ,
97+ } ) ;
98+
99+ expect ( component . canShowForm ( ) ) . toBe ( false ) ;
100+ expect ( toastService . showError ) . toHaveBeenCalledWith ( 'registries.new.registryClosedForSubmissions' ) ;
101+ expect ( mockRouter . navigate ) . toHaveBeenCalledWith ( [ '/registries' , 'prov-1' ] ) ;
102+ } ) ;
103+
104+ it ( 'should redirect and show error when allowSubmissions is undefined' , ( ) => {
105+ setup ( {
106+ selectorOverrides : [ { selector : RegistrationProviderSelectors . getBrandedProvider , value : { id : 'prov-1' } } ] ,
107+ } ) ;
108+
109+ expect ( component . canShowForm ( ) ) . toBe ( false ) ;
110+ expect ( toastService . showError ) . toHaveBeenCalledWith ( 'registries.new.registryClosedForSubmissions' ) ;
111+ expect ( mockRouter . navigate ) . toHaveBeenCalledWith ( [ '/registries' , 'prov-1' ] ) ;
112+ } ) ;
113+
66114 it ( 'should dispatch initial data fetching on init' , ( ) => {
115+ setup ( ) ;
67116 expect ( store . dispatch ) . toHaveBeenCalledWith ( new GetProjects ( 'user-1' , '' ) ) ;
68117 expect ( store . dispatch ) . toHaveBeenCalledWith ( new GetRegistryProvider ( 'prov-1' ) ) ;
69118 expect ( store . dispatch ) . toHaveBeenCalledWith ( new GetProviderSchemas ( 'prov-1' ) ) ;
70119 } ) ;
71120
72121 it ( 'should init fromProject as true when projectId is present' , ( ) => {
122+ setup ( ) ;
73123 expect ( component . fromProject ( ) ) . toBe ( true ) ;
74124 } ) ;
75125
76126 it ( 'should init form with project id from route' , ( ) => {
127+ setup ( ) ;
77128 expect ( component . draftForm . get ( 'project' ) ?. value ) . toBe ( 'proj-1' ) ;
78129 } ) ;
79130
80131 it ( 'should default providerSchema when schemas are available' , ( ) => {
132+ setup ( ) ;
81133 expect ( component . draftForm . get ( 'providerSchema' ) ?. value ) . toBe ( 'schema-1' ) ;
82134 } ) ;
83135
84136 it ( 'should toggle fromProject and add/remove validator' , ( ) => {
137+ setup ( ) ;
85138 component . fromProject . set ( false ) ;
86139 component . toggleFromProject ( ) ;
87140 expect ( component . fromProject ( ) ) . toBe ( true ) ;
@@ -93,6 +146,7 @@ describe('NewRegistrationComponent', () => {
93146 } ) ;
94147
95148 it ( 'should dispatch createDraft and navigate when form is valid' , ( ) => {
149+ setup ( ) ;
96150 component . draftForm . patchValue ( { providerSchema : 'schema-1' , project : 'proj-1' } ) ;
97151 component . fromProject . set ( true ) ;
98152 ( store . dispatch as jest . Mock ) . mockClear ( ) ;
@@ -106,6 +160,7 @@ describe('NewRegistrationComponent', () => {
106160 } ) ;
107161
108162 it ( 'should not dispatch createDraft when form is invalid' , ( ) => {
163+ setup ( ) ;
109164 component . draftForm . patchValue ( { providerSchema : '' } ) ;
110165 ( store . dispatch as jest . Mock ) . mockClear ( ) ;
111166
@@ -115,6 +170,7 @@ describe('NewRegistrationComponent', () => {
115170 } ) ;
116171
117172 it ( 'should dispatch getProjects after debounced filter' , fakeAsync ( ( ) => {
173+ setup ( ) ;
118174 ( store . dispatch as jest . Mock ) . mockClear ( ) ;
119175
120176 component . onProjectFilter ( 'abc' ) ;
@@ -124,6 +180,7 @@ describe('NewRegistrationComponent', () => {
124180 } ) ) ;
125181
126182 it ( 'should not dispatch duplicate getProjects for same filter value' , fakeAsync ( ( ) => {
183+ setup ( ) ;
127184 ( store . dispatch as jest . Mock ) . mockClear ( ) ;
128185
129186 component . onProjectFilter ( 'abc' ) ;
@@ -132,12 +189,13 @@ describe('NewRegistrationComponent', () => {
132189 tick ( 300 ) ;
133190
134191 const getProjectsCalls = ( store . dispatch as jest . Mock ) . mock . calls . filter (
135- ( [ action ] : [ any ] ) => action instanceof GetProjects
192+ ( [ action ] : [ unknown ] ) => action instanceof GetProjects
136193 ) ;
137194 expect ( getProjectsCalls . length ) . toBe ( 1 ) ;
138195 } ) ) ;
139196
140197 it ( 'should debounce rapid filter calls and dispatch only the last value' , fakeAsync ( ( ) => {
198+ setup ( ) ;
141199 ( store . dispatch as jest . Mock ) . mockClear ( ) ;
142200
143201 component . onProjectFilter ( 'a' ) ;
@@ -146,7 +204,7 @@ describe('NewRegistrationComponent', () => {
146204 tick ( 300 ) ;
147205
148206 const getProjectsCalls = ( store . dispatch as jest . Mock ) . mock . calls . filter (
149- ( [ action ] : [ any ] ) => action instanceof GetProjects
207+ ( [ action ] : [ unknown ] ) => action instanceof GetProjects
150208 ) ;
151209 expect ( getProjectsCalls . length ) . toBe ( 1 ) ;
152210 expect ( getProjectsCalls [ 0 ] [ 0 ] ) . toEqual ( new GetProjects ( 'user-1' , 'abc' ) ) ;
0 commit comments