113169: Renamed the service in charge of adding metadata head tags to you HTML to HeadTagService & made its methods protected to make it easier to override them

This commit is contained in:
Alexandre Vryghem
2024-03-15 16:12:22 +01:00
parent 404ccd9b0e
commit 179e7e0543
14 changed files with 95 additions and 170 deletions

View File

@@ -9,11 +9,11 @@ import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { AppComponent } from './app.component';
import { HostWindowState } from './shared/search/host-window.reducer';
import { HostWindowResizeAction } from './shared/host-window.actions';
import { MetadataService } from './core/metadata/metadata.service';
import { HeadTagService } from './core/metadata/head-tag.service';
import { NativeWindowRef, NativeWindowService } from './core/services/window.service';
import { TranslateLoaderMock } from './shared/mocks/translate-loader.mock';
import { MetadataServiceMock } from './shared/mocks/metadata-service.mock';
import { HeadTagServiceMock } from './shared/mocks/head-tag-service.mock';
import { AngularticsProviderMock } from './shared/mocks/angulartics-provider.service.mock';
import { AuthServiceMock } from './shared/mocks/auth.service.mock';
import { AuthService } from './core/auth/auth.service';
@@ -71,7 +71,7 @@ describe('App component', () => {
declarations: [AppComponent], // declare the test component
providers: [
{ provide: NativeWindowService, useValue: new NativeWindowRef() },
{ provide: MetadataService, useValue: new MetadataServiceMock() },
{ provide: HeadTagService, useValue: new HeadTagServiceMock() },
{ provide: Angulartics2DSpace, useValue: new AngularticsProviderMock() },
{ provide: AuthService, useValue: new AuthServiceMock() },
{ provide: Router, useValue: new RouterMock() },

View File

@@ -3,14 +3,10 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { CommunityDataService } from '../core/data/community-data.service';
import { RemoteData } from '../core/data/remote-data';
import { Bitstream } from '../core/shared/bitstream.model';
import { Community } from '../core/shared/community.model';
import { MetadataService } from '../core/metadata/metadata.service';
import { fadeInOut } from '../shared/animations/fade';
import { hasValue } from '../shared/empty.util';
import { getAllSucceededRemoteDataPayload} from '../core/shared/operators';
@@ -53,8 +49,6 @@ export class CommunityPageComponent implements OnInit {
communityPageRoute$: Observable<string>;
constructor(
private communityDataService: CommunityDataService,
private metadata: MetadataService,
private route: ActivatedRoute,
private router: Router,
private authService: AuthService,

View File

@@ -64,7 +64,7 @@ import { Group } from './eperson/models/group.model';
import { JsonPatchOperationsBuilder } from './json-patch/builder/json-patch-operations-builder';
import { MetadataField } from './metadata/metadata-field.model';
import { MetadataSchema } from './metadata/metadata-schema.model';
import { MetadataService } from './metadata/metadata.service';
import { HeadTagService } from './metadata/head-tag.service';
import { RegistryService } from './registry/registry.service';
import { RoleService } from './roles/role.service';
import { FeedbackDataService } from './feedback/feedback-data.service';
@@ -218,7 +218,7 @@ const PROVIDERS = [
HALEndpointService,
HostWindowService,
ItemDataService,
MetadataService,
HeadTagService,
ObjectCacheService,
PaginationComponentOptions,
ResourcePolicyDataService,

View File

@@ -19,7 +19,7 @@ import { PaginatedList } from '../data/paginated-list.model';
import { Bitstream } from '../shared/bitstream.model';
import { MetadataValue } from '../shared/metadata.models';
import { MetadataService } from './metadata.service';
import { HeadTagService } from './head-tag.service';
import { RootDataService } from '../data/root-data.service';
import { Bundle } from '../shared/bundle.model';
import { createPaginatedList } from '../../shared/testing/utils.test';
@@ -31,8 +31,8 @@ import { AddMetaTagAction, ClearMetaTagAction } from './meta-tag.actions';
import { AuthorizationDataService } from '../data/feature-authorization/authorization-data.service';
import { AppConfig } from '../../../config/app-config.interface';
describe('MetadataService', () => {
let metadataService: MetadataService;
describe('HeadTagService', () => {
let headTagService: HeadTagService;
let meta: Meta;
@@ -41,7 +41,6 @@ describe('MetadataService', () => {
let dsoNameService: DSONameService;
let bundleDataService;
let bitstreamDataService;
let rootService: RootDataService;
let translateService: TranslateService;
let hardRedirectService: HardRedirectService;
@@ -59,9 +58,6 @@ describe('MetadataService', () => {
rootService = jasmine.createSpyObj({
findRoot: createSuccessfulRemoteDataObject$({ dspaceVersion: 'mock-dspace-version' })
});
bitstreamDataService = jasmine.createSpyObj({
findListByHref: createSuccessfulRemoteDataObject$(createPaginatedList([MockBitstream3])),
});
bundleDataService = jasmine.createSpyObj({
findByItemAndName: mockBundleRD$([MockBitstream3])
});
@@ -102,15 +98,13 @@ describe('MetadataService', () => {
}
} as any;
metadataService = new MetadataService(
headTagService = new HeadTagService(
router,
translateService,
meta,
title,
dsoNameService,
bundleDataService,
bitstreamDataService,
undefined,
rootService,
store,
hardRedirectService,
@@ -120,7 +114,7 @@ describe('MetadataService', () => {
});
it('items page should set meta tags', fakeAsync(() => {
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(ItemMock),
@@ -147,7 +141,7 @@ describe('MetadataService', () => {
}));
it('items page should set meta tags as published Thesis', fakeAsync(() => {
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(mockPublisher(mockType(ItemMock, 'Thesis'))),
@@ -166,7 +160,7 @@ describe('MetadataService', () => {
}));
it('items page should set meta tags as published Technical Report', fakeAsync(() => {
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(mockPublisher(mockType(ItemMock, 'Technical Report'))),
@@ -182,7 +176,7 @@ describe('MetadataService', () => {
it('route titles should overwrite dso titles', fakeAsync(() => {
(translateService.get as jasmine.Spy).and.returnValues(of('DSpace :: '), of('Translated Route Title'));
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(ItemMock),
@@ -198,7 +192,7 @@ describe('MetadataService', () => {
it('other navigation should add title and description', fakeAsync(() => {
(translateService.get as jasmine.Spy).and.returnValues(of('DSpace :: '), of('Dummy Title'), of('This is a dummy item component for testing!'));
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
title: 'Dummy Title',
@@ -220,14 +214,14 @@ describe('MetadataService', () => {
describe(`listenForRouteChange`, () => {
it(`should call processRouteChange`, fakeAsync(() => {
spyOn(metadataService as any, 'processRouteChange').and.callFake(() => undefined);
metadataService.listenForRouteChange();
spyOn(headTagService as any, 'processRouteChange').and.callFake(() => undefined);
headTagService.listenForRouteChange();
tick();
expect((metadataService as any).processRouteChange).toHaveBeenCalled();
expect((headTagService as any).processRouteChange).toHaveBeenCalled();
}));
it(`should add Generator`, fakeAsync(() => {
spyOn(metadataService as any, 'processRouteChange').and.callFake(() => undefined);
metadataService.listenForRouteChange();
spyOn(headTagService as any, 'processRouteChange').and.callFake(() => undefined);
headTagService.listenForRouteChange();
tick();
expect(meta.addTag).toHaveBeenCalledWith({
name: 'Generator',
@@ -238,7 +232,7 @@ describe('MetadataService', () => {
describe('citation_abstract_html_url', () => {
it('should use dc.identifier.uri if available', fakeAsync(() => {
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(mockUri(ItemMock, 'https://ddg.gg')),
@@ -253,7 +247,7 @@ describe('MetadataService', () => {
}));
it('should use current route as fallback', fakeAsync(() => {
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(mockUri(ItemMock)),
@@ -270,7 +264,7 @@ describe('MetadataService', () => {
describe('citation_*_institution / citation_publisher', () => {
it('should use citation_dissertation_institution tag for dissertations', fakeAsync(() => {
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(mockPublisher(mockType(ItemMock, 'Thesis'))),
@@ -287,7 +281,7 @@ describe('MetadataService', () => {
}));
it('should use citation_tech_report_institution tag for tech reports', fakeAsync(() => {
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(mockPublisher(mockType(ItemMock, 'Technical Report'))),
@@ -304,7 +298,7 @@ describe('MetadataService', () => {
}));
it('should use citation_publisher for other item types', fakeAsync(() => {
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(mockPublisher(mockType(ItemMock, 'Some Other Type'))),
@@ -325,7 +319,7 @@ describe('MetadataService', () => {
it('should link to primary Bitstream URL regardless of format', fakeAsync(() => {
(bundleDataService.findByItemAndName as jasmine.Spy).and.returnValue(mockBundleRD$([], MockBitstream3));
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(ItemMock),
@@ -344,7 +338,7 @@ describe('MetadataService', () => {
(bundleDataService.findByItemAndName as jasmine.Spy).and.returnValue(mockBundleRD$([MockBitstream3]));
(authorizationService.isAuthorized as jasmine.Spy).and.returnValue(observableOf(false));
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(ItemMock),
@@ -361,7 +355,7 @@ describe('MetadataService', () => {
it('should link to first and only Bitstream regardless of format', fakeAsync(() => {
(bundleDataService.findByItemAndName as jasmine.Spy).and.returnValue(mockBundleRD$([MockBitstream3]));
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(ItemMock),
@@ -381,13 +375,10 @@ describe('MetadataService', () => {
beforeEach(() => {
bitstreams = [MockBitstream2, MockBitstream3, MockBitstream1];
(bundleDataService.findByItemAndName as jasmine.Spy).and.returnValue(mockBundleRD$(bitstreams));
(bitstreamDataService.findListByHref as jasmine.Spy).and.returnValues(
...mockBitstreamPages$(bitstreams).map(bp => createSuccessfulRemoteDataObject$(bp)),
);
});
it('should link to first Bitstream with allowed format', fakeAsync(() => {
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(ItemMock),
@@ -412,13 +403,10 @@ describe('MetadataService', () => {
beforeEach(() => {
bitstreams = [MockBitstream1, MockBitstream3, MockBitstream2];
(bundleDataService.findByItemAndName as jasmine.Spy).and.returnValue(mockBundleRD$(bitstreams));
(bitstreamDataService.findListByHref as jasmine.Spy).and.returnValues(
...mockBitstreamPages$(bitstreams).map(bp => createSuccessfulRemoteDataObject$(bp)),
);
});
it(`shouldn't add a citation_pdf_url meta tag`, fakeAsync(() => {
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(ItemMock),
@@ -437,7 +425,7 @@ describe('MetadataService', () => {
describe('tagstore', () => {
beforeEach(fakeAsync(() => {
(metadataService as any).processRouteChange({
(headTagService as any).processRouteChange({
data: {
value: {
dso: createSuccessfulRemoteDataObject(ItemMock),

View File

@@ -17,8 +17,6 @@ import { filter, map, switchMap, take, mergeMap } from 'rxjs/operators';
import { hasNoValue, hasValue, isNotEmpty } from '../../shared/empty.util';
import { DSONameService } from '../breadcrumbs/dso-name.service';
import { BitstreamDataService } from '../data/bitstream-data.service';
import { BitstreamFormatDataService } from '../data/bitstream-format-data.service';
import { RemoteData } from '../data/remote-data';
import { BitstreamFormat } from '../shared/bitstream-format.model';
@@ -64,7 +62,7 @@ const tagsInUseSelector =
);
@Injectable()
export class MetadataService {
export class HeadTagService {
private currentObject: BehaviorSubject<DSpaceObject> = new BehaviorSubject<DSpaceObject>(undefined);
@@ -84,19 +82,17 @@ export class MetadataService {
];
constructor(
private router: Router,
private translate: TranslateService,
private meta: Meta,
private title: Title,
private dsoNameService: DSONameService,
private bundleDataService: BundleDataService,
private bitstreamDataService: BitstreamDataService,
private bitstreamFormatDataService: BitstreamFormatDataService,
private rootService: RootDataService,
private store: Store<CoreState>,
private hardRedirectService: HardRedirectService,
@Inject(APP_CONFIG) private appConfig: AppConfig,
private authorizationService: AuthorizationDataService
protected router: Router,
protected translate: TranslateService,
protected meta: Meta,
protected title: Title,
protected dsoNameService: DSONameService,
protected bundleDataService: BundleDataService,
protected rootService: RootDataService,
protected store: Store<CoreState>,
protected hardRedirectService: HardRedirectService,
@Inject(APP_CONFIG) protected appConfig: AppConfig,
protected authorizationService: AuthorizationDataService
) {
}
@@ -115,7 +111,7 @@ export class MetadataService {
});
}
private processRouteChange(routeInfo: any): void {
protected processRouteChange(routeInfo: any): void {
this.clearMetaTags();
if (hasValue(routeInfo.data.value.dso) && hasValue(routeInfo.data.value.dso.payload)) {
@@ -138,14 +134,14 @@ export class MetadataService {
}
}
private getCurrentRoute(route: ActivatedRoute): ActivatedRoute {
protected getCurrentRoute(route: ActivatedRoute): ActivatedRoute {
while (route.firstChild) {
route = route.firstChild;
}
return route;
}
private setDSOMetaTags(): void {
protected setDSOMetaTags(): void {
this.setTitleTag();
this.setDescriptionTag();
@@ -187,7 +183,7 @@ export class MetadataService {
/**
* Add <meta name="title" ... > to the <head>
*/
private setTitleTag(): void {
protected setTitleTag(): void {
const value = this.dsoNameService.getName(this.currentObject.getValue());
this.addMetaTag('title', value);
this.title.setTitle(value);
@@ -196,7 +192,7 @@ export class MetadataService {
/**
* Add <meta name="description" ... > to the <head>
*/
private setDescriptionTag(): void {
protected setDescriptionTag(): void {
// TODO: truncate abstract
const value = this.getMetaTagValue('dc.description.abstract');
this.addMetaTag('description', value);
@@ -205,7 +201,7 @@ export class MetadataService {
/**
* Add <meta name="citation_title" ... > to the <head>
*/
private setCitationTitleTag(): void {
protected setCitationTitleTag(): void {
const value = this.getMetaTagValue('dc.title');
this.addMetaTag('citation_title', value);
}
@@ -213,7 +209,7 @@ export class MetadataService {
/**
* Add <meta name="citation_author" ... > to the <head>
*/
private setCitationAuthorTags(): void {
protected setCitationAuthorTags(): void {
const values: string[] = this.getMetaTagValues(['dc.author', 'dc.contributor.author', 'dc.creator']);
this.addMetaTags('citation_author', values);
}
@@ -221,7 +217,7 @@ export class MetadataService {
/**
* Add <meta name="citation_publication_date" ... > to the <head>
*/
private setCitationPublicationDateTag(): void {
protected setCitationPublicationDateTag(): void {
const value = this.getFirstMetaTagValue(['dc.date.copyright', 'dc.date.issued', 'dc.date.available', 'dc.date.accessioned']);
this.addMetaTag('citation_publication_date', value);
}
@@ -229,7 +225,7 @@ export class MetadataService {
/**
* Add <meta name="citation_issn" ... > to the <head>
*/
private setCitationISSNTag(): void {
protected setCitationISSNTag(): void {
const value = this.getMetaTagValue('dc.identifier.issn');
this.addMetaTag('citation_issn', value);
}
@@ -237,7 +233,7 @@ export class MetadataService {
/**
* Add <meta name="citation_isbn" ... > to the <head>
*/
private setCitationISBNTag(): void {
protected setCitationISBNTag(): void {
const value = this.getMetaTagValue('dc.identifier.isbn');
this.addMetaTag('citation_isbn', value);
}
@@ -245,7 +241,7 @@ export class MetadataService {
/**
* Add <meta name="citation_language" ... > to the <head>
*/
private setCitationLanguageTag(): void {
protected setCitationLanguageTag(): void {
const value = this.getFirstMetaTagValue(['dc.language', 'dc.language.iso']);
this.addMetaTag('citation_language', value);
}
@@ -253,7 +249,7 @@ export class MetadataService {
/**
* Add <meta name="citation_dissertation_name" ... > to the <head>
*/
private setCitationDissertationNameTag(): void {
protected setCitationDissertationNameTag(): void {
const value = this.getMetaTagValue('dc.title');
this.addMetaTag('citation_dissertation_name', value);
}
@@ -261,7 +257,7 @@ export class MetadataService {
/**
* Add dc.publisher to the <head>. The tag name depends on the item type.
*/
private setCitationPublisherTag(): void {
protected setCitationPublisherTag(): void {
const value = this.getMetaTagValue('dc.publisher');
if (this.isDissertation()) {
this.addMetaTag('citation_dissertation_institution', value);
@@ -275,7 +271,7 @@ export class MetadataService {
/**
* Add <meta name="citation_keywords" ... > to the <head>
*/
private setCitationKeywordsTag(): void {
protected setCitationKeywordsTag(): void {
const value = this.getMetaTagValuesAndCombine('dc.subject');
this.addMetaTag('citation_keywords', value);
}
@@ -283,7 +279,7 @@ export class MetadataService {
/**
* Add <meta name="citation_abstract_html_url" ... > to the <head>
*/
private setCitationAbstractUrlTag(): void {
protected setCitationAbstractUrlTag(): void {
if (this.currentObject.value instanceof Item) {
let url = this.getMetaTagValue('dc.identifier.uri');
if (hasNoValue(url)) {
@@ -296,7 +292,7 @@ export class MetadataService {
/**
* Add <meta name="citation_pdf_url" ... > to the <head>
*/
private setCitationPdfUrlTag(): void {
protected setCitationPdfUrlTag(): void {
if (this.currentObject.value instanceof Item) {
const item = this.currentObject.value as Item;
@@ -389,7 +385,7 @@ export class MetadataService {
* @param bitstreamRd
* @private
*/
private getFirstAllowedFormatBitstreamLink(bitstreamRd: RemoteData<PaginatedList<Bitstream>>): Observable<string> {
protected getFirstAllowedFormatBitstreamLink(bitstreamRd: RemoteData<PaginatedList<Bitstream>>): Observable<string> {
if (hasValue(bitstreamRd.payload) && isNotEmpty(bitstreamRd.payload.page)) {
// Retrieve the formats of all bitstreams in the page sequentially
return observableConcat(
@@ -422,13 +418,13 @@ export class MetadataService {
/**
* Add <meta name="Generator" ... > to the <head> containing the current DSpace version
*/
private setGenerator(): void {
protected setGenerator(): void {
this.rootService.findRoot().pipe(getFirstSucceededRemoteDataPayload()).subscribe((root) => {
this.meta.addTag({ name: 'Generator', content: root.dspaceVersion });
});
}
private hasType(value: string): boolean {
protected hasType(value: string): boolean {
return this.currentObject.value.hasMetadata('dc.type', { value: value, ignoreCase: true });
}
@@ -438,7 +434,7 @@ export class MetadataService {
* @returns {boolean}
* true if this._item has a dc.type equal to 'Thesis'
*/
private isDissertation(): boolean {
protected isDissertation(): boolean {
return this.hasType('thesis');
}
@@ -448,27 +444,27 @@ export class MetadataService {
* @returns {boolean}
* true if this._item has a dc.type equal to 'Technical Report'
*/
private isTechReport(): boolean {
protected isTechReport(): boolean {
return this.hasType('technical report');
}
private getMetaTagValue(key: string): string {
protected getMetaTagValue(key: string): string {
return this.currentObject.value.firstMetadataValue(key);
}
private getFirstMetaTagValue(keys: string[]): string {
protected getFirstMetaTagValue(keys: string[]): string {
return this.currentObject.value.firstMetadataValue(keys);
}
private getMetaTagValuesAndCombine(key: string): string {
protected getMetaTagValuesAndCombine(key: string): string {
return this.getMetaTagValues([key]).join('; ');
}
private getMetaTagValues(keys: string[]): string[] {
protected getMetaTagValues(keys: string[]): string[] {
return this.currentObject.value.allMetadataValues(keys);
}
private addMetaTag(name: string, content: string): void {
protected addMetaTag(name: string, content: string): void {
if (content) {
const tag = { name, content } as MetaDefinition;
this.meta.addTag(tag);
@@ -476,17 +472,17 @@ export class MetadataService {
}
}
private addMetaTags(name: string, content: string[]): void {
protected addMetaTags(name: string, content: string[]): void {
for (const value of content) {
this.addMetaTag(name, value);
}
}
private storeTag(key: string): void {
protected storeTag(key: string): void {
this.store.dispatch(new AddMetaTagAction(key));
}
public clearMetaTags() {
protected clearMetaTags(): void {
this.store.pipe(
select(tagsInUseSelector),
take(1)

View File

@@ -2,7 +2,7 @@ import { InitService } from './init.service';
import { APP_CONFIG } from 'src/config/app-config.interface';
import { APP_INITIALIZER, Injectable } from '@angular/core';
import { inject, TestBed, waitForAsync } from '@angular/core/testing';
import { MetadataService } from './core/metadata/metadata.service';
import { HeadTagService } from './core/metadata/head-tag.service';
import { BreadcrumbsService } from './breadcrumbs/breadcrumbs.service';
import { CommonModule } from '@angular/common';
import { Store, StoreModule } from '@ngrx/store';
@@ -31,6 +31,7 @@ import objectContaining = jasmine.objectContaining;
import createSpyObj = jasmine.createSpyObj;
import SpyObj = jasmine.SpyObj;
import { getTestScheduler } from 'jasmine-marbles';
import { HeadTagServiceMock } from './shared/mocks/head-tag-service.mock';
let spy: SpyObj<any>;
@@ -121,7 +122,7 @@ describe('InitService', () => {
let correlationIdServiceSpy;
let dspaceTransferStateSpy;
let transferStateSpy;
let metadataServiceSpy;
let headTagService: HeadTagServiceMock;
let breadcrumbsServiceSpy;
let menuServiceSpy;
@@ -147,9 +148,7 @@ describe('InitService', () => {
breadcrumbsServiceSpy = jasmine.createSpyObj('breadcrumbsServiceSpy', [
'listenForRouteChanges',
]);
metadataServiceSpy = jasmine.createSpyObj('metadataService', [
'listenForRouteChange',
]);
headTagService = new HeadTagServiceMock();
menuServiceSpy = jasmine.createSpyObj('menuServiceSpy', [
'listenForRouteChanges',
]);
@@ -173,7 +172,7 @@ describe('InitService', () => {
{ provide: APP_CONFIG, useValue: environment },
{ provide: LocaleService, useValue: getMockLocaleService() },
{ provide: Angulartics2DSpace, useValue: new AngularticsProviderMock() },
{ provide: MetadataService, useValue: metadataServiceSpy },
{ provide: HeadTagService, useValue: headTagService },
{ provide: BreadcrumbsService, useValue: breadcrumbsServiceSpy },
{ provide: AuthService, useValue: new AuthServiceMock() },
{ provide: Router, useValue: new RouterMock() },
@@ -189,9 +188,9 @@ describe('InitService', () => {
describe('initRouteListeners', () => {
it('should call listenForRouteChanges', inject([InitService], (service) => {
// @ts-ignore
spyOn(headTagService, 'listenForRouteChange');
service.initRouteListeners();
expect(metadataServiceSpy.listenForRouteChange).toHaveBeenCalledTimes(1);
expect(headTagService.listenForRouteChange).toHaveBeenCalledTimes(1);
expect(breadcrumbsServiceSpy.listenForRouteChanges).toHaveBeenCalledTimes(1);
expect(breadcrumbsServiceSpy.listenForRouteChanges).toHaveBeenCalledTimes(1);
}));

View File

@@ -17,7 +17,7 @@ import isEqual from 'lodash/isEqual';
import { TranslateService } from '@ngx-translate/core';
import { LocaleService } from './core/locale/locale.service';
import { Angulartics2DSpace } from './statistics/angulartics/dspace-provider';
import { MetadataService } from './core/metadata/metadata.service';
import { HeadTagService } from './core/metadata/head-tag.service';
import { BreadcrumbsService } from './breadcrumbs/breadcrumbs.service';
import { ThemeService } from './shared/theme-support/theme.service';
import { isAuthenticationBlocking } from './core/auth/selectors';
@@ -49,7 +49,7 @@ export abstract class InitService {
protected translate: TranslateService,
protected localeService: LocaleService,
protected angulartics2DSpace: Angulartics2DSpace,
protected metadata: MetadataService,
protected headTagService: HeadTagService,
protected breadcrumbsService: BreadcrumbsService,
protected themeService: ThemeService,
protected menuService: MenuService,
@@ -178,13 +178,13 @@ export abstract class InitService {
/**
* Start route-listening subscriptions
* - {@link MetadataService.listenForRouteChange}
* - {@link HeadTagService.listenForRouteChange}
* - {@link BreadcrumbsService.listenForRouteChanges}
* - {@link ThemeService.listenForRouteChanges}
* @protected
*/
protected initRouteListeners(): void {
this.metadata.listenForRouteChange();
this.headTagService.listenForRouteChange();
this.breadcrumbsService.listenForRouteChanges();
this.themeService.listenForRouteChanges();
this.menuService.listenForRouteChanges();

View File

@@ -5,7 +5,7 @@ import { TranslateLoaderMock } from '../../shared/mocks/translate-loader.mock';
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA, PLATFORM_ID } from '@angular/core';
import { TruncatePipe } from '../../shared/utils/truncate.pipe';
import { FullItemPageComponent } from './full-item-page.component';
import { MetadataService } from '../../core/metadata/metadata.service';
import { HeadTagService } from '../../core/metadata/head-tag.service';
import { ActivatedRoute } from '@angular/router';
import { ActivatedRouteStub } from '../../shared/testing/active-router.stub';
import { VarDirective } from '../../shared/utils/var.directive';
@@ -116,7 +116,7 @@ describe('FullItemPageComponent', () => {
providers: [
{ provide: ActivatedRoute, useValue: routeStub },
{ provide: ItemDataService, useValue: {} },
{ provide: MetadataService, useValue: metadataServiceStub },
{ provide: HeadTagService, useValue: metadataServiceStub },
{ provide: AuthService, useValue: authService },
{ provide: AuthorizationDataService, useValue: authorizationDataService },
{ provide: ServerResponseService, useValue: serverResponseService },

View File

@@ -6,7 +6,6 @@ import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA, PLATFORM_ID } from '@angular
import { ItemPageComponent } from './item-page.component';
import { ActivatedRoute, Router } from '@angular/router';
import { ActivatedRouteStub } from '../../shared/testing/active-router.stub';
import { MetadataService } from '../../core/metadata/metadata.service';
import { VarDirective } from '../../shared/utils/var.directive';
import { Item } from '../../core/shared/item.model';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
@@ -63,12 +62,6 @@ describe('ItemPageComponent', () => {
let signpostingDataService: jasmine.SpyObj<SignpostingDataService>;
let linkHeadService: jasmine.SpyObj<LinkHeadService>;
const mockMetadataService = {
/* eslint-disable no-empty,@typescript-eslint/no-empty-function */
processRemoteData: () => {
}
/* eslint-enable no-empty, @typescript-eslint/no-empty-function */
};
const mockRoute = Object.assign(new ActivatedRouteStub(), {
data: observableOf({ dso: createSuccessfulRemoteDataObject(mockItem) })
});
@@ -105,7 +98,6 @@ describe('ItemPageComponent', () => {
providers: [
{ provide: ActivatedRoute, useValue: mockRoute },
{ provide: ItemDataService, useValue: {} },
{ provide: MetadataService, useValue: mockMetadataService },
{ provide: Router, useValue: {} },
{ provide: AuthService, useValue: authService },
{ provide: AuthorizationDataService, useValue: authorizationDataService },

View File

@@ -1,29 +1,14 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RootComponent } from './root.component';
import { CommonModule } from '@angular/common';
import { StoreModule } from '@ngrx/store';
import { authReducer } from '../core/auth/auth.reducer';
import { storeModuleConfig } from '../app.reducer';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateLoaderMock } from '../shared/mocks/translate-loader.mock';
import { NativeWindowRef, NativeWindowService } from '../core/services/window.service';
import { MetadataService } from '../core/metadata/metadata.service';
import { MetadataServiceMock } from '../shared/mocks/metadata-service.mock';
import { AngularticsProviderMock } from '../shared/mocks/angulartics-provider.service.mock';
import { Angulartics2DSpace } from '../statistics/angulartics/dspace-provider';
import { AuthService } from '../core/auth/auth.service';
import { AuthServiceMock } from '../shared/mocks/auth.service.mock';
import { ActivatedRoute, Router } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
import { Router } from '@angular/router';
import { RouterMock } from '../shared/mocks/router.mock';
import { MockActivatedRoute } from '../shared/mocks/active-router.mock';
import { MenuService } from '../shared/menu/menu.service';
import { CSSVariableService } from '../shared/sass-helper/css-variable.service';
import { CSSVariableServiceStub } from '../shared/testing/css-variable-service.stub';
import { HostWindowService } from '../shared/host-window.service';
import { HostWindowServiceStub } from '../shared/testing/host-window-service.stub';
import { LocaleService } from '../core/locale/locale.service';
import { provideMockStore } from '@ngrx/store/testing';
import { RouteService } from '../core/services/route.service';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { MenuServiceStub } from '../shared/testing/menu-service.stub';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
@@ -37,29 +22,14 @@ describe('RootComponent', () => {
imports: [
CommonModule,
NoopAnimationsModule,
StoreModule.forRoot(authReducer, storeModuleConfig),
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useClass: TranslateLoaderMock
}
}),
TranslateModule.forRoot(),
],
declarations: [RootComponent], // declare the test component
providers: [
{ provide: NativeWindowService, useValue: new NativeWindowRef() },
{ provide: MetadataService, useValue: new MetadataServiceMock() },
{ provide: Angulartics2DSpace, useValue: new AngularticsProviderMock() },
{ provide: AuthService, useValue: new AuthServiceMock() },
{ provide: Router, useValue: new RouterMock() },
{ provide: ActivatedRoute, useValue: new MockActivatedRoute() },
{ provide: MenuService, useValue: new MenuServiceStub() },
{ provide: CSSVariableService, useClass: CSSVariableServiceStub },
{ provide: HostWindowService, useValue: new HostWindowServiceStub(800) },
{ provide: LocaleService, useValue: {} },
provideMockStore({ core: { auth: { loading: false } } } as any),
RootComponent,
RouteService
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
}).compileComponents();

View File

@@ -1,20 +1,12 @@
import { map, startWith } from 'rxjs/operators';
import { Component, Inject, Input, OnInit } from '@angular/core';
import { Component, Input, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { combineLatest as combineLatestObservable, Observable, of } from 'rxjs';
import { Store } from '@ngrx/store';
import { TranslateService } from '@ngx-translate/core';
import { MetadataService } from '../core/metadata/metadata.service';
import { HostWindowState } from '../shared/search/host-window.reducer';
import { NativeWindowRef, NativeWindowService } from '../core/services/window.service';
import { AuthService } from '../core/auth/auth.service';
import { CSSVariableService } from '../shared/sass-helper/css-variable.service';
import { MenuService } from '../shared/menu/menu.service';
import { HostWindowService } from '../shared/host-window.service';
import { ThemeConfig } from '../../config/theme.model';
import { Angulartics2DSpace } from '../statistics/angulartics/dspace-provider';
import { environment } from '../../environments/environment';
import { slideSidebarPadding } from '../shared/animations/slide';
import { MenuID } from '../shared/menu/menu-id.model';
@@ -47,12 +39,6 @@ export class RootComponent implements OnInit {
@Input() shouldShowRouteLoader: boolean;
constructor(
@Inject(NativeWindowService) private _window: NativeWindowRef,
private translate: TranslateService,
private store: Store<HostWindowState>,
private metadata: MetadataService,
private angulartics2DSpace: Angulartics2DSpace,
private authService: AuthService,
private router: Router,
private cssService: CSSVariableService,
private menuService: MenuService,

View File

@@ -1,5 +1,5 @@
export class MetadataServiceMock {
export class HeadTagServiceMock {
// eslint-disable-next-line no-empty, @typescript-eslint/no-empty-function
public listenForRouteChange(): void {

View File

@@ -19,7 +19,7 @@ import { TranslateService } from '@ngx-translate/core';
import { LocaleService } from '../../app/core/locale/locale.service';
import { Angulartics2DSpace } from '../../app/statistics/angulartics/dspace-provider';
import { GoogleAnalyticsService } from '../../app/statistics/google-analytics.service';
import { MetadataService } from '../../app/core/metadata/metadata.service';
import { HeadTagService } from '../../app/core/metadata/head-tag.service';
import { BreadcrumbsService } from '../../app/breadcrumbs/breadcrumbs.service';
import { KlaroService } from '../../app/shared/cookies/klaro.service';
import { AuthService } from '../../app/core/auth/auth.service';
@@ -50,7 +50,7 @@ export class BrowserInitService extends InitService {
protected localeService: LocaleService,
protected angulartics2DSpace: Angulartics2DSpace,
protected googleAnalyticsService: GoogleAnalyticsService,
protected metadata: MetadataService,
protected headTagService: HeadTagService,
protected breadcrumbsService: BreadcrumbsService,
protected klaroService: KlaroService,
protected authService: AuthService,
@@ -65,7 +65,7 @@ export class BrowserInitService extends InitService {
translate,
localeService,
angulartics2DSpace,
metadata,
headTagService,
breadcrumbsService,
themeService,
menuService,

View File

@@ -16,7 +16,7 @@ import { Inject, Injectable } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { LocaleService } from '../../app/core/locale/locale.service';
import { Angulartics2DSpace } from '../../app/statistics/angulartics/dspace-provider';
import { MetadataService } from '../../app/core/metadata/metadata.service';
import { HeadTagService } from '../../app/core/metadata/head-tag.service';
import { BreadcrumbsService } from '../../app/breadcrumbs/breadcrumbs.service';
import { ThemeService } from '../../app/shared/theme-support/theme.service';
import { take } from 'rxjs/operators';
@@ -35,7 +35,7 @@ export class ServerInitService extends InitService {
protected translate: TranslateService,
protected localeService: LocaleService,
protected angulartics2DSpace: Angulartics2DSpace,
protected metadata: MetadataService,
protected headTagService: HeadTagService,
protected breadcrumbsService: BreadcrumbsService,
protected themeService: ThemeService,
protected menuService: MenuService
@@ -47,7 +47,7 @@ export class ServerInitService extends InitService {
translate,
localeService,
angulartics2DSpace,
metadata,
headTagService,
breadcrumbsService,
themeService,
menuService,