[DURACOM-367] fix matomo SSR error on bitstream download page

This commit is contained in:
Andrea Barbasso
2025-05-09 14:48:27 +02:00
parent 73bd0d67ea
commit 37cef0fbae
4 changed files with 45 additions and 21 deletions

View File

@@ -60,7 +60,7 @@ export class FooterComponent implements OnInit {
} }
showCookieSettings() { showCookieSettings() {
if (hasValue(this.cookies)) { if (hasValue(this.cookies) && this.cookies.showSettings instanceof Function) {
this.cookies.showSettings(); this.cookies.showSettings();
} }
return false; return false;

View File

@@ -4,7 +4,7 @@ import { Observable } from 'rxjs';
/** /**
* Abstract class representing a service for handling Orejime consent preferences and UI * Abstract class representing a service for handling Orejime consent preferences and UI
*/ */
@Injectable() @Injectable({ providedIn: 'root' })
export abstract class OrejimeService { export abstract class OrejimeService {
/** /**
* Initializes the service * Initializes the service

View File

@@ -1,3 +1,7 @@
import {
Injector,
runInInjectionContext,
} from '@angular/core';
import { import {
fakeAsync, fakeAsync,
TestBed, TestBed,
@@ -53,6 +57,7 @@ describe('MatomoService', () => {
{ provide: OrejimeService, useValue: orejimeService }, { provide: OrejimeService, useValue: orejimeService },
{ provide: NativeWindowService, useValue: nativeWindowService }, { provide: NativeWindowService, useValue: nativeWindowService },
{ provide: ConfigurationDataService, useValue: configService }, { provide: ConfigurationDataService, useValue: configService },
{ provide: Injector, useValue: TestBed },
], ],
}); });
@@ -70,11 +75,13 @@ describe('MatomoService', () => {
}); });
it('should call setConsentGiven when consent is true', () => { it('should call setConsentGiven when consent is true', () => {
service.matomoTracker = matomoTracker;
service.changeMatomoConsent(true); service.changeMatomoConsent(true);
expect(matomoTracker.setConsentGiven).toHaveBeenCalled(); expect(matomoTracker.setConsentGiven).toHaveBeenCalled();
}); });
it('should call forgetConsentGiven when consent is false', () => { it('should call forgetConsentGiven when consent is false', () => {
service.matomoTracker = matomoTracker;
service.changeMatomoConsent(false); service.changeMatomoConsent(false);
expect(matomoTracker.forgetConsentGiven).toHaveBeenCalled(); expect(matomoTracker.forgetConsentGiven).toHaveBeenCalled();
}); });
@@ -91,7 +98,10 @@ describe('MatomoService', () => {
configService.findByPropertyName.withArgs(MATOMO_SITE_ID).and.returnValue( configService.findByPropertyName.withArgs(MATOMO_SITE_ID).and.returnValue(
createSuccessfulRemoteDataObject$(Object.assign(new ConfigurationProperty(), { values: ['1'] }))); createSuccessfulRemoteDataObject$(Object.assign(new ConfigurationProperty(), { values: ['1'] })));
orejimeService.getSavedPreferences.and.returnValue(of({ matomo: true })); orejimeService.getSavedPreferences.and.returnValue(of({ matomo: true }));
service.init();
runInInjectionContext(TestBed, () => {
service.init();
});
expect(matomoTracker.setConsentGiven).toHaveBeenCalled(); expect(matomoTracker.setConsentGiven).toHaveBeenCalled();
expect(matomoInitializer.initializeTracker).toHaveBeenCalledWith({ expect(matomoInitializer.initializeTracker).toHaveBeenCalledWith({
@@ -100,7 +110,7 @@ describe('MatomoService', () => {
}); });
}); });
it('should initialize tracker with REST configuration correct parameters in production', () => { it('should initialize tracker with REST configuration correct parameters in production', fakeAsync(() => {
environment.production = true; environment.production = true;
environment.matomo = { trackerUrl: '' }; environment.matomo = { trackerUrl: '' };
configService.findByPropertyName.withArgs(MATOMO_TRACKER_URL).and.returnValue( configService.findByPropertyName.withArgs(MATOMO_TRACKER_URL).and.returnValue(
@@ -113,19 +123,25 @@ describe('MatomoService', () => {
createSuccessfulRemoteDataObject$(Object.assign(new ConfigurationProperty(), { values: ['1'] }))); createSuccessfulRemoteDataObject$(Object.assign(new ConfigurationProperty(), { values: ['1'] })));
orejimeService.getSavedPreferences.and.returnValue(of({ matomo: true })); orejimeService.getSavedPreferences.and.returnValue(of({ matomo: true }));
service.init(); runInInjectionContext(TestBed, () => {
service.init();
});
tick();
expect(matomoTracker.setConsentGiven).toHaveBeenCalled(); expect(matomoTracker.setConsentGiven).toHaveBeenCalled();
expect(matomoInitializer.initializeTracker).toHaveBeenCalledWith({ expect(matomoInitializer.initializeTracker).toHaveBeenCalledWith({
siteId: '1', siteId: '1',
trackerUrl: 'http://example.com', trackerUrl: 'http://example.com',
}); });
}); }));
it('should not initialize tracker if not in production', () => { it('should not initialize tracker if not in production', () => {
environment.production = false; environment.production = false;
service.init(); runInInjectionContext(TestBed, () => {
service.init();
});
expect(matomoInitializer.initializeTracker).not.toHaveBeenCalled(); expect(matomoInitializer.initializeTracker).not.toHaveBeenCalled();
}); });
@@ -143,7 +159,9 @@ describe('MatomoService', () => {
createSuccessfulRemoteDataObject$(Object.assign(new ConfigurationProperty(), { values: ['1'] }))); createSuccessfulRemoteDataObject$(Object.assign(new ConfigurationProperty(), { values: ['1'] })));
orejimeService.getSavedPreferences.and.returnValue(of({ matomo: true })); orejimeService.getSavedPreferences.and.returnValue(of({ matomo: true }));
service.init(); runInInjectionContext(TestBed, () => {
service.init();
});
expect(matomoInitializer.initializeTracker).not.toHaveBeenCalled(); expect(matomoInitializer.initializeTracker).not.toHaveBeenCalled();
}); });
@@ -151,6 +169,7 @@ describe('MatomoService', () => {
describe('with visitorId set', () => { describe('with visitorId set', () => {
beforeEach(() => { beforeEach(() => {
matomoTracker.getVisitorId.and.returnValue(Promise.resolve('12345')); matomoTracker.getVisitorId.and.returnValue(Promise.resolve('12345'));
service.matomoTracker = matomoTracker;
}); });
it('should add trackerId parameter', fakeAsync(() => { it('should add trackerId parameter', fakeAsync(() => {

View File

@@ -1,6 +1,8 @@
import { import {
EnvironmentInjector,
inject, inject,
Injectable, Injectable,
runInInjectionContext,
} from '@angular/core'; } from '@angular/core';
import { import {
MatomoInitializerService, MatomoInitializerService,
@@ -11,12 +13,10 @@ import {
from as fromPromise, from as fromPromise,
Observable, Observable,
of, of,
switchMap,
} from 'rxjs'; } from 'rxjs';
import { import {
map, map,
take, take,
tap,
} from 'rxjs/operators'; } from 'rxjs/operators';
import { environment } from '../../environments/environment'; import { environment } from '../../environments/environment';
@@ -47,10 +47,10 @@ export const MATOMO_ENABLED = 'matomo.enabled';
export class MatomoService { export class MatomoService {
/** Injects the MatomoInitializerService to initialize the Matomo tracker. */ /** Injects the MatomoInitializerService to initialize the Matomo tracker. */
matomoInitializer = inject(MatomoInitializerService); matomoInitializer: MatomoInitializerService;
/** Injects the MatomoTracker to manage Matomo tracking operations. */ /** Injects the MatomoTracker to manage Matomo tracking operations. */
matomoTracker = inject(MatomoTracker); matomoTracker: MatomoTracker;
/** Injects the OrejimeService to manage cookie consent preferences. */ /** Injects the OrejimeService to manage cookie consent preferences. */
orejimeService = inject(OrejimeService); orejimeService = inject(OrejimeService);
@@ -61,6 +61,10 @@ export class MatomoService {
/** Injects the ConfigurationService. */ /** Injects the ConfigurationService. */
configService = inject(ConfigurationDataService); configService = inject(ConfigurationDataService);
constructor(private injector: EnvironmentInjector) {
}
/** /**
* Initializes the Matomo tracker if in production environment. * Initializes the Matomo tracker if in production environment.
* Sets up the changeMatomoConsent function on the native window object. * Sets up the changeMatomoConsent function on the native window object.
@@ -74,14 +78,15 @@ export class MatomoService {
if (environment.production) { if (environment.production) {
const preferences$ = this.orejimeService.getSavedPreferences(); const preferences$ = this.orejimeService.getSavedPreferences();
preferences$ combineLatest([preferences$, this.isMatomoEnabled$(), this.getSiteId$(), this.getTrackerUrl$()])
.pipe( .subscribe(([preferences, isMatomoEnabled, siteId, trackerUrl]) => {
tap(preferences => this.changeMatomoConsent(preferences?.matomo)),
switchMap(_ => combineLatest([this.isMatomoEnabled$(), this.getSiteId$(), this.getTrackerUrl$()])),
)
.subscribe(([isMatomoEnabled, siteId, trackerUrl]) => {
if (isMatomoEnabled && siteId && trackerUrl) { if (isMatomoEnabled && siteId && trackerUrl) {
runInInjectionContext(this.injector, () => {
this.matomoTracker = inject(MatomoTracker);
this.matomoInitializer = inject(MatomoInitializerService);
});
this.matomoInitializer.initializeTracker({ siteId, trackerUrl }); this.matomoInitializer.initializeTracker({ siteId, trackerUrl });
this.changeMatomoConsent(preferences?.matomo);
} }
}); });
} }
@@ -93,9 +98,9 @@ export class MatomoService {
*/ */
changeMatomoConsent = (consent: boolean) => { changeMatomoConsent = (consent: boolean) => {
if (consent) { if (consent) {
this.matomoTracker.setConsentGiven(); this.matomoTracker?.setConsentGiven();
} else { } else {
this.matomoTracker.forgetConsentGiven(); this.matomoTracker?.forgetConsentGiven();
} }
}; };
@@ -105,7 +110,7 @@ export class MatomoService {
* @returns An Observable that emits the URL with the visitor ID appended. * @returns An Observable that emits the URL with the visitor ID appended.
*/ */
appendVisitorId(url: string): Observable<string> { appendVisitorId(url: string): Observable<string> {
return fromPromise(this.matomoTracker.getVisitorId()) return fromPromise(this.matomoTracker?.getVisitorId())
.pipe( .pipe(
map(visitorId => this.appendTrackerId(url, visitorId)), map(visitorId => this.appendTrackerId(url, visitorId)),
take(1), take(1),