Skip to content

Commit 38704b9

Browse files
committed
fix(models): fixed issues and updated tests
1 parent ce6b97c commit 38704b9

8 files changed

Lines changed: 92 additions & 124 deletions

File tree

src/app/features/collections/components/add-to-collection/collection-metadata-step/collection-metadata-step.component.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { CollectionSubmissionReviewState } from '@osf/shared/enums/collection-su
1414
import {
1515
CollectionProjectSubmission,
1616
CollectionSubmissionWithGuid,
17-
} from '@osf/shared/models/collections/collections.model';
17+
} from '@osf/shared/models/collections/collection-submissions.model';
1818
import { CollectionsSelectors, GetCollectionDetails } from '@osf/shared/stores/collections';
1919

2020
import {

src/app/shared/models/collections/collection-details-json-api.model.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ResourceDataLinksJsonApi } from '../common/json-api/links.model';
1+
import { ResourceLinksJsonApi } from '../common/json-api/links.model';
22
import { JsonApiResource } from '../common/json-api/resource.model';
33
import { ItemResponse, ListResponse } from '../common/json-api/responses.model';
44

@@ -10,7 +10,7 @@ export interface CollectionDetailsDataJsonApi extends JsonApiResource<
1010
'collections',
1111
CollectionDetailsAttributesJsonApi
1212
> {
13-
links?: Pick<ResourceDataLinksJsonApi, 'iri'>;
13+
links?: Pick<ResourceLinksJsonApi, 'iri'>;
1414
}
1515
export type SparseCollectionDataJsonApi = JsonApiResource<'collections', SparseCollectionAttributesJsonApi>;
1616

src/app/shared/models/collections/collection-provider-json-api.model.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { CedarMetadataDataTemplateJsonApi } from '@osf/features/metadata/models/
22

33
import { BrandDataJsonApi } from '../brand/brand.json-api.model';
44
import { Embed } from '../common/json-api/embeds.model';
5-
import { ResourceDataLinksJsonApi } from '../common/json-api/links.model';
5+
import { ResourceLinksJsonApi } from '../common/json-api/links.model';
66
import { ToOneRel } from '../common/json-api/relationships.model';
77
import { JsonApiResource } from '../common/json-api/resource.model';
88
import { ItemResponse } from '../common/json-api/responses.model';
@@ -16,7 +16,7 @@ export interface CollectionProviderDataJsonApi extends JsonApiResource<
1616
> {
1717
embeds: CollectionProviderEmbedsJsonApi;
1818
relationships: CollectionProviderRelationshipsJsonApi;
19-
links?: Pick<ResourceDataLinksJsonApi, 'iri'>;
19+
links?: Pick<ResourceLinksJsonApi, 'iri'>;
2020
}
2121

2222
interface CollectionProviderEmbedsJsonApi {

src/app/shared/models/common/json-api/links.model.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,3 @@
1-
export interface ResourceDataLinksJsonApi {
2-
html?: string;
3-
self: string;
4-
iri?: string;
5-
download?: string;
6-
delete?: string;
7-
}
8-
91
export interface ResourceLinksJsonApi {
102
html: string;
113
self: string;

src/app/shared/models/pagination-links.model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ export interface PaginationLinksModel {
44
prev?: LinkModel;
55
}
66

7-
export interface LinkModel {
7+
interface LinkModel {
88
href: string;
99
}

src/app/shared/stores/global-search/global-search.state.spec.ts

Lines changed: 56 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
import { provideStore, Store } from '@ngxs/store';
22

3+
import { MockProvider } from 'ng-mocks';
4+
35
import { EMPTY, of } from 'rxjs';
46

5-
import { vi } from 'vitest';
7+
import { Mock, vi } from 'vitest';
68

79
import { 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';
1412
import { 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';
1719
import { provideOSFCore } from '@testing/osf.testing.provider';
1820

1921
import {
@@ -27,188 +29,142 @@ import {
2729
import { GlobalSearchSelectors } from './global-search.selectors';
2830
import { 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', [

src/testing/data/collections/cedar-metadata.mock.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const MOCK_CEDAR_TEMPLATE: CedarMetadataDataTemplateJsonApi = {
66
id: 'template-1',
77
type: 'cedar-metadata-templates',
88
attributes: {
9+
active: true,
910
schema_name: 'Test Template',
1011
cedar_id: 'cedar-1',
1112
template: {

0 commit comments

Comments
 (0)