Skip to content

Commit a65f248

Browse files
authored
Merge pull request DSpace#2651 from alexandrevryghem/theme-fixes_contribute-main
Fixed ItemSearchResultListElementComponent not fully themable
2 parents 476e5a5 + da320b5 commit a65f248

5 files changed

Lines changed: 130 additions & 60 deletions

File tree

src/app/shared/object-collection/shared/listable-object/listable-object-component-loader.component.spec.ts

Lines changed: 42 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
import {
2-
ChangeDetectionStrategy,
3-
NO_ERRORS_SCHEMA,
4-
} from '@angular/core';
1+
import { ChangeDetectionStrategy } from '@angular/core';
52
import {
63
ComponentFixture,
74
fakeAsync,
@@ -11,29 +8,31 @@ import {
118
} from '@angular/core/testing';
129
import { By } from '@angular/platform-browser';
1310
import { ActivatedRoute } from '@angular/router';
14-
import { provideMockStore } from '@ngrx/store/testing';
1511
import { TranslateModule } from '@ngx-translate/core';
16-
import { of } from 'rxjs';
17-
import { AuthRequestService } from 'src/app/core/auth/auth-request.service';
18-
import { CookieService } from 'src/app/core/services/cookie.service';
19-
import { HardRedirectService } from 'src/app/core/services/hard-redirect.service';
20-
import { XSRFService } from 'src/app/core/xsrf/xsrf.service';
21-
import { CookieServiceMock } from 'src/app/shared/mocks/cookie.service.mock';
22-
import { getMockThemeService } from 'src/app/shared/mocks/theme-service.mock';
23-
import { AuthRequestServiceStub } from 'src/app/shared/testing/auth-request-service.stub';
2412

25-
import {
26-
APP_CONFIG,
27-
APP_DATA_SERVICES_MAP,
28-
} from '../../../../../config/app-config.interface';
29-
import { REQUEST } from '../../../../../express.tokens';
13+
import { APP_CONFIG } from '../../../../../config/app-config.interface';
14+
import { environment } from '../../../../../environments/environment.test';
15+
import { AuthService } from '../../../../core/auth/auth.service';
16+
import { DSONameService } from '../../../../core/breadcrumbs/dso-name.service';
17+
import { AuthorizationDataService } from '../../../../core/data/feature-authorization/authorization-data.service';
3018
import { Context } from '../../../../core/shared/context.model';
19+
import { FileService } from '../../../../core/shared/file.service';
3120
import { GenericConstructor } from '../../../../core/shared/generic-constructor';
3221
import { ListableModule } from '../../../../core/shared/listable.module';
3322
import { ViewMode } from '../../../../core/shared/view-mode.model';
23+
import { XSRFService } from '../../../../core/xsrf/xsrf.service';
3424
import { DynamicComponentLoaderDirective } from '../../../abstract-component-loader/dynamic-component-loader.directive';
25+
import { DSONameServiceMock } from '../../../mocks/dso-name.service.mock';
26+
import { getMockThemeService } from '../../../mocks/theme-service.mock';
3527
import { ItemListElementComponent } from '../../../object-list/item-list-element/item-types/item/item-list-element.component';
28+
import { SearchResultListElementComponent } from '../../../object-list/search-result-list-element/search-result-list-element.component';
29+
import { ActivatedRouteStub } from '../../../testing/active-router.stub';
30+
import { AuthServiceStub } from '../../../testing/auth-service.stub';
31+
import { AuthorizationDataServiceStub } from '../../../testing/authorization-service.stub';
32+
import { FileServiceStub } from '../../../testing/file-service.stub';
33+
import { TruncatableServiceStub } from '../../../testing/truncatable-service.stub';
3634
import { ThemeService } from '../../../theme-support/theme.service';
35+
import { TruncatableService } from '../../../truncatable/truncatable.service';
3736
import { ListableObject } from '../listable-object.model';
3837
import { ListableObjectComponentLoaderComponent } from './listable-object-component-loader.component';
3938

@@ -57,30 +56,39 @@ describe('ListableObjectComponentLoaderComponent', () => {
5756
let comp: ListableObjectComponentLoaderComponent;
5857
let fixture: ComponentFixture<ListableObjectComponentLoaderComponent>;
5958

59+
let activatedRoute: ActivatedRouteStub;
60+
let authService: AuthServiceStub;
61+
let authorizationService: AuthorizationDataServiceStub;
62+
let fileService: FileServiceStub;
63+
let themeService: ThemeService;
64+
let truncatableService: TruncatableServiceStub;
65+
6066
beforeEach(waitForAsync(() => {
61-
TestBed.configureTestingModule({
67+
activatedRoute = new ActivatedRouteStub();
68+
authService = new AuthServiceStub();
69+
authorizationService = new AuthorizationDataServiceStub();
70+
fileService = new FileServiceStub();
71+
themeService = getMockThemeService();
72+
truncatableService = new TruncatableServiceStub();
73+
74+
void TestBed.configureTestingModule({
6275
imports: [
6376
TranslateModule.forRoot(),
6477
ListableObjectComponentLoaderComponent,
6578
ListableModule,
6679
ItemListElementComponent,
6780
DynamicComponentLoaderDirective,
6881
],
69-
schemas: [NO_ERRORS_SCHEMA],
7082
providers: [
71-
{ provide: HardRedirectService, useValue: jasmine.createSpyObj('hardRedirectService', ['redirect']) },
72-
{ provide: AuthRequestService, useValue: new AuthRequestServiceStub() },
73-
{ provide: CookieService, useValue: new CookieServiceMock() },
83+
{ provide: APP_CONFIG, useValue: environment },
84+
{ provide: ActivatedRoute, useValue: activatedRoute },
85+
{ provide: AuthService, useValue: authService },
86+
{ provide: AuthorizationDataService, useValue: authorizationService },
87+
{ provide: DSONameService, useValue: new DSONameServiceMock() },
88+
{ provide: FileService, useValue: fileService },
89+
{ provide: ThemeService, useValue: themeService },
90+
{ provide: TruncatableService, useValue: truncatableService },
7491
{ provide: XSRFService, useValue: {} },
75-
{ provide: REQUEST, useValue: {} },
76-
{
77-
provide: ActivatedRoute,
78-
useValue: { data: of({ dso: { payload: {} } }), params: of({}) },
79-
},
80-
provideMockStore({}),
81-
{ provide: ThemeService, useValue: getMockThemeService('dspace') },
82-
{ provide: APP_CONFIG, useValue: { browseBy: { showThumbnails: true } } },
83-
{ provide: APP_DATA_SERVICES_MAP, useValue: {} },
8492
],
8593
}).overrideComponent(ListableObjectComponentLoaderComponent, {
8694
set: {
@@ -95,7 +103,7 @@ describe('ListableObjectComponentLoaderComponent', () => {
95103
comp.object = new TestType();
96104
comp.viewMode = testViewMode;
97105
comp.context = testContext;
98-
spyOn(comp, 'getComponent').and.returnValue(ItemListElementComponent as any);
106+
spyOn(comp, 'getComponent').and.returnValue(SearchResultListElementComponent as any);
99107
spyOn(comp as any, 'connectInputsAndOutputs').and.callThrough();
100108
fixture.detectChanges();
101109

@@ -119,7 +127,7 @@ describe('ListableObjectComponentLoaderComponent', () => {
119127
spyOn(comp, 'instantiateComponent').and.returnValue(null);
120128
spyOn(comp.contentChange, 'emit').and.returnValue(null);
121129

122-
listableComponent = fixture.debugElement.query(By.css('ds-item-list-element')).componentInstance;
130+
listableComponent = fixture.debugElement.query(By.css('ds-search-result-list-element')).componentInstance;
123131
reloadedObject = 'object';
124132
});
125133

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
<ds-item-search-result-list-element [showLabel]="showLabel" [object]="{ indexableObject: object, hitHighlights: {} }" [linkType]="linkType"></ds-item-search-result-list-element>
1+
<ds-listable-object-component-loader
2+
[object]="itemSearchResult"
3+
[viewMode]="viewMode"
4+
[linkType]="linkType">
5+
</ds-listable-object-component-loader>

src/app/shared/object-list/item-list-element/item-types/item/item-list-element.component.spec.ts

Lines changed: 37 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
1+
import { ChangeDetectionStrategy } from '@angular/core';
12
import {
2-
ChangeDetectionStrategy,
3-
NO_ERRORS_SCHEMA,
4-
} from '@angular/core';
5-
import {
3+
ComponentFixture,
64
TestBed,
75
waitForAsync,
86
} from '@angular/core/testing';
97
import { By } from '@angular/platform-browser';
108
import { ActivatedRoute } from '@angular/router';
119
import { TranslateModule } from '@ngx-translate/core';
1210
import { of as observableOf } from 'rxjs';
13-
import { APP_CONFIG } from 'src/config/app-config.interface';
14-
import { environment } from 'src/environments/environment.test';
1511

12+
import { APP_CONFIG } from '../../../../../../config/app-config.interface';
13+
import { environment } from '../../../../../../environments/environment.test';
1614
import { AuthService } from '../../../../../core/auth/auth.service';
1715
import { DSONameService } from '../../../../../core/breadcrumbs/dso-name.service';
1816
import { AuthorizationDataService } from '../../../../../core/data/feature-authorization/authorization-data.service';
1917
import { Item } from '../../../../../core/shared/item.model';
2018
import { XSRFService } from '../../../../../core/xsrf/xsrf.service';
21-
import { AuthServiceMock } from '../../../../../shared/mocks/auth.service.mock';
22-
import { mockTruncatableService } from '../../../../../shared/mocks/mock-trucatable.service';
23-
import { getMockThemeService } from '../../../../../shared/mocks/theme-service.mock';
24-
import { ActivatedRouteStub } from '../../../../../shared/testing/active-router.stub';
25-
import { ThemeService } from '../../../../../shared/theme-support/theme.service';
2619
import { DSONameServiceMock } from '../../../../mocks/dso-name.service.mock';
20+
import { getMockThemeService } from '../../../../mocks/theme-service.mock';
21+
import { ActivatedRouteStub } from '../../../../testing/active-router.stub';
22+
import { AuthServiceStub } from '../../../../testing/auth-service.stub';
23+
import { AuthorizationDataServiceStub } from '../../../../testing/authorization-service.stub';
24+
import { TruncatableServiceStub } from '../../../../testing/truncatable-service.stub';
25+
import { ThemeService } from '../../../../theme-support/theme.service';
2726
import { TruncatableService } from '../../../../truncatable/truncatable.service';
2827
import { TruncatePipe } from '../../../../utils/truncate.pipe';
2928
import { ItemListElementComponent } from './item-list-element.component';
@@ -65,23 +64,39 @@ const mockItem: Item = Object.assign(new Item(), {
6564
});
6665

6766
describe('ItemListElementComponent', () => {
68-
let comp;
69-
let fixture;
67+
let comp: ItemListElementComponent;
68+
let fixture: ComponentFixture<ItemListElementComponent>;
69+
70+
let activatedRoute: ActivatedRouteStub;
71+
let authService: AuthServiceStub;
72+
let authorizationService: AuthorizationDataServiceStub;
73+
let themeService: ThemeService;
74+
let truncatableService: TruncatableServiceStub;
7075

7176
beforeEach(waitForAsync(() => {
72-
TestBed.configureTestingModule({
73-
imports: [TruncatePipe, TranslateModule.forRoot(), ItemListElementComponent],
77+
activatedRoute = new ActivatedRouteStub();
78+
authService = new AuthServiceStub();
79+
authorizationService = new AuthorizationDataServiceStub();
80+
themeService = getMockThemeService();
81+
truncatableService = new TruncatableServiceStub();
82+
83+
void TestBed.configureTestingModule({
84+
imports: [
85+
TranslateModule.forRoot(),
86+
TruncatePipe,
87+
],
88+
declarations: [
89+
],
7490
providers: [
7591
{ provide: DSONameService, useValue: new DSONameServiceMock() },
76-
{ provide: TruncatableService, useValue: mockTruncatableService },
7792
{ provide: APP_CONFIG, useValue: environment },
78-
{ provide: ThemeService, useValue: getMockThemeService() },
79-
{ provide: ActivatedRoute, useValue: new ActivatedRouteStub() },
80-
{ provide: AuthService, useValue: new AuthServiceMock() },
81-
{ provide: AuthorizationDataService, useValue: {} },
93+
{ provide: ActivatedRoute, useValue: activatedRoute },
94+
{ provide: AuthService, useValue: authService },
95+
{ provide: AuthorizationDataService, useValue: authorizationService },
96+
{ provide: ThemeService, useValue: themeService },
97+
{ provide: TruncatableService, useValue: truncatableService },
8298
{ provide: XSRFService, useValue: {} },
8399
],
84-
schemas: [NO_ERRORS_SCHEMA],
85100
}).overrideComponent(ItemListElementComponent, {
86101
set: { changeDetection: ChangeDetectionStrategy.Default },
87102
}).compileComponents();
@@ -95,6 +110,7 @@ describe('ItemListElementComponent', () => {
95110
describe(`when the publication is rendered`, () => {
96111
beforeEach(() => {
97112
comp.object = mockItem;
113+
comp.ngOnChanges();
98114
fixture.detectChanges();
99115
});
100116

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
import { Component } from '@angular/core';
1+
import {
2+
Component,
3+
OnChanges,
4+
} from '@angular/core';
25

36
import { Item } from '../../../../../core/shared/item.model';
47
import { ViewMode } from '../../../../../core/shared/view-mode.model';
8+
import { hasValue } from '../../../../empty.util';
9+
import { ItemSearchResult } from '../../../../object-collection/shared/item-search-result.model';
510
import { listableObjectComponent } from '../../../../object-collection/shared/listable-object/listable-object.decorator';
11+
import { ListableObjectComponentLoaderComponent } from '../../../../object-collection/shared/listable-object/listable-object-component-loader.component';
612
import { AbstractListableElementComponent } from '../../../../object-collection/shared/object-collection-element/abstract-listable-element.component';
7-
import { ItemSearchResultListElementComponent } from '../../../search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component';
813

914
@listableObjectComponent('Publication', ViewMode.ListElement)
1015
@listableObjectComponent(Item, ViewMode.ListElement)
@@ -13,10 +18,23 @@ import { ItemSearchResultListElementComponent } from '../../../search-result-lis
1318
styleUrls: ['./item-list-element.component.scss'],
1419
templateUrl: './item-list-element.component.html',
1520
standalone: true,
16-
imports: [ItemSearchResultListElementComponent],
21+
imports: [
22+
ListableObjectComponentLoaderComponent,
23+
],
1724
})
1825
/**
1926
* The component for displaying a list element for an item of the type Publication
2027
*/
21-
export class ItemListElementComponent extends AbstractListableElementComponent<Item> {
28+
export class ItemListElementComponent extends AbstractListableElementComponent<Item> implements OnChanges {
29+
30+
itemSearchResult: ItemSearchResult;
31+
32+
ngOnChanges(): void {
33+
if (hasValue(this.object)) {
34+
this.itemSearchResult = Object.assign(new ItemSearchResult(), {
35+
indexableObject: this.object,
36+
});
37+
}
38+
}
39+
2240
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import {
2+
Observable,
3+
of as observableOf,
4+
} from 'rxjs';
5+
6+
export class TruncatableServiceStub {
7+
8+
isCollapsed(_id: string): Observable<boolean> {
9+
return observableOf(false);
10+
}
11+
12+
// eslint-disable-next-line no-empty, @typescript-eslint/no-empty-function
13+
public toggle(_id: string): void {
14+
}
15+
16+
// eslint-disable-next-line no-empty, @typescript-eslint/no-empty-function
17+
public collapse(_id: string): void {
18+
}
19+
20+
// eslint-disable-next-line no-empty, @typescript-eslint/no-empty-function
21+
public expand(_id: string): void {
22+
}
23+
24+
}

0 commit comments

Comments
 (0)