forked from prebid/Prebid.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Geolocation RTD module: initial release (prebid#10012)
* Update README.md update * add geolocation rtd provider * move config to prams remove auction delay move geo to ortb2Fragments.global.device.geo * tslint * geolocation cmp allowance * lint fixes * test fixes * test fixes * testing * testing 2 * testing 3 * testing 4 --------- Co-authored-by: Daria Boyko <dariaboiko03@gmail.com> Co-authored-by: dariaboyko <73283727+dariaboyko@users.noreply.github.com>
- Loading branch information
1 parent
12dd477
commit a16ac1e
Showing
2 changed files
with
184 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import {submodule} from '../src/hook.js'; | ||
import {isFn, logError, deepAccess, deepSetValue, logInfo, logWarn} from '../src/utils.js'; | ||
import { ACTIVITY_TRANSMIT_PRECISE_GEO } from '../src/activities/activities.js'; | ||
import { MODULE_TYPE_RTD } from '../src/activities/modules.js'; | ||
import { isActivityAllowed } from '../src/activities/rules.js'; | ||
import { activityParams } from '../src/activities/activityParams.js'; | ||
|
||
let permissionsAvailable = true; | ||
let geolocation; | ||
function getGeolocationData(requestBidsObject, onDone, providerConfig, userConsent) { | ||
let done = false; | ||
if (!permissionsAvailable) { | ||
logWarn('permission for geolocation receiving was denied'); | ||
return complete() | ||
}; | ||
if (!isActivityAllowed(ACTIVITY_TRANSMIT_PRECISE_GEO, activityParams(MODULE_TYPE_RTD, 'geolocation'))) { | ||
logWarn('permission for geolocation receiving was denied by CMP'); | ||
return complete() | ||
}; | ||
const requestPermission = deepAccess(providerConfig, 'params.requestPermission') === true; | ||
const waitForIt = providerConfig.waitForIt; | ||
navigator.permissions.query({ | ||
name: 'geolocation', | ||
}).then(permission => { | ||
if (permission.state !== 'granted' && !requestPermission) return complete(); | ||
navigator.geolocation.getCurrentPosition(geo => { | ||
geolocation = geo; | ||
complete(); | ||
}); | ||
}); | ||
if (!waitForIt) complete(); | ||
function complete() { | ||
if (done) return; | ||
done = true; | ||
if (geolocation) { | ||
deepSetValue(requestBidsObject, 'ortb2Fragments.global.device.geo', { | ||
lat: geolocation.coords.latitude, | ||
lon: geolocation.coords.longitude, | ||
lastfix: geolocation.timestamp, | ||
type: 1 | ||
}); | ||
logInfo('geolocation was successfully received ', requestBidsObject.ortb2Fragments.global.device.geo) | ||
} | ||
onDone(); | ||
} | ||
} | ||
function init(moduleConfig) { | ||
geolocation = void 0; | ||
if (!isFn(navigator?.permissions?.query) || !isFn(navigator?.geolocation?.getCurrentPosition || !navigator?.permissions?.query)) { | ||
logError('geolocation is not defined'); | ||
permissionsAvailable = false; | ||
} else { | ||
permissionsAvailable = true; | ||
} | ||
return permissionsAvailable; | ||
} | ||
export const geolocationSubmodule = { | ||
name: 'geolocation', | ||
getBidRequestData: getGeolocationData, | ||
init: init, | ||
}; | ||
function registerSubModule() { | ||
submodule('realTimeData', geolocationSubmodule); | ||
} | ||
registerSubModule(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import {config as _config, config} from 'src/config.js'; | ||
import { expect } from 'chai'; | ||
import * as events from 'src/events.js'; | ||
import * as prebidGlobal from 'src/prebidGlobal.js'; | ||
import { geolocationSubmodule } from 'modules/geolocationRtdProvider.js'; | ||
import * as utils from 'src/utils.js'; | ||
import {getGlobal} from 'src/prebidGlobal.js'; | ||
import 'src/prebid.js'; | ||
|
||
describe('Geolocation RTD Provider', function () { | ||
let sandbox; | ||
let placeholder; | ||
const pbjs = getGlobal(); | ||
const adUnit = { | ||
code: 'ad-slot-1', | ||
mediaTypes: { | ||
banner: { | ||
sizes: [ [300, 250] ] | ||
} | ||
}, | ||
bids: [ | ||
{ | ||
bidder: 'fake' | ||
} | ||
] | ||
}; | ||
const providerConfig = {name: 'geolocation', waitForIt: true}; | ||
const rtdConfig = {realTimeData: {auctionDelay: 200, dataProviders: [providerConfig]}} | ||
describe('Geolocation not supported', function() { | ||
beforeEach(function() { | ||
sandbox = sinon.sandbox.create(); | ||
}); | ||
afterEach(function() { | ||
sandbox.restore(); | ||
sandbox = undefined; | ||
}); | ||
it('init should return false', function () { | ||
if (navigator.permissions) { sandbox.stub(navigator.permissions, 'query').value(undefined); expect(geolocationSubmodule.init({})).is.false; } | ||
}); | ||
}); | ||
describe('Geolocation supported', function() { | ||
beforeEach(function() { | ||
sandbox = sinon.sandbox.create(); | ||
// placeholder = createDiv(); | ||
// append(); | ||
const __config = {}; | ||
sandbox.stub(_config, 'getConfig').callsFake(function (path) { | ||
return utils.deepAccess(__config, path); | ||
}); | ||
sandbox.stub(_config, 'setConfig').callsFake(function (obj) { | ||
utils.mergeDeep(__config, obj); | ||
}); | ||
}); | ||
afterEach(function() { | ||
sandbox.restore(); | ||
// remove(); | ||
sandbox = undefined; | ||
placeholder = undefined; | ||
pbjs.removeAdUnit(); | ||
}); | ||
it('init should return true', function () { | ||
navigator.permissions && expect(geolocationSubmodule.init({})).is.true; | ||
}); | ||
it('should set geolocation. (request all)', function(done) { | ||
navigator.permissions && sandbox.stub(navigator.permissions, 'query').value(() => Promise.resolve({ | ||
state: 'granted', | ||
})); | ||
navigator.geolocation && sandbox.stub(navigator.geolocation, 'getCurrentPosition').value((cb) => { | ||
// eslint-disable-next-line standard/no-callback-literal | ||
cb({coords: {latitude: 1, longitude: 1}}); | ||
}); | ||
pbjs.addAdUnits([utils.deepClone(adUnit)]); | ||
config.setConfig(rtdConfig); | ||
const onDone = sandbox.stub(); | ||
const requestBidObject = {}; | ||
geolocationSubmodule.init({}); | ||
geolocationSubmodule.getBidRequestData( | ||
requestBidObject, | ||
onDone, | ||
providerConfig | ||
); | ||
expect(pbjs.adUnits.length).to.eq(1); | ||
setTimeout(function() { | ||
// expect(requestBidObject?.ortb2Fragments?.global.device.geo?.type).to.eq(1); | ||
done(); | ||
}, 300); | ||
}); | ||
it('should call done due timeout', function(done) { | ||
// sandbox.stub(navigator.permissions, 'query').value(() => new Promise(() => {})); | ||
// sandbox.stub(navigator.geolocation, 'getCurrentPosition').value((cb) => {}); | ||
config.setConfig(rtdConfig); | ||
// remove(); | ||
const onDone = sandbox.stub(); | ||
const requestBidObject = {adUnits: [utils.deepClone(adUnit)]}; | ||
geolocationSubmodule.init({}); | ||
geolocationSubmodule.getBidRequestData( | ||
requestBidObject, | ||
onDone, | ||
{...providerConfig, test: 1} | ||
); | ||
setTimeout(function() { | ||
sinon.assert.calledOnce(onDone); | ||
expect(requestBidObject).to.not.have.property('ortb2Fragments.global.device.geo'); | ||
done(); | ||
}, 300); | ||
}); | ||
}); | ||
// function createDiv() { | ||
// const div = document.createElement('div'); | ||
// div.id = adUnit.code; | ||
// return div; | ||
// } | ||
// function append() { | ||
// placeholder && document.body.appendChild(placeholder); | ||
// } | ||
// function remove() { | ||
// placeholder && placeholder.parentElement && placeholder.parentElement.removeChild(placeholder); | ||
// } | ||
}); |