diff --git a/modules/tpmnBidAdapter.js b/modules/tpmnBidAdapter.js index 006357cd4b9..88e89bcd64b 100644 --- a/modules/tpmnBidAdapter.js +++ b/modules/tpmnBidAdapter.js @@ -1,13 +1,16 @@ /* eslint-disable no-tabs */ import { registerBidder } from '../src/adapters/bidderFactory.js'; import { parseUrl, deepAccess } from '../src/utils.js'; +import { getStorageManager } from '../src/storageManager.js'; import { BANNER } from '../src/mediaTypes.js'; +import { config } from '../src/config.js'; export const ADAPTER_VERSION = '1'; const SUPPORTED_AD_TYPES = [BANNER]; - const BIDDER_CODE = 'tpmn'; const URL = 'https://ad.tpmn.co.kr/prebidhb.tpmn'; +const IFRAMESYNC = 'https://ad.tpmn.co.kr/sync.tpmn?type=iframe'; +export const storage = getStorageManager({bidderCode: BIDDER_CODE}); export const spec = { code: BIDDER_CODE, @@ -18,20 +21,20 @@ export const spec = { * @param {object} bid The bid to validate. * @return boolean True if this is a valid bid, and false otherwise. */ - isBidRequestValid: function(bid) { + isBidRequestValid: function (bid) { return 'params' in bid && - 'inventoryId' in bid.params && - 'publisherId' in bid.params && - !isNaN(Number(bid.params.inventoryId)) && - bid.params.inventoryId > 0 && - (typeof bid.mediaTypes.banner.sizes != 'undefined'); // only accepting appropriate sizes + 'inventoryId' in bid.params && + 'publisherId' in bid.params && + !isNaN(Number(bid.params.inventoryId)) && + bid.params.inventoryId > 0 && + (typeof bid.mediaTypes.banner.sizes != 'undefined'); // only accepting appropriate sizes }, /** - * @param {BidRequest[]} bidRequests - * @param {*} bidderRequest - * @return {ServerRequest} - */ + * @param {BidRequest[]} bidRequests + * @param {*} bidderRequest + * @return {ServerRequest} + */ buildRequests: (bidRequests, bidderRequest) => { if (bidRequests.length === 0) { return []; @@ -49,11 +52,11 @@ export const spec = { }]; }, /** - * Unpack the response from the server into a list of bids. - * - * @param {serverResponse} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ + * Unpack the response from the server into a list of bids. + * + * @param {serverResponse} serverResponse A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ interpretResponse: function (serverResponse, serverRequest) { if (!Array.isArray(serverResponse.body)) { return []; @@ -63,7 +66,48 @@ export const spec = { // our server directly returns the format needed by prebid.js so no more // transformation is needed here. return bidResults; - } + }, + + getUserSyncs: function (syncOptions, serverResponses, gdprConsent, uspConsent) { + const syncArr = []; + if (syncOptions.iframeEnabled) { + let policyParam = ''; + if (gdprConsent && gdprConsent.consentString) { + if (typeof gdprConsent.gdprApplies === 'boolean') { + policyParam += `&gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; + } else { + policyParam += `&gdpr=0&gdpr_consent=${gdprConsent.consentString}`; + } + } + if (uspConsent && uspConsent.consentString) { + policyParam += `&ccpa_consent=${uspConsent.consentString}`; + } + const coppa = config.getConfig('coppa') ? 1 : 0; + policyParam += `&coppa=${coppa}`; + syncArr.push({ + type: 'iframe', + url: IFRAMESYNC + policyParam + }) + } else { + syncArr.push({ + type: 'image', + url: 'https://x.bidswitch.net/sync?ssp=tpmn' + }); + syncArr.push({ + type: 'image', + url: 'https://gocm.c.appier.net/tpmn' + }); + syncArr.push({ + type: 'image', + url: 'https://info.mmnneo.com/getGuidRedirect.info?url=https%3A%2F%2Fad.tpmn.co.kr%2Fcookiesync.tpmn%3Ftpmn_nid%3Dbf91e8b3b9d3f1af3fc1d657f090b4fb%26tpmn_buid%3D' + }); + syncArr.push({ + type: 'image', + url: 'https://sync.aralego.com/idSync?redirect=https%3A%2F%2Fad.tpmn.co.kr%2FpixelCt.tpmn%3Ftpmn_nid%3Dde91e8b3b9d3f1af3fc1d657f090b815%26tpmn_buid%3DSspCookieUserId' + }); + } + return syncArr; + }, }; registerBidder(spec); diff --git a/test/spec/modules/tpmnBidAdapter_spec.js b/test/spec/modules/tpmnBidAdapter_spec.js index b4f6882dbe1..468769c2573 100644 --- a/test/spec/modules/tpmnBidAdapter_spec.js +++ b/test/spec/modules/tpmnBidAdapter_spec.js @@ -1,9 +1,39 @@ /* eslint-disable no-tabs */ -import { expect } from 'chai'; -import { spec } from 'modules/tpmnBidAdapter.js'; +import {expect} from 'chai'; +import {spec, storage} from 'modules/tpmnBidAdapter.js'; +import {generateUUID} from '../../../src/utils.js'; +import {newBidder} from '../../../src/adapters/bidderFactory'; +import * as sinon from 'sinon'; -describe('tpmnAdapterTests', function() { - describe('isBidRequestValid', function() { +describe('tpmnAdapterTests', function () { + const adapter = newBidder(spec); + const BIDDER_CODE = 'tpmn'; + let sandbox = sinon.sandbox.create(); + let getCookieStub; + + beforeEach(function () { + $$PREBID_GLOBAL$$.bidderSettings = { + tpmn: { + storageAllowed: true + } + }; + sandbox = sinon.sandbox.create(); + getCookieStub = sinon.stub(storage, 'getCookie'); + }); + + afterEach(function () { + sandbox.restore(); + getCookieStub.restore(); + $$PREBID_GLOBAL$$.bidderSettings = {}; + }); + + describe('inherited functions', function () { + it('exists and is a function', function () { + expect(adapter.callBids).to.exist.and.to.be.a('function') + }) + }); + + describe('isBidRequestValid', function () { let bid = { adUnitCode: 'temp-unitcode', bidder: 'tpmn', @@ -20,17 +50,18 @@ describe('tpmnAdapterTests', function() { } } }; - it('should return true if a bid is valid banner bid request', function() { + + it('should return true if a bid is valid banner bid request', function () { expect(spec.isBidRequestValid(bid)).to.be.equal(true); }); - it('should return false where requried param is missing', function() { + it('should return false where requried param is missing', function () { let bid = Object.assign({}, bid); bid.params = {}; expect(spec.isBidRequestValid(bid)).to.be.equal(false); }); - it('should return false when required param values have invalid type', function() { + it('should return false when required param values have invalid type', function () { let bid = Object.assign({}, bid); bid.params = { 'inventoryId': null, @@ -40,14 +71,14 @@ describe('tpmnAdapterTests', function() { }); }); - describe('buildRequests', function() { - it('should return an empty list if there are no bid requests', function() { + describe('buildRequests', function () { + it('should return an empty list if there are no bid requests', function () { const emptyBidRequests = []; const bidderRequest = {}; const request = spec.buildRequests(emptyBidRequests, bidderRequest); expect(request).to.be.an('array').that.is.empty; }); - it('should generate a POST server request with bidder API url, data', function() { + it('should generate a POST server request with bidder API url, data', function () { const bid = { adUnitCode: 'temp-unitcode', bidder: 'tpmn', @@ -65,13 +96,15 @@ describe('tpmnAdapterTests', function() { } }; const tempBidRequests = [bid]; - const tempBidderRequest = {refererInfo: { - referer: 'http://localhost/test', - site: { - domain: 'localhost', - page: 'http://localhost/test' + const tempBidderRequest = { + refererInfo: { + referer: 'http://localhost/test', + site: { + domain: 'localhost', + page: 'http://localhost/test' + } } - }}; + }; const builtRequest = spec.buildRequests(tempBidRequests, tempBidderRequest); expect(builtRequest).to.have.lengthOf(1); @@ -96,7 +129,7 @@ describe('tpmnAdapterTests', function() { }); }); - describe('interpretResponse', function() { + describe('interpretResponse', function () { const bid = { adUnitCode: 'temp-unitcode', bidder: 'tpmn', @@ -115,12 +148,12 @@ describe('tpmnAdapterTests', function() { }; const tempBidRequests = [bid]; - it('should return an empty aray to indicate no valid bids', function() { + it('should return an empty aray to indicate no valid bids', function () { const emptyServerResponse = {}; const bidResponses = spec.interpretResponse(emptyServerResponse, tempBidRequests); expect(bidResponses).is.an('array').that.is.empty; }); - it('should return an empty array to indicate no valid bids', function() { + it('should return an empty array to indicate no valid bids', function () { const mockBidResult = { requestId: '9cf19229-34f6-4d06-bc1d-0e44e8d616c8', cpm: 10.0, @@ -141,4 +174,36 @@ describe('tpmnAdapterTests', function() { expect(bidResponses).deep.equal([mockBidResult]); }); }); + + describe('getUserSync', function () { + const KEY_ID = 'uuid'; + const TMP_UUID = generateUUID().replace(/-/g, ''); + + it('getCookie mock Test', () => { + const uuid = storage.getCookie(KEY_ID); + expect(uuid).to.equal(undefined); + }); + + it('getCookie mock Test', () => { + expect(TMP_UUID.length).to.equal(32); + getCookieStub.withArgs(KEY_ID).returns(TMP_UUID); + const uuid = storage.getCookie(KEY_ID); + expect(uuid).to.equal(TMP_UUID); + }); + + it('case 1 -> allow iframe', () => { + const syncs = spec.getUserSyncs({iframeEnabled: true, pixelEnabled: true}); + expect(syncs.length).to.equal(1); + expect(syncs[0].type).to.equal('iframe'); + }); + + it('case 2 -> allow pixel with static sync', () => { + const syncs = spec.getUserSyncs({ iframeEnabled: false, pixelEnabled: true }); + expect(syncs.length).to.be.equal(4); + expect(syncs[0].type).to.be.equal('image'); + expect(syncs[1].type).to.be.equal('image'); + expect(syncs[2].type).to.be.equal('image'); + expect(syncs[3].type).to.be.equal('image'); + }); + }); });