From c19f49fb968efffa96e7dd187fcea253dfcdbba6 Mon Sep 17 00:00:00 2001 From: lotte Date: Tue, 1 Sep 2020 17:59:34 +0200 Subject: [PATCH] added tests --- src/app/app.component.ts | 1 - src/app/core/data/data.service.ts | 30 +- .../cookies/browser-klaro.service.spec.ts | 202 +++++++++++++- .../shared/cookies/browser-klaro.service.ts | 257 ++++-------------- src/app/shared/cookies/klaro-configuration.ts | 166 +++++++++++ src/app/shared/cookies/klaro.effects.ts | 3 - .../shared/mocks/translate.service.mock.ts | 3 +- 7 files changed, 441 insertions(+), 221 deletions(-) create mode 100644 src/app/shared/cookies/klaro-configuration.ts delete mode 100644 src/app/shared/cookies/klaro.effects.ts diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 318bad8895..43ae0534ad 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -84,7 +84,6 @@ export class AppComponent implements OnInit, AfterViewInit { // set the current language code this.localeService.setCurrentLanguageCode(); - angulartics2GoogleAnalytics.startTracking(); angulartics2DSpace.startTracking(); diff --git a/src/app/core/data/data.service.ts b/src/app/core/data/data.service.ts index 0d818f2030..9c4a95b1b9 100644 --- a/src/app/core/data/data.service.ts +++ b/src/app/core/data/data.service.ts @@ -2,7 +2,7 @@ import { HttpClient } from '@angular/common/http'; import { Store } from '@ngrx/store'; import { Operation } from 'fast-json-patch'; import { Observable } from 'rxjs'; -import { distinctUntilChanged, filter, find, first, map, mergeMap, switchMap, take } from 'rxjs/operators'; +import { distinctUntilChanged, filter, find, first, map, mergeMap, switchMap, take, tap } from 'rxjs/operators'; import { hasValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util'; import { NotificationOptions } from '../../shared/notifications/models/notification-options.model'; import { NotificationsService } from '../../shared/notifications/notifications.service'; @@ -378,6 +378,14 @@ export abstract class DataService implements UpdateDa ); } + createPatchFromCache(object: T): Observable { + const oldVersion$ = this.findByHref(object._links.self.href); + return oldVersion$.pipe( + getSucceededRemoteData(), + getRemoteDataPayload(), + map((oldVersion: T) => this.comparator.diff(oldVersion, object))); + } + /** * Send a PUT request for the specified object * @@ -406,18 +414,16 @@ export abstract class DataService implements UpdateDa * @param {DSpaceObject} object The given object */ update(object: T): Observable> { - const oldVersion$ = this.findByHref(object._links.self.href); - return oldVersion$.pipe( - getSucceededRemoteData(), - getRemoteDataPayload(), - mergeMap((oldVersion: T) => { - const operations = this.comparator.diff(oldVersion, object); - if (isNotEmpty(operations)) { - this.objectCache.addPatch(object._links.self.href, operations); + return this.createPatchFromCache(object) + .pipe( + mergeMap((operations: Operation[]) => { + if (isNotEmpty(operations)) { + this.objectCache.addPatch(object._links.self.href, operations); + } + return this.findByHref(object._links.self.href); } - return this.findByHref(object._links.self.href); - } - )); + ) + ); } /** diff --git a/src/app/shared/cookies/browser-klaro.service.spec.ts b/src/app/shared/cookies/browser-klaro.service.spec.ts index e33f497d73..51da132173 100644 --- a/src/app/shared/cookies/browser-klaro.service.spec.ts +++ b/src/app/shared/cookies/browser-klaro.service.spec.ts @@ -1,12 +1,206 @@ import { TestBed } from '@angular/core/testing'; -import { BrowserKlaroService } from './browser-klaro.service'; +import { BrowserKlaroService, COOKIE_MDFIELD } from './browser-klaro.service'; +import { getMockTranslateService } from '../mocks/translate.service.mock'; +import { of as observableOf } from 'rxjs' +import { RestResponse } from '../../core/cache/response.models'; +import { EPerson } from '../../core/eperson/models/eperson.model'; +import { TranslateService } from '@ngx-translate/core'; +import { EPersonDataService } from '../../core/eperson/eperson-data.service'; +import { AuthService } from '../../core/auth/auth.service'; +import { CookieService } from '../../core/services/cookie.service'; +import { getTestScheduler } from 'jasmine-marbles'; +import { MetadataValue } from '../../core/shared/metadata.models'; +import { cloneDeep } from 'lodash'; -describe('KlaroService', () => { - beforeEach(() => TestBed.configureTestingModule({})); +describe('BrowserKlaroService', () => { + let translateService; + let ePersonService; + let authService; + let cookieService; + + let user; + let service: BrowserKlaroService; + + let mockConfig; + let appName; + let purpose; + let testKey; + + beforeEach(() => { + user = new EPerson(); + + translateService = getMockTranslateService(); + ePersonService = jasmine.createSpyObj('ePersonService', { + createPatchFromCache: observableOf([]), + patch: observableOf(new RestResponse(true, 200, 'Ok')) + }); + authService = jasmine.createSpyObj('authService', { + isAuthenticated: observableOf(true), + getAuthenticatedUserFromStore: observableOf(user) + }); + cookieService = jasmine.createSpyObj('cookieService', { + get: '{%22token_item%22:true%2C%22impersonation%22:true%2C%22redirect%22:true%2C%22language%22:true%2C%22klaro%22:true%2C%22has_agreed_end_user%22:true%2C%22google-analytics%22:true}', + set: () => { + /* empty */ + } + }); + + TestBed.configureTestingModule({ + providers: [ + BrowserKlaroService, + { + provide: TranslateService, + useValue: translateService + }, + { + provide: EPersonDataService, + useValue: ePersonService, + }, + { + provide: AuthService, + useValue: authService + }, + { + provide: CookieService, + useValue: cookieService + } + ] + }); + service = TestBed.get(BrowserKlaroService); + appName = 'testName'; + purpose = 'test purpose'; + testKey = 'this.is.a.fake.message.key'; + + mockConfig = { + translations: { + en: { + purposes: {}, + test: { + testeritis: testKey + } + } + }, + apps: [{ + name: appName, + purposes: [purpose] + }], + + }; + + service.klaroConfig = mockConfig; + }); it('should be created', () => { - const service: BrowserKlaroService = TestBed.get(BrowserKlaroService); expect(service).toBeTruthy(); }); + + it('addAppMessages', () => { + service.addAppMessages(); + expect(mockConfig.translations.en[appName]).toBeDefined(); + expect(mockConfig.translations.en.purposes[purpose]).toBeDefined(); + }); + + it('translateConfiguration', () => { + service.translateConfiguration(); + expect((service as any).translateService.instant).toHaveBeenCalledWith(testKey); + }); + + describe('initializeUser when there is a metadata field value', () => { + beforeEach(() => { + user.setMetadata(COOKIE_MDFIELD, undefined, '{}'); + spyOn(service, 'restoreSettingsForUsers'); + }); + + it('initializeUser', () => { + (service as any).initializeUser(user); + expect(service.restoreSettingsForUsers).toHaveBeenCalledWith(user); + }); + }); + + describe('initializeUser when there is no metadata field value but there is an anonymous cookie', () => { + const cookie = '{test: \'testt\'}'; + beforeEach(() => { + (service as any).cookieService.get.and.returnValue(cookie); + spyOn(service, 'updateSettingsForUsers'); + }); + + it('initializeUser', () => { + (service as any).initializeUser(user); + expect((service as any).cookieService.set).toHaveBeenCalledWith(service.getStorageName(user.uuid), cookie) + expect(service.updateSettingsForUsers).toHaveBeenCalledWith(user); + }); + }); + + describe('getUser$ when there is no one authenticated', () => { + beforeEach(() => { + (service as any).authService.isAuthenticated.and.returnValue(observableOf(false)); + }); + it('should return undefined', () => { + getTestScheduler().expectObservable((service as any).getUser$()).toBe('(a|)', { a: undefined }); + }); + }); + + describe('getUser$ when there someone is authenticated', () => { + beforeEach(() => { + (service as any).authService.isAuthenticated.and.returnValue(observableOf(true)); + (service as any).authService.getAuthenticatedUserFromStore.and.returnValue(observableOf(user)); + }); + it('should return the user', () => { + getTestScheduler().expectObservable((service as any).getUser$()).toBe('(a|)', { a: user }); + }); + }); + + describe('getSettingsForUser', () => { + const cookieConsentString = '{test: \'testt\'}'; + beforeEach(() => { + user.metadata = {}; + user.metadata[COOKIE_MDFIELD] = [Object.assign(new MetadataValue(), { value: cookieConsentString })]; + spyOn(JSON, 'parse'); + }); + it('should return the cookie consents object', () => { + service.getSettingsForUser(user); + expect(JSON.parse).toHaveBeenCalledWith(cookieConsentString); + }); + }); + + describe('setSettingsForUser when there are changes', () => { + const cookieConsent = { test: 'testt' }; + const cookieConsentString = '{test: \'testt\'}'; + const operation = { op: 'add', path: 'metadata/dc.agreements.cookie', value: cookieConsentString }; + let updatedUser; + + beforeEach(() => { + updatedUser = cloneDeep(user); + + spyOn(updatedUser, 'setMetadata'); + spyOn(JSON, 'stringify').and.returnValue(cookieConsentString); + ePersonService.createPatchFromCache.and.returnValue(observableOf([operation])) + }); + it('should call patch on the data service', () => { + service.setSettingsForUser(updatedUser, cookieConsent); + expect(updatedUser.setMetadata).toHaveBeenCalledWith(COOKIE_MDFIELD, undefined, cookieConsentString); + expect(ePersonService.patch).toHaveBeenCalledWith(updatedUser, [operation]) + }); + }); + + describe('setSettingsForUser when there are no changes', () => { + const cookieConsent = { test: 'testt' }; + const cookieConsentString = '{test: \'testt\'}'; + let updatedUser; + + beforeEach(() => { + updatedUser = cloneDeep(user); + + spyOn(updatedUser, 'setMetadata'); + spyOn(JSON, 'stringify').and.returnValue(cookieConsentString); + ePersonService.createPatchFromCache.and.returnValue(observableOf([])) + }); + it('should not call patch on the data service', () => { + service.setSettingsForUser(updatedUser, cookieConsent); + expect(updatedUser.setMetadata).toHaveBeenCalledWith(COOKIE_MDFIELD, undefined, cookieConsentString); + expect(ePersonService.patch).not.toHaveBeenCalled(); + }); + }); }); + diff --git a/src/app/shared/cookies/browser-klaro.service.ts b/src/app/shared/cookies/browser-klaro.service.ts index 7df91d48e1..88ebead410 100644 --- a/src/app/shared/cookies/browser-klaro.service.ts +++ b/src/app/shared/cookies/browser-klaro.service.ts @@ -1,191 +1,29 @@ import { Injectable } from '@angular/core'; import * as Klaro from 'klaro' -import { BehaviorSubject, Observable } from 'rxjs'; -import { TOKENITEM } from '../../core/auth/models/auth-token-info.model'; -import { AuthService, IMPERSONATING_COOKIE, REDIRECT_COOKIE } from '../../core/auth/auth.service'; -import { LANG_COOKIE } from '../../core/locale/locale.service'; +import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs'; +import { AuthService } from '../../core/auth/auth.service'; import { TranslateService } from '@ngx-translate/core'; import { environment } from '../../../environments/environment'; -import { map, switchMap, take, tap } from 'rxjs/operators'; +import { switchMap, take } from 'rxjs/operators'; import { EPerson } from '../../core/eperson/models/eperson.model'; -import { of as observableOf, combineLatest as observableCombineLatest } from 'rxjs'; import { KlaroService } from './klaro.service'; -import { hasValue } from '../empty.util'; +import { hasValue, isNotEmpty } from '../empty.util'; import { CookieService } from '../../core/services/cookie.service'; import { EPersonDataService } from '../../core/eperson/eperson-data.service'; +import { cloneDeep } from 'lodash'; +import { klaroConfiguration } from './klaro-configuration'; +import { Operation } from 'fast-json-patch'; export const HAS_AGREED_END_USER = 'dsHasAgreedEndUser'; export const COOKIE_MDFIELD = 'dspace.agreements.cookies'; +export const ANONYMOUS_STORAGE_NAME_KLARO = 'klaro-anonymous'; const cookieNameMessagePrefix = 'cookies.consent.app.title.'; const cookieDescriptionMessagePrefix = 'cookies.consent.app.description.'; const cookiePurposeMessagePrefix = 'cookies.consent.purpose.'; @Injectable() export class BrowserKlaroService extends KlaroService { - - message$: BehaviorSubject = new BehaviorSubject(''); - - klaroConfig: any = { - storageName: this.getStorageName('anonymous'), - - privacyPolicy: '/info/privacy', - - /* - Setting 'hideLearnMore' to 'true' will hide the "learn more / customize" link in - the consent notice. We strongly advise against using this under most - circumstances, as it keeps the user from customizing his/her consent choices. - */ - hideLearnMore: false, - - /* - Setting 'acceptAll' to 'true' will show an "accept all" button in the notice and - modal, which will enable all third-party apps if the user clicks on it. If set - to 'false', there will be an "accept" button that will only enable the apps that - are enabled in the consent modal. - */ - acceptAll: true, - - /* - You can also set a custom expiration time for the Klaro cookie. By default, it - will expire after 30 days. Only relevant if 'storageMethod' is set to 'cookie'. - */ - cookieExpiresAfterDays: 365, - - htmlTexts: true, - - /* - You can overwrite existing translations and add translations for your app - descriptions and purposes. See `src/translations/` for a full list of - translations that can be overwritten: - https://github.com/KIProtect/klaro/tree/master/src/translations - */ - translations: { - en: { - acceptAll: 'cookies.consent.accept-all', - acceptSelected: 'cookies.consent.accept-selected', - app: { - optOut: { - description: 'cookies.consent.app.opt-out.description', - title: 'cookies.consent.app.opt-out.title' - }, - purpose: 'cookies.consent.app.purpose', - purposes: 'cookies.consent.app.purposes', - required: { - description: 'cookies.consent.app.required.description', - title: 'cookies.consent.app.required.title' - } - }, - close: 'cookies.consent.close', - decline: 'cookies.consent.decline', - consentNotice: { - description: 'cookies.consent.content-notice.description', - learnMore: 'cookies.consent.content-notice.learnMore' - }, - consentModal: { - description: 'cookies.consent.content-modal.description', - privacyPolicy: { - name: 'cookies.consent.content-modal.privacy-policy.name', - text: 'cookies.consent.content-modal.privacy-policy.text' - }, - title: 'cookies.consent.content-modal.title' - }, - purposes: {} - } - }, - apps: [ - { - name: 'token_item', - purposes: ['authentication'], - required: true, - cookies: [ - TOKENITEM - ] - }, - { - name: 'impersonation', - purposes: ['authentication'], - required: true, - cookies: [ - IMPERSONATING_COOKIE - ] - }, - { - name: 'redirect', - purposes: ['authentication'], - required: true, - cookies: [ - REDIRECT_COOKIE - ] - }, - { - name: 'language', - purposes: ['preferences'], - required: true, - cookies: [ - LANG_COOKIE - ] - }, - { - name: 'klaro', - purposes: ['acknowledgement'], - required: true, - cookies: [ - [/^klaro-.+$/], - ] - }, - { - name: 'has_agreed_end_user', - purposes: ['acknowledgement'], - required: true, - cookies: [ - HAS_AGREED_END_USER - ] - }, - { - name: 'google-analytics', - purposes: ['statistics'], - required: false, - cookies: [ - // /* - // you an either only provide a cookie name or regular expression (regex) or a list - // consisting of a name or regex, a path and a cookie domain. Providing a path and - // domain is necessary if you have apps that set cookies for a path that is not - // "/", or a domain that is not the current domain. If you do not set these values - // properly, the cookie can't be deleted by Klaro, as there is no way to access the - // path or domain of a cookie in JS. Notice that it is not possible to delete - // cookies that were set on a third-party domain, or cookies that have the HTTPOnly - // attribute: https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#new- - // cookie_domain - // */ - // - // /* - // This rule will match cookies that contain the string '_pk_' and that are set on - // the path '/' and the domain 'klaro.kiprotect.com' - // */ - [/^_ga.?$/], - [/^_gid$/], - // - // /* - // Same as above, only for the 'localhost' domain - // */ - // [/^_pk_.*$/, '/', 'localhost'], - // - // /* - // This rule will match all cookies named 'piwik_ignore' that are set on the path - // '/' on the current domain - // */ - // 'piwik_ignore', - ], - /* - If 'onlyOnce' is set to 'true', the app will only be executed once regardless - how often the user toggles it on and off. This is relevant e.g. for tracking - scripts that would generate new page view events every time Klaro disables and - re-enables them due to a consent change by the user. - */ - onlyOnce: true, - }, - ], - }; + klaroConfig = klaroConfiguration; constructor( private translateService: TranslateService, @@ -196,39 +34,17 @@ export class BrowserKlaroService extends KlaroService { } initialize() { - - /** - * Make sure the fallback language is english - */ this.translateService.setDefaultLang(environment.defaultLanguage); - const user$: Observable = this.authService.isAuthenticated() - .pipe( - take(1), - switchMap((loggedIn: boolean) => { - console.log('loggedIn', loggedIn); - if (loggedIn) { - return this.authService.getAuthenticatedUserFromStore(); - } - return observableOf(undefined); - }), - take(1) - ); + const user$: Observable = this.getUser$(); const translationServiceReady$ = this.translateService.get('loading.default').pipe(take(1)); observableCombineLatest(user$, translationServiceReady$) .subscribe(([user, translation]: [EPerson, string]) => { + user = cloneDeep(user); if (hasValue(user)) { - this.klaroConfig.callback = (consent, app) => this.updateSettingsForUsers(user); - this.klaroConfig.storageName = this.getStorageName(user.uuid); - - const anonCookie = this.cookieService.get(this.getStorageName('anonymous')); - if (hasValue(this.getSettingsForUser(user))) { - this.restoreSettingsForUsers(user); - } else if (hasValue(anonCookie)) { - this.cookieService.set(this.getStorageName(user.uuid), anonCookie); - } + this.initializeUser(user); } /** @@ -248,6 +64,33 @@ export class BrowserKlaroService extends KlaroService { } + private initializeUser(user: EPerson) { + this.klaroConfig.callback = (consent, app) => this.updateSettingsForUsers(user); + this.klaroConfig.storageName = this.getStorageName(user.uuid); + + const anonCookie = this.cookieService.get(ANONYMOUS_STORAGE_NAME_KLARO); + if (hasValue(this.getSettingsForUser(user))) { + this.restoreSettingsForUsers(user); + } else if (hasValue(anonCookie)) { + this.cookieService.set(this.getStorageName(user.uuid), anonCookie); + this.updateSettingsForUsers(user); + } + } + + private getUser$() { + return this.authService.isAuthenticated() + .pipe( + take(1), + switchMap((loggedIn: boolean) => { + if (loggedIn) { + return this.authService.getAuthenticatedUserFromStore(); + } + return observableOf(undefined); + }), + take(1) + ); + } + private getTitleTranslation(title: string) { return cookieNameMessagePrefix + title; } @@ -283,6 +126,11 @@ export class BrowserKlaroService extends KlaroService { * Translate the translation section from the Klaro configuration */ translateConfiguration() { + /** + * Make sure the fallback language is english + */ + this.translateService.setDefaultLang(environment.defaultLanguage); + this.translate(this.klaroConfig.translations.en); } @@ -297,21 +145,30 @@ export class BrowserKlaroService extends KlaroService { } getSettingsForUser(user: EPerson) { - return JSON.parse(user.firstMetadataValue(COOKIE_MDFIELD)); + const mdValue = user.firstMetadataValue(COOKIE_MDFIELD); + return hasValue(mdValue) ? JSON.parse(mdValue) : undefined; } setSettingsForUser(user: EPerson, config: object) { user.setMetadata(COOKIE_MDFIELD, undefined, JSON.stringify(config)); - this.ePersonService.update(user); + this.ePersonService.createPatchFromCache(user) + .pipe( + take(1), + switchMap((operations: Operation[]) => { + if (isNotEmpty(operations)) { + return this.ePersonService.patch(user, operations) + } + return observableOf(undefined) + } + ) + ).subscribe(); } restoreSettingsForUsers(user: EPerson) { - console.log('restore klaro', user); this.cookieService.set(this.getStorageName(user.uuid), this.getSettingsForUser(user)); } updateSettingsForUsers(user: EPerson) { - console.log('update klaro', user); this.setSettingsForUser(user, this.cookieService.get(this.getStorageName(user.uuid))) } diff --git a/src/app/shared/cookies/klaro-configuration.ts b/src/app/shared/cookies/klaro-configuration.ts new file mode 100644 index 0000000000..b97bede986 --- /dev/null +++ b/src/app/shared/cookies/klaro-configuration.ts @@ -0,0 +1,166 @@ +import { TOKENITEM } from '../../core/auth/models/auth-token-info.model'; +import { IMPERSONATING_COOKIE, REDIRECT_COOKIE } from '../../core/auth/auth.service'; +import { LANG_COOKIE } from '../../core/locale/locale.service'; +import { ANONYMOUS_STORAGE_NAME_KLARO, HAS_AGREED_END_USER } from './browser-klaro.service'; + +export const klaroConfiguration: any = { + storageName: ANONYMOUS_STORAGE_NAME_KLARO, + + privacyPolicy: '/info/privacy', + + /* + Setting 'hideLearnMore' to 'true' will hide the "learn more / customize" link in + the consent notice. We strongly advise against using this under most + circumstances, as it keeps the user from customizing his/her consent choices. + */ + hideLearnMore: false, + + /* + Setting 'acceptAll' to 'true' will show an "accept all" button in the notice and + modal, which will enable all third-party apps if the user clicks on it. If set + to 'false', there will be an "accept" button that will only enable the apps that + are enabled in the consent modal. + */ + acceptAll: true, + + /* + You can also set a custom expiration time for the Klaro cookie. By default, it + will expire after 30 days. Only relevant if 'storageMethod' is set to 'cookie'. + */ + cookieExpiresAfterDays: 365, + + htmlTexts: true, + + /* + You can overwrite existing translations and add translations for your app + descriptions and purposes. See `src/translations/` for a full list of + translations that can be overwritten: + https://github.com/KIProtect/klaro/tree/master/src/translations + */ + translations: { + en: { + acceptAll: 'cookies.consent.accept-all', + acceptSelected: 'cookies.consent.accept-selected', + app: { + optOut: { + description: 'cookies.consent.app.opt-out.description', + title: 'cookies.consent.app.opt-out.title' + }, + purpose: 'cookies.consent.app.purpose', + purposes: 'cookies.consent.app.purposes', + required: { + description: 'cookies.consent.app.required.description', + title: 'cookies.consent.app.required.title' + } + }, + close: 'cookies.consent.close', + decline: 'cookies.consent.decline', + consentNotice: { + description: 'cookies.consent.content-notice.description', + learnMore: 'cookies.consent.content-notice.learnMore' + }, + consentModal: { + description: 'cookies.consent.content-modal.description', + privacyPolicy: { + name: 'cookies.consent.content-modal.privacy-policy.name', + text: 'cookies.consent.content-modal.privacy-policy.text' + }, + title: 'cookies.consent.content-modal.title' + }, + purposes: {} + } + }, + apps: [ + { + name: 'token_item', + purposes: ['authentication'], + required: true, + cookies: [ + TOKENITEM + ] + }, + { + name: 'impersonation', + purposes: ['authentication'], + required: true, + cookies: [ + IMPERSONATING_COOKIE + ] + }, + { + name: 'redirect', + purposes: ['authentication'], + required: true, + cookies: [ + REDIRECT_COOKIE + ] + }, + { + name: 'language', + purposes: ['preferences'], + required: true, + cookies: [ + LANG_COOKIE + ] + }, + { + name: 'klaro', + purposes: ['acknowledgement'], + required: true, + cookies: [ + [/^klaro-.+$/], + ] + }, + { + name: 'has_agreed_end_user', + purposes: ['acknowledgement'], + required: true, + cookies: [ + HAS_AGREED_END_USER + ] + }, + { + name: 'google-analytics', + purposes: ['statistics'], + required: false, + cookies: [ + // /* + // you an either only provide a cookie name or regular expression (regex) or a list + // consisting of a name or regex, a path and a cookie domain. Providing a path and + // domain is necessary if you have apps that set cookies for a path that is not + // "/", or a domain that is not the current domain. If you do not set these values + // properly, the cookie can't be deleted by Klaro, as there is no way to access the + // path or domain of a cookie in JS. Notice that it is not possible to delete + // cookies that were set on a third-party domain, or cookies that have the HTTPOnly + // attribute: https://developer.mozilla.org/en-US/docs/Web/API/Document/cookie#new- + // cookie_domain + // */ + // + // /* + // This rule will match cookies that contain the string '_pk_' and that are set on + // the path '/' and the domain 'klaro.kiprotect.com' + // */ + [/^_ga.?$/], + [/^_gid$/], + // + // /* + // Same as above, only for the 'localhost' domain + // */ + // [/^_pk_.*$/, '/', 'localhost'], + // + // /* + // This rule will match all cookies named 'piwik_ignore' that are set on the path + // '/' on the current domain + // */ + // 'piwik_ignore', + ], + /* + If 'onlyOnce' is set to 'true', the app will only be executed once regardless + how often the user toggles it on and off. This is relevant e.g. for tracking + scripts that would generate new page view events every time Klaro disables and + re-enables them due to a consent change by the user. + */ + onlyOnce: true, + }, + ], +}; diff --git a/src/app/shared/cookies/klaro.effects.ts b/src/app/shared/cookies/klaro.effects.ts deleted file mode 100644 index 5409779978..0000000000 --- a/src/app/shared/cookies/klaro.effects.ts +++ /dev/null @@ -1,3 +0,0 @@ -export class KlaroEffects { - -} diff --git a/src/app/shared/mocks/translate.service.mock.ts b/src/app/shared/mocks/translate.service.mock.ts index 8106b3788f..0bc172b408 100644 --- a/src/app/shared/mocks/translate.service.mock.ts +++ b/src/app/shared/mocks/translate.service.mock.ts @@ -3,6 +3,7 @@ import { TranslateService } from '@ngx-translate/core'; export function getMockTranslateService(): TranslateService { return jasmine.createSpyObj('translateService', { get: jasmine.createSpy('get'), - instant: jasmine.createSpy('instant') + instant: jasmine.createSpy('instant'), + setDefaultLang: jasmine.createSpy('setDefaultLang') }); }