11import { provideStore , Store } from '@ngxs/store' ;
22
3+ import { MockProvider } from 'ng-mocks' ;
4+
35import { EMPTY , of } from 'rxjs' ;
46
5- import { vi } from 'vitest' ;
7+ import { Mock , vi } from 'vitest' ;
68
79import { TestBed } from '@angular/core/testing' ;
810
9- import {
10- DiscoverableFilter ,
11- FilterOperatorOption ,
12- FilterOption ,
13- } from '@osf/shared/models/search/discoverable-filter.model' ;
11+ import { FilterOption } from '@osf/shared/models/search/discoverable-filter.model' ;
1412import { GlobalSearchService } from '@osf/shared/services/global-search.service' ;
15- import { ResourcesData } from '@shared/models/search/resource.model' ;
1613
14+ import {
15+ MOCK_CEDAR_FILTER ,
16+ MOCK_REGULAR_FILTER ,
17+ MOCK_RESOURCES_DATA ,
18+ } from '@testing/data/global-search/global-search.data' ;
1719import { provideOSFCore } from '@testing/osf.testing.provider' ;
1820
1921import {
@@ -27,188 +29,142 @@ import {
2729import { GlobalSearchSelectors } from './global-search.selectors' ;
2830import { GlobalSearchState } from './global-search.state' ;
2931
30- const MOCK_RESOURCES_DATA : ResourcesData = {
31- resources : [ ] ,
32- filters : [ ] ,
33- count : 0 ,
34- self : '' ,
35- first : null ,
36- next : null ,
37- previous : null ,
38- } ;
39-
40- const CEDAR_FILTER : DiscoverableFilter = {
41- key : 'School Type' ,
42- label : 'School Type' ,
43- operator : FilterOperatorOption . AnyOf ,
44- cedarPropertyIri : 'uuid-school-type' ,
45- options : [
46- { label : 'High School' , value : 'High School' , cardSearchResultCount : null } ,
47- { label : 'Middle School' , value : 'Middle School' , cardSearchResultCount : null } ,
48- ] ,
49- } ;
50-
51- const REGULAR_FILTER : DiscoverableFilter = {
52- key : 'subject' ,
53- label : 'Subject' ,
54- operator : FilterOperatorOption . AnyOf ,
55- resultCount : 10 ,
56- } ;
57-
58- function setup ( ) {
59- const mockGetResources = vi . fn ( ) . mockReturnValue ( of ( MOCK_RESOURCES_DATA ) ) ;
60- const mockGetFilterOptions = vi . fn ( ) . mockReturnValue ( of ( { options : [ ] , nextUrl : undefined } ) ) ;
61-
62- TestBed . configureTestingModule ( {
63- providers : [
64- provideOSFCore ( ) ,
65- provideStore ( [ GlobalSearchState ] ) ,
66- {
67- provide : GlobalSearchService ,
68- useValue : {
32+ describe ( 'State: GlobalSearch' , ( ) => {
33+ let store : Store ;
34+ let mockGetResources : Mock ;
35+ let mockGetFilterOptions : Mock ;
36+
37+ beforeEach ( ( ) => {
38+ mockGetResources = vi . fn ( ) . mockReturnValue ( of ( MOCK_RESOURCES_DATA ) ) ;
39+ mockGetFilterOptions = vi . fn ( ) . mockReturnValue ( of ( { options : [ ] , nextUrl : undefined } ) ) ;
40+
41+ TestBed . configureTestingModule ( {
42+ providers : [
43+ provideOSFCore ( ) ,
44+ provideStore ( [ GlobalSearchState ] ) ,
45+ MockProvider ( GlobalSearchService , {
6946 getResources : mockGetResources ,
7047 getFilterOptions : mockGetFilterOptions ,
7148 getResourcesByLink : vi . fn ( ) . mockReturnValue ( EMPTY ) ,
7249 getFilterOptionsFromPaginationUrl : vi . fn ( ) . mockReturnValue ( EMPTY ) ,
73- } ,
74- } ,
75- ] ,
76- } ) ;
50+ } ) ,
51+ ] ,
52+ } ) ;
7753
78- return {
79- store : TestBed . inject ( Store ) ,
80- mockGetResources,
81- mockGetFilterOptions,
82- } ;
83- }
54+ store = TestBed . inject ( Store ) ;
55+ } ) ;
8456
85- describe ( 'GlobalSearchState' , ( ) => {
8657 describe ( 'LoadFilterOptions' , ( ) => {
8758 it ( 'should skip the API call for a CEDAR filter (cedarPropertyIri set)' , ( ) => {
88- const { store, mockGetFilterOptions } = setup ( ) ;
89-
90- store . dispatch ( new SetExtraFilters ( [ CEDAR_FILTER ] ) ) ;
59+ store . dispatch ( new SetExtraFilters ( [ MOCK_CEDAR_FILTER ] ) ) ;
9160 store . dispatch ( new FetchResources ( ) ) ;
92- store . dispatch ( new LoadFilterOptions ( CEDAR_FILTER . key ) ) ;
61+ store . dispatch ( new LoadFilterOptions ( MOCK_CEDAR_FILTER . key ) ) ;
9362
9463 expect ( mockGetFilterOptions ) . not . toHaveBeenCalled ( ) ;
9564 } ) ;
9665
9766 it ( 'should set isLoaded to true for a CEDAR filter when short-circuiting' , ( ) => {
98- const { store } = setup ( ) ;
99-
100- store . dispatch ( new SetExtraFilters ( [ CEDAR_FILTER ] ) ) ;
67+ store . dispatch ( new SetExtraFilters ( [ MOCK_CEDAR_FILTER ] ) ) ;
10168 store . dispatch ( new FetchResources ( ) ) ;
102- store . dispatch ( new LoadFilterOptions ( CEDAR_FILTER . key ) ) ;
69+ store . dispatch ( new LoadFilterOptions ( MOCK_CEDAR_FILTER . key ) ) ;
10370
10471 const filters = store . selectSnapshot ( GlobalSearchSelectors . getFilters ) ;
105- const cedarFilterState = filters . find ( ( f ) => f . key === CEDAR_FILTER . key ) ;
72+ const cedarFilterState = filters . find ( ( f ) => f . key === MOCK_CEDAR_FILTER . key ) ;
10673 expect ( cedarFilterState ?. isLoaded ) . toBe ( true ) ;
10774 } ) ;
10875
10976 it ( 'should call the API for a regular filter' , ( ) => {
110- const { store, mockGetFilterOptions } = setup ( ) ;
111-
11277 store . dispatch ( new FetchResources ( ) ) ;
113- store . dispatch ( new LoadFilterOptions ( REGULAR_FILTER . key ) ) ;
78+ store . dispatch ( new LoadFilterOptions ( MOCK_REGULAR_FILTER . key ) ) ;
11479
11580 expect ( mockGetFilterOptions ) . toHaveBeenCalled ( ) ;
11681 const params = mockGetFilterOptions . mock . calls [ 0 ] [ 0 ] ;
117- expect ( params [ 'valueSearchPropertyPath' ] ) . toBe ( REGULAR_FILTER . key ) ;
82+ expect ( params [ 'valueSearchPropertyPath' ] ) . toBe ( MOCK_REGULAR_FILTER . key ) ;
11883 } ) ;
11984 } ) ;
12085
12186 describe ( 'LoadFilterOptionsAndSetValues' , ( ) => {
12287 it ( 'should not call the API for CEDAR filter keys' , ( ) => {
123- const { store, mockGetFilterOptions } = setup ( ) ;
124- store . dispatch ( new SetExtraFilters ( [ CEDAR_FILTER ] ) ) ;
88+ store . dispatch ( new SetExtraFilters ( [ MOCK_CEDAR_FILTER ] ) ) ;
12589
12690 store . dispatch (
12791 new LoadFilterOptionsAndSetValues ( {
128- [ CEDAR_FILTER . key ] : [ { label : 'High School' , value : 'High School' , cardSearchResultCount : null } ] ,
92+ [ MOCK_CEDAR_FILTER . key ] : [ { label : 'High School' , value : 'High School' , cardSearchResultCount : null } ] ,
12993 } )
13094 ) ;
13195
13296 expect ( mockGetFilterOptions ) . not . toHaveBeenCalled ( ) ;
13397 } ) ;
13498
13599 it ( 'should still set selectedFilterOptions for CEDAR keys' , ( ) => {
136- const { store } = setup ( ) ;
137- store . dispatch ( new SetExtraFilters ( [ CEDAR_FILTER ] ) ) ;
100+ store . dispatch ( new SetExtraFilters ( [ MOCK_CEDAR_FILTER ] ) ) ;
138101
139102 const selectedOption : FilterOption = { label : 'High School' , value : 'High School' , cardSearchResultCount : null } ;
140- store . dispatch ( new LoadFilterOptionsAndSetValues ( { [ CEDAR_FILTER . key ] : [ selectedOption ] } ) ) ;
103+ store . dispatch ( new LoadFilterOptionsAndSetValues ( { [ MOCK_CEDAR_FILTER . key ] : [ selectedOption ] } ) ) ;
141104
142105 const selected = store . selectSnapshot ( GlobalSearchSelectors . getSelectedOptions ) ;
143- expect ( selected [ CEDAR_FILTER . key ] ) . toEqual ( [ selectedOption ] ) ;
106+ expect ( selected [ MOCK_CEDAR_FILTER . key ] ) . toEqual ( [ selectedOption ] ) ;
144107 } ) ;
145108
146109 it ( 'should only call the API for non-CEDAR keys in a mixed payload' , ( ) => {
147- const { store, mockGetFilterOptions } = setup ( ) ;
148- store . dispatch ( new SetExtraFilters ( [ CEDAR_FILTER ] ) ) ;
110+ store . dispatch ( new SetExtraFilters ( [ MOCK_CEDAR_FILTER ] ) ) ;
149111
150112 store . dispatch (
151113 new LoadFilterOptionsAndSetValues ( {
152- [ CEDAR_FILTER . key ] : [ { label : 'High School' , value : 'High School' , cardSearchResultCount : null } ] ,
153- [ REGULAR_FILTER . key ] : [ { label : 'Biology' , value : 'biology' , cardSearchResultCount : 5 } ] ,
114+ [ MOCK_CEDAR_FILTER . key ] : [ { label : 'High School' , value : 'High School' , cardSearchResultCount : null } ] ,
115+ [ MOCK_REGULAR_FILTER . key ] : [ { label : 'Biology' , value : 'biology' , cardSearchResultCount : 5 } ] ,
154116 } )
155117 ) ;
156118
157119 expect ( mockGetFilterOptions ) . toHaveBeenCalledTimes ( 1 ) ;
158120 const params = mockGetFilterOptions . mock . calls [ 0 ] [ 0 ] ;
159- expect ( params [ 'valueSearchPropertyPath' ] ) . toBe ( REGULAR_FILTER . key ) ;
121+ expect ( params [ 'valueSearchPropertyPath' ] ) . toBe ( MOCK_REGULAR_FILTER . key ) ;
160122 } ) ;
161123 } ) ;
162124
163125 describe ( 'FetchResources (CEDAR filter params)' , ( ) => {
164126 it ( 'should add iriShorthand[cedar] when extraFilters are present' , ( ) => {
165- const { store, mockGetResources } = setup ( ) ;
166- store . dispatch ( new SetExtraFilters ( [ CEDAR_FILTER ] ) ) ;
167-
127+ store . dispatch ( new SetExtraFilters ( [ MOCK_CEDAR_FILTER ] ) ) ;
168128 store . dispatch ( new FetchResources ( ) ) ;
169129
170130 const params = mockGetResources . mock . calls [ 0 ] [ 0 ] ;
171131 expect ( params [ 'iriShorthand[cedar]' ] ) . toBe ( 'https://schema.metadatacenter.org/properties/' ) ;
172132 } ) ;
173133
174134 it ( 'should not add iriShorthand[cedar] when no extraFilters are present' , ( ) => {
175- const { store, mockGetResources } = setup ( ) ;
176-
177135 store . dispatch ( new FetchResources ( ) ) ;
178136
179137 const params = mockGetResources . mock . calls [ 0 ] [ 0 ] ;
180138 expect ( params [ 'iriShorthand[cedar]' ] ) . toBeUndefined ( ) ;
181139 } ) ;
182140
183141 it ( 'should use cardSearchText for a selected CEDAR filter value' , ( ) => {
184- const { store, mockGetResources } = setup ( ) ;
185- store . dispatch ( new SetExtraFilters ( [ CEDAR_FILTER ] ) ) ;
186- store . dispatch ( new FetchResources ( ) ) ; // populates state.filters via updateResourcesState
142+ store . dispatch ( new SetExtraFilters ( [ MOCK_CEDAR_FILTER ] ) ) ;
143+ store . dispatch ( new FetchResources ( ) ) ;
187144 mockGetResources . mockClear ( ) ;
188145
189146 store . dispatch (
190147 new LoadFilterOptionsAndSetValues ( {
191- [ CEDAR_FILTER . key ] : [ { label : 'High School' , value : 'High School' , cardSearchResultCount : null } ] ,
148+ [ MOCK_CEDAR_FILTER . key ] : [ { label : 'High School' , value : 'High School' , cardSearchResultCount : null } ] ,
192149 } )
193150 ) ;
194151 store . dispatch ( new FetchResources ( ) ) ;
195152
196153 const params = mockGetResources . mock . calls [ 0 ] [ 0 ] ;
197- expect ( params [ `cardSearchText[osf:hasCedarRecord.cedar:${ CEDAR_FILTER . cedarPropertyIri } ][]` ] ) . toEqual ( [
154+ expect ( params [ `cardSearchText[osf:hasCedarRecord.cedar:${ MOCK_CEDAR_FILTER . cedarPropertyIri } ][]` ] ) . toEqual ( [
198155 '"High School"' ,
199156 ] ) ;
200- expect ( params [ `cardSearchFilter[${ CEDAR_FILTER . key } ][]` ] ) . toBeUndefined ( ) ;
157+ expect ( params [ `cardSearchFilter[${ MOCK_CEDAR_FILTER . key } ][]` ] ) . toBeUndefined ( ) ;
201158 } ) ;
202159
203160 it ( 'should include all selected values for a CEDAR filter' , ( ) => {
204- const { store, mockGetResources } = setup ( ) ;
205- store . dispatch ( new SetExtraFilters ( [ CEDAR_FILTER ] ) ) ;
161+ store . dispatch ( new SetExtraFilters ( [ MOCK_CEDAR_FILTER ] ) ) ;
206162 store . dispatch ( new FetchResources ( ) ) ;
207163 mockGetResources . mockClear ( ) ;
208164
209165 store . dispatch (
210166 new LoadFilterOptionsAndSetValues ( {
211- [ CEDAR_FILTER . key ] : [
167+ [ MOCK_CEDAR_FILTER . key ] : [
212168 { label : 'High School' , value : 'High School' , cardSearchResultCount : null } ,
213169 { label : 'Middle School' , value : 'Middle School' , cardSearchResultCount : null } ,
214170 ] ,
@@ -217,35 +173,31 @@ describe('GlobalSearchState', () => {
217173 store . dispatch ( new FetchResources ( ) ) ;
218174
219175 const params = mockGetResources . mock . calls [ 0 ] [ 0 ] ;
220- expect ( params [ `cardSearchText[osf:hasCedarRecord.cedar:${ CEDAR_FILTER . cedarPropertyIri } ][]` ] ) . toEqual ( [
176+ expect ( params [ `cardSearchText[osf:hasCedarRecord.cedar:${ MOCK_CEDAR_FILTER . cedarPropertyIri } ][]` ] ) . toEqual ( [
221177 '"High School"' ,
222178 '"Middle School"' ,
223179 ] ) ;
224180 } ) ;
225181
226182 it ( 'should use extraFilters as fallback for CEDAR lookup before state.filters is populated' , ( ) => {
227- const { store, mockGetResources } = setup ( ) ;
228- store . dispatch ( new SetExtraFilters ( [ CEDAR_FILTER ] ) ) ;
183+ store . dispatch ( new SetExtraFilters ( [ MOCK_CEDAR_FILTER ] ) ) ;
229184
230185 store . dispatch (
231186 new LoadFilterOptionsAndSetValues ( {
232- [ CEDAR_FILTER . key ] : [ { label : 'High School' , value : 'High School' , cardSearchResultCount : null } ] ,
187+ [ MOCK_CEDAR_FILTER . key ] : [ { label : 'High School' , value : 'High School' , cardSearchResultCount : null } ] ,
233188 } )
234189 ) ;
235- // First FetchResources — state.filters is still empty at this point
236190 store . dispatch ( new FetchResources ( ) ) ;
237191
238192 const params = mockGetResources . mock . calls [ 0 ] [ 0 ] ;
239- expect ( params [ `cardSearchText[osf:hasCedarRecord.cedar:${ CEDAR_FILTER . cedarPropertyIri } ][]` ] ) . toEqual ( [
193+ expect ( params [ `cardSearchText[osf:hasCedarRecord.cedar:${ MOCK_CEDAR_FILTER . cedarPropertyIri } ][]` ] ) . toEqual ( [
240194 '"High School"' ,
241195 ] ) ;
242196 } ) ;
243197 } ) ;
244198
245199 describe ( 'SetDefaultFilterValue' , ( ) => {
246200 it ( 'should include the default filter in the API call' , ( ) => {
247- const { store, mockGetResources } = setup ( ) ;
248-
249201 store . dispatch ( new SetDefaultFilterValue ( 'defaultKey' , 'default-value' ) ) ;
250202 store . dispatch ( new FetchResources ( ) ) ;
251203
@@ -254,8 +206,6 @@ describe('GlobalSearchState', () => {
254206 } ) ;
255207
256208 it ( 'should not be overridden when a selected filter for the same key is cleared' , ( ) => {
257- const { store, mockGetResources } = setup ( ) ;
258-
259209 store . dispatch ( new SetDefaultFilterValue ( 'defaultKey' , 'default-value' ) ) ;
260210 store . dispatch ( new UpdateSelectedFilterOption ( 'defaultKey' , [ ] ) ) ;
261211 store . dispatch ( new FetchResources ( ) ) ;
@@ -266,8 +216,6 @@ describe('GlobalSearchState', () => {
266216 } ) ;
267217
268218 it ( 'should AND the default value with an any-of clause for an explicitly selected value' , ( ) => {
269- const { store, mockGetResources } = setup ( ) ;
270-
271219 store . dispatch ( new SetDefaultFilterValue ( 'defaultKey' , 'default-value' ) ) ;
272220 store . dispatch (
273221 new UpdateSelectedFilterOption ( 'defaultKey' , [
@@ -282,8 +230,6 @@ describe('GlobalSearchState', () => {
282230 } ) ;
283231
284232 it ( 'should OR multiple selected values together via a single any-of clause' , ( ) => {
285- const { store, mockGetResources } = setup ( ) ;
286-
287233 store . dispatch ( new SetDefaultFilterValue ( 'defaultKey' , 'default-value' ) ) ;
288234 store . dispatch (
289235 new UpdateSelectedFilterOption ( 'defaultKey' , [
0 commit comments