Skip to content

Commit

Permalink
fix(permutive-rtd): merge external submodule params
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonioGargaro committed Aug 23, 2022
1 parent 7e5548e commit 5bbb8b7
Show file tree
Hide file tree
Showing 2 changed files with 207 additions and 10 deletions.
63 changes: 55 additions & 8 deletions modules/permutiveRtdProvider.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@
import {getGlobal} from '../src/prebidGlobal.js';
import {submodule} from '../src/hook.js';
import {getStorageManager} from '../src/storageManager.js';
import {deepAccess, deepSetValue, isFn, logError, mergeDeep} from '../src/utils.js';
import {deepAccess, deepSetValue, isFn, logError, mergeDeep, isPlainObject, safeJSONParse} from '../src/utils.js';
import {includes} from '../src/polyfill.js';

const MODULE_NAME = 'permutive'

export const PERMUTIVE_SUBMODULE_CONFIG_KEY = 'permutive-prebid-rtd'

export const storage = getStorageManager({gvlid: null, moduleName: MODULE_NAME})

function init (moduleConfig, userConsent) {
function init(moduleConfig, userConsent) {
readPermutiveModuleConfigFromCache()

return true
}

Expand Down Expand Up @@ -43,20 +47,63 @@ export function initSegments (reqBidsConfigObj, callback, customModuleConfig) {
}
}

function liftIntoParams(params) {
return isPlainObject(params) ? { params } : {}
}

let cachedPermutiveModuleConfig = {}

/**
* Merges segments into existing bidder config
* Access the submodules RTD params that are cached to LocalStorage by the Permutive SDK. This lets the RTD submodule
* apply publisher defined params set in the Permutive platform, so they may still be applied if the Permutive SDK has
* not initialised before this submodule is initialised.
*/
function readPermutiveModuleConfigFromCache() {
const params = safeJSONParse(window.localStorage.getItem(PERMUTIVE_SUBMODULE_CONFIG_KEY))
return cachedPermutiveModuleConfig = liftIntoParams(params)
}

/**
* Access the submodules RTD params attached to the Permutive SDK.
*
* @return The Permutive config available by the Permutive SDK or null if the operation errors.
*/
function getParamsFromPermutive() {
try {
return liftIntoParams(window.permutive.addons.prebid.getPermutiveRtdConfig())
} catch (e) {
return null
}
}

/**
* Merges segments into existing bidder config in reverse priority order. The highest priority is 1.
*
* 1. customModuleConfig <- set by publisher with pbjs.setConfig
* 2. permutiveRtdConfig <- set by the publisher using the Permutive platform
* 3. defaultConfig
*
* As items with a higher priority will be deeply merged into the previous config, deep merges are performed by
* reversing the priority order.
*
* @param {Object} customModuleConfig - Publisher config for module
* @return {Object} Merged defatul and custom config
* @return {Object} Deep merges of the default, Permutive and custom config.
*/
function getModuleConfig (customModuleConfig) {
export function getModuleConfig(customModuleConfig) {
// Use the params from Permutive if available, otherwise fallback to the cached value set by Permutive.
const permutiveModuleConfig = getParamsFromPermutive() || cachedPermutiveModuleConfig

return mergeDeep({
waitForIt: false,
params: {
maxSegs: 500,
acBidders: [],
overwrites: {}
}
}, customModuleConfig)
overwrites: {},
},
},
permutiveModuleConfig,
customModuleConfig,
)
}

