diff --git a/docs/src/docs/03-configuration.adoc b/docs/src/docs/03-configuration.adoc index e3317476..e8454f2f 100644 --- a/docs/src/docs/03-configuration.adoc +++ b/docs/src/docs/03-configuration.adoc @@ -42,7 +42,7 @@ To instantiate oil.js with POI activated, make up a name for your company group * Setup a server where the consent cookie is stored. For example `any.domain.com`. * Upload `hub.html` from the `./release` folder, resulting in `https://any.domain.com/hub.html` -* Create a `MyGroupName.json` and upload it in a subfolder named `poi-lists` to your server, resulting in `https://any.domain.com/poi-lists/MyGroupName.json`. Note the file name must be the same as the value passed in poi_group_name. For an example see <>. +* Create a `MyGroupName.json` and upload it in a subfolder named `poi-lists` to your server, resulting in `https://any.domain.com/poi-lists/MyGroupName.json`. Note: The file name must be the same as the value passed in `poi_group_name`. For an example see <>. Note: Enable CORS for the `poi-lists` directory and its contained files. * Make sure the `MyGroupName.json` is served with the right CORS-headers so that your websites are allowed to read it. * Add the required parameters to each website configuration that should share the consent cookie: diff --git a/http_server.js b/http_server.js index 281b034b..45e7b914 100644 --- a/http_server.js +++ b/http_server.js @@ -82,6 +82,7 @@ app.use(compression()); // Serve directory indexes folder (with icons) app.use('/release', cors(), serveIndex('release', {'icons': true})); app.use('/demos', cors(), serveIndex('dist/demos', {'icons': true})); +app.use('/poi-lists', cors(), serveIndex('dist/poi-lists', {'icons': true})); // static with cache headers app.use(serveStatic(DOCUMENT_ROOT, {maxAge: CACHE_DURATION, cacheControl: true})); diff --git a/src/demos/direct-integration.html b/src/demos/direct-integration.html index 3c26cb90..e87a2df6 100644 --- a/src/demos/direct-integration.html +++ b/src/demos/direct-integration.html @@ -27,6 +27,8 @@ "config_version": 1, "poi_activate_poi": true, "poi_group_name": "axelSpringerSe_01", + "poi_hub_origin": "/", + "poi_hub_path": "demos/complete-integration-mypass.html", "timeout": -1 } diff --git a/src/demos/poi-group-blacklist.html b/src/demos/poi-group-blacklist.html index 2e536a6c..57a5b620 100644 --- a/src/demos/poi-group-blacklist.html +++ b/src/demos/poi-group-blacklist.html @@ -13,8 +13,8 @@ "poi_activate_poi": true, "theme": "dark", "poi_group_name": "withBlacklist", - "poi_hub_origin": "https://oil.axelspringer.com", - "poi_hub_path": "/demos/complete-integration-mypass.html", + "poi_hub_origin": "/", + "poi_hub_path": "demos/complete-integration-mypass.html", "iabVendorBlacklist": [2,8], "show_limited_vendors_only": true } diff --git a/src/demos/poi-group-whitelist.html b/src/demos/poi-group-whitelist.html index a67b085f..cf9aafbb 100644 --- a/src/demos/poi-group-whitelist.html +++ b/src/demos/poi-group-whitelist.html @@ -12,8 +12,8 @@ "advanced_settings": true, "poi_activate_poi": true, "poi_group_name": "withWhitelist", - "poi_hub_origin": "https://oil.axelspringer.com", - "poi_hub_path": "/demos/complete-integration-mypass.html", + "poi_hub_origin": "/", + "poi_hub_path": "demos/complete-integration-mypass.html", "iabVendorWhitelist": [2,8], "show_limited_vendors_only": true } diff --git a/src/scripts/core/core_config.js b/src/scripts/core/core_config.js index c6df8951..739a11aa 100644 --- a/src/scripts/core/core_config.js +++ b/src/scripts/core/core_config.js @@ -116,7 +116,7 @@ export function isPoiActive() { export function getHubOrigin() { let origin = getConfigValue(OIL_CONFIG.ATTR_HUB_ORIGIN, 'https://unpkg.com'); if (origin) { - return origin.indexOf('http') !== -1 ? origin : location.protocol + origin; + return origin === '/' || origin.indexOf('http') !== -1 ? origin : location.protocol + origin; } return null; } @@ -199,10 +199,12 @@ export function getLanguageFromLocale(localeVariantName = 'en') { * @returns {string, null} complete iframe orgin */ export function getHubLocation() { - if (getHubOrigin() && getHubPath()) { - return getHubOrigin() + getHubPath(); - } - return null; + return getHubOrigin() + getHubPath(); +} + +export function getPoiListDirectory() { + let hubOrigin = getHubOrigin(); + return hubOrigin.endsWith('/') ? hubOrigin.replace(/\/$/, '/poi-lists') : hubOrigin + '/poi-lists'; } /** diff --git a/src/scripts/poi-list/poi.group.list.js b/src/scripts/poi-list/poi.group.list.js index e5efe128..ac4bd173 100644 --- a/src/scripts/poi-list/poi.group.list.js +++ b/src/scripts/poi-list/poi.group.list.js @@ -1,6 +1,6 @@ import { fetchJsonData, getGlobalOilObject, setGlobalOilObject } from '../core/core_utils'; import { logError } from '../core/core_log'; -import { getPoiGroupName, setIabVendorWhitelist, setIabVendorBlacklist, isPoiActive } from '../core/core_config'; +import { getPoiGroupName, getPoiListDirectory, isPoiActive, setIabVendorBlacklist, setIabVendorWhitelist } from '../core/core_config'; /** * IF POI is enabled: Gets the group list and sets IAB Vendor Whitelist/Blacklist @@ -16,7 +16,7 @@ export function getGroupList() { if (cachedGroupList || !isPoiActive()) { resolve(cachedGroupList); } else { - fetchJsonData(__webpack_public_path__ + 'poi-lists/' + groupName + '.json') + fetchJsonData(`${getPoiListDirectory()}/${groupName}.json`) .then(response => { cachedGroupList = response.companyList; setGlobalOilObject('oilCachedGroupList', cachedGroupList); diff --git a/test/fixtures/config/given.config.with.poiHubOrigin.and.poiHubPath.html b/test/fixtures/config/given.config.with.poiHubOrigin.and.poiHubPath.html new file mode 100644 index 00000000..0e56bcf9 --- /dev/null +++ b/test/fixtures/config/given.config.with.poiHubOrigin.and.poiHubPath.html @@ -0,0 +1,7 @@ + diff --git a/test/fixtures/config/given.config.with.poiHubOrigin.being.slash.html b/test/fixtures/config/given.config.with.poiHubOrigin.being.slash.html new file mode 100644 index 00000000..126a1976 --- /dev/null +++ b/test/fixtures/config/given.config.with.poiHubOrigin.being.slash.html @@ -0,0 +1,7 @@ + diff --git a/test/fixtures/config/given.config.with.poiHubOrigin.ending.with.slash.html b/test/fixtures/config/given.config.with.poiHubOrigin.ending.with.slash.html new file mode 100644 index 00000000..68ce8285 --- /dev/null +++ b/test/fixtures/config/given.config.with.poiHubOrigin.ending.with.slash.html @@ -0,0 +1,7 @@ + diff --git a/test/fixtures/config/given.config.with.poiHubOrigin.without.protocol.html b/test/fixtures/config/given.config.with.poiHubOrigin.without.protocol.html new file mode 100644 index 00000000..0c20ca5c --- /dev/null +++ b/test/fixtures/config/given.config.with.poiHubOrigin.without.protocol.html @@ -0,0 +1,7 @@ + diff --git a/test/specs/core/core_config.spec.js b/test/specs/core/core_config.spec.js index cbca8b5b..a9af64fe 100644 --- a/test/specs/core/core_config.spec.js +++ b/test/specs/core/core_config.spec.js @@ -1,22 +1,25 @@ import { + gdprApplies, getAdvancedSettingsPurposesDefault, getConfigValue, getCookieExpireInDays, getCustomPurposes, getDefaultToOptin, + getHubLocation, + getHubOrigin, getHubPath, getIabVendorBlacklist, getIabVendorWhitelist, + getLanguageFromLocale, getLocale, getLocaleUrl, getLocaleVariantName, - getLanguageFromLocale, getPoiGroupName, + getPoiListDirectory, getPublicPath, - setLocale, - gdprApplies, + getShowLimitedVendors, setGdprApplies, - getShowLimitedVendors + setLocale } from '../../../src/scripts/core/core_config'; import { loadFixture } from '../../test-utils/utils_fixtures'; import * as CoreLog from '../../../src/scripts/core/core_log'; @@ -25,7 +28,6 @@ import { OilVersion } from '../../../src/scripts/core/core_utils'; describe('core_config', () => { - const DEFAULT_FALLBACK_BACKEND_URL = 'https://oil-backend.herokuapp.com/oil/api/userViewLocales/enEN_01'; const EXPECTED_PUBLIC_PATH = '//www/'; const EXPECTED_PUBLIC_PATH_WITH_SLASH = '//www/i-forgot-the-trailing-slash/'; @@ -63,7 +65,7 @@ describe('core_config', () => { }); - describe('getLocaleVariantName', function() { + describe('getLocaleVariantName', function () { it('returns default enEN_01 when locale in config empty', function () { let result = getLocaleVariantName(); @@ -86,24 +88,23 @@ describe('core_config', () => { expect(getLocaleVariantName()).toEqual('floo'); }); - it ('returns default enEN_01 when locale is defined without locale id', function () { + it('returns default enEN_01 when locale is defined without locale id', function () { AS_OIL = { CONFIG: { - locale: { - } + locale: {} } }; expect(getLocaleVariantName()).toEqual('enEN_01'); }); }); - describe('getLanguageFromLocale', function() { + describe('getLanguageFromLocale', function () { - it('retrieves substring from parameter', function() { + it('retrieves substring from parameter', function () { expect(getLanguageFromLocale('foo_bar')).toEqual('fo'); }); - it('returns "en" when parameter is null', function(){ + it('returns "en" when parameter is null', function () { expect(getLanguageFromLocale()).toEqual('en'); }) @@ -156,36 +157,36 @@ describe('core_config', () => { }); - describe('getPublicPath', function() { + describe('getPublicPath', function () { - it('returns publicPath from configuration', function() { + it('returns publicPath from configuration', function () { loadFixture('config/given.config.with.publicPath.html'); expect(getPublicPath()).toEqual(EXPECTED_PUBLIC_PATH); }); - it('adds slash when missing to publicPath', function() { + it('adds slash when missing to publicPath', function () { loadFixture('config/given.config.with.publicPath.noslash.html'); expect(getPublicPath()).toEqual(EXPECTED_PUBLIC_PATH_WITH_SLASH); }); - it('returns undefined when no publicPath in config', function() { + it('returns undefined when no publicPath in config', function () { expect(getPublicPath()).toBeFalsy(); }); }); - describe('gdprApplies', function() { + describe('gdprApplies', function () { - it('returns true when gdpr_applies_globally and gdpr_applies not in config', function() { + it('returns true when gdpr_applies_globally and gdpr_applies not in config', function () { expect(gdprApplies()).toBeTruthy(); }); - it('returns false when gdpr_applies_globally is false and setGdprApplies is not invoked with true', function() { + it('returns false when gdpr_applies_globally is false and setGdprApplies is not invoked with true', function () { loadFixture('config/given.config.with.gdpr.not.applies.html'); expect(gdprApplies()).toBeFalsy(); }); - it('returns true when set after initialisation', function() { + it('returns true when set after initialisation', function () { loadFixture('config/given.config.with.gdpr.not.applies.html'); setGdprApplies(true); expect(gdprApplies()).toBeTruthy(); @@ -193,9 +194,9 @@ describe('core_config', () => { }); - describe('setGdprApplies', function() { + describe('setGdprApplies', function () { - it('sets gdprApplies in configuration', function() { + it('sets gdprApplies in configuration', function () { loadFixture('config/given.config.with.gdpr.not.applies.html'); expect(gdprApplies()).toBeFalsy(); setGdprApplies(true); @@ -206,17 +207,64 @@ describe('core_config', () => { }); - describe('getShowLimitedVendors', function() { - - it('returns false by default', function() { + describe('getShowLimitedVendors', function () { + + it('returns false by default', function () { expect(getShowLimitedVendors()).toEqual(false); }); - it('returns true when show_limited_vendors_only in configuration', function() { + it('returns true when show_limited_vendors_only in configuration', function () { loadFixture('config/given.config.with.advanced.settings.show.limited.vendors.html'); expect(getShowLimitedVendors()).toBeTruthy(); }); }); + describe('getHubOrigin', () => { + + it('returns complete configured hub origin', () => { + loadFixture('config/given.config.with.poiHubOrigin.and.poiHubPath.html'); + expect(getHubOrigin()).toEqual('https://myServer.com'); + }); + + it('returns complete configured hub origin if it is "/"', () => { + loadFixture('config/given.config.with.poiHubOrigin.being.slash.html'); + expect(getHubOrigin()).toEqual('/'); + }); + + it('returns configured hub origin with added protocol it missed', () => { + loadFixture('config/given.config.with.poiHubOrigin.without.protocol.html'); + expect(getHubOrigin()).toEqual('http://myServer.com'); + }); + + }); + + describe('getHubLocation', () => { + + it('returns correct hub location depending on configured hub origin and hub path', () => { + loadFixture('config/given.config.with.poiHubOrigin.and.poiHubPath.html'); + expect(getHubLocation()).toEqual('https://myServer.com/path/to/my/hub.html'); + }); + + }); + + describe('getPoiListDirectory', () => { + + it('returns correct poi list directory depending on configured hub origin ending with "/"', () => { + loadFixture('config/given.config.with.poiHubOrigin.ending.with.slash.html'); + expect(getPoiListDirectory()).toEqual('https://myServer.com/poi-lists'); + }); + + it('returns correct poi list directory depending on configured hub origin not ending with "/"', () => { + loadFixture('config/given.config.with.poiHubOrigin.and.poiHubPath.html'); + expect(getPoiListDirectory()).toEqual('https://myServer.com/poi-lists'); + }); + + it('returns correct poi list directory depending on configured hub origin being "/"', () => { + loadFixture('config/given.config.with.poiHubOrigin.being.slash.html'); + expect(getPoiListDirectory()).toEqual('/poi-lists'); + }); + + }); + }); diff --git a/test/specs/poi-list/oil.company.list.spec.js b/test/specs/poi-list/oil.company.list.spec.js index 43270dd2..fad4f49b 100644 --- a/test/specs/poi-list/oil.company.list.spec.js +++ b/test/specs/poi-list/oil.company.list.spec.js @@ -4,16 +4,17 @@ import { resetOil } from '../../test-utils/utils_reset'; import { getGroupList } from '../../../src/scripts/poi-list/poi.group.list'; import * as CoreUtils from '../../../src/scripts/core/core_utils'; import * as CoreConfig from '../../../src/scripts/core/core_config'; +import * as CoreLog from '../../../src/scripts/core/core_log'; require('jasmine-ajax'); -describe('the company list', () => { +describe('the poi list', () => { beforeEach(() => { resetOil(); }); - describe('template', () => { + describe('poi list template', () => { it('should be loaded with the given elements', () => { loadFixture('config/given.config.example.labels.html'); let result = oilGroupListTemplate(['a', 'b']); @@ -21,7 +22,7 @@ describe('the company list', () => { }); }); - describe('with POI-Blacklist/Whitelist stored in GroupList', () => { + describe('fetching', () => { const testResponse = { companyList: [ @@ -30,34 +31,93 @@ describe('the company list', () => { "Ultra Inc.", "Special Tech Ltd." ], - "iabVendorBlacklist": [1, 2, 3] + "iabVendorBlacklist": [1, 2, 3], + "iabVendorWhitelist": [4, 5] }; - it('should be loaded with POI enabled', (done) => { + it('is disabled if poi is not active', (done) => { + loadFixture('config/given.config.example.labels.html'); + getGroupList().then((result) => { + expect(result).toBeUndefined(); + done(); + }); + }); + + it('is disabled if cached poi group list exists', (done) => { loadFixture('config/given.config.poi.html'); - let fetchSpy = spyOn(CoreUtils, 'fetchJsonData').and.returnValue(new Promise((resolve) => resolve(testResponse))); - let configSpy = spyOn(CoreConfig, 'isPoiActive').and.returnValue(true); - getGroupList() - .then((result) => { - expect(result).toBe(testResponse.companyList); - }) - .finally(() => { - fetchSpy.calls.reset(); - configSpy.calls.reset(); - done(); - }); + spyOn(CoreUtils, 'getGlobalOilObject').and.returnValue(testResponse.companyList); + + getGroupList().then((result) => { + expect(result).toEqual(testResponse.companyList); + done(); + }); }); - it('should not be loaded if POI is disabled', (done) => { - loadFixture('config/given.config.example.labels.html'); - getGroupList() - .then((result) => { - expect(result).toBeUndefined(); + it('is enabled and fetches poi group list for configured poi group', () => { + loadFixture('config/given.config.poi.html'); + + spyOn(CoreUtils, 'fetchJsonData').and.returnValue(Promise.resolve(testResponse)); + spyOn(CoreConfig, 'isPoiActive').and.returnValue(true); + spyOn(CoreConfig, 'getPoiGroupName').and.returnValue('aGroupName'); + spyOn(CoreConfig, 'getPoiListDirectory').and.returnValue('aPoiListDirectory'); + + getGroupList().then((result) => { + expect(result).toEqual(testResponse.companyList); + expect(CoreUtils.fetchJsonData).toHaveBeenCalledWith('aPoiListDirectory/aGroupName.json'); + done(); + }); + }); + + it('is enabled and returns empty group if it fails', () => { + loadFixture('config/given.config.poi.html'); + + spyOn(CoreUtils, 'fetchJsonData').and.returnValue(Promise.reject('something went wrong')); + spyOn(CoreLog, 'logError').and.callThrough(); + spyOn(CoreConfig, 'isPoiActive').and.returnValue(true); + spyOn(CoreConfig, 'getPoiGroupName').and.returnValue('aGroupName'); + + getGroupList().then((result) => { + expect(result).toEqual([]); + expect(CoreLog.logError).toHaveBeenCalledWith(`OIL getGroupList failed and returned error: something went wrong. Group "aGroupName" not found! Please add the JSON file with the correct name.`); + done(); + }); + + }); + + it('is enabled and sets fetched poi group list as new cached poi group list', () => { + loadFixture('config/given.config.poi.html'); + + spyOn(CoreUtils, 'fetchJsonData').and.returnValue(Promise.resolve(testResponse)); + spyOn(CoreUtils, 'setGlobalOilObject').and.callThrough(); + spyOn(CoreConfig, 'isPoiActive').and.returnValue(true); + + getGroupList().then((result) => { + expect(result).toEqual(testResponse.companyList); + expect(CoreUtils.setGlobalOilObject).toHaveBeenCalledWith('oilCachedGroupList', testResponse.companyList); + done(); + }); + }); + + describe('with iab blacklist/whitelist stored in poi list', () => { + + it('should be loaded', (done) => { + loadFixture('config/given.config.poi.html'); + + spyOn(CoreUtils, 'fetchJsonData').and.returnValue(new Promise((resolve) => resolve(testResponse))); + spyOn(CoreConfig, 'isPoiActive').and.returnValue(true); + spyOn(CoreConfig, 'setIabVendorWhitelist').and.callThrough(); + spyOn(CoreConfig, 'setIabVendorBlacklist').and.callThrough(); + + getGroupList().then(() => { + expect(CoreConfig.setIabVendorBlacklist).toHaveBeenCalledWith(testResponse.iabVendorBlacklist); + expect(CoreConfig.setIabVendorWhitelist).toHaveBeenCalledWith(testResponse.iabVendorWhitelist); done(); - }); + }) + }); + }); - }); + }); });