1- import { ComponentFixture , TestBed } from '@angular/core/testing' ;
2-
3- import { LuckySearchComponent } from './lucky-search.component' ;
4- import { LuckySearchService } from '../lucky-search.service' ;
5- import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service' ;
6- import { Router , UrlTree } from '@angular/router' ;
7- import { createSuccessfulRemoteDataObject , createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils' ;
8- import { createPaginatedList } from '../../shared/testing/utils.test' ;
9- import { Item } from '../../core/shared/item.model' ;
10- import { of as observableOf } from 'rxjs' ;
11- import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model' ;
12- import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model' ;
13- import { SortDirection , SortOptions } from '../../core/cache/models/sort-options.model' ;
14- import { TranslateModule } from '@ngx-translate/core' ;
15- import { By } from '@angular/platform-browser' ;
16- import { SearchResult } from '../../shared/search/models/search-result.model' ;
17- import { DSpaceObject } from '../../core/shared/dspace-object.model' ;
18- import { BitstreamDataService , MetadataFilter } from '../../core/data/bitstream-data.service' ;
19- import { Bitstream } from '../../core/shared/bitstream.model' ;
20- import { RouterMock } from '../../shared/mocks/router.mock' ;
21- import { MetadataMap , MetadataValue } from '../../core/shared/metadata.models' ;
22- import { FileSizePipe } from '../../shared/utils/file-size-pipe' ;
23-
24- describe ( 'SearchComponent' , ( ) => {
1+ import { ComponentFixture , TestBed } from '@angular/core/testing' ;
2+
3+ import { LuckySearchComponent } from './lucky-search.component' ;
4+ import { LuckySearchService } from '../lucky-search.service' ;
5+ import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service' ;
6+ import { Router , UrlTree } from '@angular/router' ;
7+ import { createSuccessfulRemoteDataObject , createSuccessfulRemoteDataObject$ } from '../../shared/remote-data.utils' ;
8+ import { createPaginatedList } from '../../shared/testing/utils.test' ;
9+ import { Item } from '../../core/shared/item.model' ;
10+ import { of as observableOf } from 'rxjs' ;
11+ import { PaginatedSearchOptions } from '../../shared/search/models/paginated-search-options.model' ;
12+ import { PaginationComponentOptions } from '../../shared/pagination/pagination-component-options.model' ;
13+ import { SortDirection , SortOptions } from '../../core/cache/models/sort-options.model' ;
14+ import { TranslateModule } from '@ngx-translate/core' ;
15+ import { By } from '@angular/platform-browser' ;
16+ import { SearchResult } from '../../shared/search/models/search-result.model' ;
17+ import { DSpaceObject } from '../../core/shared/dspace-object.model' ;
18+ import { BitstreamDataService , MetadataFilter } from '../../core/data/bitstream-data.service' ;
19+ import { Bitstream } from '../../core/shared/bitstream.model' ;
20+ import { RouterMock } from '../../shared/mocks/router.mock' ;
21+ import { MetadataMap , MetadataValue } from '../../core/shared/metadata.models' ;
22+ import { FileSizePipe } from '../../shared/utils/file-size-pipe' ;
23+ import { HardRedirectService } from '../../core/services/hard-redirect.service' ;
24+ import { getBitstreamDownloadRoute } from '../../app-routing-paths' ;
25+ import { PLATFORM_ID } from '@angular/core' ;
26+
27+ describe ( 'LuckySearchComponent' , ( ) => {
2528 let fixture : ComponentFixture < LuckySearchComponent > ;
29+ const defaultPagination : PaginatedSearchOptions = Object . assign ( {
30+ id : 'test-pg-id' ,
31+ pageSize : 10 ,
32+ currentPage : 1
33+ } ) ;
34+
35+ const hardRedirectService = jasmine . createSpyObj ( 'hardRedirectService' , [ 'redirect' ] ) ;
36+
2637 const collection1 = Object . assign ( new Item ( ) , {
2738 uuid : 'item-uuid-1' ,
2839 name : 'Test item 1'
@@ -66,6 +77,16 @@ describe('SearchComponent', () => {
6677 'value' : 'test'
6778 } ;
6879 const routerStub = new RouterMock ( ) ;
80+
81+ const bitstreamMetadata = {
82+ 'dc.title' : [ { value : 'test.pdf' } as MetadataValue ] ,
83+ 'dc.description' : [ { value : 'TestDescription' } as MetadataValue ]
84+ } as MetadataMap ;
85+ const bitstream = Object . assign (
86+ new Bitstream ( ) ,
87+ { _name : 'test.pdf' , sizeBytes : 15 , uuid : 'fa272dbf-e458-4ad2-868b-b4a27c6eac15' , metadata : bitstreamMetadata }
88+ ) as Bitstream ;
89+
6990 beforeEach ( async ( ) => {
7091 await TestBed . configureTestingModule ( {
7192 declarations : [ LuckySearchComponent , FileSizePipe ] ,
@@ -74,7 +95,9 @@ describe('SearchComponent', () => {
7495 { provide : Router , useValue : routerStub } ,
7596 { provide : SearchConfigurationService , useValue : searchConfigServiceStub } ,
7697 { provide : LuckySearchService , useValue : searchServiceStub } ,
77- { provide : BitstreamDataService , useValue : bitstreamDataService }
98+ { provide : BitstreamDataService , useValue : bitstreamDataService } ,
99+ { provide : HardRedirectService , useValue : hardRedirectService } ,
100+ { provide : PLATFORM_ID , useValue : 'browser' } ,
78101 ] ,
79102 } )
80103 . compileComponents ( ) ;
@@ -87,24 +110,6 @@ describe('SearchComponent', () => {
87110 } ) ;
88111
89112 describe ( 'should search items' , ( ) => {
90-
91- beforeEach ( ( ) => {
92- spyOn ( routerStub , 'parseUrl' ) . and . returnValue ( urlTree ) ;
93- } ) ;
94-
95- it ( 'should create' , ( ) => {
96- expect ( component ) . toBeTruthy ( ) ;
97- } ) ;
98-
99- it ( 'should show multiple results' , ( ) => {
100- expect ( component . showMultipleSearchSection ) . toEqual ( true ) ;
101- } ) ;
102-
103- it ( 'should display basic search form results' , ( ) => {
104- expect ( fixture . debugElement . query ( By . css ( 'ds-search-results' ) ) )
105- . toBeTruthy ( ) ;
106- } ) ;
107-
108113 beforeEach ( ( ) => {
109114 fixture = TestBed . createComponent ( LuckySearchComponent ) ;
110115 component = fixture . componentInstance ;
@@ -121,46 +126,44 @@ describe('SearchComponent', () => {
121126 } )
122127 } ) ;
123128
129+ const secondSearchResult = Object . assign ( new SearchResult ( ) , {
130+ indexableObject : Object . assign ( new DSpaceObject ( ) , {
131+ id : 'd317835d-7b06-4219-91e2-26565' ,
132+ uuid : 'd317835d-7b06-4219-91e2-26565' ,
133+ name : 'publication' ,
134+ metadata : {
135+ 'dspace.entity.type' : [
136+ { value : 'Publication' }
137+ ]
138+ }
139+ } )
140+ } ) ;
141+ spyOn ( routerStub , 'parseUrl' ) . and . returnValue ( urlTree ) ;
124142 const data = createSuccessfulRemoteDataObject ( createPaginatedList ( [
125- firstSearchResult
143+ firstSearchResult , secondSearchResult
126144 ] ) ) ;
127- component . resultsRD$ . next ( data as any ) ;
128- fixture . detectChanges ( ) ;
129- } ) ;
130145
131- it ( 'should call navigate or router' , ( ) => {
132- expect ( routerStub . navigateByUrl ) . toHaveBeenCalled ( ) ;
133- } ) ;
134-
135- beforeEach ( ( ) => {
136- fixture = TestBed . createComponent ( LuckySearchComponent ) ;
137- component = fixture . componentInstance ;
138- const data = createSuccessfulRemoteDataObject ( createPaginatedList ( [ ] ) ) ;
139- component . resultsRD$ . next ( data as any ) ;
146+ component . resultsRD$ . next ( data ) ;
140147 fixture . detectChanges ( ) ;
141148 } ) ;
142149
143- it ( 'should not have results ' , ( ) => {
144- expect ( component . showEmptySearchSection ) . toEqual ( true ) ;
150+ it ( 'should create ' , ( ) => {
151+ expect ( component ) . toBeTruthy ( ) ;
145152 } ) ;
146153
147- it ( 'should display basic search form' , ( ) => {
148- expect ( fixture . debugElement . query ( By . css ( 'ds-search-form ' ) ) )
154+ it ( 'should display basic search form results ' , ( ) => {
155+ expect ( fixture . debugElement . query ( By . css ( 'ds-search-results ' ) ) )
149156 . toBeTruthy ( ) ;
150157 } ) ;
158+
159+ it ( 'should call router.navigateByUrl when platform is browser' , ( ) => {
160+ component . redirect ( 'test-url' ) ;
161+ expect ( routerStub . navigateByUrl ) . toHaveBeenCalledWith ( 'test-url' , { replaceUrl : true } ) ;
162+ } ) ;
151163 } ) ;
152164
153165 describe ( 'should search bitstreams' , ( ) => {
154166
155- const bitstreamMetadata = {
156- 'dc.title' : [ { value : 'test.pdf' } as MetadataValue ] ,
157- 'dc.description' : [ { value : 'TestDescription' } as MetadataValue ]
158- } as MetadataMap ;
159- const bitstream = Object . assign (
160- new Bitstream ( ) ,
161- { _name : 'test.pdf' , sizeBytes : 15 , uuid : 'fa272dbf-e458-4ad2-868b-b4a27c6eac15' , metadata : bitstreamMetadata }
162- ) as Bitstream ;
163-
164167 beforeEach ( ( ) => {
165168 fixture = TestBed . createComponent ( LuckySearchComponent ) ;
166169 component = fixture . componentInstance ;
@@ -174,39 +177,40 @@ describe('SearchComponent', () => {
174177 } ;
175178
176179 const itemUUID = 'd317835d-7b06-4219-91e2-1191900cb897' ;
177- const firstSearchResult = Object . assign ( new SearchResult ( ) , {
180+ const searchResult = Object . assign ( new SearchResult ( ) , {
178181 indexableObject : Object . assign ( new DSpaceObject ( ) , {
179- id : 'd317835d-7b06-4219-91e2-1191900cb897 ' ,
182+ id : 'd317835d-7b06-4219-91e2-12222 ' ,
180183 uuid : itemUUID ,
181184 name : 'My first publication' ,
182185 metadata : {
183186 'dspace.entity.type' : [
184- { value : 'Publication' }
187+ { value : 'Publication' }
185188 ]
186189 }
187190 } )
188191 } ) ;
189- const data = createSuccessfulRemoteDataObject ( createPaginatedList ( [ firstSearchResult ] ) ) ;
190- const metadataFilters = [ { metadataName : 'dc.title' , metadataValue : 'test .pdf' } ] as MetadataFilter [ ] ;
192+ const data = createSuccessfulRemoteDataObject ( createPaginatedList ( [ searchResult ] ) ) ;
193+ const metadataFilters = [ { metadataName : 'dc.title' , metadataValue : 'title .pdf' } ] as MetadataFilter [ ] ;
191194 component . bitstreamFilters$ . next ( metadataFilters ) ;
192195 bitstreamDataService . findByItem . withArgs ( itemUUID , 'ORIGINAL' , metadataFilters , { } )
193196 . and . returnValue ( createSuccessfulRemoteDataObject$ ( createPaginatedList ( [ bitstream ] ) ) ) ;
194197
198+ component . currentFilter = { identifier : 'test' , value : 'test' } ;
199+ component . searchOptions$ = observableOf ( defaultPagination ) ;
200+
201+ spyOn ( ( component as any ) , 'getLuckySearchResults' ) . and . returnValue ( observableOf ( data ) ) ;
202+ spyOn ( ( component as any ) , 'loadBitstreamsAndRedirectIfNeeded' ) . and . returnValue ( observableOf ( [ bitstream ] ) ) ;
203+ spyOn ( ( component as any ) , 'hasBitstreamFilters' ) . and . returnValue ( true ) ;
195204 spyOn ( component , 'redirect' ) ;
196- spyOn ( component . bitstreams$ , 'next' ) . and . callThrough ( ) ;
197205 spyOn ( routerStub , 'parseUrl' ) . and . returnValue ( bitstreamSearchTree ) ;
198206
199- component . resultsRD$ . next ( data as any ) ;
207+ component . resultsRD$ . next ( data ) ;
200208
201209 fixture . detectChanges ( ) ;
202210 } ) ;
203211
204- it ( 'should load item bitstreams' , ( ) => {
205- expect ( component . bitstreams$ . next ) . toHaveBeenCalledWith ( [ bitstream ] ) ;
206- } ) ;
207-
208- it ( 'should redirect to bitstream' , ( ) => {
209- expect ( component . redirect ) . toHaveBeenCalledWith ( `/bitstreams/${ bitstream . uuid } /download` ) ;
212+ it ( 'should redirect to bitstream download route when only one bitstream is found' , ( ) => {
213+ expect ( component . redirect ) . toHaveBeenCalledWith ( getBitstreamDownloadRoute ( bitstream ) ) ;
210214 } ) ;
211215
212216 it ( 'should return bitstream filename' , ( ) => {
@@ -221,4 +225,96 @@ describe('SearchComponent', () => {
221225 expect ( component . getSize ( bitstream ) ) . toEqual ( 15 ) ;
222226 } ) ;
223227 } ) ;
228+
229+ describe ( 'one item is available' , ( ) => {
230+ beforeEach ( ( ) => {
231+ fixture = TestBed . createComponent ( LuckySearchComponent ) ;
232+ component = fixture . componentInstance ;
233+
234+ const bitstreamSearchTree = new UrlTree ( ) ;
235+ bitstreamSearchTree . queryParams = {
236+ index : 'testIndex' ,
237+ value : 'testValue' ,
238+ bitstreamMetadata : 'testMetadata' ,
239+ bitstreamValue : 'testMetadataValue'
240+ } ;
241+
242+ const itemUUID = 'd317835d-7b06-4219-91e2-1191900cb897' ;
243+ const firstSearchResult = Object . assign ( new SearchResult ( ) , {
244+ indexableObject : Object . assign ( new DSpaceObject ( ) , {
245+ id : 'd317835d-7b06-4219-91e2-1191900cb897' ,
246+ uuid : itemUUID ,
247+ name : 'My first publication' ,
248+ metadata : {
249+ 'dspace.entity.type' : [
250+ { value : 'Publication' }
251+ ]
252+ }
253+ } )
254+ } ) ;
255+ const data = createSuccessfulRemoteDataObject ( createPaginatedList ( [ firstSearchResult ] ) ) ;
256+ const metadataFilters = [ { metadataName : 'dc.title' , metadataValue : 'test.pdf' } ] as MetadataFilter [ ] ;
257+ component . bitstreamFilters$ . next ( metadataFilters ) ;
258+ bitstreamDataService . findByItem . withArgs ( itemUUID , 'ORIGINAL' , metadataFilters , { } )
259+ . and . returnValue ( createSuccessfulRemoteDataObject$ ( createPaginatedList ( [ bitstream ] ) ) ) ;
260+
261+ component . currentFilter = { identifier : 'test' , value : 'test' } ;
262+ component . searchOptions$ = observableOf ( defaultPagination ) ;
263+
264+ spyOn ( ( component as any ) , 'getLuckySearchResults' ) . and . returnValue ( observableOf ( data ) ) ;
265+ spyOn ( ( component as any ) , 'loadBitstreamsAndRedirectIfNeeded' ) . and . returnValue ( observableOf ( [ bitstream ] ) ) ;
266+ spyOn ( ( component as any ) , 'hasBitstreamFilters' ) . and . returnValue ( true ) ;
267+ spyOn ( component , 'redirect' ) ;
268+ spyOn ( routerStub , 'parseUrl' ) . and . returnValue ( bitstreamSearchTree ) ;
269+
270+ component . resultsRD$ . next ( data ) ;
271+
272+ fixture . detectChanges ( ) ;
273+ } ) ;
274+
275+ it ( 'should create' , ( ) => {
276+ expect ( component ) . toBeTruthy ( ) ;
277+ } ) ;
278+
279+ it ( 'should redirect to item page when only one result is found' , ( ) => {
280+ expect ( component . redirect ) . toHaveBeenCalled ( ) ;
281+ } ) ;
282+ } ) ;
283+
284+ it ( 'should not redirect when no bitstreams are found' , ( ) => {
285+ const item = Object . assign ( new Item ( ) , { uuid : 'item-uuid-1' , name : 'Test item 1' } ) ;
286+ const data = createSuccessfulRemoteDataObject ( createPaginatedList ( [
287+ { indexableObject : item , hitHighlights : { } }
288+ ] ) ) as any ;
289+ component . resultsRD$ . next ( data ) ;
290+ component . bitstreamFilters$ . next ( [ { metadataName : 'dc.title' , metadataValue : 'Non-existent bitstream' } ] ) ;
291+ bitstreamDataService . findByItem . and . returnValue ( createSuccessfulRemoteDataObject$ ( createPaginatedList ( [ ] ) ) ) ;
292+ spyOn ( component , 'redirect' ) ;
293+ fixture . detectChanges ( ) ;
294+ expect ( component . redirect ) . not . toHaveBeenCalled ( ) ;
295+ } ) ;
296+
297+ it ( 'should update showEmptySearchSection$ and showMultipleSearchSection$ based on search results' , ( ) => {
298+ const emptyResults = createSuccessfulRemoteDataObject ( createPaginatedList ( [ ] ) ) ;
299+ const multipleResults = createSuccessfulRemoteDataObject ( createPaginatedList ( [
300+ new SearchResult < DSpaceObject > ( ) ,
301+ new SearchResult < DSpaceObject > ( )
302+ ] ) ) ;
303+
304+ spyOn ( component as any , 'getLuckySearchResults' ) . and . returnValue ( observableOf ( emptyResults ) ) ;
305+ spyOn ( component as any , 'processSearchResults' ) . and . returnValue ( observableOf ( emptyResults ) ) ;
306+
307+ component . getSearchResults ( ) ;
308+
309+ expect ( component . showEmptySearchSection$ . getValue ( ) ) . toBe ( true ) ;
310+ expect ( component . showMultipleSearchSection$ . getValue ( ) ) . toBe ( false ) ;
311+
312+ ( component as any ) . getLuckySearchResults . and . returnValue ( observableOf ( multipleResults ) ) ;
313+ ( component as any ) . processSearchResults . and . returnValue ( observableOf ( multipleResults ) ) ;
314+
315+ component . getSearchResults ( ) ;
316+
317+ expect ( component . showEmptySearchSection$ . getValue ( ) ) . toBe ( false ) ;
318+ expect ( component . showMultipleSearchSection$ . getValue ( ) ) . toBe ( true ) ;
319+ } ) ;
224320} ) ;
0 commit comments