/**
Expand Down
154 changes: 152 additions & 2 deletions test/spec/modules/permutiveRtdProvider_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import {
initSegments,
isAcEnabled,
isPermutiveOnPage,
setBidderRtb
setBidderRtb,
getModuleConfig,
PERMUTIVE_SUBMODULE_CONFIG_KEY,
} from 'modules/permutiveRtdProvider.js'
import { deepAccess } from '../../../src/utils.js'
import { deepAccess, deepSetValue, mergeDeep } from '../../../src/utils.js'
import { config } from 'src/config.js'

describe('permutiveRtdProvider', function () {
Expand All @@ -29,6 +31,154 @@ describe('permutiveRtdProvider', function () {
})
})

describe('getModuleConfig', function () {
beforeEach(function () {
// Reads data from the cache
permutiveSubmodule.init()
})

const liftToParams = (params) => ({ params })

const getDefaultConfig = () => ({
waitForIt: false,
params: {
maxSegs: 500,
acBidders: [],
overwrites: {},
},
})

const storeConfigInCacheAndInit = (data) => {
const dataToStore = { [PERMUTIVE_SUBMODULE_CONFIG_KEY]: data }
setLocalStorage(dataToStore)
// Reads data from the cache
permutiveSubmodule.init()

// Cleanup
return () => removeLocalStorage(dataToStore)
}

const setWindowPermutivePrebid = (getPermutiveRtdConfig) => {
// Read from Permutive
const backup = window.permutive

deepSetValue(window, 'permutive.addons.prebid', {
getPermutiveRtdConfig,
})

// Cleanup
return () => window.permutive = backup
}

it('should return default values', function () {
const config = getModuleConfig({})
expect(config).to.deep.equal(getDefaultConfig())
})

it('should override deeply on custom config', function () {
const defaultConfig = getDefaultConfig()

const customModuleConfig = { waitForIt: true, params: { acBidders: ['123'] } }
const config = getModuleConfig(customModuleConfig)

expect(config).to.deep.equal(mergeDeep(defaultConfig, customModuleConfig))
})

it('should override deeply on cached config', function () {
const defaultConfig = getDefaultConfig()

const cachedParamsConfig = { acBidders: ['123'] }
const cleanupCache = storeConfigInCacheAndInit(cachedParamsConfig)

const config = getModuleConfig({})

expect(config).to.deep.equal(mergeDeep(defaultConfig, liftToParams(cachedParamsConfig)))

// Cleanup
cleanupCache()
})

it('should override deeply on Permutive Rtd config', function () {
const defaultConfig = getDefaultConfig()

const permutiveRtdConfigParams = { acBidders: ['123'], overwrites: { '123': true } }
const cleanupPermutive = setWindowPermutivePrebid(function () {
return permutiveRtdConfigParams
})

const config = getModuleConfig({})

expect(config).to.deep.equal(mergeDeep(defaultConfig, liftToParams(permutiveRtdConfigParams)))

// Cleanup
cleanupPermutive()
})

it('should NOT use cached Permutive Rtd config if window.permutive is available', function () {
const defaultConfig = getDefaultConfig()

// As Permutive is available on the window object, this value won't be used.
const cachedParamsConfig = { acBidders: ['123'] }
const cleanupCache = storeConfigInCacheAndInit(cachedParamsConfig)

const permutiveRtdConfigParams = { acBidders: ['456'], overwrites: { '123': true } }
const cleanupPermutive = setWindowPermutivePrebid(function () {
return permutiveRtdConfigParams
})

const config = getModuleConfig({})

expect(config).to.deep.equal(mergeDeep(defaultConfig, liftToParams(permutiveRtdConfigParams)))

// Cleanup
cleanupCache()
cleanupPermutive()
})

it('should handle calling Permutive method throwing error', function () {
const defaultConfig = getDefaultConfig()

const cleanupPermutive = setWindowPermutivePrebid(function () {
throw new Error()
})

const config = getModuleConfig({})

expect(config).to.deep.equal(defaultConfig)

// Cleanup
cleanupPermutive()
})

it('should override deeply in priority order', function () {
const defaultConfig = getDefaultConfig()

// As Permutive is available on the window object, this value won't be used.
const cachedConfig = { acBidders: ['123'] }
const cleanupCache = storeConfigInCacheAndInit(cachedConfig)

// Read from Permutive
const permutiveRtdConfig = { acBidders: ['456'] }
const cleanupPermutive = setWindowPermutivePrebid(function () {
return permutiveRtdConfig
})

const customModuleConfig = { params: { acBidders: ['789'], maxSegs: 499 } }
const config = getModuleConfig(customModuleConfig)

// The configs are in reverse priority order as configs are merged left to right. So the priority is,
// 1. customModuleConfig <- set by publisher with pbjs.setConfig
// 2. permutiveRtdConfig <- set by the publisher using Permutive.
// 3. defaultConfig
const configMergedInPriorityOrder = mergeDeep(defaultConfig, liftToParams(permutiveRtdConfig), customModuleConfig)
expect(config).to.deep.equal(configMergedInPriorityOrder)

// Cleanup
cleanupCache()
cleanupPermutive()
})
})

describe('ortb2 config', function () {
beforeEach(function () {
config.resetConfig()
Expand Down

0 comments on commit 5bbb8b7

Please sign in to comment.