added tests

This commit is contained in:
lotte
2020-09-01 17:59:34 +02:00
parent 19ca179e7a
commit c19f49fb96
7 changed files with 441 additions and 221 deletions

View File

@@ -84,7 +84,6 @@ export class AppComponent implements OnInit, AfterViewInit {
// set the current language code // set the current language code
this.localeService.setCurrentLanguageCode(); this.localeService.setCurrentLanguageCode();
angulartics2GoogleAnalytics.startTracking(); angulartics2GoogleAnalytics.startTracking();
angulartics2DSpace.startTracking(); angulartics2DSpace.startTracking();

View File

@@ -2,7 +2,7 @@ import { HttpClient } from '@angular/common/http';
import { Store } from '@ngrx/store'; import { Store } from '@ngrx/store';
import { Operation } from 'fast-json-patch'; import { Operation } from 'fast-json-patch';
import { Observable } from 'rxjs'; 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 { hasValue, isNotEmpty, isNotEmptyOperator } from '../../shared/empty.util';
import { NotificationOptions } from '../../shared/notifications/models/notification-options.model'; import { NotificationOptions } from '../../shared/notifications/models/notification-options.model';
import { NotificationsService } from '../../shared/notifications/notifications.service'; import { NotificationsService } from '../../shared/notifications/notifications.service';
@@ -378,6 +378,14 @@ export abstract class DataService<T extends CacheableObject> implements UpdateDa
); );
} }
createPatchFromCache(object: T): Observable<Operation[]> {
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 * Send a PUT request for the specified object
* *
@@ -406,18 +414,16 @@ export abstract class DataService<T extends CacheableObject> implements UpdateDa
* @param {DSpaceObject} object The given object * @param {DSpaceObject} object The given object
*/ */
update(object: T): Observable<RemoteData<T>> { update(object: T): Observable<RemoteData<T>> {
const oldVersion$ = this.findByHref(object._links.self.href); return this.createPatchFromCache(object)
return oldVersion$.pipe( .pipe(
getSucceededRemoteData(), mergeMap((operations: Operation[]) => {
getRemoteDataPayload(),
mergeMap((oldVersion: T) => {
const operations = this.comparator.diff(oldVersion, object);
if (isNotEmpty(operations)) { if (isNotEmpty(operations)) {
this.objectCache.addPatch(object._links.self.href, operations); this.objectCache.addPatch(object._links.self.href, operations);
} }
return this.findByHref(object._links.self.href); return this.findByHref(object._links.self.href);
} }
)); )
);
} }
/** /**

View File

@@ -1,12 +1,206 @@
import { TestBed } from '@angular/core/testing'; 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', () => { describe('BrowserKlaroService', () => {
beforeEach(() => TestBed.configureTestingModule({})); 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', () => { it('should be created', () => {
const service: BrowserKlaroService = TestBed.get(BrowserKlaroService);
expect(service).toBeTruthy(); 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();
});
});
});

View File

@@ -1,191 +1,29 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import * as Klaro from 'klaro' import * as Klaro from 'klaro'
import { BehaviorSubject, Observable } from 'rxjs'; import { combineLatest as observableCombineLatest, Observable, of as observableOf } from 'rxjs';
import { TOKENITEM } from '../../core/auth/models/auth-token-info.model'; import { AuthService } from '../../core/auth/auth.service';
import { AuthService, IMPERSONATING_COOKIE, REDIRECT_COOKIE } from '../../core/auth/auth.service';
import { LANG_COOKIE } from '../../core/locale/locale.service';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { environment } from '../../../environments/environment'; 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 { EPerson } from '../../core/eperson/models/eperson.model';
import { of as observableOf, combineLatest as observableCombineLatest } from 'rxjs';
import { KlaroService } from './klaro.service'; import { KlaroService } from './klaro.service';
import { hasValue } from '../empty.util'; import { hasValue, isNotEmpty } from '../empty.util';
import { CookieService } from '../../core/services/cookie.service'; import { CookieService } from '../../core/services/cookie.service';
import { EPersonDataService } from '../../core/eperson/eperson-data.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 HAS_AGREED_END_USER = 'dsHasAgreedEndUser';
export const COOKIE_MDFIELD = 'dspace.agreements.cookies'; export const COOKIE_MDFIELD = 'dspace.agreements.cookies';
export const ANONYMOUS_STORAGE_NAME_KLARO = 'klaro-anonymous';
const cookieNameMessagePrefix = 'cookies.consent.app.title.'; const cookieNameMessagePrefix = 'cookies.consent.app.title.';
const cookieDescriptionMessagePrefix = 'cookies.consent.app.description.'; const cookieDescriptionMessagePrefix = 'cookies.consent.app.description.';
const cookiePurposeMessagePrefix = 'cookies.consent.purpose.'; const cookiePurposeMessagePrefix = 'cookies.consent.purpose.';
@Injectable() @Injectable()
export class BrowserKlaroService extends KlaroService { export class BrowserKlaroService extends KlaroService {
klaroConfig = klaroConfiguration;
message$: BehaviorSubject<string> = new BehaviorSubject<string>('');
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,
},
],
};
constructor( constructor(
private translateService: TranslateService, private translateService: TranslateService,
@@ -196,39 +34,17 @@ export class BrowserKlaroService extends KlaroService {
} }
initialize() { initialize() {
/**
* Make sure the fallback language is english
*/
this.translateService.setDefaultLang(environment.defaultLanguage); this.translateService.setDefaultLang(environment.defaultLanguage);
const user$: Observable<EPerson> = this.authService.isAuthenticated() const user$: Observable<EPerson> = this.getUser$();
.pipe(
take(1),
switchMap((loggedIn: boolean) => {
console.log('loggedIn', loggedIn);
if (loggedIn) {
return this.authService.getAuthenticatedUserFromStore();
}
return observableOf(undefined);
}),
take(1)
);
const translationServiceReady$ = this.translateService.get('loading.default').pipe(take(1)); const translationServiceReady$ = this.translateService.get('loading.default').pipe(take(1));
observableCombineLatest(user$, translationServiceReady$) observableCombineLatest(user$, translationServiceReady$)
.subscribe(([user, translation]: [EPerson, string]) => { .subscribe(([user, translation]: [EPerson, string]) => {
user = cloneDeep(user);
if (hasValue(user)) { if (hasValue(user)) {
this.klaroConfig.callback = (consent, app) => this.updateSettingsForUsers(user); this.initializeUser(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);
}
} }
/** /**
@@ -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) { private getTitleTranslation(title: string) {
return cookieNameMessagePrefix + title; return cookieNameMessagePrefix + title;
} }
@@ -283,6 +126,11 @@ export class BrowserKlaroService extends KlaroService {
* Translate the translation section from the Klaro configuration * Translate the translation section from the Klaro configuration
*/ */
translateConfiguration() { translateConfiguration() {
/**
* Make sure the fallback language is english
*/
this.translateService.setDefaultLang(environment.defaultLanguage);
this.translate(this.klaroConfig.translations.en); this.translate(this.klaroConfig.translations.en);
} }
@@ -297,21 +145,30 @@ export class BrowserKlaroService extends KlaroService {
} }
getSettingsForUser(user: EPerson) { 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) { setSettingsForUser(user: EPerson, config: object) {
user.setMetadata(COOKIE_MDFIELD, undefined, JSON.stringify(config)); 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) { restoreSettingsForUsers(user: EPerson) {
console.log('restore klaro', user);
this.cookieService.set(this.getStorageName(user.uuid), this.getSettingsForUser(user)); this.cookieService.set(this.getStorageName(user.uuid), this.getSettingsForUser(user));
} }
updateSettingsForUsers(user: EPerson) { updateSettingsForUsers(user: EPerson) {
console.log('update klaro', user);
this.setSettingsForUser(user, this.cookieService.get(this.getStorageName(user.uuid))) this.setSettingsForUser(user, this.cookieService.get(this.getStorageName(user.uuid)))
} }

View File

@@ -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,
},
],
};

View File

@@ -1,3 +0,0 @@
export class KlaroEffects {
}

View File

@@ -3,6 +3,7 @@ import { TranslateService } from '@ngx-translate/core';
export function getMockTranslateService(): TranslateService { export function getMockTranslateService(): TranslateService {
return jasmine.createSpyObj('translateService', { return jasmine.createSpyObj('translateService', {
get: jasmine.createSpy('get'), get: jasmine.createSpy('get'),
instant: jasmine.createSpy('instant') instant: jasmine.createSpy('instant'),
setDefaultLang: jasmine.createSpy('setDefaultLang')
}); });
} }