From 5c39e3489fa8cd91f80fc24c19f8d8c9506488f0 Mon Sep 17 00:00:00 2001 From: Patrick McCann Date: Wed, 14 Jun 2023 13:58:30 -0400 Subject: [PATCH] Prebid 8: initial release (#10071) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Prebid 8: Delete Inskin (#9868) * Delete inskinBidAdapter.js * Delete inskinBidAdapter.md * Delete inskinBidAdapter_spec.js * Prebid 8: Renaming TrustPid User ID module to Utiq (#9872) * feature: Add trustpid user id module * refactor: Update trustpidSystem module, comments and md file * refactor: Update trustpidSystem file to handle domain setting regardless of message events * refactor: Update trustpidSystem module and dependent tests and docs * refactor: Update trustpid undefined checks and returns * tests: Update trustpid tests * docs: Update trustpid docs typo * refactor: Update trustpid acronyms logic * TrustPid: Remove deprecated acronyms logic * Rename TrustPid User ID module to Utiq --------- Co-authored-by: Tomasz Januszek * RTB-2173: Removing Inmar from Prebid (#8913) * Delete viewability.js (#9873) * Prebid 8: Delete realvu (#9867) * Delete realvuAnalyticsAdapter_spec.js * Delete realvuAnalyticsAdapter.md * Delete realvuAnalyticsAdapter.js * Prebid 8: Delete pubcid (#9869) * Realvu analytics adapter: fix test failures on Edge (#9857) * Realvu analytics adapter: fix test failures on Edge * Remove realVu tests * Delete pubCommonId.js * Delete pubCommonId.md * Delete pubCommonId_spec.js --------- Co-authored-by: Demetrio Girardi * Prebid 8: Delete openxortb and analytics (#9864) * Delete openxOrtbBidAdapter.js * Delete openxOrtbBidAdapter.md * Delete openxOrtbBidAdapter_spec.js * Update openxBidAdapter_spec.js * Delete openxAnalyticsAdapter.js * Delete openxAnalyticsAdapter.md * Delete openxAnalyticsAdapter_spec.js * Core & multiple modules: populate ortb2.source.tid (#9862) * Core & multiple modules: populate ortb2.source.tid * enable codeql for prebid-8 * Prebid 8: IMDS bid adapter - Rename synacormedia adapter (#9381) * CAPT-252: Synacormedia bid adapter: add tmax to requests based upon provided timeouts. * Re-brand synacormedia adapter to imds (iMedia Digitial Services) * Add alias to synacormedia for backwards compatibility --------- Co-authored-by: Timothy M. Ace Co-authored-by: Pratik Chavan * Prebid 8: Dead Module removal (#9887) * Delete liveyieldAnalyticsAdapter_spec.js * Delete liveyieldAnalyticsAdapter.md * Delete liveyieldAnalyticsAdapter.js * Delete glimpseBidAdapter.js * Delete glimpseBidAdapter.md * Delete glimpseBidAdapter_spec.js * Prebid 8: Delete GA analytics - universal analytics (#9866) * Delete googleAnalyticsAdapter.js * Delete googleAnalyticsAdapter.md * Delete googleAnalyticsAdapter_spec.js * Prebid 8: Delete zeus (#9874) * Delete zeusPrimeRtdProvider.md * Delete zeusPrimeRtdProvider.js * Prebid 8: remove special augmentation of `auctionInit` event (#9897) * Prebid 8 - deprecate bidder category translation feature in core (#9898) * prebid 8 - deprecate category translation in core * remove storage export and move mapping data to library file * Prebid 8: Delete adgeneration (#9904) * Delete adgenerationBidAdapter_spec.js * Delete adgenerationBidAdapter.md * Delete adgenerationBidAdapter.js * Prebid 8: do not use hardcoded `bidderCode` in resposes from bid adapters (#9905) * Revert "Prebid 8: Delete adgeneration (#9904)" (#9915) This reverts commit ce984b34fbacd753264bc87c4c6b9fabf4871344. * Prebid 8: No mas mass (#9909) * Delete index.html * Delete mass_spec.js * Delete mass.md * Delete mass.js * Prebid 8: Delete emx (#9918) * Delete emx_digitalBidAdapter.js * Delete emx_digitalBidAdapter.md * Delete emx_digitalBidAdapter_spec.js * Remove Rubicon Analytics for Prebid 8 (#9932) * Prebid 8: stop using transactionId as source.tid on ortb2 payloads (#9916) * Update bizzclickBidAdapter.js * Update rubiconBidAdapter.js * Update gothamadsBidAdapter.js * Update luponmediaBidAdapter.js * Update ozoneBidAdapter.js * Update pubmaticBidAdapter.js * Update improvedigitalBidAdapter.js * Update newspassidBidAdapter.js * Update deltaprojectsBidAdapter.js * Update bizzclickBidAdapter.js * Update deltaprojectsBidAdapter.js * Update gothamadsBidAdapter.js * Update luponmediaBidAdapter.js * Update newspassidBidAdapter.js * Update ozoneBidAdapter.js * Update pubmaticBidAdapter.js * Update rubiconBidAdapter.js * Update improvedigitalBidAdapter_spec.js * Update luponmediaBidAdapter_spec.js * Update rubiconBidAdapter_spec.js * Update improvedigitalBidAdapter.js * Update pubmaticBidAdapter.js * Update improvedigitalBidAdapter.js * Update pubmaticBidAdapter.js * Update pubmaticBidAdapter.js * Update pubmaticBidAdapter_spec.js * Update adtrueBidAdapter.js * Update adtrueBidAdapter_spec.js * Update adtrueBidAdapter.js * Update adtrueBidAdapter_spec.js * Update adtrueBidAdapter_spec.js * Do not call onBidViewable, onBidWon, etc for S2S bids (#9919) * Access x_source.tid from ortb2 object (#9960) * Access x_source.tid from ortb2 object * Fix lint errors * Prebid 8: set pubmatic source.tid to auctionId (#9954) * set source.tid to auctionId * removed changes to test page * added support for setting ext.wrapper.transactionId as well * Prebid 8: use `prebid.floors.floorMin` instead of `prebid.floorMin` (#9899) * Prebid 8: remove shutdown company from appnexus aliases (#9977) * Update appnexusBidAdapter.js * Update appnexusBidAdapter.js * add bidResponse before emitting the event BID_RESPONSE, so that the bid is stored in the auction instance when the event is triggered (#9847) * Multiple modules: use `ortb2.source.tid` and `ortb2Imp.ext.tid` instead of auctionId/transactionId (#9969) * adkernel * aidem * beop * bliink * criteo * feedad * grid * kargo * medianet * optidigital * rubicon * smilewanted * Multiple modules: use `ortb2.source.tid` and `ortb2Imp.ext.tid` instead of auction/transaction IDs * tappx * onetag * use bidderRequestId instead of generateUUID * Epsilon - Prebid v8 changes to remove documentation in coding project (#9966) Co-authored-by: aarprice@publicisgroupe.net * Prebid 8: pick keywords from FPD in addition to bid params (#9917) * extract appnexus-style keyword logic into its own library * refactor appnexus clones to share keyword logic * pick keywords from ortb2 in addition to bid params * Prebid 8: support sizeMapping for video; extract it into a module (#9893) * Core: support sizeMapping for video * make sizeMapping a module * Magnite Analytics Adapter : do not rely on BID_RESPONSE 0cpm rejected bids (#9933) * Magnite Analytics - Do not rely on BID_RESPONSE for rejected bids * use rejection floor constant! * Remove AOL bid adapter (#10030) Co-authored-by: slimkrazy * AdTelligent Bid Adapter: remove onefiftytwo alias (#10025) * Smartadserver Bid Adapter: support GPID (#10004) * Smartadserver Bid Adapter: Add support for SDA user and site * Smartadserver Bid Adapter: Fix SDA support getConfig and add to unit testing * support floors per media type * Add GPP support * Rework payloads enriching * Add gpid support --------- Co-authored-by: Meven Courouble Co-authored-by: Krzysztof Sokół <88041828+smart-adserver@users.noreply.github.com> * chore: update default video placement value [PB-1560] (#9948) Co-authored-by: Chris Corbo * ShareThrough Bid Adapter : fix playerSize (#10011) * fix sharethrough playersize * fix unit test --------- Co-authored-by: Reinout Stevens * GrowthCode RTD : initial release (#9852) * The New RTD Module * GrowthCode new RTD Module * Fixed to Prebid Added Testing Added Docs * Fixed to Prebid Added Testing Added Docs * Completed testing spec * Update the MD file to provide more infomation about what the module does * Update sample to point to the correct server for testing. * Stv Bid Adapter: add schain support (#10010) * initial commit * adapted buildRequests function * refinement pfilter and bcat * refinement * adapted tests for isBidRequestValid,buildRequests * adaptations for test * finished building stvBidAdapter.js * finished: ran tests, coverage 99% * update: rename w->srw, h->srh * adapt stvBidAdapter.md * remove dspx from stv adapters * some changes (missing: getUserSyncs, but is the same as in radsBidAdapter) * added checks in getUserSyncs; ran tests * added schain support (94.8% coverage) * correct schain encoding --------- Co-authored-by: theo_ * fix module type (#10019) * Update ad generation adapter 1.6.0: update userSync (#9984) * Update AdGenerationAdapter: update userSync * update test spec * remove onefiftytwo alias --------- Co-authored-by: Krzysztof Sokół <88041828+krzysztofequativ@users.noreply.github.com> Co-authored-by: Meven Courouble Co-authored-by: Krzysztof Sokół <88041828+smart-adserver@users.noreply.github.com> Co-authored-by: ccorbo Co-authored-by: Chris Corbo Co-authored-by: Reinout Stevens <518971+ReinoutStevens@users.noreply.github.com> Co-authored-by: Reinout Stevens Co-authored-by: southern-growthcode <79725079+southern-growthcode@users.noreply.github.com> Co-authored-by: theo-stv <120092078+theo-stv@users.noreply.github.com> Co-authored-by: theo_ Co-authored-by: Chris Huie Co-authored-by: Takaaki.Kojima * Revert "AdTelligent Bid Adapter: remove onefiftytwo alias (#10025)" (#10032) This reverts commit 88dbc0429739a56b16272d9e51aedd4d2d55b987. * Prebid 8: update PBS adapter defaults to signal support for native js trackers (#9900) * Prebid 8: introduce new `transmitTid` activity control (#10034) * Core: introduce new `transmitTid` activity control and turn off TIDs by default * enable TIDs for e2e tests * set session_id param based on the bidderRequestId (#10049) Co-authored-by: Patrick McCann * appnexus bid adapter - update logic banner adtype in request (#10048) * Prebid 8: do not keep previous floor data on subsequent `setConfig`s (#10051) * Prebid 8: remove NO_BID bids (#9902) * remove NO_BID bids: currency * remove NO_BID bids: priceFloors * remove NO_BID bids: PBS * remove NO_BID status * fix lint * Utiq: Update domain resolving logic and tests (#10044) Co-authored-by: Tomasz Januszek * Prebid 8: Enforcement, lat and long can only come from the request (#10041) * Update apacdexBidAdapter.js * Update ebdrBidAdapter.js * Update mediafuseBidAdapter.js * Update microadBidAdapter.js * Update zetaBidAdapter.js * Update pubwiseBidAdapter.js * Update pubmaticBidAdapter.js * Update ebdrBidAdapter.js * Update microadBidAdapter.js * Update apacdexBidAdapter.js * Update apacdexBidAdapter_spec.js * Update mediafuseBidAdapter_spec.js * Update pubmaticBidAdapter_spec.js * Update microadBidAdapter_spec.js * Update pubmaticBidAdapter_spec.js * Update pubmaticBidAdapter_spec.js * Prebid 8: remove GDPR check when GDPR enforcement is disabled (#10050) * Cadent Bid Adapter: rename emxdigital to cadent (#10069) * rename files * rename bidder_code * rename adapter object * rename remaining references * add alias from emx_digital --------- Co-authored-by: Michael Denton * IX Bid Adapter: remove transactionid usage in complience with prebid 8 [PB-1743] (#10070) Co-authored-by: shahin.rahbariasl * Update cadentApertureMXBidAdapter.js * Prebid 8: Remove Captify (#10072) * Delete captifyRtdProvider.md * Delete captifyRtdProvider_spec.js * Delete captifyRtdProvider_example.html * Delete captifyRtdProvider.js * Update kargoBidAdapter.js * AdagioBidAdapter: prebid-8: stop using auctionid and transactionid (#10079) * AdagioBidAdapter: stop using Prebid.js internal auctionId and transactionId * AdagioBidAdapter: remove transformBidParams() logic * Criteo Bid Adapter : remove usage of bidRequest.auctionId (#10084) * Grid Bid Adapter : removed embedded criteo bid adapter (#10088) * prebid 8 - read ortb segment data in appnexus keywords library functions (#10082) * prebid8 - read ortb segment data in appnexus keywords library functions * remove null condition from segtax map * airgrid RTD provider: use data segments instead of keywords, remove bidder specific handling (#10080) * Prebid 8: improve `transmitTid` logic for PBS adapter (#10092) * Prebid 8: remove bidder specific handling for 1plusX (#10093) * 1plusX: Do not set keywords for appnexus * weborama: remove appnexus specific handling * remove key=value keyword parsing for appnexus and its clones * fix lint * use 1plusX instead of 1plusx * Revert "remove key=value keyword parsing for appnexus and its clones" This reverts commit 80567cddaf7e721eaf343899dc150f95868834c5. * Revert "weborama: remove appnexus specific handling" This reverts commit d6450d17b5d9f27c288f1c9cacfab156d16b3ebf. * 1plusX: add segtax to user data * Update codeql-analysis.yml --------- Co-authored-by: jkthomas Co-authored-by: Tomasz Januszek Co-authored-by: prashuc <105750978+prashuc@users.noreply.github.com> Co-authored-by: Demetrio Girardi Co-authored-by: Timothy Ace Co-authored-by: Timothy M. Ace Co-authored-by: Pratik Chavan Co-authored-by: jsnellbaker <31102355+jsnellbaker@users.noreply.github.com> Co-authored-by: Robert Ray Martinez III Co-authored-by: Andrew Slagle <42588549+spotxslagle@users.noreply.github.com> Co-authored-by: Jason Quaccia Co-authored-by: olafbuitelaar Co-authored-by: Aaron Price <67345931+AaronColbyPrice@users.noreply.github.com> Co-authored-by: aarprice@publicisgroupe.net Co-authored-by: Samuel Adu Co-authored-by: slimkrazy Co-authored-by: Gena Co-authored-by: Krzysztof Sokół <88041828+krzysztofequativ@users.noreply.github.com> Co-authored-by: Meven Courouble Co-authored-by: Krzysztof Sokół <88041828+smart-adserver@users.noreply.github.com> Co-authored-by: ccorbo Co-authored-by: Chris Corbo Co-authored-by: Reinout Stevens <518971+ReinoutStevens@users.noreply.github.com> Co-authored-by: Reinout Stevens Co-authored-by: southern-growthcode <79725079+southern-growthcode@users.noreply.github.com> Co-authored-by: theo-stv <120092078+theo-stv@users.noreply.github.com> Co-authored-by: theo_ Co-authored-by: Chris Huie Co-authored-by: Takaaki.Kojima Co-authored-by: lasloche <62240785+lasloche@users.noreply.github.com> Co-authored-by: EMX Digital <43830380+EMXDigital@users.noreply.github.com> Co-authored-by: Michael Denton Co-authored-by: shahinrahbariasl <56240400+shahinrahbariasl@users.noreply.github.com> Co-authored-by: shahin.rahbariasl Co-authored-by: Olivier Co-authored-by: Léonard Labat --- .github/workflows/codeql-analysis.yml | 4 +- .../gpt/captifyRtdProvider_example.html | 167 -- integrationExamples/mass/index.html | 132 - .../analyticsAdapter/AnalyticsAdapter.js | 8 +- libraries/appnexusKeywords/anKeywords.js | 140 + libraries/categoryTranslationMapping/index.js | 100 + libraries/keywords/keywords.js | 31 + libraries/objectGuard/objectGuard.js | 13 +- libraries/ortbConverter/processors/default.js | 7 +- modules/.submodules.json | 2 +- modules/1plusXRtdProvider.js | 18 +- modules/33acrossBidAdapter.js | 22 +- modules/adWMGBidAdapter.js | 3 +- modules/adagioBidAdapter.js | 48 +- modules/adbookpspBidAdapter.js | 2 +- modules/addefendBidAdapter.js | 1 + modules/adfBidAdapter.js | 6 +- modules/adgenerationBidAdapter.js | 2 +- modules/adkernelAdnBidAdapter.js | 11 +- modules/adkernelBidAdapter.js | 10 +- modules/adprimeBidAdapter.js | 3 +- modules/adqueryBidAdapter.js | 1 + modules/adrelevantisBidAdapter.js | 27 +- modules/adtrueBidAdapter.js | 4 +- modules/aduptechBidAdapter.js | 3 +- modules/advangelistsBidAdapter.js | 1 - modules/adxcgBidAdapter.js | 2 +- modules/adyoulikeBidAdapter.js | 2 +- modules/afpBidAdapter.js | 4 +- modules/aidemBidAdapter.js | 19 +- modules/airgridRtdProvider.js | 77 +- modules/ajaBidAdapter.js | 2 +- modules/alkimiBidAdapter.js | 3 +- modules/amxBidAdapter.js | 1 + modules/aolBidAdapter.js | 462 --- modules/aolBidAdapter.md | 46 - modules/apacdexBidAdapter.js | 6 +- modules/appnexusBidAdapter.js | 130 +- modules/apstreamBidAdapter.js | 1 + modules/asoBidAdapter.js | 2 +- modules/astraoneBidAdapter.js | 2 +- modules/audiencerunBidAdapter.js | 3 +- modules/automatadBidAdapter.js | 10 +- modules/beachfrontBidAdapter.js | 1 - modules/beopBidAdapter.js | 37 +- modules/betweenBidAdapter.js | 3 +- modules/bizzclickBidAdapter.js | 15 +- modules/bliinkBidAdapter.js | 1 + modules/bluebillywigBidAdapter.js | 4 +- modules/braveBidAdapter.js | 16 +- modules/browsiBidAdapter.js | 6 +- ...apter.js => cadentApertureMXBidAdapter.js} | 117 +- ...apter.md => cadentApertureMXBidAdapter.md} | 12 +- modules/captifyRtdProvider.js | 146 - modules/captifyRtdProvider.md | 68 - modules/carodaBidAdapter.js | 1 + modules/ccxBidAdapter.js | 2 +- modules/cleanmedianetBidAdapter.js | 6 +- modules/codefuelBidAdapter.js | 2 +- modules/colossussspBidAdapter.js | 2 +- modules/concertBidAdapter.js | 2 +- modules/connectadBidAdapter.js | 1 + modules/conversantAnalyticsAdapter.js | 2 + modules/conversantAnalyticsAdapter.md | 46 - modules/conversantBidAdapter.js | 28 +- modules/conversantBidAdapter.md | 46 - modules/craftBidAdapter.js | 34 +- modules/criteoBidAdapter.js | 21 +- modules/currency.js | 6 +- modules/dailyhuntBidAdapter.js | 4 +- modules/datablocksBidAdapter.js | 18 +- modules/datawrkzBidAdapter.js | 6 - modules/deltaprojectsBidAdapter.js | 15 +- modules/dianomiBidAdapter.js | 2 +- modules/discoveryBidAdapter.js | 1 + modules/displayioBidAdapter.js | 3 +- modules/dspxBidAdapter.js | 1 + modules/ebdrBidAdapter.js | 5 +- modules/etargetBidAdapter.js | 3 +- modules/feedadBidAdapter.js | 2 +- modules/finativeBidAdapter.js | 16 +- modules/fluctBidAdapter.js | 3 +- modules/gamoshiBidAdapter.js | 6 +- modules/gdprEnforcement.js | 15 - modules/genericAnalyticsAdapter.js | 5 - modules/glimpseBidAdapter.js | 198 -- modules/glimpseBidAdapter.md | 37 - modules/glomexBidAdapter.js | 1 + modules/gmosspBidAdapter.js | 2 +- modules/gnetBidAdapter.js | 2 +- modules/goldbachBidAdapter.js | 52 +- modules/googleAnalyticsAdapter.js | 298 -- modules/googleAnalyticsAdapter.md | 38 - modules/gothamadsBidAdapter.js | 7 +- modules/gridBidAdapter.js | 441 +-- modules/gumgumBidAdapter.js | 3 +- modules/h12mediaBidAdapter.js | 2 +- modules/holidBidAdapter.js | 21 +- modules/hybridBidAdapter.js | 4 +- ...ormediaBidAdapter.js => imdsBidAdapter.js} | 19 +- ...ormediaBidAdapter.md => imdsBidAdapter.md} | 10 +- modules/impactifyBidAdapter.js | 12 +- modules/improvedigitalBidAdapter.js | 3 +- modules/inmarBidAdapter.js | 132 - modules/inmarBidAdapter.md | 44 - modules/innityBidAdapter.js | 1 + modules/inskinBidAdapter.js | 391 --- modules/inskinBidAdapter.md | 31 - modules/insticatorBidAdapter.js | 2 +- modules/interactiveOffersBidAdapter.js | 9 +- modules/iqmBidAdapter.js | 1 + modules/ixBidAdapter.js | 149 +- modules/jixieBidAdapter.js | 1 + modules/kargoBidAdapter.js | 2 +- modules/koblerBidAdapter.js | 3 +- modules/kueezBidAdapter.js | 2 +- modules/kueezRtbBidAdapter.js | 1 + modules/kulturemediaBidAdapter.js | 14 +- modules/lassoBidAdapter.js | 3 +- modules/limelightDigitalBidAdapter.js | 2 +- modules/livewrappedBidAdapter.js | 4 +- modules/liveyieldAnalyticsAdapter.js | 454 --- modules/liveyieldAnalyticsAdapter.md | 45 - modules/logicadBidAdapter.js | 3 +- modules/loglyliftBidAdapter.js | 3 +- modules/luponmediaBidAdapter.js | 20 +- modules/magniteAnalyticsAdapter.js | 133 +- modules/malltvBidAdapter.js | 1 + modules/mass.js | 184 -- modules/mass.md | 137 - modules/mediaforceBidAdapter.js | 3 +- modules/mediafuseBidAdapter.js | 107 +- modules/mediagoBidAdapter.js | 1 + modules/mediakeysBidAdapter.js | 8 +- modules/medianetBidAdapter.js | 3 +- modules/mediasniperBidAdapter.js | 3 +- modules/mediasquareBidAdapter.js | 3 +- modules/microadBidAdapter.js | 10 +- modules/minutemediaBidAdapter.js | 4 +- modules/minutemediaplusBidAdapter.js | 5 +- modules/newspassidBidAdapter.js | 10 +- modules/nextMillenniumBidAdapter.js | 19 +- modules/oguryBidAdapter.js | 10 +- modules/onetagBidAdapter.js | 3 +- modules/openxAnalyticsAdapter.js | 27 - modules/openxAnalyticsAdapter.md | 135 - modules/openxOrtbBidAdapter.js | 238 -- modules/openxOrtbBidAdapter.md | 108 - modules/operaadsBidAdapter.js | 4 +- modules/optidigitalBidAdapter.js | 4 +- modules/orbidderBidAdapter.js | 3 +- modules/otmBidAdapter.js | 4 +- modules/outbrainBidAdapter.js | 20 +- modules/ozoneBidAdapter.js | 3 +- modules/padsquadBidAdapter.js | 4 +- modules/pixfutureBidAdapter.js | 48 +- modules/prebidServerBidAdapter/index.js | 4 +- .../prebidServerBidAdapter/ortbConverter.js | 39 +- modules/priceFloors.js | 14 +- modules/prismaBidAdapter.js | 7 +- modules/proxistoreBidAdapter.js | 3 +- modules/pubCommonId.js | 303 -- modules/pubCommonId.md | 37 - modules/pubgeniusBidAdapter.js | 10 +- modules/pubmaticAnalyticsAdapter.js | 4 - modules/pubmaticBidAdapter.js | 10 +- modules/pubwiseBidAdapter.js | 11 +- modules/pxyzBidAdapter.js | 8 +- modules/rasBidAdapter.js | 6 +- modules/readpeakBidAdapter.js | 2 +- modules/realvuAnalyticsAdapter.js | 976 ------- modules/realvuAnalyticsAdapter.md | 9 - modules/relaidoBidAdapter.js | 3 +- modules/resetdigitalBidAdapter.js | 1 + modules/revcontentBidAdapter.js | 13 +- modules/rhythmoneBidAdapter.js | 2 - modules/richaudienceBidAdapter.js | 10 +- modules/riseBidAdapter.js | 2 +- modules/rtbhouseBidAdapter.js | 10 +- modules/rtbsapeBidAdapter.js | 1 + modules/rubiconAnalyticsAdapter.js | 938 ------ modules/rubiconBidAdapter.js | 19 +- modules/saambaaBidAdapter.js | 1 - modules/seedingAllianceBidAdapter.js | 13 +- modules/seedtagBidAdapter.js | 2 +- modules/sharethroughBidAdapter.js | 2 +- modules/shinezBidAdapter.js | 870 +++--- modules/showheroes-bsBidAdapter.js | 2 +- {src => modules}/sizeMapping.js | 78 +- modules/slimcutBidAdapter.js | 4 +- modules/smaatoBidAdapter.js | 19 +- modules/smartadserverBidAdapter.js | 2 +- modules/smarticoBidAdapter.js | 1 + modules/smartytechBidAdapter.js | 1 - modules/smilewantedBidAdapter.js | 4 +- modules/sonobiBidAdapter.js | 3 +- modules/sspBCBidAdapter.js | 2 +- modules/stroeerCoreBidAdapter.js | 1 + modules/sublimeBidAdapter.js | 1 + modules/taboolaBidAdapter.js | 6 +- modules/talkadsBidAdapter.js | 1 + modules/tappxBidAdapter.js | 2 +- modules/teadsBidAdapter.js | 2 +- modules/telariaBidAdapter.js | 2 +- modules/theAdxBidAdapter.js | 2 +- modules/tpmnBidAdapter.js | 1 + modules/truereachBidAdapter.js | 1 + modules/trustpidSystem.js | 143 - modules/ttdBidAdapter.js | 6 +- modules/underdogmediaBidAdapter.js | 1 - modules/unicornBidAdapter.js | 2 +- modules/unrulyBidAdapter.js | 2 +- modules/userId/eids.js | 6 +- modules/userId/eids.md | 2 +- modules/userId/index.js | 21 +- modules/userId/userId.md | 22 +- modules/utiqSystem.js | 129 + modules/{trustpidSystem.md => utiqSystem.md} | 14 +- modules/vdoaiBidAdapter.js | 1 + modules/vibrantmediaBidAdapter.js | 2 +- modules/vidazooBidAdapter.js | 5 +- modules/videobyteBidAdapter.js | 1 - modules/videoheroesBidAdapter.js | 2 + modules/videoreachBidAdapter.js | 3 +- modules/viewability.js | 9 - modules/vlybyBidAdapter.js | 1 + modules/voxBidAdapter.js | 2 + modules/vrtcalBidAdapter.js | 2 +- modules/winrBidAdapter.js | 29 +- modules/xeBidAdapter.js | 3 +- modules/yieldliftBidAdapter.js | 4 +- modules/yieldmoBidAdapter.js | 1 + modules/yieldoneBidAdapter.js | 2 +- modules/zetaBidAdapter.js | 13 +- modules/zeta_global_sspBidAdapter.js | 2 +- modules/zeusPrimeRtdProvider.js | 37 - modules/zeusPrimeRtdProvider.md | 63 - src/activities/activities.js | 5 + src/activities/redactor.js | 44 +- src/adapterManager.js | 51 +- src/adapters/bidderFactory.js | 132 +- src/auction.js | 26 +- src/constants.json | 3 +- src/utils.js | 36 +- test/fixtures/fixtures.js | 7 - test/pages/banner.html | 1 + test/pages/bidderSettings.html | 1 + test/pages/consent_mgt_gdpr.html | 1 + test/pages/currency.html | 1 + test/pages/instream.html | 1 + test/pages/multiple_bidders.html | 2 +- test/pages/native.html | 1 + test/pages/outstream.html | 5 +- test/spec/activities/redactor_spec.js | 12 +- test/spec/appnexusKeywords_spec.js | 70 + test/spec/auctionmanager_spec.js | 33 +- test/spec/keywords_spec.js | 102 + test/spec/modules/1plusXRtdProvider_spec.js | 35 +- test/spec/modules/33acrossBidAdapter_spec.js | 122 +- test/spec/modules/adagioBidAdapter_spec.js | 39 +- test/spec/modules/adbookpspBidAdapter_spec.js | 5 + test/spec/modules/adfBidAdapter_spec.js | 5 +- .../modules/adkernelAdnBidAdapter_spec.js | 4 +- .../modules/adrelevantisBidAdapter_spec.js | 9 - test/spec/modules/adriverBidAdapter_spec.js | 9 - test/spec/modules/adtrueBidAdapter_spec.js | 18 +- test/spec/modules/aduptechBidAdapter_spec.js | 34 +- .../modules/advangelistsBidAdapter_spec.js | 1 - test/spec/modules/adxcgBidAdapter_spec.js | 5 +- test/spec/modules/adyoulikeBidAdapter_spec.js | 60 +- test/spec/modules/afpBidAdapter_spec.js | 6 +- test/spec/modules/aidemBidAdapter_spec.js | 12 +- test/spec/modules/airgridRtdProvider_spec.js | 68 +- test/spec/modules/aolBidAdapter_spec.js | 890 ------ test/spec/modules/apacdexBidAdapter_spec.js | 4 +- test/spec/modules/appnexusBidAdapter_spec.js | 127 +- test/spec/modules/astraoneBidAdapter_spec.js | 6 +- .../spec/modules/beachfrontBidAdapter_spec.js | 1 - .../modules/big-richmediaBidAdapter_spec.js | 10 - .../modules/bluebillywigBidAdapter_spec.js | 22 +- test/spec/modules/browsiBidAdapter_spec.js | 9 +- ....js => cadentApertureMXBidAdapter_spec.js} | 32 +- test/spec/modules/captifyRtdProvider_spec.js | 253 -- test/spec/modules/ccxBidAdapter_spec.js | 2 +- .../modules/cleanmedianetBidAdapter_spec.js | 4 +- test/spec/modules/codefuelBidAdapter_spec.js | 11 +- .../modules/colossussspBidAdapter_spec.js | 2 +- test/spec/modules/concertBidAdapter_spec.js | 6 +- .../spec/modules/conversantBidAdapter_spec.js | 9 +- test/spec/modules/criteoBidAdapter_spec.js | 86 +- test/spec/modules/currency_spec.js | 24 +- test/spec/modules/datawrkzBidAdapter_spec.js | 4 - test/spec/modules/dianomiBidAdapter_spec.js | 2 +- test/spec/modules/etargetBidAdapter_spec.js | 43 +- test/spec/modules/euidIdSystem_spec.js | 7 - test/spec/modules/feedadBidAdapter_spec.js | 6 +- test/spec/modules/finativeBidAdapter_spec.js | 12 - test/spec/modules/fluctBidAdapter_spec.js | 2 - test/spec/modules/gamoshiBidAdapter_spec.js | 7 +- test/spec/modules/glimpseBidAdapter_spec.js | 422 --- test/spec/modules/gmosspBidAdapter_spec.js | 6 +- test/spec/modules/gnetBidAdapter_spec.js | 6 +- test/spec/modules/goldbachBidAdapter_spec.js | 10 - .../modules/googleAnalyticsAdapter_spec.js | 27 - test/spec/modules/gridBidAdapter_spec.js | 344 +-- test/spec/modules/hybridBidAdapter_spec.js | 6 +- ...Adapter_spec.js => imdsBidAdapter_spec.js} | 38 +- .../modules/improvedigitalBidAdapter_spec.js | 7 +- test/spec/modules/inmarBidAdapter_spec.js | 242 -- test/spec/modules/inskinBidAdapter_spec.js | 386 --- .../spec/modules/insticatorBidAdapter_spec.js | 8 +- .../modules/invisiblyAnalyticsAdapter_spec.js | 2 +- test/spec/modules/ivsBidAdapter_spec.js | 2 - test/spec/modules/ixBidAdapter_spec.js | 11 +- test/spec/modules/kargoBidAdapter_spec.js | 6 +- test/spec/modules/koblerBidAdapter_spec.js | 15 +- .../modules/kulturemediaBidAdapter_spec.js | 1 - .../limelightDigitalBidAdapter_spec.js | 26 +- .../livewrappedAnalyticsAdapter_spec.js | 2 +- .../modules/livewrappedBidAdapter_spec.js | 11 +- .../modules/liveyieldAnalyticsAdapter_spec.js | 704 ----- test/spec/modules/loglyliftBidAdapter_spec.js | 10 + .../spec/modules/luponmediaBidAdapter_spec.js | 25 +- .../modules/magniteAnalyticsAdapter_spec.js | 94 +- test/spec/modules/mass_spec.js | 141 - .../spec/modules/mediaforceBidAdapter_spec.js | 14 +- test/spec/modules/mediafuseBidAdapter_spec.js | 8 +- test/spec/modules/mediakeysBidAdapter_spec.js | 8 +- test/spec/modules/medianetBidAdapter_spec.js | 103 +- .../modules/mediasniperBidAdapter_spec.js | 2 +- .../modules/mediasquareBidAdapter_spec.js | 10 +- test/spec/modules/microadBidAdapter_spec.js | 10 +- .../modules/minutemediaplusBidAdapter_spec.js | 10 +- .../modules/nextMillenniumBidAdapter_spec.js | 4 +- test/spec/modules/nexx360BidAdapter_spec.js | 1 - test/spec/modules/oguryBidAdapter_spec.js | 3 +- test/spec/modules/onetagBidAdapter_spec.js | 6 +- .../modules/openxAnalyticsAdapter_spec.js | 21 - test/spec/modules/openxBidAdapter_spec.js | 2 +- test/spec/modules/openxOrtbBidAdapter_spec.js | 1615 ----------- test/spec/modules/operaadsBidAdapter_spec.js | 10 +- .../modules/optidigitalBidAdapter_spec.js | 2 - test/spec/modules/orbidderBidAdapter_spec.js | 16 +- test/spec/modules/outbrainBidAdapter_spec.js | 5 + .../modules/prebidServerBidAdapter_spec.js | 146 +- test/spec/modules/priceFloors_spec.js | 32 +- test/spec/modules/pubCommonId_spec.js | 353 --- test/spec/modules/pubgeniusBidAdapter_spec.js | 3 +- test/spec/modules/pubmaticBidAdapter_spec.js | 73 +- test/spec/modules/pubwiseBidAdapter_spec.js | 16 +- test/spec/modules/relaidoBidAdapter_spec.js | 8 +- .../spec/modules/revcontentBidAdapter_spec.js | 10 - .../modules/richaudienceBidAdapter_spec.js | 6 +- .../modules/rubiconAnalyticsAdapter_spec.js | 2540 ----------------- test/spec/modules/rubiconAnalyticsSchema.json | 494 ---- test/spec/modules/rubiconBidAdapter_spec.js | 33 +- test/spec/modules/scatteredBidAdapter_spec.js | 2 - .../modules/seedingAllianceAdapter_spec.js | 13 - test/spec/modules/seedtagBidAdapter_spec.js | 6 +- .../modules/sharethroughBidAdapter_spec.js | 8 +- test/spec/modules/sizeMapping_spec.js | 342 +++ test/spec/modules/slimcutBidAdapter_spec.js | 1 - test/spec/modules/smaatoBidAdapter_spec.js | 5 +- .../modules/smartadserverBidAdapter_spec.js | 18 +- .../modules/smilewantedBidAdapter_spec.js | 31 +- test/spec/modules/sspBCBidAdapter_spec.js | 8 +- test/spec/modules/taboolaBidAdapter_spec.js | 22 +- .../modules/terceptAnalyticsAdapter_spec.js | 1 - test/spec/modules/trustpidSystem_spec.js | 237 -- test/spec/modules/ttdBidAdapter_spec.js | 18 +- test/spec/modules/uid2IdSystem_spec.js | 10 - .../modules/underdogmediaBidAdapter_spec.js | 1 - test/spec/modules/utiqSystem_spec.js | 188 ++ test/spec/modules/vidazooBidAdapter_spec.js | 8 +- test/spec/modules/videobyteBidAdapter_spec.js | 1 - test/spec/modules/winrBidAdapter_spec.js | 9 - test/spec/modules/xeBidAdapter_spec.js | 8 +- test/spec/sizeMapping_spec.js | 341 --- test/spec/unit/core/adapterManager_spec.js | 184 +- test/spec/unit/core/bidderFactory_spec.js | 232 +- test/spec/unit/core/targeting_spec.js | 6 - test/spec/utils_spec.js | 111 +- 382 files changed, 4079 insertions(+), 18367 deletions(-) delete mode 100644 integrationExamples/gpt/captifyRtdProvider_example.html delete mode 100644 integrationExamples/mass/index.html create mode 100644 libraries/appnexusKeywords/anKeywords.js create mode 100644 libraries/categoryTranslationMapping/index.js create mode 100644 libraries/keywords/keywords.js delete mode 100644 modules/aolBidAdapter.js delete mode 100644 modules/aolBidAdapter.md rename modules/{emx_digitalBidAdapter.js => cadentApertureMXBidAdapter.js} (77%) rename modules/{emx_digitalBidAdapter.md => cadentApertureMXBidAdapter.md} (58%) delete mode 100644 modules/captifyRtdProvider.js delete mode 100644 modules/captifyRtdProvider.md delete mode 100644 modules/conversantAnalyticsAdapter.md delete mode 100644 modules/conversantBidAdapter.md delete mode 100644 modules/glimpseBidAdapter.js delete mode 100644 modules/glimpseBidAdapter.md delete mode 100644 modules/googleAnalyticsAdapter.js delete mode 100644 modules/googleAnalyticsAdapter.md rename modules/{synacormediaBidAdapter.js => imdsBidAdapter.js} (93%) rename modules/{synacormediaBidAdapter.md => imdsBidAdapter.md} (84%) delete mode 100755 modules/inmarBidAdapter.js delete mode 100644 modules/inmarBidAdapter.md delete mode 100644 modules/inskinBidAdapter.js delete mode 100644 modules/inskinBidAdapter.md delete mode 100644 modules/liveyieldAnalyticsAdapter.js delete mode 100644 modules/liveyieldAnalyticsAdapter.md delete mode 100644 modules/mass.js delete mode 100644 modules/mass.md delete mode 100644 modules/openxAnalyticsAdapter.js delete mode 100644 modules/openxAnalyticsAdapter.md delete mode 100644 modules/openxOrtbBidAdapter.js delete mode 100644 modules/openxOrtbBidAdapter.md delete mode 100644 modules/pubCommonId.js delete mode 100644 modules/pubCommonId.md delete mode 100644 modules/realvuAnalyticsAdapter.js delete mode 100644 modules/realvuAnalyticsAdapter.md delete mode 100644 modules/rubiconAnalyticsAdapter.js rename {src => modules}/sizeMapping.js (73%) delete mode 100644 modules/trustpidSystem.js create mode 100644 modules/utiqSystem.js rename modules/{trustpidSystem.md => utiqSystem.md} (84%) delete mode 100644 modules/viewability.js delete mode 100644 modules/zeusPrimeRtdProvider.js delete mode 100644 modules/zeusPrimeRtdProvider.md create mode 100644 test/spec/appnexusKeywords_spec.js create mode 100644 test/spec/keywords_spec.js delete mode 100644 test/spec/modules/aolBidAdapter_spec.js rename test/spec/modules/{emx_digitalBidAdapter_spec.js => cadentApertureMXBidAdapter_spec.js} (97%) delete mode 100644 test/spec/modules/captifyRtdProvider_spec.js delete mode 100644 test/spec/modules/glimpseBidAdapter_spec.js delete mode 100644 test/spec/modules/googleAnalyticsAdapter_spec.js rename test/spec/modules/{synacormediaBidAdapter_spec.js => imdsBidAdapter_spec.js} (98%) delete mode 100644 test/spec/modules/inmarBidAdapter_spec.js delete mode 100644 test/spec/modules/inskinBidAdapter_spec.js delete mode 100644 test/spec/modules/liveyieldAnalyticsAdapter_spec.js delete mode 100644 test/spec/modules/mass_spec.js delete mode 100644 test/spec/modules/openxAnalyticsAdapter_spec.js delete mode 100644 test/spec/modules/openxOrtbBidAdapter_spec.js delete mode 100644 test/spec/modules/pubCommonId_spec.js delete mode 100644 test/spec/modules/rubiconAnalyticsAdapter_spec.js delete mode 100644 test/spec/modules/rubiconAnalyticsSchema.json create mode 100644 test/spec/modules/sizeMapping_spec.js delete mode 100644 test/spec/modules/trustpidSystem_spec.js create mode 100644 test/spec/modules/utiqSystem_spec.js delete mode 100644 test/spec/sizeMapping_spec.js diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 9b7c39d53d0..584f6f8894a 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -13,10 +13,10 @@ name: "CodeQL" on: push: - branches: [ "master" ] + branches: [ "master"] pull_request: # The branches below must be a subset of the branches above - branches: [ "master" ] + branches: [ "master"] schedule: - cron: '22 11 * * 0' diff --git a/integrationExamples/gpt/captifyRtdProvider_example.html b/integrationExamples/gpt/captifyRtdProvider_example.html deleted file mode 100644 index 955fbf8be70..00000000000 --- a/integrationExamples/gpt/captifyRtdProvider_example.html +++ /dev/null @@ -1,167 +0,0 @@ - - - - - - - - - - - - - - - - -
-

- Module will add key/value pairs in ad calls. - Check out for captify_segments key in the payload sent to Xandr to endpoint https://ib.adnxs.com/ut/v3/prebid : keywords.key[captify_segments] should have an array of string as value. - This array will have Xandr RTSS segment ids. -

-
-

Basic Prebid.js Example with CaptifyRTD

-
Div-1
-
- -
- - - diff --git a/integrationExamples/mass/index.html b/integrationExamples/mass/index.html deleted file mode 100644 index 3b034957d13..00000000000 --- a/integrationExamples/mass/index.html +++ /dev/null @@ -1,132 +0,0 @@ - - - - - - - - - - - - - - - -
-

Note: for this example to work, you need access to a bid simulation tool from your MASS enabled Exchange partner.

-
- -
-
- - diff --git a/libraries/analyticsAdapter/AnalyticsAdapter.js b/libraries/analyticsAdapter/AnalyticsAdapter.js index b6e270b3c3c..e1933d215e4 100644 --- a/libraries/analyticsAdapter/AnalyticsAdapter.js +++ b/libraries/analyticsAdapter/AnalyticsAdapter.js @@ -134,13 +134,7 @@ export default function AnalyticsAdapter({ url, analyticsType, global, handler } handlers = Object.fromEntries( Array.from(trackedEvents) .map((ev) => { - const handler = ev === CONSTANTS.EVENTS.AUCTION_INIT - ? (args) => { - // TODO: remove this special case in v8 - args.config = typeof config === 'object' ? config.options || {} : {}; - this.enqueue({eventType: ev, args}); - } - : (args) => this.enqueue({eventType: ev, args}); + const handler = (args) => this.enqueue({eventType: ev, args}); events.on(ev, handler); return [ev, handler]; }) diff --git a/libraries/appnexusKeywords/anKeywords.js b/libraries/appnexusKeywords/anKeywords.js new file mode 100644 index 00000000000..5dc0b453253 --- /dev/null +++ b/libraries/appnexusKeywords/anKeywords.js @@ -0,0 +1,140 @@ +import {_each, deepAccess, getValueString, isArray, isStr, mergeDeep, isNumber} from '../../src/utils.js'; +import {getAllOrtbKeywords} from '../keywords/keywords.js'; +import {CLIENT_SECTIONS} from '../../src/fpd/oneClient.js'; + +const ORTB_SEGTAX_KEY_MAP = { + 526: '1plusX', + 527: '1plusX', + 541: 'captify_segments', + 540: 'perid' +}; +const ORTB_SEG_PATHS = ['user.data'].concat( + CLIENT_SECTIONS.map((prefix) => `${prefix}.content.data`) +); + +/** + * Converts an object of arrays (either strings or numbers) into an array of objects containing key and value properties + * normally read from bidder params + * eg { foo: ['bar', 'baz'], fizz: ['buzz'] } + * becomes [{ key: 'foo', value: ['bar', 'baz']}, {key: 'fizz', value: ['buzz']}] + * @param {Object} keywords object of arrays representing keyvalue pairs + * @param {string} paramName name of parent object (eg 'keywords') containing keyword data, used in error handling + * @returns {Array<{key, value}>} + */ +export function transformBidderParamKeywords(keywords, paramName = 'keywords') { + const arrs = []; + + _each(keywords, (v, k) => { + if (isArray(v)) { + let values = []; + _each(v, (val) => { + val = getValueString(paramName + '.' + k, val); + if (val || val === '') { + values.push(val); + } + }); + v = values; + } else { + v = getValueString(paramName + '.' + k, v); + if (isStr(v)) { + v = [v]; + } else { + return; + } // unsuported types - don't send a key + } + v = v.filter(kw => kw !== '') + const entry = {key: k} + if (v.length > 0) { + entry.value = v; + } + arrs.push(entry); + }); + + return arrs; +} + +// converts a comma separated list of keywords into the standard keyword object format used in appnexus bid params +// 'genre=rock,genre=pop,pets=dog,music' goes to { 'genre': ['rock', 'pop'], 'pets': ['dog'], 'music': [''] } +export function convertKeywordStringToANMap(keyStr) { + if (isStr(keyStr) && keyStr !== '') { + // will split based on commas and will eat white space before/after the comma + return convertKeywordsToANMap(keyStr.split(/\s*(?:,)\s*/)); + } else { + return {} + } +} + +/** + * @param {Array} kwarray: keywords as an array of strings + * @return {{}} appnexus-style keyword map + */ +function convertKeywordsToANMap(kwarray) { + const result = {}; + kwarray.forEach(kw => { + // if = exists, then split + if (kw.indexOf('=') !== -1) { + let kwPair = kw.split('='); + let key = kwPair[0]; + let val = kwPair[1]; + + // then check for existing key in result > if so add value to the array > if not, add new key and create value array + if (result.hasOwnProperty(key)) { + result[key].push(val); + } else { + result[key] = [val]; + } + } else { + if (!result.hasOwnProperty(kw)) { + result[kw] = []; + } + } + }) + return result; +} + +/** + * @param ortb2 + * @return {{}} appnexus-style keyword map using all keywords contained in ortb2 + */ +export function getANMapFromOrtbKeywords(ortb2) { + return convertKeywordsToANMap(getAllOrtbKeywords(ortb2)); +} + +export function getANKewyordParamFromMaps(...anKeywordMaps) { + return transformBidderParamKeywords( + mergeDeep(...anKeywordMaps.map(kwMap => Object.fromEntries( + Object.entries(kwMap || {}) + .map(([k, v]) => [k, (isNumber(v) || isStr(v)) ? [v] : v]) + ))) + ) +} + +export function getANKeywordParam(ortb2, ...anKeywordsMaps) { + return getANKewyordParamFromMaps( + getANMapFromOrtbKeywords(ortb2), + getANMapFromOrtbSegments(ortb2), + ...anKeywordsMaps + ) +} + +export function getANMapFromOrtbSegments(ortb2) { + let ortbSegData = {}; + ORTB_SEG_PATHS.forEach(path => { + let ortbSegsArrObj = deepAccess(ortb2, path) || []; + ortbSegsArrObj.forEach(segObj => { + // only read segment data from known sources + const segtax = ORTB_SEGTAX_KEY_MAP[deepAccess(segObj, 'ext.segtax')]; + if (segtax) { + segObj.segment.forEach(seg => { + // if source was in multiple locations of ortb or had multiple segments in same area, stack them together into an array + if (ortbSegData[segtax]) { + ortbSegData[segtax].push(seg.id); + } else { + ortbSegData[segtax] = [seg.id] + } + }); + } + }); + }); + return ortbSegData; +} diff --git a/libraries/categoryTranslationMapping/index.js b/libraries/categoryTranslationMapping/index.js new file mode 100644 index 00000000000..13b10423450 --- /dev/null +++ b/libraries/categoryTranslationMapping/index.js @@ -0,0 +1,100 @@ +/** + * Provides mapping objects used by bidders for categoryTranslation type logic for Adpod feature + */ +export const APPNEXUS_CATEGORY_MAPPING = { + '1': 'IAB20-3', + '2': 'IAB18-5', + '3': 'IAB10-1', + '4': 'IAB2-3', + '5': 'IAB19-8', + '6': 'IAB22-1', + '7': 'IAB18-1', + '8': 'IAB12-3', + '9': 'IAB5-1', + '10': 'IAB4-5', + '11': 'IAB13-4', + '12': 'IAB8-7', + '13': 'IAB9-7', + '14': 'IAB7-1', + '15': 'IAB20-18', + '16': 'IAB10-7', + '17': 'IAB19-18', + '18': 'IAB13-6', + '19': 'IAB18-4', + '20': 'IAB1-5', + '21': 'IAB1-6', + '22': 'IAB3-4', + '23': 'IAB19-13', + '24': 'IAB22-2', + '25': 'IAB3-9', + '26': 'IAB17-18', + '27': 'IAB19-6', + '28': 'IAB1-7', + '29': 'IAB9-30', + '30': 'IAB20-7', + '31': 'IAB20-17', + '32': 'IAB7-32', + '33': 'IAB16-5', + '34': 'IAB19-34', + '35': 'IAB11-5', + '36': 'IAB12-3', + '37': 'IAB11-4', + '38': 'IAB12-3', + '39': 'IAB9-30', + '41': 'IAB7-44', + '42': 'IAB7-1', + '43': 'IAB7-30', + '50': 'IAB19-30', + '51': 'IAB17-12', + '52': 'IAB19-30', + '53': 'IAB3-1', + '55': 'IAB13-2', + '56': 'IAB19-30', + '57': 'IAB19-30', + '58': 'IAB7-39', + '59': 'IAB22-1', + '60': 'IAB7-39', + '61': 'IAB21-3', + '62': 'IAB5-1', + '63': 'IAB12-3', + '64': 'IAB20-18', + '65': 'IAB11-2', + '66': 'IAB17-18', + '67': 'IAB9-9', + '68': 'IAB9-5', + '69': 'IAB7-44', + '71': 'IAB22-3', + '73': 'IAB19-30', + '74': 'IAB8-5', + '78': 'IAB22-1', + '85': 'IAB12-2', + '86': 'IAB22-3', + '87': 'IAB11-3', + '112': 'IAB7-32', + '113': 'IAB7-32', + '114': 'IAB7-32', + '115': 'IAB7-32', + '118': 'IAB9-5', + '119': 'IAB9-5', + '120': 'IAB9-5', + '121': 'IAB9-5', + '122': 'IAB9-5', + '123': 'IAB9-5', + '124': 'IAB9-5', + '125': 'IAB9-5', + '126': 'IAB9-5', + '127': 'IAB22-1', + '132': 'IAB1-2', + '133': 'IAB19-30', + '137': 'IAB3-9', + '138': 'IAB19-3', + '140': 'IAB2-3', + '141': 'IAB2-1', + '142': 'IAB2-3', + '143': 'IAB17-13', + '166': 'IAB11-4', + '175': 'IAB3-1', + '176': 'IAB13-4', + '182': 'IAB8-9', + '183': 'IAB3-5' +}; diff --git a/libraries/keywords/keywords.js b/libraries/keywords/keywords.js new file mode 100644 index 00000000000..645c9c8d38f --- /dev/null +++ b/libraries/keywords/keywords.js @@ -0,0 +1,31 @@ +import {CLIENT_SECTIONS} from '../../src/fpd/oneClient.js'; +import {deepAccess} from '../../src/utils.js'; + +const ORTB_KEYWORDS_PATHS = ['user.keywords'].concat( + CLIENT_SECTIONS.flatMap((prefix) => ['keywords', 'content.keywords'].map(suffix => `${prefix}.${suffix}`)) +); + +/** + * @param commaSeparatedKeywords: any number of either keyword arrays, or comma-separated keyword strings + * @returns an array with all unique keywords contained across all inputs + */ +export function mergeKeywords(...commaSeparatedKeywords) { + const keywords = new Set(); + commaSeparatedKeywords + .filter(kwds => kwds) + .flatMap(kwds => Array.isArray(kwds) ? kwds : kwds.split(',')) + .map(kw => kw.replace(/^\s*/, '').replace(/\s*$/, '')) + .filter(kw => kw) + .forEach(kw => keywords.add(kw)); + return Array.from(keywords.keys()); +} + +/** + * Get an array with all keywords contained in an ortb2 object. + */ +export function getAllOrtbKeywords(ortb2, ...extraCommaSeparatedKeywords) { + return mergeKeywords( + ...ORTB_KEYWORDS_PATHS.map(path => deepAccess(ortb2, path)), + ...extraCommaSeparatedKeywords + ) +} diff --git a/libraries/objectGuard/objectGuard.js b/libraries/objectGuard/objectGuard.js index a404f8653f8..cf3d2f38256 100644 --- a/libraries/objectGuard/objectGuard.js +++ b/libraries/objectGuard/objectGuard.js @@ -1,4 +1,4 @@ -import {isData, objectTransformer} from '../../src/activities/redactor.js'; +import {isData, objectTransformer, sessionedApplies} from '../../src/activities/redactor.js'; import {deepAccess, deepClone, deepEqual, deepSetValue} from '../../src/utils.js'; /** @@ -41,15 +41,6 @@ export function objectGuard(rules) { const wpTransformer = objectTransformer(writeRules); - function mkApplies(session, args) { - return function applies(rule) { - if (!session.hasOwnProperty(rule.name)) { - session[rule.name] = rule.applies(...args); - } - return session[rule.name]; - } - } - function mkGuard(obj, tree, applies) { return new Proxy(obj, { get(target, prop, receiver) { @@ -76,7 +67,7 @@ export function objectGuard(rules) { return function guard(obj, ...args) { const session = {}; return { - obj: mkGuard(obj, root.children || {}, mkApplies(session, args)), + obj: mkGuard(obj, root.children || {}, sessionedApplies(session, ...args)), verify: mkVerify(wpTransformer(session, obj, ...args)) } }; diff --git a/libraries/ortbConverter/processors/default.js b/libraries/ortbConverter/processors/default.js index 00922608707..8db2c1c461e 100644 --- a/libraries/ortbConverter/processors/default.js +++ b/libraries/ortbConverter/processors/default.js @@ -1,4 +1,4 @@ -import {deepSetValue, mergeDeep} from '../../../src/utils.js'; +import {generateUUID, mergeDeep} from '../../../src/utils.js'; import {bannerResponseProcessor, fillBannerImp} from './banner.js'; import {fillVideoImp, fillVideoResponse} from './video.js'; import {setResponseMediaType} from './mediaType.js'; @@ -21,17 +21,16 @@ export const DEFAULT_PROCESSORS = { fn: clientSectionChecker('ORTB request') }, props: { - // sets request properties id, tmax, test, source.tid + // sets request properties id, tmax, test fn(ortbRequest, bidderRequest) { Object.assign(ortbRequest, { - id: ortbRequest.id || bidderRequest.auctionId, + id: ortbRequest.id || generateUUID(), test: ortbRequest.test || 0 }); const timeout = parseInt(bidderRequest.timeout, 10); if (!isNaN(timeout)) { ortbRequest.tmax = timeout; } - deepSetValue(ortbRequest, 'source.tid', ortbRequest.source?.tid || bidderRequest.auctionId); } } }, diff --git a/modules/.submodules.json b/modules/.submodules.json index fd37c1caed2..bcc94b1f36a 100644 --- a/modules/.submodules.json +++ b/modules/.submodules.json @@ -38,7 +38,7 @@ "tapadIdSystem", "teadsIdSystem", "tncIdSystem", - "trustpidSystem", + "utiqSystem", "uid2IdSystem", "euidIdSystem", "unifiedIdSystem", diff --git a/modules/1plusXRtdProvider.js b/modules/1plusXRtdProvider.js index 665a0f2b35e..c5c4594ff22 100644 --- a/modules/1plusXRtdProvider.js +++ b/modules/1plusXRtdProvider.js @@ -152,19 +152,15 @@ const getTargetingDataFromPapi = (papiUrl) => { export const buildOrtb2Updates = ({ segments = [], topics = [] }) => { const userData = { name: ORTB2_NAME, - segment: segments.map((segmentId) => ({ id: segmentId })) + segment: segments.map((segmentId) => ({ id: segmentId })), + ext: { segtax: segtaxes.AUDIENCE } }; const siteContentData = { name: ORTB2_NAME, segment: topics.map((topicId) => ({ id: topicId })), ext: { segtax: segtaxes.CONTENT } } - // Currently appnexus bidAdapter doesn't support topics in `site.content.data.segment` - // Therefore, writing them in `site.keywords` until it's supported - // Other bidAdapters do fine with `site.content.data.segment` - const siteKeywords = topics.map(topic => `1plusX=${topic}`).join(','); - - return { userData, siteContentData, siteKeywords }; + return { userData, siteContentData }; } /** @@ -174,16 +170,10 @@ export const buildOrtb2Updates = ({ segments = [], topics = [] }) => { * @param {Object} biddersOrtb2 All current bidder configs */ export const updateBidderConfig = (bidder, ortb2Updates, biddersOrtb2) => { - const { siteKeywords, siteContentData, userData } = ortb2Updates; + const { siteContentData, userData } = ortb2Updates; mergeDeep(biddersOrtb2, { [bidder]: {} }); const bidderConfig = deepAccess(biddersOrtb2, bidder); - { - // Legacy : cf. comment on buildOrtb2Updates - const siteKeywordsPath = 'site.keywords'; - deepSetValue(bidderConfig, siteKeywordsPath, siteKeywords); - } - { const siteDataPath = 'site.content.data'; const currentSiteContentData = deepAccess(bidderConfig, siteDataPath) || []; diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 606933e7b63..26fc0a11fd5 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -1,19 +1,19 @@ -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { config } from '../src/config.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {config} from '../src/config.js'; import { deepAccess, - uniques, - isArray, + getWindowSelf, getWindowTop, + isArray, isGptPubadsDefined, isSlotMatchingAdUnitCode, logInfo, logWarn, - getWindowSelf, mergeDeep, - pick + pick, + uniques } from '../src/utils.js'; -import { BANNER, VIDEO } from '../src/mediaTypes.js'; +import {BANNER, VIDEO} from '../src/mediaTypes.js'; // **************************** UTILS *************************** // const BIDDER_CODE = '33across'; @@ -183,7 +183,8 @@ function buildRequests(bidRequests, bidderRequest) { uspConsent, pageUrl, referer, - ttxSettings + ttxSettings, + bidderRequest, }) ) } @@ -246,7 +247,7 @@ function _getMRAKey(bidRequest) { } // Infer the necessary data from valid bid for a minimal ttxRequest and create HTTP request -function _createServerRequest({ bidRequests, gdprConsent = {}, uspConsent, pageUrl, referer, ttxSettings }) { +function _createServerRequest({ bidRequests, gdprConsent = {}, uspConsent, pageUrl, referer, ttxSettings, bidderRequest }) { const ttxRequest = {}; const firstBidRequest = bidRequests[0]; const { siteId, test } = firstBidRequest.params; @@ -271,7 +272,7 @@ function _createServerRequest({ bidRequests, gdprConsent = {}, uspConsent, pageU ttxRequest.site.ref = referer; } - ttxRequest.id = firstBidRequest.auctionId; + ttxRequest.id = bidderRequest?.bidderRequestId; if (gdprConsent.consentString) { ttxRequest.user = setExtensions(ttxRequest.user, { @@ -681,7 +682,6 @@ function _createBidResponse(bid, cur) { bid.adomain && bid.adomain.length; const bidResponse = { requestId: bid.impid, - bidderCode: BIDDER_CODE, cpm: bid.price, width: bid.w, height: bid.h, diff --git a/modules/adWMGBidAdapter.js b/modules/adWMGBidAdapter.js index 12dc36d694c..36935e80d3b 100644 --- a/modules/adWMGBidAdapter.js +++ b/modules/adWMGBidAdapter.js @@ -59,11 +59,12 @@ export const spec = { } const request = { + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 auctionId: bidRequest.auctionId, requestId: bidRequest.bidId, bidRequestsCount: bidRequest.bidRequestsCount, bidderRequestId: bidRequest.bidderRequestId, - transactionId: bidRequest.transactionId, + transactionId: bidRequest.ortb2Imp?.ext?.tid, referrer: referrer, timeout: timeout, adUnit: adUnit, diff --git a/modules/adagioBidAdapter.js b/modules/adagioBidAdapter.js index c70fc724611..57dd80aa9b1 100644 --- a/modules/adagioBidAdapter.js +++ b/modules/adagioBidAdapter.js @@ -860,7 +860,7 @@ function storeRequestInAdagioNS(bidRequest) { bidder: bidRequest.bidder, params: bidRequest.params // use the updated bid.params object with auto-detected params }], - auctionId: bidRequest.auctionId, + auctionId: bidRequest.auctionId, // this auctionId has been generated by adagioBidAdapter pageviewId: internal.getPageviewId(), printNumber, localPbjs: '$$PREBID_GLOBAL$$', @@ -869,7 +869,7 @@ function storeRequestInAdagioNS(bidRequest) { // (legacy) Store internal adUnit information w.ADAGIO.adUnits[bidRequest.adUnitCode] = { - auctionId: bidRequest.auctionId, + auctionId: bidRequest.auctionId, // this auctionId has been generated by adagioBidAdapter pageviewId: internal.getPageviewId(), printNumber, }; @@ -981,7 +981,14 @@ export const spec = { const syncEnabled = deepAccess(config.getConfig('userSync'), 'syncEnabled') const usIfr = syncEnabled && userSync.canBidderRegisterSync('iframe', 'adagio') - const adUnits = _map(validBidRequests, (bidRequest) => { + const aucId = generateUUID() + + const adUnits = _map(validBidRequests, (rawBidRequest) => { + const bidRequest = {...rawBidRequest} + + // Fix https://github.com/prebid/Prebid.js/issues/9781 + bidRequest.auctionId = aucId + const globalFeatures = GlobalExchange.getOrSetGlobalFeatures(); const features = { ...globalFeatures, @@ -1094,6 +1101,12 @@ export const spec = { storeRequestInAdagioNS(bidRequest); + // Remove these fields at the very end, so we can still use them before. + delete bidRequest.transactionId; + delete bidRequest.ortb2Imp; + delete bidRequest.ortb2; + delete bidRequest.sizes; + return bidRequest; }); @@ -1232,33 +1245,8 @@ export const spec = { * @returns {object} updated params */ transformBidParams(params, isOrtb, adUnit, bidRequests) { - const adagioBidderRequest = find(bidRequests, bidRequest => bidRequest.bidderCode === 'adagio'); - const adagioBid = find(adagioBidderRequest.bids, bid => bid.adUnitCode === adUnit.code); - - if (isOrtb) { - autoFillParams(adagioBid); - - adagioBid.params.auctionId = deepAccess(adagioBidderRequest, 'auctionId'); - - const globalFeatures = GlobalExchange.getOrSetGlobalFeatures(); - adagioBid.params.features = { - ...globalFeatures, - print_number: getPrintNumber(adagioBid.adUnitCode, adagioBidderRequest).toString(), - adunit_position: getSlotPosition(adagioBid.params.adUnitElementId) // adUnitElementId à déplacer ??? - }; - - adagioBid.params.pageviewId = internal.getPageviewId(); - adagioBid.params.prebidVersion = '$prebid.version$'; - adagioBid.params.data = GlobalExchange.getExchangeData(); - - if (deepAccess(adagioBid, 'mediaTypes.video.context') === OUTSTREAM) { - adagioBid.params.playerName = setPlayerName(adagioBid); - } - - storeRequestInAdagioNS(adagioBid); - } - - return adagioBid.params; + // We do not have a prebid server adapter. So let's return unchanged params. + return params; } }; diff --git a/modules/adbookpspBidAdapter.js b/modules/adbookpspBidAdapter.js index 917d18e9fae..cb03f2ffc17 100644 --- a/modules/adbookpspBidAdapter.js +++ b/modules/adbookpspBidAdapter.js @@ -203,7 +203,7 @@ function buildRegs(bidderRequest) { function buildSource(bidRequests, bidderRequest) { const source = { fd: 1, - tid: bidderRequest.auctionId, + tid: bidderRequest.ortb2.source.tid, }; const schain = deepAccess(bidRequests, '0.schain'); diff --git a/modules/addefendBidAdapter.js b/modules/addefendBidAdapter.js index d73c25935ee..dbb186fdc86 100644 --- a/modules/addefendBidAdapter.js +++ b/modules/addefendBidAdapter.js @@ -30,6 +30,7 @@ export const spec = { for (var i = 0; i < validBidRequests.length; i++) { let vb = validBidRequests[i]; let o = vb.params; + // TODO: fix auctionId/transactionId leak: https://github.com/prebid/Prebid.js/issues/9781 bid.auctionId = vb.auctionId; o.bidId = vb.bidId; o.transactionId = vb.transactionId; diff --git a/modules/adfBidAdapter.js b/modules/adfBidAdapter.js index 82bd7f03ff0..5c4b03c3bb2 100644 --- a/modules/adfBidAdapter.js +++ b/modules/adfBidAdapter.js @@ -3,7 +3,7 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {deepAccess, deepSetValue, mergeDeep, parseSizesInput, deepClone} from '../src/utils.js'; +import {deepAccess, deepClone, deepSetValue, mergeDeep, parseSizesInput} from '../src/utils.js'; import {config} from '../src/config.js'; import {Renderer} from '../src/Renderer.js'; @@ -58,7 +58,7 @@ export const spec = { const adxDomain = setOnAny(validBidRequests, 'params.adxDomain') || 'adx.adform.net'; const pt = setOnAny(validBidRequests, 'params.pt') || setOnAny(validBidRequests, 'params.priceType') || 'net'; - const tid = bidderRequest.auctionId; + const tid = bidderRequest.ortb2?.source?.tid; const test = setOnAny(validBidRequests, 'params.test'); const currency = getConfig('currency.adServerCurrency'); const cur = currency && [ currency ]; @@ -139,7 +139,7 @@ export const spec = { }); const request = { - id: bidderRequest.auctionId, + id: bidderRequest.bidderRequestId, site, app, user, diff --git a/modules/adgenerationBidAdapter.js b/modules/adgenerationBidAdapter.js index 67333a2137e..f18b7629d8f 100644 --- a/modules/adgenerationBidAdapter.js +++ b/modules/adgenerationBidAdapter.js @@ -48,7 +48,7 @@ export const spec = { data = tryAppendQueryString(data, 'sdktype', '0'); data = tryAppendQueryString(data, 'hb', 'true'); data = tryAppendQueryString(data, 't', 'json3'); - data = tryAppendQueryString(data, 'transactionid', validReq.transactionId); + data = tryAppendQueryString(data, 'transactionid', validReq.ortb2Imp?.ext?.tid); data = tryAppendQueryString(data, 'sizes', getSizes(validReq)); data = tryAppendQueryString(data, 'currency', getCurrencyType()); data = tryAppendQueryString(data, 'pbver', '$prebid.version$'); diff --git a/modules/adkernelAdnBidAdapter.js b/modules/adkernelAdnBidAdapter.js index 3e348e0795d..4db46aca3c6 100644 --- a/modules/adkernelAdnBidAdapter.js +++ b/modules/adkernelAdnBidAdapter.js @@ -1,4 +1,4 @@ -import { deepAccess, parseSizesInput, isArray, deepSetValue, isStr, isNumber, logInfo } from '../src/utils.js'; +import {deepAccess, deepSetValue, isArray, isNumber, isStr, logInfo, parseSizesInput} from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; @@ -58,11 +58,11 @@ function canonicalizeSizesArray(sizes) { } function buildRequestParams(tags, bidderRequest) { - let {auctionId, gdprConsent, uspConsent, transactionId, refererInfo} = bidderRequest; + let {gdprConsent, uspConsent, refererInfo, ortb2} = bidderRequest; let req = { - id: auctionId, - // TODO: transactionId is undefined here, should this be auctionId? see #8573 - tid: transactionId, + id: bidderRequest.bidderRequestId, + // TODO: root-level `tid` is not ORTB; is this intentional? + tid: ortb2?.source?.tid, site: buildSite(refererInfo), imp: tags }; @@ -99,7 +99,6 @@ function buildSite(refInfo) { function buildBid(tag) { let bid = { requestId: tag.impid, - bidderCode: spec.code, cpm: tag.bid, creativeId: tag.crid, currency: 'USD', diff --git a/modules/adkernelBidAdapter.js b/modules/adkernelBidAdapter.js index 820528a71da..64567832dbd 100644 --- a/modules/adkernelBidAdapter.js +++ b/modules/adkernelBidAdapter.js @@ -6,6 +6,7 @@ import { deepAccess, deepSetValue, getAdUnitSizes, + getDefinedParams, getDNT, isArray, isArrayOfNums, @@ -14,14 +15,13 @@ import { isPlainObject, isStr, mergeDeep, - parseGPTSingleSizeArrayToRtbSize, - getDefinedParams + parseGPTSingleSizeArrayToRtbSize } from '../src/utils.js'; import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {find} from '../src/polyfill.js'; import {config} from '../src/config.js'; -import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; /* * In case you're AdKernel whitelable platform's client who needs branded adapter to @@ -491,9 +491,9 @@ function makeRegulations(bidderRequest) { * @returns */ function makeBaseRequest(bidderRequest, imps, fpd) { - let {auctionId, timeout} = bidderRequest; + let {timeout} = bidderRequest; let request = { - 'id': auctionId, + 'id': bidderRequest.bidderRequestId, 'imp': imps, 'at': 1, 'tmax': parseInt(timeout) diff --git a/modules/adprimeBidAdapter.js b/modules/adprimeBidAdapter.js index 49c18c2d067..55ee1f0900c 100644 --- a/modules/adprimeBidAdapter.js +++ b/modules/adprimeBidAdapter.js @@ -3,6 +3,7 @@ import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; import { isFn, deepAccess, logMessage } from '../src/utils.js'; import { config } from '../src/config.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import {getAllOrtbKeywords} from '../libraries/keywords/keywords.js'; const BIDDER_CODE = 'adprime'; const AD_URL = 'https://delta.adprime.com/pbjs'; @@ -128,7 +129,7 @@ export const spec = { wPlayer: sizes ? sizes[0] : 0, hPlayer: sizes ? sizes[1] : 0, schain: bid.schain || {}, - keywords: bid.params.keywords || [], + keywords: getAllOrtbKeywords(bidderRequest.ortb2, bid.params.keywords), audiences: bid.params.audiences || [], identeties, bidFloor: getBidFloor(bid) diff --git a/modules/adqueryBidAdapter.js b/modules/adqueryBidAdapter.js index c4b38fb36fa..8a953f0d97f 100644 --- a/modules/adqueryBidAdapter.js +++ b/modules/adqueryBidAdapter.js @@ -199,6 +199,7 @@ function buildRequest(validBidRequests, bidderRequest) { return { v: '$prebid.version$', placementCode: bid.params.placementId, + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 auctionId: bid.auctionId, type: bid.params.type, adUnitCode: bid.adUnitCode, diff --git a/modules/adrelevantisBidAdapter.js b/modules/adrelevantisBidAdapter.js index 40cfe18f025..cf785a1fc87 100644 --- a/modules/adrelevantisBidAdapter.js +++ b/modules/adrelevantisBidAdapter.js @@ -13,8 +13,7 @@ import { isStr, logError, logMessage, - logWarn, - transformBidderParamKeywords + logWarn } from '../src/utils.js'; import {config} from '../src/config.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; @@ -22,6 +21,7 @@ import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {find, includes} from '../src/polyfill.js'; import {INSTREAM, OUTSTREAM} from '../src/video.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import {getANKeywordParam, transformBidderParamKeywords} from '../libraries/appnexusKeywords/anKeywords.js'; const BIDDER_CODE = 'adrelevantis'; const URL = 'https://ssp.adrelevantis.com/prebid'; @@ -194,10 +194,6 @@ export const spec = { params.use_pmt_rule = (typeof params.usePaymentRule === 'boolean') ? params.usePaymentRule : false; if (params.usePaymentRule) { delete params.usePaymentRule; } - if (isPopulatedArray(params.keywords)) { - params.keywords.forEach(deleteValues); - } - Object.keys(params).forEach(paramKey => { let convertedKey = convertCamelToUnderscore(paramKey); if (convertedKey !== paramKey) { @@ -211,16 +207,6 @@ export const spec = { } }; -function isPopulatedArray(arr) { - return !!(isArray(arr) && arr.length > 0); -} - -function deleteValues(keyPairObj) { - if (isPopulatedArray(keyPairObj.value) && keyPairObj.value[0] === '') { - delete keyPairObj.value; - } -} - function formatRequest(payload, bidderRequest) { let request = []; @@ -475,14 +461,7 @@ function bidToTag(bid) { if (bid.params.externalImpId) { tag.external_imp_id = bid.params.externalImpId; } - if (!isEmpty(bid.params.keywords)) { - let keywords = transformBidderParamKeywords(bid.params.keywords); - - if (keywords.length > 0) { - keywords.forEach(deleteValues); - } - tag.keywords = keywords; - } + tag.keywords = getANKeywordParam(bid.ortb2, bid.params.keywords) if (bid.params.category) { tag.category = bid.params.category; } diff --git a/modules/adtrueBidAdapter.js b/modules/adtrueBidAdapter.js index 2ec5cd59e1d..389986eb586 100644 --- a/modules/adtrueBidAdapter.js +++ b/modules/adtrueBidAdapter.js @@ -469,7 +469,7 @@ export const spec = { conf.zoneId = conf.zoneId || bid.params.zoneId; conf.pubId = conf.pubId || bid.params.publisherId; - conf.transactionId = bid.transactionId; + conf.transactionId = bid.ortb2Imp?.ext?.tid; if (bidCurrency === '') { bidCurrency = bid.params.currency || UNDEFINED; } else if (bid.params.hasOwnProperty('currency') && bidCurrency !== bid.params.currency) { @@ -492,7 +492,7 @@ export const spec = { payload.ext.wrapper = {}; payload.ext.wrapper.transactionId = conf.transactionId; - payload.ext.wrapper.wiid = conf.wiid || bidderRequest.auctionId; + payload.ext.wrapper.wiid = conf.wiid || bidderRequest.ortb2?.ext?.tid; payload.ext.wrapper.wp = 'pbjs'; payload.user.geo = {}; diff --git a/modules/aduptechBidAdapter.js b/modules/aduptechBidAdapter.js index c7138e43cfe..1ea5f1a0096 100644 --- a/modules/aduptechBidAdapter.js +++ b/modules/aduptechBidAdapter.js @@ -255,6 +255,7 @@ export const spec = { url: internal.buildEndpointUrl(publisher), method: ENDPOINT_METHOD, data: { + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 auctionId: auctionId, pageUrl: pageUrl, referrer: referrer, @@ -271,7 +272,7 @@ export const spec = { groupedBidRequests[publisher].forEach(bidRequest => { const bid = { bidId: bidRequest.bidId, - transactionId: bidRequest.transactionId, + transactionId: bidRequest.ortb2Imp?.ext?.tid, adUnitCode: bidRequest.adUnitCode, params: internal.extractParams(bidRequest) }; diff --git a/modules/advangelistsBidAdapter.js b/modules/advangelistsBidAdapter.js index 4963150caed..8e5be83f166 100755 --- a/modules/advangelistsBidAdapter.js +++ b/modules/advangelistsBidAdapter.js @@ -58,7 +58,6 @@ export const spec = { if (isVideoBid(bidRequest)) { let bidResponse = { requestId: response.id, - bidderCode: BIDDER_CODE, cpm: response.seatbid[0].bid[0].price, width: response.seatbid[0].bid[0].w, height: response.seatbid[0].bid[0].h, diff --git a/modules/adxcgBidAdapter.js b/modules/adxcgBidAdapter.js index 564960cf2c9..5930f3adb67 100644 --- a/modules/adxcgBidAdapter.js +++ b/modules/adxcgBidAdapter.js @@ -98,7 +98,7 @@ export const spec = { device.dnt = getDNT() ? 1 : 0; device.language = (navigator && navigator.language) ? navigator.language.split('-')[0] : ''; - const tid = bidderRequest.auctionId; + const tid = bidderRequest.ortb2?.source?.tid; const test = setOnAny(validBidRequests, 'params.test'); const currency = getConfig('currency.adServerCurrency'); const cur = currency && [ currency ]; diff --git a/modules/adyoulikeBidAdapter.js b/modules/adyoulikeBidAdapter.js index 376d108e980..4080d9f25cd 100644 --- a/modules/adyoulikeBidAdapter.js +++ b/modules/adyoulikeBidAdapter.js @@ -71,7 +71,7 @@ export const spec = { let size = getSize(sizesArray); accumulator[bidReq.bidId] = {}; accumulator[bidReq.bidId].PlacementID = bidReq.params.placement; - accumulator[bidReq.bidId].TransactionID = bidReq.transactionId; + accumulator[bidReq.bidId].TransactionID = bidReq.ortb2Imp?.ext?.tid; accumulator[bidReq.bidId].Width = size.width; accumulator[bidReq.bidId].Height = size.height; accumulator[bidReq.bidId].AvailableSizes = sizesArray.join(','); diff --git a/modules/afpBidAdapter.js b/modules/afpBidAdapter.js index f690b70973d..cec61b29b82 100644 --- a/modules/afpBidAdapter.js +++ b/modules/afpBidAdapter.js @@ -100,13 +100,13 @@ export const spec = { pageUrl: IS_DEV ? TEST_PAGE_URL : refererInfo.page, gdprConsent: gdprConsent, bidRequests: validBidRequests.map(validBidRequest => { - const {bidId, transactionId, sizes, params: { + const {bidId, ortb2Imp, sizes, params: { placeId, placeType, imageUrl, imageWidth, imageHeight }} = validBidRequest bidRequestMap[bidId] = validBidRequest const bidRequest = { bidId, - transactionId, + transactionId: ortb2Imp?.ext?.tid, sizes, placeId, } diff --git a/modules/aidemBidAdapter.js b/modules/aidemBidAdapter.js index d43c07aeece..7469f26156b 100644 --- a/modules/aidemBidAdapter.js +++ b/modules/aidemBidAdapter.js @@ -1,4 +1,15 @@ -import {_each, contains, deepAccess, deepSetValue, getDNT, isBoolean, isStr, isNumber, logError, logInfo} from '../src/utils.js'; +import { + _each, + contains, + deepAccess, + deepSetValue, + getDNT, + isBoolean, + isNumber, + isStr, + logError, + logInfo +} from '../src/utils.js'; import {config} from '../src/config.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; @@ -164,6 +175,7 @@ function buildWinNotice(bid) { impid: deepAccess(bid, 'meta.impid'), dsp_id: deepAccess(bid, 'meta.dsp_id'), adUnitCode: bid.adUnitCode, + // TODO: fix auctionId/transactionId leak: https://github.com/prebid/Prebid.js/issues/9781 auctionId: bid.auctionId, transactionId: bid.transactionId, ttl: bid.ttl, @@ -201,7 +213,7 @@ function getMediaType(bidRequest) { function getPrebidRequestFields(bidderRequest, bidRequests) { const payload = {}; // Base Payload Data - deepSetValue(payload, 'id', bidderRequest.auctionId); + deepSetValue(payload, 'id', bidderRequest.bidderRequestId); // Impressions setPrebidImpressionObject(bidRequests, payload); // Device @@ -231,7 +243,8 @@ function setPrebidImpressionObject(bidRequests, payload) { // Placement or ad tag used to initiate the auction deepSetValue(impressionObject, 'id', bidRequest.bidId); // Transaction id - deepSetValue(impressionObject, 'tid', deepAccess(bidRequest, 'transactionId')); + // TODO: `imp.tid` is not ORTB, is this intentional? + deepSetValue(impressionObject, 'tid', deepAccess(bidRequest, 'ortb2Imp.ext.tid')); // placement id deepSetValue(impressionObject, 'tagid', deepAccess(bidRequest, 'params.placementId', null)); // Publisher id diff --git a/modules/airgridRtdProvider.js b/modules/airgridRtdProvider.js index 6af53a9094a..7c6cf1f5de0 100644 --- a/modules/airgridRtdProvider.js +++ b/modules/airgridRtdProvider.js @@ -5,16 +5,11 @@ * @module modules/airgridRtdProvider * @requires module:modules/realTimeData */ -import { config } from '../src/config.js'; -import { submodule } from '../src/hook.js'; -import { - deepSetValue, - deepAccess, -} from '../src/utils.js'; -import { getGlobal } from '../src/prebidGlobal.js'; -import { getStorageManager } from '../src/storageManager.js'; -import { loadExternalScript } from '../src/adloader.js'; -import { MODULE_TYPE_RTD } from '../src/activities/modules.js'; +import {submodule} from '../src/hook.js'; +import {deepAccess, deepSetValue, mergeDeep} from '../src/utils.js'; +import {getStorageManager} from '../src/storageManager.js'; +import {loadExternalScript} from '../src/adloader.js'; +import {MODULE_TYPE_RTD} from '../src/activities/modules.js'; const MODULE_NAME = 'realTimeData'; const SUBMODULE_NAME = 'airgrid'; @@ -62,54 +57,35 @@ export function getMatchedAudiencesFromStorage() { } } -/** - * Mutates the adUnits object - * @param {Object} adUnits - * @param {Array} audiences - * @return {void} - */ -function setAudiencesToAppNexusAdUnits(adUnits, audiences) { - adUnits.forEach((adUnit) => { - adUnit.bids.forEach((bid) => { - if (bid.bidder && bid.bidder === 'appnexus') { - deepSetValue(bid, 'params.keywords.perid', audiences || []); - } - }); - }); -} - /** * Pass audience data to configured bidders, using ORTB2 + * @param {Object} bidConfig * @param {Object} rtdConfig * @param {Array} audiences - * @return {{}} a map from bidder code to ORTB2 config + * @return {void} */ -export function setAudiencesAsBidderOrtb2(rtdConfig, audiences) { +export function setAudiencesAsBidderOrtb2(bidConfig, rtdConfig, audiences) { const bidders = deepAccess(rtdConfig, 'params.bidders'); if (!bidders || bidders.length === 0 || !audiences || audiences.length === 0) return; - const keywords = audiences.map( - (audienceId) => `perid=${audienceId}` - ).join(','); + const agOrtb2 = {}; - config.mergeBidderConfig({ - bidders: bidders, - config: { - ortb2: { - site: { - keywords, - } - } + const agUserData = [ + { + id: String(AG_TCF_ID), + ext: { + segtax: 540, + }, + name: 'airgrid', + segment: audiences.map((id) => ({id})) } - }) -} + ] + deepSetValue(agOrtb2, 'user.data', agUserData); -export function setAudiencesUsingAppNexusAuctionKeywords(audiences) { - config.setConfig({ - appnexusAuctionKeywords: { - perid: audiences, - }, - }); + const bidderConfig = Object.fromEntries( + bidders.map((bidder) => [bidder, agOrtb2]) + ) + mergeDeep(bidConfig?.ortb2Fragments?.bidder, bidderConfig) } /** @@ -137,14 +113,9 @@ export function passAudiencesToBidders( rtdConfig, userConsent ) { - const adUnits = bidConfig.adUnits || getGlobal().adUnits; const audiences = getMatchedAudiencesFromStorage(); if (audiences.length > 0) { - setAudiencesUsingAppNexusAuctionKeywords(audiences); - setAudiencesAsBidderOrtb2(rtdConfig, audiences) - if (adUnits) { - setAudiencesToAppNexusAdUnits(adUnits, audiences); - } + setAudiencesAsBidderOrtb2(bidConfig, rtdConfig, audiences) } onDone(); } diff --git a/modules/ajaBidAdapter.js b/modules/ajaBidAdapter.js index 133a2fdbadf..ffab41611ef 100644 --- a/modules/ajaBidAdapter.js +++ b/modules/ajaBidAdapter.js @@ -55,7 +55,7 @@ export const spec = { const asi = getBidIdParameter('asi', bidRequest.params); queryString = tryAppendQueryString(queryString, 'asi', asi); queryString = tryAppendQueryString(queryString, 'skt', SDKType); - queryString = tryAppendQueryString(queryString, 'tid', bidRequest.transactionId) + queryString = tryAppendQueryString(queryString, 'tid', bidRequest.ortb2Imp?.ext?.tid) queryString = tryAppendQueryString(queryString, 'prebid_id', bidRequest.bidId); queryString = tryAppendQueryString(queryString, 'prebid_ver', '$prebid.version$'); diff --git a/modules/alkimiBidAdapter.js b/modules/alkimiBidAdapter.js index 69b3fdae3d8..c087b3061a0 100644 --- a/modules/alkimiBidAdapter.js +++ b/modules/alkimiBidAdapter.js @@ -1,5 +1,5 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; -import {deepClone, deepAccess} from '../src/utils.js'; +import {deepAccess, deepClone} from '../src/utils.js'; import {ajax} from '../src/ajax.js'; import {VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; @@ -41,6 +41,7 @@ export const spec = { const alkimiConfig = config.getConfig('alkimi'); let payload = { + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 requestId: bidderRequest.auctionId, signRequest: {bids, randomUUID: alkimiConfig && alkimiConfig.randomUUID}, bidIds, diff --git a/modules/amxBidAdapter.js b/modules/amxBidAdapter.js index 68a3a370c01..7286001b888 100644 --- a/modules/amxBidAdapter.js +++ b/modules/amxBidAdapter.js @@ -303,6 +303,7 @@ export const spec = { }; const payload = { + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 a: bidderRequest.auctionId, B: 0, b: loc.host, diff --git a/modules/aolBidAdapter.js b/modules/aolBidAdapter.js deleted file mode 100644 index d15a5434e0c..00000000000 --- a/modules/aolBidAdapter.js +++ /dev/null @@ -1,462 +0,0 @@ -import { isInteger, logError, isEmpty, logWarn, getUniqueIdentifierStr, _each, deepSetValue } from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER } from '../src/mediaTypes.js'; - -const AOL_BIDDERS_CODES = { - AOL: 'aol', - VERIZON: 'verizon', - ONEMOBILE: 'onemobile', - ONEDISPLAY: 'onedisplay' -}; - -const AOL_ENDPOINTS = { - DISPLAY: { - GET: 'display-get' - }, - MOBILE: { - GET: 'mobile-get', - POST: 'mobile-post' - } -}; - -const SYNC_TYPES = { - IFRAME: { - TAG: 'iframe', - TYPE: 'iframe' - }, - IMAGE: { - TAG: 'img', - TYPE: 'image' - } -}; - -const SUPPORTED_USER_ID_SOURCES = [ - 'admixer.net', - 'adserver.org', - 'adtelligent.com', - 'akamai.com', - 'amxdt.net', - 'audigent.com', - 'britepool.com', - 'criteo.com', - 'crwdcntrl.net', - 'deepintent.com', - 'epsilon.com', - 'hcn.health', - 'id5-sync.com', - 'idx.lat', - 'intentiq.com', - 'intimatemerger.com', - 'liveintent.com', - 'liveramp.com', - 'mediawallahscript.com', - 'merkleinc.com', - 'netid.de', - 'neustar.biz', - 'nextroll.com', - 'novatiq.com', - 'parrable.com', - 'pubcid.org', - 'quantcast.com', - 'tapad.com', - 'uidapi.com', - 'verizonmedia.com', - 'yahoo.com', - 'zeotap.com' -]; - -const pubapiTemplate = template`${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'};misc=${'misc'};${'dynamicParams'}`; -const nexageBaseApiTemplate = template`${'host'}/bidRequest?`; -const nexageGetApiTemplate = template`dcn=${'dcn'}&pos=${'pos'}&cmd=bid${'dynamicParams'}`; -const MP_SERVER_MAP = { - us: 'adserver-us.adtech.advertising.com', - eu: 'adserver-eu.adtech.advertising.com', - as: 'adserver-as.adtech.advertising.com' -}; -const NEXAGE_SERVER = 'c2shb.ssp.yahoo.com'; -const ONE_DISPLAY_TTL = 60; -const ONE_MOBILE_TTL = 3600; -const DEFAULT_PROTO = 'https'; - -const NUMERIC_VALUES = { - TRUE: 1, - FALSE: 0 -}; - -function template(strings, ...keys) { - return function (...values) { - let dict = values[values.length - 1] || {}; - let result = [strings[0]]; - keys.forEach(function (key, i) { - let value = isInteger(key) ? values[key] : dict[key]; - result.push(value, strings[i + 1]); - }); - return result.join(''); - }; -} - -function _isMarketplaceBidder(bidderCode) { - return bidderCode === AOL_BIDDERS_CODES.AOL || - bidderCode === AOL_BIDDERS_CODES.VERIZON || - bidderCode === AOL_BIDDERS_CODES.ONEDISPLAY; -} - -function _isOneMobileBidder(bidderCode) { - return bidderCode === AOL_BIDDERS_CODES.AOL || - bidderCode === AOL_BIDDERS_CODES.VERIZON || - bidderCode === AOL_BIDDERS_CODES.ONEMOBILE; -} - -function _isNexageRequestPost(bid) { - if (_isOneMobileBidder(bid.bidder) && bid.params.id && bid.params.imp && bid.params.imp[0]) { - let imp = bid.params.imp[0]; - return imp.id && imp.tagid && imp.banner && imp.banner.w && imp.banner.h; - } -} - -function _isNexageRequestGet(bid) { - return _isOneMobileBidder(bid.bidder) && bid.params.dcn && bid.params.pos; -} - -function isMarketplaceBid(bid) { - return _isMarketplaceBidder(bid.bidder) && bid.params.placement && bid.params.network; -} - -function isMobileBid(bid) { - return _isNexageRequestGet(bid) || _isNexageRequestPost(bid); -} - -function resolveEndpointCode(bid) { - if (_isNexageRequestGet(bid)) { - return AOL_ENDPOINTS.MOBILE.GET; - } else if (_isNexageRequestPost(bid)) { - return AOL_ENDPOINTS.MOBILE.POST; - } else if (isMarketplaceBid(bid)) { - return AOL_ENDPOINTS.DISPLAY.GET; - } -} - -function getSupportedEids(bid) { - return bid.userIdAsEids.filter(eid => { - return SUPPORTED_USER_ID_SOURCES.indexOf(eid.source) !== -1 - }); -} - -export const spec = { - code: AOL_BIDDERS_CODES.AOL, - gvlid: 25, - aliases: [ - AOL_BIDDERS_CODES.ONEMOBILE, - AOL_BIDDERS_CODES.ONEDISPLAY, - AOL_BIDDERS_CODES.VERIZON - ], - supportedMediaTypes: [BANNER], - isBidRequestValid(bid) { - return isMarketplaceBid(bid) || isMobileBid(bid); - }, - buildRequests(bids, bidderRequest) { - const consentData = {}; - if (bidderRequest) { - consentData.gdpr = bidderRequest.gdprConsent; - consentData.uspConsent = bidderRequest.uspConsent; - consentData.gppConsent = bidderRequest.gppConsent; - if (!consentData.gppConsent && bidderRequest.ortb2?.regs?.gpp) { - consentData.gppConsent = { - gppString: bidderRequest.ortb2.regs.gpp, - applicableSections: bidderRequest.ortb2.regs.gpp_sid - } - } - } - - return bids.map(bid => { - const endpointCode = resolveEndpointCode(bid); - - if (endpointCode) { - return this.formatBidRequest(endpointCode, bid, consentData); - } - }); - }, - interpretResponse({ body }, bidRequest) { - if (!body) { - logError('Empty bid response', bidRequest.bidderCode, body); - } else { - let bid = this._parseBidResponse(body, bidRequest); - - if (bid) { - return bid; - } - } - }, - getUserSyncs(options, serverResponses) { - const bidResponse = !isEmpty(serverResponses) && serverResponses[0].body; - - if (bidResponse && bidResponse.ext && bidResponse.ext.pixels) { - return this.parsePixelItems(bidResponse.ext.pixels); - } - - return []; - }, - - formatBidRequest(endpointCode, bid, consentData) { - let bidRequest; - - switch (endpointCode) { - case AOL_ENDPOINTS.DISPLAY.GET: - bidRequest = { - url: this.buildMarketplaceUrl(bid, consentData), - method: 'GET', - ttl: ONE_DISPLAY_TTL - }; - break; - - case AOL_ENDPOINTS.MOBILE.GET: - bidRequest = { - url: this.buildOneMobileGetUrl(bid, consentData), - method: 'GET', - ttl: ONE_MOBILE_TTL - }; - break; - - case AOL_ENDPOINTS.MOBILE.POST: - bidRequest = { - url: this.buildOneMobileBaseUrl(bid), - method: 'POST', - ttl: ONE_MOBILE_TTL, - data: this.buildOpenRtbRequestData(bid, consentData), - options: { - contentType: 'application/json', - customHeaders: { - 'x-openrtb-version': '2.2' - } - } - }; - break; - } - - bidRequest.bidderCode = bid.bidder; - bidRequest.bidId = bid.bidId; - bidRequest.userSyncOn = bid.params.userSyncOn; - - return bidRequest; - }, - buildMarketplaceUrl(bid, consentData) { - const params = bid.params; - const serverParam = params.server; - let regionParam = params.region || 'us'; - let server; - - if (!MP_SERVER_MAP.hasOwnProperty(regionParam)) { - logWarn(`Unknown region '${regionParam}' for AOL bidder.`); - regionParam = 'us'; // Default region. - } - - if (serverParam) { - server = serverParam; - } else { - server = MP_SERVER_MAP[regionParam]; - } - - // Set region param, used by AOL analytics. - params.region = regionParam; - - return this.applyProtocol(pubapiTemplate({ - host: server, - network: params.network, - placement: parseInt(params.placement), - pageid: params.pageId || 0, - sizeid: params.sizeId || 0, - alias: params.alias || getUniqueIdentifierStr(), - misc: new Date().getTime(), // cache busting - dynamicParams: this.formatMarketplaceDynamicParams(params, consentData) - })); - }, - buildOneMobileGetUrl(bid, consentData) { - let { dcn, pos, ext } = bid.params; - if (typeof bid.userId === 'object') { - ext = ext || {}; - let eids = getSupportedEids(bid); - eids.forEach(eid => { - ext['eid' + eid.source] = eid.uids[0].id; - }); - } - let nexageApi = this.buildOneMobileBaseUrl(bid); - if (dcn && pos) { - let dynamicParams = this.formatOneMobileDynamicParams(ext, consentData); - nexageApi += nexageGetApiTemplate({ dcn, pos, dynamicParams }); - } - return nexageApi; - }, - buildOneMobileBaseUrl(bid) { - return this.applyProtocol(nexageBaseApiTemplate({ - host: bid.params.host || NEXAGE_SERVER - })); - }, - applyProtocol(url) { - if (/^https?:\/\//i.test(url)) { - return url; - } - return (url.indexOf('//') === 0) ? `${DEFAULT_PROTO}:${url}` : `${DEFAULT_PROTO}://${url}`; - }, - formatMarketplaceDynamicParams(params = {}, consentData = {}) { - let queryParams = {}; - - Object.assign(queryParams, this.formatKeyValues(params.keyValues)); - Object.assign(queryParams, this.formatConsentData(consentData)); - - let paramsFormatted = ''; - _each(queryParams, (value, key) => { - paramsFormatted += `${key}=${encodeURIComponent(value)};`; - }); - - return paramsFormatted; - }, - formatOneMobileDynamicParams(params = {}, consentData = {}) { - if (this.isSecureProtocol()) { - params.secure = NUMERIC_VALUES.TRUE; - } - - Object.assign(params, this.formatConsentData(consentData)); - - let paramsFormatted = ''; - _each(params, (value, key) => { - paramsFormatted += `&${key}=${encodeURIComponent(value)}`; - }); - - return paramsFormatted; - }, - buildOpenRtbRequestData(bid, consentData = {}) { - let openRtbObject = { - id: bid.params.id, - imp: bid.params.imp - }; - - if (this.isEUConsentRequired(consentData)) { - deepSetValue(openRtbObject, 'regs.ext.gdpr', NUMERIC_VALUES.TRUE); - if (consentData.gdpr.consentString) { - deepSetValue(openRtbObject, 'user.ext.consent', consentData.gdpr.consentString); - } - } - - if (consentData.uspConsent) { - deepSetValue(openRtbObject, 'regs.ext.us_privacy', consentData.uspConsent); - } - - if (typeof bid.userId === 'object') { - openRtbObject.user = openRtbObject.user || {}; - openRtbObject.user.ext = openRtbObject.user.ext || {}; - - let eids = getSupportedEids(bid); - if (eids.length > 0) { - openRtbObject.user.ext.eids = eids - } - } - - return openRtbObject; - }, - isEUConsentRequired(consentData) { - return !!(consentData && consentData.gdpr && consentData.gdpr.gdprApplies); - }, - formatKeyValues(keyValues) { - let keyValuesHash = {}; - - _each(keyValues, (value, key) => { - keyValuesHash[`kv${key}`] = value; - }); - - return keyValuesHash; - }, - formatConsentData(consentData) { - let params = {}; - - if (this.isEUConsentRequired(consentData)) { - params.gdpr = NUMERIC_VALUES.TRUE; - - if (consentData.gdpr.consentString) { - params.euconsent = consentData.gdpr.consentString; - } - } - - if (consentData.uspConsent) { - params.us_privacy = consentData.uspConsent; - } - - if (consentData.gppConsent && consentData.gppConsent.gppString) { - params.gpp = consentData.gppConsent.gppString; - params.gpp_sid = consentData.gppConsent.applicableSections; - } - - return params; - }, - parsePixelItems(pixels) { - let itemsRegExp = /(img|iframe)[\s\S]*?src\s*=\s*("|')(.*?)\2/gi; - let tagNameRegExp = /\w*(?=\s)/; - let srcRegExp = /src=("|')(.*?)\1/; - let pixelsItems = []; - - if (pixels) { - let matchedItems = pixels.match(itemsRegExp); - if (matchedItems) { - matchedItems.forEach(item => { - let tagName = item.match(tagNameRegExp)[0]; - let url = item.match(srcRegExp)[2]; - - if (tagName && url) { - pixelsItems.push({ - type: tagName === SYNC_TYPES.IMAGE.TAG ? SYNC_TYPES.IMAGE.TYPE : SYNC_TYPES.IFRAME.TYPE, - url: url - }); - } - }); - } - } - - return pixelsItems; - }, - - _parseBidResponse(response, bidRequest) { - let bidData; - - try { - bidData = response.seatbid[0].bid[0]; - } catch (e) { - return; - } - - let cpm; - - if (bidData.ext && bidData.ext.encp) { - cpm = bidData.ext.encp; - } else { - cpm = bidData.price; - - if (cpm === null || isNaN(cpm)) { - logError('Invalid price in bid response', AOL_BIDDERS_CODES.AOL, bidData); - return; - } - } - - return { - bidderCode: bidRequest.bidderCode, - requestId: bidRequest.bidId, - ad: bidData.adm, - cpm: cpm, - width: bidData.w, - height: bidData.h, - creativeId: bidData.crid || 0, - pubapiId: response.id, - currency: response.cur || 'USD', - dealId: bidData.dealid, - netRevenue: true, - meta: { - advertiserDomains: bidData && bidData.adomain ? bidData.adomain : [] - }, - ttl: bidRequest.ttl - }; - }, - isOneMobileBidder: _isOneMobileBidder, - isSecureProtocol() { - return document.location.protocol === 'https:'; - } -}; - -registerBidder(spec); diff --git a/modules/aolBidAdapter.md b/modules/aolBidAdapter.md deleted file mode 100644 index 8a9d1e3291d..00000000000 --- a/modules/aolBidAdapter.md +++ /dev/null @@ -1,46 +0,0 @@ -# Overview - -Module Name: AOL Bid Adapter - -Module Type: AOL Adapter - -Maintainer: hb-fe-tech@oath.com - -# Description - -Module that connects to AOL's demand sources - -# Test Parameters -```javascript - var adUnits = [ - { - code: 'test-ad', - sizes: [[300, 250]], - bids: [ - { - bidder: 'onedisplay', - params: { - placement: '3611253', - network: '9599.1', - keyValues: { - test: 'key' - } - } - } - ] - }, - { - code: 'test-mobile-ad', - sizes: [[300, 250]], - bids: [ - { - bidder: 'onemobile', - params: { - dcn: '2c9d2b50015a5aa95b70a9b0b5b10012', - pos: 'header' - } - } - ] - } - ]; -``` diff --git a/modules/apacdexBidAdapter.js b/modules/apacdexBidAdapter.js index 10593855c59..e1557d9c6d3 100644 --- a/modules/apacdexBidAdapter.js +++ b/modules/apacdexBidAdapter.js @@ -1,4 +1,4 @@ -import { deepAccess, isPlainObject, isArray, replaceAuctionPrice, isFn } from '../src/utils.js'; +import { deepAccess, isPlainObject, isArray, replaceAuctionPrice, isFn, logError } from '../src/utils.js'; import { config } from '../src/config.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import {hasPurpose1Consent} from '../src/utils/gpdr.js'; @@ -134,14 +134,14 @@ export const spec = { // Apply geo if (geo) { - payload.geo = geo; + logError('apacdex adapter: Precise lat and long must be set on config; not on bidder parameters'); } payload.bids = bids.map(function (bid) { return { params: bid.params, mediaTypes: bid.mediaTypes, - transactionId: bid.transactionId, + transactionId: bid.ortb2Imp?.ext?.tid, sizes: bid.sizes, bidId: bid.bidId, adUnitCode: bid.adUnitCode, diff --git a/modules/appnexusBidAdapter.js b/modules/appnexusBidAdapter.js index bf9c44c4c31..0660f4f4b10 100644 --- a/modules/appnexusBidAdapter.js +++ b/modules/appnexusBidAdapter.js @@ -22,21 +22,25 @@ import { logError, logInfo, logMessage, - logWarn, - mergeDeep, - transformBidderParamKeywords + logWarn } from '../src/utils.js'; import {Renderer} from '../src/Renderer.js'; import {config} from '../src/config.js'; -import {getIabSubCategory, registerBidder} from '../src/adapters/bidderFactory.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; import {ADPOD, BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; -import {auctionManager} from '../src/auctionManager.js'; import {find, includes} from '../src/polyfill.js'; import {INSTREAM, OUTSTREAM} from '../src/video.js'; import {getStorageManager} from '../src/storageManager.js'; import {bidderSettings} from '../src/bidderSettings.js'; import {hasPurpose1Consent} from '../src/utils/gpdr.js'; -import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; +import {APPNEXUS_CATEGORY_MAPPING} from '../libraries/categoryTranslationMapping/index.js'; +import { + convertKeywordStringToANMap, + getANKewyordParamFromMaps, + getANKeywordParam, + transformBidderParamKeywords +} from '../libraries/appnexusKeywords/anKeywords.js'; const BIDDER_CODE = 'appnexus'; const URL = 'https://ib.adnxs.com/ut/v3/prebid'; @@ -89,7 +93,6 @@ const NATIVE_MAPPING = { }; const SOURCE = 'pbjs'; const MAX_IMPS_PER_REQUEST = 15; -const mappingFileUrl = 'https://acdn.adnxs-simple.com/prebid/appnexus-mapping/mappings.json'; const SCRIPT_TAG_START = ' { - let keyStr = deepAccess(ortb2Obj, path); - if (isStr(keyStr)) result.push(keyStr); - }); - return result; - } - // grab the ortb2 keyword data (if it exists) and convert from the comma list string format to object format let ortb2 = deepClone(bidderRequest && bidderRequest.ortb2); - let ortb2KeywordsObjList = grabOrtb2Keywords(ortb2).map(keyStr => convertStringToKeywordsObj(keyStr)); let anAuctionKeywords = deepClone(config.getConfig('appnexusAuctionKeywords')) || {}; - // need to convert the string values into array of strings, to properly merge values with other existing keys later - Object.keys(anAuctionKeywords).forEach(k => { if (isStr(anAuctionKeywords[k]) || isNumber(anAuctionKeywords[k])) anAuctionKeywords[k] = [anAuctionKeywords[k]] }); - // combine all sources of keywords (converted from string comma list to object format) into one object (that combines the values for shared keys) - let mergedAuctionKeywords = mergeDeep({}, anAuctionKeywords, ...ortb2KeywordsObjList); - - // convert to final format used by adserver - let auctionKeywords = transformBidderParamKeywords(mergedAuctionKeywords); + let auctionKeywords = getANKeywordParam(ortb2, anAuctionKeywords) if (auctionKeywords.length > 0) { - auctionKeywords.forEach(deleteValues); payload.keywords = auctionKeywords; } @@ -422,24 +405,6 @@ export const spec = { return bids; }, - /** - * @typedef {Object} mappingFileInfo - * @property {string} url mapping file json url - * @property {number} refreshInDays prebid stores mapping data in localstorage so you can return in how many days you want to update value stored in localstorage. - * @property {string} localStorageKey unique key to store your mapping json in localstorage - */ - - /** - * Returns mapping file info. This info will be used by bidderFactory to preload mapping file and store data in local storage - * @returns {mappingFileInfo} - */ - getMappingFileInfo: function () { - return { - url: mappingFileUrl, - refreshInDays: 2 - } - }, - getUserSyncs: function (syncOptions, responses, gdprConsent, uspConsent, gppConsent) { function checkGppStatus(gppConsent) { // this is a temporary measure to supress usersync in US-based GPP regions @@ -488,10 +453,6 @@ export const spec = { }, params); if (isOpenRtb) { - if (isPopulatedArray(params.keywords)) { - params.keywords.forEach(deleteValues); - } - Object.keys(params).forEach(paramKey => { let convertedKey = convertCamelToUnderscore(paramKey); if (convertedKey !== paramKey) { @@ -508,16 +469,6 @@ export const spec = { } }; -function isPopulatedArray(arr) { - return !!(isArray(arr) && arr.length > 0); -} - -function deleteValues(keyPairObj) { - if (isPopulatedArray(keyPairObj.value) && keyPairObj.value[0] === '') { - delete keyPairObj.value; - } -} - function strIsAppnexusViewabilityScript(str) { if (!str || str === '') return false; @@ -669,7 +620,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { const videoContext = deepAccess(bidRequest, 'mediaTypes.video.context'); switch (videoContext) { case ADPOD: - const primaryCatId = getIabSubCategory(bidRequest.bidder, rtbBid.brand_category_id); + const primaryCatId = (APPNEXUS_CATEGORY_MAPPING[rtbBid.brand_category_id]) ? APPNEXUS_CATEGORY_MAPPING[rtbBid.brand_category_id] : null; bid.meta = Object.assign({}, bid.meta, { primaryCatId }); const dealTier = rtbBid.deal_priority; bid.video = { @@ -832,24 +783,9 @@ function bidToTag(bid) { tag.external_imp_id = bid.params.external_imp_id; } - let ortb2ImpKwStr = deepAccess(bid, 'ortb2Imp.ext.data.keywords'); - if ((isStr(ortb2ImpKwStr) && ortb2ImpKwStr !== '') || !isEmpty(bid.params.keywords)) { - // convert ortb2 from comma list string format to bid param object format - let ortb2ImpKwObj = convertStringToKeywordsObj(ortb2ImpKwStr); - - let bidParamsKwObj = (isPlainObject(bid.params.keywords)) ? deepClone(bid.params.keywords) : {}; - // need to convert the string values into an array of strings, to properly merge values with other existing keys later - Object.keys(bidParamsKwObj).forEach(k => { if (isStr(bidParamsKwObj[k]) || isNumber(bidParamsKwObj[k])) bidParamsKwObj[k] = [bidParamsKwObj[k]] }); - - // combine both sources of keywords into one merged object (that combines the values for shared keys) - let keywordsObj = mergeDeep({}, bidParamsKwObj, ortb2ImpKwObj); - - // convert to final format used by adserver - let keywordsUt = transformBidderParamKeywords(keywordsObj); - if (keywordsUt.length > 0) { - keywordsUt.forEach(deleteValues); - tag.keywords = keywordsUt; - } + const auKeywords = getANKewyordParamFromMaps(convertKeywordStringToANMap(deepAccess(bid, 'ortb2Imp.ext.data.keywords')), bid.params?.keywords); + if (auKeywords.length > 0) { + tag.keywords = auKeywords; } let gpid = deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); @@ -980,8 +916,7 @@ function bidToTag(bid) { tag['banner_frameworks'] = bid.params.frameworks; } - let adUnit = find(auctionManager.getAdUnits(), au => bid.transactionId === au.transactionId); - if (adUnit && adUnit.mediaTypes && adUnit.mediaTypes.banner) { + if (deepAccess(bid, `mediaTypes.${BANNER}`)) { tag.ad_types.push(BANNER); } @@ -1277,37 +1212,4 @@ function convertKeywordsToString(keywords) { return result; } -// converts a comma separated list of keywords into the standard keyword object format used in appnexus bid params -// 'genre=rock,genre=pop,pets=dog,music' goes to { 'genre': ['rock', 'pop'], 'pets': ['dog'], 'music': [''] } -function convertStringToKeywordsObj(keyStr) { - let result = {}; - - if (isStr(keyStr) && keyStr !== '') { - // will split based on commas and will eat white space before/after the comma - let keywordList = keyStr.split(/\s*(?:,)\s*/); - keywordList.forEach(kw => { - // if = exists, then split - if (kw.indexOf('=') !== -1) { - let kwPair = kw.split('='); - let key = kwPair[0]; - let val = kwPair[1]; - - // then check for existing key in result > if so add value to the array > if not, add new key and create value array - if (result.hasOwnProperty(key)) { - result[key].push(val); - } else { - result[key] = [val]; - } - } else { - // make a key with '' value; if key already exists > don't add - if (!result.hasOwnProperty(kw)) { - result[kw] = ['']; - } - } - }); - } - - return result; -} - registerBidder(spec); diff --git a/modules/apstreamBidAdapter.js b/modules/apstreamBidAdapter.js index 871b04442da..2856fb02087 100644 --- a/modules/apstreamBidAdapter.js +++ b/modules/apstreamBidAdapter.js @@ -421,6 +421,7 @@ function buildRequests(bidRequests, bidderRequest) { bidRequests = convertOrtbRequestToProprietaryNative(bidRequests); const data = { med: encodeURIComponent(window.location.href), + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 auid: bidderRequest.auctionId, ref: document.referrer, dnt: getDNT() ? 1 : 0, diff --git a/modules/asoBidAdapter.js b/modules/asoBidAdapter.js index 7db9a89bd74..e569f04a2a8 100644 --- a/modules/asoBidAdapter.js +++ b/modules/asoBidAdapter.js @@ -300,7 +300,7 @@ function createBasePayload(bidRequest, bidderRequest) { const urlsInfo = getUrlsInfo(bidderRequest); const payload = { - id: bidRequest.auctionId + '_' + bidRequest.bidId, + id: bidRequest.bidId, at: 1, tmax: bidderRequest.timeout, site: { diff --git a/modules/astraoneBidAdapter.js b/modules/astraoneBidAdapter.js index d6bfa4b93ee..d7f92bb5fac 100644 --- a/modules/astraoneBidAdapter.js +++ b/modules/astraoneBidAdapter.js @@ -11,7 +11,7 @@ function buildBidRequests(validBidRequests) { const params = validBidRequest.params; const bidRequest = { bidId: validBidRequest.bidId, - transactionId: validBidRequest.transactionId, + transactionId: validBidRequest.ortb2Imp?.ext?.tid, sizes: validBidRequest.sizes, placement: params.placement, placeId: params.placeId, diff --git a/modules/audiencerunBidAdapter.js b/modules/audiencerunBidAdapter.js index efd88aa6f58..9beb20d4f77 100644 --- a/modules/audiencerunBidAdapter.js +++ b/modules/audiencerunBidAdapter.js @@ -114,8 +114,9 @@ export const spec = { bidId: bid.bidId, bidderRequestId: getBidIdParameter('bidderRequestId', bid), adUnitCode: getBidIdParameter('adUnitCode', bid), + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 auctionId: getBidIdParameter('auctionId', bid), - transactionId: getBidIdParameter('transactionId', bid), + transactionId: bid.ortb2Imp?.ext?.tid || '', }; }); diff --git a/modules/automatadBidAdapter.js b/modules/automatadBidAdapter.js index 1174c2a9f38..bea2a9df5b2 100644 --- a/modules/automatadBidAdapter.js +++ b/modules/automatadBidAdapter.js @@ -1,7 +1,7 @@ -import { logInfo } from '../src/utils.js'; -import {registerBidder} from '../src/adapters/bidderFactory.js' -import {BANNER} from '../src/mediaTypes.js' -import {ajax} from '../src/ajax.js' +import {logInfo} from '../src/utils.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {BANNER} from '../src/mediaTypes.js'; +import {ajax} from '../src/ajax.js'; const BIDDER = 'automatad' @@ -57,7 +57,7 @@ export const spec = { // params from bid request const openrtbRequest = { - id: validBidRequests[0].auctionId, + id: bidderRequest.bidderRequestId, imp: impressions, site: { id: siteId, diff --git a/modules/beachfrontBidAdapter.js b/modules/beachfrontBidAdapter.js index f80481d66c8..37de8e637a9 100644 --- a/modules/beachfrontBidAdapter.js +++ b/modules/beachfrontBidAdapter.js @@ -103,7 +103,6 @@ export const spec = { let responseMeta = Object.assign({ mediaType: VIDEO, advertiserDomains: [] }, response.meta); let bidResponse = { requestId: bidRequest.bidId, - bidderCode: spec.code, cpm: response.bidPrice, width: firstSize.w, height: firstSize.h, diff --git a/modules/beopBidAdapter.js b/modules/beopBidAdapter.js index 07c62bbee8c..6348854ec2a 100644 --- a/modules/beopBidAdapter.js +++ b/modules/beopBidAdapter.js @@ -1,7 +1,18 @@ -import { deepAccess, isArray, isStr, logWarn, triggerPixel, buildUrl, logInfo, getValue, getBidIdParameter } from '../src/utils.js'; -import { getRefererInfo } from '../src/refererDetection.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { config } from '../src/config.js'; +import { + buildUrl, + deepAccess, + getBidIdParameter, + getValue, + isArray, + logInfo, + logWarn, + triggerPixel +} from '../src/utils.js'; +import {getRefererInfo} from '../src/refererDetection.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {config} from '../src/config.js'; +import {getAllOrtbKeywords} from '../libraries/keywords/keywords.js'; + const BIDDER_CODE = 'beop'; const ENDPOINT_URL = 'https://hb.beop.io/bid'; const TCF_VENDOR_ID = 666; @@ -43,18 +54,8 @@ export const spec = { const gdpr = bidderRequest.gdprConsent; const firstSlot = slots[0]; const kwdsFromRequest = firstSlot.kwds; - let keywords = []; - if (kwdsFromRequest) { - if (isArray(kwdsFromRequest)) { - keywords = kwdsFromRequest; - } else if (isStr(kwdsFromRequest)) { - if (kwdsFromRequest.indexOf(',') != -1) { - keywords = kwdsFromRequest.split(',').map((e) => { return e.trim() }); - } else { - keywords.push(kwdsFromRequest); - } - } - } + let keywords = getAllOrtbKeywords(bidderRequest.ortb2, kwdsFromRequest); + const payloadObject = { at: new Date().toString(), nid: firstSlot.nid, @@ -128,6 +129,7 @@ function buildTrackingParams(data, info, value) { nptnid: params.networkPartnerId, bid: data.bidId || data.requestId, sl_n: data.adUnitCode, + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 aid: data.auctionId, se_ca: 'bid', se_ac: info, @@ -156,8 +158,9 @@ function beOpRequestSlotsMaker(bid) { bid: getBidIdParameter('bidId', bid), brid: getBidIdParameter('bidderRequestId', bid), name: getBidIdParameter('adUnitCode', bid), + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 aid: getBidIdParameter('auctionId', bid), - tid: getBidIdParameter('transactionId', bid), + tid: bid.ortb2Imp?.ext?.tid || '', brc: getBidIdParameter('bidRequestsCount', bid), bdrc: getBidIdParameter('bidderRequestCount', bid), bwc: getBidIdParameter('bidderWinsCount', bid), diff --git a/modules/betweenBidAdapter.js b/modules/betweenBidAdapter.js index ea28420481d..d615e433cc0 100644 --- a/modules/betweenBidAdapter.js +++ b/modules/betweenBidAdapter.js @@ -43,7 +43,8 @@ export const spec = { rr: getRr(), s: i.params && i.params.s, bidid: i.bidId, - transactionid: i.transactionId, + transactionid: i.ortb2Imp?.ext?.tid, + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 auctionid: i.auctionId }; diff --git a/modules/bizzclickBidAdapter.js b/modules/bizzclickBidAdapter.js index 4ef2b6dd9f8..dc7731231ab 100644 --- a/modules/bizzclickBidAdapter.js +++ b/modules/bizzclickBidAdapter.js @@ -1,8 +1,9 @@ -import { logMessage, getDNT, deepSetValue, deepAccess, _map, logWarn } from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; +import {_map, deepAccess, deepSetValue, getDNT, logMessage, logWarn} from '../src/utils.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {config} from '../src/config.js'; -import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; + const BIDDER_CODE = 'bizzclick'; const ACCOUNTID_MACROS = '[account_id]'; const URL_ENDPOINT = `https://us-e-node1.bizzclick.com/bid?rtb_seat_id=prebidjs&secret_key=${ACCOUNTID_MACROS}`; @@ -92,7 +93,7 @@ export const spec = { host: location.host }, source: { - tid: bidRequest.transactionId, + tid: bidRequest.ortb2Imp?.ext?.tid, ext: { schain: {} } @@ -234,7 +235,9 @@ const prepareImpObject = (bidRequest) => { }; const addNativeParameters = bidRequest => { let impObject = { - id: bidRequest.transactionId, + // TODO: top-level ID is not in ORTB native 1.2, is this intentional? + // (despite the name, this appears to be an ORTB native request - not an imp - object) + id: bidRequest.bidId, ver: NATIVE_VERSION, }; const assets = _map(bidRequest.mediaTypes.native, (bidParams, key) => { diff --git a/modules/bliinkBidAdapter.js b/modules/bliinkBidAdapter.js index ee814807331..9a9d74d14c1 100644 --- a/modules/bliinkBidAdapter.js +++ b/modules/bliinkBidAdapter.js @@ -154,6 +154,7 @@ export const buildRequests = (validBidRequests, bidderRequest) => { return { sizes: bid.sizes.map((size) => ({ w: size[0], h: size[1] })), id: bid.params.tagId, + // TODO: bidId is globally unique, is it a good choice for transaction ID (vs ortb2Imp.ext.tid)? transactionId: bid.bidId, mediaTypes: Object.keys(bid.mediaTypes), imageUrl: deepAccess(bid, 'params.imageUrl', ''), diff --git a/modules/bluebillywigBidAdapter.js b/modules/bluebillywigBidAdapter.js index 9022ca120af..d4bde9b3f2c 100644 --- a/modules/bluebillywigBidAdapter.js +++ b/modules/bluebillywigBidAdapter.js @@ -276,8 +276,8 @@ export const spec = { }); const request = { - id: bidderRequest.auctionId, - source: {tid: bidderRequest.auctionId}, + id: bidderRequest.bidderRequestId, + source: {tid: bidderRequest.ortb2?.source?.tid}, tmax: BB_CONSTANTS.DEFAULT_TIMEOUT, imp: imps, test: DEV_MODE ? 1 : 0, diff --git a/modules/braveBidAdapter.js b/modules/braveBidAdapter.js index ea8b4af690c..d954522ae24 100644 --- a/modules/braveBidAdapter.js +++ b/modules/braveBidAdapter.js @@ -1,8 +1,8 @@ -import { parseUrl, isEmpty, isStr, triggerPixel } from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes.js'; -import { config } from '../src/config.js'; -import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import {isEmpty, isStr, parseUrl, triggerPixel} from '../src/utils.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; +import {config} from '../src/config.js'; +import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; const BIDDER_CODE = 'brave'; const DEFAULT_CUR = 'USD'; @@ -58,7 +58,8 @@ export const spec = { impObject.video = createVideoRequest(br); } else if (br.mediaTypes.native) { impObject.native = { - id: br.transactionId, + // TODO: `id` is not part of the ORTB native spec, is this intentional? + id: br.bidId, ver: '1.2', request: createNativeRequest(br) }; @@ -229,7 +230,8 @@ const createBannerRequest = br => { }; const createVideoRequest = br => { - let videoObj = {id: br.transactionId}; + // TODO: `id` is not part of imp.video in ORTB; is this intentional? + let videoObj = {id: br.bidId}; let supportParamsList = ['mimes', 'minduration', 'maxduration', 'protocols', 'startdelay', 'skip', 'minbitrate', 'maxbitrate', 'api', 'linearity']; for (let param of supportParamsList) { diff --git a/modules/browsiBidAdapter.js b/modules/browsiBidAdapter.js index f66b7b2c353..03b6b2a8f3d 100644 --- a/modules/browsiBidAdapter.js +++ b/modules/browsiBidAdapter.js @@ -38,7 +38,7 @@ export const spec = { const requests = []; const {refererInfo, bidderRequestId, gdprConsent, uspConsent} = bidderRequest; validBidRequests.forEach(bidRequest => { - const {bidId, adUnitCode, auctionId, transactionId, schain, params} = bidRequest; + const {bidId, adUnitCode, auctionId, ortb2Imp, schain, params} = bidRequest; const video = getVideoMediaType(bidRequest); const request = { @@ -55,8 +55,9 @@ export const spec = { sizes: video.playerSize, video: video, aUCode: adUnitCode, + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 aID: auctionId, - tID: transactionId, + tID: ortb2Imp?.ext?.tid, schain: schain, params: params } @@ -98,7 +99,6 @@ export const spec = { width: w, height: h, currency: cur, - bidderCode: BIDDER_CODE, ...extraParams }; bidResponses.push(bidResponse); diff --git a/modules/emx_digitalBidAdapter.js b/modules/cadentApertureMXBidAdapter.js similarity index 77% rename from modules/emx_digitalBidAdapter.js rename to modules/cadentApertureMXBidAdapter.js index 99f313b9484..26e8639154c 100644 --- a/modules/emx_digitalBidAdapter.js +++ b/modules/cadentApertureMXBidAdapter.js @@ -15,18 +15,22 @@ import {Renderer} from '../src/Renderer.js'; import {find, includes} from '../src/polyfill.js'; import {parseDomain} from '../src/refererDetection.js'; -const BIDDER_CODE = 'emx_digital'; +const BIDDER_CODE = 'cadent_aperture_mx'; const ENDPOINT = 'hb.emxdgt.com'; const RENDERER_URL = 'https://js.brealtime.com/outstream/1.30.0/bundle.js'; const ADAPTER_VERSION = '1.5.1'; const DEFAULT_CUR = 'USD'; +const ALIASES = [ + { code: 'emx_digital', gvlid: 183 }, + { code: 'cadent', gvlid: 183 }, +]; const EIDS_SUPPORTED = [ { key: 'idl_env', source: 'liveramp.com', rtiPartner: 'idl', queryParam: 'idl' }, { key: 'uid2.id', source: 'uidapi.com', rtiPartner: 'UID2', queryParam: 'uid2' } ]; -export const emxAdapter = { +export const cadentAdapter = { validateSizes: (sizes) => { if (!isArray(sizes) || typeof sizes[0] === 'undefined') { logWarn(BIDDER_CODE + ': Sizes should be an array'); @@ -40,7 +44,7 @@ export const emxAdapter = { buildBanner: (bid) => { let sizes = []; bid.mediaTypes && bid.mediaTypes.banner && bid.mediaTypes.banner.sizes ? sizes = bid.mediaTypes.banner.sizes : sizes = bid.sizes; - if (!emxAdapter.validateSizes(sizes)) { + if (!cadentAdapter.validateSizes(sizes)) { logWarn(BIDDER_CODE + ': could not detect mediaType banner sizes. Assigning to bid sizes instead'); sizes = bid.sizes } @@ -55,13 +59,13 @@ export const emxAdapter = { h: sizes[0][1] }; }, - formatVideoResponse: (bidResponse, emxBid, bidRequest) => { - bidResponse.vastXml = emxBid.adm; + formatVideoResponse: (bidResponse, cadentBid, bidRequest) => { + bidResponse.vastXml = cadentBid.adm; if (bidRequest.bidderRequest && bidRequest.bidderRequest.bids && bidRequest.bidderRequest.bids.length > 0) { const matchingBid = find(bidRequest.bidderRequest.bids, bid => bidResponse.requestId && bid.bidId && bidResponse.requestId === bid.bidId && bid.mediaTypes && bid.mediaTypes.video && bid.mediaTypes.video.context === 'outstream'); if (matchingBid) { - bidResponse.renderer = emxAdapter.createRenderer(bidResponse, { - id: emxBid.id, + bidResponse.renderer = cadentAdapter.createRenderer(bidResponse, { + id: cadentBid.id, url: RENDERER_URL }); } @@ -81,7 +85,7 @@ export const emxAdapter = { dnt: (navigator.doNotTrack === 'yes' || navigator.doNotTrack === '1' || navigator.msDoNotTrack === '1') ? 1 : 0, h: screen.height, w: screen.width, - devicetype: emxAdapter.isMobile() ? 1 : emxAdapter.isConnectedTV() ? 3 : 2, + devicetype: cadentAdapter.isMobile() ? 1 : cadentAdapter.isConnectedTV() ? 3 : 2, language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), }; }, @@ -114,7 +118,7 @@ export const emxAdapter = { loaded: false }); try { - renderer.setRender(emxAdapter.outstreamRender); + renderer.setRender(cadentAdapter.outstreamRender); } catch (err) { logWarn('Prebid Error calling setRender on renderer', err); } @@ -131,13 +135,13 @@ export const emxAdapter = { videoObj['w'] = bid.mediaTypes.video.playerSize[0]; videoObj['h'] = bid.mediaTypes.video.playerSize[1]; } - return emxAdapter.cleanProtocols(videoObj); + return cadentAdapter.cleanProtocols(videoObj); }, parseResponse: (bidResponseAdm) => { try { return decodeURIComponent(bidResponseAdm.replace(/%(?![0-9][0-9a-fA-F]+)/g, '%25')); } catch (err) { - logError('emx_digitalBidAdapter', 'error', err); + logError('cadent_aperture_mxBidAdapter', 'error', err); } }, getSite: (refInfo) => { @@ -148,45 +152,45 @@ export const emxAdapter = { ref: refInfo.ref || window.document.referrer } }, - getGdpr: (bidRequests, emxData) => { + getGdpr: (bidRequests, cadentData) => { if (bidRequests.gdprConsent) { - emxData.regs = { + cadentData.regs = { ext: { gdpr: bidRequests.gdprConsent.gdprApplies === true ? 1 : 0 } }; } if (bidRequests.gdprConsent && bidRequests.gdprConsent.gdprApplies) { - emxData.user = { + cadentData.user = { ext: { consent: bidRequests.gdprConsent.consentString } }; } - return emxData; + return cadentData; }, - getSupplyChain: (bidderRequest, emxData) => { + getSupplyChain: (bidderRequest, cadentData) => { if (bidderRequest.bids[0] && bidderRequest.bids[0].schain) { - emxData.source = { + cadentData.source = { ext: { schain: bidderRequest.bids[0].schain } }; } - return emxData; + return cadentData; }, // supporting eids getEids(bidRequests) { return EIDS_SUPPORTED - .map(emxAdapter.getUserId(bidRequests)) + .map(cadentAdapter.getUserId(bidRequests)) .filter(x => x); }, getUserId(bidRequests) { return ({ key, source, rtiPartner }) => { let id = deepAccess(bidRequests, `userId.${key}`); - return id ? emxAdapter.formatEid(id, source, rtiPartner) : null; + return id ? cadentAdapter.formatEid(id, source, rtiPartner) : null; }; }, formatEid(id, source, rtiPartner) { @@ -203,6 +207,7 @@ export const emxAdapter = { export const spec = { code: BIDDER_CODE, gvlid: 183, + alias: ALIASES, supportedMediaTypes: [BANNER, VIDEO], isBidRequestValid: function (bid) { if (!bid || !bid.params) { @@ -211,7 +216,7 @@ export const spec = { } if (bid.bidder !== BIDDER_CODE) { - logWarn(BIDDER_CODE + ': Must use "emx_digital" as bidder code.'); + logWarn(BIDDER_CODE + ': Must use "cadent_aperture_mx" as bidder code.'); return false; } @@ -223,12 +228,12 @@ export const spec = { if (bid.mediaTypes && bid.mediaTypes.banner) { let sizes; bid.mediaTypes.banner.sizes ? sizes = bid.mediaTypes.banner.sizes : sizes = bid.sizes; - if (!emxAdapter.validateSizes(sizes)) { + if (!cadentAdapter.validateSizes(sizes)) { logWarn(BIDDER_CODE + ': Missing sizes in bid'); return false; } } else if (bid.mediaTypes && bid.mediaTypes.video) { - if (!emxAdapter.checkVideoContext(bid)) { + if (!cadentAdapter.checkVideoContext(bid)) { logWarn(BIDDER_CODE + ': Missing video context: instream or outstream'); return false; } @@ -242,13 +247,13 @@ export const spec = { return true; }, buildRequests: function (validBidRequests, bidderRequest) { - const emxImps = []; + const cadentImps = []; const timeout = bidderRequest.timeout || ''; const timestamp = Date.now(); const url = 'https://' + ENDPOINT + ('?t=' + timeout + '&ts=' + timestamp + '&src=pbjs'); const secure = location.protocol.indexOf('https') > -1 ? 1 : 0; - const device = emxAdapter.getDevice(); - const site = emxAdapter.getSite(bidderRequest.refererInfo); + const device = cadentAdapter.getDevice(); + const site = cadentAdapter.getSite(bidderRequest.refererInfo); _each(validBidRequests, function (bid) { let tagid = getBidIdParameter('tagid', bid.params); @@ -269,35 +274,35 @@ export const spec = { if (gpid) { data.ext = {gpid: gpid.toString()}; } - let typeSpecifics = isVideo ? { video: emxAdapter.buildVideo(bid) } : { banner: emxAdapter.buildBanner(bid) }; + let typeSpecifics = isVideo ? { video: cadentAdapter.buildVideo(bid) } : { banner: cadentAdapter.buildBanner(bid) }; let bidfloorObj = bidfloor > 0 ? { bidfloor, bidfloorcur: DEFAULT_CUR } : {}; - let emxBid = Object.assign(data, typeSpecifics, bidfloorObj); - emxImps.push(emxBid); + let cadentBid = Object.assign(data, typeSpecifics, bidfloorObj); + cadentImps.push(cadentBid); }); - let emxData = { + let cadentData = { id: bidderRequest.auctionId, - imp: emxImps, + imp: cadentImps, device, site, cur: DEFAULT_CUR, version: ADAPTER_VERSION }; - emxData = emxAdapter.getGdpr(bidderRequest, Object.assign({}, emxData)); - emxData = emxAdapter.getSupplyChain(bidderRequest, Object.assign({}, emxData)); + cadentData = cadentAdapter.getGdpr(bidderRequest, Object.assign({}, cadentData)); + cadentData = cadentAdapter.getSupplyChain(bidderRequest, Object.assign({}, cadentData)); if (bidderRequest && bidderRequest.uspConsent) { - emxData.us_privacy = bidderRequest.uspConsent; + cadentData.us_privacy = bidderRequest.uspConsent; } // adding eid support if (bidderRequest.userId) { - let eids = emxAdapter.getEids(bidderRequest); + let eids = cadentAdapter.getEids(bidderRequest); if (eids.length > 0) { - if (emxData.user && emxData.user.ext) { - emxData.user.ext.eids = eids; + if (cadentData.user && cadentData.user.ext) { + cadentData.user.ext.eids = eids; } else { - emxData.user = { + cadentData.user = { ext: {eids} }; } @@ -307,7 +312,7 @@ export const spec = { return { method: 'POST', url, - data: JSON.stringify(emxData), + data: JSON.stringify(cadentData), options: { withCredentials: true }, @@ -315,42 +320,42 @@ export const spec = { }; }, interpretResponse: function (serverResponse, bidRequest) { - let emxBidResponses = []; + let cadentBidResponses = []; let response = serverResponse.body || {}; if (response.seatbid && response.seatbid.length > 0 && response.seatbid[0].bid) { - response.seatbid.forEach(function (emxBid) { - emxBid = emxBid.bid[0]; + response.seatbid.forEach(function (cadentBid) { + cadentBid = cadentBid.bid[0]; let isVideo = false; - let adm = emxAdapter.parseResponse(emxBid.adm) || ''; + let adm = cadentAdapter.parseResponse(cadentBid.adm) || ''; let bidResponse = { - requestId: emxBid.id, - cpm: emxBid.price, - width: emxBid.w, - height: emxBid.h, - creativeId: emxBid.crid || emxBid.id, - dealId: emxBid.dealid || null, + requestId: cadentBid.id, + cpm: cadentBid.price, + width: cadentBid.w, + height: cadentBid.h, + creativeId: cadentBid.crid || cadentBid.id, + dealId: cadentBid.dealid || null, currency: 'USD', netRevenue: true, - ttl: emxBid.ttl, + ttl: cadentBid.ttl, ad: adm }; - if (emxBid.adm && emxBid.adm.indexOf(' -1) { + if (cadentBid.adm && cadentBid.adm.indexOf(' -1) { isVideo = true; - bidResponse = emxAdapter.formatVideoResponse(bidResponse, Object.assign({}, emxBid), bidRequest); + bidResponse = cadentAdapter.formatVideoResponse(bidResponse, Object.assign({}, cadentBid), bidRequest); } bidResponse.mediaType = (isVideo ? VIDEO : BANNER); // support for adomain in prebid 5.0 - if (emxBid.adomain && emxBid.adomain.length) { + if (cadentBid.adomain && cadentBid.adomain.length) { bidResponse.meta = { - advertiserDomains: emxBid.adomain + advertiserDomains: cadentBid.adomain }; } - emxBidResponses.push(bidResponse); + cadentBidResponses.push(bidResponse); }); } - return emxBidResponses; + return cadentBidResponses; }, getUserSyncs: function (syncOptions, responses, gdprConsent, uspConsent) { const syncs = []; diff --git a/modules/emx_digitalBidAdapter.md b/modules/cadentApertureMXBidAdapter.md similarity index 58% rename from modules/emx_digitalBidAdapter.md rename to modules/cadentApertureMXBidAdapter.md index 03ba554c5ad..11d63134587 100644 --- a/modules/emx_digitalBidAdapter.md +++ b/modules/cadentApertureMXBidAdapter.md @@ -1,18 +1,18 @@ # Overview ``` -Module Name: EMX Digital Adapter +Module Name: Cadent Aperture MX Adapter Module Type: Bidder Adapter Maintainer: git@emxdigital.com ``` # Description -The EMX Digital adapter provides publishers with access to the EMX Marketplace. The adapter is GDPR compliant. Please note that the adapter supports Banner and Video (Instream & Outstream) media types. +The Cadent Aperture MX adapter provides publishers with access to the Cadent Aperture MX SSP. The adapter is GDPR compliant. Please note that the adapter supports Banner and Video (Instream & Outstream) media types. -Note: The EMX Digital adapter requires approval and implementation guidelines from the EMX team, including existing publishers that work with EMX Digital. Please reach out to your account manager or prebid@emxdigital.com for more information. +Note: The Cadent Aperture MX adapter requires approval and implementation guidelines from the Cadent team, including existing publishers that work with Cadent. Please reach out to your account manager or prebid@emxdigital.com for more information. -The bidder code should be ```emx_digital``` +The bidder code should be ```cadent_aperture_mx``` The params used by the bidder are : ```tagid``` - string (mandatory) ```bidfloor``` - string (optional) @@ -29,7 +29,7 @@ var adUnits = [{ }, bids: [ { - bidder: 'emx_digital', + bidder: 'cadent_aperture_mx', params: { tagid: '25251', } @@ -49,7 +49,7 @@ var adUnits = [{ }, bids: [ { - bidder: 'emx_digital', + bidder: 'cadent_aperture_mx', params: { tagid: '25251', video: { diff --git a/modules/captifyRtdProvider.js b/modules/captifyRtdProvider.js deleted file mode 100644 index b97aa49a48e..00000000000 --- a/modules/captifyRtdProvider.js +++ /dev/null @@ -1,146 +0,0 @@ -/** - * This module adds Captify real time data provider module - * The {@link module:modules/realTimeData} module is required - * The module will fetch segments (page-centric) from Captify live-classification server - * @module modules/captifyRtdProvider - * @requires module:modules/realTimeData - */ -import { submodule } from '../src/hook.js'; -import { getRefererInfo } from '../src/refererDetection.js'; -import { ajax } from '../src/ajax.js'; -import { config } from '../src/config.js'; -import {deepAccess, isArray, isEmptyStr, isNumber, logError} from '../src/utils.js'; -import {getGlobal} from '../src/prebidGlobal.js'; - -const MODULE_NAME = 'realTimeData'; -const SUBMODULE_NAME = 'CaptifyRTDModule'; -const DEFAULT_LC_URL = 'https://live-classification.cpx.to/prebid-segments'; - -const STATUS = { - SUCCESS: 200, - ACCEPTED: 202, -}; - -/** - * Set `appnexusAuctionKeywords` that appnexus bidder will read and send in request to Xandr - * @param {Array} segments captify segments for Appnexus(Xandr) system, in form of [id1, id2, id3] - * where id1, id2, id3 - actual Xandr segment ids with keywords enabled - */ -export function setAppnexusSegments(segments) { - config.setConfig({ - appnexusAuctionKeywords: { - 'captify_segments': segments, - }, - }) -} - -/** - * Function returns only bidders that contained both, in moduleConfig and at least one adUnit. - * @param {Array} bidders Contains list of bidders, to set targeting for - * @param {Object} data Response of live-classification service - */ -export function addSegmentData(bidders, data) { - for (const bidder of bidders) { - if (bidder === 'appnexus') { setAppnexusSegments(data['xandr']) } - } -} - -/** - * Function returns only bidders that contained in both, moduleConfig and at least one adUnit. - * @param {Object} moduleConfig Config object passed to the module - * @param {Object} reqBidsConfigObj Config object for the bidders; each adapter has its own entry - */ -export function getMatchingBidders(moduleConfig, reqBidsConfigObj) { - const biddersFromConf = deepAccess(moduleConfig, 'params.bidders'); - - const adUnitBidders = reqBidsConfigObj.adUnits - .flatMap(({bids}) => bids.map(({bidder}) => bidder)) - .filter((e, i, a) => a.indexOf(e) === i); - - if (!isArray(adUnitBidders) || !adUnitBidders.length) { - logError(SUBMODULE_NAME, 'Missing parameter bidders in bidRequestConfig'); - return []; - } - - return biddersFromConf.filter(bidder => adUnitBidders.includes(bidder)); -} - -/** - * Main function that sets Captify targeting for various bidders - * @param {Object} moduleConfig Config object passed to the module - * @param {Function} onDone callback function that executed when everything is done - * @param {Object} reqBidsConfigObj Config object for the bidders; each adapter has its own entry - * @param {Object} gcv contains data related to user consent, if applies - */ -export function setCaptifyTargeting(reqBidsConfigObj, onDone, moduleConfig, gcv) { - const pbjsVer = getGlobal(); - const ref = getRefererInfo().referer; - const url = document.URL; - const pubId = moduleConfig.params.pubId; - const bidders = getMatchingBidders(moduleConfig, reqBidsConfigObj) - const requestBody = { - pubId, - ref, - url, - pbjsVer, - gcv - }; - let requestUrl = moduleConfig.params.url; - if (!requestUrl || isEmptyStr(requestUrl)) { - requestUrl = DEFAULT_LC_URL; - } - - if (!bidders.length) { - logError(SUBMODULE_NAME, 'There are no matched bidders to work with'); - return; - } - - ajax(requestUrl, { - success: function (response, req) { - if (req.status === STATUS.SUCCESS) { - try { - const data = JSON.parse(response); - if (data) { - addSegmentData(bidders, data); - } - } catch (e) { - logError(SUBMODULE_NAME, 'Unable to parse live-classification data' + e); - } - } - onDone(); - }, - error: function () { - onDone(); - logError(SUBMODULE_NAME, 'Unable to get live-classification data'); - } - }, - JSON.stringify(requestBody), - { - contentType: 'application/json', - method: 'POST', - }); -} - -export function init(moduleConfig, userConsent) { - // Validate bidders - const biddersFromConf = deepAccess(moduleConfig, 'params.bidders'); - if (!isArray(biddersFromConf) || !biddersFromConf.length) { - logError(SUBMODULE_NAME, 'Missing parameter bidders in moduleConfig'); - return false - } - const publisherId = deepAccess(moduleConfig, 'params.pubId'); - // Publisher Id - if (!isNumber(publisherId)) { - logError(SUBMODULE_NAME, 'Missing parameter pubId in moduleConfig'); - return false - } - return true -} - -export const captifySubmodule = { - name: SUBMODULE_NAME, - init: init, - setCaptifyTargeting -}; - -submodule(MODULE_NAME, captifySubmodule); diff --git a/modules/captifyRtdProvider.md b/modules/captifyRtdProvider.md deleted file mode 100644 index a1a8e9c273f..00000000000 --- a/modules/captifyRtdProvider.md +++ /dev/null @@ -1,68 +0,0 @@ -# Captify Real-Time Data Submodule - -# Overview - - Module Name: Captify Rtd Provider - Module Type: Rtd Provider - Layout: integrationExamples/gpt/captifyRtdProvider_example.html - Maintainer: prebid@captify.tech - -# Description - -Captify uses publisher first-party on-site search data to power machine learning algorithms to create a suite of -contextual based targeting solutions that activate in a cookieless environment. - -The RTD submodule allows bid requests to be classified by our live-classification service on the first ad call, -maximising value for publishers by increasing scale for advertisers. - -Segments will be attached to bid request objects sent to different SSPs in order to optimize targeting. - -Contact prebid@captify.tech for information. - -### Publisher Usage - -Compile the Captify RTD module into your Prebid build: - -`npm ci && gulp build --modules=rtdModule,appnexusBidAdapter,captifyRtdProvider` - -Add the Captify RTD provider to your Prebid config. - -```javascript -pbjs.setConfig({ - realTimeData: { - auctionDelay: 1000, - dataProviders: [ - { - name: "CaptifyRTDModule", - waitForIt: true, - params: { - pubId: 123456, - bidders: ['appnexus'], - } - } - ] - } -}); -``` - -### Parameter Description -This module is configured as part of the `realTimeData.dataProviders` object. - -| Name |Type | Description |Mandatory | Notes | -| :------------- | :------------ | :------------------------------------------------------------------ |:---------|:------------ | -| name | String | Real time data module name | yes | Always 'CaptifyRTDModule' | -| waitForIt | Boolean | Should be `true` if there's an `auctionDelay` defined (recommended) | no | Default `false` | -| params | Object | | | | -| params.pubId | Integer | Partner ID, required to get results and provided by Captify | yes | Use 123456 for tests and speak to your Captify account manager to receive your pubId | -| params.bidders | Array | List of bidders for which you would like data to be set | yes | Currently only 'appnexus' supported | -| params.url | String | Captify live-classification service url | no | Defaults to `https://live-classification.cpx.to/prebid-segments` - -### Testing - -To view an example of available segments returned by Captify: - -`gulp serve --modules=rtdModule,captifyRtdProvider,appnexusBidAdapter` - -and then point your browser at: - -`http://localhost:9999/integrationExamples/gpt/captifyRtdProvider_example.html?pbjs_debug=true` diff --git a/modules/carodaBidAdapter.js b/modules/carodaBidAdapter.js index 7267452dd4c..cb7b5fbe7c5 100644 --- a/modules/carodaBidAdapter.js +++ b/modules/carodaBidAdapter.js @@ -48,6 +48,7 @@ export const spec = { const eids = getFirstWithKey(validBidRequests, 'userIdAsEids'); const schain = getFirstWithKey(validBidRequests, 'schain'); const request = { + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 auctionId: bidderRequest.auctionId, currency, hb_version: '$prebid.version$', diff --git a/modules/ccxBidAdapter.js b/modules/ccxBidAdapter.js index 28f3fe3a166..b1fcb29e3d0 100644 --- a/modules/ccxBidAdapter.js +++ b/modules/ccxBidAdapter.js @@ -178,7 +178,7 @@ export const spec = { requestBody.imp = [] requestBody.site = _getSiteObj(bidderRequest) requestBody.device = _getDeviceObj() - requestBody.id = bidderRequest.bids[0].auctionId + requestBody.id = bidderRequest.bidderRequestId; requestBody.ext = {'ce': (storage.cookiesAreEnabled() ? 1 : 0)} // Attaching GDPR Consent Params diff --git a/modules/cleanmedianetBidAdapter.js b/modules/cleanmedianetBidAdapter.js index 46253d7af69..601a237baa8 100644 --- a/modules/cleanmedianetBidAdapter.js +++ b/modules/cleanmedianetBidAdapter.js @@ -80,11 +80,11 @@ export const spec = { buildRequests: function (validBidRequests, bidderRequest) { return validBidRequests.map(bidRequest => { - const {adUnitCode, auctionId, mediaTypes, params, sizes, transactionId} = bidRequest; + const {adUnitCode, bidId, mediaTypes, params, sizes} = bidRequest; const baseEndpoint = (params['rtbEndpoint'] || ENDPOINTS['cleanmedianet']).replace(/^http:/, 'https:'); const rtbEndpoint = `${baseEndpoint}/r/${params.supplyPartnerId}/bidr?rformat=open_rtb&reqformat=rtb_json&bidder=prebid` + (params.query ? '&' + params.query : ''); const rtbBidRequest = { - id: auctionId, + id: bidId, site: { domain: bidderRequest.refererInfo.domain, page: bidderRequest.refererInfo.page, @@ -118,7 +118,7 @@ export const spec = { } const imp = { - id: transactionId, + id: bidId, instl: deepAccess(bidderRequest.ortb2Imp, 'instl') === 1 || params.instl === 1 ? 1 : 0, tagid: adUnitCode, bidfloor: helper.getBidFloor(bidRequest) || 0, diff --git a/modules/codefuelBidAdapter.js b/modules/codefuelBidAdapter.js index bde168a79e3..2548b20189b 100644 --- a/modules/codefuelBidAdapter.js +++ b/modules/codefuelBidAdapter.js @@ -58,7 +58,7 @@ export const spec = { }); const request = { - id: bidderRequest.auctionId, + id: bidderRequest.bidderRequestId, site: { page, domain, publisher }, device: { ua, devicetype }, source: { fd: 1 }, diff --git a/modules/colossussspBidAdapter.js b/modules/colossussspBidAdapter.js index 082fb0ac4db..00d90f62a2c 100644 --- a/modules/colossussspBidAdapter.js +++ b/modules/colossussspBidAdapter.js @@ -125,7 +125,7 @@ export const spec = { placementId: bid.params.placement_id, groupId: bid.params.group_id, bidId: bid.bidId, - tid: bid.transactionId, + tid: bid.ortb2Imp?.ext?.tid, eids: [], floor: {} }; diff --git a/modules/concertBidAdapter.js b/modules/concertBidAdapter.js index a25d9086446..bf4079322ff 100644 --- a/modules/concertBidAdapter.js +++ b/modules/concertBidAdapter.js @@ -66,7 +66,7 @@ export const spec = { let slot = { name: bidRequest.adUnitCode, bidId: bidRequest.bidId, - transactionId: bidRequest.transactionId, + transactionId: bidRequest.ortb2Imp?.ext?.tid, sizes: bidRequest.params.sizes || bidRequest.sizes, partnerId: bidRequest.params.partnerId, slotType: bidRequest.params.slotType, diff --git a/modules/connectadBidAdapter.js b/modules/connectadBidAdapter.js index d53e3b28ab5..d5665b318be 100644 --- a/modules/connectadBidAdapter.js +++ b/modules/connectadBidAdapter.js @@ -77,6 +77,7 @@ export const spec = { validBidRequests.map(bid => { const placement = Object.assign({ + // TODO: fix transactionId leak: https://github.com/prebid/Prebid.js/issues/9781 id: bid.transactionId, divName: bid.bidId, pisze: bid.mediaTypes.banner.sizes[0] || bid.sizes[0], diff --git a/modules/conversantAnalyticsAdapter.js b/modules/conversantAnalyticsAdapter.js index ce4597eecfe..0c58402ca87 100644 --- a/modules/conversantAnalyticsAdapter.js +++ b/modules/conversantAnalyticsAdapter.js @@ -6,6 +6,8 @@ import adapterManager from '../src/adapterManager.js'; import {logInfo, logWarn, logError, logMessage, deepAccess, isInteger} from '../src/utils.js'; import {getRefererInfo} from '../src/refererDetection.js'; +// Maintainer: mediapsr@epsilon.com + const { EVENTS: { AUCTION_END, AD_RENDER_FAILED, BID_TIMEOUT, BID_WON, BIDDER_ERROR } } = CONSTANTS; diff --git a/modules/conversantAnalyticsAdapter.md b/modules/conversantAnalyticsAdapter.md deleted file mode 100644 index 2f026cbcbb9..00000000000 --- a/modules/conversantAnalyticsAdapter.md +++ /dev/null @@ -1,46 +0,0 @@ -# Overview -- Module Name: Epsilon Analytics Adapter -- Module Type: Analytics Adapter -- Maintainer: mediapsr@epsilon.com - -## Description - -Analytics adapter for Epsilon (formerly Conversant) is used to track performance of Prebid auctions. See the usage below for how to -configure the adapter for your webpage. To enable analytics and gain access to the data publishers will need - to contact their Epsilon representative (publishersupport@epsilon.com). - -## Setup - -Before any analytics are recorded for your website you will need to have an Epsilon representative turn -on Prebid analytics for your website. - -The simplest configuration to add Epsilon Prebid analytics to your page is as follows: - -``` - pbjs.que.push(function() { - pbjs.enableAnalytics({ - provider: 'conversant', - options: { - site_id: - } - }) - }); -``` - -Additionally, the following options are supported: - -- **cnvr_sampling**: Sample rate for analytics data. Value should be between 0 and 1 (inclusive), 0 == never sample, -1 == always sample, 0.5 == send analytics 50% of the time. - -### Complete Example -``` - pbjs.que.push(function() { - pbjs.enableAnalytics({ - provider: 'conversant', - options: { - site_id: 1234, - cnvr_sampling: 0.9 - } - }) - }); -``` diff --git a/modules/conversantBidAdapter.js b/modules/conversantBidAdapter.js index b5a1424dcba..fd436e51461 100644 --- a/modules/conversantBidAdapter.js +++ b/modules/conversantBidAdapter.js @@ -1,8 +1,27 @@ -import { logWarn, isStr, deepAccess, isArray, getBidIdParameter, deepSetValue, isEmpty, _each, convertTypes, parseUrl, mergeDeep, buildUrl, _map, logError, isFn, isPlainObject } from '../src/utils.js'; +import { + logWarn, + isStr, + deepAccess, + isArray, + getBidIdParameter, + deepSetValue, + isEmpty, + _each, + convertTypes, + parseUrl, + mergeDeep, + buildUrl, + _map, + logError, + isFn, + isPlainObject, +} from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {getStorageManager} from '../src/storageManager.js'; +// Maintainer: mediapsr@epsilon.com + const GVLID = 24; const BIDDER_CODE = 'conversant'; @@ -56,7 +75,6 @@ export const spec = { buildRequests: function(validBidRequests, bidderRequest) { const page = (bidderRequest && bidderRequest.refererInfo) ? bidderRequest.refererInfo.page : ''; let siteId = ''; - let requestId = ''; let pubcid = null; let pubcidName = '_pubcid'; let bidurl = URL; @@ -67,8 +85,6 @@ export const spec = { siteId = getBidIdParameter('site_id', bid.params) || siteId; pubcidName = getBidIdParameter('pubcid_name', bid.params) || pubcidName; - requestId = bid.auctionId; - const imp = { id: bid.bidId, secure: 1, @@ -122,10 +138,10 @@ export const spec = { }); const payload = { - id: requestId, + id: bidderRequest.bidderRequestId, imp: conversantImps, source: { - tid: requestId + tid: bidderRequest.ortb2?.source?.tid, }, site: { id: siteId, diff --git a/modules/conversantBidAdapter.md b/modules/conversantBidAdapter.md deleted file mode 100644 index baf8b756aca..00000000000 --- a/modules/conversantBidAdapter.md +++ /dev/null @@ -1,46 +0,0 @@ -# Overview - -- Module Name: Epsilon Bidder Adapter -- Module Type: Bidder Adapter -- Maintainer: mediapsr@epsilon.com - -# Description - -Module that connects to Epsilon's (formerly Conversant) demand sources. Supports banners and videos. - -# Test Parameters -``` -var adUnits = [ - { - code: 'banner-test-div', - mediaTypes: { - banner: { - sizes: [[300, 250],[300,600]] - } - }, - bids: [{ - bidder: "conversant", - params: { - site_id: '108060' - } - }] - },{ - code: 'video-test-div', - mediaTypes: { - video: { - context: 'instream', - playerSize: [640, 480], - api: [2], - protocols: [1, 2], - mimes: ['video/mp4'] - } - }, - bids: [{ - bidder: "conversant", - params: { - site_id: '108060', - white_label_url: 'https://web.hb.ad.cpe.dotomi.com/s2s/header/24' - } - }] - }]; -``` diff --git a/modules/craftBidAdapter.js b/modules/craftBidAdapter.js index 8ffdabcb597..8f7821173c1 100644 --- a/modules/craftBidAdapter.js +++ b/modules/craftBidAdapter.js @@ -1,12 +1,4 @@ -import { - convertCamelToUnderscore, - convertTypes, - getBidRequest, - isArray, - isEmpty, - logError, - transformBidderParamKeywords -} from '../src/utils.js'; +import {convertCamelToUnderscore, convertTypes, getBidRequest, logError} from '../src/utils.js'; import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {auctionManager} from '../src/auctionManager.js'; @@ -14,7 +6,8 @@ import {find, includes} from '../src/polyfill.js'; import {getStorageManager} from '../src/storageManager.js'; import {ajax} from '../src/ajax.js'; import {hasPurpose1Consent} from '../src/utils/gpdr.js'; -import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; +import {getANKeywordParam, transformBidderParamKeywords} from '../libraries/appnexusKeywords/anKeywords.js'; const BIDDER_CODE = 'craft'; const URL_BASE = 'https://gacraft.jp/prebid-v3'; @@ -114,9 +107,6 @@ export const spec = { 'keywords': transformBidderParamKeywords, }, params); if (isOpenRtb) { - if (isPopulatedArray(params.keywords)) { - params.keywords.forEach(deleteValues); - } Object.keys(params).forEach(paramKey => { let convertedKey = convertCamelToUnderscore(paramKey); if (convertedKey !== paramKey) { @@ -136,16 +126,6 @@ export const spec = { } }; -function isPopulatedArray(arr) { - return !!(isArray(arr) && arr.length > 0); -} - -function deleteValues(keyPairObj) { - if (isPopulatedArray(keyPairObj.value) && keyPairObj.value[0] === '') { - delete keyPairObj.value; - } -} - function formatRequest(payload, bidderRequest) { let options = {}; if (!hasPurpose1Consent(bidderRequest?.gdprConsent)) { @@ -200,13 +180,11 @@ function bidToTag(bid) { tag.primary_size = tag.sizes[0]; tag.ad_types = []; tag.uuid = bid.bidId; - if (!isEmpty(bid.params.keywords)) { - let keywords = transformBidderParamKeywords(bid.params.keywords); - if (keywords.length > 0) { - keywords.forEach(deleteValues); - } + const keywords = getANKeywordParam(bid.ortb2, bid.params.keywords); + if (keywords.length) { tag.keywords = keywords; } + // TODO: why does this need to iterate through every ad unit? let adUnit = find(auctionManager.getAdUnits(), au => bid.transactionId === au.transactionId); if (adUnit && adUnit.mediaTypes && adUnit.mediaTypes.banner) { tag.ad_types.push(BANNER); diff --git a/modules/criteoBidAdapter.js b/modules/criteoBidAdapter.js index 6892c9f692f..993346df849 100644 --- a/modules/criteoBidAdapter.js +++ b/modules/criteoBidAdapter.js @@ -1,4 +1,4 @@ -import { deepAccess, isArray, logError, logInfo, logWarn, parseUrl } from '../src/utils.js'; +import { deepAccess, generateUUID, isArray, logError, logInfo, logWarn, parseUrl } from '../src/utils.js'; import { loadExternalScript } from '../src/adloader.js'; import { registerBidder } from '../src/adapters/bidderFactory.js'; import { config } from '../src/config.js'; @@ -242,7 +242,7 @@ export const spec = { bid.meta = Object.assign({}, bid.meta, { advertiserDomains: [slot.adomain].flat() }); } if (slot.ext?.meta?.networkName) { - bid.meta = Object.assign({}, bid.meta, {networkName: slot.ext.meta.networkName}) + bid.meta = Object.assign({}, bid.meta, { networkName: slot.ext.meta.networkName }) } if (slot.native) { if (bidRequest.params.nativeCallback) { @@ -427,6 +427,7 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { let schain; let userIdAsEids; const request = { + id: generateUUID(), publisher: { url: context.url, ext: bidderRequest.publisherExt, @@ -444,8 +445,7 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { schain = bidRequest.schain || schain; const slot = { impid: bidRequest.adUnitCode, - transactionid: bidRequest.transactionId, - auctionId: bidRequest.auctionId, + transactionid: bidRequest.ortb2Imp?.ext?.tid }; if (bidRequest.params.zoneId) { slot.zoneid = bidRequest.params.zoneId; @@ -515,11 +515,14 @@ function buildCdbRequest(context, bidRequests, bidderRequest) { if (networkId) { request.publisher.networkid = networkId; } + + request.source = { + tid: bidderRequest.ortb2?.source?.tid + }; + if (schain) { - request.source = { - ext: { - schain: schain - } + request.source.ext = { + schain: schain }; }; request.user = bidderRequest.ortb2?.user || {}; @@ -760,7 +763,7 @@ function createOutstreamVideoRenderer(slot) { window.CriteoOutStream[slot.ext.videoPlayerType].play(payload, outstreamConfig) }; - const renderer = Renderer.install({url: PUBLISHER_TAG_OUTSTREAM_SRC, config: config}); + const renderer = Renderer.install({ url: PUBLISHER_TAG_OUTSTREAM_SRC, config: config }); renderer.setRender(render); return renderer; } diff --git a/modules/currency.js b/modules/currency.js index 9272a507d05..3da0cfe73e8 100644 --- a/modules/currency.js +++ b/modules/currency.js @@ -238,9 +238,9 @@ function wrapFunction(fn, context, params) { bid.currency = adServerCurrency; } } catch (e) { - logWarn('Returning NO_BID, getCurrencyConversion threw error: ', e); - // TODO: in v8, this should not continue with a "NO_BID" - params[1] = params[2](CONSTANTS.REJECTION_REASON.CANNOT_CONVERT_CURRENCY); + logWarn('getCurrencyConversion threw error: ', e); + params[2](CONSTANTS.REJECTION_REASON.CANNOT_CONVERT_CURRENCY); + return; } } return fn.apply(context, params); diff --git a/modules/dailyhuntBidAdapter.js b/modules/dailyhuntBidAdapter.js index 5ae8ee3ea21..f96e07b71bf 100644 --- a/modules/dailyhuntBidAdapter.js +++ b/modules/dailyhuntBidAdapter.js @@ -4,7 +4,7 @@ import {_map, deepAccess, isEmpty} from '../src/utils.js'; import {ajax} from '../src/ajax.js'; import {find} from '../src/polyfill.js'; import {INSTREAM, OUTSTREAM} from '../src/video.js'; -import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; const BIDDER_CODE = 'dailyhunt'; const BIDDER_ALIAS = 'dh'; @@ -99,7 +99,7 @@ const createOrtbRequest = (validBidRequests, bidderRequest) => { let user = createOrtbUserObj(validBidRequests) let site = createOrtbSiteObj(validBidRequests, bidderRequest.refererInfo.page) return { - id: bidderRequest.auctionId, + id: bidderRequest.bidderRequestId, imp: [], site, device, diff --git a/modules/datablocksBidAdapter.js b/modules/datablocksBidAdapter.js index 4e21e08ba57..11d3ebb1589 100644 --- a/modules/datablocksBidAdapter.js +++ b/modules/datablocksBidAdapter.js @@ -1,10 +1,11 @@ -import { getWindowTop, isGptPubadsDefined, deepAccess, getAdUnitSizes, isEmpty } from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { config } from '../src/config.js'; -import { BANNER, NATIVE } from '../src/mediaTypes.js'; -import { getStorageManager } from '../src/storageManager.js'; -import { ajax } from '../src/ajax.js'; -import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import {deepAccess, getAdUnitSizes, getWindowTop, isEmpty, isGptPubadsDefined} from '../src/utils.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {config} from '../src/config.js'; +import {BANNER, NATIVE} from '../src/mediaTypes.js'; +import {getStorageManager} from '../src/storageManager.js'; +import {ajax} from '../src/ajax.js'; +import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; + export const storage = getStorageManager({bidderCode: 'datablocks'}); const NATIVE_ID_MAP = {}; @@ -229,6 +230,7 @@ export const spec = { let scope = this; if (isGptPubadsDefined()) { if (typeof window['googletag'].pubads().addEventListener == 'function') { + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 window['googletag'].pubads().addEventListener('impressionViewable', function(event) { scope.queue_metric({type: 'slot_view', source_id: scope.db_obj.source_id, auction_id: bid.auctionId, div_id: event.slot.getSlotElementId(), slot_id: event.slot.getSlotId().getAdUnitPath()}); }); @@ -400,7 +402,7 @@ export const spec = { method: 'POST', url: `https://${host}/openrtb/?sid=${sourceId}`, data: { - id: bidderRequest.auctionId, + id: bidderRequest.bidderRequestId, imp: imps, site: site, device: device diff --git a/modules/datawrkzBidAdapter.js b/modules/datawrkzBidAdapter.js index 193a1723403..2cf28c36330 100644 --- a/modules/datawrkzBidAdapter.js +++ b/modules/datawrkzBidAdapter.js @@ -414,8 +414,6 @@ function buildBannerResponse(bidRequest, bidResponse) { } let bidSizes = (deepAccess(bidRequest, 'mediaTypes.banner.sizes')) ? deepAccess(bidRequest, 'mediaTypes.banner.sizes') : bidRequest.sizes; bidResponse.requestId = bidRequest.bidId; - bidResponse.auctionId = bidRequest.auctionId; - bidResponse.transactionId = bidRequest.transactionId; bidResponse.placementCode = placementCode; bidResponse.cpm = responseCPM; bidResponse.size = bidSizes; @@ -456,8 +454,6 @@ function buildNativeResponse(bidRequest, response) { return; } bidResponse.requestId = bidRequest.bidId; - bidResponse.auctionId = bidRequest.auctionId; - bidResponse.transactionId = bidRequest.transactionId; bidResponse.placementCode = placementCode; bidResponse.cpm = responseCPM; @@ -509,8 +505,6 @@ function buildVideoResponse(bidRequest, response) { let context = bidRequest.mediaTypes.video.context; bidResponse.requestId = bidRequest.bidId; - bidResponse.auctionId = bidRequest.auctionId; - bidResponse.transactionId = bidRequest.transactionId; bidResponse.placementCode = placementCode; bidResponse.cpm = responseCPM; diff --git a/modules/deltaprojectsBidAdapter.js b/modules/deltaprojectsBidAdapter.js index e40ec58461c..c66e381b8f1 100644 --- a/modules/deltaprojectsBidAdapter.js +++ b/modules/deltaprojectsBidAdapter.js @@ -1,6 +1,15 @@ import {registerBidder} from '../src/adapters/bidderFactory.js'; import {BANNER} from '../src/mediaTypes.js'; -import {_each, _map, createTrackPixelHtml, deepAccess, isFn, isNumber, logError, logWarn} from '../src/utils.js'; +import { + _each, + _map, + createTrackPixelHtml, + deepAccess, + isFn, + isNumber, + logError, + logWarn +} from '../src/utils.js'; import {config} from '../src/config.js'; export const BIDDER_CODE = 'deltaprojects'; @@ -27,7 +36,7 @@ function isBidRequestValid(bid) { function buildRequests(validBidRequests, bidderRequest) { /** == shared ==**/ // -- build id - const id = bidderRequest.auctionId; + const id = bidderRequest.bidderRequestId; // -- build site const publisherId = setOnAny(validBidRequests, 'params.publisherId'); @@ -90,7 +99,7 @@ function buildOpenRTBRequest(validBidRequest, id, site, device, user, tmax, regs // build source const source = { - tid: validBidRequest.transactionId, + tid: validBidRequest.auctionId, fd: 1, } diff --git a/modules/dianomiBidAdapter.js b/modules/dianomiBidAdapter.js index f8f47df1239..d4b2a4a5da5 100644 --- a/modules/dianomiBidAdapter.js +++ b/modules/dianomiBidAdapter.js @@ -112,7 +112,7 @@ export const spec = { setOnAny(validBidRequests, 'params.pt') || setOnAny(validBidRequests, 'params.priceType') || 'net'; - const tid = bidderRequest.auctionId; + const tid = bidderRequest.ortb2?.source?.tid; const currency = getConfig('currency.adServerCurrency'); const cur = currency && [currency]; const eids = setOnAny(validBidRequests, 'userIdAsEids'); diff --git a/modules/discoveryBidAdapter.js b/modules/discoveryBidAdapter.js index a0f864d529f..675ede273a6 100644 --- a/modules/discoveryBidAdapter.js +++ b/modules/discoveryBidAdapter.js @@ -301,6 +301,7 @@ function getParam(validBidRequests, bidderRequest) { if (items && items.length) { let c = { + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 id: 'pp_hbjs_' + auctionId, test: +isTest, at: 1, diff --git a/modules/displayioBidAdapter.js b/modules/displayioBidAdapter.js index d46cc8ee309..3d34f2c8b26 100644 --- a/modules/displayioBidAdapter.js +++ b/modules/displayioBidAdapter.js @@ -3,6 +3,7 @@ import {BANNER, VIDEO} from '../src/mediaTypes.js'; import {Renderer} from '../src/Renderer.js'; import {getWindowFromDocument, logWarn} from '../src/utils.js'; import {getStorageManager} from '../src/storageManager.js'; +import {getAllOrtbKeywords} from '../libraries/keywords/keywords.js'; const ADAPTER_VERSION = '1.1.0'; const BIDDER_CODE = 'displayio'; @@ -105,7 +106,7 @@ function getPayload (bid, bidderRequest) { renderURL, data: { pagecat: pageCategory ? pageCategory.split(',').map(k => k.trim()) : [], - keywords: keywords ? keywords.split(',').map(k => k.trim()) : [], + keywords: getAllOrtbKeywords(bidderRequest.ortb2, keywords), lang_content: document.documentElement.lang, lang: window.navigator.language, domain: refererInfo.domain, diff --git a/modules/dspxBidAdapter.js b/modules/dspxBidAdapter.js index 74a93ce086e..b8e812f581a 100644 --- a/modules/dspxBidAdapter.js +++ b/modules/dspxBidAdapter.js @@ -29,6 +29,7 @@ export const spec = { const referrer = bidderRequest.refererInfo.page; const bidId = bidRequest.bidId; const pbcode = bidRequest.adUnitCode || false; // div id + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 const auctionId = bidRequest.auctionId || false; const isDev = params.devMode || false; diff --git a/modules/ebdrBidAdapter.js b/modules/ebdrBidAdapter.js index a7b1991df9b..a03a1ec12ca 100644 --- a/modules/ebdrBidAdapter.js +++ b/modules/ebdrBidAdapter.js @@ -36,8 +36,9 @@ export const spec = { w: whArr[0], h: whArr[1] }; - ebdrParams['latitude'] = getBidIdParameter('latitude', bid.params); - ebdrParams['longitude'] = getBidIdParameter('longitude', bid.params); + // TODO: fix lat and long to only come from request + ebdrParams['latitude'] = '0'; + ebdrParams['longitude'] = '0'; ebdrParams['ifa'] = (getBidIdParameter('IDFA', bid.params).length > getBidIdParameter('ADID', bid.params).length) ? getBidIdParameter('IDFA', bid.params) : getBidIdParameter('ADID', bid.params); }); let ebdrBidReq = { diff --git a/modules/etargetBidAdapter.js b/modules/etargetBidAdapter.js index b290a62420c..cced180e061 100644 --- a/modules/etargetBidAdapter.js +++ b/modules/etargetBidAdapter.js @@ -35,7 +35,7 @@ export const spec = { lastCountry = countryMap[bid.params.country]; } reqParams = bid.params; - reqParams.transactionId = bid.transactionId; + reqParams.transactionId = bid.ortb2Imp?.ext?.tid; request.push(formRequestUrl(reqParams)); floors[i] = getBidFloor(bid); } @@ -137,7 +137,6 @@ export const spec = { vastXml: data.vast_content, vastUrl: data.vast_link, mediaType: data.response, - transactionId: bid.transactionId }; if (bidRequest.gdpr) { bidObject.gdpr = bidRequest.gdpr.gdpr; diff --git a/modules/feedadBidAdapter.js b/modules/feedadBidAdapter.js index 34e14cd674a..7b41f0fcc03 100644 --- a/modules/feedadBidAdapter.js +++ b/modules/feedadBidAdapter.js @@ -234,7 +234,7 @@ function buildRequests(validBidRequests, bidderRequest) { }); data.bids.forEach(bid => BID_METADATA[bid.bidId] = { referer: data.refererInfo.page, - transactionId: bid.transactionId + transactionId: bid.ortb2Imp?.ext?.tid, }); if (bidderRequest.gdprConsent) { data.consentIabTcf = bidderRequest.gdprConsent.consentString; diff --git a/modules/finativeBidAdapter.js b/modules/finativeBidAdapter.js index b236ddb3d95..87580a209bb 100644 --- a/modules/finativeBidAdapter.js +++ b/modules/finativeBidAdapter.js @@ -1,11 +1,11 @@ // jshint esversion: 6, es3: false, node: true 'use strict'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { NATIVE } from '../src/mediaTypes.js'; -import { _map, deepSetValue, isEmpty, deepAccess } from '../src/utils.js'; -import { config } from '../src/config.js'; -import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {NATIVE} from '../src/mediaTypes.js'; +import {_map, deepAccess, deepSetValue, isEmpty} from '../src/utils.js'; +import {config} from '../src/config.js'; +import {convertOrtbRequestToProprietaryNative} from '../src/native.js'; const BIDDER_CODE = 'finative'; const DEFAULT_CUR = 'EUR'; @@ -63,7 +63,7 @@ export const spec = { // convert Native ORTB definition to old-style prebid native definition validBidRequests = convertOrtbRequestToProprietaryNative(validBidRequests); const pt = setOnAny(validBidRequests, 'params.pt') || setOnAny(validBidRequests, 'params.priceType') || 'net'; - const tid = bidderRequest.auctionId; + const tid = bidderRequest.ortb2?.source?.tid; const cur = [config.getConfig('currency.adServerCurrency') || DEFAULT_CUR]; let url = bidderRequest.refererInfo.referer; @@ -104,6 +104,7 @@ export const spec = { return { id: String(id + 1), tagid: bid.params.adUnitId, + // TODO: `tid` is not under `imp` in ORTB, is this intentional? tid: tid, pt: pt, native: { @@ -115,7 +116,7 @@ export const spec = { }); const request = { - id: bidderRequest.auctionId, + id: bidderRequest.bidderRequestId, site: { page: url }, @@ -174,7 +175,6 @@ export const spec = { netRevenue: (!bid.netRevenue || bid.netRevenue === 'net'), currency: cur, mediaType: NATIVE, - bidderCode: BIDDER_CODE, native: parseNative(bidResponse), meta: { advertiserDomains: bidResponse.adomain && bidResponse.adomain.length > 0 ? bidResponse.adomain : [] diff --git a/modules/fluctBidAdapter.js b/modules/fluctBidAdapter.js index 97b9847eae4..edb750a6b90 100644 --- a/modules/fluctBidAdapter.js +++ b/modules/fluctBidAdapter.js @@ -48,7 +48,7 @@ export const spec = { data.page = page; data.adUnitCode = request.adUnitCode; data.bidId = request.bidId; - data.transactionId = request.transactionId; + data.transactionId = request.ortb2Imp?.ext?.tid; data.user = { eids: (request.userIdAsEids || []).filter((eid) => SUPPORTED_USER_ID_SOURCES.indexOf(eid.source) !== -1) }; @@ -125,7 +125,6 @@ export const spec = { `(function() { var img = new Image(); img.src = "${beaconUrl}"})()` + ``; let data = { - bidderCode: BIDDER_CODE, requestId: res.id, currency: res.cur, cpm: parseFloat(bid.price) || 0, diff --git a/modules/gamoshiBidAdapter.js b/modules/gamoshiBidAdapter.js index ae320db1251..1c279cdb9b8 100644 --- a/modules/gamoshiBidAdapter.js +++ b/modules/gamoshiBidAdapter.js @@ -80,11 +80,11 @@ export const spec = { buildRequests: function (validBidRequests, bidderRequest) { return validBidRequests.map(bidRequest => { - const {adUnitCode, auctionId, mediaTypes, params, sizes, transactionId} = bidRequest; + const {adUnitCode, mediaTypes, params, sizes, bidId} = bidRequest; const baseEndpoint = params['rtbEndpoint'] || ENDPOINTS['gamoshi']; const rtbEndpoint = `${baseEndpoint}/r/${params.supplyPartnerId}/bidr?rformat=open_rtb&reqformat=rtb_json&bidder=prebid` + (params.query ? '&' + params.query : ''); const rtbBidRequest = { - id: auctionId, + id: bidderRequest.bidderRequestId, site: { domain: bidderRequest.refererInfo.domain, page: bidderRequest.refererInfo.page, @@ -118,7 +118,7 @@ export const spec = { } const imp = { - id: transactionId, + id: bidId, instl: deepAccess(bidderRequest.ortb2Imp, 'instl') === 1 || params.instl === 1 ? 1 : 0, tagid: adUnitCode, bidfloor: helper.getBidFloor(bidRequest) || 0, diff --git a/modules/gdprEnforcement.js b/modules/gdprEnforcement.js index a834c0da2d5..4bac4b0cf74 100644 --- a/modules/gdprEnforcement.js +++ b/modules/gdprEnforcement.js @@ -6,7 +6,6 @@ import {deepAccess, logError, logWarn} from '../src/utils.js'; import {config} from '../src/config.js'; import adapterManager, {gdprDataHandler} from '../src/adapterManager.js'; import {find} from '../src/polyfill.js'; -import {getHook} from '../src/hook.js'; import * as events from '../src/events.js'; import CONSTANTS from '../src/constants.json'; import {GDPR_GVLIDS, VENDORLESS_GVLID} from '../src/consentHandler.js'; @@ -219,15 +218,6 @@ export const accessDeviceRule = ((rule) => { export const syncUserRule = gdprRule(1, () => purpose1Rule, storageBlocked); export const enrichEidsRule = gdprRule(1, () => purpose1Rule, storageBlocked); -export function userIdHook(fn, submodules, consentData) { - // TODO: remove this in v8 (https://github.com/prebid/Prebid.js/issues/9766) - if (shouldEnforce(consentData, 1, 'User ID')) { - fn.call(this, submodules, {...consentData, hasValidated: true}); - } else { - fn.call(this, submodules, consentData); - } -} - export const fetchBidsRule = ((rule) => { return function (params) { if (params[ACTIVITY_PARAM_COMPONENT_TYPE] !== MODULE_TYPE_BIDDER) { @@ -307,8 +297,6 @@ export function setEnforcementConfig(config) { RULE_HANDLES.push(registerActivityControl(ACTIVITY_ACCESS_DEVICE, RULE_NAME, accessDeviceRule)); RULE_HANDLES.push(registerActivityControl(ACTIVITY_SYNC_USER, RULE_NAME, syncUserRule)); RULE_HANDLES.push(registerActivityControl(ACTIVITY_ENRICH_EIDS, RULE_NAME, enrichEidsRule)); - // TODO: remove this hook in v8 (https://github.com/prebid/Prebid.js/issues/9766) - getHook('validateGdprEnforcement').before(userIdHook, 47); } if (purpose2Rule) { RULE_HANDLES.push(registerActivityControl(ACTIVITY_FETCH_BIDS, RULE_NAME, fetchBidsRule)); @@ -321,9 +309,6 @@ export function setEnforcementConfig(config) { export function uninstall() { while (RULE_HANDLES.length) RULE_HANDLES.pop()(); - [ - getHook('validateGdprEnforcement').getHooks({hook: userIdHook}), - ].forEach(hook => hook.remove()); hooksAdded = false; } diff --git a/modules/genericAnalyticsAdapter.js b/modules/genericAnalyticsAdapter.js index 4909745e72b..b52cb7e5464 100644 --- a/modules/genericAnalyticsAdapter.js +++ b/modules/genericAnalyticsAdapter.js @@ -115,11 +115,6 @@ export function GenericAnalytics() { } }, track(event) { - if (event.eventType === CONSTANTS.EVENTS.AUCTION_INIT && event.args.hasOwnProperty('config')) { - // clean up auctionInit event - // TODO: remove this special case in v8 - delete event.args.config; - } const datum = translate(event); if (datum != null) { batch.push(datum); diff --git a/modules/glimpseBidAdapter.js b/modules/glimpseBidAdapter.js deleted file mode 100644 index 53dc0bd3e1a..00000000000 --- a/modules/glimpseBidAdapter.js +++ /dev/null @@ -1,198 +0,0 @@ -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER } from '../src/mediaTypes.js'; -import { getStorageManager } from '../src/storageManager.js'; -import { - isArray, - isEmpty, - isEmptyStr, - isStr, - isPlainObject, -} from '../src/utils.js'; - -const GVLID = 1012; -const BIDDER_CODE = 'glimpse'; -const storageManager = getStorageManager({bidderCode: BIDDER_CODE}); -const ENDPOINT = 'https://market.glimpsevault.io/public/v1/prebid'; -const LOCAL_STORAGE_KEY = { - vault: { - jwt: 'gp_vault_jwt', - }, -}; - -export const spec = { - gvlid: GVLID, - code: BIDDER_CODE, - supportedMediaTypes: [BANNER], - - /** - * Determines if the bid request is valid - * @param bid {BidRequest} The bid to validate - * @return {boolean} - */ - isBidRequestValid: (bid) => { - const pid = bid?.params?.pid; - return isStr(pid) && !isEmptyStr(pid); - }, - - /** - * Builds the http request - * @param validBidRequests {BidRequest[]} - * @param bidderRequest {BidderRequest} - * @returns {ServerRequest} - */ - buildRequests: (validBidRequests, bidderRequest) => { - const url = buildQuery(bidderRequest); - const auth = getVaultJwt(); - const referer = getReferer(bidderRequest); - const imp = validBidRequests.map(processBidRequest); - const fpd = getFirstPartyData(bidderRequest.ortb2); - - const data = { - auth, - data: { - referer, - imp, - fpd, - }, - }; - - return { - method: 'POST', - url, - data: JSON.stringify(data), - options: {}, - }; - }, - - /** - * Parse http response - * @param response {ServerResponse} - * @returns {Bid[]} - */ - interpretResponse: (response) => { - if (isValidResponse(response)) { - const { auth, data } = response.body; - setVaultJwt(auth); - const bids = data.bids.map(processBidResponse); - return bids; - } - return []; - }, -}; - -function setVaultJwt(auth) { - storageManager.setDataInLocalStorage(LOCAL_STORAGE_KEY.vault.jwt, auth); -} - -function getVaultJwt() { - return ( - storageManager.getDataFromLocalStorage(LOCAL_STORAGE_KEY.vault.jwt) || '' - ); -} - -function getReferer(bidderRequest) { - // TODO: is 'page' the right value here? - return bidderRequest?.refererInfo?.page || ''; -} - -function buildQuery(bidderRequest) { - let url = appendQueryParam(ENDPOINT, 'ver', '$prebid.version$'); - - const timeout = bidderRequest.timeout; - url = appendQueryParam(url, 'tmax', timeout); - - if (gdprApplies(bidderRequest)) { - const consentString = bidderRequest.gdprConsent.consentString; - url = appendQueryParam(url, 'gdpr', consentString); - } - - if (ccpaApplies(bidderRequest)) { - url = appendQueryParam(url, 'ccpa', bidderRequest.uspConsent); - } - - return url; -} - -function appendQueryParam(url, key, value) { - if (!value) { - return url; - } - const prefix = url.includes('?') ? '&' : '?'; - return `${url}${prefix}${key}=${encodeURIComponent(value)}`; -} - -function gdprApplies(bidderRequest) { - return Boolean(bidderRequest?.gdprConsent?.gdprApplies); -} - -function ccpaApplies(bidderRequest) { - return ( - isStr(bidderRequest.uspConsent) && - !isEmptyStr(bidderRequest.uspConsent) && - bidderRequest.uspConsent?.substr(1, 3) !== '---' - ); -} - -function processBidRequest(bid) { - const sizes = normalizeSizes(bid.sizes); - - return { - bid: bid.bidId, - pid: bid.params.pid, - sizes, - }; -} - -function normalizeSizes(sizes) { - const isSingleSize = - isArray(sizes) && - sizes.length === 2 && - !isArray(sizes[0]) && - !isArray(sizes[1]); - - if (isSingleSize) { - return [sizes]; - } - - return sizes; -} - -function getFirstPartyData(ortb2) { - let fpd = ortb2 || {}; - optimizeObject(fpd); - return fpd; -} - -function optimizeObject(obj) { - if (!isPlainObject(obj)) { - return; - } - for (const [key, value] of Object.entries(obj)) { - optimizeObject(value); - // only delete empty object, array, or string - if ( - (isPlainObject(value) || isArray(value) || isStr(value)) && - isEmpty(value) - ) { - delete obj[key]; - } - } -} - -function isValidResponse(bidResponse) { - const auth = bidResponse?.body?.auth; - const bids = bidResponse?.body?.data?.bids; - return isStr(auth) && isArray(bids) && !isEmpty(bids); -} - -function processBidResponse(bid) { - const meta = bid.meta || {}; - meta.advertiserDomains = bid.meta?.advertiserDomains || []; - - return { - ...bid, - meta, - }; -} - -registerBidder(spec); diff --git a/modules/glimpseBidAdapter.md b/modules/glimpseBidAdapter.md deleted file mode 100644 index e82c5d8f32e..00000000000 --- a/modules/glimpseBidAdapter.md +++ /dev/null @@ -1,37 +0,0 @@ -# Overview - -``` -Module Name: Glimpse Protocol Bid Adapter -Module Type: Bidder Adapter -Maintainer: publisher@glimpseprotocol.io -``` - -# Description - -This module connects publishers to Glimpse Protocol's demand sources via Prebid.js. Our innovative marketplace protects -consumer privacy while allowing precise targeting. It is compliant with GDPR, DPA and CCPA. - -The Glimpse Adapter supports banner formats. - -# Test Parameters - -```javascript -const adUnits = [ - { - code: 'banner-div-a', - mediaTypes: { - banner: { - sizes: [[300, 250]], - }, - }, - bids: [ - { - bidder: 'glimpse', - params: { - pid: 'e53a7f564f8f44cc913b', - }, - }, - ], - }, -]; -``` diff --git a/modules/glomexBidAdapter.js b/modules/glomexBidAdapter.js index 5c9b3c1fa28..10f5593940e 100644 --- a/modules/glomexBidAdapter.js +++ b/modules/glomexBidAdapter.js @@ -26,6 +26,7 @@ export const spec = { method: 'POST', url: `${ENDPOINT}`, data: { + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 auctionId: bidderRequest.auctionId, refererInfo: { // TODO: this collects everything it finds, except for canonicalUrl diff --git a/modules/gmosspBidAdapter.js b/modules/gmosspBidAdapter.js index 9bc1a15b60b..8c90d0cccfe 100644 --- a/modules/gmosspBidAdapter.js +++ b/modules/gmosspBidAdapter.js @@ -47,7 +47,7 @@ export const spec = { let queryString = ''; const request = validBidRequests[i]; - const tid = request.transactionId; + const tid = request.ortb2Imp?.ext?.tid; const bid = request.bidId; const imuid = deepAccess(request, 'userId.imuid'); const sharedId = deepAccess(request, 'userId.pubcid'); diff --git a/modules/gnetBidAdapter.js b/modules/gnetBidAdapter.js index 0b02a29c0d4..38e96c183b9 100644 --- a/modules/gnetBidAdapter.js +++ b/modules/gnetBidAdapter.js @@ -39,7 +39,7 @@ export const spec = { data.referer = referer; data.adUnitCode = request.adUnitCode; data.bidId = request.bidId; - data.transactionId = request.transactionId; + data.transactionId = request.ortb2Imp?.ext?.tid; data.gftuid = _getCookie(); data.sizes = parseSizesInput(request.sizes); diff --git a/modules/goldbachBidAdapter.js b/modules/goldbachBidAdapter.js index 21c56643353..4768931950c 100644 --- a/modules/goldbachBidAdapter.js +++ b/modules/goldbachBidAdapter.js @@ -20,17 +20,18 @@ import { isStr, logError, logInfo, - logMessage, - transformBidderParamKeywords + logMessage } from '../src/utils.js'; import {config} from '../src/config.js'; -import {getIabSubCategory, registerBidder} from '../src/adapters/bidderFactory.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; import {ADPOD, BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js'; import {auctionManager} from '../src/auctionManager.js'; import {find, includes} from '../src/polyfill.js'; import {INSTREAM, OUTSTREAM} from '../src/video.js'; import {hasPurpose1Consent} from '../src/utils/gpdr.js'; import { convertOrtbRequestToProprietaryNative } from '../src/native.js'; +import { APPNEXUS_CATEGORY_MAPPING } from '../libraries/categoryTranslationMapping/index.js'; +import {getANKeywordParam, transformBidderParamKeywords} from '../libraries/appnexusKeywords/anKeywords.js'; const BIDDER_CODE = 'goldbach'; const URL = 'https://ib.adnxs.com/ut/v3/prebid'; @@ -86,7 +87,6 @@ const NATIVE_MAPPING = { }; const SOURCE = 'pbjs'; const MAX_IMPS_PER_REQUEST = 15; -const mappingFileUrl = 'https://acdn.adnxs-simple.com/prebid/appnexus-mapping/mappings.json'; const SCRIPT_TAG_START = ' { let convertedKey = convertCamelToUnderscore(paramKey); if (convertedKey !== paramKey) { @@ -443,16 +421,6 @@ export const spec = { } }; -function isPopulatedArray(arr) { - return !!(isArray(arr) && arr.length > 0); -} - -function deleteValues(keyPairObj) { - if (isPopulatedArray(keyPairObj.value) && keyPairObj.value[0] === '') { - delete keyPairObj.value; - } -} - function reloadViewabilityScriptWithCorrectParameters(bid) { let viewJsPayload = getAppnexusViewabilityScriptFromJsTrackers(bid.native.javascriptTrackers); @@ -656,7 +624,7 @@ function newBid(serverBid, rtbBid, bidderRequest) { const videoContext = deepAccess(bidRequest, 'mediaTypes.video.context'); switch (videoContext) { case ADPOD: - const primaryCatId = getIabSubCategory(bidRequest.bidder, rtbBid.brand_category_id); + const primaryCatId = (APPNEXUS_CATEGORY_MAPPING[rtbBid.brand_category_id]) ? APPNEXUS_CATEGORY_MAPPING[rtbBid.brand_category_id] : null; bid.meta = Object.assign({}, bid.meta, { primaryCatId }); const dealTier = rtbBid.deal_priority; bid.video = { @@ -797,14 +765,7 @@ function bidToTag(bid) { if (bid.params.externalImpId) { tag.external_imp_id = bid.params.externalImpId; } - if (!isEmpty(bid.params.keywords)) { - let keywords = transformBidderParamKeywords(bid.params.keywords); - - if (keywords.length > 0) { - keywords.forEach(deleteValues); - } - tag.keywords = keywords; - } + tag.keywords = getANKeywordParam(bid.ortb2, bid.params.keywords); let gpid = deepAccess(bid, 'ortb2Imp.ext.data.pbadslot'); if (gpid) { @@ -919,6 +880,7 @@ function bidToTag(bid) { tag['banner_frameworks'] = bid.params.frameworks; } + // TODO: why does this need to iterate through every ad unit? let adUnit = find(auctionManager.getAdUnits(), au => bid.transactionId === au.transactionId); if (adUnit && adUnit.mediaTypes && adUnit.mediaTypes.banner) { tag.ad_types.push(BANNER); diff --git a/modules/googleAnalyticsAdapter.js b/modules/googleAnalyticsAdapter.js deleted file mode 100644 index 88ce20d07fa..00000000000 --- a/modules/googleAnalyticsAdapter.js +++ /dev/null @@ -1,298 +0,0 @@ -/** - * ga.js - analytics adapter for google analytics - */ - -import { _each, logMessage } from '../src/utils.js'; -import * as events from '../src/events.js'; -import CONSTANTS from '../src/constants.json'; -import adapterManager from '../src/adapterManager.js'; - -var BID_REQUESTED = CONSTANTS.EVENTS.BID_REQUESTED; -var BID_TIMEOUT = CONSTANTS.EVENTS.BID_TIMEOUT; -var BID_RESPONSE = CONSTANTS.EVENTS.BID_RESPONSE; -var BID_WON = CONSTANTS.EVENTS.BID_WON; - -var _disableInteraction = { nonInteraction: true }; -var _analyticsQueue = []; -var _gaGlobal = null; -var _enableCheck = true; -var _category = 'Prebid.js Bids'; -var _eventCount = 0; -var _enableDistribution = false; -var _cpmDistribution = null; -var _trackerSend = null; -var _sampled = true; -var _sendFloors = false; - -let adapter = {}; - -/** - * This will enable sending data to google analytics. Only call once, or duplicate data will be sent! - * @param {object} provider use to set GA global (if renamed); - * @param {object} options use to configure adapter; - * @return {[type]} [description] - */ -adapter.enableAnalytics = function ({ provider, options }) { - _gaGlobal = provider || 'ga'; - _trackerSend = options && options.trackerName ? options.trackerName + '.send' : 'send'; - _sampled = typeof options === 'undefined' || typeof options.sampling === 'undefined' || - Math.random() < parseFloat(options.sampling); - - if (options && typeof options.global !== 'undefined') { - _gaGlobal = options.global; - } - if (options && typeof options.enableDistribution !== 'undefined') { - _enableDistribution = options.enableDistribution; - } - if (options && typeof options.cpmDistribution === 'function') { - _cpmDistribution = options.cpmDistribution; - } - if (options && typeof options.sendFloors !== 'undefined') { - _sendFloors = options.sendFloors; - } - - var bid = null; - - if (_sampled) { - // first send all events fired before enableAnalytics called - - var existingEvents = events.getEvents(); - - _each(existingEvents, function (eventObj) { - if (typeof eventObj !== 'object') { - return; - } - var args = eventObj.args; - - if (eventObj.eventType === BID_REQUESTED) { - bid = args; - sendBidRequestToGa(bid); - } else if (eventObj.eventType === BID_RESPONSE) { - // bid is 2nd args - bid = args; - sendBidResponseToGa(bid); - } else if (eventObj.eventType === BID_TIMEOUT) { - const bidderArray = args; - sendBidTimeouts(bidderArray); - } else if (eventObj.eventType === BID_WON) { - bid = args; - sendBidWonToGa(bid); - } - }); - - // Next register event listeners to send data immediately - - // bidRequests - events.on(BID_REQUESTED, function (bidRequestObj) { - sendBidRequestToGa(bidRequestObj); - }); - - // bidResponses - events.on(BID_RESPONSE, function (bid) { - sendBidResponseToGa(bid); - }); - - // bidTimeouts - events.on(BID_TIMEOUT, function (bidderArray) { - sendBidTimeouts(bidderArray); - }); - - // wins - events.on(BID_WON, function (bid) { - sendBidWonToGa(bid); - }); - } else { - logMessage('Prebid.js google analytics disabled by sampling'); - } - - // finally set this function to return log message, prevents multiple adapter listeners - this.enableAnalytics = function _enable() { - return logMessage(`Analytics adapter already enabled, unnecessary call to \`enableAnalytics\`.`); - }; -}; - -adapter.getTrackerSend = function getTrackerSend() { - return _trackerSend; -}; - -/** - * Check if gaGlobal or window.ga is defined on page. If defined execute all the GA commands - */ -function checkAnalytics() { - if (_enableCheck && typeof window[_gaGlobal] === 'function') { - for (var i = 0; i < _analyticsQueue.length; i++) { - _analyticsQueue[i].call(); - } - - // override push to execute the command immediately from now on - _analyticsQueue.push = function (fn) { - fn.call(); - }; - - // turn check into NOOP - _enableCheck = false; - } - - logMessage('event count sent to GA: ' + _eventCount); -} - -function convertToCents(dollars) { - if (dollars) { - return Math.floor(dollars * 100); - } - - return 0; -} - -function getLoadTimeDistribution(time) { - var distribution; - if (time >= 0 && time < 200) { - distribution = '0-200ms'; - } else if (time >= 200 && time < 300) { - distribution = '0200-300ms'; - } else if (time >= 300 && time < 400) { - distribution = '0300-400ms'; - } else if (time >= 400 && time < 500) { - distribution = '0400-500ms'; - } else if (time >= 500 && time < 600) { - distribution = '0500-600ms'; - } else if (time >= 600 && time < 800) { - distribution = '0600-800ms'; - } else if (time >= 800 && time < 1000) { - distribution = '0800-1000ms'; - } else if (time >= 1000 && time < 1200) { - distribution = '1000-1200ms'; - } else if (time >= 1200 && time < 1500) { - distribution = '1200-1500ms'; - } else if (time >= 1500 && time < 2000) { - distribution = '1500-2000ms'; - } else if (time >= 2000) { - distribution = '2000ms above'; - } - - return distribution; -} - -function getCpmDistribution(cpm) { - if (_cpmDistribution) { - return _cpmDistribution(cpm); - } - var distribution; - if (cpm >= 0 && cpm < 0.5) { - distribution = '$0-0.5'; - } else if (cpm >= 0.5 && cpm < 1) { - distribution = '$0.5-1'; - } else if (cpm >= 1 && cpm < 1.5) { - distribution = '$1-1.5'; - } else if (cpm >= 1.5 && cpm < 2) { - distribution = '$1.5-2'; - } else if (cpm >= 2 && cpm < 2.5) { - distribution = '$2-2.5'; - } else if (cpm >= 2.5 && cpm < 3) { - distribution = '$2.5-3'; - } else if (cpm >= 3 && cpm < 4) { - distribution = '$3-4'; - } else if (cpm >= 4 && cpm < 6) { - distribution = '$4-6'; - } else if (cpm >= 6 && cpm < 8) { - distribution = '$6-8'; - } else if (cpm >= 8) { - distribution = '$8 above'; - } - - return distribution; -} - -function sendBidRequestToGa(bid) { - if (bid && bid.bidderCode) { - _analyticsQueue.push(function () { - _eventCount++; - if (_sendFloors) { - var floor = 'No Floor'; - if (bid.floorData) { - floor = bid.floorData.floorValue; - } else if (bid.bids.length) { - floor = bid.bids[0].getFloor().floor; - } - window[_gaGlobal](_trackerSend, 'event', _category, 'Requests by Floor=' + floor, bid.bidderCode, 1, _disableInteraction); - } else { - window[_gaGlobal](_trackerSend, 'event', _category, 'Requests', bid.bidderCode, 1, _disableInteraction); - } - }); - } - - // check the queue - checkAnalytics(); -} - -function sendBidResponseToGa(bid) { - if (bid && bid.bidderCode) { - _analyticsQueue.push(function () { - var cpmCents = convertToCents(bid.cpm); - var bidder = bid.bidderCode; - if (typeof bid.timeToRespond !== 'undefined' && _enableDistribution) { - _eventCount++; - var dis = getLoadTimeDistribution(bid.timeToRespond); - window[_gaGlobal](_trackerSend, 'event', 'Prebid.js Load Time Distribution', dis, bidder, 1, _disableInteraction); - } - - if (bid.cpm > 0) { - _eventCount = _eventCount + 2; - var cpmDis = getCpmDistribution(bid.cpm); - if (_enableDistribution) { - _eventCount++; - window[_gaGlobal](_trackerSend, 'event', 'Prebid.js CPM Distribution', cpmDis, bidder, 1, _disableInteraction); - } - if (_sendFloors) { - var floor = (bid.floorData) ? bid.floorData.floorValue : 'No Floor'; - window[_gaGlobal](_trackerSend, 'event', _category, 'Bids by Floor=' + floor, 'Size=' + bid.size + ',' + bidder, cpmCents, _disableInteraction); - } else { - window[_gaGlobal](_trackerSend, 'event', _category, 'Bids', bidder, cpmCents, _disableInteraction); - } - window[_gaGlobal](_trackerSend, 'event', _category, 'Bid Load Time', bidder, bid.timeToRespond, _disableInteraction); - } - }); - } - - // check the queue - checkAnalytics(); -} - -function sendBidTimeouts(timedOutBidders) { - _analyticsQueue.push(function () { - _each(timedOutBidders, function (bidderCode) { - _eventCount++; - var bidderName = bidderCode.bidder; - window[_gaGlobal](_trackerSend, 'event', _category, 'Timeouts', bidderName, _disableInteraction); - }); - }); - - checkAnalytics(); -} - -function sendBidWonToGa(bid) { - var cpmCents = convertToCents(bid.cpm); - _analyticsQueue.push(function () { - _eventCount++; - if (_sendFloors) { - var floor = (bid.floorData) ? bid.floorData.floorValue : 'No Floor'; - window[_gaGlobal](_trackerSend, 'event', _category, 'Wins by Floor=' + floor, 'Size=' + bid.size + ',' + bid.bidderCode, cpmCents, _disableInteraction); - } else { - window[_gaGlobal](_trackerSend, 'event', _category, 'Wins', bid.bidderCode, cpmCents, _disableInteraction); - } - }); - - checkAnalytics(); -} - -/** - * Exposed for testing purposes - */ -adapter.getCpmDistribution = getCpmDistribution; - -adapterManager.registerAnalyticsAdapter({ - adapter, - code: 'ga' -}); - -export default adapter; diff --git a/modules/googleAnalyticsAdapter.md b/modules/googleAnalyticsAdapter.md deleted file mode 100644 index 8c31b07b811..00000000000 --- a/modules/googleAnalyticsAdapter.md +++ /dev/null @@ -1,38 +0,0 @@ -# Google Analytics Adapter - -The google analytics adapter pushes prebid events into google analytics. - -## Usage - -The simplest way to enable the analytics adapter is this - -```javascript -pbjs.enableAnalytics([{ - provider: 'ga' -}]); -``` - -Defaults will be used and you should see events being pushed to analytics. - -You can customize the adapter with various `options` like this - -```javascript -pbjs.enableAnalytics([{ - provider: 'ga', - options: { ... } -}]); - -Here is a full list of settings available - -- `global` (string) - name of the global analytics object. Default is `ga` -- `trackerName` (string) - use another tracker for prebid events. Default is the default tracker -- `sampling` (number) - choose a value from `0` to `1`, where `0` means 0% and `1` means 100% tracked -- `enableDistribution` (boolean) - enables additional events that track load time and cpm distribution - by creating buckets for load time and cpm -- `cpmDistribution` (cpm: number => string) - customize the cpm buckets for the cpm distribution -- `sendFloors` (boolean) - if set, will include floor data in the eventCategory field and include ad unit code in eventAction field - - -## Additional resources - -- [Prebid GA Analytics](http://prebid.org/overview/ga-analytics.html) diff --git a/modules/gothamadsBidAdapter.js b/modules/gothamadsBidAdapter.js index 6b549f347bb..9f44a54460f 100644 --- a/modules/gothamadsBidAdapter.js +++ b/modules/gothamadsBidAdapter.js @@ -104,7 +104,7 @@ export const spec = { host: location.host }, source: { - tid: bidRequest.transactionId + tid: bidderRequest?.ortb2?.source?.tid, }, regs: { coppa: config.getConfig('coppa') === true ? 1 : 0, @@ -224,7 +224,7 @@ const parseNative = admObject => { const prepareImpObject = (bidRequest) => { let impObject = { - id: bidRequest.transactionId, + id: bidRequest.bidId, secure: 1, ext: { placementId: bidRequest.params.placementId @@ -247,7 +247,8 @@ const prepareImpObject = (bidRequest) => { const addNativeParameters = bidRequest => { let impObject = { - id: bidRequest.transactionId, + // TODO: this is not an "impObject", and `id` is not part of the ORTB native spec + id: bidRequest.bidId, ver: NATIVE_VERSION, }; diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js index 130eac9512d..9c63e871356 100644 --- a/modules/gridBidAdapter.js +++ b/modules/gridBidAdapter.js @@ -6,8 +6,6 @@ import { generateUUID, mergeDeep, logWarn, - parseUrl, - isArray, isNumber, isStr } from '../src/utils.js'; @@ -16,25 +14,16 @@ import { Renderer } from '../src/Renderer.js'; import { VIDEO, BANNER } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; import { getStorageManager } from '../src/storageManager.js'; -import { find } from '../src/polyfill.js'; const BIDDER_CODE = 'grid'; const ENDPOINT_URL = 'https://grid.bidswitch.net/hbjson'; -const ADAPTER_VERSION_FOR_CRITEO_MODE = 34; -const CDB_ENDPOINT = 'https://bidder.criteo.com/cdb'; -const PROFILE_ID_INLINE = 207; -const SID_COOKIE_NAME = 'cto_sid'; -const IDCPY_COOKIE_NAME = 'cto_idcpy'; -const OPTOUT_COOKIE_NAME = 'cto_optout'; -const BUNDLE_COOKIE_NAME = 'cto_bundle'; - const SYNC_URL = 'https://x.bidswitch.net/sync?ssp=themediagrid'; const TIME_TO_LIVE = 360; const USER_ID_KEY = 'tmguid'; const GVLID = 686; const RENDERER_URL = 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js'; -export const storage = getStorageManager({bidderCode: BIDDER_CODE}); +export const storage = getStorageManager({ bidderCode: BIDDER_CODE }); const LOG_ERROR_MESS = { noAuid: 'Bid from response has no auid parameter - ', @@ -98,33 +87,24 @@ export const spec = { let userExt = null; let endpoint = null; let forceBidderName = false; - let {bidderRequestId, auctionId, gdprConsent, uspConsent, timeout, refererInfo, gppConsent} = bidderRequest || {}; + let {bidderRequestId, gdprConsent, uspConsent, timeout, refererInfo, gppConsent} = bidderRequest || {}; const referer = refererInfo ? encodeURIComponent(refererInfo.page) : ''; const tmax = timeout; const imp = []; const bidsMap = {}; const requests = []; - const criteoBidsMap = {}; - const criteoBidRequests = []; const sources = []; const bidsArray = []; validBidRequests.forEach((bid) => { const bidObject = { bid, savedPrebidBid: null }; - if (bid.params.withCriteo && criteoSpec.isBidRequestValid(bid)) { - criteoBidsMap[bid.bidId] = bidObject; - criteoBidRequests.push(bid); - } if (!bid.params.uid && !bid.params.secid) { return; } if (!bidderRequestId) { bidderRequestId = bid.bidderRequestId; } - if (!auctionId) { - auctionId = bid.auctionId; - } if (!schain) { schain = bid.schain; } @@ -196,7 +176,7 @@ export const spec = { if (impObj.banner || impObj.video) { if (multiRequest) { const reqSource = { - tid: bid.auctionId && bid.auctionId.toString(), + tid: bidderRequest?.ortb2?.source?.tid?.toString?.(), ext: { wrapper: 'Prebid_js', wrapper_version: '$prebid.version$' @@ -247,7 +227,7 @@ export const spec = { } const reqSource = { - tid: auctionId && auctionId.toString(), + tid: bidderRequest?.ortb2?.source?.tid?.toString?.(), ext: { wrapper: 'Prebid_js', wrapper_version: '$prebid.version$' @@ -405,11 +385,6 @@ export const spec = { } }); - const criteoRequest = criteoBidRequests.length && criteoSpec.buildRequests(criteoBidRequests, bidderRequest); - if (criteoRequest) { - criteoRequest.criteoBidsMap = criteoBidsMap; - } - return [...requests.map((req, i) => { let sp; const url = (endpoint || ENDPOINT_URL).replace(/[?&]sp=([^?&=]+)/, (i, found) => { @@ -431,7 +406,7 @@ export const spec = { url: endpoint || ENDPOINT_URL, data: JSON.stringify(mainRequest), bidsMap - }] : []), ...(criteoRequest ? [criteoRequest] : [])]; + }] : [])]; }, /** * Unpack the response from the server into a list of bids. @@ -441,34 +416,26 @@ export const spec = { * @param {*} RendererConst * @return {Bid[]} An array of bids which were nested inside the server. */ - interpretResponse: function(serverResponse, bidRequest, RendererConst = Renderer) { - if (bidRequest.criteoBidsMap && bidRequest.bidRequests) { - const criteoBids = criteoSpec.interpretResponse(serverResponse, bidRequest); - return criteoBids.filter((bid) => { - const { savedPrebidBid } = bidRequest.criteoBidsMap[bid.requestId] || {}; - return canPublishResponse(bid.cpm, savedPrebidBid && savedPrebidBid.cpm); - }); - } else { - serverResponse = serverResponse && serverResponse.body; - const bidResponses = []; + interpretResponse: function (serverResponse, bidRequest, RendererConst = Renderer) { + serverResponse = serverResponse && serverResponse.body; + const bidResponses = []; - let errorMessage; + let errorMessage; - if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse; - else if (serverResponse.seatbid && !serverResponse.seatbid.length) { - errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray; - } + if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse; + else if (serverResponse.seatbid && !serverResponse.seatbid.length) { + errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray; + } - const bidderCode = this.forceBidderName || this.code; + const bidderCode = this.forceBidderName || this.code; - if (!errorMessage && serverResponse.seatbid) { - serverResponse.seatbid.forEach(respItem => { - _addBidResponse(_getBidFromResponse(respItem), bidRequest, bidResponses, RendererConst, bidderCode); - }); - } - if (errorMessage) logError(errorMessage); - return bidResponses; + if (!errorMessage && serverResponse.seatbid) { + serverResponse.seatbid.forEach(respItem => { + _addBidResponse(_getBidFromResponse(respItem), bidRequest, bidResponses, RendererConst, bidderCode); + }); } + if (errorMessage) logError(errorMessage); + return bidResponses; }, getUserSyncs: function (...args) { const [syncOptions,, gdprConsent, uspConsent] = args; @@ -746,372 +713,4 @@ export function getSyncUrl() { return SYNC_URL; } -// ================ Criteo methods ================== - -const criteoSpec = { - /** f - * @param {object} bid - * @return {boolean} - */ - isBidRequestValid: (bid) => { - // either one of zoneId or networkId should be set - if (!(bid && bid.params && (bid.params.zoneId || bid.params.networkId))) { - return false; - } - - // video media types requires some mandatory params - if (hasVideoMediaType(bid)) { - if (!hasValidVideoMediaType(bid)) { - return false; - } - } - - return true; - }, - - /** - * @param {BidRequest[]} bidRequests - * @param {*} bidderRequest - * @return {ServerRequest} - */ - buildRequests: (bidRequests, bidderRequest) => { - let url; - let data; - let fpd = bidderRequest.ortb2 || {}; - - Object.assign(bidderRequest, { - publisherExt: fpd.site?.ext, - userExt: fpd.user?.ext, - ceh: config.getConfig('criteo.ceh'), - coppa: config.getConfig('coppa') - }); - - const context = buildContext(bidRequests, bidderRequest); - url = buildCdbUrl(context); - data = buildCdbRequest(context, bidRequests, bidderRequest); - - if (data) { - return { method: 'POST', url, data, bidRequests }; - } - }, - - /** - * @param {*} response - * @param {ServerRequest} request - * @return {Bid[]} - */ - interpretResponse: (response, request) => { - const body = response.body || response; - const bids = []; - - if (body && body.slots && isArray(body.slots)) { - body.slots.forEach(slot => { - const bidRequest = find(request.bidRequests, b => b.adUnitCode === slot.impid && (!b.params.zoneId || parseInt(b.params.zoneId) === slot.zoneid)); - const bidId = bidRequest.bidId; - const bid = { - requestId: bidId, - cpm: slot.cpm, - currency: slot.currency, - netRevenue: true, - ttl: slot.ttl || 60, - creativeId: slot.creativecode, - width: slot.width, - height: slot.height, - dealId: slot.dealCode, - }; - if (body.ext?.paf?.transmission && slot.ext?.paf?.content_id) { - const pafResponseMeta = { - content_id: slot.ext.paf.content_id, - transmission: response.ext.paf.transmission - }; - bid.meta = Object.assign({}, bid.meta, { paf: pafResponseMeta }); - } - if (slot.adomain) { - bid.meta = Object.assign({}, bid.meta, { advertiserDomains: slot.adomain }); - } - if (slot.video) { - bid.vastUrl = slot.displayurl; - bid.mediaType = VIDEO; - } else { - bid.ad = slot.creative; - } - bids.push(bid); - }); - } - - return bids; - } -}; - -function readFromAllStorages(name) { - const fromCookie = storage.getCookie(name); - const fromLocalStorage = storage.getDataFromLocalStorage(name); - - return fromCookie || fromLocalStorage || undefined; -} - -/** - * @param {BidRequest[]} bidRequests - * @param bidderRequest - */ -function buildContext(bidRequests, bidderRequest) { - let referrer = ''; - if (bidderRequest && bidderRequest.refererInfo) { - referrer = bidderRequest.refererInfo.page; - } - const queryString = parseUrl(bidderRequest?.refererInfo?.topmostLocation).search; - - const context = { - url: referrer, - debug: queryString['pbt_debug'] === '1', - noLog: queryString['pbt_nolog'] === '1', - amp: false, - }; - - bidRequests.forEach(bidRequest => { - if (bidRequest.params.integrationMode === 'amp') { - context.amp = true; - } - }); - - return context; -} - -/** - * @param {CriteoContext} context - * @return {string} - */ -function buildCdbUrl(context) { - let url = CDB_ENDPOINT; - url += '?profileId=' + PROFILE_ID_INLINE; - url += '&av=' + String(ADAPTER_VERSION_FOR_CRITEO_MODE); - url += '&wv=' + encodeURIComponent('$prebid.version$'); - url += '&cb=' + String(Math.floor(Math.random() * 99999999999)); - - if (storage.localStorageIsEnabled()) { - url += '&lsavail=1'; - } else { - url += '&lsavail=0'; - } - - if (context.amp) { - url += '&im=1'; - } - if (context.debug) { - url += '&debug=1'; - } - if (context.noLog) { - url += '&nolog=1'; - } - - const bundle = readFromAllStorages(BUNDLE_COOKIE_NAME); - if (bundle) { - url += `&bundle=${bundle}`; - } - - const optout = readFromAllStorages(OPTOUT_COOKIE_NAME); - if (optout) { - url += `&optout=1`; - } - - const sid = readFromAllStorages(SID_COOKIE_NAME); - if (sid) { - url += `&sid=${sid}`; - } - - const idcpy = readFromAllStorages(IDCPY_COOKIE_NAME); - if (idcpy) { - url += `&idcpy=${idcpy}`; - } - - return url; -} - -/** - * @param {CriteoContext} context - * @param {BidRequest[]} bidRequests - * @param bidderRequest - * @return {*} - */ -function buildCdbRequest(context, bidRequests, bidderRequest) { - let networkId; - let schain; - const request = { - publisher: { - url: context.url, - ext: bidderRequest.publisherExt, - }, - regs: { - coppa: bidderRequest.coppa === true ? 1 : (bidderRequest.coppa === false ? 0 : undefined) - }, - slots: bidRequests.map(bidRequest => { - networkId = bidRequest.params.networkId || networkId; - schain = bidRequest.schain || schain; - const slot = { - impid: bidRequest.adUnitCode, - transactionid: bidRequest.transactionId, - auctionId: bidRequest.auctionId, - }; - if (bidRequest.params.zoneId) { - slot.zoneid = bidRequest.params.zoneId; - } - if (deepAccess(bidRequest, 'ortb2Imp.ext')) { - slot.ext = bidRequest.ortb2Imp.ext; - } - if (bidRequest.params.ext) { - slot.ext = Object.assign({}, slot.ext, bidRequest.params.ext); - } - if (bidRequest.params.publisherSubId) { - slot.publishersubid = bidRequest.params.publisherSubId; - } - - if (hasBannerMediaType(bidRequest)) { - slot.sizes = parseSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes'), parseSize); - } else { - slot.sizes = []; - } - - if (hasVideoMediaType(bidRequest)) { - const video = { - playersizes: parseSizes(deepAccess(bidRequest, 'mediaTypes.video.playerSize'), parseSize), - mimes: bidRequest.mediaTypes.video.mimes, - protocols: bidRequest.mediaTypes.video.protocols, - maxduration: bidRequest.mediaTypes.video.maxduration, - api: bidRequest.mediaTypes.video.api, - skip: bidRequest.mediaTypes.video.skip, - placement: bidRequest.mediaTypes.video.placement, - minduration: bidRequest.mediaTypes.video.minduration, - playbackmethod: bidRequest.mediaTypes.video.playbackmethod, - startdelay: bidRequest.mediaTypes.video.startdelay - }; - if ('plcmt' in bidRequest.mediaTypes.video) { - video.plcmt = bidRequest.mediaTypes.video.plcmt; - } - const paramsVideo = bidRequest.params.video; - if (paramsVideo !== undefined) { - video.skip = video.skip || paramsVideo.skip || 0; - video.placement = video.placement || paramsVideo.placement; - video.minduration = video.minduration || paramsVideo.minduration; - video.playbackmethod = video.playbackmethod || paramsVideo.playbackmethod; - video.startdelay = video.startdelay || paramsVideo.startdelay || 0; - } - - slot.video = video; - } - - enrichSlotWithFloors(slot, bidRequest); - - return slot; - }), - }; - if (networkId) { - request.publisher.networkid = networkId; - } - if (schain) { - request.source = { - ext: { - schain: schain - } - }; - } - request.user = { - ext: bidderRequest.userExt - }; - if (bidderRequest && bidderRequest.ceh) { - request.user.ceh = bidderRequest.ceh; - } - if (bidderRequest && bidderRequest.gdprConsent) { - request.gdprConsent = {}; - if (typeof bidderRequest.gdprConsent.gdprApplies !== 'undefined') { - request.gdprConsent.gdprApplies = !!(bidderRequest.gdprConsent.gdprApplies); - } - request.gdprConsent.version = bidderRequest.gdprConsent.apiVersion; - if (typeof bidderRequest.gdprConsent.consentString !== 'undefined') { - request.gdprConsent.consentData = bidderRequest.gdprConsent.consentString; - } - } - if (bidderRequest && bidderRequest.uspConsent) { - request.user.uspIab = bidderRequest.uspConsent; - } - return request; -} - -function parseSizes(sizes, parser = s => s) { - if (sizes === undefined) { - return []; - } - if (Array.isArray(sizes[0])) { // is there several sizes ? (ie. [[728,90],[200,300]]) - return sizes.map(size => parser(size)); - } - return [parser(sizes)]; // or a single one ? (ie. [728,90]) -} - -function parseSize(size) { - return size[0] + 'x' + size[1]; -} - -function hasVideoMediaType(bidRequest) { - return deepAccess(bidRequest, 'mediaTypes.video') !== undefined; -} - -function hasBannerMediaType(bidRequest) { - return deepAccess(bidRequest, 'mediaTypes.banner') !== undefined; -} - -function hasValidVideoMediaType(bidRequest) { - let isValid = true; - - var requiredMediaTypesParams = ['mimes', 'playerSize', 'maxduration', 'protocols', 'api', 'skip', 'placement', 'playbackmethod']; - - requiredMediaTypesParams.forEach(function (param) { - if (deepAccess(bidRequest, 'mediaTypes.video.' + param) === undefined && deepAccess(bidRequest, 'params.video.' + param) === undefined) { - isValid = false; - logError('TheMediaGrid Bid Adapter (withCriteo mode): mediaTypes.video.' + param + ' is required'); - } - }); - - if (isValid) { - const videoPlacement = bidRequest.mediaTypes.video.placement || bidRequest.params.video.placement; - // We do not support long form for now, also we have to check that context & placement are consistent - if (bidRequest.mediaTypes.video.context === 'instream' && videoPlacement === 1) { - return true; - } else if (bidRequest.mediaTypes.video.context === 'outstream' && videoPlacement !== 1) { - return true; - } - } - - return false; -} - -function enrichSlotWithFloors(slot, bidRequest) { - try { - const slotFloors = {}; - - if (bidRequest.getFloor) { - if (bidRequest.mediaTypes?.banner) { - slotFloors.banner = {}; - const bannerSizes = parseSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes')) - bannerSizes.forEach(bannerSize => slotFloors.banner[parseSize(bannerSize).toString()] = bidRequest.getFloor({ size: bannerSize, mediaType: BANNER })); - } - - if (bidRequest.mediaTypes?.video) { - slotFloors.video = {}; - const videoSizes = parseSizes(deepAccess(bidRequest, 'mediaTypes.video.playerSize')) - videoSizes.forEach(videoSize => slotFloors.video[parseSize(videoSize).toString()] = bidRequest.getFloor({ size: videoSize, mediaType: VIDEO })); - } - - if (Object.keys(slotFloors).length > 0) { - if (!slot.ext) { - slot.ext = {} - } - Object.assign(slot.ext, { - floors: slotFloors - }); - } - } - } catch (e) { - logError('Could not parse floors from Prebid: ' + e); - } -} - registerBidder(spec); diff --git a/modules/gumgumBidAdapter.js b/modules/gumgumBidAdapter.js index fdd3030bb7a..d050af4ac8f 100644 --- a/modules/gumgumBidAdapter.js +++ b/modules/gumgumBidAdapter.js @@ -293,7 +293,6 @@ function buildRequests(validBidRequests, bidderRequest) { mediaTypes = {}, params = {}, schain, - transactionId, userId = {}, ortb2Imp, adUnitCode = '' @@ -404,7 +403,7 @@ function buildRequests(validBidRequests, bidderRequest) { bids.push({ id: bidId, tmax: timeout, - tId: transactionId, + tId: ortb2Imp?.ext?.tid, pi: data.pi, selector: params.selector, sizes, diff --git a/modules/h12mediaBidAdapter.js b/modules/h12mediaBidAdapter.js index c58f15c9a81..7b1ba9ee286 100644 --- a/modules/h12mediaBidAdapter.js +++ b/modules/h12mediaBidAdapter.js @@ -41,7 +41,7 @@ export const spec = { const bidrequest = { bidId: bidRequest.bidId, - transactionId: bidRequest.transactionId, + transactionId: bidRequest.ortb2Imp?.ext?.tid, adunitId: bidRequest.adUnitCode, pubid: bidderParams.pubid, placementid: bidderParams.placementid || '', diff --git a/modules/holidBidAdapter.js b/modules/holidBidAdapter.js index 92b0a1c18db..f41829bd123 100644 --- a/modules/holidBidAdapter.js +++ b/modules/holidBidAdapter.js @@ -1,15 +1,9 @@ -import { - deepAccess, - getBidIdParameter, - isStr, - logMessage, - triggerPixel, -} from '../src/utils.js' -import * as events from '../src/events.js' -import CONSTANTS from '../src/constants.json' -import { BANNER } from '../src/mediaTypes.js' - -import { registerBidder } from '../src/adapters/bidderFactory.js' +import {deepAccess, getBidIdParameter, isStr, logMessage, triggerPixel, } from '../src/utils.js'; +import * as events from '../src/events.js'; +import CONSTANTS from '../src/constants.json'; +import {BANNER} from '../src/mediaTypes.js'; + +import {registerBidder} from '../src/adapters/bidderFactory.js'; const BIDDER_CODE = 'holid' const GVLID = 1177 @@ -33,7 +27,7 @@ export const spec = { return validBidRequests.map((bid) => { const requestData = { ...bid.ortb2, - id: bid.auctionId, + id: _bidderRequest.bidderRequestId, imp: [getImp(bid)], } @@ -56,6 +50,7 @@ export const spec = { serverResponse.body.seatbid.map((response) => { response.bid.map((bid) => { const requestId = bidRequest.bidId + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 const auctionId = bidRequest.auctionId const wurl = deepAccess(bid, 'ext.prebid.events.win') const bidResponse = { diff --git a/modules/hybridBidAdapter.js b/modules/hybridBidAdapter.js index 6cedb094444..f746e69cbba 100644 --- a/modules/hybridBidAdapter.js +++ b/modules/hybridBidAdapter.js @@ -25,7 +25,7 @@ function buildBidRequests(validBidRequests) { const params = validBidRequest.params; const bidRequest = { bidId: validBidRequest.bidId, - transactionId: validBidRequest.transactionId, + transactionId: validBidRequest.ortb2Imp?.ext?.tid, sizes: validBidRequest.sizes, placement: placementTypes[params.placement], placeId: params.placeId, @@ -88,6 +88,7 @@ function buildBid(bidData) { bid.vastXml = bidData.content; bid.mediaType = VIDEO; + // TODO: why does this need to iterate through every ad unit? let adUnit = find(auctionManager.getAdUnits(), function (unit) { return unit.transactionId === bidData.transactionId; }); @@ -244,7 +245,6 @@ export const spec = { return item.bidId === bid.bidId; }); bid.placement = rawBid.placement; - bid.transactionId = rawBid.transactionId; bid.placeId = rawBid.placeId; return buildBid(bid); }); diff --git a/modules/synacormediaBidAdapter.js b/modules/imdsBidAdapter.js similarity index 93% rename from modules/synacormediaBidAdapter.js rename to modules/imdsBidAdapter.js index 7165f778e5f..545a0bd1ac3 100644 --- a/modules/synacormediaBidAdapter.js +++ b/modules/imdsBidAdapter.js @@ -16,7 +16,10 @@ const BLOCKED_AD_SIZES = [ ]; const DEFAULT_MAX_TTL = 420; // 7 minutes export const spec = { - code: 'synacormedia', + code: 'imds', + aliases: [ + { code: 'synacormedia' } + ], supportedMediaTypes: [ BANNER, VIDEO ], sizeMap: {}, @@ -36,7 +39,7 @@ export const spec = { } const refererInfo = bidderRequest.refererInfo; const openRtbBidRequest = { - id: bidderRequest.auctionId, + id: bidderRequest.bidderRequestId, site: { // TODO: does the fallback make sense here? domain: refererInfo.domain || location.hostname, @@ -63,7 +66,7 @@ export const spec = { validBidReqs.forEach((bid, i) => { if (seatId && seatId !== bid.params.seatId) { - logWarn(`Synacormedia: there is an inconsistent seatId: ${bid.params.seatId} but only sending bid requests for ${seatId}, you should double check your configuration`); + logWarn(`IMDS: there is an inconsistent seatId: ${bid.params.seatId} but only sending bid requests for ${seatId}, you should double check your configuration`); return; } else { seatId = bid.params.seatId; @@ -71,7 +74,7 @@ export const spec = { const tagIdOrPlacementId = bid.params.tagId || bid.params.placementId; let pos = parseInt(bid.params.pos || deepAccess(bid.mediaTypes, 'video.pos'), 10); if (isNaN(pos)) { - logWarn(`Synacormedia: there is an invalid POS: ${bid.params.pos}`); + logWarn(`IMDS: there is an invalid POS: ${bid.params.pos}`); pos = 0; } const videoOrBannerKey = this.isVideoBid(bid) ? 'video' : 'banner'; @@ -149,7 +152,7 @@ export const spec = { }; const bidFloor = getBidFloor(bid, 'banner', '*'); if (isNaN(bidFloor)) { - logWarn(`Synacormedia: there is an invalid bid floor: ${bid.params.bidfloor}`); + logWarn(`IMDS: there is an invalid bid floor: ${bid.params.bidfloor}`); } if (bidFloor !== null && !isNaN(bidFloor)) { imp.bidfloor = bidFloor; @@ -173,7 +176,7 @@ export const spec = { }; const bidFloor = getBidFloor(bid, 'video', size); if (isNaN(bidFloor)) { - logWarn(`Synacormedia: there is an invalid bid floor: ${bid.params.bidfloor}`); + logWarn(`IMDS: there is an invalid bid floor: ${bid.params.bidfloor}`); } if (bidFloor !== null && !isNaN(bidFloor)) { @@ -211,7 +214,7 @@ export const spec = { }; if (!serverResponse.body || typeof serverResponse.body != 'object') { - logWarn('Synacormedia: server returned empty/non-json response: ' + JSON.stringify(serverResponse.body)); + logWarn('IMDS: server returned empty/non-json response: ' + JSON.stringify(serverResponse.body)); return; } const {id, seatbid: seatbids} = serverResponse.body; @@ -299,7 +302,7 @@ export const spec = { url: `${USER_SYNC_HOST}/html/usersync.html?src=$$REPO_AND_VERSION$$` }); } else { - logWarn('Synacormedia: Please enable iframe based user sync.'); + logWarn('IMDS: Please enable iframe based user sync.'); } return syncs; } diff --git a/modules/synacormediaBidAdapter.md b/modules/imdsBidAdapter.md similarity index 84% rename from modules/synacormediaBidAdapter.md rename to modules/imdsBidAdapter.md index 523c66fd1d9..15fb407e7ef 100644 --- a/modules/synacormediaBidAdapter.md +++ b/modules/imdsBidAdapter.md @@ -1,14 +1,14 @@ # Overview ``` -Module Name: Synacor Media Bidder Adapter +Module Name: iMedia Digital Services Bidder Adapter Module Type: Bidder Adapter -Maintainer: eng-demand@synacor.com +Maintainer: eng-demand@imds.tv ``` # Description -The Synacor Media adapter requires setup and approval from Synacor. +The iMedia Digital Services adapter requires setup and approval from iMedia Digital Services. Please reach out to your account manager for more information. ### DFP Video Creative @@ -30,7 +30,7 @@ https://track.technoratimedia.com/openrtb/tags?ID=%%PATTERN:hb_cache_id_synacorm } }, bids: [{ - bidder: "synacormedia", + bidder: "imds", params: { seatId: "prebid", tagId: "demo1", @@ -49,7 +49,7 @@ https://track.technoratimedia.com/openrtb/tags?ID=%%PATTERN:hb_cache_id_synacorm } }, bids: [{ - bidder: "synacormedia", + bidder: "imds", params: { seatId: "prebid", tagId: "demo1", diff --git a/modules/impactifyBidAdapter.js b/modules/impactifyBidAdapter.js index d35d4498136..f2bf9aaddcb 100644 --- a/modules/impactifyBidAdapter.js +++ b/modules/impactifyBidAdapter.js @@ -1,7 +1,7 @@ -import { deepAccess, deepSetValue, generateUUID } from '../src/utils.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { config } from '../src/config.js'; -import { ajax } from '../src/ajax.js'; +import {deepAccess, deepSetValue, generateUUID} from '../src/utils.js'; +import {registerBidder} from '../src/adapters/bidderFactory.js'; +import {config} from '../src/config.js'; +import {ajax} from '../src/ajax.js'; const BIDDER_CODE = 'impactify'; const BIDDER_ALIAS = ['imp']; @@ -41,11 +41,11 @@ const getFloor = (bid) => { const createOpenRtbRequest = (validBidRequests, bidderRequest) => { // Create request and set imp bids inside let request = { - id: bidderRequest.auctionId, + id: bidderRequest.bidderRequestId, validBidRequests, cur: [DEFAULT_CURRENCY], imp: [], - source: {tid: bidderRequest.auctionId} + source: {tid: bidderRequest.ortb2?.source?.tid} }; // Get the url parameters diff --git a/modules/improvedigitalBidAdapter.js b/modules/improvedigitalBidAdapter.js index 437fcf7d5bb..b56cc56a186 100644 --- a/modules/improvedigitalBidAdapter.js +++ b/modules/improvedigitalBidAdapter.js @@ -150,8 +150,7 @@ export const CONVERTER = ortbConverter({ mergeDeep(request, { id: getUniqueIdentifierStr(), source: { - // TODO: once https://github.com/prebid/Prebid.js/issues/8573 is resolved, this should be handled by the base ortbConverter logic - tid: context.bidRequests[0].transactionId, + }, ext: { improvedigital: { diff --git a/modules/inmarBidAdapter.js b/modules/inmarBidAdapter.js deleted file mode 100755 index 42bd64ee816..00000000000 --- a/modules/inmarBidAdapter.js +++ /dev/null @@ -1,132 +0,0 @@ -import {logError, mergeDeep} from '../src/utils.js'; -import { config } from '../src/config.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; -import { BANNER, VIDEO } from '../src/mediaTypes.js'; - -const BIDDER_CODE = 'inmar'; - -export const spec = { - code: BIDDER_CODE, - aliases: ['inm'], - supportedMediaTypes: [BANNER, VIDEO], - - /** - * Determines whether or not the given bid request is valid - * - * @param {bidRequest} bid The bid params to validate. - * @returns {boolean} True if this is a valid bid, and false otherwise - */ - isBidRequestValid: function(bid) { - return !!(bid.params && bid.params.partnerId); - }, - - /** - * Build a server request from the list of valid BidRequests - * @param {validBidRequests} is an array of the valid bids - * @param {bidderRequest} bidder request object - * @returns {ServerRequest} Info describing the request to the server - */ - buildRequests: function(validBidRequests, bidderRequest) { - var payload = { - bidderCode: bidderRequest.bidderCode, - auctionId: bidderRequest.auctionId, - bidderRequestId: bidderRequest.bidderRequestId, - bidRequests: validBidRequests, - auctionStart: bidderRequest.auctionStart, - timeout: bidderRequest.timeout, - // TODO: please do not send internal data structures over the network - refererInfo: bidderRequest.refererInfo.legacy, - start: bidderRequest.start, - gdprConsent: bidderRequest.gdprConsent, - uspConsent: bidderRequest.uspConsent, - currencyCode: config.getConfig('currency.adServerCurrency'), - coppa: config.getConfig('coppa'), - firstPartyData: getLegacyFpd(bidderRequest.ortb2), - prebidVersion: '$prebid.version$' - }; - - var payloadString = JSON.stringify(payload); - - return { - method: 'POST', - url: 'https://prebid.owneriq.net:8443/bidder/pb/bid', - data: payloadString, - }; - }, - - /** - * Read the response from the server and build a list of bids - * @param {serverResponse} Response from the server. - * @param {bidRequest} Bid request object - * @returns {bidResponses} Array of bids which were nested inside the server - */ - interpretResponse: function(serverResponse, bidRequest) { - const bidResponses = []; - var response = serverResponse.body; - - try { - if (response) { - var bidResponse = { - requestId: response.requestId, - cpm: response.cpm, - currency: response.currency, - width: response.width, - height: response.height, - ad: response.ad, - ttl: response.ttl, - creativeId: response.creativeId, - netRevenue: response.netRevenue, - vastUrl: response.vastUrl, - dealId: response.dealId, - meta: response.meta - }; - - bidResponses.push(bidResponse); - } - } catch (error) { - logError('Error while parsing inmar response', error); - } - return bidResponses; - }, - - /** - * User Syncs - * - * @param {syncOptions} Publisher prebid configuration - * @param {serverResponses} Response from the server - * @returns {Array} - */ - getUserSyncs: function(syncOptions, serverResponses) { - const syncs = []; - if (syncOptions.pixelEnabled) { - syncs.push({ - type: 'image', - url: 'https://px.owneriq.net/eucm/p/pb' - }); - } - return syncs; - } -}; - -function getLegacyFpd(ortb2) { - if (typeof ortb2 !== 'object') return; - - let duplicate = {}; - - Object.keys(ortb2).forEach((type) => { - let prop = (type === 'site') ? 'context' : type; - duplicate[prop] = (prop === 'context' || prop === 'user') ? Object.keys(ortb2[type]).filter(key => key !== 'data').reduce((result, key) => { - if (key === 'ext') { - mergeDeep(result, ortb2[type][key]); - } else { - mergeDeep(result, {[key]: ortb2[type][key]}); - } - - return result; - }, {}) : ortb2[type]; - }); - - return duplicate; -} - -registerBidder(spec); diff --git a/modules/inmarBidAdapter.md b/modules/inmarBidAdapter.md deleted file mode 100644 index 8ed6b998602..00000000000 --- a/modules/inmarBidAdapter.md +++ /dev/null @@ -1,44 +0,0 @@ -# Overview - -``` -Module Name: Inmar Bidder Adapter -Module Type: Bidder Adapter -Maintainer: oiq_rtb@inmar.com -``` - -# Description - -Connects to Inmar for bids. This adapter supports Display and Video. - -The Inmar adapter requires setup and approval from the Inmar team. -Please reach out to your account manager for more information. - -# Test Parameters - -## Web -``` - var adUnits = [ - { - code: 'test-div1', - sizes: [[300, 250],[300, 600]], - bids: [{ - bidder: 'inmar', - params: { - partnerId: 12345, - position: 1 - } - }] - }, - { - code: 'test-div2', - sizes: [[728, 90],[970, 250]], - bids: [{ - bidder: 'inmar', - params: { - partnerId: 12345, - position: 0 - } - }] - } - ]; -``` diff --git a/modules/innityBidAdapter.js b/modules/innityBidAdapter.js index 71fe588441c..99eec210193 100644 --- a/modules/innityBidAdapter.js +++ b/modules/innityBidAdapter.js @@ -30,6 +30,7 @@ export const spec = { vph: window.screen.height, callback: 'json', callback_uid: bidRequest.bidId, + // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 auction: bidRequest.auctionId, }, }; diff --git a/modules/inskinBidAdapter.js b/modules/inskinBidAdapter.js deleted file mode 100644 index f3464765bde..00000000000 --- a/modules/inskinBidAdapter.js +++ /dev/null @@ -1,391 +0,0 @@ -import { createTrackPixelHtml } from '../src/utils.js'; -import { loadExternalScript } from '../src/adloader.js'; -import { registerBidder } from '../src/adapters/bidderFactory.js'; - -const BIDDER_CODE = 'inskin'; - -const CONFIG = { - BASE_URI: 'https://mfad.inskinad.com/api/v2' -}; - -export const spec = { - code: BIDDER_CODE, - - /** - * Determines whether or not the given bid request is valid. - * - * @param {BidRequest} bid The bid params to validate. - * @return boolean True if this is a valid bid, and false otherwise. - */ - isBidRequestValid: function(bid) { - return !!(bid.params.networkId && bid.params.siteId); - }, - - /** - * Make a server request from the list of BidRequests. - * - * @param {validBidRequests[]} - an array of bids - * @param {bidderRequest} - the full bidder request object - * @return ServerRequest Info describing the request to the server. - */ - - buildRequests: function(validBidRequests, bidderRequest) { - // Do we need to group by bidder? i.e. to make multiple requests for - // different endpoints. - - let ret = { - method: 'POST', - url: '', - data: '', - bidRequest: [] - }; - - if (validBidRequests.length < 1) { - return ret; - } - - let ENDPOINT_URL; - - const data = Object.assign({ - placements: [], - time: Date.now(), - user: {}, - url: bidderRequest.refererInfo.page, - enableBotFiltering: true, - includePricingData: true, - parallel: true - }, validBidRequests[0].params); - - if (validBidRequests[0].schain) { - data.rtb = { - schain: validBidRequests[0].schain - }; - } else if (data.publisherId) { - data.rtb = { - schain: { - ext: { - sid: String(data.publisherId) - } - } - }; - } - - delete data.publisherId; - - data.keywords = data.keywords || []; - const restrictions = []; - - if (bidderRequest && bidderRequest.gdprConsent) { - data.consent = { - gdprVendorId: 150, - gdprConsentString: bidderRequest.gdprConsent.consentString, - // will check if the gdprApplies field was populated with a boolean value (ie from page config). If it's undefined, then default to true - gdprConsentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true - }; - - const purposes = [ - {id: 1, kw: 'nocookies'}, - {id: 2, kw: 'nocontext'}, - {id: 3, kw: 'nodmp'}, - {id: 4, kw: 'nodata'}, - {id: 7, kw: 'noclicks'}, - {id: 9, kw: 'noresearch'} - ]; - - const d = bidderRequest.gdprConsent.vendorData; - - if (d) { - if (d.purposeOneTreatment) { - data.keywords.push('cst-nodisclosure'); - restrictions.push('nodisclosure'); - } - - purposes.map(p => { - if (!checkConsent(p.id, d)) { - data.keywords.push('cst-' + p.kw); - restrictions.push(p.kw); - } - }); - } - } - - validBidRequests.map(bid => { - ENDPOINT_URL = CONFIG.BASE_URI; - - const placement = Object.assign({ - divName: bid.bidId, - adTypes: bid.adTypes || getSize(bid.sizes), - eventIds: [40, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295] - }, bid.params); - - placement.adTypes.push(5, 9, 163, 2163, 3006); - - placement.properties = placement.properties || {}; - - placement.properties.screenWidth = screen.width; - placement.properties.screenHeight = screen.height; - - if (restrictions.length) { - placement.properties.restrictions = restrictions; - } - - if (placement.networkId && placement.siteId) { - data.placements.push(placement); - } - }); - - ret.data = JSON.stringify(data); - ret.bidRequest = validBidRequests; - ret.url = ENDPOINT_URL; - - return ret; - }, - - /** - * Unpack the response from the server into a list of bids. - * - * @param {*} serverResponse A successful response from the server. - * @return {Bid[]} An array of bids which were nested inside the server. - */ - interpretResponse: function(serverResponse, bidRequest) { - let bid; - let bids; - let bidId; - let bidObj; - let bidResponses = []; - let bidsMap = {}; - - bids = bidRequest.bidRequest; - - serverResponse = (serverResponse || {}).body; - for (let i = 0; i < bids.length; i++) { - bid = {}; - bidObj = bids[i]; - bidId = bidObj.bidId; - - bidsMap[bidId] = bidObj; - - if (serverResponse) { - const decision = serverResponse.decisions && serverResponse.decisions[bidId]; - const data = decision && decision.contents && decision.contents[0] && decision.contents[0].data; - const pubCPM = data && data.customData && data.customData.pubCPM; - const clearPrice = decision && decision.pricing && decision.pricing.clearPrice; - const price = pubCPM || clearPrice; - - if (decision && price) { - decision.impressionUrl += ('&property:pubcpm=' + price); - bidObj.price = price; - - bid.requestId = bidId; - bid.cpm = price; - bid.width = decision.width; - bid.height = decision.height; - bid.ad = retrieveAd(bidId, decision); - bid.currency = 'USD'; - bid.creativeId = decision.adId; - bid.ttl = 360; - bid.meta = { advertiserDomains: decision.adomain ? decision.adomain : [] }; - bid.netRevenue = true; - - bidResponses.push(bid); - } - } - } - - if (bidResponses.length) { - window.addEventListener('message', function(e) { - if (!e.data || e.data.from !== 'ism-bid') { - return; - } - - const decision = serverResponse.decisions && serverResponse.decisions[e.data.bidId]; - if (!decision) { - return; - } - - const id = 'ism_tag_' + Math.floor((Math.random() * 10e16)); - window[id] = { - plr_AdSlot: e.source && e.source.frameElement, - bidId: e.data.bidId, - bidPrice: bidsMap[e.data.bidId].price, - serverResponse - }; - - const url = 'https://cdn.inskinad.com/isfe/publishercode/' + bidsMap[e.data.bidId].params.siteId + '/default.js?autoload&id=' + id; - loadExternalScript(url, BIDDER_CODE); - }); - } - - return bidResponses; - }, - - getUserSyncs: function(syncOptions) { - const userSyncs = []; - - if (syncOptions.pixelEnabled) { - userSyncs.push({ - type: 'image', - url: 'https://e.serverbid.com/udb/9969/match?redir=https%3A%2F%2Fmfad.inskinad.com%2Fudb%2F9874%2Fpool%2Fset%2Fi.gif%3FpoolId%3D9969%26poolKey%3D' - }); - userSyncs.push({ - type: 'image', - url: 'https://ssum.casalemedia.com/usermatchredir?s=185638&cb=https%3A%2F%2Fmfad.inskinad.com%2Fudb%2F9874%2Fsync%2Fi.gif%3FpartnerId%3D1%26userId%3D' - }); - } - - if (syncOptions.iframeEnabled) { - userSyncs.push({ - type: 'iframe', - url: 'https://ssum-sec.casalemedia.com/usermatch?s=184665&cb=https%3A%2F%2Fmfad.inskinad.com%2Fudb%2F9874%2Fsync%2Fi.gif%3FpartnerId%3D1%26userId%3D' - }); - } - - return userSyncs; - } -}; - -const sizeMap = [ - null, - '120x90', - '120x90', - '468x60', - '728x90', - '300x250', - '160x600', - '120x600', - '300x100', - '180x150', - '336x280', - '240x400', - '234x60', - '88x31', - '120x60', - '120x240', - '125x125', - '220x250', - '250x250', - '250x90', - '0x0', - '200x90', - '300x50', - '320x50', - '320x480', - '185x185', - '620x45', - '300x125', - '800x250' -]; - -sizeMap[77] = '970x90'; -sizeMap[123] = '970x250'; -sizeMap[43] = '300x600'; - -function getSize(sizes) { - const result = []; - sizes.forEach(function(size) { - const index = sizeMap.indexOf(size[0] + 'x' + size[1]); - if (index >= 0) { - result.push(index); - } - }); - return result; -} - -function retrieveAd(bidId, decision) { - return "'; - -let getDefaultBidResponse = () => { - return { - id: '245730051428950632', - cur: 'USD', - seatbid: [{ - bid: [{ - id: 1, - impid: '245730051428950632', - price: 0.09, - adm: DEFAULT_AD_CONTENT, - crid: 'creative-id', - h: 90, - w: 728, - dealid: 'deal-id', - ext: {sizeid: 225} - }] - }] - }; -}; - -let getMarketplaceBidParams = () => { - return { - placement: 1234567, - network: '9599.1' - }; -}; - -let getNexageGetBidParams = () => { - return { - dcn: '2c9d2b50015c5ce9db6aeeed8b9500d6', - pos: 'header' - }; -}; - -let getNexagePostBidParams = () => { - return { - id: 'id-1', - imp: [{ - id: 'id-2', - banner: { - w: '100', - h: '100' - }, - tagid: 'header1' - }] - }; -}; - -let getDefaultBidRequest = () => { - return { - bidderCode: 'aol', - auctionId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', - bidderRequestId: '7101db09af0db2', - start: new Date().getTime(), - bids: [{ - bidder: 'aol', - bidId: '84ab500420319d', - bidderRequestId: '7101db09af0db2', - auctionId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', - placementCode: 'foo', - params: getMarketplaceBidParams() - }] - }; -}; - -let getPixels = () => { - return ''; -}; - -describe('AolAdapter', function () { - const MARKETPLACE_URL = 'https://adserver-us.adtech.advertising.com/pubapi/3.0/'; - const NEXAGE_URL = 'https://c2shb.ssp.yahoo.com/bidRequest?'; - const ONE_DISPLAY_TTL = 60; - const ONE_MOBILE_TTL = 3600; - const SUPPORTED_USER_ID_SOURCES = { - 'admixer.net': '100', - 'adserver.org': '200', - 'adtelligent.com': '300', - 'amxdt.net': '500', - 'audigent.com': '600', - 'britepool.com': '700', - 'criteo.com': '800', - 'crwdcntrl.net': '900', - 'deepintent.com': '1000', - 'epsilon.com': '1100', - 'hcn.health': '1200', - 'id5-sync.com': '1300', - 'idx.lat': '1400', - 'intentiq.com': '1500', - 'intimatemerger.com': '1600', - 'liveintent.com': '1700', - 'liveramp.com': '1800', - 'mediawallahscript.com': '1900', - 'netid.de': '2100', - 'neustar.biz': '2200', - 'pubcid.org': '2600', - 'quantcast.com': '2700', - 'tapad.com': '2800', - 'zeotap.com': '3200' - }; - - const USER_ID_DATA = { - admixerId: SUPPORTED_USER_ID_SOURCES['admixer.net'], - adtelligentId: SUPPORTED_USER_ID_SOURCES['adtelligent.com'], - amxId: SUPPORTED_USER_ID_SOURCES['amxdt.net'], - britepoolid: SUPPORTED_USER_ID_SOURCES['britepool.com'], - criteoId: SUPPORTED_USER_ID_SOURCES['criteo.com'], - connectid: SUPPORTED_USER_ID_SOURCES['verizonmedia.com'], - dmdId: SUPPORTED_USER_ID_SOURCES['hcn.health'], - hadronId: SUPPORTED_USER_ID_SOURCES['audigent.com'], - lotamePanoramaId: SUPPORTED_USER_ID_SOURCES['crwdcntrl.net'], - deepintentId: SUPPORTED_USER_ID_SOURCES['deepintent.com'], - fabrickId: SUPPORTED_USER_ID_SOURCES['neustar.biz'], - idl_env: SUPPORTED_USER_ID_SOURCES['liveramp.com'], - IDP: SUPPORTED_USER_ID_SOURCES['zeotap.com'], - lipb: { - lipbid: SUPPORTED_USER_ID_SOURCES['liveintent.com'], - segments: ['100', '200'] - }, - tdid: SUPPORTED_USER_ID_SOURCES['adserver.org'], - id5id: { - uid: SUPPORTED_USER_ID_SOURCES['id5-sync.com'], - ext: {foo: 'bar'} - }, - idx: SUPPORTED_USER_ID_SOURCES['idx.lat'], - imuid: SUPPORTED_USER_ID_SOURCES['intimatemerger.com'], - intentIqId: SUPPORTED_USER_ID_SOURCES['intentiq.com'], - mwOpenLinkId: SUPPORTED_USER_ID_SOURCES['mediawallahscript.com'], - netId: SUPPORTED_USER_ID_SOURCES['netid.de'], - quantcastId: SUPPORTED_USER_ID_SOURCES['quantcast.com'], - publinkId: SUPPORTED_USER_ID_SOURCES['epsilon.com'], - pubcid: SUPPORTED_USER_ID_SOURCES['pubcid.org'], - tapadId: SUPPORTED_USER_ID_SOURCES['tapad.com'] - }; - - function createCustomBidRequest({bids, params} = {}) { - var bidderRequest = getDefaultBidRequest(); - if (bids && Array.isArray(bids)) { - bidderRequest.bids = bids; - } - if (params) { - bidderRequest.bids.forEach(bid => bid.params = params); - } - return bidderRequest; - } - - describe('interpretResponse()', function () { - let bidderSettingsBackup; - let bidResponse; - let bidRequest; - let logWarnSpy; - let isOneMobileBidderStub; - - beforeEach(function () { - bidderSettingsBackup = $$PREBID_GLOBAL$$.bidderSettings; - bidRequest = { - bidderCode: 'test-bidder-code', - bidId: 'bid-id', - ttl: 1234 - }; - bidResponse = { - body: getDefaultBidResponse() - }; - logWarnSpy = sinon.spy(utils, 'logWarn'); - isOneMobileBidderStub = sinon.stub(spec, 'isOneMobileBidder'); - }); - - afterEach(function () { - $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsBackup; - logWarnSpy.restore(); - isOneMobileBidderStub.restore(); - }); - - it('should return formatted bid response with required properties', function () { - let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); - expect(formattedBidResponse).to.deep.equal({ - bidderCode: bidRequest.bidderCode, - requestId: 'bid-id', - ad: DEFAULT_AD_CONTENT, - cpm: 0.09, - width: 728, - height: 90, - creativeId: 'creative-id', - pubapiId: '245730051428950632', - currency: 'USD', - dealId: 'deal-id', - netRevenue: true, - meta: { - advertiserDomains: [] - }, - ttl: bidRequest.ttl - }); - }); - }); - - describe('buildRequests()', function () { - it('method exists and is a function', function () { - expect(spec.buildRequests).to.exist.and.to.be.a('function'); - }); - - describe('Marketplace', function () { - it('should not return request when no bids are present', function () { - let [request] = spec.buildRequests([]); - expect(request).to.be.undefined; - }); - - it('should return request for Marketplace endpoint', function () { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); - }); - - it('should return request for Marketplace via onedisplay bidder code', function () { - let bidRequest = createCustomBidRequest({ - bids: [{ - bidder: 'onedisplay' - }], - params: getMarketplaceBidParams() - }); - - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); - }); - - it('should return Marketplace request via onedisplay bidder code when' + - 'Marketplace and One Mobile GET params are present', () => { - let bidParams = Object.assign(getMarketplaceBidParams(), getNexageGetBidParams()); - let bidRequest = createCustomBidRequest({ - bids: [{ - bidder: 'onedisplay' - }], - params: bidParams - }); - - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); - }); - - it('should return Marketplace request via onedisplay bidder code when' + - 'Marketplace and One Mobile GET + POST params are present', () => { - let bidParams = Object.assign(getMarketplaceBidParams(), getNexageGetBidParams(), getNexagePostBidParams()); - let bidRequest = createCustomBidRequest({ - bids: [{ - bidder: 'onedisplay' - }], - params: bidParams - }); - - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); - }); - - it('should not resolve endpoint for onedisplay bidder code ' + - 'when only One Mobile params are present', () => { - let bidParams = Object.assign(getNexageGetBidParams(), getNexagePostBidParams()); - let bidRequest = createCustomBidRequest({ - bids: [{ - bidder: 'onedisplay' - }], - params: bidParams - }); - - let [request] = spec.buildRequests(bidRequest.bids); - expect(request).to.be.undefined; - }); - - it('should return Marketplace URL for eu region', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - region: 'eu' - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf('https://adserver-eu.adtech.advertising.com/pubapi/3.0/')) - .to.equal(0); - }); - - it('should return insecure MP URL if insecure server option is present', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - server: 'https://adserver-eu.adtech.advertising.com' - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf('https://adserver-eu.adtech.advertising.com/pubapi/3.0/')) - .to.equal(0); - }); - - it('should return a secure MP URL if relative proto server option is present', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - server: 'https://adserver-eu.adtech.advertising.com' - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf('https://adserver-eu.adtech.advertising.com/pubapi/3.0/')) - .to.equal(0); - }); - - it('should return a secure MP URL when server option without protocol is present', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - server: 'adserver-eu.adtech.advertising.com' - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf('https://adserver-eu.adtech.advertising.com/pubapi/3.0/')) - .to.equal(0); - }); - - it('should return default Marketplace URL in case of unknown region config option', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - region: 'an' - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url.indexOf(MARKETPLACE_URL)).to.equal(0); - }); - - it('should return url with pubapi bid option', function () { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('cmd=bid;'); - }); - - it('should return url with version 2 of pubapi', function () { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('v=2;'); - }); - - it('should return url with cache busting option', function () { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.match(/misc=\d+/); - }); - - it('should return url with default pageId and sizeId', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1' - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('/pubapi/3.0/9599.1/1234567/0/0/ADTECH;'); - }); - - it('should return url with custom pageId and sizeId when options are present', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - pageId: 1111, - sizeId: 2222 - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('/pubapi/3.0/9599.1/1234567/1111/2222/ADTECH;'); - }); - - it('should return url with default alias if alias param is missing', function () { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.match(/alias=\w+?;/); - }); - - it('should return url with custom alias if it is present', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - alias: 'desktop_articlepage_something_box_300_250' - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('alias=desktop_articlepage_something_box_300_250'); - }); - - it('should return url without bidfloor option if is is missing', function () { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).not.to.contain('bidfloor='); - }); - - it('should return url with key values if keyValues param is present', function () { - let bidRequest = createCustomBidRequest({ - params: { - placement: 1234567, - network: '9599.1', - keyValues: { - age: 25, - height: 3.42, - test: 'key' - } - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('kvage=25;kvheight=3.42;kvtest=key'); - }); - - it('should return request object for One Display when configuration is present', function () { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.method).to.equal('GET'); - expect(request.ttl).to.equal(ONE_DISPLAY_TTL); - }); - }); - - describe('One Mobile', function () { - it('should return One Mobile url when One Mobile get params are present', function () { - let bidRequest = createCustomBidRequest({ - params: getNexageGetBidParams() - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(NEXAGE_URL); - }); - - it('should return One Mobile url with different host when host option is present', function () { - let bidParams = Object.assign({ - host: 'https://qa-hb.nexage.com' - }, getNexageGetBidParams()); - let bidRequest = createCustomBidRequest({ - params: bidParams - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('https://qa-hb.nexage.com/bidRequest?'); - }); - - it('should return One Mobile url when One Mobile and Marketplace params are present', function () { - let bidParams = Object.assign(getNexageGetBidParams(), getMarketplaceBidParams()); - let bidRequest = createCustomBidRequest({ - params: bidParams - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(NEXAGE_URL); - }); - - it('should return One Mobile url for onemobile bidder code ' + - 'when One Mobile GET and Marketplace params are present', () => { - let bidParams = Object.assign(getNexageGetBidParams(), getMarketplaceBidParams()); - let bidRequest = createCustomBidRequest({ - bids: [{ - bidder: 'onemobile' - }], - params: bidParams - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(NEXAGE_URL); - }); - - it('should not return any url for onemobile bidder code' + - 'when only Marketplace params are present', () => { - let bidRequest = createCustomBidRequest({ - bids: [{ - bidder: 'onemobile' - }], - params: getMarketplaceBidParams() - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request).to.be.undefined; - }); - - it('should return One Mobile url with required params - dcn & pos', function () { - let bidRequest = createCustomBidRequest({ - params: getNexageGetBidParams() - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(NEXAGE_URL + 'dcn=2c9d2b50015c5ce9db6aeeed8b9500d6&pos=header'); - }); - - it('should return One Mobile url with configured GPP data', function () { - let bidRequest = createCustomBidRequest({ - params: getNexageGetBidParams() - }); - bidRequest.ortb2 = { - regs: { - gpp: 'testgpp', - gpp_sid: [8] - } - } - let [request] = spec.buildRequests(bidRequest.bids, bidRequest); - expect(request.url).to.contain('gpp=testgpp&gpp_sid=8'); - }); - - it('should return One Mobile url with cmd=bid option', function () { - let bidRequest = createCustomBidRequest({ - params: getNexageGetBidParams() - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('cmd=bid'); - }); - - it('should return One Mobile url with generic params if ext option is present', function () { - let bidRequest = createCustomBidRequest({ - params: { - dcn: '54321123', - pos: 'footer-2324', - ext: { - param1: 'val1', - param2: 'val2', - param3: 'val3', - param4: 'val4' - } - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.equal('https://c2shb.ssp.yahoo.com/bidRequest?dcn=54321123&pos=footer-2324&cmd=bid' + - '¶m1=val1¶m2=val2¶m3=val3¶m4=val4'); - }); - - Object.keys(SUPPORTED_USER_ID_SOURCES).forEach(source => { - it(`should set the user ID query param for ${source}`, function () { - let bidRequest = createCustomBidRequest({ - params: getNexageGetBidParams() - }); - bidRequest.bids[0].userId = {}; - bidRequest.bids[0].userIdAsEids = createEidsArray(USER_ID_DATA); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(`&eid${source}=${encodeURIComponent(SUPPORTED_USER_ID_SOURCES[source])}`); - }); - }); - - it('should return request object for One Mobile POST endpoint when POST configuration is present', function () { - let bidConfig = getNexagePostBidParams(); - let bidRequest = createCustomBidRequest({ - params: bidConfig - }); - - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(NEXAGE_URL); - expect(request.method).to.equal('POST'); - expect(request.ttl).to.equal(ONE_MOBILE_TTL); - expect(request.data).to.deep.equal(bidConfig); - expect(request.options).to.deep.equal({ - contentType: 'application/json', - customHeaders: { - 'x-openrtb-version': '2.2' - } - }); - }); - - it('should not return request object for One Mobile POST endpoint' + - 'if required parameters are missed', () => { - let bidRequest = createCustomBidRequest({ - params: { - imp: [] - } - }); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request).to.be.undefined; - }); - }); - }); - - describe('buildOpenRtbRequestData', () => { - const bid = { - params: { - id: 'bid-id', - imp: [] - } - }; - let euConsentRequiredStub; - - beforeEach(function () { - euConsentRequiredStub = sinon.stub(spec, 'isEUConsentRequired'); - }); - - afterEach(function () { - euConsentRequiredStub.restore(); - }); - - it('returns the basic bid info when regulation data is omitted', () => { - expect(spec.buildOpenRtbRequestData(bid)).to.deep.equal({ - id: 'bid-id', - imp: [] - }); - }); - - it('returns the basic bid info with gdpr data when gdpr consent data is included', () => { - let consentData = { - gdpr: { - consentString: 'someEUConsent' - } - }; - euConsentRequiredStub.returns(true); - expect(spec.buildOpenRtbRequestData(bid, consentData)).to.deep.equal({ - id: 'bid-id', - imp: [], - regs: { - ext: { - gdpr: 1 - } - }, - user: { - ext: { - consent: 'someEUConsent' - } - } - }); - }); - - it('returns the basic bid info with CCPA data when CCPA consent data is included', () => { - let consentData = { - uspConsent: 'someUSPConsent' - }; - expect(spec.buildOpenRtbRequestData(bid, consentData)).to.deep.equal({ - id: 'bid-id', - imp: [], - regs: { - ext: { - us_privacy: 'someUSPConsent' - } - } - }); - }); - - it('returns the basic bid info with GDPR and CCPA data when GDPR and CCPA consent data is included', () => { - let consentData = { - gdpr: { - consentString: 'someEUConsent' - }, - uspConsent: 'someUSPConsent' - }; - euConsentRequiredStub.returns(true); - expect(spec.buildOpenRtbRequestData(bid, consentData)).to.deep.equal({ - id: 'bid-id', - imp: [], - regs: { - ext: { - gdpr: 1, - us_privacy: 'someUSPConsent' - } - }, - user: { - ext: { - consent: 'someEUConsent' - } - } - }); - }); - - it('returns the bid object with eid array populated with PB set eids', () => { - let userIdBid = Object.assign({ - userId: {} - }, bid); - userIdBid.userIdAsEids = createEidsArray(USER_ID_DATA); - expect(spec.buildOpenRtbRequestData(userIdBid)).to.deep.equal({ - id: 'bid-id', - imp: [], - user: { - ext: { - eids: userIdBid.userIdAsEids - } - } - }); - }); - }); - - describe('getUserSyncs()', function () { - let serverResponses; - let bidResponse; - - beforeEach(function () { - bidResponse = getDefaultBidResponse(); - bidResponse.ext = { - pixels: getPixels() - }; - - serverResponses = [ - {body: bidResponse} - ]; - }); - - it('should return user syncs if pixels are present in the response', function () { - let userSyncs = spec.getUserSyncs({}, serverResponses); - - expect(userSyncs).to.deep.equal([ - {type: 'image', url: 'img.org'}, - {type: 'iframe', url: 'pixels1.org'} - ]); - }); - - it('should not return user syncs if pixels are not present', function () { - bidResponse.ext.pixels = null; - let userSyncs = spec.getUserSyncs({}, serverResponses); - - expect(userSyncs).to.deep.equal([]); - }); - }); - - describe('isOneMobileBidder()', function () { - it('should return false when when bidderCode is not present', () => { - expect(spec.isOneMobileBidder(null)).to.be.false; - }); - - it('should return false for unknown bidder code', function () { - expect(spec.isOneMobileBidder('unknownBidder')).to.be.false; - }); - - it('should return true for aol bidder code', function () { - expect(spec.isOneMobileBidder('aol')).to.be.true; - }); - - it('should return true for one mobile bidder code', function () { - expect(spec.isOneMobileBidder('onemobile')).to.be.true; - }); - }); - - describe('isEUConsentRequired()', function () { - it('should return false when consentData object is not present', function () { - expect(spec.isEUConsentRequired(null)).to.be.false; - }); - - it('should return true when gdprApplies equals true and consentString is not present', function () { - let consentData = { - gdpr: { - consentString: null, - gdprApplies: true - } - }; - - expect(spec.isEUConsentRequired(consentData)).to.be.true; - }); - - it('should return false when consentString is present and gdprApplies equals false', function () { - let consentData = { - gdpr: { - consentString: 'consent-string', - gdprApplies: false - } - }; - - expect(spec.isEUConsentRequired(consentData)).to.be.false; - }); - - it('should return true when consentString is present and gdprApplies equals true', function () { - let consentData = { - gdpr: { - consentString: 'consent-string', - gdprApplies: true - } - }; - - expect(spec.isEUConsentRequired(consentData)).to.be.true; - }); - }); - - describe('formatMarketplaceDynamicParams()', function () { - let formatConsentDataStub; - let formatKeyValuesStub; - - beforeEach(function () { - formatConsentDataStub = sinon.stub(spec, 'formatConsentData'); - formatKeyValuesStub = sinon.stub(spec, 'formatKeyValues'); - }); - - afterEach(function () { - formatConsentDataStub.restore(); - formatKeyValuesStub.restore(); - }); - - it('should return empty string when params are not present', function () { - expect(spec.formatMarketplaceDynamicParams()).to.be.equal(''); - }); - - it('should return formatted EU consent params when formatConsentData returns GDPR data', function () { - formatConsentDataStub.returns({ - euconsent: 'test-consent', - gdpr: 1 - }); - expect(spec.formatMarketplaceDynamicParams()).to.be.equal('euconsent=test-consent;gdpr=1;'); - }); - - it('should return formatted US privacy params when formatConsentData returns USP data', function () { - formatConsentDataStub.returns({ - us_privacy: 'test-usp-consent' - }); - expect(spec.formatMarketplaceDynamicParams()).to.be.equal('us_privacy=test-usp-consent;'); - }); - - it('should return formatted EU and USP consent params when formatConsentData returns all data', function () { - formatConsentDataStub.returns({ - euconsent: 'test-consent', - gdpr: 1, - us_privacy: 'test-usp-consent' - }); - expect(spec.formatMarketplaceDynamicParams()).to.be.equal( - 'euconsent=test-consent;gdpr=1;us_privacy=test-usp-consent;'); - }); - - it('should return formatted gpp privacy params when formatConsentData returns GPP data', function () { - formatConsentDataStub.returns({ - gpp: 'gppstring', - gpp_sid: [6, 7] - }); - expect(spec.formatMarketplaceDynamicParams()).to.be.equal('gpp=gppstring;gpp_sid=6%2C7;'); - }); - - it('should return formatted params when formatKeyValues returns data', function () { - formatKeyValuesStub.returns({ - param1: 'val1', - param2: 'val2', - param3: 'val3' - }); - expect(spec.formatMarketplaceDynamicParams()).to.be.equal('param1=val1;param2=val2;param3=val3;'); - }); - }); - - describe('formatOneMobileDynamicParams()', function () { - let euConsentRequiredStub; - let secureProtocolStub; - - beforeEach(function () { - euConsentRequiredStub = sinon.stub(spec, 'isEUConsentRequired'); - secureProtocolStub = sinon.stub(spec, 'isSecureProtocol'); - }); - - afterEach(function () { - euConsentRequiredStub.restore(); - secureProtocolStub.restore(); - }); - - it('should return empty string when params are not present', function () { - expect(spec.formatOneMobileDynamicParams()).to.be.equal(''); - }); - - it('should return formatted params when params are present', function () { - let params = { - param1: 'val1', - param2: 'val2', - param3: 'val3' - }; - expect(spec.formatOneMobileDynamicParams(params)).to.contain('¶m1=val1¶m2=val2¶m3=val3'); - }); - - it('should return formatted gdpr params when isEUConsentRequired returns true', function () { - let consentData = { - gdpr: { - consentString: 'test-consent' - } - }; - euConsentRequiredStub.returns(true); - expect(spec.formatOneMobileDynamicParams({}, consentData)).to.be.equal('&gdpr=1&euconsent=test-consent'); - }); - - it('should return formatted US privacy params when consentData contains USP data', function () { - let consentData = { - uspConsent: 'test-usp-consent' - }; - expect(spec.formatMarketplaceDynamicParams({}, consentData)).to.be.equal('us_privacy=test-usp-consent;'); - }); - - it('should return formatted EU and USP consent params when consentData contains gdpr and usp values', function () { - euConsentRequiredStub.returns(true); - let consentData = { - gdpr: { - consentString: 'test-consent' - }, - uspConsent: 'test-usp-consent' - }; - expect(spec.formatMarketplaceDynamicParams({}, consentData)).to.be.equal( - 'gdpr=1;euconsent=test-consent;us_privacy=test-usp-consent;'); - }); - - it('should return formatted secure param when isSecureProtocol returns true', function () { - secureProtocolStub.returns(true); - expect(spec.formatOneMobileDynamicParams()).to.be.equal('&secure=1'); - }); - }); -}); diff --git a/test/spec/modules/apacdexBidAdapter_spec.js b/test/spec/modules/apacdexBidAdapter_spec.js index 773c9925d58..98d07575ee7 100644 --- a/test/spec/modules/apacdexBidAdapter_spec.js +++ b/test/spec/modules/apacdexBidAdapter_spec.js @@ -321,9 +321,9 @@ describe('ApacdexBidAdapter', function () { const bidRequests = spec.buildRequests(bidRequest, bidderRequests); expect(bidRequests.data.eids).to.deep.equal(bidRequest[0].userIdAsEids) }); - it('should return a properly formatted request with geo defined', function () { + it('should fail to return a properly formatted request with geo defined', function () { const bidRequests = spec.buildRequests(bidRequest, bidderRequests); - expect(bidRequests.data.geo).to.deep.equal(bidRequest[0].params.geo) + expect(bidRequests.data.geo).to.not.deep.equal(bidRequest[0].params.geo) }); it('should return a properly formatted request with us_privacy included', function () { const bidRequests = spec.buildRequests(bidRequest, bidderRequests); diff --git a/test/spec/modules/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index 1603c6e9397..13ef31a68d4 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -18,6 +18,18 @@ describe('AppNexusAdapter', function () { }); }); + function expectKeywords(actual, expected) { + expect(actual.length).to.equal(expected.length); + actual.forEach(el => { + const match = expected.find(ob => ob.key === el.key); + if (el.value) { + expect(el.value).to.have.members(match.value); + } else { + expect(match.value).to.not.exist; + } + }) + } + describe('isBidRequestValid', function () { let bid = { 'bidder': 'appnexus', @@ -737,7 +749,7 @@ describe('AppNexusAdapter', function () { const request = spec.buildRequests([bidRequest], bidderRequest); const payload = JSON.parse(request.data); - expect(payload.keywords).to.deep.equal([{ + expectKeywords(payload.keywords, [{ 'key': 'gender', 'value': ['m'] }, { @@ -772,6 +784,69 @@ describe('AppNexusAdapter', function () { config.getConfig.restore(); }); + it('adds ortb2 segments to auction request as keywords', function() { + let bidRequest = Object.assign({}, bidRequests[0]); + const bidderRequest = { + ortb2: { + site: { + keywords: 'drill', + content: { + data: [{ + name: 'siteseg1', + ext: { + segtax: 540 + }, + segment: [{ + id: 's123', + }, { + id: 's234' + }] + }, { + name: 'sitseg2', + ext: { + segtax: 1 + }, + segment: [{ + id: 'unknown' + }] + }, { + name: 'siteseg3', + ext: { + segtax: 526 + }, + segment: [{ + id: 'dog' + }] + }] + } + }, + user: { + data: [{ + name: 'userseg1', + ext: { + segtax: 526 + }, + segment: [{ + id: 'cat' + }] + }] + } + } + }; + const request = spec.buildRequests([bidRequest], bidderRequest); + const payload = JSON.parse(request.data); + + expectKeywords(payload.keywords, [{ + 'key': 'drill' + }, { + 'key': '1plusX', + 'value': ['cat', 'dog'] + }, { + 'key': 'perid', + 'value': ['s123', 's234'] + }]); + }); + if (FEATURES.NATIVE) { it('should attach native params to the request', function () { let bidRequest = Object.assign({}, @@ -872,26 +947,28 @@ describe('AppNexusAdapter', function () { const request = spec.buildRequests([bidRequest]); const payload = JSON.parse(request.data); - expect(payload.tags[0].keywords).to.deep.equal([{ - 'key': 'single', - 'value': ['val'] - }, { - 'key': 'singleArr', - 'value': ['val'] - }, { - 'key': 'singleArrNum', - 'value': ['5'] - }, { - 'key': 'multiValMixed', - 'value': ['value1', '2', 'value3'] - }, { - 'key': 'singleValNum', - 'value': ['123'] - }, { - 'key': 'emptyStr' - }, { - 'key': 'emptyArr' - }]); + expectKeywords(payload.tags[0].keywords, [ + { + 'key': 'single', + 'value': ['val'] + }, { + 'key': 'singleArr', + 'value': ['val'] + }, { + 'key': 'singleArrNum', + 'value': ['5'] + }, { + 'key': 'multiValMixed', + 'value': ['value1', '2', 'value3'] + }, { + 'key': 'singleValNum', + 'value': ['123'] + }, { + 'key': 'emptyStr' + }, { + 'key': 'emptyArr' + } + ]) }); it('should convert adUnit ortb2 keywords (when there are no bid param keywords) to proper form and attaches to request', function () { @@ -911,7 +988,7 @@ describe('AppNexusAdapter', function () { const request = spec.buildRequests([bidRequest]); const payload = JSON.parse(request.data); - expect(payload.tags[0].keywords).to.deep.equal([{ + expectKeywords(payload.tags[0].keywords, [{ 'key': 'ortb2', 'value': ['yes'] }, { @@ -955,7 +1032,7 @@ describe('AppNexusAdapter', function () { const request = spec.buildRequests([bidRequest]); const payload = JSON.parse(request.data); - expect(payload.tags[0].keywords).to.deep.equal([{ + expectKeywords(payload.tags[0].keywords, [{ 'key': 'single', 'value': ['val'] }, { @@ -1451,16 +1528,13 @@ describe('AppNexusAdapter', function () { }) describe('interpretResponse', function () { - let bfStub; let bidderSettingsStorage; before(function () { - bfStub = sinon.stub(bidderFactory, 'getIabSubCategory'); bidderSettingsStorage = $$PREBID_GLOBAL$$.bidderSettings; }); after(function () { - bfStub.restore(); $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsStorage; }); @@ -1707,7 +1781,6 @@ describe('AppNexusAdapter', function () { } }] }; - bfStub.returns('1'); let result = spec.interpretResponse({ body: response }, { bidderRequest }); expect(result[0]).to.have.property('vastUrl'); diff --git a/test/spec/modules/astraoneBidAdapter_spec.js b/test/spec/modules/astraoneBidAdapter_spec.js index 0e545081869..80d6dcdf627 100644 --- a/test/spec/modules/astraoneBidAdapter_spec.js +++ b/test/spec/modules/astraoneBidAdapter_spec.js @@ -8,7 +8,11 @@ function getSlotConfigs(mediaTypes, params) { bidId: '2df8c0733f284e', bidder: 'astraone', mediaTypes: mediaTypes, - transactionId: '31a58515-3634-4e90-9c96-f86196db1459' + ortb2Imp: { + ext: { + tid: '31a58515-3634-4e90-9c96-f86196db1459' + } + } } } diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index addd4304c7d..4e30b822a61 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -695,7 +695,6 @@ describe('BeachfrontAdapter', function () { const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); expect(bidResponse).to.deep.equal({ requestId: bidRequest.bidId, - bidderCode: spec.code, cpm: serverResponse.bidPrice, creativeId: serverResponse.crid, vastUrl: serverResponse.url, diff --git a/test/spec/modules/big-richmediaBidAdapter_spec.js b/test/spec/modules/big-richmediaBidAdapter_spec.js index f01e261ef9f..c3a9a8ef6c1 100644 --- a/test/spec/modules/big-richmediaBidAdapter_spec.js +++ b/test/spec/modules/big-richmediaBidAdapter_spec.js @@ -131,16 +131,6 @@ describe('bigRichMediaAdapterTests', function () { }); describe('interpretResponse', function () { - let bfStub; - - before(function() { - bfStub = sinon.stub(bidderFactory, 'getIabSubCategory'); - }); - - after(function() { - bfStub.restore(); - }); - const response = { 'version': '3.0.0', 'tags': [ diff --git a/test/spec/modules/bluebillywigBidAdapter_spec.js b/test/spec/modules/bluebillywigBidAdapter_spec.js index 0826acc7f29..4b58e3507db 100644 --- a/test/spec/modules/bluebillywigBidAdapter_spec.js +++ b/test/spec/modules/bluebillywigBidAdapter_spec.js @@ -1,10 +1,8 @@ -import { expect } from 'chai'; -import { spec } from 'modules/bluebillywigBidAdapter.js'; -import * as bidderFactory from 'src/adapters/bidderFactory.js'; -import { auctionManager } from 'src/auctionManager.js'; -import { deepClone, deepAccess } from 'src/utils.js'; -import { config } from 'src/config.js'; -import { VIDEO } from 'src/mediaTypes.js'; +import {expect} from 'chai'; +import {spec} from 'modules/bluebillywigBidAdapter.js'; +import {deepAccess, deepClone} from 'src/utils.js'; +import {config} from 'src/config.js'; +import {VIDEO} from 'src/mediaTypes.js'; const BB_CONSTANTS = { BIDDER_CODE: 'bluebillywig', @@ -254,7 +252,11 @@ describe('BlueBillywigAdapter', () => { const baseValidBidRequests = [baseValidBid]; const validBidderRequest = { - auctionId: '12abc345-67d8-9012-e345-6f78901a2b34', + ortb2: { + source: { + tid: '12abc345-67d8-9012-e345-6f78901a2b34', + } + }, auctionStart: 1585918458868, bidderCode: BB_CONSTANTS.BIDDER_CODE, bidderRequestId: '1a2345b67c8d9e0', @@ -293,9 +295,9 @@ describe('BlueBillywigAdapter', () => { const request = spec.buildRequests(baseValidBidRequests, validBidderRequest); const payload = JSON.parse(request.data); - expect(payload.id).to.equal(validBidderRequest.auctionId); + expect(payload.id).to.exist; expect(payload.source).to.be.an('object'); - expect(payload.source.tid).to.equal(validBidderRequest.auctionId); + expect(payload.source.tid).to.equal(validBidderRequest.ortb2.source.tid); expect(payload.tmax).to.equal(BB_CONSTANTS.DEFAULT_TIMEOUT); expect(payload.imp).to.be.an('array'); expect(payload.test).to.be.a('number'); diff --git a/test/spec/modules/browsiBidAdapter_spec.js b/test/spec/modules/browsiBidAdapter_spec.js index 8892396adac..9693972fd7f 100644 --- a/test/spec/modules/browsiBidAdapter_spec.js +++ b/test/spec/modules/browsiBidAdapter_spec.js @@ -64,7 +64,11 @@ describe('browsi Bid Adapter Test', function () { 'sizes': [640, 480], 'bidId': '12345678', 'requestId': '1234567-3456-4562-7689-98765434A', - 'transactionId': '1234567-3456-4562-7689-98765434B', + ortb2Imp: { + ext: { + tid: '1234567-3456-4562-7689-98765434B', + } + }, 'schain': {}, 'mediaTypes': {video: {playerSize: [640, 480]}} } @@ -112,7 +116,7 @@ describe('browsi Bid Adapter Test', function () { video: {playerSize: [640, 480]}, aUCode: inputRequest.adUnitCode, aID: inputRequest.auctionId, - tID: inputRequest.transactionId, + tID: inputRequest.ortb2Imp.ext.tid, schain: inputRequest.schain, params: inputRequest.params } @@ -157,7 +161,6 @@ describe('browsi Bid Adapter Test', function () { const actualBidResponse = bidResponses[0]; const expectedBidResponse = { requestId: bidRequest.data.bidId, - bidderCode: 'browsi', bidId: 'bidId1', width: 300, height: 250, diff --git a/test/spec/modules/emx_digitalBidAdapter_spec.js b/test/spec/modules/cadentApertureMXBidAdapter_spec.js similarity index 97% rename from test/spec/modules/emx_digitalBidAdapter_spec.js rename to test/spec/modules/cadentApertureMXBidAdapter_spec.js index d80d0f3e875..091a8105354 100644 --- a/test/spec/modules/emx_digitalBidAdapter_spec.js +++ b/test/spec/modules/cadentApertureMXBidAdapter_spec.js @@ -1,9 +1,9 @@ import { expect } from 'chai'; -import { spec } from 'modules/emx_digitalBidAdapter.js'; +import { spec } from 'modules/cadentApertureMXBidAdapter.js'; import * as utils from 'src/utils.js'; import { newBidder } from 'src/adapters/bidderFactory.js'; -describe('emx_digital Adapter', function () { +describe('cadent_aperture_mx Adapter', function () { describe('callBids', function () { const adapter = newBidder(spec); it('exists and is a function', function () { @@ -14,7 +14,7 @@ describe('emx_digital Adapter', function () { describe('isBidRequestValid', function () { describe('banner request validity', function () { let bid = { - 'bidder': 'emx_digital', + 'bidder': 'cadent_aperture_mx', 'params': { 'tagid': '25251' }, @@ -33,7 +33,7 @@ describe('emx_digital Adapter', function () { 'auctionId': '1d1a01234a475' }; let badBid = { - 'bidder': 'emx_digital', + 'bidder': 'cadent_aperture_mx', 'params': { 'tagid': '25251' }, @@ -95,7 +95,7 @@ describe('emx_digital Adapter', function () { describe('video request validity', function () { let bid = { - 'bidder': 'emx_digital', + 'bidder': 'cadent_aperture_mx', 'params': { 'tagid': '25251', 'video': {} @@ -116,7 +116,7 @@ describe('emx_digital Adapter', function () { 'auctionId': '1d1a01234a475' }; let noInstreamBid = { - 'bidder': 'emx_digital', + 'bidder': 'cadent_aperture_mx', 'params': { 'tagid': '25251', 'video': { @@ -139,7 +139,7 @@ describe('emx_digital Adapter', function () { }; let outstreamBid = { - 'bidder': 'emx_digital', + 'bidder': 'cadent_aperture_mx', 'params': { 'tagid': '25251', 'video': {} @@ -168,7 +168,7 @@ describe('emx_digital Adapter', function () { it('should contain tagid param', function () { expect(spec.isBidRequestValid({ - bidder: 'emx_digital', + bidder: 'cadent_aperture_mx', params: {}, mediaTypes: { banner: { @@ -177,7 +177,7 @@ describe('emx_digital Adapter', function () { } })).to.equal(false); expect(spec.isBidRequestValid({ - bidder: 'emx_digital', + bidder: 'cadent_aperture_mx', params: { tagid: '' }, @@ -188,7 +188,7 @@ describe('emx_digital Adapter', function () { } })).to.equal(false); expect(spec.isBidRequestValid({ - bidder: 'emx_digital', + bidder: 'cadent_aperture_mx', params: { tagid: '123' }, @@ -204,7 +204,7 @@ describe('emx_digital Adapter', function () { describe('buildRequests', function () { let bidderRequest = { - 'bidderCode': 'emx_digital', + 'bidderCode': 'cadent_aperture_mx', 'auctionId': 'e19f1eff-8b27-42a6-888d-9674e5a6130c', 'bidderRequestId': '22edbae3120bf6', 'timeout': 1500, @@ -216,7 +216,7 @@ describe('emx_digital Adapter', function () { 'ref': 'https://referrer.com' }, 'bids': [{ - 'bidder': 'emx_digital', + 'bidder': 'cadent_aperture_mx', 'params': { 'tagid': '25251' }, @@ -464,7 +464,7 @@ describe('emx_digital Adapter', function () { describe('interpretResponse', function () { let bid = { - 'bidder': 'emx_digital', + 'bidder': 'cadent_aperture_mx', 'params': { 'tagid': '25251', 'video': {} @@ -488,7 +488,7 @@ describe('emx_digital Adapter', function () { const bid_outstream = { 'bidderRequest': { 'bids': [{ - 'bidder': 'emx_digital', + 'bidder': 'cadent_aperture_mx', 'params': { 'tagid': '25251', 'video': {} @@ -508,7 +508,7 @@ describe('emx_digital Adapter', function () { 'bidderRequestId': '22edbae3120bf6', 'auctionId': '1d1a01234a475' }, { - 'bidder': 'emx_digital', + 'bidder': 'cadent_aperture_mx', 'params': { 'tagid': '25252', 'video': {} @@ -700,7 +700,7 @@ describe('emx_digital Adapter', function () { it('should not throw an error when decoding an improperly encoded adm', function () { const badAdmServerResponse = utils.deepClone(serverResponse); badAdmServerResponse.seatbid[0].bid[0].adm = '\\<\\/script\\>'; - badAdmServerResponse.seatbid[1].bid[0].adm = '%3F%%3Demx%3C3prebid'; + badAdmServerResponse.seatbid[1].bid[0].adm = '%3F%%3Dcadent%3C3prebid'; assert.doesNotThrow(() => spec.interpretResponse({ body: badAdmServerResponse diff --git a/test/spec/modules/captifyRtdProvider_spec.js b/test/spec/modules/captifyRtdProvider_spec.js deleted file mode 100644 index 2e1052e000f..00000000000 --- a/test/spec/modules/captifyRtdProvider_spec.js +++ /dev/null @@ -1,253 +0,0 @@ -import {addSegmentData, captifySubmodule, getMatchingBidders, setCaptifyTargeting} from 'modules/captifyRtdProvider.js'; -import {server} from 'test/mocks/xhr.js'; -import {config} from 'src/config.js'; -import {deepAccess} from '../../../src/utils'; - -const responseHeader = {'Content-Type': 'application/json'}; -const defaultRequestUrl = 'https://live-classification.cpx.to/prebid-segments'; - -describe('captifyRtdProvider', function () { - describe('init function', function () { - it('successfully instantiates, when configured properly', function () { - const config = { - params: { - pubId: 123456, - bidders: ['appnexus'], - } - }; - expect(captifySubmodule.init(config, null)).to.equal(true); - }); - - it('return false on init, when config is invalid', function () { - const config = { - params: {} - }; - expect(captifySubmodule.init(config, null)).to.equal(false); - expect(captifySubmodule.init(null, null)).to.equal(false); - }); - - it('return false on init, when pubId is absent', function () { - const config = { - params: { - bidders: ['appnexus'], - } - }; - expect(captifySubmodule.init(config, null)).to.equal(false); - expect(captifySubmodule.init(null, null)).to.equal(false); - }); - - it('return false on init, when bidders is empty array', function () { - const config = { - params: { - bidders: [], - pubId: 123, - } - }; - expect(captifySubmodule.init(config, null)).to.equal(false); - expect(captifySubmodule.init(null, null)).to.equal(false); - }); - }); - - describe('addSegmentData function', function () { - it('adds segment data', function () { - config.resetConfig(); - - let data = { - xandr: [111111, 222222], - }; - - addSegmentData(['appnexus'], data); - expect(deepAccess(config.getConfig(), 'appnexusAuctionKeywords.captify_segments')).to.eql(data['xandr']); - }); - }); - - describe('getMatchingBidders function', function () { - it('returns only bidders that used within adUnits', function () { - const moduleConfig = { - params: { - pubId: 123, - bidders: ['appnexus', 'pubmatic'], - } - }; - let reqBidsConfigObj = { - adUnits: [{ - bids: [{ - bidder: 'appnexus', - params: { - placementId: 13144370 - } - }] - }] - }; - - let matchedBidders = getMatchingBidders(moduleConfig, reqBidsConfigObj); - expect(matchedBidders).to.eql(['appnexus']); - }); - - it('return empty result, when there are no bidders configured for adUnits', function () { - const moduleConfig = { - params: { - pubId: 123, - bidders: ['pubmatic'], - } - }; - let reqBidsConfigObj = { - adUnits: [{ - bids: [] - }] - }; - expect(getMatchingBidders(moduleConfig, reqBidsConfigObj)).to.be.empty; - }); - - it('return empty result, when there are no bidders matched', function () { - const moduleConfig = { - params: { - pubId: 123, - bidders: ['pubmatic'], - } - }; - let reqBidsConfigObj = { - adUnits: [{ - bids: [{ - params: { - bidder: 'appnexus', - placementId: 13144370, - } - }] - }] - }; - expect(getMatchingBidders(moduleConfig, reqBidsConfigObj)).to.be.empty; - }); - - it('return empty result, when there are no adUnits with bidders', function () { - const moduleConfig = { - params: { - pubId: 123, - bidders: ['pubmatic'], - } - }; - let reqBidsConfigObj = { - adUnits: [{ - bids: [{ - params: { - placementId: 13144370, - } - }] - }] - }; - expect(getMatchingBidders(moduleConfig, reqBidsConfigObj)).to.be.empty; - }); - }); - - describe('integration test with mock live-classification response', function () { - const moduleConfig = { - params: { - pubId: 123456, - bidders: ['appnexus'], - } - }; - - const reqBidsConfigObj = { - adUnits: [{ - bids: [{ - bidder: 'appnexus', - params: { - placementId: 13144370 - } - }, { - bidder: 'other' - }] - }] - }; - - const expectedUrlParam = 'http://localhost:9876/context.html'; - - it('gets data from async request and adds segment data', function () { - config.resetConfig(); - let data = {xandr: [111111, 222222]}; - const callbackSpy = sinon.spy(); - setCaptifyTargeting(reqBidsConfigObj, callbackSpy, moduleConfig, {}); - let request = server.requests[0]; - let requestBody = JSON.parse(server.requests[0].requestBody); - expect(request.url).to.be.eq(defaultRequestUrl); - expect(requestBody['pubId']).to.eq(moduleConfig.params.pubId); - expect(requestBody['url']).to.eq(expectedUrlParam); - request.respond(200, responseHeader, JSON.stringify(data)); - expect(deepAccess(config.getConfig(), 'appnexusAuctionKeywords.captify_segments')).to.eql(data['xandr']); - expect(callbackSpy.calledOnce).to.be.true; - }); - - it('do not send classification request, if no matching adUnits on page', function () { - config.resetConfig(); - let reqBidsConfigObj = { - adUnits: [{ - bids: [ - {bidder: 'pubmatic'} - ] - }] - }; - const callbackSpy = sinon.spy(); - setCaptifyTargeting(reqBidsConfigObj, callbackSpy, moduleConfig, {}); - expect(server.requests).to.be.empty; - }); - - it('gets data from async request and adds segment data, using URL from config', function () { - config.resetConfig(); - let data = {xandr: [111111, 222222]}; - const callbackSpy = sinon.spy(); - const testUrl = 'http://my-test-server.com/path'; - const conf = { - params: { - url: testUrl, - pubId: 123456, - bidders: ['appnexus'], - } - }; - setCaptifyTargeting(reqBidsConfigObj, callbackSpy, conf, {}); - let request = server.requests[0]; - let requestBody = JSON.parse(server.requests[0].requestBody); - expect(request.url).to.be.eq(testUrl); - expect(requestBody['pubId']).to.eq(conf.params.pubId); - expect(requestBody['url']).to.eq(expectedUrlParam); - request.respond(200, responseHeader, JSON.stringify(data)); - expect(deepAccess(config.getConfig(), 'appnexusAuctionKeywords.captify_segments')).to.eql(data['xandr']); - expect(callbackSpy.calledOnce).to.be.true; - }); - - it('do not set anything, in case server responded with 202', function () { - config.resetConfig(); - const callbackSpy = sinon.spy(); - setCaptifyTargeting(reqBidsConfigObj, callbackSpy, moduleConfig, {}); - let request = server.requests[0]; - let requestBody = JSON.parse(server.requests[0].requestBody); - expect(request.url).to.be.eq(defaultRequestUrl); - expect(requestBody['pubId']).to.eq(moduleConfig.params.pubId); - expect(requestBody['url']).to.eq(expectedUrlParam); - request.respond(202, responseHeader, ''); - expect(deepAccess(config.getConfig(), 'appnexusAuctionKeywords.captify_segments')).to.be.undefined; - expect(callbackSpy.calledOnce).to.be.true; - }); - - it('do not set anything, in case server responded with error', function () { - config.resetConfig(); - const callbackSpy = sinon.spy(); - setCaptifyTargeting(reqBidsConfigObj, callbackSpy, moduleConfig, {}); - let request = server.requests[0]; - expect(request.url).to.be.eq(defaultRequestUrl); - request.respond(500, null, ''); - expect(deepAccess(config.getConfig(), 'appnexusAuctionKeywords.captify_segments')).to.be.undefined; - expect(callbackSpy.calledOnce).to.be.true; - }); - - it('do not set anything, in case request error', function () { - config.resetConfig(); - const callbackSpy = sinon.spy(); - setCaptifyTargeting(reqBidsConfigObj, callbackSpy, moduleConfig, {}); - let request = server.requests[0]; - expect(request.url).to.be.eq(defaultRequestUrl); - request.abort('test error'); - expect(deepAccess(config.getConfig(), 'appnexusAuctionKeywords.captify_segments')).to.be.undefined; - expect(callbackSpy.calledOnce).to.be.true; - }); - }); -}); diff --git a/test/spec/modules/ccxBidAdapter_spec.js b/test/spec/modules/ccxBidAdapter_spec.js index d346a14d38a..cbae441e7e7 100644 --- a/test/spec/modules/ccxBidAdapter_spec.js +++ b/test/spec/modules/ccxBidAdapter_spec.js @@ -81,7 +81,7 @@ describe('ccxAdapter', function () { }); it('Valid bid request - default', function () { - let response = spec.buildRequests(bids, {bids}); + let response = spec.buildRequests(bids, {bids, bidderRequestId: 'id'}); expect(response).to.be.not.empty; expect(response.data).to.be.not.empty; diff --git a/test/spec/modules/cleanmedianetBidAdapter_spec.js b/test/spec/modules/cleanmedianetBidAdapter_spec.js index a19cdf7fd35..3c73dac07de 100644 --- a/test/spec/modules/cleanmedianetBidAdapter_spec.js +++ b/test/spec/modules/cleanmedianetBidAdapter_spec.js @@ -310,7 +310,7 @@ describe('CleanmedianetAdapter', () => { response = spec.buildRequests([bidRequest], bidRequest)[0]; expect(response.method).to.equal('POST'); expect(response.url).to.match(new RegExp(`^https://bidder\\.cleanmediaads\\.com/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); - expect(response.data.id).to.equal(bidRequest.auctionId); + expect(response.data.id).to.equal(bidRequest.bidId); const bidRequestWithEndpoint = utils.deepClone(bidRequest); bidRequestWithEndpoint.params.rtbEndpoint = 'https://bidder.cleanmediaads.com/a12'; response = spec.buildRequests([bidRequestWithEndpoint], bidRequest)[0]; @@ -330,7 +330,7 @@ describe('CleanmedianetAdapter', () => { expect(response.data.site.page).to.equal('http://www.test.com/page.html'); expect(response.data.site.ref).to.equal('http://referrer.com'); expect(response.data.imp.length).to.equal(1); - expect(response.data.imp[0].id).to.equal(bidRequest.transactionId); + expect(response.data.imp[0].id).to.equal(bidRequest.bidId); expect(response.data.imp[0].instl).to.equal(0); expect(response.data.imp[0].tagid).to.equal(bidRequest.adUnitCode); expect(response.data.imp[0].bidfloor).to.equal(0); diff --git a/test/spec/modules/codefuelBidAdapter_spec.js b/test/spec/modules/codefuelBidAdapter_spec.js index 354cbe63ffa..6123f768d88 100644 --- a/test/spec/modules/codefuelBidAdapter_spec.js +++ b/test/spec/modules/codefuelBidAdapter_spec.js @@ -1,6 +1,7 @@ import {expect} from 'chai'; import {spec} from 'modules/codefuelBidAdapter.js'; import {config} from 'src/config.js'; +import * as utils from 'src/utils.js'; import {server} from 'test/mocks/xhr'; const USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/92.0.4515.159 Safari/537.36'; @@ -9,6 +10,13 @@ const setUADefault = () => { window.navigator.__defineGetter__('userAgent', func const setUAMock = () => { window.navigator.__defineGetter__('userAgent', function () { return USER_AGENT }) }; describe('Codefuel Adapter', function () { + let sandbox; + beforeEach(() => { + sandbox = sinon.sandbox.create(); + }); + afterEach(() => { + sandbox.restore(); + }) describe('Bid request and response', function () { const commonBidRequest = { bidder: 'codefuel', @@ -137,6 +145,7 @@ describe('Codefuel Adapter', function () { const commonBidderRequest = { timeout: 500, + bidderRequestId: 'mock-uuid', auctionId: '12043683-3254-4f74-8934-f941b085579e', refererInfo: { page: 'https://example.com/', @@ -157,7 +166,7 @@ describe('Codefuel Adapter', function () { devicetype: 2, ua: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/92.0.4515.159 Safari/537.36' }, - id: '12043683-3254-4f74-8934-f941b085579e', + id: 'mock-uuid', imp: [ { banner: { diff --git a/test/spec/modules/colossussspBidAdapter_spec.js b/test/spec/modules/colossussspBidAdapter_spec.js index adb9137d892..0d16f9897fa 100644 --- a/test/spec/modules/colossussspBidAdapter_spec.js +++ b/test/spec/modules/colossussspBidAdapter_spec.js @@ -19,12 +19,12 @@ describe('ColossussspAdapter', function () { }, ortb2Imp: { ext: { + tid: '3bb2f6da-87a6-4029-aeb0-bfe951372e62', data: { pbadslot: '/19968336/prebid_cache_video_adunit' } } }, - transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62', schain: { ver: '1.0', complete: 1, diff --git a/test/spec/modules/concertBidAdapter_spec.js b/test/spec/modules/concertBidAdapter_spec.js index f5c807b4703..96c98e5e5a2 100644 --- a/test/spec/modules/concertBidAdapter_spec.js +++ b/test/spec/modules/concertBidAdapter_spec.js @@ -48,7 +48,11 @@ describe('ConcertAdapter', function () { }, adUnitCode: 'desktop_leaderboard_variable', bidId: 'foo', - transactionId: '', + ortb2Imp: { + ext: { + tid: '' + } + }, sizes: [[1030, 590]] } ]; diff --git a/test/spec/modules/conversantBidAdapter_spec.js b/test/spec/modules/conversantBidAdapter_spec.js index bf02a2893f0..59ebefa2d60 100644 --- a/test/spec/modules/conversantBidAdapter_spec.js +++ b/test/spec/modules/conversantBidAdapter_spec.js @@ -256,6 +256,11 @@ describe('Conversant adapter tests', function() { const bidderRequest = { refererInfo: { page: page + }, + ortb2: { + source: { + tid: 'tid000' + } } }; const request = spec.buildRequests(bidRequests, bidderRequest); @@ -263,8 +268,8 @@ describe('Conversant adapter tests', function() { expect(request.url).to.equal('https://web.hb.ad.cpe.dotomi.com/cvx/client/hb/ortb/25'); const payload = request.data; - expect(payload).to.have.property('id', 'req000'); - expect(payload.source).to.have.property('tid', 'req000'); + expect(payload).to.have.property('id'); + expect(payload.source).to.have.property('tid', 'tid000'); expect(payload).to.have.property('at', 1); expect(payload).to.have.property('imp'); expect(payload.imp).to.be.an('array').with.lengthOf(8); diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index 1d246e4cd2a..b2f3d64a156 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -604,13 +604,67 @@ describe('The Criteo bidding adapter', function () { config.resetConfig(); }); + it('should properly build a request using random uuid as auction id', function () { + const generateUUIDStub = sinon.stub(utils, 'generateUUID'); + generateUUIDStub.returns('def'); + const bidderRequest = { + }; + const bidRequests = [ + { + bidder: 'criteo', + adUnitCode: 'bid-123', + transactionId: 'transaction-123', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + params: {} + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + const ortbRequest = request.data; + expect(ortbRequest.id).to.equal('def'); + generateUUIDStub.restore(); + }); + + it('should properly transmit source.tid if available', function () { + const bidderRequest = { + ortb2: { + source: { + tid: 'abc' + } + } + }; + const bidRequests = [ + { + bidder: 'criteo', + adUnitCode: 'bid-123', + transactionId: 'transaction-123', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + params: {} + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + const ortbRequest = request.data; + expect(ortbRequest.source.tid).to.equal('abc'); + }); + it('should properly build a request if refererInfo is not provided', function () { const bidderRequest = {}; const bidRequests = [ { bidder: 'criteo', adUnitCode: 'bid-123', - transactionId: 'transaction-123', + ortb2Imp: { + ext: { + tid: 'transaction-123', + }, + }, mediaTypes: { banner: { sizes: [[728, 90]] @@ -629,7 +683,11 @@ describe('The Criteo bidding adapter', function () { { bidder: 'criteo', adUnitCode: 'bid-123', - transactionId: 'transaction-123', + ortb2Imp: { + ext: { + tid: 'transaction-123', + }, + }, mediaTypes: { banner: { sizes: [[728, 90]] @@ -842,7 +900,11 @@ describe('The Criteo bidding adapter', function () { { bidder: 'criteo', adUnitCode: 'bid-123', - transactionId: 'transaction-123', + ortb2Imp: { + ext: { + tid: 'transaction-123', + }, + }, mediaTypes: { banner: { sizes: [[300, 250], [728, 90]] @@ -881,7 +943,11 @@ describe('The Criteo bidding adapter', function () { { bidder: 'criteo', adUnitCode: 'bid-123', - transactionId: 'transaction-123', + ortb2Imp: { + ext: { + tid: 'transaction-123', + }, + }, mediaTypes: { banner: { sizes: [[728, 90]] @@ -894,7 +960,11 @@ describe('The Criteo bidding adapter', function () { { bidder: 'criteo', adUnitCode: 'bid-234', - transactionId: 'transaction-234', + ortb2Imp: { + ext: { + tid: 'transaction-234', + }, + }, mediaTypes: { banner: { sizes: [[300, 250], [728, 90]] @@ -1063,7 +1133,7 @@ describe('The Criteo bidding adapter', function () { }); it('should properly build a request with bcat field', function () { - const bcat = [ 'IAB1', 'IAB2' ]; + const bcat = ['IAB1', 'IAB2']; const bidRequests = [ { bidder: 'criteo', @@ -1091,7 +1161,7 @@ describe('The Criteo bidding adapter', function () { }); it('should properly build a request with badv field', function () { - const badv = [ 'ford.com' ]; + const badv = ['ford.com']; const bidRequests = [ { bidder: 'criteo', @@ -1119,7 +1189,7 @@ describe('The Criteo bidding adapter', function () { }); it('should properly build a request with bapp field', function () { - const bapp = [ 'com.foo.mygame' ]; + const bapp = ['com.foo.mygame']; const bidRequests = [ { bidder: 'criteo', diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js index b674cb5976d..88c640e38cc 100644 --- a/test/spec/modules/currency_spec.js +++ b/test/spec/modules/currency_spec.js @@ -366,15 +366,15 @@ describe('currency', function () { expect(innerBid.cpm).to.equal(1); }); - it('should result in NO_BID when currency support is not enabled and fromCurrency is not USD', function () { + it('should reject bid when currency support is not enabled and fromCurrency is not USD', function () { setConfig({}); var bid = makeBid({ 'cpm': 1, 'currency': 'GBP' }); - var innerBid; + let bidAdded = false; addBidResponseHook(function(adCodeId, bid) { - innerBid = bid; + bidAdded = true; }, 'elementId', bid, reject); - expect(innerBid.status).to.equal('rejected'); + expect(bidAdded).to.be.false; expect(reject.calledOnce).to.be.true; }); @@ -390,7 +390,7 @@ describe('currency', function () { expect(bid).to.equal(innerBid); }); - it('should result in NO_BID when fromCurrency is not supported in file', function () { + it('should reject bid when fromCurrency is not supported in file', function () { // RESET to request currency file setConfig({ 'adServerCurrency': undefined }); @@ -398,24 +398,24 @@ describe('currency', function () { setConfig({ 'adServerCurrency': 'JPY' }); fakeCurrencyFileServer.respond(); var bid = makeBid({ 'cpm': 1, 'currency': 'ABC' }); - var innerBid; + let bidAdded = false; addBidResponseHook(function(adCodeId, bid) { - innerBid = bid; + bidAdded = true; }, 'elementId', bid, reject); - expect(innerBid.status).to.equal('rejected'); + expect(bidAdded).to.be.false; expect(reject.calledOnce).to.be.true; }); - it('should result in NO_BID when adServerCurrency is not supported in file', function () { + it('should reject bid when adServerCurrency is not supported in file', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'ABC' }); fakeCurrencyFileServer.respond(); var bid = makeBid({ 'cpm': 1, 'currency': 'GBP' }); - var innerBid; + let bidAdded = false; addBidResponseHook(function(adCodeId, bid) { - innerBid = bid; + bidAdded = true; }, 'elementId', bid, reject); - expect(innerBid.status).to.equal('rejected'); + expect(bidAdded).to.be.false; expect(reject.calledOnce).to.be.true; }); diff --git a/test/spec/modules/datawrkzBidAdapter_spec.js b/test/spec/modules/datawrkzBidAdapter_spec.js index 3ddc2bad1cf..5524e318600 100644 --- a/test/spec/modules/datawrkzBidAdapter_spec.js +++ b/test/spec/modules/datawrkzBidAdapter_spec.js @@ -462,7 +462,6 @@ describe('datawrkzAdapterTests', function () { expect(result[0].ad).to.equal(decodeURIComponent(serverResponse.body.seatbid[0].bid[0].adm + '')); expect(result[0].creativeId).to.equal('1'); expect(result[0].bidderCode).to.equal(request.bidRequest.bidder); - expect(result[0].transactionId).to.equal(request.bidRequest.transactionId); expect(result[0].mediaType).to.equal('banner'); }); @@ -540,7 +539,6 @@ describe('datawrkzAdapterTests', function () { expect(result[0].native.desc).to.equal('Test body'); expect(result[0].creativeId).to.equal('1'); expect(result[0].bidderCode).to.equal(request.bidRequest.bidder); - expect(result[0].transactionId).to.equal(request.bidRequest.transactionId); expect(result[0].mediaType).to.equal('native'); }); @@ -610,7 +608,6 @@ describe('datawrkzAdapterTests', function () { expect(result[0].adserverTargeting.hb_protocol).to.equal('3'); expect(result[0].creativeId).to.equal('1'); expect(result[0].bidderCode).to.equal(request.bidRequest.bidder); - expect(result[0].transactionId).to.equal(request.bidRequest.transactionId); expect(result[0].mediaType).to.equal('video'); }); @@ -649,7 +646,6 @@ describe('datawrkzAdapterTests', function () { expect(result[0].renderer).to.exist; expect(result[0].creativeId).to.equal('1'); expect(result[0].bidderCode).to.equal(request.bidRequest.bidder); - expect(result[0].transactionId).to.equal(request.bidRequest.transactionId); expect(result[0].mediaType).to.equal('video'); }); }); diff --git a/test/spec/modules/dianomiBidAdapter_spec.js b/test/spec/modules/dianomiBidAdapter_spec.js index 61509913c41..0838762d750 100644 --- a/test/spec/modules/dianomiBidAdapter_spec.js +++ b/test/spec/modules/dianomiBidAdapter_spec.js @@ -162,7 +162,7 @@ describe('Dianomi adapter', () => { }, ]; let request = JSON.parse( - spec.buildRequests(validBidRequests, { refererInfo: { page: 'page' }, auctionId: 'tid' }).data + spec.buildRequests(validBidRequests, {refererInfo: {page: 'page'}, ortb2: {source: {tid: 'tid'}}}).data ); assert.equal(request.source.tid, 'tid'); diff --git a/test/spec/modules/etargetBidAdapter_spec.js b/test/spec/modules/etargetBidAdapter_spec.js index 55394dcdeea..a950100d612 100644 --- a/test/spec/modules/etargetBidAdapter_spec.js +++ b/test/spec/modules/etargetBidAdapter_spec.js @@ -173,7 +173,6 @@ describe('etarget adapter', function () { assert.isNotNull(result.reason); assert.equal(result.ttl, 360); assert.equal(result.ad, ''); - assert.equal(result.transactionId, '5f33781f-9552-4ca1'); }); it('should set correct netRevenue', function () { @@ -296,7 +295,11 @@ describe('etarget adapter', function () { tid: 45, placementCode: placementCode[0], sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], - transactionId: '5f33781f-9552-4ca1' + ortb2Imp: { + ext: { + tid: '5f33781f-9552-4ca1' + } + } }, { adUnitCode: placementCode[1], @@ -307,7 +310,11 @@ describe('etarget adapter', function () { params: params[1], placementCode: placementCode[1], sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], - transactionId: '5f33781f-9552-4iuy' + ortb2Imp: { + ext: { + tid: '5f33781f-9552-4iuy' + } + } }, { adUnitCode: placementCode[2], @@ -318,7 +325,11 @@ describe('etarget adapter', function () { params: params[2], placementCode: placementCode[2], sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], - transactionId: '5f33781f-9552-7ev3' + ortb2Imp: { + ext: { + tid: '5f33781f-9552-7ev3' + } + } }, { adUnitCode: placementCode[3], @@ -329,7 +340,11 @@ describe('etarget adapter', function () { params: params[2], placementCode: placementCode[2], sizes: [], - transactionId: '5f33781f-9552-7ev3' + ortb2Imp: { + ext: { + tid: '5f33781f-9552-7ev3' + } + } }, { adUnitCode: placementCode[4], @@ -340,7 +355,11 @@ describe('etarget adapter', function () { params: params[2], placementCode: placementCode[2], sizes: [], - transactionId: '5f33781f-9552-7ev3' + ortb2Imp: { + ext: { + tid: '5f33781f-9552-7ev3' + } + } }, { adUnitCode: placementCode[4], @@ -351,7 +370,11 @@ describe('etarget adapter', function () { params: params[3], placementCode: placementCode[2], sizes: [], - transactionId: '5f33781f-9552-7ev3' + ortb2Imp: { + ext: { + tid: '5f33781f-9552-7ev3' + } + } }, { adUnitCode: placementCode[4], @@ -362,7 +385,11 @@ describe('etarget adapter', function () { params: params[4], placementCode: placementCode[2], sizes: [], - transactionId: '5f33781f-9552-7ev3' + ortb2Imp: { + ext: { + tid: '5f33781f-9552-7ev3' + } + } } ]; serverResponse = { diff --git a/test/spec/modules/euidIdSystem_spec.js b/test/spec/modules/euidIdSystem_spec.js index 5f75f9dc16f..9a016b0facd 100644 --- a/test/spec/modules/euidIdSystem_spec.js +++ b/test/spec/modules/euidIdSystem_spec.js @@ -64,13 +64,6 @@ describe('EUID module', function() { coreStorage.removeDataFromLocalStorage(moduleCookieName); }); - it('When a server-only token value is provided in config but consent is not available, it is not available to the auction.', async function() { - setGdprApplies(); - config.setConfig(makePrebidConfig(null, {value: makeEuidIdentityContainer(initialToken)})); - const bid = await runAuction(); - expectNoIdentity(bid); - }); - it('When a server-only token value is provided in config, it is available to the auction.', async function() { setGdprApplies(true); config.setConfig(makePrebidConfig(null, {value: makeEuidIdentityContainer(initialToken)})); diff --git a/test/spec/modules/feedadBidAdapter_spec.js b/test/spec/modules/feedadBidAdapter_spec.js index 5789361d2a1..152adba9d00 100644 --- a/test/spec/modules/feedadBidAdapter_spec.js +++ b/test/spec/modules/feedadBidAdapter_spec.js @@ -508,7 +508,11 @@ describe('FeedAdAdapter', function () { } }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': transactionId, + ortb2Imp: { + ext: { + tid: transactionId + } + }, 'sizes': [ [ 300, diff --git a/test/spec/modules/finativeBidAdapter_spec.js b/test/spec/modules/finativeBidAdapter_spec.js index 7b3f23d8b9e..d5c56aca65d 100644 --- a/test/spec/modules/finativeBidAdapter_spec.js +++ b/test/spec/modules/finativeBidAdapter_spec.js @@ -49,17 +49,6 @@ describe('Finative adapter', function () { assert.deepEqual(keys, data); }); - it('Verify the auction ID', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {}, - auctionId: 'auctionId' - }]; - let request = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' }, auctionId: validBidRequests[0].auctionId }).data); - - assert.equal(request.id, validBidRequests[0].auctionId); - }); - it('Verify the device', function () { let validBidRequests = [{ bidId: 'bidId', @@ -166,7 +155,6 @@ describe('Finative adapter', function () { assert.deepEqual(result[0].cpm, bid.price); assert.deepEqual(result[0].creativeId, bid.crid); assert.deepEqual(result[0].mediaType, 'native'); - assert.deepEqual(result[0].bidderCode, 'finative'); }); it('should return the correct tracking links', function () { diff --git a/test/spec/modules/fluctBidAdapter_spec.js b/test/spec/modules/fluctBidAdapter_spec.js index e9681c05314..d970f70ad85 100644 --- a/test/spec/modules/fluctBidAdapter_spec.js +++ b/test/spec/modules/fluctBidAdapter_spec.js @@ -319,7 +319,6 @@ describe('fluctAdapter', function () { const expectedResponse = [ { - bidderCode: 'fluct', requestId: '237f4d1a293f99', currency: 'JPY', cpm: 100, @@ -376,7 +375,6 @@ describe('fluctAdapter', function () { const expectedResponse = [ { - bidderCode: 'fluct', requestId: '237f4d1a293f99', currency: 'JPY', cpm: 100, diff --git a/test/spec/modules/gamoshiBidAdapter_spec.js b/test/spec/modules/gamoshiBidAdapter_spec.js index 8f8e3f03736..984830f67d4 100644 --- a/test/spec/modules/gamoshiBidAdapter_spec.js +++ b/test/spec/modules/gamoshiBidAdapter_spec.js @@ -46,7 +46,11 @@ describe('GamoshiAdapter', () => { 'supplyPartnerId': supplyPartnerId }, 'sizes': [[300, 250], [300, 600]], - 'transactionId': 'a123456789', + ortb2Imp: { + ext: { + tid: 'a123456789', + } + }, refererInfo: {referer: 'http://examplereferer.com'}, gdprConsent: { consentString: 'some string', @@ -310,7 +314,6 @@ describe('GamoshiAdapter', () => { response = spec.buildRequests([bidRequest], bidRequest)[0]; expect(response.method).to.equal('POST'); expect(response.url).to.match(new RegExp(`^https://rtb\\.gamoshi\\.io/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); - expect(response.data.id).to.equal(bidRequest.auctionId); const bidRequestWithEndpoint = utils.deepClone(bidRequest); bidRequestWithEndpoint.params.rtbEndpoint = 'https://rtb2.gamoshi.io/a12'; response = spec.buildRequests([bidRequestWithEndpoint], bidRequest)[0]; diff --git a/test/spec/modules/glimpseBidAdapter_spec.js b/test/spec/modules/glimpseBidAdapter_spec.js deleted file mode 100644 index 353e61c7859..00000000000 --- a/test/spec/modules/glimpseBidAdapter_spec.js +++ /dev/null @@ -1,422 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/glimpseBidAdapter.js'; -import { newBidder } from 'src/adapters/bidderFactory.js'; -import { config } from 'src/config'; -import { BANNER } from '../../../src/mediaTypes'; - -const ENDPOINT = 'https://market.glimpsevault.io/public/v1/prebid'; - -const nonStringValues = [null, undefined, 123, true, {}, [], () => {}]; -const nonArrayValues = [null, undefined, 123, true, {}, 'str', () => {}]; - -const mock = { - bidRequest: { - bidder: 'glimpse', - bidId: '26a80b71cfd671', - bidderRequestId: '133baeded6ac94', - auctionId: '96692a73-307b-44b8-8e4f-ddfb40341570', - adUnitCode: 'banner-div-a', - sizes: [[300, 250]], - params: { - pid: 'glimpse-demo-300x250', - }, - }, - bidderRequest: { - bidderCode: 'glimpse', - bidderRequestId: '133baeded6ac94', - auctionId: '96692a73-307b-44b8-8e4f-ddfb40341570', - timeout: 3000, - gdprConsent: { - consentString: - 'COzP517OzP517AcABBENAlCsAP_AAAAAAAwIF8NX-T5eL2vju2Zdt7JEaYwfZxyigOgThgQIsW8NwIeFbBoGP2EgHBG4JCQAGBAkkgCBAQMsHGBcCQAAgIgRiRKMYE2MjzNKBJJAigkbc0FACDVunsHS2ZCY70-8O__bPAviADAvUC-AAAAA.YAAAAAAAAAAA', - vendorData: {}, - gdprApplies: true, - }, - uspConsent: '1YYY', - refererInfo: { - numIframes: 0, - reachedTop: true, - page: 'https://demo.glimpseprotocol.io/prebid/desktop', - stack: ['https://demo.glimpseprotocol.io/prebid/desktop'], - }, - }, - bidResponse: { - auth: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJoZWxsbyI6IndvcmxkISJ9.1p6T0ORhJ6riLprhXBGdzRhG3Q1egM27uFhPGNapPxs', - data: { - bids: [ - { - requestId: '133baeded6ac94', - creativeId: 'glimpse-demo-300x250', - adUnitCode: 'banner-div-a', - currency: 'GBP', - ad: '
Hello, World!
', - width: 300, - height: 250, - cpm: 1.04, - netRevenue: true, - mediaType: 'banner', - ttl: 300, - }, - ], - }, - }, -}; - -const getBidRequest = () => getDeepCopy(mock.bidRequest); -const getBidderRequest = () => ({ - bids: [getBidRequest()], - ...getDeepCopy(mock.bidderRequest), -}); - -const getBidResponse = () => ({ - body: getDeepCopy(mock.bidResponse), -}); - -function getDeepCopy(object) { - return JSON.parse(JSON.stringify(object)); -} - -describe('GlimpseProtocolAdapter', () => { - const glimpseAdapter = newBidder(spec); - - describe('spec', () => { - it('Has defined the glimpse gvlid', () => { - expect(spec.gvlid).to.equal(1012); - }); - - it('Has defined glimpse as the bidder', () => { - expect(spec.code).to.equal('glimpse'); - }); - - it('Has defined valid mediaTypes', () => { - expect(spec.supportedMediaTypes).to.deep.equal([BANNER]); - }); - }); - - describe('Inherited functions', () => { - it('Functions exist and are valid types', () => { - expect(glimpseAdapter.callBids).to.exist.and.to.be.a('function'); - expect(glimpseAdapter.getSpec).to.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid', () => { - it('Returns true if placement id is non-empty string', () => { - const bidRequest = getBidRequest(); - - const isValidBidRequest = spec.isBidRequestValid(bidRequest); - expect(isValidBidRequest).to.be.true; - }); - - it('Returns false if no pid is provided', () => { - const bidRequest = getBidRequest(); - delete bidRequest.params.pid; - - const isValidBidRequest = spec.isBidRequestValid(bidRequest); - expect(isValidBidRequest).to.be.false; - }); - - it('Returns false if pid is empty string', () => { - const bidRequest = getBidRequest(); - bidRequest.params.pid = ''; - - const isValidBidRequest = spec.isBidRequestValid(bidRequest); - expect(isValidBidRequest).to.be.false; - }); - - it('Returns false if pid is not string', () => { - const bidRequest = getBidRequest(); - const invalidPids = nonStringValues; - - invalidPids.forEach((invalidPid) => { - bidRequest.params.pid = invalidPid; - const isValidBidRequest = spec.isBidRequestValid(bidRequest); - expect(isValidBidRequest).to.be.false; - }); - }); - }); - - describe('buildRequests', () => { - const bidRequests = [getBidRequest()]; - const bidderRequest = getBidderRequest(); - - it('Adds additional info to api request query', () => { - const request = spec.buildRequests(bidRequests, bidderRequest); - const url = new URL(request.url); - const queries = new URLSearchParams(url.search); - - expect(queries.get('ver')).to.exist; - expect(queries.get('tmax')).to.exist; - expect(queries.get('gdpr')).to.equal( - bidderRequest.gdprConsent.consentString - ); - expect(queries.get('ccpa')).to.equal(bidderRequest.uspConsent); - }); - - it('Has correct payload shape', () => { - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - - expect(payload.auth).to.be.a('string'); - expect(payload.data).to.be.an('object'); - expect(payload.data.referer).to.be.a('string'); - expect(payload.data.imp).to.be.an('array'); - expect(payload.data.fpd).to.be.an('object'); - }); - - it('Has referer information', () => { - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - const expected = mock.bidderRequest.refererInfo.page; - - expect(payload.data.referer).to.equal(expected); - }); - - it('Has correct bids (imp) shape', () => { - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - const imp = payload.data.imp; - - imp.forEach((i) => { - expect(i.bid).to.be.a('string'); - expect(i.pid).to.be.a('string'); - expect(i.sizes).to.be.an('array').that.deep.include([300, 250]); - }); - }); - }); - - describe('interpretResponse', () => { - it('Returns valid bids', () => { - const bidResponse = getBidResponse(); - const bids = spec.interpretResponse(bidResponse); - - expect(bids).to.have.lengthOf(1); - expect(bids[0].adUnitCode).to.equal(mock.bidRequest.adUnitCode); - }); - - it('Returns no bids if auth is not string', () => { - const bidResponse = getBidResponse(); - const invalidAuths = nonStringValues; - - invalidAuths.forEach((invalidAuth) => { - bidResponse.body.auth = invalidAuth; - - const bids = spec.interpretResponse(bidResponse); - expect(bids).to.have.lengthOf(0); - }); - }); - - it('Returns no bids if bids is empty', () => { - const bidResponse = getBidResponse(); - bidResponse.body.data.bids = []; - - const bids = spec.interpretResponse(bidResponse); - expect(bids).to.have.lengthOf(0); - }); - - it('Returns no bids if bids is not array', () => { - const bidResponse = getBidResponse(); - const invalidBids = nonArrayValues; - - invalidBids.forEach((invalidBid) => { - bidResponse.body.data.bids = invalidBid; - - const bids = spec.interpretResponse(bidResponse); - expect(bids).to.have.lengthOf(0); - }); - }); - - it('Contains advertiserDomains', () => { - const bidResponse = getBidResponse(); - - const bids = spec.interpretResponse(bidResponse); - bids.forEach((bid) => { - expect(bid.meta.advertiserDomains).to.be.an('array'); - }); - }); - }); - - describe('optimize request fpd data', () => { - const bidRequests = [getBidRequest()]; - const bidderRequest = getBidderRequest(); - - const fpdMockBase = { - site: { - keywords: 'site,keywords', - ext: { - data: { - fpdProvider: { - dataArray: ['data1', 'data2'], - dataObject: { - data1: 'data1', - data2: 'data2', - }, - dataString: 'data1,data2', - }, - }, - }, - }, - user: { - keywords: 'user,keywords', - ext: { - data: { - fpdProvider: { - dataArray: ['data1', 'data2'], - dataObject: { - data1: 'data1', - data2: 'data2', - }, - dataString: 'data1,data2', - }, - }, - }, - }, - }; - - it('should keep all non-empty fields', () => { - const fpdMock = fpdMockBase; - const expected = fpdMockBase; - - const request = spec.buildRequests(bidRequests, {...bidderRequest, ortb2: fpdMock}); - const payload = JSON.parse(request.data); - const fpd = payload.data.fpd; - - expect(fpd).to.deep.equal(expected); - }); - - it('should remove all empty objects', () => { - const fpdMock = getDeepCopy(fpdMockBase); - fpdMock.site.ext.data.fpdProvider.dataObject = {}; - fpdMock.user.ext.data.fpdProvider = {}; - - const expected = { - site: { - keywords: 'site,keywords', - ext: { - data: { - fpdProvider: { - dataArray: ['data1', 'data2'], - dataString: 'data1,data2', - }, - }, - }, - }, - user: { - keywords: 'user,keywords', - }, - }; - - const request = spec.buildRequests(bidRequests, {...bidderRequest, ortb2: fpdMock}); - const payload = JSON.parse(request.data); - const fpd = payload.data.fpd; - - expect(fpd).to.deep.equal(expected); - }); - - it('should remove all empty arrays', () => { - const fpdMock = getDeepCopy(fpdMockBase); - fpdMock.site.ext.data.fpdProvider.dataArray = []; - fpdMock.user.ext.data.fpdProvider.dataArray = []; - - const expected = { - site: { - keywords: 'site,keywords', - ext: { - data: { - fpdProvider: { - dataObject: { - data1: 'data1', - data2: 'data2', - }, - dataString: 'data1,data2', - }, - }, - }, - }, - user: { - keywords: 'user,keywords', - ext: { - data: { - fpdProvider: { - dataObject: { - data1: 'data1', - data2: 'data2', - }, - dataString: 'data1,data2', - }, - }, - }, - }, - }; - - const request = spec.buildRequests(bidRequests, {...bidderRequest, ortb2: fpdMock}); - const payload = JSON.parse(request.data); - const fpd = payload.data.fpd; - - expect(fpd).to.deep.equal(expected); - }); - - it('should remove all empty strings', () => { - const fpdMock = getDeepCopy(fpdMockBase); - fpdMock.site.keywords = ''; - fpdMock.site.ext.data.fpdProvider.dataString = ''; - fpdMock.user.keywords = ''; - fpdMock.user.ext.data.fpdProvider.dataString = ''; - - const expected = { - site: { - ext: { - data: { - fpdProvider: { - dataArray: ['data1', 'data2'], - dataObject: { - data1: 'data1', - data2: 'data2', - }, - }, - }, - }, - }, - user: { - ext: { - data: { - fpdProvider: { - dataArray: ['data1', 'data2'], - dataObject: { - data1: 'data1', - data2: 'data2', - }, - }, - }, - }, - }, - }; - - const request = spec.buildRequests(bidRequests, {...bidderRequest, ortb2: fpdMock}); - const payload = JSON.parse(request.data); - const fpd = payload.data.fpd; - - expect(fpd).to.deep.equal(expected); - }); - - it('should remove all empty fields', () => { - const fpdMock = getDeepCopy(fpdMockBase); - fpdMock.site.keywords = ''; - fpdMock.site.ext.data.fpdProvider.dataArray = []; - fpdMock.site.ext.data.fpdProvider.dataObject = {}; - fpdMock.site.ext.data.fpdProvider.dataString = ''; - fpdMock.user.keywords = ''; - fpdMock.user.ext.data.fpdProvider.dataArray = []; - fpdMock.user.ext.data.fpdProvider.dataObject = {}; - fpdMock.user.ext.data.fpdProvider.dataString = ''; - - const expected = {}; - - const request = spec.buildRequests(bidRequests, {...bidderRequest, ortb2: fpdMock}); - const payload = JSON.parse(request.data); - const fpd = payload.data.fpd; - - expect(fpd).to.deep.equal(expected); - }); - }); -}); diff --git a/test/spec/modules/gmosspBidAdapter_spec.js b/test/spec/modules/gmosspBidAdapter_spec.js index 6d290504194..8c3aa6c94cb 100644 --- a/test/spec/modules/gmosspBidAdapter_spec.js +++ b/test/spec/modules/gmosspBidAdapter_spec.js @@ -50,7 +50,11 @@ describe('GmosspAdapter', function () { bidId: '2b84475b5b636e', bidderRequestId: '1f4001782ac16c', auctionId: 'aba03555-4802-4c45-9f15-05ffa8594cff', - transactionId: '791e9d84-af92-4903-94da-24c7426d9d0c', + ortb2Imp: { + ext: { + tid: '791e9d84-af92-4903-94da-24c7426d9d0c', + } + }, userId: { imuid: 'h.0a4749e7ffe09fa6', pubcid: '1111', diff --git a/test/spec/modules/gnetBidAdapter_spec.js b/test/spec/modules/gnetBidAdapter_spec.js index 21526aba201..f1af3b71103 100644 --- a/test/spec/modules/gnetBidAdapter_spec.js +++ b/test/spec/modules/gnetBidAdapter_spec.js @@ -63,7 +63,11 @@ describe('gnetAdapter', function () { bidId: '2a19afd5173318', bidderRequestId: '1f4001782ac16c', auctionId: 'aba03555-4802-4c45-9f15-05ffa8594cff', - transactionId: '894bdff6-61ec-4bec-a5a9-f36a5bfccef5', + ortb2Imp: { + ext: { + tid: '894bdff6-61ec-4bec-a5a9-f36a5bfccef5', + } + }, gftuid: null }]; diff --git a/test/spec/modules/goldbachBidAdapter_spec.js b/test/spec/modules/goldbachBidAdapter_spec.js index fc2c1beb900..93956d2caf9 100644 --- a/test/spec/modules/goldbachBidAdapter_spec.js +++ b/test/spec/modules/goldbachBidAdapter_spec.js @@ -1001,15 +1001,6 @@ describe('GoldbachXandrAdapter', function () { }) describe('interpretResponse', function () { - let bfStub; - before(function() { - bfStub = sinon.stub(bidderFactory, 'getIabSubCategory'); - }); - - after(function() { - bfStub.restore(); - }); - let response = { 'version': '3.0.0', 'tags': [ @@ -1206,7 +1197,6 @@ describe('GoldbachXandrAdapter', function () { } }] }; - bfStub.returns('1'); let result = spec.interpretResponse({ body: response }, {bidderRequest}); expect(result[0]).to.have.property('vastUrl'); diff --git a/test/spec/modules/googleAnalyticsAdapter_spec.js b/test/spec/modules/googleAnalyticsAdapter_spec.js deleted file mode 100644 index b801b5fe696..00000000000 --- a/test/spec/modules/googleAnalyticsAdapter_spec.js +++ /dev/null @@ -1,27 +0,0 @@ -import ga from 'modules/googleAnalyticsAdapter.js'; - -var assert = require('assert'); - -describe('Ga', function () { - describe('enableAnalytics', function () { - var cpmDistribution = function(cpm) { - return cpm <= 1 ? '<= 1$' : '> 1$'; - } - var config = { options: { trackerName: 'foo', enableDistribution: true, cpmDistribution: cpmDistribution } }; - - // enableAnalytics can only be called once - ga.enableAnalytics(config); - - it('should accept a tracker name option and output prefixed send string', function () { - var output = ga.getTrackerSend(); - assert.equal(output, 'foo.send'); - }); - - it('should use the custom cpm distribution', function() { - assert.equal(ga.getCpmDistribution(0.5), '<= 1$'); - assert.equal(ga.getCpmDistribution(1), '<= 1$'); - assert.equal(ga.getCpmDistribution(2), '> 1$'); - assert.equal(ga.getCpmDistribution(5.23), '> 1$'); - }); - }); -}); diff --git a/test/spec/modules/gridBidAdapter_spec.js b/test/spec/modules/gridBidAdapter_spec.js index 775e1a98a9c..4a1148bf377 100644 --- a/test/spec/modules/gridBidAdapter_spec.js +++ b/test/spec/modules/gridBidAdapter_spec.js @@ -22,7 +22,6 @@ describe('TheMediaGrid Adapter', function () { 'sizes': [[300, 250], [300, 600]], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', }; it('should return true when required params found', function () { @@ -47,8 +46,13 @@ describe('TheMediaGrid Adapter', function () { refererInfo: { page: 'https://example.com' }, bidderRequestId: '22edbae2733bf6', transactionId: '1239bd74-4511-4335-af21-e828852e25d7', + timeout: 3000, auctionId: '9e2dfbfe-00c7-4f5e-9850-4044df3229c7', - timeout: 3000 + ortb2: { + source: { + tid: '9e2dfbfe-00c7-4f5e-9850-4044df3229c7', + } + } }; const referrer = encodeURIComponent(bidderRequest.refererInfo.page); let bidRequests = [ @@ -69,6 +73,11 @@ describe('TheMediaGrid Adapter', function () { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '9e2dfbfe-00c7-4f5e-9850-4044df3229c7', transactionId: '1239bd74-4511-4335-af21-e828852e25d7', + ortb2Imp: { + ext: { + tid: '1239bd74-4511-4335-af21-e828852e25d7', + } + } }, { 'bidder': 'grid', @@ -81,6 +90,11 @@ describe('TheMediaGrid Adapter', function () { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '9e2dfbfe-00c7-4f5e-9850-4044df3229c7', transactionId: '1239bd74-4511-4335-af21-e828852e25d7', + ortb2Imp: { + ext: { + tid: '1239bd74-4511-4335-af21-e828852e25d7', + } + } }, { 'bidder': 'grid', @@ -99,6 +113,11 @@ describe('TheMediaGrid Adapter', function () { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '9e2dfbfe-00c7-4f5e-9850-4044df3229c7', transactionId: '1239bd74-4511-4335-af21-e828852e25d7', + ortb2Imp: { + ext: { + tid: '1239bd74-4511-4335-af21-e828852e25d7', + } + } }, { 'bidder': 'grid', @@ -120,6 +139,11 @@ describe('TheMediaGrid Adapter', function () { 'bidderRequestId': '22edbae2733bf6', 'auctionId': '9e2dfbfe-00c7-4f5e-9850-4044df3229c7', transactionId: '1239bd74-4511-4335-af21-e828852e25d7', + ortb2Imp: { + ext: { + tid: '1239bd74-4511-4335-af21-e828852e25d7', + } + } } ]; @@ -152,7 +176,7 @@ describe('TheMediaGrid Adapter', function () { }, 'tmax': bidderRequest.timeout, 'source': { - 'tid': bidderRequest.auctionId, + 'tid': bidderRequest.ortb2.source.tid, 'ext': {'wrapper': 'Prebid_js', 'wrapper_version': '$prebid.version$'} }, 'user': { @@ -400,169 +424,6 @@ describe('TheMediaGrid Adapter', function () { getDataFromLocalStorageStub.restore(); }); - it('should send additional request with adUnits with withCriteo parameter', function () { - const fpdUserIdVal = '0b0f84a1-1596-4165-9742-2e1a7dfac57f'; - const getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage').callsFake( - arg => arg === 'tmguid' ? fpdUserIdVal : null); - - const bidRequestsWithCriteo = bidRequests.map((bid, i) => - i % 2 ? bid : { - ...bid, - params: { - ...bid.params, - withCriteo: true, - networkId: 123 + i - }, - mediaTypes: { - ...bid.mediaTypes, - ...(bid.mediaTypes.video && { video: { - ...bid.mediaTypes.video, - context: 'instream', - protocols: [1, 2, 3], - maxduration: 30, - api: [1, 2], - skip: 1, - placement: 1, - plcmt: 2, - minduration: 0, - playbackmethod: 1, - startdelay: 0 - } - }) - } - }); - - const [request, criteoRequest] = spec.buildRequests(bidRequestsWithCriteo, bidderRequest); - expect(request.data).to.be.an('string'); - expect(criteoRequest.data).to.be.an('object'); - const payload = parseRequest(request.data); - const criteoPayload = criteoRequest.data; - expect(request.url).to.equal('https://grid.bidswitch.net/hbjson'); - expect(criteoRequest.url.replace(/\?.*$/, '')) - .to.equal('https://bidder.criteo.com/cdb'); - expect(payload).to.deep.equal({ - 'id': bidderRequest.bidderRequestId, - 'site': { - 'page': referrer - }, - 'tmax': bidderRequest.timeout, - 'source': { - 'tid': bidderRequest.auctionId, - 'ext': {'wrapper': 'Prebid_js', 'wrapper_version': '$prebid.version$'} - }, - 'user': { - 'id': fpdUserIdVal - }, - 'imp': [{ - 'id': bidRequests[0].bidId, - 'tagid': bidRequests[0].params.uid, - 'ext': {'divid': bidRequests[0].adUnitCode}, - 'bidfloor': bidRequests[0].params.bidFloor, - 'banner': { - 'w': 300, - 'h': 250, - 'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}] - } - }, { - 'id': bidRequests[1].bidId, - 'tagid': bidRequests[1].params.uid, - 'ext': {'divid': bidRequests[1].adUnitCode}, - 'banner': { - 'w': 300, - 'h': 250, - 'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}] - } - }, { - 'id': bidRequests[2].bidId, - 'tagid': bidRequests[2].params.uid, - 'ext': {'divid': bidRequests[2].adUnitCode}, - 'video': { - 'w': 400, - 'h': 600, - 'protocols': [1, 2, 3], - 'mimes': ['video/mp4', 'video/webm', 'application/javascript', 'video/ogg'], - 'context': 'instream', - 'maxduration': 30, - 'minduration': 0, - 'api': [1, 2], - 'skip': 1, - 'placement': 1, - 'plcmt': 2, - 'playbackmethod': 1, - 'startdelay': 0 - } - }, { - 'id': bidRequests[3].bidId, - 'tagid': bidRequests[3].params.uid, - 'ext': {'divid': bidRequests[3].adUnitCode}, - 'banner': { - 'w': 728, - 'h': 90, - 'format': [{'w': 728, 'h': 90}] - }, - 'video': { - 'w': 400, - 'h': 600, - 'protocols': [1, 2, 3] - } - }] - }); - - expect(criteoPayload).to.deep.equal({ - 'publisher': { - 'ext': undefined, - 'url': bidderRequest.refererInfo.page, - 'networkid': 125 - }, - 'regs': { - 'coppa': undefined - }, - 'slots': [{ - 'impid': bidRequests[0].adUnitCode, - 'transactionid': bidderRequest.transactionId, - 'auctionId': bidderRequest.auctionId, - 'sizes': ['300x250', '300x600'] - }, { - 'impid': bidRequests[2].adUnitCode, - 'transactionid': bidderRequest.transactionId, - 'auctionId': bidderRequest.auctionId, - 'sizes': [], - 'video': { - 'api': [ - 1, - 2 - ], - 'maxduration': 30, - 'mimes': [ - 'video/mp4', - 'video/webm', - 'application/javascript', - 'video/ogg', - ], - 'minduration': 0, - 'placement': 1, - 'plcmt': 2, - 'playbackmethod': 1, - 'playersizes': [ - '400x600' - ], - 'protocols': [ - 1, - 2, - 3 - ], - 'skip': 1, - 'startdelay': 0 - } - }], - 'user': { - 'ext': undefined - } - }); - - getDataFromLocalStorageStub.restore(); - }); - it('if gdprConsent is present payload must have gdpr params', function () { const gdprBidderRequest = Object.assign({gdprConsent: {consentString: 'AAA', gdprApplies: true}}, bidderRequest); const [request] = spec.buildRequests(bidRequests, gdprBidderRequest); @@ -600,7 +461,13 @@ describe('TheMediaGrid Adapter', function () { it('should add gpp information to the request via bidderRequest.ortb2.regs.gpp', function () { let consentString = 'abc1234'; - const gppBidderRequest = Object.assign({ortb2: {regs: {gpp: consentString, gpp_sid: [8]}}}, bidderRequest); + const gppBidderRequest = { + ...bidderRequest, + ortb2: { + regs: {gpp: consentString, gpp_sid: [8]}, + ...bidderRequest.ortb2 + } + }; const [request] = spec.buildRequests(bidRequests, gppBidderRequest); const payload = JSON.parse(request.data); @@ -897,7 +764,7 @@ describe('TheMediaGrid Adapter', function () { } }]; const bidRequestsWithOrtb2Imp = bidRequests.slice(0, 3).map((bid, ind) => { - return Object.assign(ortb2Imp[ind] ? { ortb2Imp: ortb2Imp[ind] } : {}, bid); + return Object.assign({}, bid, ortb2Imp[ind] ? { ortb2Imp: {...bid.ortb2Imp, ...ortb2Imp[ind]} } : {}); }); const [request] = spec.buildRequests(bidRequestsWithOrtb2Imp, bidderRequest); expect(request.data).to.be.an('string'); @@ -934,7 +801,7 @@ describe('TheMediaGrid Adapter', function () { } }]; const bidRequestsWithOrtb2Imp = bidRequests.slice(0, 3).map((bid, ind) => { - return Object.assign(ortb2Imp[ind] ? { ortb2Imp: ortb2Imp[ind] } : {}, bid); + return Object.assign({}, bid, ortb2Imp[ind] ? { ortb2Imp: ortb2Imp[ind] } : {}); }); const [request] = spec.buildRequests(bidRequestsWithOrtb2Imp, bidderRequest); expect(request.data).to.be.an('string'); @@ -966,8 +833,12 @@ describe('TheMediaGrid Adapter', function () { const bidderRequestWithNumId = { refererInfo: {page: 'https://example.com'}, bidderRequestId: 345345345, - auctionId: 654645, - timeout: 3000 + timeout: 3000, + ortb2: { + source: { + tid: 654645 + } + } }; const parsedReferrer = encodeURIComponent(bidderRequestWithNumId.refererInfo.page); const [request] = spec.buildRequests([bidRequestWithNumId], bidderRequestWithNumId); @@ -1529,137 +1400,6 @@ describe('TheMediaGrid Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should add response with biggest price', function () { - const mainResponse = [ - {'bid': [{'impid': '2164be6358b9', 'price': 1.15, 'adm': '
test content 1
', 'auid': 1, 'h': 250, 'w': 300, dealid: 11}], 'seat': '1'}, - {'bid': [{'impid': '4e111f1b66e4', 'price': 0.5, 'adm': '
test content 2
', 'auid': 2, 'h': 600, 'w': 300, dealid: 12}], 'seat': '1'}, - ]; - const criteoResponse = [ - { - impid: 'adunit-code-1', - cpm: 0.15, - creative: '
test content 3
', - creativecode: 1, - bidId: '2164be6358b9', - currency: 'USD', - width: 300, - height: 250, - dealCode: 11, - zoneid: 123, - ttl: 360, - adomain: ['criteo.com'], - }, - { - impid: 'adunit-code-1', - cpm: 1, - creative: '
test content 4
', - creativecode: 2, - bidId: '4e111f1b66e4', - currency: 'USD', - width: 300, - height: 600, - dealCode: 12, - zoneid: 456, - ttl: 360, - adomain: ['criteo.com'], - } - ]; - const bidRequests = [ - { - 'bidder': 'grid', - 'params': { - 'uid': '1', - 'zoneId': 123, - 'withCriteo': true - }, - 'adUnitCode': 'adunit-code-1', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '2164be6358b9', - 'bidderRequestId': '106efe3247', - 'auctionId': '32a1f276cb87cb8', - 'transactionId': '43534f55b213ac', - }, - { - 'bidder': 'grid', - 'params': { - 'uid': '2', - 'zoneId': 456, - 'withCriteo': true - }, - 'adUnitCode': 'adunit-code-1', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '4e111f1b66e4', - 'bidderRequestId': '106efe3247', - 'auctionId': '32a1f276cb87cb8', - 'transactionId': '43534f55b213ac', - } - ]; - const bidderRequest = { - refererInfo: { page: 'https://example.com' }, - bidderRequestId: '106efe3247', - transactionId: '43534f55b213ac', - auctionId: '32a1f276cb87cb8', - timeout: 3000 - }; - const [mainRequest, criteoRequest] = spec.buildRequests(bidRequests, bidderRequest); - const expectedMainResponse = [ - { - 'requestId': '2164be6358b9', - 'cpm': 1.15, - 'creativeId': 1, - 'dealId': 11, - 'width': 300, - 'height': 250, - 'ad': '
test content 1
', - 'currency': 'USD', - 'mediaType': 'banner', - 'netRevenue': true, - 'ttl': 360, - 'meta': { - advertiserDomains: [] - }, - }, - { - 'requestId': '4e111f1b66e4', - 'cpm': 0.5, - 'creativeId': 2, - 'dealId': 12, - 'width': 300, - 'height': 600, - 'ad': '
test content 2
', - 'currency': 'USD', - 'mediaType': 'banner', - 'netRevenue': true, - 'ttl': 360, - 'meta': { - advertiserDomains: [] - }, - } - ]; - const expectedCriteoResponse = [ - { - 'requestId': '4e111f1b66e4', - 'cpm': 1, - 'creativeId': 2, - 'dealId': 12, - 'width': 300, - 'height': 600, - 'ad': '
test content 4
', - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 360, - 'meta': { - advertiserDomains: ['criteo.com'] - }, - } - ]; - - const mainResult = spec.interpretResponse({'body': {'seatbid': mainResponse}}, mainRequest); - const criteoResult = spec.interpretResponse({'body': {'slots': criteoResponse}}, criteoRequest); - expect(mainResult).to.deep.equal(expectedMainResponse); - expect(criteoResult).to.deep.equal(expectedCriteoResponse); - }); - it('response with ext.bidder.grid.demandSource', function () { const bidRequests = [ { diff --git a/test/spec/modules/hybridBidAdapter_spec.js b/test/spec/modules/hybridBidAdapter_spec.js index 6c98264c06f..a0d479fb4dc 100644 --- a/test/spec/modules/hybridBidAdapter_spec.js +++ b/test/spec/modules/hybridBidAdapter_spec.js @@ -8,7 +8,11 @@ function getSlotConfigs(mediaTypes, params) { bidId: '2df8c0733f284e', bidder: 'hybrid', mediaTypes: mediaTypes, - transactionId: '31a58515-3634-4e90-9c96-f86196db1459' + ortb2Imp: { + ext: { + tid: '31a58515-3634-4e90-9c96-f86196db1459' + } + } } } diff --git a/test/spec/modules/synacormediaBidAdapter_spec.js b/test/spec/modules/imdsBidAdapter_spec.js similarity index 98% rename from test/spec/modules/synacormediaBidAdapter_spec.js rename to test/spec/modules/imdsBidAdapter_spec.js index 747dc4edc63..ce04fabe02b 100644 --- a/test/spec/modules/synacormediaBidAdapter_spec.js +++ b/test/spec/modules/imdsBidAdapter_spec.js @@ -1,9 +1,10 @@ import { assert, expect } from 'chai'; import { BANNER } from 'src/mediaTypes.js'; import { config } from 'src/config.js'; -import { spec } from 'modules/synacormediaBidAdapter.js'; +import { spec } from 'modules/imdsBidAdapter.js'; +import * as utils from 'src/utils.js'; -describe('synacormediaBidAdapter ', function () { +describe('imdsBidAdapter ', function () { describe('isBidRequestValid', function () { let bid; beforeEach(function () { @@ -115,7 +116,7 @@ describe('synacormediaBidAdapter ', function () { }); describe('buildRequests', function () { let validBidRequestVideo = { - bidder: 'synacormedia', + bidder: 'imds', params: { seatId: 'prebid', tagId: '1234', @@ -140,7 +141,7 @@ describe('synacormediaBidAdapter ', function () { }; let bidderRequestVideo = { - bidderCode: 'synacormedia', + bidderCode: 'imds', auctionId: 'VideoAuctionId124', bidderRequestId: '117954d20d7c9c', auctionStart: 1553624929697, @@ -177,7 +178,7 @@ describe('synacormediaBidAdapter ', function () { }; let bidderRequest = { - auctionId: 'xyz123', + bidderRequestId: 'xyz123', refererInfo: { referer: 'https://test.com/foo/bar' } @@ -192,7 +193,7 @@ describe('synacormediaBidAdapter ', function () { }; let bidderRequestWithCCPA = { - auctionId: 'xyz123', + bidderRequestId: 'xyz123', refererInfo: { referer: 'https://test.com/foo/bar' }, @@ -299,7 +300,6 @@ describe('synacormediaBidAdapter ', function () { expect(reqVideo).to.have.property('url'); expect(reqVideo.url).to.contain('https://prebid.technoratimedia.com/openrtb/bids/prebid?'); expect(reqVideo.data).to.exist.and.to.be.an('object'); - expect(reqVideo.data.id).to.equal('VideoAuctionId124'); expect(reqVideo.data.imp).to.eql([expectedDataVideo1]); }); @@ -543,7 +543,7 @@ describe('synacormediaBidAdapter ', function () { }); it('should use all the video params in the impression request', function () { let validBidRequestVideo = { - bidder: 'synacormedia', + bidder: 'imds', params: { seatId: 'prebid', tagId: '1234', @@ -601,7 +601,7 @@ describe('synacormediaBidAdapter ', function () { }); it('should move any video params in the mediaTypes object to params.video object', function () { let validBidRequestVideo = { - bidder: 'synacormedia', + bidder: 'imds', params: { seatId: 'prebid', tagId: '1234', @@ -659,7 +659,7 @@ describe('synacormediaBidAdapter ', function () { }); it('should create params.video object if not present on bid request and move any video params in the mediaTypes object to it', function () { let validBidRequestVideo = { - bidder: 'synacormedia', + bidder: 'imds', params: { seatId: 'prebid', tagId: '1234' @@ -731,7 +731,7 @@ describe('synacormediaBidAdapter ', function () { describe('Bid Requests with placementId should be backward compatible ', function () { let validVideoBidReq = { - bidder: 'synacormedia', + bidder: 'imds', params: { seatId: 'prebid', placementId: 'demo1', @@ -772,7 +772,7 @@ describe('synacormediaBidAdapter ', function () { refererInfo: { referer: 'http://localhost:9999/' }, - bidderCode: 'synacormedia', + bidderCode: 'imds', auctionId: 'f8a75621-d672-4cbb-9275-3db7d74fb110' }; @@ -793,7 +793,7 @@ describe('synacormediaBidAdapter ', function () { describe('Bid Requests with schain object ', function () { let validBidReq = { - bidder: 'synacormedia', + bidder: 'imds', params: { seatId: 'prebid', tagId: 'demo1', @@ -835,12 +835,12 @@ describe('synacormediaBidAdapter ', function () { refererInfo: { referer: 'http://localhost:9999/' }, - bidderCode: 'synacormedia', + bidderCode: 'imds', auctionId: 'f8a75621-d672-4cbb-9275-3db7d74fb110', bidderRequestId: '16d438671bfbec', bids: [ { - bidder: 'synacormedia', + bidder: 'imds', params: { seatId: 'prebid', tagId: 'demo1', @@ -1313,7 +1313,7 @@ describe('synacormediaBidAdapter ', function () { describe('Bid Requests with price module should use if available', function () { let validVideoBidRequest = { - bidder: 'synacormedia', + bidder: 'imds', params: { bidfloor: '0.50', seatId: 'prebid', @@ -1356,7 +1356,7 @@ describe('synacormediaBidAdapter ', function () { refererInfo: { referer: 'http://localhost:9999/' }, - bidderCode: 'synacormedia', + bidderCode: 'imds', auctionId: 'f8a75621-d672-4cbb-9275-3db7d74fb110' }; @@ -1383,7 +1383,7 @@ describe('synacormediaBidAdapter ', function () { describe('Bid Requests with gpid or anything in bid.ext should use if available', function () { let validVideoBidRequest = { - bidder: 'synacormedia', + bidder: 'imds', params: { seatId: 'prebid', placementId: 'demo1', @@ -1440,7 +1440,7 @@ describe('synacormediaBidAdapter ', function () { refererInfo: { referer: 'http://localhost:9999/' }, - bidderCode: 'synacormedia', + bidderCode: 'imds', auctionId: 'f8a75621-d672-4cbb-9275-3db7d74fb110' }; diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index 1c3bd3197d0..f427f9e7624 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -119,6 +119,11 @@ describe('Improve Digital Adapter Tests', function () { }; const bidderRequest = { + ortb2: { + source: { + tid: 'mock-tid' + } + }, bids: [simpleBidRequest], }; @@ -236,7 +241,7 @@ describe('Improve Digital Adapter Tests', function () { expect(payload.tmax).not.to.exist; expect(payload.regs).to.not.exist; expect(payload.schain).to.not.exist; - sinon.assert.match(payload.source, {tid: 'f183e871-fbed-45f0-a427-c8a63c4c01eb'}) + sinon.assert.match(payload.source, {tid: 'mock-tid'}) expect(payload.device).to.be.an('object'); expect(payload.user).to.not.exist; sinon.assert.match(payload.imp, [ diff --git a/test/spec/modules/inmarBidAdapter_spec.js b/test/spec/modules/inmarBidAdapter_spec.js deleted file mode 100644 index d21fcbc377b..00000000000 --- a/test/spec/modules/inmarBidAdapter_spec.js +++ /dev/null @@ -1,242 +0,0 @@ -// import or require modules necessary for the test, e.g.: -import {expect} from 'chai'; // may prefer 'assert' in place of 'expect' -import { - spec -} from 'modules/inmarBidAdapter.js'; -import {config} from 'src/config.js'; - -describe('Inmar adapter tests', function () { - var DEFAULT_PARAMS_NEW_SIZES = [{ - adUnitCode: 'test-div', - bidId: '2c7c8e9c900244', - mediaTypes: { - banner: { - sizes: [ - [300, 250], [300, 600], [728, 90], [970, 250]] - } - }, - bidder: 'inmar', - params: { - partnerId: 12345 - }, - auctionId: '0cb3144c-d084-4686-b0d6-f5dbe917c563', - bidRequestsCount: 1, - bidderRequestId: '1858b7382993ca', - transactionId: '29df2112-348b-4961-8863-1b33684d95e6', - user: {} - }]; - - var DEFAULT_PARAMS_VIDEO = [{ - adUnitCode: 'test-div', - bidId: '2c7c8e9c900244', - mediaTypes: { - video: { - context: 'instream', // or 'outstream' - playerSize: [640, 480], - mimes: ['video/mp4'] - } - }, - bidder: 'inmar', - params: { - partnerId: 12345 - }, - auctionId: '0cb3144c-d084-4686-b0d6-f5dbe917c563', - bidRequestsCount: 1, - bidderRequestId: '1858b7382993ca', - transactionId: '29df2112-348b-4961-8863-1b33684d95e6', - user: {} - }]; - - var DEFAULT_PARAMS_WO_OPTIONAL = [{ - adUnitCode: 'test-div', - bidId: '2c7c8e9c900244', - sizes: [ - [300, 250], - [300, 600], - [728, 90], - [970, 250] - ], - bidder: 'inmar', - params: { - partnerId: 12345, - }, - auctionId: '851adee7-d843-48f9-a7e9-9ff00573fcbf', - bidRequestsCount: 1, - bidderRequestId: '1858b7382993ca', - transactionId: '29df2112-348b-4961-8863-1b33684d95e6' - }]; - - var BID_RESPONSE = { - body: { - cpm: 1.50, - ad: '', - meta: { - mediaType: 'banner', - }, - width: 300, - height: 250, - creativeId: '189198063', - netRevenue: true, - currency: 'USD', - ttl: 300, - dealId: 'dealId' - - } - }; - - var BID_RESPONSE_VIDEO = { - body: { - cpm: 1.50, - meta: { - mediaType: 'video', - }, - width: 1, - height: 1, - creativeId: '189198063', - netRevenue: true, - currency: 'USD', - ttl: 300, - vastUrl: 'https://vast.com/vast.xml', - dealId: 'dealId' - } - }; - - it('Verify build request to prebid 3.0 display test', function() { - const request = spec.buildRequests(DEFAULT_PARAMS_NEW_SIZES, { - gdprConsent: { - consentString: 'BOZcQl_ObPFjWAeABAESCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NohBgA', - gdprApplies: true - }, - refererInfo: { - legacy: { - referer: 'https://domain.com', - numIframes: 0 - } - } - }); - - expect(request).to.have.property('method').and.to.equal('POST'); - const requestContent = JSON.parse(request.data); - expect(requestContent.bidRequests[0].params).to.have.property('partnerId').and.to.equal(12345); - expect(requestContent.bidRequests[0]).to.have.property('auctionId').and.to.equal('0cb3144c-d084-4686-b0d6-f5dbe917c563'); - expect(requestContent.bidRequests[0]).to.have.property('bidId').and.to.equal('2c7c8e9c900244'); - expect(requestContent.bidRequests[0]).to.have.property('bidRequestsCount').and.to.equal(1); - expect(requestContent.bidRequests[0]).to.have.property('bidder').and.to.equal('inmar'); - expect(requestContent.bidRequests[0]).to.have.property('bidderRequestId').and.to.equal('1858b7382993ca'); - expect(requestContent.bidRequests[0]).to.have.property('adUnitCode').and.to.equal('test-div'); - expect(requestContent.refererInfo).to.have.property('referer').and.to.equal('https://domain.com'); - expect(requestContent.bidRequests[0].mediaTypes.banner).to.have.property('sizes'); - expect(requestContent.bidRequests[0].mediaTypes.banner.sizes[0]).to.have.ordered.members([300, 250]); - expect(requestContent.bidRequests[0].mediaTypes.banner.sizes[1]).to.have.ordered.members([300, 600]); - expect(requestContent.bidRequests[0].mediaTypes.banner.sizes[2]).to.have.ordered.members([728, 90]); - expect(requestContent.bidRequests[0].mediaTypes.banner.sizes[3]).to.have.ordered.members([970, 250]); - expect(requestContent.bidRequests[0]).to.have.property('transactionId').and.to.equal('29df2112-348b-4961-8863-1b33684d95e6'); - expect(requestContent.refererInfo).to.have.property('numIframes').and.to.equal(0); - }) - - it('Verify interprete response', function () { - const request = spec.buildRequests(DEFAULT_PARAMS_NEW_SIZES, { - gdprConsent: { - consentString: 'BOZcQl_ObPFjWAeABAESCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NohBgA', - gdprApplies: true - }, - refererInfo: { - referer: 'https://domain.com', - numIframes: 0 - } - }); - - const bids = spec.interpretResponse(BID_RESPONSE, request); - expect(bids).to.have.lengthOf(1); - const bid = bids[0]; - expect(bid.cpm).to.equal(1.50); - expect(bid.ad).to.equal(''); - expect(bid.meta.mediaType).to.equal('banner'); - expect(bid.width).to.equal(300); - expect(bid.height).to.equal(250); - expect(bid.creativeId).to.equal('189198063'); - expect(bid.netRevenue).to.equal(true); - expect(bid.currency).to.equal('USD'); - expect(bid.ttl).to.equal(300); - expect(bid.dealId).to.equal('dealId'); - }); - - it('no banner media response', function () { - const request = spec.buildRequests(DEFAULT_PARAMS_NEW_SIZES, { - gdprConsent: { - consentString: 'BOZcQl_ObPFjWAeABAESCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NohBgA', - gdprApplies: true - }, - refererInfo: { - referer: 'https://domain.com', - numIframes: 0 - } - }); - - const bids = spec.interpretResponse(BID_RESPONSE_VIDEO, request); - const bid = bids[0]; - expect(bid.vastUrl).to.equal('https://vast.com/vast.xml'); - }); - - it('Verifies bidder_code', function () { - expect(spec.code).to.equal('inmar'); - }); - - it('Verifies bidder aliases', function () { - expect(spec.aliases).to.have.lengthOf(1); - expect(spec.aliases[0]).to.equal('inm'); - }); - - it('Verifies if bid request is valid', function () { - expect(spec.isBidRequestValid(DEFAULT_PARAMS_NEW_SIZES[0])).to.equal(true); - expect(spec.isBidRequestValid(DEFAULT_PARAMS_WO_OPTIONAL[0])).to.equal(true); - expect(spec.isBidRequestValid({})).to.equal(false); - expect(spec.isBidRequestValid({ - params: {} - })).to.equal(false); - expect(spec.isBidRequestValid({ - params: { - } - })).to.equal(false); - expect(spec.isBidRequestValid({ - params: { - partnerId: 12345 - } - })).to.equal(true); - }); - - it('Verifies user syncs image', function () { - var syncs = spec.getUserSyncs({ - iframeEnabled: false, - pixelEnabled: true - }, [BID_RESPONSE], { - consentString: 'BOZcQl_ObPFjWAeABAESCD-AAAAjx7_______9______9uz_Ov_v_f__33e8__9v_l_7_-___u_-33d4-_1vf99yfm1-7ftr3tp_87ues2_Xur__59__3z3_NohBgA', - referer: 'http://domain.com', - gdprApplies: true - }) - expect(syncs).to.have.lengthOf(1); - expect(syncs[0].type).to.equal('image'); - - syncs = spec.getUserSyncs({ - iframeEnabled: false, - pixelEnabled: true - }, [BID_RESPONSE], { - consentString: '', - referer: 'http://domain.com', - gdprApplies: true - }) - expect(syncs).to.have.lengthOf(1); - expect(syncs[0].type).to.equal('image'); - - syncs = spec.getUserSyncs({ - iframeEnabled: false, - pixelEnabled: true - }, [], { - consentString: null, - referer: 'http://domain.com', - gdprApplies: true - }) - expect(syncs).to.have.lengthOf(1); - expect(syncs[0].type).to.equal('image'); - }); -}); diff --git a/test/spec/modules/inskinBidAdapter_spec.js b/test/spec/modules/inskinBidAdapter_spec.js deleted file mode 100644 index 3d0ec82fca5..00000000000 --- a/test/spec/modules/inskinBidAdapter_spec.js +++ /dev/null @@ -1,386 +0,0 @@ -import { expect } from 'chai'; -import { spec } from 'modules/inskinBidAdapter.js'; -import { createBid } from 'src/bidfactory.js'; - -const ENDPOINT = 'https://mfad.inskinad.com/api/v2'; - -const REQUEST = { - 'bidderCode': 'inskin', - 'requestId': 'a4713c32-3762-4798-b342-4ab810ca770d', - 'bidderRequestId': '109f2a181342a9', - 'bidRequest': [{ - 'bidder': 'inskin', - 'params': { - 'networkId': 9874, - 'siteId': 730181, - 'publisherId': 123456 - }, - 'placementCode': 'div-gpt-ad-1487778092495-0', - 'sizes': [ - [728, 90], - [970, 90] - ], - 'bidId': '2b0f82502298c9', - 'bidderRequestId': '109f2a181342a9', - 'requestId': 'a4713c32-3762-4798-b342-4ab810ca770d' - }, - { - 'bidder': 'inskin', - 'params': { - 'networkId': 9874, - 'siteId': 730181 - }, - 'placementCode': 'div-gpt-ad-1487778092495-0', - 'sizes': [ - [728, 90], - [970, 90] - ], - 'bidId': '123', - 'bidderRequestId': '109f2a181342a9', - 'requestId': 'a4713c32-3762-4798-b342-4ab810ca770d' - }], - 'start': 1487883186070, - 'auctionStart': 1487883186069, - 'timeout': 3000 -}; - -const RESPONSE = { - 'headers': null, - 'body': { - 'user': { 'key': 'ue1-2d33e91b71e74929b4aeecc23f4376f1' }, - 'decisions': { - '2b0f82502298c9': { - 'adId': 2364764, - 'creativeId': 1950991, - 'flightId': 2788300, - 'campaignId': 542982, - 'clickUrl': 'https://mfad.inskinad.com/r', - 'impressionUrl': 'https://mfad.inskinad.com/i.gif', - 'contents': [{ - 'type': 'html', - 'body': '', - 'data': { - 'height': 90, - 'width': 728, - 'imageUrl': 'https://static.adzerk.net/Advertisers/b0ab77db8a7848c8b78931aed022a5ef.gif', - 'fileName': 'b0ab77db8a7848c8b78931aed022a5ef.gif' - }, - 'template': 'image' - }], - 'height': 90, - 'width': 728, - 'events': [], - 'pricing': {'price': 0.5, 'clearPrice': 0.5, 'revenue': 0.0005, 'rateType': 2, 'eCPM': 0.5} - }, - '123': { - 'adId': 2364764, - 'creativeId': 1950991, - 'flightId': 2788300, - 'campaignId': 542982, - 'clickUrl': 'https://mfad.inskinad.com/r', - 'impressionUrl': 'https://mfad.inskinad.com/i.gif', - 'contents': [{ - 'type': 'html', - 'body': '', - 'data': { - 'customData': { - 'pubCPM': 1 - }, - 'height': 90, - 'width': 728, - 'imageUrl': 'https://static.adzerk.net/Advertisers/b0ab77db8a7848c8b78931aed022a5ef.gif', - 'fileName': 'b0ab77db8a7848c8b78931aed022a5ef.gif' - }, - 'template': 'image' - }], - 'height': 90, - 'width': 728, - 'events': [], - 'pricing': {'price': 0.5, 'clearPrice': 0.5, 'revenue': 0.0005, 'rateType': 2, 'eCPM': 0.5} - } - } - } -}; - -const consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; -const bidderRequest = { - bidderCode: 'inskin', - gdprConsent: { - consentString: consentString, - gdprApplies: true - }, - refererInfo: { - referer: 'https://www.inskinmedia.com' - } -}; - -describe('InSkin BidAdapter', function () { - let bidRequests; - let adapter = spec; - - beforeEach(function () { - bidRequests = [ - { - bidder: 'inskin', - params: { - networkId: '9874', - siteId: 'xxxxx' - }, - placementCode: 'header-bid-tag-1', - sizes: [[300, 250], [300, 600]], - bidId: '23acc48ad47af5', - requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', - bidderRequestId: '1c56ad30b9b8ca8', - transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' - } - ]; - }); - - describe('bid request validation', function () { - it('should accept valid bid requests', function () { - let bid = { - bidder: 'inskin', - params: { - networkId: '9874', - siteId: 'xxxxx' - } - }; - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should accept valid bid requests with extra fields', function () { - let bid = { - bidder: 'inskin', - params: { - networkId: '9874', - siteId: 'xxxxx', - zoneId: 'xxxxx' - } - }; - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should reject bid requests without siteId', function () { - let bid = { - bidder: 'inskin', - params: { - networkId: '9874' - } - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - - it('should reject bid requests without networkId', function () { - let bid = { - bidder: 'inskin', - params: { - siteId: '9874' - } - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequests validation', function () { - it('creates request data', function () { - let request = spec.buildRequests(bidRequests, bidderRequest); - - expect(request).to.exist.and.to.be.a('object'); - }); - - it('request to inskin should contain a url', function () { - let request = spec.buildRequests(bidRequests, bidderRequest); - - expect(request.url).to.have.string('inskinad.com'); - }); - - it('requires valid bids to make request', function () { - let request = spec.buildRequests([], bidderRequest); - expect(request.bidRequest).to.be.empty; - }); - - it('sends bid request to ENDPOINT via POST', function () { - let request = spec.buildRequests(bidRequests, bidderRequest); - - expect(request.method).to.have.string('POST'); - }); - - it('should add gdpr consent information to the request', function () { - bidderRequest.bids = bidRequests; - - const request = spec.buildRequests(bidRequests, bidderRequest); - const payload = JSON.parse(request.data); - - expect(payload.consent.gdprConsentString).to.exist; - expect(payload.consent.gdprConsentRequired).to.exist; - expect(payload.consent.gdprConsentString).to.exist.and.to.equal(consentString); - expect(payload.consent.gdprConsentRequired).to.exist.and.to.be.true; - }); - - it('should not add keywords if TCF v2 purposes are granted', function () { - const bidderRequest2 = Object.assign({}, bidderRequest, { - gdprConsent: { - gdprApplies: true, - consentString: 'consentString', - vendorData: { - vendor: { - consents: { - 150: true - } - }, - purpose: { - consents: { - 1: true, - 2: true, - 3: true, - 4: true, - 5: true, - 6: true, - 7: true, - 8: true, - 9: true, - 10: true - } - } - }, - apiVersion: 2 - } - }); - - const request = spec.buildRequests(bidRequests, bidderRequest2); - const payload = JSON.parse(request.data); - - expect(payload.keywords).to.be.an('array').that.is.empty; - expect(payload.placements[0].properties.restrictions).to.be.undefined; - }); - - it('should add keywords if TCF v2 purposes are not granted', function () { - const bidderRequest2 = Object.assign({}, bidderRequest, { - gdprConsent: { - gdprApplies: true, - consentString: 'consentString', - vendorData: { - vendor: { - consents: { - 150: false - } - }, - purpose: { - consents: { - 1: true, - 2: true, - 3: true, - 4: true, - 5: true, - 6: true, - 7: true, - 8: true, - 9: true, - 10: true - } - } - }, - apiVersion: 2 - } - }); - - const request = spec.buildRequests(bidRequests, bidderRequest2); - const payload = JSON.parse(request.data); - - expect(payload.keywords).to.be.an('array').that.includes('cst-nocookies'); - expect(payload.keywords).to.be.an('array').that.includes('cst-nocontext'); - expect(payload.keywords).to.be.an('array').that.includes('cst-nodmp'); - expect(payload.keywords).to.be.an('array').that.includes('cst-nodata'); - expect(payload.keywords).to.be.an('array').that.includes('cst-noclicks'); - expect(payload.keywords).to.be.an('array').that.includes('cst-noresearch'); - - expect(payload.placements[0].properties.restrictions).to.be.an('array').that.includes('nocookies'); - expect(payload.placements[0].properties.restrictions).to.be.an('array').that.includes('nocontext'); - expect(payload.placements[0].properties.restrictions).to.be.an('array').that.includes('nodmp'); - expect(payload.placements[0].properties.restrictions).to.be.an('array').that.includes('nodata'); - expect(payload.placements[0].properties.restrictions).to.be.an('array').that.includes('noclicks'); - expect(payload.placements[0].properties.restrictions).to.be.an('array').that.includes('noresearch'); - }); - }); - describe('interpretResponse validation', function () { - it('response should have valid bidderCode', function () { - let bidRequest = spec.buildRequests(REQUEST.bidRequest, bidderRequest); - let bid = createBid(1, bidRequest.bidRequest[0]); - - expect(bid.bidderCode).to.equal('inskin'); - }); - - it('response should include objects for all bids', function () { - let bids = spec.interpretResponse(RESPONSE, REQUEST); - - expect(bids.length).to.equal(2); - }); - - it('registers bids', function () { - let bids = spec.interpretResponse(RESPONSE, REQUEST); - bids.forEach(b => { - expect(b).to.have.property('cpm'); - expect(b.cpm).to.be.above(0); - expect(b).to.have.property('requestId'); - expect(b).to.have.property('cpm'); - expect(b).to.have.property('width'); - expect(b).to.have.property('height'); - expect(b).to.have.property('ad'); - expect(b).to.have.property('currency', 'USD'); - expect(b).to.have.property('creativeId'); - expect(b).to.have.property('ttl', 360); - expect(b.meta).to.have.property('advertiserDomains'); - expect(b).to.have.property('netRevenue', true); - }); - }); - - it('cpm is correctly set', function () { - let bids = spec.interpretResponse(RESPONSE, REQUEST); - - expect(bids[0].cpm).to.equal(0.5); - expect(bids[1].cpm).to.equal(1); - }); - - it('handles nobid responses', function () { - let EMPTY_RESP = Object.assign({}, RESPONSE, {'body': {'decisions': null}}) - let bids = spec.interpretResponse(EMPTY_RESP, REQUEST); - - expect(bids).to.be.empty; - }); - - it('handles no server response', function () { - let bids = spec.interpretResponse(null, REQUEST); - - expect(bids).to.be.empty; - }); - }); - describe('getUserSyncs', function () { - it('handles empty sync options', function () { - let opts = spec.getUserSyncs({}); - - expect(opts).to.be.empty; - }); - - it('should return two sync urls if pixel syncs are enabled', function () { - let syncOptions = {'pixelEnabled': true}; - let opts = spec.getUserSyncs(syncOptions); - - expect(opts.length).to.equal(2); - }); - - it('should return three sync urls if pixel and iframe syncs are enabled', function () { - let syncOptions = {'iframeEnabled': true, 'pixelEnabled': true}; - let opts = spec.getUserSyncs(syncOptions); - - expect(opts.length).to.equal(3); - }); - }); - describe('supply chain id', function () { - it('should use publisherId as sid', function () { - const request = spec.buildRequests(REQUEST.bidRequest, bidderRequest); - const payload = JSON.parse(request.data); - - expect(payload.rtb.schain.ext.sid).to.equal('123456'); - }); - }); -}); diff --git a/test/spec/modules/insticatorBidAdapter_spec.js b/test/spec/modules/insticatorBidAdapter_spec.js index fc7ed1833ac..de0358f2b46 100644 --- a/test/spec/modules/insticatorBidAdapter_spec.js +++ b/test/spec/modules/insticatorBidAdapter_spec.js @@ -72,7 +72,11 @@ describe('InsticatorBidAdapter', function () { let bidderRequest = { bidderRequestId, - auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', + ortb2: { + source: { + tid: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', + } + }, timeout: 300, gdprConsent: { consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', @@ -248,7 +252,7 @@ describe('InsticatorBidAdapter', function () { expect(data.tmax).to.equal(bidderRequest.timeout); expect(data.source).to.have.all.keys('fd', 'tid', 'ext'); expect(data.source.fd).to.equal(1); - expect(data.source.tid).to.equal(bidderRequest.auctionId); + expect(data.source.tid).to.equal(bidderRequest.ortb2.source.tid); expect(data.source.ext).to.have.property('schain').to.deep.equal({ ver: '1.0', complete: 1, diff --git a/test/spec/modules/invisiblyAnalyticsAdapter_spec.js b/test/spec/modules/invisiblyAnalyticsAdapter_spec.js index 3b3542d43b0..2c460156318 100644 --- a/test/spec/modules/invisiblyAnalyticsAdapter_spec.js +++ b/test/spec/modules/invisiblyAnalyticsAdapter_spec.js @@ -53,7 +53,7 @@ describe('Invisibly Analytics Adapter test suite', function () { hb_source: 'server', }, getStatusCode() { - return CONSTANTS.STATUS.NO_BID; + return CONSTANTS.STATUS.GOOD; }, }; diff --git a/test/spec/modules/ivsBidAdapter_spec.js b/test/spec/modules/ivsBidAdapter_spec.js index 79b3d6811f4..819c7480595 100644 --- a/test/spec/modules/ivsBidAdapter_spec.js +++ b/test/spec/modules/ivsBidAdapter_spec.js @@ -112,9 +112,7 @@ describe('ivsBidAdapter', function () { it('should contain the required parameters', function () { const bidRequest = spec.buildRequests(validBidRequests, validBidderRequest); const bidderRequest = bidRequest.data; - assert.equal(bidderRequest.id, validBidderRequest.auctionId); assert.ok(bidderRequest.site); - assert.ok(bidderRequest.source); assert.lengthOf(bidderRequest.imp, 1); }); }); diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 7c446150b86..783d273e425 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -389,11 +389,11 @@ describe('IndexexchangeAdapter', function () { ext: { tid: '173f49a8-7549-4218-a23c-e7ba59b47230', data: { - pbadslot: 'div-gpt-ad-1460505748562-0' + pbadslot: 'div-gpt-ad-1460505748562-1' } } }, - adUnitCode: 'div-gpt-ad-1460505748562-0', + adUnitCode: 'div-gpt-ad-1460505748562-1', transactionId: '273f49a8-7549-4218-a23c-e7ba59b47230', bidId: '1a2b3c4e', bidderRequestId: '11a22b33c44e', @@ -729,6 +729,9 @@ describe('IndexexchangeAdapter', function () { ortb2: { site: { page: 'https://www.prebid.org' + }, + source: { + tid: 'mock-tid' } } }; @@ -1894,7 +1897,7 @@ describe('IndexexchangeAdapter', function () { expect(payload.source.ext.schain).to.deep.equal(SAMPLE_SCHAIN); expect(payload.imp).to.be.an('array'); expect(payload.imp).to.have.lengthOf(1); - expect(payload.source.tid).to.equal(DEFAULT_BANNER_VALID_BID[0].auctionId); + expect(payload.source.tid).to.equal(DEFAULT_OPTION.ortb2.source.tid); }); it('payload should have correct format and value for r.id when bidderRequestId is a number ', function () { @@ -2432,9 +2435,11 @@ describe('IndexexchangeAdapter', function () { bid1.bidId = '2f6g5s5e'; const bid2 = utils.deepClone(bid1); + bid2.adUnitCode = 'div-gpt-2' bid2.transactionId = 'tr2'; bid2.mediaTypes.banner.sizes = [[220, 221], [222, 223], [300, 250]]; const bid3 = utils.deepClone(bid1); + bid3.adUnitCode = 'div-gpt-3' bid3.transactionId = 'tr3'; bid3.mediaTypes.banner.sizes = [[330, 331], [332, 333], [300, 250]]; diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index d692cc67e26..dae2640d224 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -76,7 +76,6 @@ describe('kargo adapter tests', function () { auctionId: '1234098', bidId: '1', adUnitCode: '101', - transactionId: '10101', sizes: [[320, 50], [300, 250], [300, 600]], mediaTypes: { banner: { @@ -135,6 +134,7 @@ describe('kargo adapter tests', function () { }, ortb2Imp: { ext: { + tid: '10101', data: { adServer: { name: 'gam', @@ -152,7 +152,6 @@ describe('kargo adapter tests', function () { }, bidId: '2', adUnitCode: '202', - transactionId: '20202', sizes: [[320, 50], [300, 250], [300, 600]], mediaTypes: { video: { @@ -164,6 +163,7 @@ describe('kargo adapter tests', function () { bidderWinsCount: 0, ortb2Imp: { ext: { + tid: '20202', data: { adServer: { name: 'gam', @@ -180,7 +180,6 @@ describe('kargo adapter tests', function () { }, bidId: '3', adUnitCode: '303', - transactionId: '30303', sizes: [[320, 50], [300, 250], [300, 600]], mediaTypes: { native: { @@ -189,6 +188,7 @@ describe('kargo adapter tests', function () { }, ortb2Imp: { ext: { + tid: '30303', data: { adServer: { name: 'gam', diff --git a/test/spec/modules/koblerBidAdapter_spec.js b/test/spec/modules/koblerBidAdapter_spec.js index 5fb0bef726e..2b5830f68d2 100644 --- a/test/spec/modules/koblerBidAdapter_spec.js +++ b/test/spec/modules/koblerBidAdapter_spec.js @@ -7,6 +7,7 @@ import {getRefererInfo} from 'src/refererDetection.js'; function createBidderRequest(auctionId, timeout, pageUrl) { return { + bidderRequestId: 'mock-uuid', auctionId: auctionId || 'c1243d83-0bed-4fdb-8c76-42b456be17d0', timeout: timeout || 2000, refererInfo: { @@ -37,6 +38,16 @@ function createValidBidRequest(params, bidId, sizes) { } describe('KoblerAdapter', function () { + let sandbox; + + beforeEach(() => { + sandbox = sinon.sandbox.create(); + }); + + afterEach(() => { + sandbox.restore() + }); + describe('inherited functions', function () { it('exists and is a function', function () { const adapter = newBidder(spec); @@ -207,7 +218,7 @@ describe('KoblerAdapter', function () { const openRtbRequest = JSON.parse(result.data); expect(openRtbRequest.tmax).to.be.equal(timeout); - expect(openRtbRequest.id).to.be.equal(auctionId); + expect(openRtbRequest.id).to.exist; expect(openRtbRequest.site.page).to.be.equal(testUrl); }); @@ -435,7 +446,7 @@ describe('KoblerAdapter', function () { const openRtbRequest = JSON.parse(result.data); const expectedOpenRtbRequest = { - id: '9ff580cf-e10e-4b66-add7-40ac0c804e21', + id: 'mock-uuid', at: 1, tmax: 4500, cur: ['USD'], diff --git a/test/spec/modules/kulturemediaBidAdapter_spec.js b/test/spec/modules/kulturemediaBidAdapter_spec.js index 1872f6c171a..f21fe4a8810 100644 --- a/test/spec/modules/kulturemediaBidAdapter_spec.js +++ b/test/spec/modules/kulturemediaBidAdapter_spec.js @@ -530,7 +530,6 @@ describe('kulturemediaBidAdapter:', function () { let o = { requestId: serverResponse.seatbid[0].bid[0].impid, ad: '', - bidderCode: spec.code, cpm: serverResponse.seatbid[0].bid[0].price, creativeId: serverResponse.seatbid[0].bid[0].crid, vastXml: serverResponse.seatbid[0].bid[0].adm, diff --git a/test/spec/modules/limelightDigitalBidAdapter_spec.js b/test/spec/modules/limelightDigitalBidAdapter_spec.js index 5a92110abb4..0e6f4817e5e 100644 --- a/test/spec/modules/limelightDigitalBidAdapter_spec.js +++ b/test/spec/modules/limelightDigitalBidAdapter_spec.js @@ -24,7 +24,11 @@ describe('limelightDigitalAdapter', function () { sizes: [[300, 250]] } }, - transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62', + ortb2Imp: { + ext: { + tid: '3bb2f6da-87a6-4029-aeb0-bfe951372e62', + } + }, userIdAsEids: [ { source: 'test1.org', @@ -64,7 +68,11 @@ describe('limelightDigitalAdapter', function () { placementCode: 'placement_1', auctionId: '482f88de-29ab-45c8-981a-d25e39454a34', sizes: [[350, 200]], - transactionId: '068867d1-46ec-40bb-9fa0-e24611786fb4', + ortb2Imp: { + ext: { + tid: '068867d1-46ec-40bb-9fa0-e24611786fb4', + } + }, userIdAsEids: [ { source: 'test2.org', @@ -110,7 +118,11 @@ describe('limelightDigitalAdapter', function () { placementCode: 'placement_2', auctionId: 'e4771143-6aa7-41ec-8824-ced4342c96c8', sizes: [[800, 600]], - transactionId: '738d5915-6651-43b9-9b6b-d50517350917', + ortb2Imp: { + ext: { + tid: '738d5915-6651-43b9-9b6b-d50517350917', + } + }, userIdAsEids: [ { source: 'test3.org', @@ -155,7 +167,11 @@ describe('limelightDigitalAdapter', function () { video: { playerSize: [800, 600] }, - transactionId: '738d5915-6651-43b9-9b6b-d50517350917', + ortb2Imp: { + ext: { + tid: '738d5915-6651-43b9-9b6b-d50517350917', + } + }, userIdAsEids: [ { source: 'test.org', @@ -647,7 +663,7 @@ function validateAdUnit(adUnit, bid) { expect(adUnit.id).to.equal(bid.params.adUnitId); expect(adUnit.bidId).to.equal(bid.bidId); expect(adUnit.type).to.equal(bid.params.adUnitType.toUpperCase()); - expect(adUnit.transactionId).to.equal(bid.transactionId); + expect(adUnit.transactionId).to.equal(bid.ortb2Imp.ext.tid); let bidSizes = []; if (bid.mediaTypes) { if (bid.mediaTypes.video && bid.mediaTypes.video.playerSize) { diff --git a/test/spec/modules/livewrappedAnalyticsAdapter_spec.js b/test/spec/modules/livewrappedAnalyticsAdapter_spec.js index bab7a68287d..d07b48752c6 100644 --- a/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +++ b/test/spec/modules/livewrappedAnalyticsAdapter_spec.js @@ -71,7 +71,7 @@ const BID3 = { auctionId: '25c6d7f5-699a-4bfc-87c9-996f915341fa', mediaType: 'banner', getStatusCode() { - return CONSTANTS.STATUS.NO_BID; + return CONSTANTS.STATUS.GOOD; } }; diff --git a/test/spec/modules/livewrappedBidAdapter_spec.js b/test/spec/modules/livewrappedBidAdapter_spec.js index 6bbdf6e1705..52eaf8d7d76 100644 --- a/test/spec/modules/livewrappedBidAdapter_spec.js +++ b/test/spec/modules/livewrappedBidAdapter_spec.js @@ -36,6 +36,11 @@ describe('Livewrapped adapter tests', function () { bidId: '2ffb201a808da7', bidderRequestId: '178e34bad3658f', auctionId: 'F7557995-65F5-4682-8782-7D5D34D82A8C', + ortb2Imp: { + ext: { + tid: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D' + } + }, transactionId: '3D1C8CF7-D288-4D7F-8ADD-97C553056C3D' } ], @@ -1211,7 +1216,6 @@ describe('Livewrapped adapter tests', function () { let expectedResponse = [{ requestId: '32e50fad901ae89', - bidderCode: 'livewrapped', cpm: 2.565917, width: 300, height: 250, @@ -1251,7 +1255,6 @@ describe('Livewrapped adapter tests', function () { let expectedResponse = [{ requestId: '32e50fad901ae89', - bidderCode: 'livewrapped', cpm: 2.565917, width: 300, height: 250, @@ -1293,7 +1296,6 @@ describe('Livewrapped adapter tests', function () { let expectedResponse = [{ requestId: '32e50fad901ae89', - bidderCode: 'livewrapped', cpm: 2.565917, width: 300, height: 250, @@ -1347,7 +1349,6 @@ describe('Livewrapped adapter tests', function () { let expectedResponse = [{ requestId: '32e50fad901ae89', - bidderCode: 'livewrapped', cpm: 2.565917, width: 300, height: 250, @@ -1359,7 +1360,6 @@ describe('Livewrapped adapter tests', function () { meta: undefined }, { requestId: '42e50fad901ae89', - bidderCode: 'livewrapped', cpm: 3.565917, width: 980, height: 240, @@ -1398,7 +1398,6 @@ describe('Livewrapped adapter tests', function () { let expectedResponse = [{ requestId: '32e50fad901ae89', - bidderCode: 'livewrapped', cpm: 2.565917, width: 300, height: 250, diff --git a/test/spec/modules/liveyieldAnalyticsAdapter_spec.js b/test/spec/modules/liveyieldAnalyticsAdapter_spec.js deleted file mode 100644 index 9ec4eaf9acd..00000000000 --- a/test/spec/modules/liveyieldAnalyticsAdapter_spec.js +++ /dev/null @@ -1,704 +0,0 @@ -import CONSTANTS from 'src/constants.json'; -import liveyield from 'modules/liveyieldAnalyticsAdapter.js'; -import { expect } from 'chai'; -const events = require('src/events'); - -const { - EVENTS: { BID_REQUESTED, BID_TIMEOUT, BID_RESPONSE, BID_WON } -} = CONSTANTS; - -describe('liveyield analytics adapter', function() { - const rtaCalls = []; - - window.rta = function() { - rtaCalls.push({ callArgs: arguments }); - }; - - beforeEach(function() { - sinon.stub(events, 'getEvents').returns([]); - }); - afterEach(function() { - events.getEvents.restore(); - }); - - describe('initialization', function() { - afterEach(function() { - rtaCalls.length = 0; - }); - it('it should require provider', function() { - liveyield.enableAnalytics({}); - expect(rtaCalls).to.be.empty; - }); - it('should require config.options', function() { - liveyield.enableAnalytics({ provider: 'liveyield' }); - expect(rtaCalls).to.be.empty; - }); - it('should require options.customerId', function() { - liveyield.enableAnalytics({ provider: 'liveyield', options: {} }); - expect(rtaCalls).to.be.empty; - }); - it('should require options.customerName', function() { - liveyield.enableAnalytics({ - provider: 'liveyield', - options: { - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa' - } - }); - expect(rtaCalls).to.be.empty; - }); - it('should require options.customerSite', function() { - liveyield.enableAnalytics({ - provider: 'liveyield', - options: { - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', - customerName: 'pubocean' - } - }); - expect(rtaCalls).to.be.empty; - }); - it('should require options.sessionTimezoneOffset', function() { - liveyield.enableAnalytics({ - provider: 'liveyield', - options: { - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', - customerName: 'pubocean', - customerSite: 'scribol.com' - } - }); - expect(rtaCalls).to.be.empty; - }); - it("should throw error, when 'rta' function is not defined ", function() { - const keepMe = window.rta; - - delete window.rta; - - liveyield.enableAnalytics({ - provider: 'liveyield', - options: { - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', - customerName: 'pubocean', - customerSite: 'scribol.com', - sessionTimezoneOffset: 12 - } - }); - expect(rtaCalls).to.be.empty; - - window.rta = keepMe; - }); - it('should initialize when all required parameters are passed', function() { - liveyield.enableAnalytics({ - provider: 'liveyield', - options: { - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', - customerName: 'pubocean', - customerSite: 'scribol.com', - sessionTimezoneOffset: 12 - } - }); - expect(rtaCalls[0].callArgs['0']).to.match(/create/); - expect(rtaCalls[0].callArgs['1']).to.match( - /d6a6f8da-190f-47d6-ae11-f1a4469083fa/ - ); - expect(rtaCalls[0].callArgs['2']).to.match(/pubocean/); - expect(rtaCalls[0].callArgs['4']).to.match(/12/); - liveyield.disableAnalytics(); - }); - it('should allow to redefine rta function name', function() { - const keepMe = window.rta; - window.abc = keepMe; - delete window.rta; - liveyield.enableAnalytics({ - provider: 'liveyield', - options: { - rtaFunctionName: 'abc', - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', - customerName: 'test', - customerSite: 'scribol.com', - sessionTimezoneOffset: 25 - } - }); - - liveyield.disableAnalytics(); - expect(rtaCalls[0].callArgs['0']).to.match(/create/); - expect(rtaCalls[0].callArgs['1']).to.match( - /d6a6f8da-190f-47d6-ae11-f1a4469083fa/ - ); - expect(rtaCalls[0].callArgs['2']).to.match(/test/); - expect(rtaCalls[0].callArgs['4']).to.match(/25/); - - window.rta = keepMe; - liveyield.disableAnalytics(); - }); - it('should handle custom parameters', function() { - liveyield.enableAnalytics({ - provider: 'liveyield', - options: { - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', - customerName: 'test2', - customerSite: 'scribol.com', - sessionTimezoneOffset: 38, - contentTitle: 'testTitle', - contentAuthor: 'testAuthor', - contentCategory: 'testCategory' - } - }); - - liveyield.disableAnalytics(); - expect(rtaCalls[0].callArgs['0']).to.match(/create/); - expect(rtaCalls[0].callArgs['2']).to.match(/test2/); - expect(rtaCalls[0].callArgs['4']).to.match(/38/); - expect(rtaCalls[0].callArgs['5'].contentTitle).to.match(/testTitle/); - expect(rtaCalls[0].callArgs['5'].contentAuthor).to.match(/testAuthor/); - expect(rtaCalls[0].callArgs['5'].contentCategory).to.match( - /testCategory/ - ); - liveyield.disableAnalytics(); - }); - }); - - describe('handling events', function() { - const options = { - provider: 'liveyield', - options: { - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', - customerName: 'pubocean', - customerSite: 'scribol.com', - sessionTimezoneOffset: 12 - } - }; - beforeEach(function() { - rtaCalls.length = 0; - liveyield.enableAnalytics(options); - }); - afterEach(function() { - liveyield.disableAnalytics(); - }); - it('should handle BID_REQUESTED event', function() { - const bidRequest = { - bidderCode: 'appnexus', - bids: [ - { - params: { - placementId: '10433394' - }, - adUnitCode: 'div-gpt-ad-1438287399331-0', - transactionId: '2f481ff1-8d20-4c28-8e36-e384e9e3eec6', - sizes: '300x250,300x600', - bidId: '2eddfdc0c791dc', - auctionId: 'a5b849e5-87d7-4205-8300-d063084fcfb7' - } - ] - }; - - events.emit(BID_REQUESTED, bidRequest); - - expect(rtaCalls[1].callArgs['0']).to.equal('bidRequested'); - expect(rtaCalls[1].callArgs['1']).to.equal('div-gpt-ad-1438287399331-0'); - expect(rtaCalls[1].callArgs['2']).to.equal('appnexus'); - }); - it('should handle BID_REQUESTED event with invalid args', function() { - const bidRequest = { - bids: [ - { - params: { - placementId: '10433394' - }, - transactionId: '2f481ff1-8d20-4c28-8e36-e384e9e3eec6', - sizes: '300x250,300x600', - bidId: '2eddfdc0c791dc', - auctionId: 'a5b849e5-87d7-4205-8300-d063084fcf' - }, - { - params: { - placementId: '31034023' - }, - transactionId: '2f481ff1-8d20-4c28-8e36-e384e9e3eec6', - sizes: '300x250,300x600', - bidId: '3dkg0404fmd0', - auctionId: 'a5b849e5-87d7-4205-8300-d063084fcf' - } - ] - }; - events.emit(BID_REQUESTED, bidRequest); - expect(rtaCalls[1].callArgs['0']).to.equal('bidRequested'); - expect(rtaCalls[1].callArgs['1']).to.equal(undefined); - expect(rtaCalls[1].callArgs['2']).to.equal(undefined); - expect(rtaCalls[1].callArgs['0']).to.equal('bidRequested'); - }); - it('should handle BID_RESPONSE event', function() { - const bidResponse = { - height: 250, - statusMessage: 'Bid available', - adId: '2eddfdc0c791dc', - mediaType: 'banner', - source: 'client', - requestId: '2eddfdc0c791dc', - cpm: 0.5, - creativeId: 29681110, - currency: 'USD', - netRevenue: true, - ttl: 300, - auctionId: 'a5b849e5-87d7-4205-8300-d063084fcfb7', - responseTimestamp: 1522265866110, - requestTimestamp: 1522265863600, - bidder: 'appnexus', - adUnitCode: 'div-gpt-ad-1438287399331-0', - timeToRespond: 2510, - size: '300x250' - }; - - events.emit(BID_RESPONSE, bidResponse); - expect(rtaCalls[1].callArgs['0']).to.equal('addBid'); - expect(rtaCalls[1].callArgs['1']).to.equal('div-gpt-ad-1438287399331-0'); - expect(rtaCalls[1].callArgs['2']).to.equal('appnexus'); - expect(rtaCalls[1].callArgs['3']).to.equal(500); - expect(rtaCalls[1].callArgs['4']).to.equal(false); - expect(rtaCalls[1].callArgs['5']).to.equal(false); - }); - it('should handle BID_RESPONSE event with undefined bidder and cpm', function() { - const bidResponse = { - height: 250, - statusMessage: 'Bid available', - adId: '2eddfdc0c791dc', - mediaType: 'banner', - source: 'client', - requestId: '2eddfdc0c791dc', - creativeId: 29681110, - currency: 'USD', - netRevenue: true, - ttl: 300, - auctionId: 'a5b849e5-87d7-4205-8300-d063084fcfb7', - responseTimestamp: 1522265866110, - requestTimestamp: 1522265863600, - adUnitCode: 'div-gpt-ad-1438287399331-0', - timeToRespond: 2510, - size: '300x250' - }; - events.emit(BID_RESPONSE, bidResponse); - expect(rtaCalls[1].callArgs['0']).to.equal('addBid'); - expect(rtaCalls[1].callArgs['2']).to.equal('unknown'); - expect(rtaCalls[1].callArgs['3']).to.equal(0); - expect(rtaCalls[1].callArgs['4']).to.equal(true); - }); - it('should handle BID_RESPONSE event with undefined status message and adUnitCode', function() { - const bidResponse = { - height: 250, - adId: '2eddfdc0c791dc', - mediaType: 'banner', - source: 'client', - requestId: '2eddfdc0c791dc', - cpm: 0.5, - creativeId: 29681110, - currency: 'USD', - netRevenue: true, - ttl: 300, - auctionId: 'a5b849e5-87d7-4205-8300-d063084fcfb7', - responseTimestamp: 1522265866110, - requestTimestamp: 1522265863600, - bidder: 'appnexus', - timeToRespond: 2510, - size: '300x250' - }; - events.emit(BID_RESPONSE, bidResponse); - expect(rtaCalls[1].callArgs['0']).to.equal('addBid'); - expect(rtaCalls[1].callArgs['1']).to.equal(undefined); - expect(rtaCalls[1].callArgs['3']).to.equal(0); - expect(rtaCalls[1].callArgs['5']).to.equal(true); - }); - it('should handle BID_TIMEOUT', function() { - const bidTimeout = [ - { - bidId: '2baa51527bd015', - bidder: 'bidderOne', - adUnitCode: '/19968336/header-bid-tag-0', - auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' - }, - { - bidId: '6fe3b4c2c23092', - bidder: 'bidderTwo', - adUnitCode: '/19968336/header-bid-tag-0', - auctionId: '66529d4c-8998-47c2-ab3e-5b953490b98f' - } - ]; - events.emit(BID_TIMEOUT, bidTimeout); - expect(rtaCalls[1].callArgs['0']).to.equal('biddersTimeout'); - expect(rtaCalls[1].callArgs['1'].length).to.equal(2); - }); - it('should handle BID_WON event', function() { - const bidWon = { - adId: '4587fec4900b81', - mediaType: 'banner', - requestId: '4587fec4900b81', - cpm: 1.962, - creativeId: 2126, - currency: 'EUR', - netRevenue: true, - ttl: 302, - auctionId: '914bedad-b145-4e46-ba58-51365faea6cb', - statusMessage: 'Bid available', - responseTimestamp: 1530628534437, - requestTimestamp: 1530628534219, - bidderCode: 'testbidder4', - adUnitCode: 'div-gpt-ad-1438287399331-0', - timeToRespond: 218, - size: '300x250', - status: 'rendered' - }; - events.emit(BID_WON, bidWon); - expect(rtaCalls[1].callArgs['0']).to.equal('resolveSlot'); - expect(rtaCalls[1].callArgs['1']).to.equal('div-gpt-ad-1438287399331-0'); - expect(rtaCalls[1].callArgs['2'].prebidWon).to.equal(true); - expect(rtaCalls[1].callArgs['2'].prebidPartner).to.equal('testbidder4'); - expect(rtaCalls[1].callArgs['2'].prebidValue).to.equal(1962); - }); - it('should throw error, invoking BID_WON event without adUnitCode', function() { - const bidWon = { - adId: '4587fec4900b81', - mediaType: 'banner', - requestId: '4587fec4900b81', - cpm: 1.962, - creativeId: 2126, - currency: 'EUR', - netRevenue: true, - ttl: 302, - auctionId: '914bedad-b145-4e46-ba58-51365faea6cb', - statusMessage: 'Bid available', - responseTimestamp: 1530628534437, - requestTimestamp: 1530628534219, - timeToRespond: 218, - bidderCode: 'testbidder4', - size: '300x250', - status: 'rendered' - }; - events.emit(BID_WON, bidWon); - expect(rtaCalls[1]).to.be.undefined; - }); - it('should throw error, invoking BID_WON event without bidderCode', function() { - const bidWon = { - adId: '4587fec4900b81', - mediaType: 'banner', - requestId: '4587fec4900b81', - cpm: 1.962, - creativeId: 2126, - currency: 'EUR', - netRevenue: true, - ttl: 302, - auctionId: '914bedad-b145-4e46-ba58-51365faea6cb', - statusMessage: 'Bid available', - responseTimestamp: 1530628534437, - requestTimestamp: 1530628534219, - adUnitCode: 'div-gpt-ad-1438287399331-0', - timeToRespond: 218, - size: '300x250', - status: 'rendered' - }; - events.emit(BID_WON, bidWon); - expect(rtaCalls[1]).to.be.undefined; - }); - }); - - describe('googletag use case', function() { - beforeEach(function() { - rtaCalls.length = 0; - }); - afterEach(function() { - liveyield.disableAnalytics(); - }); - it('should ignore BID_WON events when gpt is provided', function() { - const options = { - provider: 'liveyield', - options: { - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', - customerName: 'pubocean', - customerSite: 'scribol.com', - sessionTimezoneOffset: 12, - googlePublisherTag: true, - wireGooglePublisherTag: function() { - return null; - } - } - }; - liveyield.enableAnalytics(options); - - const bidWon = { - adId: 'ignore_me', - mediaType: 'banner', - requestId: '4587fec4900b81', - cpm: 1.962, - creativeId: 2126, - currency: 'EUR', - netRevenue: true, - ttl: 302, - auctionId: '914bedad-b145-4e46-ba58-51365faea6cb', - statusMessage: 'Bid available', - responseTimestamp: 1530628534437, - requestTimestamp: 1530628534219, - bidderCode: 'hello', - adUnitCode: 'div-gpt-ad-1438287399331-0', - timeToRespond: 218, - size: '300x250', - status: 'rendered' - }; - events.emit(BID_WON, bidWon); - - expect(rtaCalls.length).to.equal(1); - }); - it('should subscribe to slotRenderEnded', function() { - var googletag; - var callback; - const options = { - provider: 'liveyield', - options: { - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', - customerName: 'pubocean', - customerSite: 'scribol.com', - sessionTimezoneOffset: 12, - googlePublisherTag: 'testGPT', - wireGooglePublisherTag: function(gpt, cb) { - googletag = gpt; - callback = cb; - } - } - }; - liveyield.enableAnalytics(options); - expect(googletag).to.equal('testGPT'); - expect(typeof callback).to.equal('function'); - }); - it('should handle BID_WON event for prebid', function() { - var call; - const slot = { - getResponseInformation: function() { - const dfpInfo = { - dfpAdvertiserId: 1, - dfpLineItemId: 2, - dfpCreativeId: 3 - }; - return dfpInfo; - }, - getTargeting: function(v) { - return ['4587fec4900b81']; - } - }; - const options = { - provider: 'liveyield', - options: { - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', - customerName: 'pubocean', - customerSite: 'scribol.com', - sessionTimezoneOffset: 12, - googlePublisherTag: 'testGPT', - wireGooglePublisherTag: function(gpt, cb) { - call = cb; - }, - getHighestPrebidAdImpressionPartner: function(slot, version) { - return 'testbidder4'; - }, - getHighestPrebidAdImpressionValue: function(slot, version) { - return 12; - }, - postProcessResolution: function( - resolution, - slot, - hbPartner, - hbValue, - version - ) { - return resolution; - }, - getAdUnitNameByGooglePublisherTagSlot: function(slot, version) { - return 'testUnit'; - } - } - }; - liveyield.enableAnalytics(options); - const bidWon = { - adId: '4587fec4900b81' - }; - events.emit(BID_WON, bidWon); - call(slot); - expect(rtaCalls[1].callArgs['2'].prebidWon).to.equal(true); - expect(rtaCalls[1].callArgs['2'].prebidPartner).to.equal('testbidder4'); - }); - it('should handle BID_WON event for dfp', function() { - let call; - const slot = { - getResponseInformation: function() { - const dfpInfo = { - dfpAdvertiserId: 1, - dfpLineItemId: 2, - dfpCreativeId: 3 - }; - return dfpInfo; - } - }; - const options = { - provider: 'liveyield', - options: { - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', - customerName: 'pubocean', - customerSite: 'scribol.com', - sessionTimezoneOffset: 12, - googlePublisherTag: 'testGPT', - wireGooglePublisherTag: function(gpt, cb) { - call = cb; - }, - getHighestPrebidAdImpressionPartner: function(slot, version) { - return 'testbidder4'; - }, - getHighestPrebidAdImpressionValue: function(slot, version) { - return 12; - }, - postProcessResolution: function(slot, version) { - return { partner: slot.prebidPartner, value: slot.prebidValue }; - }, - getAdUnitNameByGooglePublisherTagSlot: function(slot, version) { - return 'testUnit'; - }, - isPrebidAdImpression: function(slot) { - return true; - } - } - }; - liveyield.enableAnalytics(options); - call(slot); - expect(rtaCalls.length).to.equal(2); - expect(rtaCalls[1].callArgs[0]).to.equal('resolveSlot'); - expect(rtaCalls[1].callArgs[1]).to.equal('testUnit'); - expect(rtaCalls[1].callArgs[2].partner).to.equal('testbidder4'); - expect(rtaCalls[1].callArgs[2].value).to.equal(12000); - }); - it('should work with defaults: prebid won', () => { - let call; - const options = { - provider: 'liveyield', - options: { - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', - customerName: 'pubocean', - customerSite: 'scribol.com', - sessionTimezoneOffset: 12, - googlePublisherTag: 'testGPT', - wireGooglePublisherTag: (gpt, cb) => (call = cb), - getAdUnitName: adUnitCode => - adUnitCode === 'PREBID_UNIT' ? 'ADUNIT' : null, - getAdUnitNameByGooglePublisherTagSlot: slot => - slot.getSlotElementId() === 'div-gpt-ad-1438287399331-0' - ? 'ADUNIT' - : null - } - }; - liveyield.enableAnalytics(options); - - const bidResponse = { - adId: 'defaults_with_cache', - statusMessage: 'Bid available', - cpm: 0.5, - bidder: 'appnexus', - adUnitCode: 'PREBID_UNIT' - }; - events.emit(BID_RESPONSE, bidResponse); - - const bidWon = { - adId: bidResponse.adId, - cpm: 1.962, // adjusted, this one shall be used, not the one from bidResponse - bidderCode: 'appnexus_from_bid_won_event', - adUnitCode: 'PREBID_UNIT' - }; - events.emit(BID_WON, bidWon); - - const slot = { - getTargeting: key => (key === 'hb_adid' ? [bidResponse.adId] : []), - getResponseInformation: () => null, - getSlotElementId: () => 'div-gpt-ad-1438287399331-0' - }; - call(slot); - - expect(rtaCalls[2].callArgs[0]).to.equal('resolveSlot'); - expect(rtaCalls[2].callArgs[1]).to.equal('ADUNIT'); - expect(rtaCalls[2].callArgs[2]).to.deep.equal({ - targetings: [], - prebidWon: true, - prebidPartner: 'appnexus_from_bid_won_event', - prebidValue: 1962 - }); - }); - it('should work with defaults: dfp won, prebid bid response', () => { - let call; - const options = { - provider: 'liveyield', - options: { - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', - customerName: 'pubocean', - customerSite: 'scribol.com', - sessionTimezoneOffset: 12, - googlePublisherTag: 'testGPT', - wireGooglePublisherTag: (gpt, cb) => (call = cb), - getAdUnitName: adUnitCode => - adUnitCode === 'PREBID_UNIT' ? 'ADUNIT' : null, - getAdUnitNameByGooglePublisherTagSlot: slot => - slot.getSlotElementId() === 'div-gpt-ad-1438287399331-0' - ? 'ADUNIT' - : null - } - }; - liveyield.enableAnalytics(options); - - const bidResponse = { - adId: 'defaults_with_cache_no_prebid_win', - statusMessage: 'Bid available', - cpm: 0.5, - bidder: 'appnexus', - adUnitCode: 'PREBID_UNIT' - }; - events.emit(BID_RESPONSE, bidResponse); - - const slot = { - getTargeting: key => (key === 'hb_adid' ? [bidResponse.adId] : []), - getResponseInformation: () => null, - getSlotElementId: () => 'div-gpt-ad-1438287399331-0' - }; - call(slot); - - expect(rtaCalls[2].callArgs[0]).to.equal('resolveSlot'); - expect(rtaCalls[2].callArgs[1]).to.equal('ADUNIT'); - expect(rtaCalls[2].callArgs[2]).to.deep.equal({ - targetings: [], - prebidPartner: 'appnexus', - prebidValue: 500 - }); - }); - it('should work with defaults: dfp won, without prebid', () => { - let call; - const options = { - provider: 'liveyield', - options: { - customerId: 'd6a6f8da-190f-47d6-ae11-f1a4469083fa', - customerName: 'pubocean', - customerSite: 'scribol.com', - sessionTimezoneOffset: 12, - googlePublisherTag: 'testGPT', - wireGooglePublisherTag: (gpt, cb) => (call = cb), - getAdUnitName: adUnitCode => - adUnitCode === 'PREBID_UNIT' ? 'ADUNIT' : null, - getAdUnitNameByGooglePublisherTagSlot: slot => - slot.getSlotElementId() === 'div-gpt-ad-1438287399331-0' - ? 'ADUNIT' - : null - } - }; - liveyield.enableAnalytics(options); - - const slot = { - getTargeting: key => (key === 'hb_adid' ? ['does-not-exist'] : []), - getResponseInformation: () => null, - getSlotElementId: () => 'div-gpt-ad-1438287399331-0' - }; - call(slot); - - expect(rtaCalls[1].callArgs[0]).to.equal('resolveSlot'); - expect(rtaCalls[1].callArgs[1]).to.equal('ADUNIT'); - expect(rtaCalls[1].callArgs[2]).to.deep.equal({ - targetings: [] - }); - }); - }); -}); diff --git a/test/spec/modules/loglyliftBidAdapter_spec.js b/test/spec/modules/loglyliftBidAdapter_spec.js index 8ff2eb97463..9805561442a 100644 --- a/test/spec/modules/loglyliftBidAdapter_spec.js +++ b/test/spec/modules/loglyliftBidAdapter_spec.js @@ -11,6 +11,11 @@ describe('loglyliftBidAdapter', function () { }, adUnitCode: '/19968336/prebid_native_example_1', transactionId: '10aee457-617c-4572-ab5b-99df1d73ccb4', + ortb2Imp: { + ext: { + tid: '10aee457-617c-4572-ab5b-99df1d73ccb4', + } + }, sizes: [[300, 250], [300, 600]], bidderRequestId: '15da3afd9632d7', auctionId: 'f890b7d9-e787-4237-ac21-6d8554abac9f', @@ -29,6 +34,11 @@ describe('loglyliftBidAdapter', function () { }, adUnitCode: '/19968336/prebid_native_example_1', transactionId: '10aee457-617c-4572-ab5b-99df1d73ccb4', + ortb2Imp: { + ext: { + tid: '10aee457-617c-4572-ab5b-99df1d73ccb4', + } + }, sizes: [ [] ], diff --git a/test/spec/modules/luponmediaBidAdapter_spec.js b/test/spec/modules/luponmediaBidAdapter_spec.js index c8d4c18c407..1441abc0fe8 100755 --- a/test/spec/modules/luponmediaBidAdapter_spec.js +++ b/test/spec/modules/luponmediaBidAdapter_spec.js @@ -142,7 +142,12 @@ describe('luponmediaBidAdapter', function () { 'https://novi.ba/clanak/176067/fast-car-beginner-s-guide-to-tuning-turbo-engines' ] }, - 'start': 1587413920835 + 'start': 1587413920835, + ortb2: { + source: { + tid: 'mock-tid' + } + }, }; it('sends bid request to ENDPOINT via POST', function () { @@ -150,7 +155,23 @@ describe('luponmediaBidAdapter', function () { let dynRes = JSON.parse(requests.data); expect(requests.url).to.equal(ENDPOINT_URL); expect(requests.method).to.equal('POST'); - expect(requests.data).to.equal('{"id":"585d96a5-bd93-4a89-b8ea-0f546f3aaa82","test":0,"source":{"tid":"585d96a5-bd93-4a89-b8ea-0f546f3aaa82","ext":{"schain":{"ver":"1.0","complete":1,"nodes":[{"asi":"novi.ba","sid":"199424","hp":1}]}}},"tmax":1500,"imp":[{"id":"268a30af10dd6f","secure":1,"ext":{"luponmedia":{"siteId":303522,"keyId":"4o2c4"}},"banner":{"format":[{"w":300,"h":250}]}}],"ext":{"prebid":{"targeting":{"includewinners":true,"includebidderkeys":false}}},"user":{"id":"' + dynRes.user.id + '","buyeruid":"8d8b16cb-1383-4a0f-b4bb-0be28464d974"},"site":{"page":"https://novi.ba/clanak/176067/fast-car-beginner-s-guide-to-tuning-turbo-engines"}}'); + expect(JSON.parse(requests.data)).to.deep.include({ + 'test': 0, + 'source': { + tid: 'mock-tid', + 'ext': {'schain': {'ver': '1.0', 'complete': 1, 'nodes': [{'asi': 'novi.ba', 'sid': '199424', 'hp': 1}]}} + }, + 'tmax': 1500, + 'imp': [{ + 'id': '268a30af10dd6f', + 'secure': 1, + 'ext': {'luponmedia': {'siteId': 303522, 'keyId': '4o2c4'}}, + 'banner': {'format': [{'w': 300, 'h': 250}]} + }], + 'ext': {'prebid': {'targeting': {'includewinners': true, 'includebidderkeys': false}}}, + 'user': {'id': dynRes.user.id, 'buyeruid': '8d8b16cb-1383-4a0f-b4bb-0be28464d974'}, + 'site': {'page': 'https://novi.ba/clanak/176067/fast-car-beginner-s-guide-to-tuning-turbo-engines'} + }); }); }); diff --git a/test/spec/modules/magniteAnalyticsAdapter_spec.js b/test/spec/modules/magniteAnalyticsAdapter_spec.js index f4dfc37d018..2d806fa717a 100644 --- a/test/spec/modules/magniteAnalyticsAdapter_spec.js +++ b/test/spec/modules/magniteAnalyticsAdapter_spec.js @@ -26,7 +26,8 @@ const { BID_WON, BID_TIMEOUT, BILLABLE_EVENT, - SEAT_NON_BID + SEAT_NON_BID, + BID_REJECTED } } = CONSTANTS; @@ -2231,4 +2232,95 @@ describe('magnite analytics adapter', function () { }); }); }); + + describe('BID_REJECTED events', () => { + let bidRejectedArgs; + + const runBidRejectedAuction = () => { + events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); + events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); + events.emit(BID_REJECTED, bidRejectedArgs) + events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); + events.emit(AUCTION_END, MOCK.AUCTION_END); + clock.tick(rubiConf.analyticsBatchTimeout + 1000); + }; + beforeEach(() => { + magniteAdapter.enableAnalytics({ + options: { + endpoint: '//localhost:9999/event', + accountId: 1001 + } + }); + bidRejectedArgs = utils.deepClone(MOCK.BID_RESPONSE); + }); + + it('updates the bid to be rejected by floors', () => { + bidRejectedArgs.floorData = { + floorValue: 0.5, + floorRule: 'banner', + floorRuleValue: 0.5, + floorCurrency: 'USD', + cpmAfterAdjustments: 0.15, + enforcements: { + enforceJS: true, + enforcePBS: false, + floorDeals: false, + bidAdjustment: true + }, + matchedFields: { + mediaType: 'banner' + } + } + bidRejectedArgs.rejectionReason = 'Bid does not meet price floor'; + + runBidRejectedAuction(); + let message = JSON.parse(server.requests[0].requestBody); + + expect(message.auctions[0].adUnits[0].bids[0]).to.deep.equal({ + bidder: 'rubicon', + bidId: '23fcd8cf4bf0d7', + source: 'client', + status: 'rejected-ipf', + clientLatencyMillis: 271, + httpLatencyMillis: 240, + bidResponse: { + bidPriceUSD: 0.15, + mediaType: 'banner', + dimensions: { + width: 300, + height: 250 + }, + floorValue: 0.5, + floorRuleValue: 0.5, + rejectionReason: 'Bid does not meet price floor' + } + }); + }); + + it('does general rejection', () => { + bidRejectedArgs + bidRejectedArgs.rejectionReason = 'this bid is rejected'; + + runBidRejectedAuction(); + let message = JSON.parse(server.requests[0].requestBody); + + expect(message.auctions[0].adUnits[0].bids[0]).to.deep.equal({ + bidder: 'rubicon', + bidId: '23fcd8cf4bf0d7', + source: 'client', + status: 'rejected', + clientLatencyMillis: 271, + httpLatencyMillis: 240, + bidResponse: { + bidPriceUSD: 3.4, + mediaType: 'banner', + dimensions: { + width: 300, + height: 250 + }, + rejectionReason: 'this bid is rejected' + } + }); + }); + }); }); diff --git a/test/spec/modules/mass_spec.js b/test/spec/modules/mass_spec.js deleted file mode 100644 index e7fc66991ca..00000000000 --- a/test/spec/modules/mass_spec.js +++ /dev/null @@ -1,141 +0,0 @@ -import { expect } from 'chai'; -import { - init, - addBidResponseHook, - addListenerOnce, - isMassBid, - useDefaultMatch, - useDefaultRender, - updateRenderers, - listenerAdded, - isEnabled -} from 'modules/mass'; -import { logInfo } from 'src/utils.js'; - -// mock a MASS bid: -const mockedMassBids = [ - { - bidder: 'ix', - bidId: 'mass-bid-1', - requestId: 'mass-bid-1', - bidderRequestId: 'bidder-request-id-1', - dealId: 'MASS1234', - ad: 'mass://provider/product/etc...', - meta: {} - }, - { - bidder: 'ix', - bidId: 'mass-bid-2', - requestId: 'mass-bid-2', - bidderRequestId: 'bidder-request-id-1', - dealId: '1234', - ad: 'mass://provider/product/etc...', - meta: { - mass: true - } - }, -]; - -// mock non-MASS bids: -const mockedNonMassBids = [ - { - bidder: 'ix', - bidId: 'non-mass-bid-1', - requstId: 'non-mass-bid-1', - bidderRequestId: 'bidder-request-id-1', - dealId: 'MASS1234', - ad: '', - meta: { - mass: true - } - }, - { - bidder: 'ix', - bidId: 'non-mass-bid-2', - requestId: 'non-mass-bid-2', - bidderRequestId: 'bidder-request-id-1', - dealId: '1234', - ad: 'mass://provider/product/etc...', - meta: {} - }, -]; - -const noop = function() {}; - -describe('MASS Module', function() { - it('should be enabled by default', function() { - expect(isEnabled).to.equal(true); - }); - - it('can be disabled', function() { - init({enabled: false}); - expect(isEnabled).to.equal(false); - }); - - it('should only affect MASS bids', function() { - init({renderUrl: 'https://...'}); - mockedNonMassBids.forEach(function(mockedBid) { - const originalBid = Object.assign({}, mockedBid); - const bid = Object.assign({}, originalBid); - - addBidResponseHook(noop, 'ad-code-id', bid); - - expect(bid).to.deep.equal(originalBid); - }); - }); - - it('should only update the ad markup field', function() { - init({renderUrl: 'https://...'}); - mockedMassBids.forEach(function(mockedBid) { - const originalBid = Object.assign({}, mockedBid); - const bid = Object.assign({}, originalBid); - - addBidResponseHook(noop, 'ad-code-id', bid); - - expect(bid.ad).to.not.equal(originalBid.ad); - - delete bid.ad; - delete originalBid.ad; - - expect(bid).to.deep.equal(originalBid); - }); - }); - - it('should add a message listener', function() { - addListenerOnce(); - expect(listenerAdded).to.equal(true); - }); - - it('should support custom renderers', function() { - init({ - renderUrl: 'https://...', - custom: [ - { - dealIdPattern: /abc/, - render: function() {} - } - ] - }); - - const renderers = updateRenderers(); - - expect(renderers.length).to.equal(2); - }); - - it('should match bids by deal ID with the default matcher', function() { - const match = useDefaultMatch(/abc/); - - expect(match({dealId: 'abc'})).to.equal(true); - expect(match({dealId: 'xyz'})).to.equal(false); - }); - - it('should have a default renderer', function() { - // SOT needs at least one script to be on the page; ugly solution, but good enough since mass is to be removed in v8 - document.body.appendChild(document.createElement('script')); - const render = useDefaultRender('https://example.com/render.js', 'abc'); - render({}); - - expect(window.abc.loaded).to.equal(true); - expect(window.abc.queue.length).to.equal(1); - }); -}); diff --git a/test/spec/modules/mediaforceBidAdapter_spec.js b/test/spec/modules/mediaforceBidAdapter_spec.js index 22f584306a9..61e5678b03b 100644 --- a/test/spec/modules/mediaforceBidAdapter_spec.js +++ b/test/spec/modules/mediaforceBidAdapter_spec.js @@ -97,7 +97,11 @@ describe('mediaforce bid adapter', function () { } } }, - transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', + ortb2Imp: { + ext: { + tid: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', + } + } }; const multiBid = [ @@ -127,7 +131,11 @@ describe('mediaforce bid adapter', function () { sizes: [[300, 250], [600, 400]] } }, - transactionId: transactionId || 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' + ortb2Imp: { + ext: { + tid: transactionId || 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' + } + }, } }); @@ -196,7 +204,7 @@ describe('mediaforce bid adapter', function () { bidfloor: bid.params.bidfloor, ext: { mediaforce: { - transactionId: bid.transactionId + transactionId: bid.ortb2Imp.ext.tid, } }, banner: {w: 300, h: 250}, diff --git a/test/spec/modules/mediafuseBidAdapter_spec.js b/test/spec/modules/mediafuseBidAdapter_spec.js index bb9bbd34d1d..dd2b5df70bd 100644 --- a/test/spec/modules/mediafuseBidAdapter_spec.js +++ b/test/spec/modules/mediafuseBidAdapter_spec.js @@ -811,8 +811,8 @@ describe('MediaFuseAdapter', function () { sha1udid: '4DFAA92388699AC6539885AEF1719293879985BF', windowsadid: '750c6be243f1c4b5c9912b95a5742fc5' }); - expect(payload.device.geo).to.exist; - expect(payload.device.geo).to.deep.equal({ + expect(payload.device.geo).to.not.exist; + expect(payload.device.geo).to.not.deep.equal({ lat: 40.0964439, lng: -75.3009142 }); @@ -1021,16 +1021,13 @@ describe('MediaFuseAdapter', function () { }) describe('interpretResponse', function () { - let bfStub; let bidderSettingsStorage; before(function() { - bfStub = sinon.stub(bidderFactory, 'getIabSubCategory'); bidderSettingsStorage = $$PREBID_GLOBAL$$.bidderSettings; }); after(function() { - bfStub.restore(); $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsStorage; }); @@ -1275,7 +1272,6 @@ describe('MediaFuseAdapter', function () { } }] }; - bfStub.returns('1'); let result = spec.interpretResponse({ body: response }, {bidderRequest}); expect(result[0]).to.have.property('vastUrl'); diff --git a/test/spec/modules/mediakeysBidAdapter_spec.js b/test/spec/modules/mediakeysBidAdapter_spec.js index 75c7f42cf58..99eaff3f378 100644 --- a/test/spec/modules/mediakeysBidAdapter_spec.js +++ b/test/spec/modules/mediakeysBidAdapter_spec.js @@ -131,7 +131,11 @@ describe('mediakeysBidAdapter', function () { const bidderRequest = { bidderCode: 'mediakeys', - auctionId: '84212956-c377-40e8-b000-9885a06dc692', + ortb2: { + source: { + tid: '84212956-c377-40e8-b000-9885a06dc692', + } + }, bidderRequestId: '1c1b642f803242', bids: [ bid @@ -208,7 +212,7 @@ describe('mediakeysBidAdapter', function () { // openRTB 2.5 expect(data.at).to.equal(1); expect(data.cur[0]).to.equal('USD'); // default currency - expect(data.source.tid).to.equal(bidderRequest.auctionId); + expect(data.source.tid).to.equal(bidderRequest.ortb2.source.tid); expect(data.imp.length).to.equal(1); expect(data.imp[0].id).to.equal(bidRequests[0].bidId); diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index 9180bbad68c..bb90eded230 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -16,7 +16,11 @@ let VALID_BID_REQUEST = [{ } }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', + ortb2Imp: { + ext: { + tid: '277b631f-92f5-4844-8b19-ea13c095d3f1' + } + }, 'mediaTypes': { 'banner': { 'sizes': [[300, 250]], @@ -38,7 +42,11 @@ let VALID_BID_REQUEST = [{ } }, 'adUnitCode': 'div-gpt-ad-1460505748561-123', - 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + ortb2Imp: { + ext: { + tid: 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + } + }, 'mediaTypes': { 'banner': { 'sizes': [[300, 251]], @@ -64,6 +72,11 @@ let VALID_BID_REQUEST = [{ } }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', + ortb2Imp: { + ext: { + tid: '277b631f-92f5-4844-8b19-ea13c095d3f1', + } + }, 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', 'mediaTypes': { 'banner': { @@ -87,7 +100,11 @@ let VALID_BID_REQUEST = [{ } }, 'adUnitCode': 'div-gpt-ad-1460505748561-123', - 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + ortb2Imp: { + ext: { + tid: 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + } + }, 'mediaTypes': { 'banner': { 'sizes': [[300, 251]], @@ -112,7 +129,6 @@ let VALID_BID_REQUEST = [{ } }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', 'mediaTypes': { 'banner': { 'sizes': [[300, 250]], @@ -121,7 +137,12 @@ let VALID_BID_REQUEST = [{ 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', - 'ortb2Imp': { 'ext': { 'data': { 'pbadslot': '/12345/my-gpt-tag-0' } } }, + 'ortb2Imp': { + 'ext': { + tid: '277b631f-92f5-4844-8b19-ea13c095d3f1', + 'data': {'pbadslot': '/12345/my-gpt-tag-0'} + } + }, 'bidRequestsCount': 1 }, { 'bidder': 'medianet', @@ -136,7 +157,6 @@ let VALID_BID_REQUEST = [{ } }, 'adUnitCode': 'div-gpt-ad-1460505748561-123', - 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', 'mediaTypes': { 'banner': { 'sizes': [[300, 251]], @@ -146,7 +166,12 @@ let VALID_BID_REQUEST = [{ 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', - 'ortb2Imp': { 'ext': { 'data': { 'pbadslot': '/12345/my-gpt-tag-0' } } }, + 'ortb2Imp': { + 'ext': { + tid: 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + 'data': {'pbadslot': '/12345/my-gpt-tag-0'} + } + }, 'bidRequestsCount': 1 }], VALID_BID_REQUEST_WITH_USERID = [{ @@ -165,7 +190,11 @@ let VALID_BID_REQUEST = [{ britepoolid: '82efd5e1-816b-4f87-97f8-044f407e2911' }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', + ortb2Imp: { + ext: { + tid: '277b631f-92f5-4844-8b19-ea13c095d3f1', + } + }, 'mediaTypes': { 'banner': { 'sizes': [[300, 250]], @@ -188,7 +217,11 @@ let VALID_BID_REQUEST = [{ } }, 'adUnitCode': 'div-gpt-ad-1460505748561-123', - 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + ortb2Imp: { + ext: { + tid: 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + } + }, 'mediaTypes': { 'banner': { 'sizes': [[300, 251]], @@ -214,7 +247,11 @@ let VALID_BID_REQUEST = [{ } }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', + ortb2Imp: { + ext: { + tid: '277b631f-92f5-4844-8b19-ea13c095d3f1', + } + }, 'sizes': [[300, 250]], 'mediaTypes': { 'banner': { @@ -237,7 +274,11 @@ let VALID_BID_REQUEST = [{ } }, 'adUnitCode': 'div-gpt-ad-1460505748561-123', - 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + ortb2Imp: { + ext: { + tid: 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + } + }, 'sizes': [[300, 251]], 'mediaTypes': { 'banner': { @@ -261,7 +302,11 @@ let VALID_BID_REQUEST = [{ } }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', + ortb2Imp: { + ext: { + tid: '277b631f-92f5-4844-8b19-ea13c095d3f1', + } + }, 'sizes': [[300, 250]], 'mediaTypes': { 'banner': { @@ -314,7 +359,11 @@ let VALID_BID_REQUEST = [{ } }, 'adUnitCode': 'div-gpt-ad-1460505748561-123', - 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + ortb2Imp: { + ext: { + tid: 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + } + }, 'sizes': [[300, 251]], 'mediaTypes': { 'banner': { @@ -389,6 +438,7 @@ let VALID_BID_REQUEST = [{ 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'imp': [{ 'id': '28f8f8130a583e', + ortb2Imp: VALID_BID_REQUEST_INVALID_BIDFLOOR[0].ortb2Imp, 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', 'ext': { 'dfp_id': 'div-gpt-ad-1460505748561-0', @@ -422,6 +472,7 @@ let VALID_BID_REQUEST = [{ } }, { 'id': '3f97ca71b1e5c2', + ortb2Imp: VALID_BID_REQUEST_INVALID_BIDFLOOR[1].ortb2Imp, 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', 'ext': { 'dfp_id': 'div-gpt-ad-1460505748561-123', @@ -477,6 +528,7 @@ let VALID_BID_REQUEST = [{ 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'imp': [{ 'id': '28f8f8130a583e', + ortb2Imp: VALID_NATIVE_BID_REQUEST[0].ortb2Imp, 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', 'ext': { 'dfp_id': 'div-gpt-ad-1460505748561-0', @@ -510,6 +562,7 @@ let VALID_BID_REQUEST = [{ } }, { 'id': '3f97ca71b1e5c2', + ortb2Imp: VALID_NATIVE_BID_REQUEST[1].ortb2Imp, 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', 'ext': { 'dfp_id': 'div-gpt-ad-1460505748561-123', @@ -567,6 +620,7 @@ let VALID_BID_REQUEST = [{ 'imp': [{ 'id': '28f8f8130a583e', 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', + ortb2Imp: VALID_BID_REQUEST[0].ortb2Imp, 'ext': { 'dfp_id': 'div-gpt-ad-1460505748561-0', 'visibility': 1, @@ -599,6 +653,7 @@ let VALID_BID_REQUEST = [{ }, { 'id': '3f97ca71b1e5c2', 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + ortb2Imp: VALID_BID_REQUEST[1].ortb2Imp, 'ext': { 'dfp_id': 'div-gpt-ad-1460505748561-123', 'visibility': 1, @@ -656,6 +711,7 @@ let VALID_BID_REQUEST = [{ 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'imp': [{ 'id': '28f8f8130a583e', + ortb2Imp: VALID_BID_REQUEST_WITH_USERID[0].ortb2Imp, 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', 'tagid': 'crid', 'ext': { @@ -690,6 +746,7 @@ let VALID_BID_REQUEST = [{ } }, { 'id': '3f97ca71b1e5c2', + ortb2Imp: VALID_BID_REQUEST_WITH_USERID[1].ortb2Imp, 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', 'tagid': 'crid', 'ext': { @@ -747,6 +804,7 @@ let VALID_BID_REQUEST = [{ 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'imp': [{ 'id': '28f8f8130a583e', + ortb2Imp: VALID_BID_REQUEST_WITH_CRID[0].ortb2Imp, 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', 'tagid': 'crid', 'ext': { @@ -781,6 +839,7 @@ let VALID_BID_REQUEST = [{ } }, { 'id': '3f97ca71b1e5c2', + ortb2Imp: VALID_BID_REQUEST_WITH_CRID[1].ortb2Imp, 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', 'tagid': 'crid', 'ext': { @@ -1103,7 +1162,11 @@ let VALID_BID_REQUEST = [{ } }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', + ortb2Imp: { + ext: { + tid: '277b631f-92f5-4844-8b19-ea13c095d3f1', + } + }, 'sizes': [300, 250], 'mediaTypes': { 'banner': { @@ -1126,7 +1189,11 @@ let VALID_BID_REQUEST = [{ } }, 'adUnitCode': 'div-gpt-ad-1460505748561-123', - 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + ortb2Imp: { + ext: { + tid: 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', + } + }, 'sizes': [300, 251], 'mediaTypes': { 'banner': { @@ -1178,6 +1245,7 @@ let VALID_BID_REQUEST = [{ 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'imp': [{ 'id': '28f8f8130a583e', + ortb2Imp: VALID_BID_REQUEST[0].ortb2Imp, 'transactionId': '277b631f-92f5-4844-8b19-ea13c095d3f1', 'ext': { 'dfp_id': 'div-gpt-ad-1460505748561-0', @@ -1210,6 +1278,7 @@ let VALID_BID_REQUEST = [{ } }, { 'id': '3f97ca71b1e5c2', + ortb2Imp: VALID_BID_REQUEST[1].ortb2Imp, 'transactionId': 'c52a5c62-3c2b-4b90-9ff8-ec1487754822', 'ext': { 'dfp_id': 'div-gpt-ad-1460505748561-123', @@ -1306,7 +1375,7 @@ describe('Media.net bid adapter', function () { it('should build valid payload on bid', function () { let requestObj = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); - expect(JSON.parse(requestObj.data)).to.deep.equal(VALID_PAYLOAD); + expect(JSON.parse(requestObj.data)).to.deep.include(VALID_PAYLOAD); }); it('should accept size as a one dimensional array', function () { @@ -1353,7 +1422,7 @@ describe('Media.net bid adapter', function () { bidreq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); actual = JSON.parse(bidreq.data).imp[0].ortb2Imp; - assert.equal(actual, undefined) + expect(actual).to.deep.equal(VALID_BID_REQUEST[0].ortb2Imp); }); it('should have userid in bid request', function () { diff --git a/test/spec/modules/mediasniperBidAdapter_spec.js b/test/spec/modules/mediasniperBidAdapter_spec.js index 21ce5297c8f..30437205067 100644 --- a/test/spec/modules/mediasniperBidAdapter_spec.js +++ b/test/spec/modules/mediasniperBidAdapter_spec.js @@ -209,7 +209,7 @@ describe('mediasniperBidAdapter', function () { // openRTB 2.5 expect(data.cur[0]).to.equal(DEFAULT_CURRENCY); - expect(data.id).to.equal(bidderRequest.auctionId); + expect(data.id).to.exist; expect(data.imp.length).to.equal(1); expect(data.imp[0].id).to.equal(bidRequests[0].bidId); diff --git a/test/spec/modules/mediasquareBidAdapter_spec.js b/test/spec/modules/mediasquareBidAdapter_spec.js index 249ff3f3f6e..4e131024d84 100644 --- a/test/spec/modules/mediasquareBidAdapter_spec.js +++ b/test/spec/modules/mediasquareBidAdapter_spec.js @@ -1,16 +1,16 @@ import {expect} from 'chai'; import {spec} from 'modules/mediasquareBidAdapter.js'; -import {newBidder} from 'src/adapters/bidderFactory.js'; -import {config} from 'src/config.js'; -import * as utils from 'src/utils.js'; -import { requestBidsHook } from 'modules/consentManagement.js'; describe('MediaSquare bid adapter tests', function () { var DEFAULT_PARAMS = [{ adUnitCode: 'banner-div', bidId: 'aaaa1234', auctionId: 'bbbb1234', - transactionId: 'cccc1234', + ortb2Imp: { + ext: { + tid: 'cccc1234', + } + }, mediaTypes: { banner: { sizes: [ diff --git a/test/spec/modules/microadBidAdapter_spec.js b/test/spec/modules/microadBidAdapter_spec.js index 98edfce20bc..bd6d04a6312 100644 --- a/test/spec/modules/microadBidAdapter_spec.js +++ b/test/spec/modules/microadBidAdapter_spec.js @@ -12,7 +12,11 @@ describe('microadBidAdapter', () => { spot: 'spot-code' }, bidId: 'bid-id', - transactionId: 'transaction-id' + ortb2Imp: { + ext: { + tid: 'transaction-id' + } + } }; describe('isBidRequestValid', () => { @@ -224,7 +228,7 @@ describe('microadBidAdapter', () => { }); }); - it('should add geo parameter to response if request parameters contain geo', () => { + it('should not add geo parameter to response even if request parameters contain geo', () => { const bidRequestWithGeo = Object.assign({}, bidRequestTemplate, { params: { spot: 'spot-code', @@ -233,7 +237,7 @@ describe('microadBidAdapter', () => { }); const requests = spec.buildRequests([bidRequestWithGeo], bidderRequest); requests.forEach(request => { - expect(request.data).to.deep.equal( + expect(request.data).to.not.deep.equal( Object.assign({}, expectedResultTemplate, { cbt: request.data.cbt, geo: '35.655275,139.693771' diff --git a/test/spec/modules/minutemediaplusBidAdapter_spec.js b/test/spec/modules/minutemediaplusBidAdapter_spec.js index 359a97465e4..33ec194c61f 100644 --- a/test/spec/modules/minutemediaplusBidAdapter_spec.js +++ b/test/spec/modules/minutemediaplusBidAdapter_spec.js @@ -35,7 +35,6 @@ const BID = { } }, 'placementCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': 'c881914b-a3b5-4ecf-ad9c-1c2f37c6aabf', 'sizes': [[300, 250], [300, 600]], 'bidderRequestId': '1fdb5ff1b6eaa7', 'auctionId': 'auction_id', @@ -47,7 +46,8 @@ const BID = { 'mediaTypes': [BANNER], 'ortb2Imp': { 'ext': { - 'gpid': '1234567890' + 'gpid': '1234567890', + tid: 'c881914b-a3b5-4ecf-ad9c-1c2f37c6aabf', } } }; @@ -60,7 +60,11 @@ const VIDEO_BID = { 'bidRequestsCount': 4, 'bidderRequestsCount': 3, 'bidderWinsCount': 1, - 'transactionId': '56e184c6-bde9-497b-b9b9-cf47a61381ee', + ortb2Imp: { + ext: { + tid: '56e184c6-bde9-497b-b9b9-cf47a61381ee', + } + }, 'schain': 'a0819c69-005b-41ed-af06-1be1e0aefefc', 'params': { 'subDomain': SUB_DOMAIN, diff --git a/test/spec/modules/nextMillenniumBidAdapter_spec.js b/test/spec/modules/nextMillenniumBidAdapter_spec.js index 7f40e7d89f8..564788c8b56 100644 --- a/test/spec/modules/nextMillenniumBidAdapter_spec.js +++ b/test/spec/modules/nextMillenniumBidAdapter_spec.js @@ -173,9 +173,9 @@ describe('nextMillenniumBidAdapterTests', function() { }); it('validate_generated_params', function() { - const request = spec.buildRequests(bidRequestData); + const request = spec.buildRequests(bidRequestData, {bidderRequestId: 'mock-uuid'}); expect(request[0].bidId).to.equal('bid1234'); - expect(JSON.parse(request[0].data).id).to.equal('b06c5141-fe8f-4cdf-9d7d-54415490a917'); + expect(JSON.parse(request[0].data).id).to.exist; }); it('use parameters group_id', function() { diff --git a/test/spec/modules/nexx360BidAdapter_spec.js b/test/spec/modules/nexx360BidAdapter_spec.js index 9ba3ac0e5a4..7c2cea99a46 100644 --- a/test/spec/modules/nexx360BidAdapter_spec.js +++ b/test/spec/modules/nexx360BidAdapter_spec.js @@ -354,7 +354,6 @@ describe('Nexx360 bid adapter tests', function () { const request = spec.buildRequests(displayBids, bidderRequest); const requestContent = request.data; expect(request).to.have.property('method').and.to.equal('POST'); - expect(requestContent.id).to.be.eql('2e684815-b44e-4e04-b812-56da54adbe74'); expect(requestContent.cur[0]).to.be.eql('USD'); expect(requestContent.imp.length).to.be.eql(2); expect(requestContent.imp[0].id).to.be.eql('44a2706ac3574'); diff --git a/test/spec/modules/oguryBidAdapter_spec.js b/test/spec/modules/oguryBidAdapter_spec.js index 2d48dca5ebb..d25363de9c9 100644 --- a/test/spec/modules/oguryBidAdapter_spec.js +++ b/test/spec/modules/oguryBidAdapter_spec.js @@ -62,6 +62,7 @@ describe('OguryBidAdapter', function () { ]; bidderRequest = { + bidderRequestId: 'mock-uuid', auctionId: bidRequests[0].auctionId, gdprConsent: {consentString: 'myConsentString', vendorData: {}, gdprApplies: true}, }; @@ -262,7 +263,7 @@ describe('OguryBidAdapter', function () { const defaultTimeout = 1000; const expectedRequestObject = { - id: bidRequests[0].auctionId, + id: 'mock-uuid', at: 1, tmax: defaultTimeout, imp: [{ diff --git a/test/spec/modules/onetagBidAdapter_spec.js b/test/spec/modules/onetagBidAdapter_spec.js index 5bd65cf0fd5..701fee5f6d9 100644 --- a/test/spec/modules/onetagBidAdapter_spec.js +++ b/test/spec/modules/onetagBidAdapter_spec.js @@ -15,7 +15,11 @@ describe('onetag', function () { 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', - 'transactionId': 'qwerty123', + ortb2Imp: { + ext: { + tid: 'qwerty123' + } + }, 'schain': { 'validation': 'off', 'config': { diff --git a/test/spec/modules/openxAnalyticsAdapter_spec.js b/test/spec/modules/openxAnalyticsAdapter_spec.js deleted file mode 100644 index 1b1adeb8807..00000000000 --- a/test/spec/modules/openxAnalyticsAdapter_spec.js +++ /dev/null @@ -1,21 +0,0 @@ -import { expect } from 'chai'; -import openxAdapter from 'modules/openxAnalyticsAdapter.js'; -import * as utils from 'src/utils.js'; - -describe('openx analytics adapter', function() { - describe('deprecation message', function () { - let spy; - beforeEach(function () { - spy = sinon.spy(utils, 'logWarn'); - }); - - afterEach(function() { - utils.logWarn.restore(); - }); - - it('should warn on enable', function() { - openxAdapter.enableAnalytics(); - expect(spy.firstCall.args[0]).to.match(/OpenX Analytics has been deprecated/); - }); - }); -}); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index d8ea79ac698..f2cff7f470c 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -1,5 +1,5 @@ import {expect} from 'chai'; -import {spec, REQUEST_URL, SYNC_URL, DEFAULT_PH} from 'modules/openxOrtbBidAdapter.js'; +import {spec, REQUEST_URL, SYNC_URL, DEFAULT_PH} from 'modules/openxBidAdapter.js'; import {newBidder} from 'src/adapters/bidderFactory.js'; import {BANNER, VIDEO} from 'src/mediaTypes.js'; import {config} from 'src/config.js'; diff --git a/test/spec/modules/openxOrtbBidAdapter_spec.js b/test/spec/modules/openxOrtbBidAdapter_spec.js deleted file mode 100644 index d8ea79ac698..00000000000 --- a/test/spec/modules/openxOrtbBidAdapter_spec.js +++ /dev/null @@ -1,1615 +0,0 @@ -import {expect} from 'chai'; -import {spec, REQUEST_URL, SYNC_URL, DEFAULT_PH} from 'modules/openxOrtbBidAdapter.js'; -import {newBidder} from 'src/adapters/bidderFactory.js'; -import {BANNER, VIDEO} from 'src/mediaTypes.js'; -import {config} from 'src/config.js'; -import * as utils from 'src/utils.js'; -// load modules that register ORTB processors -import 'src/prebid.js' -import 'modules/currency.js'; -import 'modules/userId/index.js'; -import 'modules/multibid/index.js'; -import 'modules/priceFloors.js'; -import 'modules/consentManagement.js'; -import 'modules/consentManagementUsp.js'; -import 'modules/schain.js'; -import {deepClone} from 'src/utils.js'; -import {syncAddFPDToBidderRequest} from '../../helpers/fpd.js'; -import {hook} from '../../../src/hook.js'; - -const DEFAULT_SYNC = SYNC_URL + '?ph=' + DEFAULT_PH; - -const BidRequestBuilder = function BidRequestBuilder(options) { - const defaults = { - request: { - auctionId: '4fd1ca2d-846c-4211-b9e5-321dfe1709c9', - adUnitCode: 'adunit-code', - bidder: 'openx' - }, - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - sizes: [[300, 250], [300, 600]], - }; - - const request = { - ...defaults.request, - ...options - }; - - this.withParams = (options) => { - request.params = { - ...defaults.params, - ...options - }; - return this; - }; - - this.build = () => request; -}; - -const BidderRequestBuilder = function BidderRequestBuilder(options) { - const defaults = { - bidderCode: 'openx', - auctionId: '4fd1ca2d-846c-4211-b9e5-321dfe1709c9', - bidderRequestId: '7g36s867Tr4xF90X', - timeout: 3000, - refererInfo: { - numIframes: 0, - reachedTop: true, - referer: 'http://test.io/index.html?pbjs_debug=true' - } - }; - - const request = { - ...defaults, - ...options - }; - - this.build = () => request; -}; - -describe('OpenxRtbAdapter', function () { - before(() => { - hook.ready(); - }); - - const adapter = newBidder(spec); - - describe('inherited functions', function () { - it('exists and is a function', function () { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid()', function () { - describe('when request is for a banner ad', function () { - let bannerBid; - beforeEach(function () { - bannerBid = { - bidder: 'openx', - params: {}, - adUnitCode: 'adunit-code', - mediaTypes: {banner: {}}, - sizes: [[300, 250], [300, 600]], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475' - }; - }); - - it('should return false when there is no delivery domain', function () { - bannerBid.params = {'unit': '12345678'}; - expect(spec.isBidRequestValid(bannerBid)).to.equal(false); - }); - - describe('when there is a delivery domain', function () { - beforeEach(function () { - bannerBid.params = {delDomain: 'test-delivery-domain'} - }); - - it('should return false when there is no ad unit id and size', function () { - expect(spec.isBidRequestValid(bannerBid)).to.equal(false); - }); - - it('should return true if there is an adunit id ', function () { - bannerBid.params.unit = '12345678'; - expect(spec.isBidRequestValid(bannerBid)).to.equal(true); - }); - - it('should return true if there is no adunit id and sizes are defined', function () { - bannerBid.mediaTypes.banner.sizes = [720, 90]; - expect(spec.isBidRequestValid(bannerBid)).to.equal(true); - }); - - it('should return false if no sizes are defined ', function () { - expect(spec.isBidRequestValid(bannerBid)).to.equal(false); - }); - - it('should return false if sizes empty ', function () { - bannerBid.mediaTypes.banner.sizes = []; - expect(spec.isBidRequestValid(bannerBid)).to.equal(false); - }); - }); - }); - - describe('when request is for a multiformat ad', function () { - describe('and request config uses mediaTypes video and banner', () => { - const multiformatBid = { - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250]] - }, - video: { - playerSize: [300, 250] - } - }, - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - transactionId: '4008d88a-8137-410b-aa35-fbfdabcb478e' - }; - it('should return true multisize when required params found', function () { - expect(spec.isBidRequestValid(multiformatBid)).to.equal(true); - }); - }); - }); - - describe('when request is for a video ad', function () { - describe('and request config uses mediaTypes', () => { - const videoBidWithMediaTypes = { - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - video: { - playerSize: [640, 480] - } - }, - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - transactionId: '4008d88a-8137-410b-aa35-fbfdabcb478e' - }; - it('should return true when required params found', function () { - expect(spec.isBidRequestValid(videoBidWithMediaTypes)).to.equal(true); - }); - - it('should return false when required params are not passed', function () { - let videoBidWithMediaTypes = Object.assign({}, videoBidWithMediaTypes); - videoBidWithMediaTypes.params = {}; - expect(spec.isBidRequestValid(videoBidWithMediaTypes)).to.equal(false); - }); - }); - describe('and request config uses both delDomain and platform', () => { - const videoBidWithDelDomainAndPlatform = { - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain', - platform: '1cabba9e-cafe-3665-beef-f00f00f00f00' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - video: { - playerSize: [640, 480] - } - }, - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475', - transactionId: '4008d88a-8137-410b-aa35-fbfdabcb478e' - }; - it('should return true when required params found', function () { - expect(spec.isBidRequestValid(videoBidWithDelDomainAndPlatform)).to.equal(true); - }); - - it('should return false when required params are not passed', function () { - let videoBidWithMediaTypes = Object.assign({}, videoBidWithDelDomainAndPlatform); - videoBidWithMediaTypes.params = {}; - expect(spec.isBidRequestValid(videoBidWithMediaTypes)).to.equal(false); - }); - }); - describe('and request config uses mediaType', () => { - const videoBidWithMediaType = { - 'bidder': 'openx', - 'params': { - 'unit': '12345678', - 'delDomain': 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - 'mediaType': 'video', - 'sizes': [640, 480], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' - }; - it('should return true when required params found', function () { - expect(spec.isBidRequestValid(videoBidWithMediaType)).to.equal(true); - }); - - it('should return false when required params are not passed', function () { - let videoBidWithMediaType = Object.assign({}, videoBidWithMediaType); - delete videoBidWithMediaType.params; - videoBidWithMediaType.params = {}; - expect(spec.isBidRequestValid(videoBidWithMediaType)).to.equal(false); - }); - }); - }); - }); - - describe('buildRequests()', function () { - let bidRequestsWithMediaTypes; - let bidRequestsWithPlatform; - let mockBidderRequest; - - beforeEach(function () { - mockBidderRequest = {refererInfo: {}}; - - bidRequestsWithMediaTypes = [{ - bidder: 'openx', - params: { - unit: '11', - delDomain: 'test-del-domain', - platform: '1cabba9e-cafe-3665-beef-f00f00f00f00', - }, - adUnitCode: '/adunit-code/test-path', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - bidId: 'test-bid-id-1', - bidderRequestId: 'test-bid-request-1', - auctionId: 'test-auction-1', - transactionId: 'test-transactionId-1', - ortb2Imp: { - ext: { - ae: 2 - } - } - }, { - bidder: 'openx', - params: { - unit: '22', - delDomain: 'test-del-domain', - platform: '1cabba9e-cafe-3665-beef-f00f00f00f00', - }, - adUnitCode: 'adunit-code', - mediaTypes: { - video: { - playerSize: [640, 480] - } - }, - bidId: 'test-bid-id-2', - bidderRequestId: 'test-bid-request-2', - auctionId: 'test-auction-2', - transactionId: 'test-transactionId-2' - }]; - }); - - context('common requests checks', function() { - it('should be able to handle multiformat requests', () => { - const multiformat = utils.deepClone(bidRequestsWithMediaTypes[0]); - multiformat.mediaTypes.video = { - context: 'outstream', - playerSize: [640, 480] - } - const requests = spec.buildRequests([multiformat], mockBidderRequest); - const outgoingFormats = requests.flatMap(rq => rq.data.imp.flatMap(imp => ['banner', 'video'].filter(k => imp[k] != null))); - const expected = FEATURES.VIDEO ? ['banner', 'video'] : ['banner'] - expect(outgoingFormats).to.have.members(expected); - }) - - it('should send bid request to openx url via POST', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); - expect(request[0].url).to.equal(REQUEST_URL); - expect(request[0].method).to.equal('POST'); - }); - - it('should send delivery domain, if available', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); - expect(request[0].data.ext.delDomain).to.equal(bidRequestsWithMediaTypes[0].params.delDomain); - expect(request[0].data.ext.platformId).to.be.undefined; - }); - - it('should send platform id, if available', function () { - bidRequestsWithMediaTypes[0].params.platform = '1cabba9e-cafe-3665-beef-f00f00f00f00'; - bidRequestsWithMediaTypes[1].params.platform = '1cabba9e-cafe-3665-beef-f00f00f00f00'; - - const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); - expect(request[0].data.ext.platform).to.equal(bidRequestsWithMediaTypes[0].params.platform); - expect(request[1].data.ext.platform).to.equal(bidRequestsWithMediaTypes[0].params.platform); - }); - - it('should send openx adunit codes', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); - expect(request[0].data.imp[0].tagid).to.equal(bidRequestsWithMediaTypes[0].params.unit); - expect(request[1].data.imp[0].tagid).to.equal(bidRequestsWithMediaTypes[1].params.unit); - }); - - it('should send out custom params on bids that have customParams specified', function () { - const bidRequest = Object.assign({}, - bidRequestsWithMediaTypes[0], - { - params: { - unit: '12345678', - delDomain: 'test-del-domain', - customParams: {'Test1': 'testval1+', 'test2': ['testval2/', 'testval3']} - } - } - ); - - mockBidderRequest.bids = [bidRequest]; - const request = spec.buildRequests([bidRequest], mockBidderRequest); - expect(request[0].data.imp[0].ext.customParams).to.equal(bidRequest.params.customParams); - }) - - describe('floors', function () { - it('should send out custom floors on bids that have customFloors, no currency as account currency is used', function () { - const bidRequest = Object.assign({}, - bidRequestsWithMediaTypes[0], - { - params: { - unit: '12345678', - delDomain: 'test-del-domain', - customFloor: 1.500 - } - } - ); - - const request = spec.buildRequests([bidRequest], mockBidderRequest); - expect(request[0].data.imp[0].bidfloor).to.equal(bidRequest.params.customFloor); - expect(request[0].data.imp[0].bidfloorcur).to.equal(undefined); - }); - - context('with floors module', function () { - let adServerCurrencyStub; - - beforeEach(function () { - adServerCurrencyStub = sinon - .stub(config, 'getConfig') - .withArgs('currency.adServerCurrency') - }); - - afterEach(function () { - config.getConfig.restore(); - }); - - it('should send out floors on bids in USD', function () { - const bidRequest = Object.assign({}, - bidRequestsWithMediaTypes[0], - { - getFloor: () => { - return { - currency: 'USD', - floor: 9.99 - } - } - } - ); - - const request = spec.buildRequests([bidRequest], mockBidderRequest); - expect(request[0].data.imp[0].bidfloor).to.equal(9.99); - expect(request[0].data.imp[0].bidfloorcur).to.equal('USD'); - }); - - it('should send not send floors', function () { - adServerCurrencyStub.returns('EUR'); - const bidRequest = Object.assign({}, - bidRequestsWithMediaTypes[0], - { - getFloor: () => { - return { - currency: 'BTC', - floor: 9.99 - } - } - } - ); - - const request = spec.buildRequests([bidRequest], mockBidderRequest); - expect(request[0].data.imp[0].bidfloor).to.equal(undefined) - expect(request[0].data.imp[0].bidfloorcur).to.equal(undefined) - }); - }) - }) - - describe('FPD', function() { - let bidRequests; - const mockBidderRequest = {refererInfo: {}}; - - beforeEach(function () { - bidRequests = [{ - bidder: 'openx', - params: { - unit: '12345678-banner', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - bidId: 'test-bid-id', - bidderRequestId: 'test-bidder-request-id', - auctionId: 'test-auction-id', - transactionId: 'test-transaction-id-1' - }, { - bidder: 'openx', - mediaTypes: { - video: { - playerSize: [640, 480] - } - }, - params: { - unit: '12345678-video', - delDomain: 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - - bidId: 'test-bid-id', - bidderRequestId: 'test-bidder-request-id', - auctionId: 'test-auction-id', - transactionId: 'test-transaction-id-2' - }]; - }); - - it('ortb2.site should be merged in the request', function() { - const request = spec.buildRequests(bidRequests, { - ...mockBidderRequest, - 'ortb2': { - site: { - domain: 'page.example.com', - cat: ['IAB2'], - sectioncat: ['IAB2-2'] - } - } - }); - let data = request[0].data; - expect(data.site.domain).to.equal('page.example.com'); - expect(data.site.cat).to.deep.equal(['IAB2']); - expect(data.site.sectioncat).to.deep.equal(['IAB2-2']); - }); - - it('ortb2.user should be merged in the request', function() { - const request = spec.buildRequests(bidRequests, { - ...mockBidderRequest, - 'ortb2': { - user: { - yob: 1985 - } - } - }); - let data = request[0].data; - expect(data.user.yob).to.equal(1985); - }); - - describe('ortb2Imp', function() { - describe('ortb2Imp.ext.data.pbadslot', function() { - beforeEach(function () { - if (bidRequests[0].hasOwnProperty('ortb2Imp')) { - delete bidRequests[0].ortb2Imp; - } - }); - - it('should not send if imp[].ext.data object is invalid', function() { - bidRequests[0].ortb2Imp = { - ext: {} - }; - const request = spec.buildRequests(bidRequests, mockBidderRequest); - let data = request[0].data; - expect(data.imp[0].ext).to.not.have.property('data'); - }); - - it('should not send if imp[].ext.data.pbadslot is undefined', function() { - bidRequests[0].ortb2Imp = { - ext: { - data: { - } - } - }; - const request = spec.buildRequests(bidRequests, mockBidderRequest); - let data = request[0].data; - if (data.imp[0].ext.data) { - expect(data.imp[0].ext.data).to.not.have.property('pbadslot'); - } else { - expect(data.imp[0].ext).to.not.have.property('data'); - } - }); - - it('should send if imp[].ext.data.pbadslot is string', function() { - bidRequests[0].ortb2Imp = { - ext: { - data: { - pbadslot: 'abcd' - } - } - }; - const request = spec.buildRequests(bidRequests, mockBidderRequest); - let data = request[0].data; - expect(data.imp[0].ext.data).to.have.property('pbadslot'); - expect(data.imp[0].ext.data.pbadslot).to.equal('abcd'); - }); - }); - - describe('ortb2Imp.ext.data.adserver', function() { - beforeEach(function () { - if (bidRequests[0].hasOwnProperty('ortb2Imp')) { - delete bidRequests[0].ortb2Imp; - } - }); - - it('should not send if imp[].ext.data object is invalid', function() { - bidRequests[0].ortb2Imp = { - ext: {} - }; - const request = spec.buildRequests(bidRequests, mockBidderRequest); - let data = request[0].data; - expect(data.imp[0].ext).to.not.have.property('data'); - }); - - it('should not send if imp[].ext.data.adserver is undefined', function() { - bidRequests[0].ortb2Imp = { - ext: { - data: { - } - } - }; - const request = spec.buildRequests(bidRequests, mockBidderRequest); - let data = request[0].data; - if (data.imp[0].ext.data) { - expect(data.imp[0].ext.data).to.not.have.property('adserver'); - } else { - expect(data.imp[0].ext).to.not.have.property('data'); - } - }); - - it('should send', function() { - let adSlotValue = 'abc'; - bidRequests[0].ortb2Imp = { - ext: { - data: { - adserver: { - name: 'GAM', - adslot: adSlotValue - } - } - } - }; - const request = spec.buildRequests(bidRequests, mockBidderRequest); - let data = request[0].data; - expect(data.imp[0].ext.data.adserver.name).to.equal('GAM'); - expect(data.imp[0].ext.data.adserver.adslot).to.equal(adSlotValue); - }); - }); - - describe('ortb2Imp.ext.data.other', function() { - beforeEach(function () { - if (bidRequests[0].hasOwnProperty('ortb2Imp')) { - delete bidRequests[0].ortb2Imp; - } - }); - - it('should not send if imp[].ext.data object is invalid', function() { - bidRequests[0].ortb2Imp = { - ext: {} - }; - const request = spec.buildRequests(bidRequests, mockBidderRequest); - let data = request[0].data; - expect(data.imp[0].ext).to.not.have.property('data'); - }); - - it('should not send if imp[].ext.data.other is undefined', function() { - bidRequests[0].ortb2Imp = { - ext: { - data: { - } - } - }; - const request = spec.buildRequests(bidRequests, mockBidderRequest); - let data = request[0].data; - if (data.imp[0].ext.data) { - expect(data.imp[0].ext.data).to.not.have.property('other'); - } else { - expect(data.imp[0].ext).to.not.have.property('data'); - } - }); - - it('ortb2Imp.ext.data.other', function() { - bidRequests[0].ortb2Imp = { - ext: { - data: { - other: 1234 - } - } - }; - const request = spec.buildRequests(bidRequests, mockBidderRequest); - let data = request[0].data; - expect(data.imp[0].ext.data.other).to.equal(1234); - }); - }); - }); - - describe('with user agent client hints', function () { - it('should add device.sua if available', function () { - const bidderRequestWithUserAgentClientHints = { refererInfo: {}, - ortb2: { - device: { - sua: { - source: 2, - platform: { - brand: 'macOS', - version: [ '12', '4', '0' ] - }, - browsers: [ - { - brand: 'Chromium', - version: [ '106', '0', '5249', '119' ] - }, - { - brand: 'Google Chrome', - version: [ '106', '0', '5249', '119' ] - }, - { - brand: 'Not;A=Brand', - version: [ '99', '0', '0', '0' ] - }], - mobile: 0, - model: 'Pro', - bitness: '64', - architecture: 'x86' - } - } - }}; - - let request = spec.buildRequests(bidRequests, bidderRequestWithUserAgentClientHints); - expect(request[0].data.device.sua).to.exist; - expect(request[0].data.device.sua).to.deep.equal(bidderRequestWithUserAgentClientHints.ortb2.device.sua); - const bidderRequestWithoutUserAgentClientHints = {refererInfo: {}, ortb2: {}}; - request = spec.buildRequests(bidRequests, bidderRequestWithoutUserAgentClientHints); - expect(request[0].data.device?.sua).to.not.exist; - }); - }); - }); - - context('when there is a consent management framework', function () { - let bidRequests; - let mockConfig; - let bidderRequest; - - beforeEach(function () { - bidRequests = [{ - bidder: 'openx', - params: { - unit: '12345678-banner', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - bidId: 'test-bid-id', - bidderRequestId: 'test-bidder-request-id', - auctionId: 'test-auction-id', - transactionId: 'test-transaction-id-1' - }, { - bidder: 'openx', - mediaTypes: { - video: { - playerSize: [640, 480] - } - }, - params: { - unit: '12345678-video', - delDomain: 'test-del-domain' - }, - 'adUnitCode': 'adunit-code', - - bidId: 'test-bid-id', - bidderRequestId: 'test-bidder-request-id', - auctionId: 'test-auction-id', - transactionId: 'test-transaction-id-2' - }]; - }); - - describe('us_privacy', function () { - beforeEach(function () { - bidderRequest = { - uspConsent: '1YYN', - refererInfo: {} - }; - - sinon.stub(config, 'getConfig').callsFake((key) => { - return utils.deepAccess(mockConfig, key); - }); - }); - - afterEach(function () { - config.getConfig.restore(); - }); - - it('should send a signal to specify that US Privacy applies to this request', function () { - const request = spec.buildRequests(bidRequests, syncAddFPDToBidderRequest(bidderRequest)); - expect(request[0].data.regs.ext.us_privacy).to.equal('1YYN'); - expect(request[1].data.regs.ext.us_privacy).to.equal('1YYN'); - }); - - it('should not send the regs object, when consent string is undefined', function () { - delete bidderRequest.uspConsent; - const request = spec.buildRequests(bidRequests, syncAddFPDToBidderRequest(bidderRequest)); - expect(request[0].data.regs?.us_privacy).to.not.exist; - }); - }); - - describe('GDPR', function () { - beforeEach(function () { - bidderRequest = { - gdprConsent: { - consentString: 'test-gdpr-consent-string', - addtlConsent: 'test-addtl-consent-string', - gdprApplies: true - }, - refererInfo: {} - }; - - mockConfig = { - consentManagement: { - cmpApi: 'iab', - timeout: 1111, - allowAuctionWithoutConsent: 'cancel' - } - }; - - sinon.stub(config, 'getConfig').callsFake((key) => { - return utils.deepAccess(mockConfig, key); - }); - }); - - afterEach(function () { - config.getConfig.restore(); - }); - - it('should send a signal to specify that GDPR applies to this request', function () { - bidderRequest.bids = bidRequests; - const request = spec.buildRequests(bidRequests, syncAddFPDToBidderRequest(bidderRequest)); - expect(request[0].data.regs.ext.gdpr).to.equal(1); - expect(request[1].data.regs.ext.gdpr).to.equal(1); - }); - - it('should send the consent string', function () { - bidderRequest.bids = bidRequests; - const request = spec.buildRequests(bidRequests, syncAddFPDToBidderRequest(bidderRequest)); - expect(request[0].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString); - expect(request[1].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString); - }); - - it('should send the addtlConsent string', function () { - bidderRequest.bids = bidRequests; - const request = spec.buildRequests(bidRequests, syncAddFPDToBidderRequest(bidderRequest)); - expect(request[0].data.user.ext.ConsentedProvidersSettings.consented_providers).to.equal(bidderRequest.gdprConsent.addtlConsent); - expect(request[1].data.user.ext.ConsentedProvidersSettings.consented_providers).to.equal(bidderRequest.gdprConsent.addtlConsent); - }); - - it('should send a signal to specify that GDPR does not apply to this request', function () { - bidderRequest.gdprConsent.gdprApplies = false; - bidderRequest.bids = bidRequests; - const request = spec.buildRequests(bidRequests, syncAddFPDToBidderRequest(bidderRequest)); - expect(request[0].data.regs.ext.gdpr).to.equal(0); - expect(request[1].data.regs.ext.gdpr).to.equal(0); - }); - - it('when GDPR application is undefined, should not send a signal to specify whether GDPR applies to this request, ' + - 'but can send consent data, ', function () { - delete bidderRequest.gdprConsent.gdprApplies; - bidderRequest.bids = bidRequests; - const request = spec.buildRequests(bidRequests, syncAddFPDToBidderRequest(bidderRequest)); - expect(request[0].data.regs?.ext?.gdpr).to.not.be.ok; - expect(request[0].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString); - expect(request[1].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString); - }); - - it('when consent string is undefined, should not send the consent string, ', function () { - delete bidderRequest.gdprConsent.consentString; - bidderRequest.bids = bidRequests; - const request = spec.buildRequests(bidRequests, syncAddFPDToBidderRequest(bidderRequest)); - expect(request[0].data.imp[0].ext.consent).to.equal(undefined); - expect(request[1].data.imp[0].ext.consent).to.equal(undefined); - }); - }); - }); - - context('coppa', function() { - it('when there are no coppa param settings, should not send a coppa flag', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes, syncAddFPDToBidderRequest(mockBidderRequest)); - expect(request[0].data.regs?.coppa).to.be.not.ok; - }); - - it('should send a coppa flag there is when there is coppa param settings in the bid requests', function () { - let mockConfig = { - coppa: true - }; - - sinon.stub(config, 'getConfig').callsFake((key) => { - return utils.deepAccess(mockConfig, key); - }); - - const request = spec.buildRequests(bidRequestsWithMediaTypes, syncAddFPDToBidderRequest(mockBidderRequest)); - expect(request[0].data.regs.coppa).to.equal(1); - }); - - it('should send a coppa flag there is when there is coppa param settings in the bid params', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes, syncAddFPDToBidderRequest(mockBidderRequest)); - request.params = {coppa: true}; - expect(request[0].data.regs.coppa).to.equal(1); - }); - - after(function () { - config.getConfig.restore() - }); - }); - - context('do not track (DNT)', function() { - let doNotTrackStub; - - beforeEach(function () { - doNotTrackStub = sinon.stub(utils, 'getDNT'); - }); - afterEach(function() { - doNotTrackStub.restore(); - }); - - it('when there is a do not track, should send a dnt', function () { - doNotTrackStub.returns(1); - - const request = spec.buildRequests(bidRequestsWithMediaTypes, syncAddFPDToBidderRequest(mockBidderRequest)); - expect(request[0].data.device.dnt).to.equal(1); - }); - - it('when there is not do not track, don\'t send dnt', function () { - doNotTrackStub.returns(0); - - const request = spec.buildRequests(bidRequestsWithMediaTypes, syncAddFPDToBidderRequest(mockBidderRequest)); - expect(request[0].data.device.dnt).to.equal(0); - }); - - it('when there is no defined do not track, don\'t send dnt', function () { - doNotTrackStub.returns(null); - - const request = spec.buildRequests(bidRequestsWithMediaTypes, syncAddFPDToBidderRequest(mockBidderRequest)); - expect(request[0].data.device.dnt).to.equal(0); - }); - }); - - context('supply chain (schain)', function () { - let bidRequests; - let schainConfig; - const supplyChainNodePropertyOrder = ['asi', 'sid', 'hp', 'rid', 'name', 'domain']; - - beforeEach(function () { - schainConfig = { - ver: '1.0', - complete: 1, - nodes: [ - { - asi: 'exchange1.com', - sid: '1234', - hp: 1, - rid: 'bid-request-1', - name: 'publisher', - domain: 'publisher.com' - // omitted ext - }, - { - asi: 'exchange2.com', - sid: 'abcd', - hp: 1, - rid: 'bid-request-2', - // name field missing - domain: 'intermediary.com' - }, - { - asi: 'exchange3.com', - sid: '4321', - hp: 1, - // request id - // name field missing - domain: 'intermediary-2.com' - } - ] - }; - - bidRequests = [{ - bidder: 'openx', - params: { - unit: '11', - delDomain: 'test-del-domain' - }, - adUnitCode: '/adunit-code/test-path', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - bidId: 'test-bid-id-1', - bidderRequestId: 'test-bid-request-1', - auctionId: 'test-auction-1', - schain: schainConfig - }]; - }); - - it('should send a supply chain object', function () { - const request = spec.buildRequests(bidRequests, mockBidderRequest); - expect(request[0].data.source.ext.schain).to.equal(schainConfig); - }); - - it('should send the supply chain object with the right version', function () { - const request = spec.buildRequests(bidRequests, mockBidderRequest); - expect(request[0].data.source.ext.schain.ver).to.equal(schainConfig.ver); - }); - - it('should send the supply chain object with the right complete value', function () { - const request = spec.buildRequests(bidRequests, mockBidderRequest); - expect(request[0].data.source.ext.schain.complete).to.equal(schainConfig.complete); - }); - }); - - context('when there are userid providers', function () { - const userIdAsEids = [ - { - source: 'adserver.org', - uids: [{ - id: 'some-random-id-value', - atype: 1, - ext: { - rtiPartner: 'TDID' - } - }] - }, - { - source: 'id5-sync.com', - uids: [{ - id: 'some-random-id-value', - atype: 1 - }] - }, - { - source: 'sharedid.org', - uids: [{ - id: 'some-random-id-value', - atype: 1, - ext: { - third: 'some-random-id-value' - } - }] - } - ]; - - it(`should send the user id under the extended ids`, function () { - const bidRequestsWithUserId = [{ - bidder: 'openx', - params: { - unit: '11', - delDomain: 'test-del-domain' - }, - userId: { - }, - adUnitCode: 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]] - } - }, - bidId: 'test-bid-id-1', - bidderRequestId: 'test-bid-request-1', - auctionId: 'test-auction-1', - userIdAsEids: userIdAsEids - }]; - // enrich bid request with userId key/value - - const request = spec.buildRequests(bidRequestsWithUserId, mockBidderRequest); - expect(request[0].data.user.ext.eids).to.equal(userIdAsEids); - }); - - it(`when no user ids are available, it should not send any extended ids`, function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); - expect(request[0].data).to.not.have.any.keys('user'); - }); - }); - - context('FLEDGE', function() { - it('when FLEDGE is enabled, should send whatever is set in ortb2imp.ext.ae in all bid requests', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes, { - ...mockBidderRequest, - fledgeEnabled: true - }); - expect(request[0].data.imp[0].ext.ae).to.equal(2); - }); - }); - }); - - context('banner', function () { - it('should send bid request with a mediaTypes specified with banner type', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); - expect(request[0].data.imp[0]).to.have.any.keys(BANNER); - }); - }); - - if (FEATURES.VIDEO) { - context('video', function () { - it('should send bid request with a mediaTypes specified with video type', function () { - const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest); - expect(request[1].data.imp[0]).to.have.any.keys(VIDEO); - }); - - it('Update imp.video with OpenRTB options from mimeTypes and params', function() { - const bid01 = new BidRequestBuilder({ - adUnitCode: 'adunit-code-01', - mediaTypes: { - banner: { sizes: [[300, 250]] }, - video: { - context: 'outstream', - playerSize: [[300, 250]], - mimes: ['video/mp4'], - protocols: [8] - } - }, - }).withParams({ - // options in video, will merge - video: { - skip: 1, - skipafter: 4, - minduration: 10, - maxduration: 30 - } - }).build(); - - const bidderRequest = new BidderRequestBuilder().build(); - const expected = { - mimes: ['video/mp4'], - skip: 1, - skipafter: 4, - minduration: 10, - maxduration: 30, - placement: 4, - protocols: [8], - w: 300, - h: 250 - }; - const requests = spec.buildRequests([bid01], bidderRequest); - expect(requests).to.have.lengthOf(2); - expect(requests[1].data.imp[0].video).to.deep.equal(expected); - }); - }); - } - }); - - describe('interpretResponse()', function () { - let bidRequestConfigs; - let bidRequest; - let bidResponse; - let bid; - - context('when there is an nbr response', function () { - let bids; - beforeEach(function () { - bidRequestConfigs = [{ - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]], - }, - }, - bidId: 'test-bid-id', - bidderRequestId: 'test-bidder-request-id', - auctionId: 'test-auction-id' - }]; - - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; - - bidResponse = {nbr: 0}; // Unknown error - bids = spec.interpretResponse({body: bidResponse}, bidRequest); - }); - - it('should not return any bids', function () { - expect(bids.length).to.equal(0); - }); - }); - - context('when no seatbid in response', function () { - let bids; - beforeEach(function () { - bidRequestConfigs = [{ - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]], - }, - }, - bidId: 'test-bid-id', - bidderRequestId: 'test-bidder-request-id', - auctionId: 'test-auction-id' - }]; - - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; - - bidResponse = {ext: {}, id: 'test-bid-id'}; - bids = spec.interpretResponse({body: bidResponse}, bidRequest); - }); - - it('should not return any bids', function () { - expect(bids.length).to.equal(0); - }); - }); - - context('when there is no response', function () { - let bids; - beforeEach(function () { - bidRequestConfigs = [{ - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]], - }, - }, - bidId: 'test-bid-id', - bidderRequestId: 'test-bidder-request-id', - auctionId: 'test-auction-id' - }]; - - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; - - bidResponse = ''; // Unknown error - bids = spec.interpretResponse({body: bidResponse}, bidRequest); - }); - - it('should not return any bids', function () { - expect(bids.length).to.equal(0); - }); - }); - - const SAMPLE_BID_REQUESTS = [{ - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]], - }, - }, - bidId: 'test-bid-id', - bidderRequestId: 'test-bidder-request-id', - auctionId: 'test-auction-id' - }]; - - const SAMPLE_BID_RESPONSE = { - seatbid: [{ - bid: [{ - impid: 'test-bid-id', - price: 2, - w: 300, - h: 250, - crid: 'test-creative-id', - dealid: 'test-deal-id', - adm: 'test-ad-markup', - adomain: ['brand.com'], - ext: { - dsp_id: '123', - buyer_id: '456', - brand_id: '789', - paf: { - content_id: 'paf_content_id' - } - } - }] - }], - cur: 'AUS', - ext: { - paf: { - transmission: {version: '12'} - } - } - }; - - context('when there is a response, the common response properties', function () { - beforeEach(function () { - bidRequestConfigs = deepClone(SAMPLE_BID_REQUESTS); - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; - bidResponse = deepClone(SAMPLE_BID_RESPONSE); - - bid = spec.interpretResponse({body: bidResponse}, bidRequest)[0]; - }); - - it('should return a price', function () { - expect(bid.cpm).to.equal(bidResponse.seatbid[0].bid[0].price); - }); - - it('should return a request id', function () { - expect(bid.requestId).to.equal(bidResponse.seatbid[0].bid[0].impid); - }); - - it('should return width and height for the creative', function () { - expect(bid.width).to.equal(bidResponse.seatbid[0].bid[0].w); - expect(bid.height).to.equal(bidResponse.seatbid[0].bid[0].h); - }); - - it('should return a creativeId', function () { - expect(bid.creativeId).to.equal(bidResponse.seatbid[0].bid[0].crid); - }); - - it('should return an ad', function () { - expect(bid.ad).to.equal(bidResponse.seatbid[0].bid[0].adm); - }); - - it('should return a deal id if it exists', function () { - expect(bid.dealId).to.equal(bidResponse.seatbid[0].bid[0].dealid); - }); - - it('should have a time-to-live of 5 minutes', function () { - expect(bid.ttl).to.equal(300); - }); - - it('should always return net revenue', function () { - expect(bid.netRevenue).to.equal(true); - }); - - it('should return a currency', function () { - expect(bid.currency).to.equal(bidResponse.cur); - }); - - it('should return a brand ID', function () { - expect(bid.meta.brandId).to.equal(bidResponse.seatbid[0].bid[0].ext.brand_id); - }); - - it('should return a dsp ID', function () { - expect(bid.meta.networkId).to.equal(bidResponse.seatbid[0].bid[0].ext.dsp_id); - }); - - it('should return a buyer ID', function () { - expect(bid.meta.advertiserId).to.equal(bidResponse.seatbid[0].bid[0].ext.buyer_id); - }); - - it('should return adomain', function () { - expect(bid.meta.advertiserDomains).to.equal(bidResponse.seatbid[0].bid[0].adomain); - }); - - it('should return paf fields', function () { - const paf = { - transmission: {version: '12'}, - content_id: 'paf_content_id' - } - expect(bid.meta.paf).to.deep.equal(paf); - }); - }); - - context('when there is more than one response', () => { - let bids; - beforeEach(function () { - bidRequestConfigs = deepClone(SAMPLE_BID_REQUESTS); - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; - bidResponse = deepClone(SAMPLE_BID_RESPONSE); - bidResponse.seatbid[0].bid.push(deepClone(bidResponse.seatbid[0].bid[0])); - bidResponse.seatbid[0].bid[1].ext.paf.content_id = 'second_paf' - - bids = spec.interpretResponse({body: bidResponse}, bidRequest); - }); - - it('should not confuse paf content_id', () => { - expect(bids.map(b => b.meta.paf.content_id)).to.eql(['paf_content_id', 'second_paf']); - }); - }) - - context('when the response is a banner', function() { - beforeEach(function () { - bidRequestConfigs = [{ - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]], - }, - }, - bidId: 'test-bid-id', - bidderRequestId: 'test-bidder-request-id', - auctionId: 'test-auction-id' - }]; - - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; - - bidResponse = { - seatbid: [{ - bid: [{ - impid: 'test-bid-id', - price: 2, - w: 300, - h: 250, - crid: 'test-creative-id', - dealid: 'test-deal-id', - adm: 'test-ad-markup' - }] - }], - cur: 'AUS' - }; - - bid = spec.interpretResponse({body: bidResponse}, bidRequest)[0]; - }); - - it('should return the proper mediaType', function () { - it('should return a creativeId', function () { - expect(bid.mediaType).to.equal(Object.keys(bidRequestConfigs[0].mediaTypes)[0]); - }); - }); - }); - - if (FEATURES.VIDEO) { - context('when the response is a video', function() { - beforeEach(function () { - bidRequestConfigs = [{ - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - video: { - playerSize: [[640, 360], [854, 480]], - }, - }, - bidId: 'test-bid-id', - bidderRequestId: 'test-bidder-request-id', - auctionId: 'test-auction-id' - }]; - - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; - - bidResponse = { - seatbid: [{ - bid: [{ - impid: 'test-bid-id', - price: 2, - w: 854, - h: 480, - crid: 'test-creative-id', - dealid: 'test-deal-id', - adm: 'test-ad-markup', - }] - }], - cur: 'AUS' - }; - }); - - it('should return the proper mediaType', function () { - bid = spec.interpretResponse({body: bidResponse}, bidRequest)[0]; - expect(bid.mediaType).to.equal(Object.keys(bidRequestConfigs[0].mediaTypes)[0]); - }); - - it('should return the proper mediaType', function () { - const winUrl = 'https//my.win.url'; - bidResponse.seatbid[0].bid[0].nurl = winUrl - bid = spec.interpretResponse({body: bidResponse}, bidRequest)[0]; - - expect(bid.vastUrl).to.equal(winUrl); - }); - }); - } - - context('when the response contains FLEDGE interest groups config', function() { - let response; - - beforeEach(function () { - sinon.stub(config, 'getConfig') - .withArgs('fledgeEnabled') - .returns(true); - - bidRequestConfigs = [{ - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: { - banner: { - sizes: [[300, 250], [300, 600]], - }, - }, - bidId: 'test-bid-id', - bidderRequestId: 'test-bidder-request-id', - auctionId: 'test-auction-id' - }]; - - bidRequest = spec.buildRequests(bidRequestConfigs, {refererInfo: {}})[0]; - - bidResponse = { - seatbid: [{ - bid: [{ - impid: 'test-bid-id', - price: 2, - w: 300, - h: 250, - crid: 'test-creative-id', - dealid: 'test-deal-id', - adm: 'test-ad-markup' - }] - }], - cur: 'AUS', - ext: { - fledge_auction_configs: { - 'test-bid-id': { - seller: 'codinginadtech.com', - interestGroupBuyers: ['somedomain.com'], - sellerTimeout: 0, - perBuyerSignals: { - 'somedomain.com': { - base_bid_micros: 0.1, - disallowed_advertiser_ids: [ - '1234', - '2345' - ], - multiplier: 1.3, - use_bid_multiplier: true, - win_reporting_id: '1234567asdf' - } - } - } - } - } - }; - - response = spec.interpretResponse({body: bidResponse}, bidRequest); - }); - - afterEach(function () { - config.getConfig.restore(); - }); - - it('should return FLEDGE auction_configs alongside bids', function () { - expect(response).to.have.property('bids'); - expect(response).to.have.property('fledgeAuctionConfigs'); - expect(response.fledgeAuctionConfigs.length).to.equal(1); - expect(response.fledgeAuctionConfigs[0].bidId).to.equal('test-bid-id'); - }); - }); - }); - - describe('user sync', function () { - it('should register the default image pixel if no pixels available', function () { - let syncs = spec.getUserSyncs( - {pixelEnabled: true}, - [] - ); - expect(syncs).to.deep.equal([{type: 'image', url: DEFAULT_SYNC}]); - }); - - it('should register custom syncUrl when exists', function () { - let syncs = spec.getUserSyncs( - {pixelEnabled: true}, - [{body: {ext: {delDomain: 'www.url.com'}}}] - ); - expect(syncs).to.deep.equal([{type: 'image', url: 'https://www.url.com/w/1.0/pd'}]); - }); - - it('should register custom syncUrl when exists', function () { - let syncs = spec.getUserSyncs( - {pixelEnabled: true}, - [{body: {ext: {platform: 'abc'}}}] - ); - expect(syncs).to.deep.equal([{type: 'image', url: SYNC_URL + '?ph=abc'}]); - }); - - it('when iframe sync is allowed, it should register an iframe sync', function () { - let syncs = spec.getUserSyncs( - {iframeEnabled: true}, - [] - ); - expect(syncs).to.deep.equal([{type: 'iframe', url: DEFAULT_SYNC}]); - }); - - it('should prioritize iframe over image for user sync', function () { - let syncs = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, - [] - ); - expect(syncs).to.deep.equal([{type: 'iframe', url: DEFAULT_SYNC}]); - }); - - describe('when gdpr applies', function () { - let gdprConsent; - let gdprPixelUrl; - const consentString = 'gdpr-pixel-consent'; - const gdprApplies = '1'; - beforeEach(() => { - gdprConsent = { - consentString, - gdprApplies: true - }; - - gdprPixelUrl = `${SYNC_URL}&gdpr=${gdprApplies}&gdpr_consent=${consentString}`; - }); - - it('when there is a response, it should have the gdpr query params', () => { - let [{url}] = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, - [], - gdprConsent - ); - - expect(url).to.have.string(`gdpr_consent=${consentString}`); - expect(url).to.have.string(`gdpr=${gdprApplies}`); - }); - - it('should not send signals if no consent object is available', function () { - let [{url}] = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, - [], - ); - expect(url).to.not.have.string('gdpr_consent='); - expect(url).to.not.have.string('gdpr='); - }); - }); - - describe('when ccpa applies', function () { - let usPrivacyConsent; - let uspPixelUrl; - const privacyString = 'TEST'; - beforeEach(() => { - usPrivacyConsent = 'TEST'; - uspPixelUrl = `${DEFAULT_SYNC}&us_privacy=${privacyString}` - }); - it('should send the us privacy string, ', () => { - let [{url}] = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, - [], - undefined, - usPrivacyConsent - ); - expect(url).to.have.string(`us_privacy=${privacyString}`); - }); - - it('should not send signals if no consent string is available', function () { - let [{url}] = spec.getUserSyncs( - {iframeEnabled: true, pixelEnabled: true}, - [], - ); - expect(url).to.not.have.string('us_privacy='); - }); - }); - }); -}); diff --git a/test/spec/modules/operaadsBidAdapter_spec.js b/test/spec/modules/operaadsBidAdapter_spec.js index 45bc8995a5c..37d4a2c7bc0 100644 --- a/test/spec/modules/operaadsBidAdapter_spec.js +++ b/test/spec/modules/operaadsBidAdapter_spec.js @@ -1,7 +1,7 @@ -import { expect } from 'chai'; -import { spec } from 'modules/operaadsBidAdapter.js'; -import { newBidder } from 'src/adapters/bidderFactory.js'; -import { BANNER, NATIVE, VIDEO } from 'src/mediaTypes.js'; +import {expect} from 'chai'; +import {spec} from 'modules/operaadsBidAdapter.js'; +import {newBidder} from 'src/adapters/bidderFactory.js'; +import {BANNER, NATIVE, VIDEO} from 'src/mediaTypes.js'; describe('Opera Ads Bid Adapter', function () { describe('Test isBidRequestValid', function () { @@ -234,7 +234,7 @@ describe('Opera Ads Bid Adapter', function () { requestData = JSON.parse(req.data); }).to.not.throw(); - expect(requestData.id).to.equal(bidderRequest.auctionId); + expect(requestData.id).to.exist; expect(requestData.tmax).to.equal(bidderRequest.timeout); expect(requestData.test).to.equal(0); expect(requestData.imp).to.be.an('array').that.have.lengthOf(1); diff --git a/test/spec/modules/optidigitalBidAdapter_spec.js b/test/spec/modules/optidigitalBidAdapter_spec.js index 8c222650f7e..caa12483ea9 100755 --- a/test/spec/modules/optidigitalBidAdapter_spec.js +++ b/test/spec/modules/optidigitalBidAdapter_spec.js @@ -557,7 +557,6 @@ describe('optidigitalAdapterTests', function () { let expectedResponse = [ { 'placementId': 'Billboard_Top', - 'transactionId': 'cf5faec3-fcee-4f26-80ae-fc8b6cf23b7d', 'requestId': '83fb53a5e67f49', 'ttl': 150, 'creativeId': 'mobile_pos_2', @@ -572,7 +571,6 @@ describe('optidigitalAdapterTests', function () { } }, { 'placementId': 'Billboard_Bottom', - 'transactionId': 'df5faec3-fcee-4f26-80ae-fc8b6cf23b7d', 'requestId': '93fb53a5e67f49', 'ttl': 150, 'creativeId': 'mobile_pos_2', diff --git a/test/spec/modules/orbidderBidAdapter_spec.js b/test/spec/modules/orbidderBidAdapter_spec.js index 0d1396866e7..e7a0c8becfb 100644 --- a/test/spec/modules/orbidderBidAdapter_spec.js +++ b/test/spec/modules/orbidderBidAdapter_spec.js @@ -9,7 +9,11 @@ describe('orbidderBidAdapter', () => { const defaultBidRequestBanner = { bidId: 'd66fa86787e0b0ca900a96eacfd5f0bb', auctionId: 'ccc4c7cdfe11cfbd74065e6dd28413d8', - transactionId: 'd58851660c0c4461e4aa06344fc9c0c6', + ortb2Imp: { + ext: { + tid: 'd58851660c0c4461e4aa06344fc9c0c6', + } + }, bidRequestCount: 1, adUnitCode: 'adunit-code', sizes: [[300, 250], [300, 600]], @@ -27,7 +31,11 @@ describe('orbidderBidAdapter', () => { const defaultBidRequestNative = { bidId: 'd66fa86787e0b0ca900a96eacfd5f0bc', auctionId: 'ccc4c7cdfe11cfbd74065e6dd28413d9', - transactionId: 'd58851660c0c4461e4aa06344fc9c0c7', + ortb2Imp: { + ext: { + tid: 'd58851660c0c4461e4aa06344fc9c0c7', + } + }, bidRequestCount: 1, adUnitCode: 'adunit-code-native', sizes: [], @@ -170,7 +178,7 @@ describe('orbidderBidAdapter', () => { expect(request.data.bidId).to.equal(defaultBidRequestBanner.bidId); expect(request.data.auctionId).to.equal(defaultBidRequestBanner.auctionId); - expect(request.data.transactionId).to.equal(defaultBidRequestBanner.transactionId); + expect(request.data.transactionId).to.equal(defaultBidRequestBanner.ortb2Imp.ext.tid); expect(request.data.bidRequestCount).to.equal(defaultBidRequestBanner.bidRequestCount); expect(request.data.adUnitCode).to.equal(defaultBidRequestBanner.adUnitCode); expect(request.data.pageUrl).to.equal('https://localhost:9876/'); @@ -187,7 +195,7 @@ describe('orbidderBidAdapter', () => { expect(nativeRequest.data.bidId).to.equal(defaultBidRequestNative.bidId); expect(nativeRequest.data.auctionId).to.equal(defaultBidRequestNative.auctionId); - expect(nativeRequest.data.transactionId).to.equal(defaultBidRequestNative.transactionId); + expect(nativeRequest.data.transactionId).to.equal(defaultBidRequestNative.ortb2Imp.ext.tid); expect(nativeRequest.data.bidRequestCount).to.equal(defaultBidRequestNative.bidRequestCount); expect(nativeRequest.data.adUnitCode).to.equal(defaultBidRequestNative.adUnitCode); expect(nativeRequest.data.pageUrl).to.equal('https://localhost:9876/'); diff --git a/test/spec/modules/outbrainBidAdapter_spec.js b/test/spec/modules/outbrainBidAdapter_spec.js index f5ce00ed8df..ab72ff85ab0 100644 --- a/test/spec/modules/outbrainBidAdapter_spec.js +++ b/test/spec/modules/outbrainBidAdapter_spec.js @@ -3,6 +3,7 @@ import { spec } from 'modules/outbrainBidAdapter.js'; import { config } from 'src/config.js'; import { server } from 'test/mocks/xhr'; import { createEidsArray } from 'modules/userId/eids.js'; +import * as utils from 'src/utils.js'; describe('Outbrain Adapter', function () { describe('Bid request and response', function () { @@ -227,6 +228,7 @@ describe('Outbrain Adapter', function () { }) const commonBidderRequest = { + bidderRequestId: 'mock-uuid', refererInfo: { page: 'https://example.com/' } @@ -263,6 +265,7 @@ describe('Outbrain Adapter', function () { ] } const expectedData = { + id: 'mock-uuid', site: { page: 'https://example.com/', publisher: { @@ -305,6 +308,7 @@ describe('Outbrain Adapter', function () { ...displayBidRequestParams, } const expectedData = { + id: 'mock-uuid', site: { page: 'https://example.com/', publisher: { @@ -352,6 +356,7 @@ describe('Outbrain Adapter', function () { ...videoBidRequestParams, } const expectedData = { + id: 'mock-uuid', site: { page: 'https://example.com/', publisher: { diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index 6427b917134..895c3754876 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -26,6 +26,7 @@ import 'modules/consentManagement.js'; import 'modules/consentManagementUsp.js'; import 'modules/schain.js'; import 'modules/fledgeForGpt.js'; +import * as redactor from 'src/activities/redactor.js'; import {hook} from '../../../src/hook.js'; import {decorateAdUnitsWithNativeParams} from '../../../src/native.js'; import {auctionManager} from '../../../src/auctionManager.js'; @@ -636,16 +637,103 @@ describe('S2S Adapter', function () { resetSyncedStatus(); }); - it('should set id and source.tid to auction ID', function () { - config.setConfig({ s2sConfig: CONFIG }); + describe('FPD redaction', () => { + let sandbox, ortb2Fragments, redactorMocks, s2sReq; - adapter.callBids(OUTSTREAM_VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + beforeEach(() => { + sandbox = sinon.sandbox.create(); + redactorMocks = {}; + sandbox.stub(redactor, 'redactor').callsFake((params) => { + if (!redactorMocks.hasOwnProperty(params.component)) { + redactorMocks[params.component] = { + ortb2: sinon.stub().callsFake(o => o), + bidRequest: sinon.stub().callsFake(o => o) + } + } + return redactorMocks[params.component]; + }) + ortb2Fragments = { + global: { + mock: 'value' + }, + bidder: { + appnexus: { + mock: 'A' + } + } + } + const s2sConfig = { + ...CONFIG, + }; + config.setConfig({s2sConfig}); + s2sReq = { + ...REQUEST, + s2sConfig + }; + }); - const requestBid = JSON.parse(server.requests[0].requestBody); - expect(requestBid.id).to.equal(BID_REQUESTS[0].auctionId); - expect(requestBid.source.tid).to.equal(BID_REQUESTS[0].auctionId); + afterEach(() => { + sandbox.restore(); + }) + + function callBids() { + adapter.callBids({ + ...s2sReq, + ortb2Fragments + }, BID_REQUESTS, addBidResponse, done, ajax); + } + + it('should be applied to ortb2Fragments', () => { + callBids(); + sinon.assert.calledWithMatch(redactorMocks['prebid.pbsBidAdapter'].ortb2, ortb2Fragments.global); + Object.entries(ortb2Fragments.bidder).forEach(([bidder, ortb2]) => { + sinon.assert.calledWith(redactorMocks[`bidder.${bidder}`].ortb2, ortb2); + }); + }); + + it('should be applied to ad units', () => { + callBids(); + s2sReq.ad_units.forEach(au => { + sinon.assert.calledWith(redactorMocks['prebid.pbsBidAdapter'].bidRequest, au); + au.bids.forEach((bid) => { + sinon.assert.calledWith(redactorMocks[`bidder.${bid.bidder}`].bidRequest, bid); + }) + }) + }) }); + describe('transaction IDs', () => { + let s2sReq; + beforeEach(() => { + s2sReq = { + ...REQUEST, + ortb2Fragments: {global: {source: {tid: 'mock-tid'}}}, + ad_units: REQUEST.ad_units.map(au => ({...au, ortb2Imp: {ext: {tid: 'mock-tid'}}})) + }; + BID_REQUESTS[0].bids[0].ortb2Imp = {ext: {tid: 'mock-tid'}}; + }); + + function makeRequest() { + adapter.callBids(s2sReq, BID_REQUESTS, addBidResponse, done, ajax); + return JSON.parse(server.requests[0].requestBody); + } + + it('should not be set when transmitTid is not allowed, with ext.prebid.createtids: false', () => { + config.setConfig({ s2sConfig: CONFIG, enableTIDs: false }); + const req = makeRequest(); + expect(req.source.tid).to.not.exist; + expect(req.imp[0].ext.tid).to.not.exist; + expect(req.ext.prebid.createtids).to.equal(false); + }); + + it('should be picked from FPD otherwise', () => { + config.setConfig({s2sConfig: CONFIG, enableTIDs: true}); + const req = makeRequest(); + expect(req.source.tid).to.eql('mock-tid'); + expect(req.imp[0].ext.tid).to.eql('mock-tid'); + }) + }) + it('should set tmax to s2sConfig.timeout', () => { const cfg = {...CONFIG, timeout: 123}; config.setConfig({s2sConfig: cfg}); @@ -1405,11 +1493,9 @@ describe('S2S Adapter', function () { const ortbReq = JSON.parse(requestBid.imp[0].native.request); expect(ortbReq).to.deep.equal({ ...ORTB_NATIVE_REQ, - 'context': 1, - 'plcmttype': 1, 'eventtrackers': [{ event: 1, - methods: [1] + methods: [1, 2] }], }); expect(requestBid.imp[0].native.ver).to.equal('1.2'); @@ -1643,19 +1729,17 @@ describe('S2S Adapter', function () { const requestBid = JSON.parse(server.requests[0].requestBody); - expect(requestBid.ext).to.deep.equal({ - prebid: { - auctiontimestamp: 1510852447530, - targeting: { - includebidderkeys: false, - includewinners: true - }, - channel: { - name: 'pbjs', - version: 'v$prebid.version$' - } + sinon.assert.match(requestBid.ext.prebid, { + auctiontimestamp: 1510852447530, + targeting: { + includebidderkeys: false, + includewinners: true + }, + channel: { + name: 'pbjs', + version: 'v$prebid.version$' } - }); + }) }); it('skips dynamic aliases to request when skipPbsAliasing enabled', function () { @@ -1682,17 +1766,15 @@ describe('S2S Adapter', function () { const requestBid = JSON.parse(server.requests[0].requestBody); - expect(requestBid.ext).to.deep.equal({ - prebid: { - auctiontimestamp: 1510852447530, - targeting: { - includebidderkeys: false, - includewinners: true - }, - channel: { - name: 'pbjs', - version: 'v$prebid.version$' - } + sinon.assert.match(requestBid.ext.prebid, { + auctiontimestamp: 1510852447530, + targeting: { + includebidderkeys: false, + includewinners: true + }, + channel: { + name: 'pbjs', + version: 'v$prebid.version$' } }); }); diff --git a/test/spec/modules/priceFloors_spec.js b/test/spec/modules/priceFloors_spec.js index f232631d73d..e9ce4c8ccd3 100644 --- a/test/spec/modules/priceFloors_spec.js +++ b/test/spec/modules/priceFloors_spec.js @@ -286,7 +286,7 @@ describe('the price floors module', function () { let myBidRequest = { ...basicBidRequest }; // should take adunit floormin first even if lower - utils.deepSetValue(myBidRequest, 'ortb2Imp.ext.prebid.floorMin', 2.2); + utils.deepSetValue(myBidRequest, 'ortb2Imp.ext.prebid.floors.floorMin', 2.2); expect(getFirstMatchingFloor(inputFloorData, myBidRequest, { mediaType: 'banner', size: '*' })).to.deep.equal({ floorMin: 2.2, floorRuleValue: 1.0, @@ -297,7 +297,7 @@ describe('the price floors module', function () { delete inputFloorData.matchingInputs; // should take adunit floormin if higher - utils.deepSetValue(myBidRequest, 'ortb2Imp.ext.prebid.floorMin', 3.0); + utils.deepSetValue(myBidRequest, 'ortb2Imp.ext.prebid.floors.floorMin', 3.0); expect(getFirstMatchingFloor(inputFloorData, myBidRequest, { mediaType: 'banner', size: '*' })).to.deep.equal({ floorMin: 3.0, floorRuleValue: 1.0, @@ -582,7 +582,7 @@ describe('the price floors module', function () { const validateBidRequests = (getFloorExpected, FloorDataExpected) => { exposedAdUnits.forEach(adUnit => adUnit.bids.forEach(bid => { expect(bid.hasOwnProperty('getFloor')).to.equal(getFloorExpected); - expect(bid.floorData).to.deep.equal(FloorDataExpected); + sinon.assert.match(bid.floorData, FloorDataExpected); })); }; const runStandardAuction = (adUnits = [getAdUnitMock('test_div_1')]) => { @@ -918,16 +918,8 @@ describe('the price floors module', function () { floorProvider: 'floorprovider' }); }); - it('should not overwrite previous data object if the new one is bad', function () { + it('should ignore and reset floor data when provided with invalid data', function () { handleSetFloorsConfig({...basicFloorConfig}); - handleSetFloorsConfig({ - ...basicFloorConfig, - data: undefined - }); - handleSetFloorsConfig({ - ...basicFloorConfig, - data: 5 - }); handleSetFloorsConfig({ ...basicFloorConfig, data: { @@ -937,17 +929,7 @@ describe('the price floors module', function () { } }); runStandardAuction(); - validateBidRequests(true, { - skipped: false, - floorMin: undefined, - modelVersion: 'basic model', - modelWeight: 10, - modelTimestamp: 1606772895, - location: 'setConfig', - skipRate: 0, - fetchStatus: undefined, - floorProvider: undefined - }); + validateBidRequests(false, sinon.match({location: 'noData', skipped: true})); }); it('should dynamically add new schema fileds and functions if added via setConfig', function () { let deviceSpoof; @@ -1835,7 +1817,7 @@ describe('the price floors module', function () { transactionId: 'au', }; beforeEach(function () { - returnedBidResponse = {}; + returnedBidResponse = null; reject = sinon.stub().returns({status: 'rejected'}); indexStub = sinon.stub(auctionManager, 'index'); indexStub.get(() => stubAuctionIndex({adUnits: [adUnit]})); @@ -1867,7 +1849,7 @@ describe('the price floors module', function () { _floorDataForAuction[AUCTION_ID].data.values = { 'banner': 1.0 }; runBidResponse(); expect(reject.calledOnce).to.be.true; - expect(returnedBidResponse.status).to.equal('rejected'); + expect(returnedBidResponse).to.not.exist; }); it('if it finds a rule and does not floor should update the bid accordingly', function () { _floorDataForAuction[AUCTION_ID] = utils.deepClone(basicFloorConfig); diff --git a/test/spec/modules/pubCommonId_spec.js b/test/spec/modules/pubCommonId_spec.js deleted file mode 100644 index 7c539014cc5..00000000000 --- a/test/spec/modules/pubCommonId_spec.js +++ /dev/null @@ -1,353 +0,0 @@ -import { - requestBidHook, - getCookie, - setCookie, - setConfig, - isPubcidEnabled, - getExpInterval, - initPubcid, - setStorageItem, - getStorageItem, - removeStorageItem, - getPubcidConfig } from 'modules/pubCommonId.js'; -import { getAdUnits } from 'test/fixtures/fixtures.js'; -import * as auctionModule from 'src/auction.js'; -import { registerBidder } from 'src/adapters/bidderFactory.js'; -import * as utils from 'src/utils.js'; - -let events = require('src/events'); -let constants = require('src/constants.json'); - -var assert = require('chai').assert; -var expect = require('chai').expect; - -const ID_NAME = '_pubcid'; -const EXP = '_exp'; -const TIMEOUT = 2000; - -const uuidPattern = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89a-f][0-9a-f]{3}-[0-9a-f]{12}$/; - -function cleanUp() { - window.document.cookie = ID_NAME + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; - localStorage.removeItem(ID_NAME); - localStorage.removeItem(ID_NAME + EXP); -} - -describe('Publisher Common ID', function () { - afterEach(function () { - $$PREBID_GLOBAL$$.requestBids.removeAll(); - }); - describe('Decorate adUnits', function () { - beforeEach(function() { - cleanUp(); - }); - afterEach(function() { - cleanUp(); - }); - - it('Check same cookie', function () { - let adUnits1 = getAdUnits(); - let adUnits2 = getAdUnits(); - let innerAdUnits1; - let innerAdUnits2; - let pubcid; - - expect(getCookie(ID_NAME)).to.be.null; // there should be no cookie initially - expect(localStorage.getItem(ID_NAME)).to.be.null; // there should be no local storage item either - - requestBidHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); - pubcid = localStorage.getItem(ID_NAME); // local storage item is created after requestbidHook - - innerAdUnits1.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('crumbs.pubcid'); - expect(bid.crumbs.pubcid).to.equal(pubcid); - }); - }); - - // verify cookie is null - expect(getCookie(ID_NAME)).to.be.null; - - // verify same pubcid is preserved - requestBidHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); - assert.deepEqual(innerAdUnits1, innerAdUnits2); - }); - - it('Check different cookies', function () { - let adUnits1 = getAdUnits(); - let adUnits2 = getAdUnits(); - let innerAdUnits1; - let innerAdUnits2; - let pubcid1; - let pubcid2; - - requestBidHook((config) => { innerAdUnits1 = config.adUnits }, {adUnits: adUnits1}); - pubcid1 = localStorage.getItem(ID_NAME); // get first pubcid - removeStorageItem(ID_NAME); // remove storage - - expect(pubcid1).to.not.be.null; - - innerAdUnits1.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('crumbs.pubcid'); - expect(bid.crumbs.pubcid).to.equal(pubcid1); - }); - }); - - requestBidHook((config) => { innerAdUnits2 = config.adUnits }, {adUnits: adUnits2}); - pubcid2 = localStorage.getItem(ID_NAME); // get second pubcid - - innerAdUnits2.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('crumbs.pubcid'); - expect(bid.crumbs.pubcid).to.equal(pubcid2); - }); - }); - - expect(pubcid2).to.not.be.null; - expect(pubcid1).to.not.equal(pubcid2); - }); - - it('Check new cookie', function () { - let adUnits = getAdUnits(); - let innerAdUnits; - let pubcid = utils.generateUUID(); - - setCookie(ID_NAME, pubcid, 600); - requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); - innerAdUnits.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('crumbs.pubcid'); - expect(bid.crumbs.pubcid).to.equal(pubcid); - }); - }); - }); - - it('Replicate cookie to storage', function() { - let adUnits = getAdUnits(); - let innerAdUnits; - let pubcid = utils.generateUUID(); - - setCookie(ID_NAME, pubcid, 600); - requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); - - expect(getStorageItem(ID_NAME)).to.equal(pubcid); - }); - - it('Does not replicate storage to cookie', function() { - let adUnits = getAdUnits(); - let innerAdUnits; - let pubcid = utils.generateUUID(); - - setStorageItem(ID_NAME, pubcid, 600); - requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); - - expect(getCookie(ID_NAME)).to.be.null; - }); - - it('Cookie only', function() { - setConfig({type: 'cookie'}); - let adUnits = getAdUnits(); - let innerAdUnits; - - requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); - - expect(getCookie(ID_NAME)).to.match(uuidPattern); - expect(getStorageItem(ID_NAME)).to.be.null; - }); - - it('Storage only', function() { - setConfig({type: 'html5'}); - let adUnits = getAdUnits(); - let innerAdUnits; - - requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); - - expect(getCookie(ID_NAME)).to.be.null; - expect(getStorageItem(ID_NAME)).to.match(uuidPattern); - }); - - it('Bad id recovery', function() { - let adUnits = getAdUnits(); - let innerAdUnits; - - setStorageItem(ID_NAME, 'undefined', 600); - requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); - - expect(getStorageItem(ID_NAME)).to.match(uuidPattern); - }); - }); - - describe('Configuration', function () { - beforeEach(() => { - setConfig(); - cleanUp(); - }); - afterEach(() => { - setConfig(); - cleanUp(); - }); - - it('empty config', function () { - // this should work as usual - setConfig({}); - let adUnits = getAdUnits(); - let innerAdUnits; - requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); - let pubcid = localStorage.getItem(ID_NAME); - innerAdUnits.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('crumbs.pubcid'); - expect(bid.crumbs.pubcid).to.equal(pubcid); - }); - }); - }); - - it('disable', function () { - setConfig({enable: false}); - let adUnits = getAdUnits(); - let unmodified = getAdUnits(); - let innerAdUnits; - expect(isPubcidEnabled()).to.be.false; - requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); - expect(getCookie(ID_NAME)).to.be.null; - assert.deepEqual(innerAdUnits, unmodified); - setConfig({enable: true}); // reset - requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); - innerAdUnits.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('crumbs.pubcid'); - }); - }); - }); - - it('change expiration time', function () { - setConfig({expInterval: 100}); - expect(getExpInterval()).to.equal(100); - let adUnits = getAdUnits(); - let innerAdUnits; - requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); - innerAdUnits.every((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('crumbs.pubcid'); - }); - }); - }); - }); - - describe('Invoking requestBid', function () { - let createAuctionStub; - let adUnits; - let adUnitCodes; - let capturedReqs; - let sampleSpec = { - code: 'sampleBidder', - isBidRequestValid: () => {}, - buildRequest: (reqs) => {}, - interpretResponse: () => {}, - getUserSyncs: () => {} - }; - - beforeEach(function () { - adUnits = [{ - code: 'adUnit-code', - mediaTypes: { - banner: {}, - native: {}, - }, - sizes: [[300, 200], [300, 600]], - bids: [ - {bidder: 'sampleBidder', params: {placementId: 'banner-only-bidder'}} - ] - }]; - adUnitCodes = ['adUnit-code']; - let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: TIMEOUT}); - createAuctionStub = sinon.stub(auctionModule, 'newAuction'); - createAuctionStub.returns(auction); - initPubcid(); - registerBidder(sampleSpec); - }); - - afterEach(function () { - auctionModule.newAuction.restore(); - }); - - it('test hook', function() { - $$PREBID_GLOBAL$$.requestBids({adUnits}); - adUnits.forEach((unit) => { - unit.bids.forEach((bid) => { - expect(bid).to.have.deep.nested.property('crumbs.pubcid'); - }); - }); - }); - }); - - describe('Storage item functions', () => { - beforeEach(() => { cleanUp(); }); - afterEach(() => { cleanUp(); }); - - it('Test set', () => { - const key = ID_NAME; - const val = 'test-set-value'; - // Set item in localStorage - const now = Date.now(); - setStorageItem(key, val, 100); - // Check both item and expiry time are stored - const expVal = localStorage.getItem(key + EXP); - const storedVal = localStorage.getItem(key); - // Verify expiry - expect(expVal).to.not.be.null; - const expDate = new Date(expVal); - expect((expDate.getTime() - now) / 1000).to.be.closeTo(100 * 60, 5); - // Verify value - expect(storedVal).to.equal(val); - }); - - it('Test get and remove', () => { - const key = ID_NAME; - const val = 'test-get-remove'; - setStorageItem(key, val, 10); - expect(getStorageItem(key)).to.equal(val); - removeStorageItem(key); - expect(getStorageItem(key)).to.be.null; - }); - - it('Test expiry', () => { - const key = ID_NAME; - const val = 'test-expiry'; - setStorageItem(key, val, -1); - expect(localStorage.getItem(key)).to.equal(val); - expect(getStorageItem(key)).to.be.null; - expect(localStorage.getItem(key)).to.be.null; - }); - }); - - describe('event callback', () => { - beforeEach(() => { - setConfig(); - cleanUp(); - sinon.stub(events, 'getEvents').returns([]); - sinon.stub(utils, 'triggerPixel'); - }); - afterEach(() => { - setConfig(); - cleanUp(); - events.getEvents.restore(); - utils.triggerPixel.restore(); - }); - it('auction end trigger', () => { - setConfig({ - pixelUrl: '/any/url' - }); - - let adUnits = getAdUnits(); - let innerAdUnits; - requestBidHook((config) => { innerAdUnits = config.adUnits }, {adUnits}); - - expect(utils.triggerPixel.called).to.be.false; - events.emit(constants.EVENTS.AUCTION_END, {}); - expect(utils.triggerPixel.called).to.be.true; - expect(utils.triggerPixel.getCall(0).args[0]).to.include('/any/url'); - }); - }); -}); diff --git a/test/spec/modules/pubgeniusBidAdapter_spec.js b/test/spec/modules/pubgeniusBidAdapter_spec.js index 1d1b0e65ec8..86c8794dc4c 100644 --- a/test/spec/modules/pubgeniusBidAdapter_spec.js +++ b/test/spec/modules/pubgeniusBidAdapter_spec.js @@ -5,6 +5,7 @@ import { config } from 'src/config.js'; import { VIDEO } from 'src/mediaTypes.js'; import { deepClone, parseQueryStringParameters } from 'src/utils.js'; import { server } from 'test/mocks/xhr.js'; +import * as utils from 'src/utils.js'; const { code, @@ -175,7 +176,7 @@ describe('pubGENIUS adapter', () => { method: 'POST', url: 'https://auction.adpearl.io/prebid/auction', data: { - id: 'fake-auction-id', + id: 'fakebidderrequestid', imp: [ { id: 'fakebidid', diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index beb8a248d13..12805c7786d 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -79,7 +79,11 @@ describe('PubMatic adapter', function () { bidId: '23acc48ad47af5', requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', bidderRequestId: '1c56ad30b9b8ca8', - transactionId: '92489f71-1bf2-49a0-adf9-000cea934729', + ortb2Imp: { + ext: { + tid: '92489f71-1bf2-49a0-adf9-000cea934729', + } + }, schain: schainConfig } ]; @@ -1125,7 +1129,12 @@ describe('PubMatic adapter', function () { it('Request params check', function () { let request = spec.buildRequests(bidRequests, { - auctionId: 'new-auction-id' + auctionId: 'new-auction-id', + ortb2: { + source: { + tid: 'source-tid' + } + } }); let data = JSON.parse(request.data); expect(data.at).to.equal(1); // auction type @@ -1135,13 +1144,13 @@ describe('PubMatic adapter', function () { expect(data.site.publisher.id).to.equal(bidRequests[0].params.publisherId); // publisher Id expect(data.user.yob).to.equal(parseInt(bidRequests[0].params.yob)); // YOB expect(data.user.gender).to.equal(bidRequests[0].params.gender); // Gender - expect(data.device.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude - expect(data.device.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude - expect(data.user.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude - expect(data.user.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.device.geo.lat).to.not.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.device.geo.lon).to.not.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.user.geo.lat).to.not.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.user.geo.lon).to.not.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude expect(data.ext.wrapper.wv).to.equal($$REPO_AND_VERSION$$); // Wrapper Version - expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].transactionId); // Prebid TransactionId - expect(data.source.tid).to.equal(bidRequests[0].transactionId); // Prebid TransactionId + expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].ortb2Imp.ext.tid); // Prebid TransactionId + expect(data.source.tid).to.equal('source-tid'); // Prebid TransactionId expect(data.ext.wrapper.wiid).to.equal(bidRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID expect(data.ext.wrapper.profile).to.equal(parseInt(bidRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID expect(data.ext.wrapper.version).to.equal(parseInt(bidRequests[0].params.verId)); // OpenWrap: Wrapper Profile Version ID @@ -1388,12 +1397,12 @@ describe('PubMatic adapter', function () { expect(data.site.publisher.id).to.equal(bidRequests[0].params.publisherId); // publisher Id expect(data.user.yob).to.equal(parseInt(bidRequests[0].params.yob)); // YOB expect(data.user.gender).to.equal(bidRequests[0].params.gender); // Gender - expect(data.device.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude - expect(data.device.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude - expect(data.user.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude - expect(data.user.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.device.geo.lat).to.not.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.device.geo.lon).to.not.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.user.geo.lat).to.not.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.user.geo.lon).to.not.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude expect(data.ext.wrapper.wv).to.equal($$REPO_AND_VERSION$$); // Wrapper Version - expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].transactionId); // Prebid TransactionId + expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].ortb2Imp.ext.tid); // Prebid TransactionId expect(data.ext.wrapper.wiid).to.equal(bidRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID expect(data.ext.wrapper.profile).to.equal(parseInt(bidRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID expect(data.ext.wrapper.version).to.equal(parseInt(bidRequests[0].params.verId)); // OpenWrap: Wrapper Profile Version ID @@ -1599,12 +1608,12 @@ describe('PubMatic adapter', function () { expect(data.site.publisher.id).to.equal(bidRequests[0].params.publisherId); // publisher Id expect(data.user.yob).to.equal(parseInt(bidRequests[0].params.yob)); // YOB expect(data.user.gender).to.equal(bidRequests[0].params.gender); // Gender - expect(data.device.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude - expect(data.device.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude - expect(data.user.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude - expect(data.user.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.device.geo.lat).to.not.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.device.geo.lon).to.not.equal(parseFloat(bidRequests[0].params.lon)); // Longitude + expect(data.user.geo.lat).to.not.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.user.geo.lon).to.not.equal(parseFloat(bidRequests[0].params.lon)); // Longitude expect(data.ext.wrapper.wv).to.equal($$REPO_AND_VERSION$$); // Wrapper Version - expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].transactionId); // Prebid TransactionId + expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].ortb2Imp.ext.tid); // Prebid TransactionId expect(data.ext.wrapper.wiid).to.equal('new-auction-id'); // OpenWrap: Wrapper Impression ID expect(data.ext.wrapper.profile).to.equal(parseInt(bidRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID expect(data.ext.wrapper.version).to.equal(parseInt(bidRequests[0].params.verId)); // OpenWrap: Wrapper Profile Version ID @@ -1635,12 +1644,12 @@ describe('PubMatic adapter', function () { expect(data.site.publisher.id).to.equal(bidRequests[0].params.publisherId); // publisher Id expect(data.user.yob).to.equal(parseInt(bidRequests[0].params.yob)); // YOB expect(data.user.gender).to.equal(bidRequests[0].params.gender); // Gender - expect(data.device.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude - expect(data.device.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude - expect(data.user.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude - expect(data.user.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.device.geo.lat).to.not.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.device.geo.lon).to.not.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.user.geo.lat).to.not.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.user.geo.lon).to.not.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude expect(data.ext.wrapper.wv).to.equal($$REPO_AND_VERSION$$); // Wrapper Version - expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].transactionId); // Prebid TransactionId + expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].ortb2Imp.ext.tid); // Prebid TransactionId expect(data.ext.wrapper.wiid).to.equal(bidRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID expect(data.ext.wrapper.profile).to.equal(parseInt(bidRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID expect(data.ext.wrapper.version).to.equal(parseInt(bidRequests[0].params.verId)); // OpenWrap: Wrapper Profile Version ID @@ -1667,12 +1676,12 @@ describe('PubMatic adapter', function () { expect(data.site.publisher.id).to.equal(bidRequests[0].params.publisherId); // publisher Id expect(data.user.yob).to.equal(parseInt(bidRequests[0].params.yob)); // YOB expect(data.user.gender).to.equal(bidRequests[0].params.gender); // Gender - expect(data.device.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude - expect(data.device.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude - expect(data.user.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude - expect(data.user.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.device.geo.lat).to.not.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.device.geo.lon).to.not.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.user.geo.lat).to.not.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.user.geo.lon).to.not.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude expect(data.ext.wrapper.wv).to.equal($$REPO_AND_VERSION$$); // Wrapper Version - expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].transactionId); // Prebid TransactionId + expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].ortb2Imp.ext.tid); // Prebid TransactionId expect(data.ext.wrapper.wiid).to.equal(bidRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID expect(data.ext.wrapper.profile).to.equal(parseInt(bidRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID expect(data.ext.wrapper.version).to.equal(parseInt(bidRequests[0].params.verId)); // OpenWrap: Wrapper Profile Version ID @@ -2697,10 +2706,10 @@ describe('PubMatic adapter', function () { expect(data.site.publisher.id).to.equal(multipleMediaRequests[0].params.publisherId); // publisher Id expect(data.user.yob).to.equal(parseInt(multipleMediaRequests[0].params.yob)); // YOB expect(data.user.gender).to.equal(multipleMediaRequests[0].params.gender); // Gender - expect(data.device.geo.lat).to.equal(parseFloat(multipleMediaRequests[0].params.lat)); // Latitude - expect(data.device.geo.lon).to.equal(parseFloat(multipleMediaRequests[0].params.lon)); // Lognitude - expect(data.user.geo.lat).to.equal(parseFloat(multipleMediaRequests[0].params.lat)); // Latitude - expect(data.user.geo.lon).to.equal(parseFloat(multipleMediaRequests[0].params.lon)); // Lognitude + expect(data.device.geo.lat).to.not.equal(parseFloat(multipleMediaRequests[0].params.lat)); // Latitude + expect(data.device.geo.lon).to.not.equal(parseFloat(multipleMediaRequests[0].params.lon)); // Lognitude + expect(data.user.geo.lat).to.not.equal(parseFloat(multipleMediaRequests[0].params.lat)); // Latitude + expect(data.user.geo.lon).to.not.equal(parseFloat(multipleMediaRequests[0].params.lon)); // Lognitude expect(data.ext.wrapper.wv).to.equal($$REPO_AND_VERSION$$); // Wrapper Version expect(data.ext.wrapper.transactionId).to.equal(multipleMediaRequests[0].transactionId); // Prebid TransactionId expect(data.ext.wrapper.wiid).to.equal(multipleMediaRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID diff --git a/test/spec/modules/pubwiseBidAdapter_spec.js b/test/spec/modules/pubwiseBidAdapter_spec.js index 780cc8b8fdb..49e36c05d1e 100644 --- a/test/spec/modules/pubwiseBidAdapter_spec.js +++ b/test/spec/modules/pubwiseBidAdapter_spec.js @@ -101,6 +101,7 @@ const sampleValidBannerBidRequest = { }, ortb2Imp: { ext: { + tid: '2001a8b2-3bcf-417d-b64f-92641dae21e0', data: { adserver: { name: 'gam', @@ -125,7 +126,6 @@ const sampleValidBannerBidRequest = { } }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '2001a8b2-3bcf-417d-b64f-92641dae21e0', 'sizes': [ [ 300, @@ -179,6 +179,7 @@ const sampleValidBidRequests = [ }, ortb2Imp: { ext: { + tid: '2c8cd034-f068-4419-8c30-f07292c0d17b', data: { adserver: { name: 'gam', @@ -213,7 +214,6 @@ const sampleValidBidRequests = [ } }, 'adUnitCode': 'div-gpt-ad-1460505748561-1', - 'transactionId': '2c8cd034-f068-4419-8c30-f07292c0d17b', 'sizes': [], 'bidId': '30ab7516a51a7c', 'bidderRequestId': '18a45bff5ff705', @@ -252,6 +252,7 @@ const sampleBidderBannerRequest = { }, ortb2Imp: { ext: { + tid: '2001a8b2-3bcf-417d-b64f-92641dae21e0', data: { adserver: { name: 'gam', @@ -272,7 +273,6 @@ const sampleBidderBannerRequest = { } }, 'adUnitCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': '2001a8b2-3bcf-417d-b64f-92641dae21e0', 'sizes': [ [ 300, @@ -299,7 +299,11 @@ const sampleBidderBannerRequest = { const sampleBidderRequest = { 'bidderCode': 'pubwise', - 'auctionId': '9f20663c-4629-4b5c-bff6-ff3aa8319358', + ortb2: { + source: { + tid: '9f20663c-4629-4b5c-bff6-ff3aa8319358', + } + }, 'bidderRequestId': '18a45bff5ff705', 'bids': [ sampleBidderBannerRequest, @@ -564,8 +568,8 @@ describe('PubWiseAdapter', function () { it('should handle complex bidRequest', function() { let request = spec.buildRequests(sampleValidBidRequests, sampleBidderRequest); expect(request.bidderRequest).to.equal(sampleBidderRequest, "Bid Request Doesn't Match Sample"); - expect(request.data.source.tid).to.equal(sampleBidderRequest.auctionId, 'AuctionId -> source.tid Mismatch'); - expect(request.data.imp[0].ext.tid).to.equal(sampleBidderRequest.bids[0].transactionId, 'TransactionId -> ext.tid Mismatch'); + expect(request.data.source.tid).to.equal(sampleBidderRequest.ortb2.source.tid, 'source.tid -> source.tid Mismatch'); + expect(request.data.imp[0].ext.tid).to.equal(sampleBidderRequest.bids[0].ortb2Imp.ext.tid, 'ext.tid -> ext.tid Mismatch'); }); it('must conform to API for buildRequests', function() { let request = spec.buildRequests(sampleValidBidRequests); diff --git a/test/spec/modules/relaidoBidAdapter_spec.js b/test/spec/modules/relaidoBidAdapter_spec.js index 0f2f9abd583..36d03c01138 100644 --- a/test/spec/modules/relaidoBidAdapter_spec.js +++ b/test/spec/modules/relaidoBidAdapter_spec.js @@ -39,7 +39,11 @@ describe('RelaidoAdapter', function () { bidId: '2ed93003f7bb99', bidderRequestId: '1c50443387a1f2', auctionId: '413ed000-8c7a-4ba1-a1fa-9732e006f8c3', - transactionId: '5c2d064c-7b76-42e8-a383-983603afdc45', + ortb2Imp: { + ext: { + tid: '5c2d064c-7b76-42e8-a383-983603afdc45', + } + }, bidRequestsCount: 1, bidderRequestsCount: 1, bidderWinsCount: 0 @@ -243,7 +247,7 @@ describe('RelaidoAdapter', function () { expect(request.bidder_request_id).to.equal(bidRequest.bidderRequestId); expect(data.bid_requests_count).to.equal(bidRequest.bidRequestsCount); expect(request.bid_id).to.equal(bidRequest.bidId); - expect(request.transaction_id).to.equal(bidRequest.transactionId); + expect(request.transaction_id).to.equal(bidRequest.ortb2Imp.ext.tid); expect(request.media_type).to.equal('video'); expect(data.uuid).to.equal(relaido_uuid); expect(data.pv).to.equal('$prebid.version$'); diff --git a/test/spec/modules/revcontentBidAdapter_spec.js b/test/spec/modules/revcontentBidAdapter_spec.js index e6ef4adec87..ca4e7bc4e4b 100644 --- a/test/spec/modules/revcontentBidAdapter_spec.js +++ b/test/spec/modules/revcontentBidAdapter_spec.js @@ -266,8 +266,6 @@ describe('revcontent adapter', function () { it('should set correct native params', function () { const result = spec.interpretResponse(serverResponse, bidRequest)[0]; - assert.equal(result.bidder, 'revcontent'); - assert.equal(result.bidderCode, 'revcontent'); assert.equal(result.mediaType, 'native'); assert.equal(result.requestId, '294a7f446202848'); assert.equal(result.cpm, '0.1'); @@ -279,8 +277,6 @@ describe('revcontent adapter', function () { bidRequest.bid[0].params.size.height = 90; const result = spec.interpretResponse(serverResponse, bidRequest)[0]; - assert.equal(result.bidder, 'revcontent'); - assert.equal(result.bidderCode, 'revcontent'); assert.equal(result.mediaType, 'native'); assert.equal(result.requestId, '294a7f446202848'); assert.equal(result.cpm, '0.1'); @@ -292,8 +288,6 @@ describe('revcontent adapter', function () { bidRequest.bid[0].params.size.height = 600; const result = spec.interpretResponse(serverResponse, bidRequest)[0]; - assert.equal(result.bidder, 'revcontent'); - assert.equal(result.bidderCode, 'revcontent'); assert.equal(result.mediaType, 'native'); assert.equal(result.requestId, '294a7f446202848'); assert.equal(result.cpm, '0.1'); @@ -304,8 +298,6 @@ describe('revcontent adapter', function () { bidRequest.bid[0].params.template = '

{title}

SEE MORE
'; const result = spec.interpretResponse(serverResponse, bidRequest)[0]; - assert.equal(result.bidder, 'revcontent'); - assert.equal(result.bidderCode, 'revcontent'); assert.equal(result.mediaType, 'native'); assert.equal(result.requestId, '294a7f446202848'); assert.equal(result.cpm, '0.1'); @@ -317,8 +309,6 @@ describe('revcontent adapter', function () { bidRequest.bid[0].params.size.height = 200; const result = spec.interpretResponse(serverResponse, bidRequest)[0]; - assert.equal(result.bidder, 'revcontent'); - assert.equal(result.bidderCode, 'revcontent'); assert.equal(result.mediaType, 'native'); assert.equal(result.requestId, '294a7f446202848'); assert.equal(result.cpm, '0.1'); diff --git a/test/spec/modules/richaudienceBidAdapter_spec.js b/test/spec/modules/richaudienceBidAdapter_spec.js index 6aed730f5d4..ea45ff7e0b0 100644 --- a/test/spec/modules/richaudienceBidAdapter_spec.js +++ b/test/spec/modules/richaudienceBidAdapter_spec.js @@ -25,7 +25,11 @@ describe('Richaudience adapter tests', function () { auctionId: '0cb3144c-d084-4686-b0d6-f5dbe917c563', bidRequestsCount: 1, bidderRequestId: '1858b7382993ca', - transactionId: '29df2112-348b-4961-8863-1b33684d95e6', + ortb2Imp: { + ext: { + tid: '29df2112-348b-4961-8863-1b33684d95e6', + } + }, user: {} }]; diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js deleted file mode 100644 index 05b6cc6b6f4..00000000000 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ /dev/null @@ -1,2540 +0,0 @@ -import rubiconAnalyticsAdapter, { - SEND_TIMEOUT, - parseBidResponse, - getHostNameFromReferer, - storage, - rubiConf, - resetRubiConf -} from 'modules/rubiconAnalyticsAdapter.js'; -import CONSTANTS from 'src/constants.json'; -import { config } from 'src/config.js'; -import { server } from 'test/mocks/xhr.js'; -import * as mockGpt from '../integration/faker/googletag.js'; -import { - setConfig, - addBidResponseHook, -} from 'modules/currency.js'; - -let Ajv = require('ajv'); -let schema = require('./rubiconAnalyticsSchema.json'); -let ajv = new Ajv({ - allErrors: true -}); - -let validator = ajv.compile(schema); - -function validate(message) { - validator(message); - expect(validator.errors).to.deep.equal(null); -} - -let events = require('src/events.js'); -let utils = require('src/utils.js'); - -const { - EVENTS: { - AUCTION_INIT, - AUCTION_END, - BID_REQUESTED, - BID_RESPONSE, - BIDDER_DONE, - BID_WON, - BID_TIMEOUT, - SET_TARGETING, - BILLABLE_EVENT - } -} = CONSTANTS; - -const BID = { - 'bidder': 'rubicon', - 'width': 640, - 'height': 480, - 'mediaType': 'video', - 'statusMessage': 'Bid available', - 'bidId': '2ecff0db240757', - 'adId': 'fake_ad_id', - 'source': 'client', - 'requestId': '2ecff0db240757', - 'currency': 'USD', - 'creativeId': '3571560', - 'cpm': 1.22752, - 'ttl': 300, - 'netRevenue': false, - 'ad': '', - 'rubiconTargeting': { - 'rpfl_elemid': '/19968336/header-bid-tag-0', - 'rpfl_14062': '2_tier0100' - }, - 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', - 'responseTimestamp': 1519149629415, - 'requestTimestamp': 1519149628471, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'timeToRespond': 944, - 'pbLg': '1.00', - 'pbMg': '1.20', - 'pbHg': '1.22', - 'pbAg': '1.20', - 'pbDg': '1.22', - 'pbCg': '', - 'size': '640x480', - 'adserverTargeting': { - 'hb_bidder': 'rubicon', - 'hb_adid': '2ecff0db240757', - 'hb_pb': 1.20, - 'hb_size': '640x480', - 'hb_source': 'client' - }, - getStatusCode() { - return 1; - } -}; - -const BID2 = Object.assign({}, BID, { - adUnitCode: '/19968336/header-bid-tag1', - bidId: '3bd4ebb1c900e2', - adId: 'fake_ad_id', - requestId: '3bd4ebb1c900e2', - width: 728, - height: 90, - mediaType: 'banner', - cpm: 1.52, - source: 'server', - seatBidId: 'aaaa-bbbb-cccc-dddd', - rubiconTargeting: { - 'rpfl_elemid': '/19968336/header-bid-tag1', - 'rpfl_14062': '2_tier0100' - }, - adserverTargeting: { - 'hb_bidder': 'rubicon', - 'hb_adid': '3bd4ebb1c900e2', - 'hb_pb': '1.500', - 'hb_size': '728x90', - 'hb_source': 'server' - } -}); - -const BID3 = Object.assign({}, BID, { - adUnitCode: '/19968336/siderail-tag1', - bidId: '5fg6hyy4r879f0', - adId: 'fake_ad_id', - requestId: '5fg6hyy4r879f0', - width: 300, - height: 250, - mediaType: 'banner', - cpm: 2.01, - source: 'server', - seatBidId: 'aaaa-bbbb-cccc-dddd', - rubiconTargeting: { - 'rpfl_elemid': '/19968336/siderail-tag1', - 'rpfl_14062': '15_tier0200' - }, - adserverTargeting: { - 'hb_bidder': 'rubicon', - 'hb_adid': '5fg6hyy4r879f0', - 'hb_pb': '2.00', - 'hb_size': '300x250', - 'hb_source': 'server' - } -}); - -const BID4 = Object.assign({}, BID, { - adUnitCode: '/19968336/header-bid-tag1', - bidId: '3bd4ebb1c900e2', - adId: 'fake_ad_id', - requestId: '3bd4ebb1c900e2', - width: 728, - height: 90, - mediaType: 'banner', - cpm: 1.52, - source: 'server', - pbsBidId: 'zzzz-yyyy-xxxx-wwww', - seatBidId: 'aaaa-bbbb-cccc-dddd', - rubiconTargeting: { - 'rpfl_elemid': '/19968336/header-bid-tag1', - 'rpfl_14062': '2_tier0100' - }, - adserverTargeting: { - 'hb_bidder': 'rubicon', - 'hb_adid': '3bd4ebb1c900e2', - 'hb_pb': '1.500', - 'hb_size': '728x90', - 'hb_source': 'server' - } -}); - -const floorMinRequest = { - 'bidder': 'rubicon', - 'params': { - 'accountId': '14062', - 'siteId': '70608', - 'zoneId': '335918', - 'userId': '12346', - 'keywords': ['a', 'b', 'c'], - 'inventory': { 'rating': '4-star', 'prodtype': 'tech' }, - 'visitor': { 'ucat': 'new', 'lastsearch': 'iphone' }, - 'position': 'atf' - }, - 'mediaTypes': { - 'banner': { - 'sizes': [[300, 250]] - } - }, - 'adUnitCode': '/19968336/siderail-tag1', - 'transactionId': 'c435626g-9e3f-401a-bee1-d56aec29a1d4', - 'sizes': [[300, 250]], - 'bidId': '5fg6hyy4r879f0', - 'bidderRequestId': '1be65d7958826a', - 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa' -}; - -const MOCK = { - SET_TARGETING: { - [BID.adUnitCode]: BID.adserverTargeting, - [BID2.adUnitCode]: BID2.adserverTargeting, - [BID3.adUnitCode]: BID3.adserverTargeting - }, - AUCTION_INIT: { - 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', - 'timestamp': 1519767010567, - 'auctionStatus': 'inProgress', - 'adUnits': [{ - 'code': '/19968336/header-bid-tag1', - 'sizes': [[640, 480]], - 'bids': [{ - 'bidder': 'rubicon', - 'params': { - 'accountId': 1001, 'siteId': 113932, 'zoneId': 535512 - } - }], - 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014' - } - ], - 'adUnitCodes': ['/19968336/header-bid-tag1'], - 'bidderRequests': [{ - 'bidderCode': 'rubicon', - 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', - 'bidderRequestId': '1be65d7958826a', - 'bids': [{ - 'bidder': 'rubicon', - 'params': { - 'accountId': 1001, 'siteId': 113932, 'zoneId': 535512 - }, - 'mediaTypes': { - 'banner': { - 'sizes': [[640, 480]] - } - }, - 'adUnitCode': '/19968336/header-bid-tag1', - 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014', - 'sizes': [[640, 480]], - 'bidId': '2ecff0db240757', - 'bidderRequestId': '1be65d7958826a', - 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', - 'src': 'client', - 'bidRequestsCount': 1 - } - ], - 'timeout': 3000, - 'refererInfo': { - 'page': 'http://www.test.com/page.html', 'reachedTop': true, 'numIframes': 0, 'stack': ['http://www.test.com/page.html'] - } - } - ], - 'bidsReceived': [], - 'winningBids': [], - 'timeout': 3000, - 'config': { - 'accountId': 1001, 'endpoint': '//localhost:9999/event' - } - }, - BID_REQUESTED: { - 'bidderCode': 'rubicon', - 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', - 'bidderRequestId': '1be65d7958826a', - 'bids': [ - { - 'bidder': 'rubicon', - 'params': { - 'accountId': '1001', - 'siteId': '70608', - 'zoneId': '335918', - 'userId': '12346', - 'keywords': ['a', 'b', 'c'], - 'inventory': 'test', - 'visitor': { 'ucat': 'new', 'lastsearch': 'iphone' }, - 'position': 'btf', - 'video': { - 'language': 'en', - 'playerHeight': 480, - 'playerWidth': 640, - 'size_id': 203, - 'skip': 1, - 'skipdelay': 15, - 'aeParams': { - 'p_aso.video.ext.skip': '1', - 'p_aso.video.ext.skipdelay': '15' - } - } - }, - 'mediaTypes': { - 'video': { - 'context': 'instream', - 'playerSize': [640, 480] - } - }, - 'adUnitCode': '/19968336/header-bid-tag-0', - 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014', - 'sizes': [[640, 480]], - 'bidId': '2ecff0db240757', - 'bidderRequestId': '1be65d7958826a', - 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', - 'src': 'client' - }, - { - 'bidder': 'rubicon', - 'params': { - 'accountId': '14062', - 'siteId': '70608', - 'zoneId': '335918', - 'userId': '12346', - 'keywords': ['a', 'b', 'c'], - 'inventory': { 'rating': '4-star', 'prodtype': 'tech' }, - 'visitor': { 'ucat': 'new', 'lastsearch': 'iphone' }, - 'position': 'atf' - }, - 'mediaTypes': { - 'banner': { - 'sizes': [[1000, 300], [970, 250], [728, 90]] - } - }, - 'adUnitCode': '/19968336/header-bid-tag1', - 'transactionId': 'c116413c-9e3f-401a-bee1-d56aec29a1d4', - 'sizes': [[1000, 300], [970, 250], [728, 90]], - 'bidId': '3bd4ebb1c900e2', - 'bidderRequestId': '1be65d7958826a', - 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', - 'src': 's2s' - } - ], - 'auctionStart': 1519149536560, - 'timeout': 5000, - 'start': 1519149562216, - 'refererInfo': { - 'page': 'http://www.test.com/page.html', 'reachedTop': true, 'numIframes': 0, 'stack': ['http://www.test.com/page.html'] - } - }, - BID_RESPONSE: [ - BID, - BID2, - BID3 - ], - AUCTION_END: { - 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa' - }, - BID_WON: [ - Object.assign({}, BID, { - 'status': 'rendered' - }), - Object.assign({}, BID2, { - 'status': 'rendered' - }), - Object.assign({}, BID3, { - 'status': 'rendered' - }) - ], - BIDDER_DONE: { - 'bidderCode': 'rubicon', - 'serverResponseTimeMs': 42, - 'bids': [ - BID, - Object.assign({}, BID2, { - 'serverResponseTimeMs': 42, - }), - Object.assign({}, BID3, { - 'serverResponseTimeMs': 55, - }) - ] - }, - BID_TIMEOUT: [ - { - 'bidId': '2ecff0db240757', - 'bidder': 'rubicon', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'auctionId': '25c6d7f5-699a-4bfc-87c9-996f915341fa' - } - ] -}; - -const STUBBED_UUID = '12345678-1234-1234-1234-123456789abc'; - -const ANALYTICS_MESSAGE = { - 'channel': 'web', - 'integration': 'pbjs', - 'version': '$prebid.version$', - 'referrerUri': 'http://www.test.com/page.html', - 'session': { - 'expires': 1519788613781, - 'id': STUBBED_UUID, - 'start': 1519767013781 - }, - 'timestamps': { - 'auctionEnded': 1519767013781, - 'eventTime': 1519767013781, - 'prebidLoaded': rubiconAnalyticsAdapter.MODULE_INITIALIZED_TIME - }, - 'trigger': 'allBidWons', - 'referrerHostname': 'www.test.com', - 'auctions': [ - { - - 'auctionEnd': 1519767013781, - 'auctionStart': 1519767010567, - 'bidderOrder': ['rubicon'], - 'requestId': '25c6d7f5-699a-4bfc-87c9-996f915341fa', - 'clientTimeoutMillis': 3000, - 'serverTimeoutMillis': 1000, - 'accountId': 1001, - 'samplingFactor': 1, - 'adUnits': [ - { - 'adUnitCode': '/19968336/header-bid-tag-0', - 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014', - 'videoAdFormat': 'outstream', - 'mediaTypes': [ - 'video' - ], - 'dimensions': [ - { - 'width': 640, - 'height': 480 - } - ], - 'status': 'success', - 'accountId': 1001, - 'siteId': 70608, - 'zoneId': 335918, - 'adserverTargeting': { - 'hb_bidder': 'rubicon', - 'hb_adid': '2ecff0db240757', - 'hb_pb': '1.200', - 'hb_size': '640x480', - 'hb_source': 'client' - }, - 'bids': [ - { - 'bidder': 'rubicon', - 'bidId': '2ecff0db240757', - 'status': 'success', - 'source': 'client', - 'clientLatencyMillis': 3214, - 'params': { - 'accountId': '1001', - 'siteId': '70608', - 'zoneId': '335918' - }, - 'bidResponse': { - 'bidPriceUSD': 1.22752, - 'dimensions': { - 'width': 640, - 'height': 480 - }, - 'mediaType': 'video' - } - } - ] - }, - { - 'adUnitCode': '/19968336/header-bid-tag1', - 'transactionId': 'c116413c-9e3f-401a-bee1-d56aec29a1d4', - 'mediaTypes': [ - 'banner' - ], - 'dimensions': [ - { - 'width': 1000, - 'height': 300 - }, - { - 'width': 970, - 'height': 250 - }, - { - 'width': 728, - 'height': 90 - } - ], - 'status': 'success', - 'adserverTargeting': { - 'hb_bidder': 'rubicon', - 'hb_adid': '3bd4ebb1c900e2', - 'hb_pb': '1.500', - 'hb_size': '728x90', - 'hb_source': 'server' - }, - 'bids': [ - { - 'bidder': 'rubicon', - 'bidId': 'aaaa-bbbb-cccc-dddd', - 'status': 'success', - 'source': 'server', - 'clientLatencyMillis': 3214, - 'serverLatencyMillis': 42, - 'params': { - 'accountId': '14062', - 'siteId': '70608', - 'zoneId': '335918' - }, - 'bidResponse': { - 'bidPriceUSD': 1.52, - 'dimensions': { - 'width': 728, - 'height': 90 - }, - 'mediaType': 'banner' - } - } - ] - } - ] - } - ], - 'bidsWon': [ - { - 'bidder': 'rubicon', - 'transactionId': 'ca4af27a-6d02-4f90-949d-d5541fa12014', - 'adUnitCode': '/19968336/header-bid-tag-0', - 'bidId': '2ecff0db240757', - 'status': 'success', - 'source': 'client', - 'clientLatencyMillis': 3214, - 'samplingFactor': 1, - 'accountId': 1001, - 'siteId': 70608, - 'zoneId': 335918, - 'params': { - 'accountId': '1001', - 'siteId': '70608', - 'zoneId': '335918' - }, - 'videoAdFormat': 'outstream', - 'mediaTypes': [ - 'video' - ], - 'adserverTargeting': { - 'hb_bidder': 'rubicon', - 'hb_adid': '2ecff0db240757', - 'hb_pb': '1.200', - 'hb_size': '640x480', - 'hb_source': 'client' - }, - 'bidResponse': { - 'bidPriceUSD': 1.22752, - 'dimensions': { - 'width': 640, - 'height': 480 - }, - 'mediaType': 'video' - }, - 'bidwonStatus': 'success' - }, - { - 'bidder': 'rubicon', - 'transactionId': 'c116413c-9e3f-401a-bee1-d56aec29a1d4', - 'adUnitCode': '/19968336/header-bid-tag1', - 'bidId': 'aaaa-bbbb-cccc-dddd', - 'status': 'success', - 'source': 'server', - 'clientLatencyMillis': 3214, - 'serverLatencyMillis': 42, - 'samplingFactor': 1, - 'accountId': 1001, - 'params': { - 'accountId': '14062', - 'siteId': '70608', - 'zoneId': '335918' - }, - 'mediaTypes': [ - 'banner' - ], - 'adserverTargeting': { - 'hb_bidder': 'rubicon', - 'hb_adid': '3bd4ebb1c900e2', - 'hb_pb': '1.500', - 'hb_size': '728x90', - 'hb_source': 'server' - }, - 'bidResponse': { - 'bidPriceUSD': 1.52, - 'dimensions': { - 'width': 728, - 'height': 90 - }, - 'mediaType': 'banner' - }, - 'bidwonStatus': 'success' - } - ], - 'wrapper': { - 'name': '10000_fakewrapper_test' - } -}; - -function performStandardAuction(gptEvents, auctionId = MOCK.AUCTION_INIT.auctionId) { - events.emit(AUCTION_INIT, { ...MOCK.AUCTION_INIT, auctionId }); - events.emit(BID_REQUESTED, { ...MOCK.BID_REQUESTED, auctionId }); - events.emit(BID_RESPONSE, { ...MOCK.BID_RESPONSE[0], auctionId }); - events.emit(BID_RESPONSE, { ...MOCK.BID_RESPONSE[1], auctionId }); - events.emit(BIDDER_DONE, { ...MOCK.BIDDER_DONE, auctionId }); - events.emit(AUCTION_END, { ...MOCK.AUCTION_END, auctionId }); - - if (gptEvents && gptEvents.length) { - gptEvents.forEach(gptEvent => mockGpt.emitEvent(gptEvent.eventName, gptEvent.params)); - } - - events.emit(SET_TARGETING, { ...MOCK.SET_TARGETING, auctionId }); - events.emit(BID_WON, { ...MOCK.BID_WON[0], auctionId }); - events.emit(BID_WON, { ...MOCK.BID_WON[1], auctionId }); -} - -describe('rubicon analytics adapter', function () { - let sandbox; - let clock; - let getDataFromLocalStorageStub, setDataInLocalStorageStub, localStorageIsEnabledStub; - beforeEach(function () { - getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage'); - setDataInLocalStorageStub = sinon.stub(storage, 'setDataInLocalStorage'); - localStorageIsEnabledStub = sinon.stub(storage, 'localStorageIsEnabled'); - mockGpt.disable(); - sandbox = sinon.sandbox.create(); - - localStorageIsEnabledStub.returns(true); - - sandbox.stub(events, 'getEvents').returns([]); - - sandbox.stub(utils, 'generateUUID').returns(STUBBED_UUID); - - clock = sandbox.useFakeTimers(1519767013781); - - rubiconAnalyticsAdapter.referrerHostname = ''; - - config.setConfig({ - s2sConfig: { - timeout: 1000, - accountId: 10000, - }, - rubicon: { - wrapperName: '10000_fakewrapper_test' - } - }) - }); - - afterEach(function () { - sandbox.restore(); - config.resetConfig(); - mockGpt.enable(); - getDataFromLocalStorageStub.restore(); - setDataInLocalStorageStub.restore(); - localStorageIsEnabledStub.restore(); - }); - - it('should require accountId', function () { - sandbox.stub(utils, 'logError'); - - rubiconAnalyticsAdapter.enableAnalytics({ - options: { - endpoint: '//localhost:9999/event' - } - }); - - expect(utils.logError.called).to.equal(true); - }); - - it('should require endpoint', function () { - sandbox.stub(utils, 'logError'); - - rubiconAnalyticsAdapter.enableAnalytics({ - options: { - accountId: 1001 - } - }); - - expect(utils.logError.called).to.equal(true); - }); - - describe('config subscribe', function () { - it('should update the pvid if user asks', function () { - expect(utils.generateUUID.called).to.equal(false); - config.setConfig({ rubicon: { updatePageView: true } }); - expect(utils.generateUUID.called).to.equal(true); - }); - it('should merge in and preserve older set configs', function () { - resetRubiConf(); - config.setConfig({ - rubicon: { - wrapperName: '1001_general', - int_type: 'dmpbjs', - fpkvs: { - source: 'fb' - } - } - }); - expect(rubiConf).to.deep.equal({ - analyticsEventDelay: 0, - dmBilling: { - enabled: false, - vendors: [], - waitForAuction: true - }, - pvid: '12345678', - wrapperName: '1001_general', - int_type: 'dmpbjs', - fpkvs: { - source: 'fb' - }, - }); - - // update it with stuff - config.setConfig({ - rubicon: { - fpkvs: { - link: 'email' - } - } - }); - expect(rubiConf).to.deep.equal({ - analyticsEventDelay: 0, - dmBilling: { - enabled: false, - vendors: [], - waitForAuction: true - }, - pvid: '12345678', - wrapperName: '1001_general', - int_type: 'dmpbjs', - fpkvs: { - source: 'fb', - link: 'email' - }, - }); - - // overwriting specific edge keys should update them - config.setConfig({ - rubicon: { - fpkvs: { - link: 'iMessage', - source: 'twitter' - } - } - }); - expect(rubiConf).to.deep.equal({ - analyticsEventDelay: 0, - dmBilling: { - enabled: false, - vendors: [], - waitForAuction: true - }, - pvid: '12345678', - wrapperName: '1001_general', - int_type: 'dmpbjs', - fpkvs: { - link: 'iMessage', - source: 'twitter' - }, - }); - }); - }); - - describe('sampling', function () { - beforeEach(function () { - sandbox.stub(Math, 'random').returns(0.08); - sandbox.stub(utils, 'logError'); - }); - - afterEach(function () { - rubiconAnalyticsAdapter.disableAnalytics(); - }); - - describe('with options.samplingFactor', function () { - it('should sample', function () { - rubiconAnalyticsAdapter.enableAnalytics({ - options: { - endpoint: '//localhost:9999/event', - accountId: 1001, - samplingFactor: 10 - } - }); - - performStandardAuction(); - - expect(server.requests.length).to.equal(1); - }); - - it('should unsample', function () { - rubiconAnalyticsAdapter.enableAnalytics({ - options: { - endpoint: '//localhost:9999/event', - accountId: 1001, - samplingFactor: 20 - } - }); - - performStandardAuction(); - - expect(server.requests.length).to.equal(0); - }); - - it('should throw errors for invalid samplingFactor', function () { - rubiconAnalyticsAdapter.enableAnalytics({ - options: { - endpoint: '//localhost:9999/event', - accountId: 1001, - samplingFactor: 30 - } - }); - - performStandardAuction(); - - expect(server.requests.length).to.equal(0); - expect(utils.logError.called).to.equal(true); - }); - }); - describe('with options.sampling', function () { - it('should sample', function () { - rubiconAnalyticsAdapter.enableAnalytics({ - options: { - endpoint: '//localhost:9999/event', - accountId: 1001, - sampling: 0.1 - } - }); - - performStandardAuction(); - - expect(server.requests.length).to.equal(1); - }); - - it('should unsample', function () { - rubiconAnalyticsAdapter.enableAnalytics({ - options: { - endpoint: '//localhost:9999/event', - accountId: 1001, - sampling: 0.05 - } - }); - - performStandardAuction(); - - expect(server.requests.length).to.equal(0); - }); - - it('should throw errors for invalid samplingFactor', function () { - rubiconAnalyticsAdapter.enableAnalytics({ - options: { - endpoint: '//localhost:9999/event', - accountId: 1001, - sampling: 1 / 30 - } - }); - - performStandardAuction(); - - expect(server.requests.length).to.equal(0); - expect(utils.logError.called).to.equal(true); - }); - }); - }); - - describe('when handling events', function () { - beforeEach(function () { - rubiconAnalyticsAdapter.enableAnalytics({ - options: { - endpoint: '//localhost:9999/event', - accountId: 1001 - } - }); - }); - - afterEach(function () { - rubiconAnalyticsAdapter.disableAnalytics(); - }); - - it('should build a batched message from prebid events', function () { - performStandardAuction(); - - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - - expect(request.url).to.equal('//localhost:9999/event'); - - let message = JSON.parse(request.requestBody); - validate(message); - - expect(message).to.deep.equal(ANALYTICS_MESSAGE); - }); - - it('should pass along bidderOrder correctly', function () { - const appnexusBid = utils.deepClone(MOCK.BID_REQUESTED); - appnexusBid.bidderCode = 'appnexus'; - const pubmaticBid = utils.deepClone(MOCK.BID_REQUESTED); - pubmaticBid.bidderCode = 'pubmatic'; - const indexBid = utils.deepClone(MOCK.BID_REQUESTED); - indexBid.bidderCode = 'ix'; - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, pubmaticBid); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - events.emit(BID_REQUESTED, indexBid); - events.emit(BID_REQUESTED, appnexusBid); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - clock.tick(SEND_TIMEOUT + 1000); - - let message = JSON.parse(server.requests[0].requestBody); - expect(message.auctions[0].bidderOrder).to.deep.equal([ - 'pubmatic', - 'rubicon', - 'ix', - 'appnexus' - ]); - }); - - it('should pass along user ids', function () { - let auctionInit = utils.deepClone(MOCK.AUCTION_INIT); - auctionInit.bidderRequests[0].bids[0].userId = { - criteoId: 'sadfe4334', - lotamePanoramaId: 'asdf3gf4eg', - pubcid: 'dsfa4545-svgdfs5', - sharedId: { id1: 'asdf', id2: 'sadf4344' } - }; - - events.emit(AUCTION_INIT, auctionInit); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[1]); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - events.emit(BID_WON, MOCK.BID_WON[0]); - events.emit(BID_WON, MOCK.BID_WON[1]); - - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - - let message = JSON.parse(request.requestBody); - validate(message); - - expect(message.auctions[0].user).to.deep.equal({ - ids: [ - { provider: 'criteoId', 'hasId': true }, - { provider: 'lotamePanoramaId', 'hasId': true }, - { provider: 'pubcid', 'hasId': true }, - { provider: 'sharedId', 'hasId': true }, - ] - }); - }); - - it('should handle bidResponse dimensions correctly', function () { - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - - // mock bid response with playerWidth and playerHeight (NO width and height) - let bidResponse1 = utils.deepClone(MOCK.BID_RESPONSE[0]); - delete bidResponse1.width; - delete bidResponse1.height; - bidResponse1.playerWidth = 640; - bidResponse1.playerHeight = 480; - - // mock bid response with no width height or playerwidth playerheight - let bidResponse2 = utils.deepClone(MOCK.BID_RESPONSE[1]); - delete bidResponse2.width; - delete bidResponse2.height; - delete bidResponse2.playerWidth; - delete bidResponse2.playerHeight; - - events.emit(BID_RESPONSE, bidResponse1); - events.emit(BID_RESPONSE, bidResponse2); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - events.emit(BID_WON, MOCK.BID_WON[0]); - events.emit(BID_WON, MOCK.BID_WON[1]); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - expect(message.auctions[0].adUnits[0].bids[0].bidResponse.dimensions).to.deep.equal({ - width: 640, - height: 480 - }); - expect(message.auctions[0].adUnits[1].bids[0].bidResponse.dimensions).to.equal(undefined); - }); - - it('should pass along adomians correctly', function () { - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - - // 1 adomains - let bidResponse1 = utils.deepClone(MOCK.BID_RESPONSE[0]); - bidResponse1.meta = { - advertiserDomains: ['magnite.com'] - } - - // two adomains - let bidResponse2 = utils.deepClone(MOCK.BID_RESPONSE[1]); - bidResponse2.meta = { - advertiserDomains: ['prebid.org', 'magnite.com'] - } - - // make sure we only pass max 10 adomains - bidResponse2.meta.advertiserDomains = [...bidResponse2.meta.advertiserDomains, ...bidResponse2.meta.advertiserDomains, ...bidResponse2.meta.advertiserDomains, ...bidResponse2.meta.advertiserDomains, ...bidResponse2.meta.advertiserDomains, ...bidResponse2.meta.advertiserDomains, ...bidResponse2.meta.advertiserDomains] - - events.emit(BID_RESPONSE, bidResponse1); - events.emit(BID_RESPONSE, bidResponse2); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - events.emit(BID_WON, MOCK.BID_WON[0]); - events.emit(BID_WON, MOCK.BID_WON[1]); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - expect(message.auctions[0].adUnits[0].bids[0].bidResponse.adomains).to.deep.equal(['magnite.com']); - expect(message.auctions[0].adUnits[1].bids[0].bidResponse.adomains).to.deep.equal(['prebid.org', 'magnite.com', 'prebid.org', 'magnite.com', 'prebid.org', 'magnite.com', 'prebid.org', 'magnite.com', 'prebid.org', 'magnite.com']); - }); - - it('should NOT pass along adomians correctly when edge cases', function () { - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - - // empty => nothing - let bidResponse1 = utils.deepClone(MOCK.BID_RESPONSE[0]); - bidResponse1.meta = { - advertiserDomains: [] - } - - // not array => nothing - let bidResponse2 = utils.deepClone(MOCK.BID_RESPONSE[1]); - bidResponse2.meta = { - advertiserDomains: 'prebid.org' - } - - events.emit(BID_RESPONSE, bidResponse1); - events.emit(BID_RESPONSE, bidResponse2); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - events.emit(BID_WON, MOCK.BID_WON[0]); - events.emit(BID_WON, MOCK.BID_WON[1]); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - expect(message.auctions[0].adUnits[0].bids[0].bidResponse.adomains).to.be.undefined; - expect(message.auctions[0].adUnits[1].bids[0].bidResponse.adomains).to.be.undefined; - }); - - it('should NOT pass along adomians with other edge cases', function () { - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - - // should filter out non string values and pass valid ones - let bidResponse1 = utils.deepClone(MOCK.BID_RESPONSE[0]); - bidResponse1.meta = { - advertiserDomains: [123, 'prebid.org', false, true, [], 'magnite.com', {}] - } - - // array of arrays (as seen when passed by kargo bid adapter) - let bidResponse2 = utils.deepClone(MOCK.BID_RESPONSE[1]); - bidResponse2.meta = { - advertiserDomains: [['prebid.org']] - } - - events.emit(BID_RESPONSE, bidResponse1); - events.emit(BID_RESPONSE, bidResponse2); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - events.emit(BID_WON, MOCK.BID_WON[0]); - events.emit(BID_WON, MOCK.BID_WON[1]); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - expect(message.auctions[0].adUnits[0].bids[0].bidResponse.adomains).to.deep.equal(['prebid.org', 'magnite.com']); - expect(message.auctions[0].adUnits[1].bids[0].bidResponse.adomains).to.be.undefined; - }); - - it('should not pass empty adServerTargeting values', function () { - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[1]); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - - const mockTargeting = utils.deepClone(MOCK.SET_TARGETING); - mockTargeting['/19968336/header-bid-tag-0'].hb_test = ''; - mockTargeting['/19968336/header-bid-tag1'].hb_test = 'NOT_EMPTY'; - events.emit(SET_TARGETING, mockTargeting); - - events.emit(BID_WON, MOCK.BID_WON[0]); - events.emit(BID_WON, MOCK.BID_WON[1]); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - expect(message.auctions[0].adUnits[0].adserverTargeting.hb_test).to.be.undefined; - expect(message.auctions[0].adUnits[1].adserverTargeting.hb_test).to.equal('NOT_EMPTY'); - }); - - function performFloorAuction(provider) { - let auctionInit = utils.deepClone(MOCK.AUCTION_INIT); - auctionInit.bidderRequests[0].bids[0].floorData = { - skipped: false, - modelVersion: 'someModelName', - modelWeight: 10, - modelTimestamp: 1606772895, - location: 'setConfig', - skipRate: 15, - fetchStatus: 'error', - floorProvider: provider - }; - let flooredResponse = { - ...BID, - floorData: { - floorValue: 4, - floorRule: '12345/sports|video', - floorCurrency: 'USD', - cpmAfterAdjustments: 2.1, - enforcements: { - enforceJS: true, - enforcePBS: false, - floorDeals: false, - bidAdjustment: true - }, - matchedFields: { - gptSlot: '12345/sports', - mediaType: 'video' - } - }, - status: 'bidRejected', - cpm: 0, - getStatusCode() { - return 2; - } - }; - - let notFlooredResponse = { - ...BID2, - floorData: { - floorValue: 1, - floorRule: '12345/news|banner', - floorCurrency: 'USD', - cpmAfterAdjustments: 1.55, - enforcements: { - enforceJS: true, - enforcePBS: false, - floorDeals: false, - bidAdjustment: true - }, - matchedFields: { - gptSlot: '12345/news', - mediaType: 'banner' - } - } - }; - - let floorMinResponse = { - ...BID3, - floorData: { - floorValue: 1.5, - floorRuleValue: 1, - floorRule: '12345/entertainment|banner', - floorCurrency: 'USD', - cpmAfterAdjustments: 2.00, - enforcements: { - enforceJS: true, - enforcePBS: false, - floorDeals: false, - bidAdjustment: true - }, - matchedFields: { - gptSlot: '12345/entertainment', - mediaType: 'banner' - } - } - }; - - let bidRequest = utils.deepClone(MOCK.BID_REQUESTED); - bidRequest.bids.push(floorMinRequest) - - // spoof the auction with just our duplicates - events.emit(AUCTION_INIT, auctionInit); - events.emit(BID_REQUESTED, bidRequest); - events.emit(BID_RESPONSE, flooredResponse); - events.emit(BID_RESPONSE, notFlooredResponse); - events.emit(BID_RESPONSE, floorMinResponse); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - events.emit(BID_WON, MOCK.BID_WON[1]); - events.emit(BID_WON, MOCK.BID_WON[2]); - clock.tick(SEND_TIMEOUT + 1000); - - expect(server.requests.length).to.equal(1); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - return message; - } - - it('should capture price floor information correctly', function () { - let message = performFloorAuction('rubicon'); - - // verify our floor stuff is passed - // top level floor info - expect(message.auctions[0].floors).to.deep.equal({ - location: 'setConfig', - modelName: 'someModelName', - modelWeight: 10, - modelTimestamp: 1606772895, - skipped: false, - enforcement: true, - dealsEnforced: false, - skipRate: 15, - fetchStatus: 'error', - provider: 'rubicon' - }); - // first adUnit's adSlot - expect(message.auctions[0].adUnits[0].gam.adSlot).to.equal('12345/sports'); - // since no other bids, we set adUnit status to no-bid - expect(message.auctions[0].adUnits[0].status).to.equal('no-bid'); - // first adUnits bid is rejected - expect(message.auctions[0].adUnits[0].bids[0].status).to.equal('rejected-ipf'); - expect(message.auctions[0].adUnits[0].bids[0].bidResponse.floorValue).to.equal(4); - // if bid rejected should take cpmAfterAdjustments val - expect(message.auctions[0].adUnits[0].bids[0].bidResponse.bidPriceUSD).to.equal(2.1); - - // second adUnit's adSlot - expect(message.auctions[0].adUnits[1].gam.adSlot).to.equal('12345/news'); - // top level adUnit status is success - expect(message.auctions[0].adUnits[1].status).to.equal('success'); - // second adUnits bid is success - expect(message.auctions[0].adUnits[1].bids[0].status).to.equal('success'); - expect(message.auctions[0].adUnits[1].bids[0].bidResponse.floorValue).to.equal(1); - expect(message.auctions[0].adUnits[1].bids[0].bidResponse.bidPriceUSD).to.equal(1.52); - - // second adUnit's adSlot - expect(message.auctions[0].adUnits[2].gam.adSlot).to.equal('12345/entertainment'); - // top level adUnit status is success - expect(message.auctions[0].adUnits[2].status).to.equal('success'); - // second adUnits bid is success - expect(message.auctions[0].adUnits[2].bids[0].status).to.equal('success'); - expect(message.auctions[0].adUnits[2].bids[0].bidResponse.floorValue).to.equal(1.5); - expect(message.auctions[0].adUnits[2].bids[0].bidResponse.floorRuleValue).to.equal(1); - expect(message.auctions[0].adUnits[2].bids[0].bidResponse.bidPriceUSD).to.equal(2.01); - }); - - it('should still send floor info if provider is not rubicon', function () { - let message = performFloorAuction('randomProvider'); - - // verify our floor stuff is passed - // top level floor info - expect(message.auctions[0].floors).to.deep.equal({ - location: 'setConfig', - modelName: 'someModelName', - modelWeight: 10, - modelTimestamp: 1606772895, - skipped: false, - enforcement: true, - dealsEnforced: false, - skipRate: 15, - fetchStatus: 'error', - provider: 'randomProvider' - }); - // first adUnit's adSlot - expect(message.auctions[0].adUnits[0].gam.adSlot).to.equal('12345/sports'); - // since no other bids, we set adUnit status to no-bid - expect(message.auctions[0].adUnits[0].status).to.equal('no-bid'); - // first adUnits bid is rejected - expect(message.auctions[0].adUnits[0].bids[0].status).to.equal('rejected-ipf'); - expect(message.auctions[0].adUnits[0].bids[0].bidResponse.floorValue).to.equal(4); - // if bid rejected should take cpmAfterAdjustments val - expect(message.auctions[0].adUnits[0].bids[0].bidResponse.bidPriceUSD).to.equal(2.1); - - // second adUnit's adSlot - expect(message.auctions[0].adUnits[1].gam.adSlot).to.equal('12345/news'); - // top level adUnit status is success - expect(message.auctions[0].adUnits[1].status).to.equal('success'); - // second adUnits bid is success - expect(message.auctions[0].adUnits[1].bids[0].status).to.equal('success'); - expect(message.auctions[0].adUnits[1].bids[0].bidResponse.floorValue).to.equal(1); - expect(message.auctions[0].adUnits[1].bids[0].bidResponse.bidPriceUSD).to.equal(1.52); - - // second adUnit's adSlot - expect(message.auctions[0].adUnits[2].gam.adSlot).to.equal('12345/entertainment'); - // top level adUnit status is success - expect(message.auctions[0].adUnits[2].status).to.equal('success'); - // second adUnits bid is success - expect(message.auctions[0].adUnits[2].bids[0].status).to.equal('success'); - expect(message.auctions[0].adUnits[2].bids[0].bidResponse.floorValue).to.equal(1.5); - expect(message.auctions[0].adUnits[2].bids[0].bidResponse.floorRuleValue).to.equal(1); - expect(message.auctions[0].adUnits[2].bids[0].bidResponse.bidPriceUSD).to.equal(2.01); - }); - - describe('with session handling', function () { - const expectedPvid = STUBBED_UUID.slice(0, 8); - beforeEach(function () { - config.setConfig({ rubicon: { updatePageView: true } }); - }); - - it('should not log any session data if local storage is not enabled', function () { - localStorageIsEnabledStub.returns(false); - - let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); - delete expectedMessage.session; - delete expectedMessage.fpkvs; - - performStandardAuction(); - - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - - expect(request.url).to.equal('//localhost:9999/event'); - - let message = JSON.parse(request.requestBody); - validate(message); - - expect(message).to.deep.equal(expectedMessage); - }); - - it('should should pass along custom rubicon kv and pvid when defined', function () { - config.setConfig({ - rubicon: { - fpkvs: { - source: 'fb', - link: 'email' - } - } - }); - performStandardAuction(); - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - validate(message); - - let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); - expectedMessage.session.pvid = STUBBED_UUID.slice(0, 8); - expectedMessage.fpkvs = [ - { key: 'source', value: 'fb' }, - { key: 'link', value: 'email' } - ] - expect(message).to.deep.equal(expectedMessage); - }); - - it('should convert kvs to strings before sending', function () { - config.setConfig({ - rubicon: { - fpkvs: { - number: 24, - boolean: false, - string: 'hello', - array: ['one', 2, 'three'], - object: { one: 'two' } - } - } - }); - performStandardAuction(); - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - validate(message); - - let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); - expectedMessage.session.pvid = STUBBED_UUID.slice(0, 8); - expectedMessage.fpkvs = [ - { key: 'number', value: '24' }, - { key: 'boolean', value: 'false' }, - { key: 'string', value: 'hello' }, - { key: 'array', value: 'one,2,three' }, - { key: 'object', value: '[object Object]' } - ] - expect(message).to.deep.equal(expectedMessage); - }); - - it('should use the query utm param rubicon kv value and pass updated kv and pvid when defined', function () { - sandbox.stub(utils, 'getWindowLocation').returns({ 'search': '?utm_source=other', 'pbjs_debug': 'true' }); - - config.setConfig({ - rubicon: { - fpkvs: { - source: 'fb', - link: 'email' - } - } - }); - performStandardAuction(); - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - validate(message); - - let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); - expectedMessage.session.pvid = STUBBED_UUID.slice(0, 8); - expectedMessage.fpkvs = [ - { key: 'source', value: 'other' }, - { key: 'link', value: 'email' } - ] - - message.fpkvs.sort((left, right) => left.key < right.key); - expectedMessage.fpkvs.sort((left, right) => left.key < right.key); - - expect(message).to.deep.equal(expectedMessage); - }); - - it('should pick up existing localStorage and use its values', function () { - // set some localStorage - let inputlocalStorage = { - id: '987654', - start: 1519766113781, // 15 mins before "now" - expires: 1519787713781, // six hours later - lastSeen: 1519766113781, - fpkvs: { source: 'tw' } - }; - getDataFromLocalStorageStub.withArgs('rpaSession').returns(btoa(JSON.stringify(inputlocalStorage))); - - config.setConfig({ - rubicon: { - fpkvs: { - link: 'email' // should merge this with what is in the localStorage! - } - } - }); - performStandardAuction(); - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - validate(message); - - let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); - expectedMessage.session = { - id: '987654', - start: 1519766113781, - expires: 1519787713781, - pvid: expectedPvid - } - expectedMessage.fpkvs = [ - { key: 'source', value: 'tw' }, - { key: 'link', value: 'email' } - ] - expect(message).to.deep.equal(expectedMessage); - - let calledWith; - try { - calledWith = JSON.parse(atob(setDataInLocalStorageStub.getCall(0).args[1])); - } catch (e) { - calledWith = {}; - } - - expect(calledWith).to.deep.equal({ - id: '987654', // should have stayed same - start: 1519766113781, // should have stayed same - expires: 1519787713781, // should have stayed same - lastSeen: 1519767013781, // lastSeen updated to our "now" - fpkvs: { source: 'tw', link: 'email' }, // link merged in - pvid: expectedPvid // new pvid stored - }); - }); - - it('should overwrite matching localstorge value and use its remaining values', function () { - sandbox.stub(utils, 'getWindowLocation').returns({ 'search': '?utm_source=fb&utm_click=dog' }); - - // set some localStorage - let inputlocalStorage = { - id: '987654', - start: 1519766113781, // 15 mins before "now" - expires: 1519787713781, // six hours later - lastSeen: 1519766113781, - fpkvs: { source: 'tw', link: 'email' } - }; - getDataFromLocalStorageStub.withArgs('rpaSession').returns(btoa(JSON.stringify(inputlocalStorage))); - - config.setConfig({ - rubicon: { - fpkvs: { - link: 'email' // should merge this with what is in the localStorage! - } - } - }); - performStandardAuction(); - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - validate(message); - - let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); - expectedMessage.session = { - id: '987654', - start: 1519766113781, - expires: 1519787713781, - pvid: expectedPvid - } - expectedMessage.fpkvs = [ - { key: 'source', value: 'fb' }, - { key: 'link', value: 'email' }, - { key: 'click', value: 'dog' } - ] - - message.fpkvs.sort((left, right) => left.key < right.key); - expectedMessage.fpkvs.sort((left, right) => left.key < right.key); - - expect(message).to.deep.equal(expectedMessage); - - let calledWith; - try { - calledWith = JSON.parse(atob(setDataInLocalStorageStub.getCall(0).args[1])); - } catch (e) { - calledWith = {}; - } - - expect(calledWith).to.deep.equal({ - id: '987654', // should have stayed same - start: 1519766113781, // should have stayed same - expires: 1519787713781, // should have stayed same - lastSeen: 1519767013781, // lastSeen updated to our "now" - fpkvs: { source: 'fb', link: 'email', click: 'dog' }, // link merged in - pvid: expectedPvid // new pvid stored - }); - }); - - it('should throw out session if lastSeen > 30 mins ago and create new one', function () { - // set some localStorage - let inputlocalStorage = { - id: '987654', - start: 1519764313781, // 45 mins before "now" - expires: 1519785913781, // six hours later - lastSeen: 1519764313781, // 45 mins before "now" - fpkvs: { source: 'tw' } - }; - getDataFromLocalStorageStub.withArgs('rpaSession').returns(btoa(JSON.stringify(inputlocalStorage))); - - config.setConfig({ - rubicon: { - fpkvs: { - link: 'email' // should merge this with what is in the localStorage! - } - } - }); - - performStandardAuction(); - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - validate(message); - - let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); - // session should match what is already in ANALYTICS_MESSAGE, just need to add pvid - expectedMessage.session.pvid = expectedPvid; - - // the saved fpkvs should have been thrown out since session expired - expectedMessage.fpkvs = [ - { key: 'link', value: 'email' } - ] - expect(message).to.deep.equal(expectedMessage); - - let calledWith; - try { - calledWith = JSON.parse(atob(setDataInLocalStorageStub.getCall(0).args[1])); - } catch (e) { - calledWith = {}; - } - - expect(calledWith).to.deep.equal({ - id: STUBBED_UUID, // should have stayed same - start: 1519767013781, // should have stayed same - expires: 1519788613781, // should have stayed same - lastSeen: 1519767013781, // lastSeen updated to our "now" - fpkvs: { link: 'email' }, // link merged in - pvid: expectedPvid // new pvid stored - }); - }); - - it('should throw out session if past expires time and create new one', function () { - // set some localStorage - let inputlocalStorage = { - id: '987654', - start: 1519745353781, // 6 hours before "expires" - expires: 1519766953781, // little more than six hours ago - lastSeen: 1519767008781, // 5 seconds ago - fpkvs: { source: 'tw' } - }; - getDataFromLocalStorageStub.withArgs('rpaSession').returns(btoa(JSON.stringify(inputlocalStorage))); - - config.setConfig({ - rubicon: { - fpkvs: { - link: 'email' // should merge this with what is in the localStorage! - } - } - }); - - performStandardAuction(); - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - validate(message); - - let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); - // session should match what is already in ANALYTICS_MESSAGE, just need to add pvid - expectedMessage.session.pvid = expectedPvid; - - // the saved fpkvs should have been thrown out since session expired - expectedMessage.fpkvs = [ - { key: 'link', value: 'email' } - ] - expect(message).to.deep.equal(expectedMessage); - - let calledWith; - try { - calledWith = JSON.parse(atob(setDataInLocalStorageStub.getCall(0).args[1])); - } catch (e) { - calledWith = {}; - } - - expect(calledWith).to.deep.equal({ - id: STUBBED_UUID, // should have stayed same - start: 1519767013781, // should have stayed same - expires: 1519788613781, // should have stayed same - lastSeen: 1519767013781, // lastSeen updated to our "now" - fpkvs: { link: 'email' }, // link merged in - pvid: expectedPvid // new pvid stored - }); - }); - }); - describe('with googletag enabled', function () { - let gptSlot0, gptSlot1; - let gptSlotRenderEnded0, gptSlotRenderEnded1; - beforeEach(function () { - mockGpt.enable(); - gptSlot0 = mockGpt.makeSlot({ code: '/19968336/header-bid-tag-0' }); - gptSlotRenderEnded0 = { - eventName: 'slotRenderEnded', - params: { - slot: gptSlot0, - isEmpty: false, - advertiserId: 1111, - sourceAgnosticCreativeId: 2222, - sourceAgnosticLineItemId: 3333 - } - }; - - gptSlot1 = mockGpt.makeSlot({ code: '/19968336/header-bid-tag1' }); - gptSlotRenderEnded1 = { - eventName: 'slotRenderEnded', - params: { - slot: gptSlot1, - isEmpty: false, - advertiserId: 4444, - sourceAgnosticCreativeId: 5555, - sourceAgnosticLineItemId: 6666 - } - }; - }); - - afterEach(function () { - mockGpt.disable(); - }); - - it('should add necessary gam information if gpt is enabled and slotRender event emmited', function () { - performStandardAuction([gptSlotRenderEnded0, gptSlotRenderEnded1]); - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - validate(message); - - let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); - expectedMessage.auctions[0].adUnits[0].gam = { - advertiserId: 1111, - creativeId: 2222, - lineItemId: 3333, - adSlot: '/19968336/header-bid-tag-0' - }; - expectedMessage.auctions[0].adUnits[1].gam = { - advertiserId: 4444, - creativeId: 5555, - lineItemId: 6666, - adSlot: '/19968336/header-bid-tag1' - }; - expect(message).to.deep.equal(expectedMessage); - }); - - it('should handle empty gam renders', function () { - performStandardAuction([gptSlotRenderEnded0, { - eventName: 'slotRenderEnded', - params: { - slot: gptSlot1, - isEmpty: true - } - }]); - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - validate(message); - - let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); - expectedMessage.auctions[0].adUnits[0].gam = { - advertiserId: 1111, - creativeId: 2222, - lineItemId: 3333, - adSlot: '/19968336/header-bid-tag-0' - }; - expectedMessage.auctions[0].adUnits[1].gam = { - isSlotEmpty: true, - adSlot: '/19968336/header-bid-tag1' - }; - expect(message).to.deep.equal(expectedMessage); - }); - - it('should still add gam ids if falsy', function () { - performStandardAuction([gptSlotRenderEnded0, { - eventName: 'slotRenderEnded', - params: { - slot: gptSlot1, - isEmpty: false, - advertiserId: 0, - sourceAgnosticCreativeId: 0, - sourceAgnosticLineItemId: 0 - } - }]); - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - validate(message); - - let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); - expectedMessage.auctions[0].adUnits[0].gam = { - advertiserId: 1111, - creativeId: 2222, - lineItemId: 3333, - adSlot: '/19968336/header-bid-tag-0' - }; - expectedMessage.auctions[0].adUnits[1].gam = { - advertiserId: 0, - creativeId: 0, - lineItemId: 0, - adSlot: '/19968336/header-bid-tag1' - }; - expect(message).to.deep.equal(expectedMessage); - }); - - it('should pick backup Ids if no sourceAgnostic available first', function () { - performStandardAuction([gptSlotRenderEnded0, { - eventName: 'slotRenderEnded', - params: { - slot: gptSlot1, - isEmpty: false, - advertiserId: 0, - lineItemId: 1234, - creativeId: 5678 - } - }]); - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - validate(message); - - let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); - expectedMessage.auctions[0].adUnits[0].gam = { - advertiserId: 1111, - creativeId: 2222, - lineItemId: 3333, - adSlot: '/19968336/header-bid-tag-0' - }; - expectedMessage.auctions[0].adUnits[1].gam = { - advertiserId: 0, - creativeId: 5678, - lineItemId: 1234, - adSlot: '/19968336/header-bid-tag1' - }; - expect(message).to.deep.equal(expectedMessage); - }); - - it('should correctly set adUnit for associated slots', function () { - performStandardAuction([gptSlotRenderEnded0, gptSlotRenderEnded1]); - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - validate(message); - - let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); - expectedMessage.auctions[0].adUnits[0].gam = { - advertiserId: 1111, - creativeId: 2222, - lineItemId: 3333, - adSlot: '/19968336/header-bid-tag-0' - }; - expectedMessage.auctions[0].adUnits[1].gam = { - advertiserId: 4444, - creativeId: 5555, - lineItemId: 6666, - adSlot: '/19968336/header-bid-tag1' - }; - expect(message).to.deep.equal(expectedMessage); - }); - - it('should only mark the first gam data not all matches', function () { - config.setConfig({ - rubicon: { - waitForGamSlots: true - } - }); - performStandardAuction(); - performStandardAuction([gptSlotRenderEnded0, gptSlotRenderEnded1], '32d332de-123a-32dg-2345-cefef3423324'); - - // tick the clock and both should fire - clock.tick(3000); - - expect(server.requests.length).to.equal(2); - - // first one should have GAM data - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - - // trigger should be gam since all adunits had associated gam render - expect(message.trigger).to.be.equal('gam'); - expect(message.auctions[0].adUnits[0].gam).to.deep.equal({ - advertiserId: 1111, - creativeId: 2222, - lineItemId: 3333, - adSlot: '/19968336/header-bid-tag-0' - }); - expect(message.auctions[0].adUnits[1].gam).to.deep.equal({ - advertiserId: 4444, - creativeId: 5555, - lineItemId: 6666, - adSlot: '/19968336/header-bid-tag1' - }); - - // second one should NOT have gam data - request = server.requests[1]; - message = JSON.parse(request.requestBody); - validate(message); - - // trigger should be auctionEnd - expect(message.trigger).to.be.equal('auctionEnd'); - expect(message.auctions[0].adUnits[0].gam).to.be.undefined; - expect(message.auctions[0].adUnits[1].gam).to.be.undefined; - }); - - it('should send request when waitForGamSlots is present but no bidWons are sent', function () { - config.setConfig({ - rubicon: { - waitForGamSlots: true, - } - }); - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[1]); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - - // should send if just slotRenderEnded is emmitted for both - mockGpt.emitEvent(gptSlotRenderEnded0.eventName, gptSlotRenderEnded0.params); - mockGpt.emitEvent(gptSlotRenderEnded1.eventName, gptSlotRenderEnded1.params); - - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - validate(message); - - let expectedMessage = utils.deepClone(ANALYTICS_MESSAGE); - delete expectedMessage.bidsWon; // should not be any of these - expectedMessage.auctions[0].adUnits[0].gam = { - advertiserId: 1111, - creativeId: 2222, - lineItemId: 3333, - adSlot: '/19968336/header-bid-tag-0' - }; - expectedMessage.auctions[0].adUnits[1].gam = { - advertiserId: 4444, - creativeId: 5555, - lineItemId: 6666, - adSlot: '/19968336/header-bid-tag1' - }; - expectedMessage.trigger = 'gam'; - expect(message).to.deep.equal(expectedMessage); - }); - - it('should delay the event call depending on analyticsEventDelay config', function () { - config.setConfig({ - rubicon: { - waitForGamSlots: true, - analyticsEventDelay: 2000 - } - }); - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[1]); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - - // should send if just slotRenderEnded is emmitted for both - mockGpt.emitEvent(gptSlotRenderEnded0.eventName, gptSlotRenderEnded0.params); - mockGpt.emitEvent(gptSlotRenderEnded1.eventName, gptSlotRenderEnded1.params); - - // Should not be sent until delay - expect(server.requests.length).to.equal(0); - - // tick the clock and it should fire - clock.tick(2000); - - expect(server.requests.length).to.equal(1); - let request = server.requests[0]; - let message = JSON.parse(request.requestBody); - validate(message); - let expectedGam0 = { - advertiserId: 1111, - creativeId: 2222, - lineItemId: 3333, - adSlot: '/19968336/header-bid-tag-0' - }; - let expectedGam1 = { - advertiserId: 4444, - creativeId: 5555, - lineItemId: 6666, - adSlot: '/19968336/header-bid-tag1' - }; - expect(expectedGam0).to.deep.equal(message.auctions[0].adUnits[0].gam); - expect(expectedGam1).to.deep.equal(message.auctions[0].adUnits[1].gam); - }); - }); - - it('should correctly overwrite bidId if seatBidId is on the bidResponse', function () { - // Only want one bid request in our mock auction - let bidRequested = utils.deepClone(MOCK.BID_REQUESTED); - bidRequested.bids.shift(); - let auctionInit = utils.deepClone(MOCK.AUCTION_INIT); - auctionInit.adUnits.shift(); - - // clone the mock bidResponse and duplicate - let seatBidResponse = utils.deepClone(BID2); - seatBidResponse.seatBidId = 'abc-123-do-re-me'; - - const setTargeting = { - [seatBidResponse.adUnitCode]: seatBidResponse.adserverTargeting - }; - - const bidWon = Object.assign({}, seatBidResponse, { - 'status': 'rendered' - }); - - // spoof the auction with just our duplicates - events.emit(AUCTION_INIT, auctionInit); - events.emit(BID_REQUESTED, bidRequested); - events.emit(BID_RESPONSE, seatBidResponse); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, setTargeting); - events.emit(BID_WON, bidWon); - - let message = JSON.parse(server.requests[0].requestBody); - - validate(message); - expect(message.auctions[0].adUnits[0].bids[0].bidId).to.equal('abc-123-do-re-me'); - expect(message.bidsWon[0].bidId).to.equal('abc-123-do-re-me'); - }); - - it('should correctly overwrite bidId if pbsBidId is on the bidResponse', function () { - // Only want one bid request in our mock auction - let bidRequested = utils.deepClone(MOCK.BID_REQUESTED); - bidRequested.bids.shift(); - let auctionInit = utils.deepClone(MOCK.AUCTION_INIT); - auctionInit.adUnits.shift(); - - // clone the mock bidResponse and duplicate - let seatBidResponse = utils.deepClone(BID4); - - const setTargeting = { - [seatBidResponse.adUnitCode]: seatBidResponse.adserverTargeting - }; - - const bidWon = Object.assign({}, seatBidResponse, { - 'status': 'rendered' - }); - - // spoof the auction with just our duplicates - events.emit(AUCTION_INIT, auctionInit); - events.emit(BID_REQUESTED, bidRequested); - events.emit(BID_RESPONSE, seatBidResponse); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, setTargeting); - events.emit(BID_WON, bidWon); - - let message = JSON.parse(server.requests[0].requestBody); - - validate(message); - expect(message.auctions[0].adUnits[0].bids[0].bidId).to.equal('zzzz-yyyy-xxxx-wwww'); - expect(message.bidsWon[0].bidId).to.equal('zzzz-yyyy-xxxx-wwww'); - }); - - it('should correctly generate new bidId if it is 0', function () { - // Only want one bid request in our mock auction - let bidRequested = utils.deepClone(MOCK.BID_REQUESTED); - bidRequested.bids.shift(); - let auctionInit = utils.deepClone(MOCK.AUCTION_INIT); - auctionInit.adUnits.shift(); - - // clone the mock bidResponse and duplicate - let seatBidResponse = utils.deepClone(BID4); - seatBidResponse.pbsBidId = '0'; - - const setTargeting = { - [seatBidResponse.adUnitCode]: seatBidResponse.adserverTargeting - }; - - const bidWon = Object.assign({}, seatBidResponse, { - 'status': 'rendered' - }); - - // spoof the auction with just our duplicates - events.emit(AUCTION_INIT, auctionInit); - events.emit(BID_REQUESTED, bidRequested); - events.emit(BID_RESPONSE, seatBidResponse); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, setTargeting); - events.emit(BID_WON, bidWon); - - let message = JSON.parse(server.requests[0].requestBody); - - validate(message); - expect(message.auctions[0].adUnits[0].bids[0].bidId).to.equal(STUBBED_UUID); - expect(message.bidsWon[0].bidId).to.equal(STUBBED_UUID); - }); - - it('should pick the highest cpm bid if more than one bid per bidRequestId', function () { - // Only want one bid request in our mock auction - let bidRequested = utils.deepClone(MOCK.BID_REQUESTED); - bidRequested.bids.shift(); - let auctionInit = utils.deepClone(MOCK.AUCTION_INIT); - auctionInit.adUnits.shift(); - - // clone the mock bidResponse and duplicate - let duplicateResponse1 = utils.deepClone(BID2); - duplicateResponse1.cpm = 1.0; - duplicateResponse1.adserverTargeting.hb_pb = '1.0'; - duplicateResponse1.adserverTargeting.hb_adid = '1111'; - let duplicateResponse2 = utils.deepClone(BID2); - duplicateResponse2.cpm = 5.5; - duplicateResponse2.adserverTargeting.hb_pb = '5.5'; - duplicateResponse2.adserverTargeting.hb_adid = '5555'; - let duplicateResponse3 = utils.deepClone(BID2); - duplicateResponse3.cpm = 0.1; - duplicateResponse3.adserverTargeting.hb_pb = '0.1'; - duplicateResponse3.adserverTargeting.hb_adid = '3333'; - - const setTargeting = { - [duplicateResponse2.adUnitCode]: duplicateResponse2.adserverTargeting - }; - - const bidWon = Object.assign({}, duplicateResponse2, { - 'status': 'rendered' - }); - - // spoof the auction with just our duplicates - events.emit(AUCTION_INIT, auctionInit); - events.emit(BID_REQUESTED, bidRequested); - events.emit(BID_RESPONSE, duplicateResponse1); - events.emit(BID_RESPONSE, duplicateResponse2); - events.emit(BID_RESPONSE, duplicateResponse3); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, setTargeting); - events.emit(BID_WON, bidWon); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - expect(message.auctions[0].adUnits[0].bids[0].bidResponse.bidPriceUSD).to.equal(5.5); - expect(message.auctions[0].adUnits[0].adserverTargeting.hb_pb).to.equal('5.5'); - expect(message.auctions[0].adUnits[0].adserverTargeting.hb_adid).to.equal('5555'); - expect(message.bidsWon.length).to.equal(1); - expect(message.bidsWon[0].bidResponse.bidPriceUSD).to.equal(5.5); - expect(message.bidsWon[0].adserverTargeting.hb_pb).to.equal('5.5'); - expect(message.bidsWon[0].adserverTargeting.hb_adid).to.equal('5555'); - }); - - it('should send batched message without BID_WON if necessary and further BID_WON events individually', function () { - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[1]); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - events.emit(BID_WON, MOCK.BID_WON[0]); - - clock.tick(SEND_TIMEOUT + 1000); - - events.emit(BID_WON, MOCK.BID_WON[1]); - - expect(server.requests.length).to.equal(2); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - expect(message.bidsWon.length).to.equal(1); - expect(message.auctions).to.deep.equal(ANALYTICS_MESSAGE.auctions); - expect(message.bidsWon[0]).to.deep.equal(ANALYTICS_MESSAGE.bidsWon[0]); - - message = JSON.parse(server.requests[1].requestBody); - validate(message); - expect(message.bidsWon.length).to.equal(1); - expect(message).to.not.have.property('auctions'); - expect(message.bidsWon[0]).to.deep.equal(ANALYTICS_MESSAGE.bidsWon[1]); - }); - - it('should properly mark bids as timed out', function () { - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - events.emit(BID_TIMEOUT, MOCK.BID_TIMEOUT); - events.emit(AUCTION_END, MOCK.AUCTION_END); - - clock.tick(SEND_TIMEOUT + 1000); - - expect(server.requests.length).to.equal(1); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - let timedOutBid = message.auctions[0].adUnits[0].bids[0]; - expect(timedOutBid.status).to.equal('error'); - expect(timedOutBid.error.code).to.equal('timeout-error'); - expect(timedOutBid.error.description).to.equal('prebid.js timeout'); - expect(timedOutBid).to.not.have.property('bidResponse'); - }); - - it('should pass aupName as pattern', function () { - let bidRequest = utils.deepClone(MOCK.BID_REQUESTED); - bidRequest.bids[0].ortb2Imp = { - ext: { - data: { - aupname: '1234/mycoolsite/*&gpt_leaderboard&deviceType=mobile' - } - } - }; - bidRequest.bids[1].ortb2Imp = { - ext: { - data: { - aupname: '1234/mycoolsite/*&gpt_skyscraper&deviceType=mobile' - } - } - }; - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, bidRequest); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - - clock.tick(SEND_TIMEOUT + 1000); - - expect(server.requests.length).to.equal(1); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - expect(message.auctions[0].adUnits[0].pattern).to.equal('1234/mycoolsite/*&gpt_leaderboard&deviceType=mobile'); - expect(message.auctions[0].adUnits[1].pattern).to.equal('1234/mycoolsite/*&gpt_skyscraper&deviceType=mobile'); - }); - - it('should pass gpid if defined', function () { - let bidRequest = utils.deepClone(MOCK.BID_REQUESTED); - bidRequest.bids[0].ortb2Imp = { - ext: { - gpid: '1234/mycoolsite/lowerbox' - } - }; - bidRequest.bids[1].ortb2Imp = { - ext: { - gpid: '1234/mycoolsite/leaderboard' - } - }; - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, bidRequest); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - - clock.tick(SEND_TIMEOUT + 1000); - - expect(server.requests.length).to.equal(1); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - expect(message.auctions[0].adUnits[0].gpid).to.equal('1234/mycoolsite/lowerbox'); - expect(message.auctions[0].adUnits[1].gpid).to.equal('1234/mycoolsite/leaderboard'); - }); - - it('should pass bidderDetail for multibid auctions', function () { - let bidResponse = utils.deepClone(MOCK.BID_RESPONSE[1]); - bidResponse.targetingBidder = 'rubi2'; - bidResponse.originalRequestId = bidResponse.requestId; - bidResponse.requestId = '1a2b3c4d5e6f7g8h9'; - - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]); - events.emit(BID_RESPONSE, bidResponse); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - events.emit(BID_WON, MOCK.BID_WON[0]); - - clock.tick(SEND_TIMEOUT + 1000); - - expect(server.requests.length).to.equal(1); - - let message = JSON.parse(server.requests[0].requestBody); - validate(message); - - expect(message.auctions[0].adUnits[1].bids[1].bidder).to.equal('rubicon'); - expect(message.auctions[0].adUnits[1].bids[1].bidderDetail).to.equal('rubi2'); - }); - - it('should successfully convert bid price to USD in parseBidResponse', function () { - // Set the rates - setConfig({ - adServerCurrency: 'JPY', - rates: { - USD: { - JPY: 100 - } - } - }); - - // set our bid response to JPY - const bidCopy = utils.deepClone(BID2); - bidCopy.currency = 'JPY'; - bidCopy.cpm = 100; - - // Now add the bidResponse hook which hooks on the currenct conversion function onto the bid response - let innerBid; - addBidResponseHook(function (adCodeId, bid) { - innerBid = bid; - }, 'elementId', bidCopy); - - // Use the rubi analytics parseBidResponse Function to get the resulting cpm from the bid response! - const bidResponseObj = parseBidResponse(innerBid); - expect(bidResponseObj).to.have.property('bidPriceUSD'); - expect(bidResponseObj.bidPriceUSD).to.equal(1.0); - }); - }); - - describe('config with integration type', () => { - it('should use the integration type provided in the config instead of the default', () => { - config.setConfig({ - rubicon: { - int_type: 'testType' - } - }) - - rubiconAnalyticsAdapter.enableAnalytics({ - options: { - endpoint: '//localhost:9999/event', - accountId: 1001 - } - }); - - performStandardAuction(); - - expect(server.requests.length).to.equal(1); - const request = server.requests[0]; - const message = JSON.parse(request.requestBody); - expect(message.integration).to.equal('testType'); - - rubiconAnalyticsAdapter.disableAnalytics(); - }); - }); - - describe('billing events integration', () => { - beforeEach(function () { - rubiconAnalyticsAdapter.enableAnalytics({ - options: { - endpoint: '//localhost:9999/event', - accountId: 1001 - } - }); - // default dmBilling - config.setConfig({ - rubicon: { - dmBilling: { - enabled: false, - vendors: [], - waitForAuction: true - } - } - }) - }); - afterEach(function () { - rubiconAnalyticsAdapter.disableAnalytics(); - }); - const basicBillingAuction = (billingEvents = []) => { - events.emit(AUCTION_INIT, MOCK.AUCTION_INIT); - events.emit(BID_REQUESTED, MOCK.BID_REQUESTED); - - // emit billing events - billingEvents.forEach(ev => events.emit(BILLABLE_EVENT, ev)); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[0]); - events.emit(BID_RESPONSE, MOCK.BID_RESPONSE[1]); - events.emit(BIDDER_DONE, MOCK.BIDDER_DONE); - events.emit(AUCTION_END, MOCK.AUCTION_END); - events.emit(SET_TARGETING, MOCK.SET_TARGETING); - events.emit(BID_WON, MOCK.BID_WON[0]); - events.emit(BID_WON, MOCK.BID_WON[1]); - } - it('should ignore billing events when not enabled', () => { - basicBillingAuction([{ - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }]); - expect(server.requests.length).to.equal(1); - const request = server.requests[0]; - const message = JSON.parse(request.requestBody); - expect(message.billableEvents).to.be.undefined; - }); - it('should ignore billing events when enabled but vendor is not whitelisted', () => { - // off by default - config.setConfig({ - rubicon: { - dmBilling: { - enabled: true - } - } - }); - basicBillingAuction([{ - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }]); - expect(server.requests.length).to.equal(1); - const request = server.requests[0]; - const message = JSON.parse(request.requestBody); - expect(message.billableEvents).to.be.undefined; - }); - it('should ignore billing events if billingId is not defined or billingId is not a string', () => { - // off by default - config.setConfig({ - rubicon: { - dmBilling: { - enabled: true, - vendors: ['vendorName'] - } - } - }); - basicBillingAuction([ - { - vendor: 'vendorName', - type: 'auction', - }, - { - vendor: 'vendorName', - type: 'auction', - billingId: true - }, - { - vendor: 'vendorName', - type: 'auction', - billingId: 1233434 - }, - { - vendor: 'vendorName', - type: 'auction', - billingId: null - } - ]); - expect(server.requests.length).to.equal(1); - const request = server.requests[0]; - const message = JSON.parse(request.requestBody); - expect(message.billableEvents).to.be.undefined; - }); - it('should pass along billing event in same payload', () => { - // off by default - config.setConfig({ - rubicon: { - dmBilling: { - enabled: true, - vendors: ['vendorName'] - } - } - }); - basicBillingAuction([{ - vendor: 'vendorName', - type: 'pageView', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }]); - expect(server.requests.length).to.equal(1); - const request = server.requests[0]; - const message = JSON.parse(request.requestBody); - expect(message).to.haveOwnProperty('auctions'); - expect(message.billableEvents).to.deep.equal([{ - accountId: 1001, - vendor: 'vendorName', - type: 'pageView', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }]); - }); - it('should pass along multiple billing events but filter out duplicates', () => { - // off by default - config.setConfig({ - rubicon: { - dmBilling: { - enabled: true, - vendors: ['vendorName'] - } - } - }); - basicBillingAuction([ - { - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }, - { - vendor: 'vendorName', - type: 'impression', - billingId: '743db6e3-21f2-44d4-917f-cb3488c6076f' - }, - { - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - } - ]); - expect(server.requests.length).to.equal(1); - const request = server.requests[0]; - const message = JSON.parse(request.requestBody); - expect(message).to.haveOwnProperty('auctions'); - expect(message.billableEvents).to.deep.equal([ - { - accountId: 1001, - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }, - { - accountId: 1001, - vendor: 'vendorName', - type: 'impression', - billingId: '743db6e3-21f2-44d4-917f-cb3488c6076f' - } - ]); - }); - it('should pass along event right away if no pending auction', () => { - // off by default - config.setConfig({ - rubicon: { - dmBilling: { - enabled: true, - vendors: ['vendorName'] - } - } - }); - - events.emit(BILLABLE_EVENT, { - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }); - expect(server.requests.length).to.equal(1); - const request = server.requests[0]; - const message = JSON.parse(request.requestBody); - expect(message).to.not.haveOwnProperty('auctions'); - expect(message.billableEvents).to.deep.equal([ - { - accountId: 1001, - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - } - ]); - }); - it('should pass along event right away if pending auction but not waiting', () => { - // off by default - config.setConfig({ - rubicon: { - dmBilling: { - enabled: true, - vendors: ['vendorName'], - waitForAuction: false - } - } - }); - // should fire right away, and then auction later - basicBillingAuction([{ - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - }]); - expect(server.requests.length).to.equal(2); - const billingRequest = server.requests[0]; - const billingMessage = JSON.parse(billingRequest.requestBody); - expect(billingMessage).to.not.haveOwnProperty('auctions'); - expect(billingMessage.billableEvents).to.deep.equal([ - { - accountId: 1001, - vendor: 'vendorName', - type: 'auction', - billingId: 'f8558d41-62de-4349-bc7b-2dbee1e69965' - } - ]); - // auction event after - const auctionRequest = server.requests[1]; - const auctionMessage = JSON.parse(auctionRequest.requestBody); - // should not double pass events! - expect(auctionMessage).to.not.haveOwnProperty('billableEvents'); - }); - }); - - describe('wrapper details passed in', () => { - it('should correctly pass in the wrapper details if provided', () => { - config.setConfig({ - rubicon: { - wrapperName: '1001_wrapperName_exp.4', - wrapperFamily: '1001_wrapperName', - rule_name: 'na-mobile' - } - }); - - rubiconAnalyticsAdapter.enableAnalytics({ - options: { - endpoint: '//localhost:9999/event', - accountId: 1001 - } - }); - - performStandardAuction(); - - expect(server.requests.length).to.equal(1); - const request = server.requests[0]; - const message = JSON.parse(request.requestBody); - expect(message.wrapper).to.deep.equal({ - name: '1001_wrapperName_exp.4', - family: '1001_wrapperName', - rule: 'na-mobile' - }); - - rubiconAnalyticsAdapter.disableAnalytics(); - }); - }); - - it('getHostNameFromReferer correctly grabs hostname from an input URL', function () { - let inputUrl = 'https://www.prebid.org/some/path?pbjs_debug=true'; - expect(getHostNameFromReferer(inputUrl)).to.equal('www.prebid.org'); - inputUrl = 'https://www.prebid.com/some/path?pbjs_debug=true'; - expect(getHostNameFromReferer(inputUrl)).to.equal('www.prebid.com'); - inputUrl = 'https://prebid.org/some/path?pbjs_debug=true'; - expect(getHostNameFromReferer(inputUrl)).to.equal('prebid.org'); - inputUrl = 'http://xn--p8j9a0d9c9a.xn--q9jyb4c/'; - expect(typeof getHostNameFromReferer(inputUrl)).to.equal('string'); - - // not non-UTF char's in query / path which break if noDecodeWholeURL not set - inputUrl = 'https://prebid.org/search_results/%95x%8Em%92%CA/?category=000'; - expect(getHostNameFromReferer(inputUrl)).to.equal('prebid.org'); - }); -}); diff --git a/test/spec/modules/rubiconAnalyticsSchema.json b/test/spec/modules/rubiconAnalyticsSchema.json deleted file mode 100644 index 2d0dca42d23..00000000000 --- a/test/spec/modules/rubiconAnalyticsSchema.json +++ /dev/null @@ -1,494 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Prebid Auctions", - "description": "A batched data object describing the lifecycle of an auction or multiple auction across a single page view.", - "type": "object", - "required": [ - "integration", - "version" - ], - "anyOf": [ - { - "required": [ - "auctions" - ] - }, - { - "required": [ - "bidsWon" - ] - }, - { - "required": [ - "billableEvents" - ] - } - ], - "properties": { - "integration": { - "type": "string", - "description": "Integration type that generated this event.", - "default": "pbjs" - }, - "version": { - "type": "string", - "description": "Version of Prebid.js responsible for the auctions contained within." - }, - "fpkvs": { - "type": "array", - "description": "List of any dynamic key value pairs set by publisher.", - "minItems": 1, - "items": { - "type": "object", - "required": [ - "key", - "value" - ], - "properties": { - "key": { - "type": "string" - }, - "value": { - "type": "string" - } - } - } - }, - "session": { - "type": "object", - "description": "The session information for a given event", - "required": [ - "id", - "start", - "expires" - ], - "properties": { - "id": { - "type": "string", - "description": "UUID of session." - }, - "start": { - "type": "integer", - "description": "Unix timestamp of time of creation for this session in milliseconds." - }, - "expires": { - "type": "integer", - "description": "Unix timestamp of the maximum allowed time in milliseconds of the session." - }, - "pvid": { - "type": "string", - "description": "id to track page view." - } - } - }, - "auctions": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "required": [ - "adUnits", - "samplingFactor" - ], - "properties": { - "clientTimeoutMillis": { - "type": "integer", - "description": "Timeout given in client for given auction in milliseconds (if applicable)." - }, - "serverTimeoutMillis": { - "type": "integer", - "description": "Timeout configured for server adapter request in milliseconds (if applicable)." - }, - "accountId": { - "type": "number", - "description": "The account id for prebid server (if applicable)." - }, - "samplingFactor": { - "$ref": "#/definitions/samplingFactor" - }, - "adUnits": { - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "description": "An array of adUnits involved in this auction.", - "required": [ - "status", - "adUnitCode", - "transactionId", - "mediaTypes", - "dimensions", - "bids" - ], - "properties": { - "status": { - "type": "string", - "description": "The status of the adUnit" - }, - "adUnitCode": { - "type": "string", - "description": "The adUnit.code identifier" - }, - "transactionId": { - "type": "string", - "description": "The UUID generated id to represent this adunit in this auction." - }, - "adSlot": { - "type": "string" - }, - "mediaTypes": { - "$ref": "#/definitions/mediaTypes" - }, - "videoAdFormat": { - "$ref": "#/definitions/videoAdFormat" - }, - "dimensions": { - "type": "array", - "description": "All valid sizes included in this auction (note: may be sizeConfig filtered).", - "minItems": 1, - "items": { - "$ref": "#/definitions/dimensions" - } - }, - "adserverTargeting": { - "$ref": "#/definitions/adserverTargeting" - }, - "bids": { - "type": "array", - "description": "An array that contains a combination of the bids from the adUnit combined with their responses.", - "minItems": 1, - "items": { - "$ref": "#/definitions/bid" - } - }, - "accountId": { - "type": "number", - "description": "The Rubicon AccountId associated with this adUnit - Removed if null" - }, - "siteId": { - "type": "number", - "description": "The Rubicon siteId associated with this adUnit - Removed if null" - }, - "zoneId": { - "type": "number", - "description": "The Rubicon zoneId associated with this adUnit - Removed if null" - }, - "gam": { - "$ref": "#/definitions/gam" - } - } - } - } - } - } - }, - "bidsWon": { - "type": "array", - "minItems": 1, - "items": { - "allOf": [ - { - "$ref": "#/definitions/bid" - }, - { - "required": [ - "transactionId", - "accountId", - "samplingFactor", - "mediaTypes", - "adUnitCode", - "bidwonStatus" - ], - "properties": { - "transactionId": { - "type": "string" - }, - "accountId": { - "type": "number" - }, - "samplingFactor": { - "$ref": "#/definitions/samplingFactor" - }, - "adUnitCode": { - "type": "string" - }, - "videoAdFormat": { - "$ref": "#/definitions/videoAdFormat" - }, - "mediaTypes": { - "$ref": "#/definitions/mediaTypes" - }, - "adserverTargeting": { - "$ref": "#/definitions/adserverTargeting" - }, - "bidwonStatus": { - "description": "Whether the bid was successfully rendered or not", - "type": "string", - "enum": [ - "success", - "error" - ] - }, - "siteId": { - "type": "number", - "description": "The Rubicon siteId associated with this adUnit - Removed if null" - }, - "zoneId": { - "type": "number", - "description": "The Rubicon zoneId associated with this adUnit - Removed if null" - } - } - } - ] - } - }, - "billableEvents":{ - "type":"array", - "minItems":1, - "items":{ - "type":"object", - "required":[ - "accountId", - "vendor", - "type", - "billingId" - ], - "properties":{ - "vendor":{ - "type":"string", - "description":"The name of the vendor who emitted the billable event" - }, - "type":{ - "type":"string", - "description":"The type of billable event", - "enum":[ - "impression", - "pageLoad", - "auction", - "request", - "general" - ] - }, - "billingId":{ - "type":"string", - "description":"A UUID which is responsible more mapping this event to" - }, - "accountId": { - "type": "number", - "description": "The account id for the rubicon publisher" - } - } - } - } - }, - "definitions": { - "gam": { - "type": "object", - "description": "The gam information for a given ad unit", - "required": [ - "adSlot" - ], - "properties": { - "adSlot": { - "type": "string" - }, - "advertiserId": { - "type": "integer" - }, - "creativeId": { - "type": "integer" - }, - "LineItemId": { - "type": "integer" - }, - "isSlotEmpty": { - "type": "boolean", - "enum": [ - true - ] - } - } - }, - "adserverTargeting": { - "type": "object", - "description": "The adserverTargeting key/value pairs", - "patternProperties": { - ".+": { - "type": "string" - } - } - }, - "samplingFactor": { - "type": "integer", - "description": "An integer value representing the factor to multiply event count by to receive unsampled count.", - "enum": [ - 1, - 10, - 20, - 40, - 100 - ] - }, - "videoAdFormat": { - "type": "string", - "description": "This value only provided for video specifies the ad format", - "enum": [ - "pre-roll", - "interstitial", - "outstream", - "mid-roll", - "post-roll", - "vertical" - ] - }, - "mediaTypes": { - "type": "array", - "uniqueItems": true, - "minItems": 1, - "items": { - "type": "string", - "enum": [ - "native", - "video", - "banner" - ] - } - }, - "dimensions": { - "type": "object", - "description": "Size object representing the dimensions of creative in pixels.", - "required": [ - "width", - "height" - ], - "properties": { - "width": { - "type": "integer", - "minimum": 1 - }, - "height": { - "type": "integer", - "minimum": 1 - } - } - }, - "bid": { - "type": "object", - "required": [ - "bidder", - "bidId", - "status", - "source" - ], - "properties": { - "bidder": { - "type": "string" - }, - "bidId": { - "type": "string", - "description": "UUID representing this individual bid request in this auction." - }, - "params": { - "description": "A copy of the bid.params from the adUnit.bids", - "anyOf": [ - { - "type": "object" - }, - { - "$ref": "#/definitions/params/rubicon" - } - ] - }, - "status": { - "type": "string", - "enum": [ - "success", - "no-bid", - "error", - "rejected-gdpr", - "rejected-ipf" - ] - }, - "error": { - "type": "object", - "additionalProperties": false, - "required": [ - "code" - ], - "properties": { - "code": { - "type": "string", - "enum": [ - "request-error", - "connect-error", - "timeout-error" - ] - }, - "description": { - "type": "string" - } - } - }, - "source": { - "type": "string", - "enum": [ - "client", - "server" - ] - }, - "clientLatencyMillis": { - "type": "integer", - "description": "Latency from auction start to bid response recieved in milliseconds." - }, - "serverLatencyMillis": { - "type": "integer", - "description": "Latency returned by prebid server (response_time_ms)." - }, - "bidResponse": { - "type": "object", - "required": [ - "mediaType", - "bidPriceUSD" - ], - "properties": { - "dimensions": { - "$ref": "#/definitions/dimensions" - }, - "mediaType": { - "type": "string", - "enum": [ - "native", - "video", - "banner" - ] - }, - "bidPriceUSD": { - "type": "number", - "description": "The bid value denoted in USD" - }, - "dealId": { - "type": "integer", - "description": "The id associated with any potential deals" - } - } - } - } - }, - "params": { - "rubicon": { - "type": "object", - "properties": { - "accountId": { - "type": "number" - }, - "siteId": { - "type": "number" - }, - "zoneId": { - "type": "number" - } - } - } - } - } -} diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index 0c8477a0fcb..d9c3555bf03 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -87,6 +87,11 @@ describe('the rubicon adapter', function () { function getBidderRequest() { return { bidderCode: 'rubicon', + ortb2: { + source: { + tid: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + } + }, auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', bidderRequestId: '178e34bad3658f', bids: [ @@ -120,7 +125,11 @@ describe('the rubicon adapter', function () { bidId: '2ffb201a808da7', bidderRequestId: '178e34bad3658f', auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', - transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' + ortb2Imp: { + ext: { + tid: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', + } + }, } ], start: 1472239426002, @@ -319,6 +328,11 @@ describe('the rubicon adapter', function () { bidderRequest = { bidderCode: 'rubicon', auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + ortb2: { + source: { + tid: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + } + }, bidderRequestId: '178e34bad3658f', bids: [ { @@ -351,7 +365,11 @@ describe('the rubicon adapter', function () { bidId: '2ffb201a808da7', bidderRequestId: '178e34bad3658f', auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', - transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' + ortb2Imp: { + ext: { + tid: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', + } + }, } ], start: 1472239426002, @@ -436,7 +454,7 @@ describe('the rubicon adapter', function () { 'rp_secure': /[01]/, 'rand': '0.1', 'tk_flint': INTEGRATION, - 'x_source.tid': 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', + 'x_source.tid': 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', 'p_screen_res': /\d+x\d+/, 'tk_user_key': '12346', 'kw': 'a,b,c', @@ -626,7 +644,7 @@ describe('the rubicon adapter', function () { 'rp_secure': /[01]/, 'rand': '0.1', 'tk_flint': INTEGRATION, - 'x_source.tid': 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', + 'x_source.tid': 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', 'x_imp.ext.tid': 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', 'p_screen_res': /\d+x\d+/, 'tk_user_key': '12346', @@ -978,7 +996,7 @@ describe('the rubicon adapter', function () { 'rp_secure': /[01]/, 'rand': '0.1', 'tk_flint': INTEGRATION, - 'x_source.tid': 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', + 'x_source.tid': 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', 'p_screen_res': /\d+x\d+/, 'tk_user_key': '12346', 'kw': 'a,b,c', @@ -2285,6 +2303,7 @@ describe('the rubicon adapter', function () { describe('createSlotParams', function () { it('should return a valid slot params object', function () { + const localBidderRequest = Object.assign({}, bidderRequest); let expectedQuery = { 'account_id': '14062', 'site_id': '70608', @@ -2294,7 +2313,7 @@ describe('the rubicon adapter', function () { 'p_pos': 'atf', 'rp_secure': /[01]/, 'tk_flint': INTEGRATION, - 'x_source.tid': 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b', + 'x_source.tid': 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', 'p_screen_res': /\d+x\d+/, 'tk_user_key': '12346', 'kw': 'a,b,c', @@ -2307,7 +2326,7 @@ describe('the rubicon adapter', function () { 'rf': 'localhost' }; - const slotParams = spec.createSlotParams(bidderRequest.bids[0], bidderRequest); + const slotParams = spec.createSlotParams(bidderRequest.bids[0], localBidderRequest); // test that all values above are both present and correct Object.keys(expectedQuery).forEach(key => { diff --git a/test/spec/modules/scatteredBidAdapter_spec.js b/test/spec/modules/scatteredBidAdapter_spec.js index 7f0b13bc07b..1db2d98d326 100644 --- a/test/spec/modules/scatteredBidAdapter_spec.js +++ b/test/spec/modules/scatteredBidAdapter_spec.js @@ -97,9 +97,7 @@ describe('Scattered adapter', function () { it('has the right fields filled', function () { let request = spec.buildRequests(arrayOfValidBidRequests, validBidderRequest); const bidderRequest = request.data; - assert.equal(bidderRequest.id, validBidderRequest.auctionId); assert.ok(bidderRequest.site); - assert.ok(bidderRequest.source); assert.lengthOf(bidderRequest.imp, 1); }); diff --git a/test/spec/modules/seedingAllianceAdapter_spec.js b/test/spec/modules/seedingAllianceAdapter_spec.js index 6086db01de4..03548cf923a 100755 --- a/test/spec/modules/seedingAllianceAdapter_spec.js +++ b/test/spec/modules/seedingAllianceAdapter_spec.js @@ -49,17 +49,6 @@ describe('SeedingAlliance adapter', function () { assert.deepEqual(keys, data); }); - it('Verify the auction ID', function () { - let validBidRequests = [{ - bidId: 'bidId', - params: {}, - auctionId: 'auctionId' - }]; - let request = JSON.parse(spec.buildRequests(validBidRequests, { refererInfo: { referer: 'page' }, auctionId: validBidRequests[0].auctionId }).data); - - assert.equal(request.id, validBidRequests[0].auctionId); - }); - it('Verify the site url', function () { let siteUrl = 'https://www.yourdomain.tld/your-directory/'; let validBidRequests = [{ @@ -189,7 +178,6 @@ describe('SeedingAlliance adapter', function () { const resultNative = spec.interpretResponse(goodNativeResponse, bidNativeRequest); const bidNative = goodNativeResponse.body.seatbid[0].bid[0]; - assert.deepEqual(resultNative[0].bidderCode, 'seedingAlliance'); assert.deepEqual(resultNative[0].currency, goodNativeResponse.body.cur); assert.deepEqual(resultNative[0].requestId, bidNativeRequest.bidRequests[0].bidId); assert.deepEqual(resultNative[0].cpm, bidNative.price); @@ -198,7 +186,6 @@ describe('SeedingAlliance adapter', function () { const resultBanner = spec.interpretResponse(goodBannerResponse, bidBannerRequest); - assert.deepEqual(resultBanner[0].bidderCode, 'seedingAlliance'); assert.deepEqual(resultBanner[0].mediaType, 'banner'); assert.deepEqual(resultBanner[0].width, bidBannerRequest.bidRequests[0].sizes[0]); assert.deepEqual(resultBanner[0].height, bidBannerRequest.bidRequests[0].sizes[1]); diff --git a/test/spec/modules/seedtagBidAdapter_spec.js b/test/spec/modules/seedtagBidAdapter_spec.js index 3627296975b..fb666e89f73 100644 --- a/test/spec/modules/seedtagBidAdapter_spec.js +++ b/test/spec/modules/seedtagBidAdapter_spec.js @@ -20,7 +20,11 @@ function getSlotConfigs(mediaTypes, params) { bidder: 'seedtag', mediaTypes: mediaTypes, src: 'client', - transactionId: 'd704d006-0d6e-4a09-ad6c-179e7e758096', + ortb2Imp: { + ext: { + tid: 'd704d006-0d6e-4a09-ad6c-179e7e758096', + } + }, adUnitCode: 'adunit-code', }; } diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js index c14b1fccf09..5b7e5b6b956 100644 --- a/test/spec/modules/sharethroughBidAdapter_spec.js +++ b/test/spec/modules/sharethroughBidAdapter_spec.js @@ -248,7 +248,11 @@ describe('sharethrough adapter spec', function () { refererInfo: { ref: 'https://referer.com', }, - auctionId: 'auction-id', + ortb2: { + source: { + tid: 'auction-id' + } + }, timeout: 242 }; }); @@ -311,7 +315,7 @@ describe('sharethrough adapter spec', function () { expect(openRtbReq.device.ua).to.equal(navigator.userAgent); expect(openRtbReq.regs.coppa).to.equal(1); - expect(openRtbReq.source.tid).to.equal(bidderRequest.auctionId); + expect(openRtbReq.source.tid).to.equal(bidderRequest.ortb2.source.tid); expect(openRtbReq.source.ext.version).not.to.be.undefined; expect(openRtbReq.source.ext.str).not.to.be.undefined; expect(openRtbReq.source.ext.schain).to.deep.equal(bidRequests[0].schain); diff --git a/test/spec/modules/sizeMapping_spec.js b/test/spec/modules/sizeMapping_spec.js new file mode 100644 index 00000000000..55b536868e6 --- /dev/null +++ b/test/spec/modules/sizeMapping_spec.js @@ -0,0 +1,342 @@ +import {expect} from 'chai'; +import {resolveStatus, setSizeConfig, sizeSupported} from 'modules/sizeMapping.js'; +import {includes} from 'src/polyfill.js'; + +let utils = require('src/utils.js'); +let deepClone = utils.deepClone; + +describe('sizeMapping', function () { + var sizeConfig = [{ + 'mediaQuery': '(min-width: 1200px)', + 'sizesSupported': [ + [970, 90], + [728, 90], + [300, 250] + ] + }, { + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': [ + [728, 90], + [300, 250], + [300, 100] + ] + }, { + 'mediaQuery': '(min-width: 0px) and (max-width: 767px)', + 'sizesSupported': [] + }]; + + var sizeConfigWithLabels = [{ + 'mediaQuery': '(min-width: 1200px)', + 'labels': ['desktop'] + }, { + 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', + 'sizesSupported': [ + [728, 90], + [300, 250] + ], + 'labels': ['tablet', 'phone'] + }, { + 'mediaQuery': '(min-width: 0px) and (max-width: 767px)', + 'sizesSupported': [ + [300, 250], + [300, 100] + ], + 'labels': ['phone'] + }]; + + let sandbox, + matchMediaOverride; + + beforeEach(function () { + setSizeConfig(sizeConfig); + + sandbox = sinon.sandbox.create(); + + matchMediaOverride = {matches: false}; + + sandbox.stub(utils.getWindowTop(), 'matchMedia').callsFake((...args) => { + if (typeof matchMediaOverride === 'function') { + return matchMediaOverride.apply(utils.getWindowTop(), args); + } + return matchMediaOverride; + }); + }); + + afterEach(function () { + setSizeConfig([]); + + sandbox.restore(); + }); + + describe('sizeConfig', () => { + it('should allow us to validate a single size', function () { + matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; + + expect(sizeSupported([300, 250])).to.equal(true); + expect(sizeSupported([80, 80])).to.equal(false); + }); + + it('should log a warning when mediaQuery property missing from sizeConfig', function () { + let errorConfig = deepClone(sizeConfig); + + delete errorConfig[0].mediaQuery; + + sandbox.stub(utils, 'logWarn'); + + resolveStatus(undefined, {}, errorConfig); + expect(utils.logWarn.firstCall.args[0]).to.match(/missing.+?mediaQuery/); + }); + + it('should log a warning message when mediaQuery property is declared as an empty string', function () { + const errorConfig = deepClone(sizeConfig); + errorConfig[0].mediaQuery = ''; + + sandbox.stub(utils, 'logWarn'); + resolveStatus(undefined, {}, errorConfig); + expect(utils.logWarn.firstCall.args[0]).to.match(/missing.+?mediaQuery/); + }); + }); + + const TEST_SIZES = [[970, 90], [728, 90], [300, 250], [300, 100], [80, 80]]; + + const suites = { + banner: { + mediaTypes: { + banner: { + sizes: TEST_SIZES + } + }, + getSizes(mediaTypes) { + return mediaTypes.banner.sizes; + }, + } + } + if (FEATURES.VIDEO) { + suites.video = { + mediaTypes: { + video: { + playerSize: TEST_SIZES + } + }, + getSizes(mediaTypes) { + return mediaTypes.video.playerSize; + } + } + } + Object.entries(suites).forEach(([mediaType, {mediaTypes, getSizes}]) => { + describe(`for ${mediaType}`, () => { + describe('when handling sizes', function () { + it('when one mediaQuery block matches, it should filter the adUnit.sizes passed in', function () { + matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; + + let status = resolveStatus(undefined, mediaTypes, sizeConfig); + + expect(status.active).to.equal(true); + expect(getSizes(status.mediaTypes)).to.deep.equal( + [[970, 90], [728, 90], [300, 250]] + ); + }); + + it('when multiple mediaQuery block matches, it should filter a union of the matched sizesSupported', function () { + matchMediaOverride = (str) => includes([ + '(min-width: 1200px)', + '(min-width: 768px) and (max-width: 1199px)' + ], str) ? {matches: true} : {matches: false}; + + let status = resolveStatus(undefined, mediaTypes, sizeConfig); + expect(status.active).to.equal(true); + expect(getSizes(status.mediaTypes)).to.deep.equal( + [[970, 90], [728, 90], [300, 250], [300, 100]] + ); + }); + + it('if no mediaQueries match, it should allow all sizes specified', function () { + matchMediaOverride = () => ({matches: false}); + + let status = resolveStatus(undefined, mediaTypes, sizeConfig); + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal(mediaTypes); + }); + + it('if a mediaQuery matches and has sizesSupported: [], it should filter all sizes', function () { + matchMediaOverride = (str) => str === '(min-width: 0px) and (max-width: 767px)' ? {matches: true} : {matches: false}; + + let status = resolveStatus(undefined, mediaTypes, sizeConfig); + expect(status.active).to.equal(false); + expect(getSizes(status.mediaTypes)).to.deep.equal([]); + }); + + it('should filter all banner sizes and should disable the adUnit even if other mediaTypes are present', function () { + matchMediaOverride = (str) => str === '(min-width: 0px) and (max-width: 767px)' ? {matches: true} : {matches: false}; + let status = resolveStatus(undefined, Object.assign({}, mediaTypes, { + native: { + type: 'image' + } + }), sizeConfig); + expect(status.active).to.equal(false); + expect(getSizes(status.mediaTypes)).to.deep.equal([]); + expect(status.mediaTypes.native).to.deep.equal({ + type: 'image' + }); + }); + + it('if a mediaQuery matches and no sizesSupported specified, it should not affect adUnit.sizes', function () { + matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; + + let status = resolveStatus(undefined, mediaTypes, sizeConfigWithLabels); + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal(mediaTypes); + }); + }); + + describe('when handling labels', function () { + it('should activate/deactivate adUnits/bidders based on sizeConfig.labels', function () { + matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; + + let status = resolveStatus({ + labels: ['desktop'] + }, mediaTypes, sizeConfigWithLabels); + + expect(status).to.deep.equal({ + active: true, + mediaTypes: mediaTypes + }); + + status = resolveStatus({ + labels: ['tablet'] + }, mediaTypes, sizeConfigWithLabels); + + expect(status.active).to.equal(false); + expect(status.mediaTypes).to.deep.equal(mediaTypes); + }); + + it('should active/deactivate adUnits/bidders based on requestBids labels', function () { + let activeLabels = ['us-visitor', 'desktop', 'smart']; + + let status = resolveStatus({ + labels: ['uk-visitor'], // from adunit + activeLabels // from requestBids.labels + }, mediaTypes, sizeConfigWithLabels); + + expect(status.active).to.equal(false); + expect(status.mediaTypes).to.deep.equal(mediaTypes); + + status = resolveStatus({ + labels: ['us-visitor'], + activeLabels + }, mediaTypes, sizeConfigWithLabels); + + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal(mediaTypes); + + status = resolveStatus({ + labels: ['us-visitor', 'tablet'], + labelAll: true, + activeLabels + }, mediaTypes, sizeConfigWithLabels); + + expect(status.active).to.equal(false); + expect(status.mediaTypes).to.deep.equal(mediaTypes); + + status = resolveStatus({ + labels: ['us-visitor', 'desktop'], + labelAll: true, + activeLabels + }, mediaTypes, undefined, sizeConfigWithLabels); + + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal(mediaTypes); + }); + }); + }); + }); + + if (FEATURES.VIDEO) { + it('should activate/decactivate adUnits/bidders based on labels with multiformat ads', function () { + matchMediaOverride = (str) => str === '(min-width: 768px) and (max-width: 1199px)' ? {matches: true} : {matches: false}; + + let multiFormatSizes = { + banner: { + sizes: [[728, 90], [300, 300]] + }, + native: { + type: 'image' + }, + video: { + context: 'outstream', + playerSize: [[728, 90], [300, 300]] + } + }; + + let status = resolveStatus({ + labels: ['tablet', 'test'], + labelAll: true + }, multiFormatSizes, sizeConfigWithLabels); + + expect(status.active).to.equal(false); + expect(status.mediaTypes).to.deep.equal({ + banner: { + sizes: [[728, 90]] + }, + native: { + type: 'image' + }, + video: { + context: 'outstream', + playerSize: [[728, 90]] + } + }); + + status = resolveStatus({ + labels: ['tablet'] + }, multiFormatSizes, sizeConfigWithLabels); + + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal({ + banner: { + sizes: [[728, 90]] + }, + native: { + type: 'image' + }, + video: { + context: 'outstream', + playerSize: [[728, 90]] + } + }); + + [multiFormatSizes.banner.sizes, multiFormatSizes.video.playerSize].forEach(sz => sz.splice(0, 1, [728, 80])) + status = resolveStatus({ + labels: ['tablet'] + }, multiFormatSizes, sizeConfigWithLabels); + + expect(status.active).to.equal(false); + expect(status.mediaTypes).to.deep.equal({ + banner: { + sizes: [] + }, + native: { + type: 'image' + }, + video: { + context: 'outstream', + playerSize: [] + } + }); + + delete multiFormatSizes.banner; + delete multiFormatSizes.video; + + status = resolveStatus({ + labels: ['tablet'] + }, multiFormatSizes, sizeConfigWithLabels); + + expect(status.active).to.equal(true); + expect(status.mediaTypes).to.deep.equal({ + native: { + type: 'image' + } + }); + }); + } +}); diff --git a/test/spec/modules/slimcutBidAdapter_spec.js b/test/spec/modules/slimcutBidAdapter_spec.js index d821627c24b..da0fee48936 100644 --- a/test/spec/modules/slimcutBidAdapter_spec.js +++ b/test/spec/modules/slimcutBidAdapter_spec.js @@ -178,7 +178,6 @@ describe('slimcutBidAdapter', function() { 'ad': AD_SCRIPT, 'requestId': '3ede2a3fa0db94', 'creativeId': 'er2ee', - 'transactionId': 'deadb33f', 'winUrl': 'https://sb.freeskreen.com/win', 'meta': { 'advertiserDomains': [] diff --git a/test/spec/modules/smaatoBidAdapter_spec.js b/test/spec/modules/smaatoBidAdapter_spec.js index 7f727d5d9e3..61a877f329d 100644 --- a/test/spec/modules/smaatoBidAdapter_spec.js +++ b/test/spec/modules/smaatoBidAdapter_spec.js @@ -13,6 +13,7 @@ const CONSENT_STRING = 'HFIDUYFIUYIUYWIPOI87392DSU' const AUCTION_ID = '6653'; const defaultBidderRequest = { + bidderRequestId: 'mock-uuid', gdprConsent: { consentString: CONSENT_STRING, gdprApplies: true @@ -554,7 +555,7 @@ describe('smaatoBidAdapterTest', () => { const reqs = spec.buildRequests([longFormVideoBidRequest], defaultBidderRequest); const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.id).to.be.equal(AUCTION_ID); + expect(req.id).to.exist; expect(req.imp.length).to.be.equal(ADPOD_DURATION / DURATION_RANGE[0]); expect(req.imp[0].id).to.be.equal(BID_ID); expect(req.imp[0].tagid).to.be.equal(ADBREAK_ID); @@ -658,7 +659,7 @@ describe('smaatoBidAdapterTest', () => { const reqs = spec.buildRequests([longFormVideoBidRequest], defaultBidderRequest); const req = extractPayloadOfFirstAndOnlyRequest(reqs); - expect(req.id).to.be.equal(AUCTION_ID); + expect(req.id).to.exist; expect(req.imp.length).to.be.equal(DURATION_RANGE.length); expect(req.imp[0].id).to.be.equal(BID_ID); expect(req.imp[0].tagid).to.be.equal(ADBREAK_ID); diff --git a/test/spec/modules/smartadserverBidAdapter_spec.js b/test/spec/modules/smartadserverBidAdapter_spec.js index 9142b730b27..9daa6a87826 100644 --- a/test/spec/modules/smartadserverBidAdapter_spec.js +++ b/test/spec/modules/smartadserverBidAdapter_spec.js @@ -30,7 +30,11 @@ describe('Smart bid adapter tests', function () { ckId: 42 }, requestId: 'efgh5678', - transactionId: 'zsfgzzg' + ortb2Imp: { + ext: { + tid: 'zsfgzzg' + } + }, }]; var DEFAULT_PARAMS_WITH_EIDS = [{ @@ -587,7 +591,11 @@ describe('Smart bid adapter tests', function () { } }, requestId: 'efgh5678', - transactionId: 'zsfgzzg' + ortb2Imp: { + ext: { + tid: 'zsfgzzg', + } + }, }]; var INSTREAM_BID_RESPONSE = { @@ -856,7 +864,11 @@ describe('Smart bid adapter tests', function () { protocol: 7 } }, - requestId: 'efgh5679', + ortb2Imp: { + ext: { + tid: 'efgh5679', + } + }, transactionId: 'zsfgzzga' }]; diff --git a/test/spec/modules/smilewantedBidAdapter_spec.js b/test/spec/modules/smilewantedBidAdapter_spec.js index 44d2c7c6507..22221dbe1ef 100644 --- a/test/spec/modules/smilewantedBidAdapter_spec.js +++ b/test/spec/modules/smilewantedBidAdapter_spec.js @@ -14,7 +14,11 @@ const DISPLAY_REQUEST = [{ zoneId: 1 }, requestId: 'request_abcd1234', - transactionId: 'trans_abcd1234' + ortb2Imp: { + ext: { + tid: 'trans_abcd1234', + } + }, }]; const DISPLAY_REQUEST_WITH_EIDS = [{ @@ -29,7 +33,11 @@ const DISPLAY_REQUEST_WITH_EIDS = [{ zoneId: 1 }, requestId: 'request_abcd1234', - transactionId: 'trans_abcd1234', + ortb2Imp: { + ext: { + tid: 'trans_abcd1234', + } + }, userIdAsEids: [{ source: 'pubcid.org', uids: [{ @@ -61,7 +69,11 @@ const DISPLAY_REQUEST_WITH_POSITION_TYPE = [{ positionType: 'infeed' }, requestId: 'request_abcd1234', - transactionId: 'trans_abcd1234' + ortb2Imp: { + ext: { + tid: 'trans_abcd1234', + } + }, }]; const BID_RESPONSE_DISPLAY = { @@ -92,7 +104,11 @@ const VIDEO_INSTREAM_REQUEST = [{ bidfloor: 2.50 }, requestId: 'request_abcd1234', - transactionId: 'trans_abcd1234' + ortb2Imp: { + ext: { + tid: 'trans_abcd1234', + } + } }]; const BID_RESPONSE_VIDEO_INSTREAM = { @@ -124,7 +140,11 @@ const VIDEO_OUTSTREAM_REQUEST = [{ bidfloor: 2.50 }, requestId: 'request_abcd1234', - transactionId: 'trans_abcd1234' + ortb2Imp: { + ext: { + tid: 'trans_abcd1234', + } + } }]; const BID_RESPONSE_VIDEO_OUTSTREAM = { @@ -224,7 +244,6 @@ describe('smilewantedBidAdapterTests', function () { describe('gdpr tests', function () { afterEach(function () { config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeAll(); }); it('SmileWanted - Verify build request with GDPR', function () { diff --git a/test/spec/modules/sspBCBidAdapter_spec.js b/test/spec/modules/sspBCBidAdapter_spec.js index 8c9bbe3b336..a95f08314b5 100644 --- a/test/spec/modules/sspBCBidAdapter_spec.js +++ b/test/spec/modules/sspBCBidAdapter_spec.js @@ -611,14 +611,14 @@ describe('SSPBC adapter', function () { expect(result.length).to.equal(bids.length); expect(resultSingle.length).to.equal(1); - expect(resultSingle[0]).to.have.keys('ad', 'cpm', 'width', 'height', 'bidderCode', 'mediaType', 'meta', 'requestId', 'creativeId', 'currency', 'netRevenue', 'ttl', 'vurls'); + expect(resultSingle[0]).to.have.keys('ad', 'cpm', 'width', 'height', 'mediaType', 'meta', 'requestId', 'creativeId', 'currency', 'netRevenue', 'ttl', 'vurls'); }); it('should create bid from OneCode (parameter-less) request, if response contains siteId', function () { let resultOneCode = spec.interpretResponse(serverResponseOneCode, requestOneCode); expect(resultOneCode.length).to.equal(1); - expect(resultOneCode[0]).to.have.keys('ad', 'cpm', 'width', 'height', 'bidderCode', 'mediaType', 'meta', 'requestId', 'creativeId', 'currency', 'netRevenue', 'ttl', 'vurls'); + expect(resultOneCode[0]).to.have.keys('ad', 'cpm', 'width', 'height', 'mediaType', 'meta', 'requestId', 'creativeId', 'currency', 'netRevenue', 'ttl', 'vurls'); }); it('should not create bid from OneCode (parameter-less) request, if response does not contain siteId', function () { @@ -649,7 +649,7 @@ describe('SSPBC adapter', function () { expect(resultVideo.length).to.equal(1); let videoBid = resultVideo[0]; - expect(videoBid).to.have.keys('adType', 'bidderCode', 'cpm', 'creativeId', 'currency', 'width', 'height', 'meta', 'mediaType', 'netRevenue', 'requestId', 'ttl', 'vastContent', 'vastXml', 'vastUrl', 'vurls'); + expect(videoBid).to.have.keys('adType', 'cpm', 'creativeId', 'currency', 'width', 'height', 'meta', 'mediaType', 'netRevenue', 'requestId', 'ttl', 'vastContent', 'vastXml', 'vastUrl', 'vurls'); expect(videoBid.adType).to.equal('instream'); expect(videoBid.mediaType).to.equal('video'); expect(videoBid.vastXml).to.match(/^<\?xml.*<\/VAST>$/); @@ -663,7 +663,7 @@ describe('SSPBC adapter', function () { expect(resultNative.length).to.equal(1); let nativeBid = resultNative[0]; - expect(nativeBid).to.have.keys('bidderCode', 'cpm', 'creativeId', 'currency', 'width', 'height', 'meta', 'mediaType', 'netRevenue', 'requestId', 'ttl', 'native', 'vurls'); + expect(nativeBid).to.have.keys('cpm', 'creativeId', 'currency', 'width', 'height', 'meta', 'mediaType', 'netRevenue', 'requestId', 'ttl', 'native', 'vurls'); expect(nativeBid.native).to.have.keys('image', 'icon', 'title', 'sponsoredBy', 'body', 'clickUrl', 'impressionTrackers', 'javascriptTrackers', 'clickTrackers'); }); }); diff --git a/test/spec/modules/taboolaBidAdapter_spec.js b/test/spec/modules/taboolaBidAdapter_spec.js index 206a0142043..7d31e291667 100644 --- a/test/spec/modules/taboolaBidAdapter_spec.js +++ b/test/spec/modules/taboolaBidAdapter_spec.js @@ -5,14 +5,15 @@ import * as utils from '../../../src/utils' import {server} from '../../mocks/xhr' describe('Taboola Adapter', function () { - let hasLocalStorage, cookiesAreEnabled, getDataFromLocalStorage, localStorageIsEnabled, getCookie, commonBidRequest; + let sandbox, hasLocalStorage, cookiesAreEnabled, getDataFromLocalStorage, localStorageIsEnabled, getCookie, commonBidRequest; beforeEach(() => { - hasLocalStorage = sinon.stub(userData.storageManager, 'hasLocalStorage'); - cookiesAreEnabled = sinon.stub(userData.storageManager, 'cookiesAreEnabled'); - getCookie = sinon.stub(userData.storageManager, 'getCookie'); - getDataFromLocalStorage = sinon.stub(userData.storageManager, 'getDataFromLocalStorage'); - localStorageIsEnabled = sinon.stub(userData.storageManager, 'localStorageIsEnabled'); + sandbox = sinon.sandbox.create(); + hasLocalStorage = sandbox.stub(userData.storageManager, 'hasLocalStorage'); + cookiesAreEnabled = sandbox.stub(userData.storageManager, 'cookiesAreEnabled'); + getCookie = sandbox.stub(userData.storageManager, 'getCookie'); + getDataFromLocalStorage = sandbox.stub(userData.storageManager, 'getDataFromLocalStorage'); + localStorageIsEnabled = sandbox.stub(userData.storageManager, 'localStorageIsEnabled'); commonBidRequest = createBidRequest(); $$PREBID_GLOBAL$$.bidderSettings = { taboola: { @@ -22,12 +23,7 @@ describe('Taboola Adapter', function () { }); afterEach(() => { - hasLocalStorage.restore(); - cookiesAreEnabled.restore(); - getCookie.restore(); - getDataFromLocalStorage.restore(); - localStorageIsEnabled.restore(); - + sandbox.restore(); $$PREBID_GLOBAL$$.bidderSettings = {}; }) @@ -124,6 +120,7 @@ describe('Taboola Adapter', function () { } const commonBidderRequest = { + bidderRequestId: 'mock-uuid', refererInfo: { page: 'https://example.com/ref', ref: 'https://ref', @@ -133,6 +130,7 @@ describe('Taboola Adapter', function () { it('should build display request', function () { const expectedData = { + id: 'mock-uuid', 'imp': [{ 'id': 1, 'banner': { diff --git a/test/spec/modules/terceptAnalyticsAdapter_spec.js b/test/spec/modules/terceptAnalyticsAdapter_spec.js index 594e1e5f5b4..a1384bfd919 100644 --- a/test/spec/modules/terceptAnalyticsAdapter_spec.js +++ b/test/spec/modules/terceptAnalyticsAdapter_spec.js @@ -709,7 +709,6 @@ describe('tercept analytics adapter', function () { 'bidsReceived': [], 'winningBids': [], 'timeout': 1000, - 'config': initOptions }, 'initOptions': initOptions }; diff --git a/test/spec/modules/trustpidSystem_spec.js b/test/spec/modules/trustpidSystem_spec.js deleted file mode 100644 index 38e861d977f..00000000000 --- a/test/spec/modules/trustpidSystem_spec.js +++ /dev/null @@ -1,237 +0,0 @@ -import { expect } from 'chai'; -import { trustpidSubmodule } from 'modules/trustpidSystem.js'; -import { storage } from 'modules/trustpidSystem.js'; - -describe('trustpid System', () => { - const connectDataKey = 'fcIdConnectData'; - const connectDomainKey = 'fcIdConnectDomain'; - - const getStorageData = (idGraph) => { - if (!idGraph) { - idGraph = {id: 501, domain: ''}; - } - return { - 'connectId': { - 'idGraph': [idGraph], - } - } - }; - - it('should have the correct module name declared', () => { - expect(trustpidSubmodule.name).to.equal('trustpid'); - }); - - describe('trustpid getId()', () => { - afterEach(() => { - storage.removeDataFromLocalStorage(connectDataKey); - storage.removeDataFromLocalStorage(connectDomainKey); - }); - - after(() => { - window.FC_CONF = {}; - }) - - it('it should return object with key callback', () => { - expect(trustpidSubmodule.getId()).to.have.property('callback'); - }); - - it('should return object with key callback with value type - function', () => { - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData())); - expect(trustpidSubmodule.getId()).to.have.property('callback'); - expect(typeof trustpidSubmodule.getId().callback).to.be.equal('function'); - }); - - it('tests if localstorage & JSON works properly ', () => { - const idGraph = { - 'domain': 'domainValue', - 'atid': 'atidValue', - }; - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - expect(JSON.parse(storage.getDataFromLocalStorage(connectDataKey))).to.have.property('connectId'); - }); - - it('returns {callback: func} if domains don\'t match', () => { - const idGraph = { - 'domain': 'domainValue', - 'atid': 'atidValue', - }; - storage.setDataInLocalStorage(connectDomainKey, JSON.stringify('differentDomainValue')); - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - expect(trustpidSubmodule.getId()).to.have.property('callback'); - }); - - it('returns {id: {trustpid: data.trustpid}} if we have the right data stored in the localstorage ', () => { - const idGraph = { - 'domain': 'test.domain', - 'atid': 'atidValue', - }; - storage.setDataInLocalStorage(connectDomainKey, JSON.stringify('test.domain')); - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - const response = trustpidSubmodule.getId(); - expect(response).to.have.property('id'); - expect(response.id).to.have.property('trustpid'); - expect(response.id.trustpid).to.be.equal('atidValue'); - }); - - it('returns {trustpid: data.trustpid} if we have the right data stored in the localstorage right after the callback is called', (done) => { - const idGraph = { - 'domain': 'test.domain', - 'atid': 'atidValue', - }; - const response = trustpidSubmodule.getId(); - expect(response).to.have.property('callback'); - expect(response.callback.toString()).contain('result(callback)'); - - if (typeof response.callback === 'function') { - storage.setDataInLocalStorage(connectDomainKey, JSON.stringify('test.domain')); - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - response.callback(function (result) { - expect(result).to.not.be.null; - expect(result).to.have.property('trustpid'); - expect(result.trustpid).to.be.equal('atidValue'); - done() - }) - } - }); - - it('returns null if domains don\'t match', (done) => { - const idGraph = { - 'domain': 'test.domain', - 'atid': 'atidValue', - }; - storage.setDataInLocalStorage(connectDomainKey, JSON.stringify('differentDomainValue')); - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - - const response = trustpidSubmodule.getId(); - expect(response).to.have.property('callback'); - expect(response.callback.toString()).contain('result(callback)'); - - if (typeof response.callback === 'function') { - setTimeout(() => { - expect(JSON.parse(storage.getDataFromLocalStorage(connectDomainKey))).to.be.equal('differentDomainValue'); - }, 100) - response.callback(function (result) { - expect(result).to.be.null; - done() - }) - } - }); - - it('returns {trustpid: data.trustpid} if we have the right data stored in the localstorage right after 500ms delay', (done) => { - const idGraph = { - 'domain': 'test.domain', - 'atid': 'atidValue', - }; - - const response = trustpidSubmodule.getId(); - expect(response).to.have.property('callback'); - expect(response.callback.toString()).contain('result(callback)'); - - if (typeof response.callback === 'function') { - setTimeout(() => { - storage.setDataInLocalStorage(connectDomainKey, JSON.stringify('test.domain')); - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - }, 500); - response.callback(function (result) { - expect(result).to.not.be.null; - expect(result).to.have.property('trustpid'); - expect(result.trustpid).to.be.equal('atidValue'); - done() - }) - } - }); - - it('returns null if we have the data stored in the localstorage after 500ms delay and the max (waiting) delay is only 200ms ', (done) => { - const idGraph = { - 'domain': 'test.domain', - 'atid': 'atidValue', - }; - - const response = trustpidSubmodule.getId({params: {maxDelayTime: 200}}); - expect(response).to.have.property('callback'); - expect(response.callback.toString()).contain('result(callback)'); - - if (typeof response.callback === 'function') { - setTimeout(() => { - storage.setDataInLocalStorage(connectDomainKey, JSON.stringify('test.domain')); - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - }, 500); - response.callback(function (result) { - expect(result).to.be.null; - done() - }) - } - }); - }); - - describe('trustpid decode()', () => { - const VALID_API_RESPONSES = [ - { - expected: '32a97f612', - payload: { - trustpid: '32a97f612' - } - }, - { - expected: '32a97f61', - payload: { - trustpid: '32a97f61', - } - }, - ]; - VALID_API_RESPONSES.forEach(responseData => { - it('should return a newly constructed object with the trustpid for a payload with {trustpid: value}', () => { - expect(trustpidSubmodule.decode(responseData.payload)).to.deep.equal( - {trustpid: responseData.expected} - ); - }); - }); - - [{}, '', {foo: 'bar'}].forEach((response) => { - it(`should return null for an invalid response "${JSON.stringify(response)}"`, () => { - expect(trustpidSubmodule.decode(response)).to.be.null; - }); - }); - }); - - describe('trustpid messageHandler', () => { - afterEach(() => { - storage.removeDataFromLocalStorage(connectDataKey); - storage.removeDataFromLocalStorage(connectDomainKey); - }); - - after(() => { - window.FC_CONF = {}; - }) - - const domains = [ - 'domain1', - 'domain2', - 'domain3', - ]; - - domains.forEach(domain => { - it(`correctly sets trustpid value for domain name ${domain}`, (done) => { - const idGraph = { - 'domain': domain, - 'atid': 'atidValue', - }; - - storage.setDataInLocalStorage(connectDomainKey, JSON.stringify(domain)); - storage.setDataInLocalStorage(connectDataKey, JSON.stringify(getStorageData(idGraph))); - - const eventData = { - data: `{\"msgType\":\"MNOSELECTOR\",\"body\":{\"url\":\"https://${domain}/some/path\"}}` - }; - - window.dispatchEvent(new MessageEvent('message', eventData)); - - const response = trustpidSubmodule.getId(); - expect(response).to.have.property('id'); - expect(response.id).to.have.property('trustpid'); - expect(response.id.trustpid).to.be.equal('atidValue'); - done(); - }); - }); - }); -}); diff --git a/test/spec/modules/ttdBidAdapter_spec.js b/test/spec/modules/ttdBidAdapter_spec.js index 5e472543a01..56c506dea6b 100644 --- a/test/spec/modules/ttdBidAdapter_spec.js +++ b/test/spec/modules/ttdBidAdapter_spec.js @@ -223,7 +223,11 @@ describe('ttdBidAdapter', function () { const baseBidderRequestReferer = detectReferer(testWindow)(); const baseBidderRequest = { 'bidderCode': 'ttd', - 'auctionId': 'e7b34fa3-8654-424e-8c49-03e509e53d8c', + ortb2: { + source: { + tid: 'e7b34fa3-8654-424e-8c49-03e509e53d8c', + } + }, 'bidderRequestId': '18084284054531', 'auctionStart': 1540945362095, 'timeout': 3000, @@ -320,10 +324,10 @@ describe('ttdBidAdapter', function () { expect(requestBody.imp[0].rwdd).to.equal(1); }); - it('sends auction id in source.tid', function () { + it('sends source.tid', function () { const requestBody = testBuildRequests(baseBannerBidRequests, baseBidderRequest).data; expect(requestBody.source).to.be.not.null; - expect(requestBody.source.tid).to.equal(baseBidderRequest.auctionId); + expect(requestBody.source.tid).to.equal(baseBidderRequest.ortb2.source.tid); }); it('includes the ad size in the bid request', function () { @@ -756,7 +760,11 @@ describe('ttdBidAdapter', function () { const baseBidderRequest = { 'bidderCode': 'ttd', - 'auctionId': 'e7b34fa3-8654-424e-8c49-03e509e53d8c', + ortb2: { + source: { + tid: 'e7b34fa3-8654-424e-8c49-03e509e53d8c', + } + }, 'bidderRequestId': '18084284054531', 'auctionStart': 1540945362095, 'timeout': 3000, @@ -776,7 +784,7 @@ describe('ttdBidAdapter', function () { const requestBody = testBuildRequests(baseBannerMultipleBidRequests, baseBidderRequest).data; expect(requestBody.imp.length).to.equal(2); expect(requestBody.source).to.be.not.null; - expect(requestBody.source.tid).to.equal(baseBidderRequest.auctionId); + expect(requestBody.source.tid).to.equal(baseBidderRequest.ortb2.source.tid); expect(requestBody.imp[0].ext).to.be.not.null; expect(requestBody.imp[0].ext.tid).to.equal('8651474f-58b1-4368-b812-84f8c937a099'); expect(requestBody.imp[1].ext).to.be.not.null; diff --git a/test/spec/modules/uid2IdSystem_spec.js b/test/spec/modules/uid2IdSystem_spec.js index 400e8988493..20a38a292bb 100644 --- a/test/spec/modules/uid2IdSystem_spec.js +++ b/test/spec/modules/uid2IdSystem_spec.js @@ -170,16 +170,6 @@ describe(`UID2 module`, function () { expectLegacyToken(bid); }); - it('When a legacy value is provided directly in configuration but GDPR applies, it is not passed on', async function() { - const valueConfig = makePrebidConfig(); - setGdprApplies(); - valueConfig.userSync.userIds[0].value = {uid2: {id: legacyToken}} - config.setConfig(valueConfig); - const bid = await runAuction(); - - expectNoIdentity(bid); - }); - // These tests cover 'legacy' cookies - i.e. cookies set with just the uid2 advertising token, which was how some previous integrations worked. // Some users might still have this cookie, and the module should use that token if a newer one isn't provided. // This should cover older integrations where the server is setting this legacy cookie and expecting the module to pass it on. diff --git a/test/spec/modules/underdogmediaBidAdapter_spec.js b/test/spec/modules/underdogmediaBidAdapter_spec.js index 040d85f9179..2d7c1f11178 100644 --- a/test/spec/modules/underdogmediaBidAdapter_spec.js +++ b/test/spec/modules/underdogmediaBidAdapter_spec.js @@ -967,7 +967,6 @@ describe('UnderdogMedia adapter', function () { expect(bids).to.be.lengthOf(2); expect(bids[0].meta.advertiserDomains).to.deep.equal(['domain1']) - expect(bids[0].bidderCode).to.equal('underdogmedia'); expect(bids[0].cpm).to.equal(2.5); expect(bids[0].width).to.equal('160'); expect(bids[0].height).to.equal('600'); diff --git a/test/spec/modules/utiqSystem_spec.js b/test/spec/modules/utiqSystem_spec.js new file mode 100644 index 00000000000..afeeea7c3ea --- /dev/null +++ b/test/spec/modules/utiqSystem_spec.js @@ -0,0 +1,188 @@ +import { expect } from 'chai'; +import { utiqSubmodule } from 'modules/utiqSystem.js'; +import { storage } from 'modules/utiqSystem.js'; + +describe('utiqSystem', () => { + const utiqPassKey = 'utiqPass'; + + const getStorageData = (idGraph) => { + if (!idGraph) { + idGraph = {id: 501, domain: ''}; + } + return { + 'connectId': { + 'idGraph': [idGraph], + } + } + }; + + it('should have the correct module name declared', () => { + expect(utiqSubmodule.name).to.equal('utiq'); + }); + + describe('utiq getId()', () => { + afterEach(() => { + storage.removeDataFromLocalStorage(utiqPassKey); + }); + + it('it should return object with key callback', () => { + expect(utiqSubmodule.getId()).to.have.property('callback'); + }); + + it('should return object with key callback with value type - function', () => { + storage.setDataInLocalStorage(utiqPassKey, JSON.stringify(getStorageData())); + expect(utiqSubmodule.getId()).to.have.property('callback'); + expect(typeof utiqSubmodule.getId().callback).to.be.equal('function'); + }); + + it('tests if localstorage & JSON works properly ', () => { + const idGraph = { + 'domain': 'domainValue', + 'atid': 'atidValue', + }; + storage.setDataInLocalStorage(utiqPassKey, JSON.stringify(getStorageData(idGraph))); + expect(JSON.parse(storage.getDataFromLocalStorage(utiqPassKey))).to.have.property('connectId'); + }); + + it('returns {id: {utiq: data.utiq}} if we have the right data stored in the localstorage ', () => { + const idGraph = { + 'domain': 'test.domain', + 'atid': 'atidValue', + }; + storage.setDataInLocalStorage(utiqPassKey, JSON.stringify(getStorageData(idGraph))); + const response = utiqSubmodule.getId(); + expect(response).to.have.property('id'); + expect(response.id).to.have.property('utiq'); + expect(response.id.utiq).to.be.equal('atidValue'); + }); + + it('returns {utiq: data.utiq} if we have the right data stored in the localstorage right after the callback is called', (done) => { + const idGraph = { + 'domain': 'test.domain', + 'atid': 'atidValue', + }; + const response = utiqSubmodule.getId(); + expect(response).to.have.property('callback'); + expect(response.callback.toString()).contain('result(callback)'); + + if (typeof response.callback === 'function') { + storage.setDataInLocalStorage(utiqPassKey, JSON.stringify(getStorageData(idGraph))); + response.callback(function (result) { + expect(result).to.not.be.null; + expect(result).to.have.property('utiq'); + expect(result.utiq).to.be.equal('atidValue'); + done() + }) + } + }); + + it('returns {utiq: data.utiq} if we have the right data stored in the localstorage right after 500ms delay', (done) => { + const idGraph = { + 'domain': 'test.domain', + 'atid': 'atidValue', + }; + + const response = utiqSubmodule.getId(); + expect(response).to.have.property('callback'); + expect(response.callback.toString()).contain('result(callback)'); + + if (typeof response.callback === 'function') { + setTimeout(() => { + storage.setDataInLocalStorage(utiqPassKey, JSON.stringify(getStorageData(idGraph))); + }, 500); + response.callback(function (result) { + expect(result).to.not.be.null; + expect(result).to.have.property('utiq'); + expect(result.utiq).to.be.equal('atidValue'); + done() + }) + } + }); + + it('returns null if we have the data stored in the localstorage after 500ms delay and the max (waiting) delay is only 200ms ', (done) => { + const idGraph = { + 'domain': 'test.domain', + 'atid': 'atidValue', + }; + + const response = utiqSubmodule.getId({params: {maxDelayTime: 200}}); + expect(response).to.have.property('callback'); + expect(response.callback.toString()).contain('result(callback)'); + + if (typeof response.callback === 'function') { + setTimeout(() => { + storage.setDataInLocalStorage(utiqPassKey, JSON.stringify(getStorageData(idGraph))); + }, 500); + response.callback(function (result) { + expect(result).to.be.null; + done() + }) + } + }); + }); + + describe('utiq decode()', () => { + const VALID_API_RESPONSES = [ + { + expected: '32a97f612', + payload: { + utiq: '32a97f612' + } + }, + { + expected: '32a97f61', + payload: { + utiq: '32a97f61', + } + }, + ]; + VALID_API_RESPONSES.forEach(responseData => { + it('should return a newly constructed object with the utiq for a payload with {utiq: value}', () => { + expect(utiqSubmodule.decode(responseData.payload)).to.deep.equal( + {utiq: responseData.expected} + ); + }); + }); + + [{}, '', {foo: 'bar'}].forEach((response) => { + it(`should return null for an invalid response "${JSON.stringify(response)}"`, () => { + expect(utiqSubmodule.decode(response)).to.be.null; + }); + }); + }); + + describe('utiq messageHandler', () => { + afterEach(() => { + storage.removeDataFromLocalStorage(utiqPassKey); + }); + + const domains = [ + 'domain1', + 'domain2', + 'domain3', + ]; + + domains.forEach(domain => { + it(`correctly sets utiq value for domain name ${domain}`, (done) => { + const idGraph = { + 'domain': domain, + 'atid': 'atidValue', + }; + + storage.setDataInLocalStorage(utiqPassKey, JSON.stringify(getStorageData(idGraph))); + + const eventData = { + data: `{\"msgType\":\"MNOSELECTOR\",\"body\":{\"url\":\"https://${domain}/some/path\"}}` + }; + + window.dispatchEvent(new MessageEvent('message', eventData)); + + const response = utiqSubmodule.getId(); + expect(response).to.have.property('id'); + expect(response.id).to.have.property('utiq'); + expect(response.id.utiq).to.be.equal('atidValue'); + done(); + }); + }); + }); +}); diff --git a/test/spec/modules/vidazooBidAdapter_spec.js b/test/spec/modules/vidazooBidAdapter_spec.js index 1ddc3058a03..6e92bae8d59 100644 --- a/test/spec/modules/vidazooBidAdapter_spec.js +++ b/test/spec/modules/vidazooBidAdapter_spec.js @@ -38,7 +38,6 @@ const BID = { } }, 'placementCode': 'div-gpt-ad-1460505748561-0', - 'transactionId': 'c881914b-a3b5-4ecf-ad9c-1c2f37c6aabf', 'sizes': [[300, 250], [300, 600]], 'bidderRequestId': '1fdb5ff1b6eaa7', 'auctionId': 'auction_id', @@ -50,6 +49,7 @@ const BID = { 'mediaTypes': [BANNER], 'ortb2Imp': { 'ext': { + tid: 'c881914b-a3b5-4ecf-ad9c-1c2f37c6aabf', 'gpid': '1234567890' } } @@ -59,7 +59,11 @@ const VIDEO_BID = { 'bidId': '2d52001cabd527', 'adUnitCode': '63550ad1ff6642d368cba59dh5884270560', 'bidderRequestId': '12a8ae9ada9c13', - 'transactionId': '56e184c6-bde9-497b-b9b9-cf47a61381ee', + ortb2Imp: { + ext: { + tid: '56e184c6-bde9-497b-b9b9-cf47a61381ee', + } + }, 'auctionId': 'auction_id', 'bidRequestsCount': 4, 'bidderRequestsCount': 3, diff --git a/test/spec/modules/videobyteBidAdapter_spec.js b/test/spec/modules/videobyteBidAdapter_spec.js index f7ea0698956..7844e2bd1be 100644 --- a/test/spec/modules/videobyteBidAdapter_spec.js +++ b/test/spec/modules/videobyteBidAdapter_spec.js @@ -463,7 +463,6 @@ describe('VideoByteBidAdapter', function () { }); let o = { requestId: serverResponse.id, - bidderCode: spec.code, cpm: serverResponse.seatbid[0].bid[0].price, creativeId: serverResponse.seatbid[0].bid[0].crid, vastXml: serverResponse.seatbid[0].bid[0].adm, diff --git a/test/spec/modules/winrBidAdapter_spec.js b/test/spec/modules/winrBidAdapter_spec.js index 174f600fa06..95d1473d1cb 100644 --- a/test/spec/modules/winrBidAdapter_spec.js +++ b/test/spec/modules/winrBidAdapter_spec.js @@ -599,15 +599,6 @@ describe('WinrAdapter', function () { }); describe('interpretResponse', function () { - let bfStub; - before(function() { - bfStub = sinon.stub(bidderFactory, 'getIabSubCategory'); - }); - - after(function() { - bfStub.restore(); - }); - let response = { 'version': '3.0.0', 'tags': [ diff --git a/test/spec/modules/xeBidAdapter_spec.js b/test/spec/modules/xeBidAdapter_spec.js index dcd82683221..38b334c32c5 100644 --- a/test/spec/modules/xeBidAdapter_spec.js +++ b/test/spec/modules/xeBidAdapter_spec.js @@ -11,7 +11,11 @@ const defaultRequest = { bidId: '1', requestId: 'qwerty', auctionId: 'auctionId', - transactionId: 'tr1', + ortb2Imp: { + ext: { + tid: 'tr1', + } + }, mediaTypes: { banner: { sizes: [ @@ -85,7 +89,7 @@ describe('buildRequests', function () { const request = JSON.parse(spec.buildRequests([defaultRequest], {}).data)[0]; expect(request).to.have.property('bidId').and.to.equal(defaultRequest.bidId); expect(request).to.have.property('auctionId').and.to.equal(defaultRequest.auctionId); - expect(request).to.have.property('transactionId').and.to.equal(defaultRequest.transactionId); + expect(request).to.have.property('transactionId').and.to.equal(defaultRequest.ortb2Imp.ext.tid); expect(request).to.have.property('tz').and.to.equal(new Date().getTimezoneOffset()); expect(request).to.have.property('bc').and.to.equal(1); expect(request).to.have.property('floor').and.to.equal(null); diff --git a/test/spec/sizeMapping_spec.js b/test/spec/sizeMapping_spec.js deleted file mode 100644 index c4efbddad6d..00000000000 --- a/test/spec/sizeMapping_spec.js +++ /dev/null @@ -1,341 +0,0 @@ -import { expect } from 'chai'; -import { resolveStatus, setSizeConfig, sizeSupported } from 'src/sizeMapping.js'; -import {includes} from 'src/polyfill.js' - -let utils = require('src/utils'); -let deepClone = utils.deepClone; - -describe('sizeMapping', function () { - var testSizes = { - banner: { - sizes: [[970, 90], [728, 90], [300, 250], [300, 100], [80, 80]] - } - }; - - var sizeConfig = [{ - 'mediaQuery': '(min-width: 1200px)', - 'sizesSupported': [ - [970, 90], - [728, 90], - [300, 250] - ] - }, { - 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', - 'sizesSupported': [ - [728, 90], - [300, 250], - [300, 100] - ] - }, { - 'mediaQuery': '(min-width: 0px) and (max-width: 767px)', - 'sizesSupported': [] - }]; - - var sizeConfigWithLabels = [{ - 'mediaQuery': '(min-width: 1200px)', - 'labels': ['desktop'] - }, { - 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', - 'sizesSupported': [ - [728, 90], - [300, 250] - ], - 'labels': ['tablet', 'phone'] - }, { - 'mediaQuery': '(min-width: 0px) and (max-width: 767px)', - 'sizesSupported': [ - [300, 250], - [300, 100] - ], - 'labels': ['phone'] - }]; - - let sandbox, - matchMediaOverride; - - beforeEach(function () { - setSizeConfig(sizeConfig); - - sandbox = sinon.sandbox.create(); - - matchMediaOverride = {matches: false}; - - sandbox.stub(utils.getWindowTop(), 'matchMedia').callsFake((...args) => { - if (typeof matchMediaOverride === 'function') { - return matchMediaOverride.apply(utils.getWindowTop(), args); - } - return matchMediaOverride; - }); - }); - - afterEach(function () { - setSizeConfig([]); - - sandbox.restore(); - }); - - describe('when handling sizes', function () { - it('should allow us to validate a single size', function() { - matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; - - expect(sizeSupported([300, 250])).to.equal(true); - expect(sizeSupported([80, 80])).to.equal(false); - }); - - it('should log a warning when mediaQuery property missing from sizeConfig', function () { - let errorConfig = deepClone(sizeConfig); - - delete errorConfig[0].mediaQuery; - - sandbox.stub(utils, 'logWarn'); - - resolveStatus(undefined, testSizes, undefined, errorConfig); - expect(utils.logWarn.firstCall.args[0]).to.match(/missing.+?mediaQuery/); - }); - - it('should log a warning message when mediaQuery property is declared as an empty string', function() { - const errorConfig = deepClone(sizeConfig); - errorConfig[0].mediaQuery = ''; - - sandbox.stub(utils, 'logWarn'); - resolveStatus(undefined, testSizes, undefined, errorConfig); - expect(utils.logWarn.firstCall.args[0]).to.match(/missing.+?mediaQuery/); - }); - - it('should allow deprecated adUnit.sizes', function() { - matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; - - let status = resolveStatus(undefined, undefined, testSizes.banner.sizes, sizeConfig); - - expect(status.active).to.equal(true); - expect(status.mediaTypes).to.deep.equal({ - banner: { - sizes: [[970, 90], [728, 90], [300, 250]] - } - }); - }); - - it('when one mediaQuery block matches, it should filter the adUnit.sizes passed in', function () { - matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; - - let status = resolveStatus(undefined, testSizes, undefined, sizeConfig); - - expect(status.active).to.equal(true); - expect(status.mediaTypes).to.deep.equal({ - banner: { - sizes: [[970, 90], [728, 90], [300, 250]] - } - }); - }); - - it('when multiple mediaQuery block matches, it should filter a union of the matched sizesSupported', function () { - matchMediaOverride = (str) => includes([ - '(min-width: 1200px)', - '(min-width: 768px) and (max-width: 1199px)' - ], str) ? {matches: true} : {matches: false}; - - let status = resolveStatus(undefined, testSizes, undefined, sizeConfig); - expect(status.active).to.equal(true); - expect(status.mediaTypes).to.deep.equal({ - banner: { - sizes: [[970, 90], [728, 90], [300, 250], [300, 100]] - } - }); - }); - - it('if no mediaQueries match, it should allow all sizes specified', function () { - matchMediaOverride = () => ({matches: false}); - - let status = resolveStatus(undefined, testSizes, undefined, sizeConfig); - expect(status.active).to.equal(true); - expect(status.mediaTypes).to.deep.equal(testSizes); - }); - - it('if a mediaQuery matches and has sizesSupported: [], it should filter all sizes', function () { - matchMediaOverride = (str) => str === '(min-width: 0px) and (max-width: 767px)' ? {matches: true} : {matches: false}; - - let status = resolveStatus(undefined, testSizes, undefined, sizeConfig); - expect(status.active).to.equal(false); - expect(status.mediaTypes).to.deep.equal({ - banner: { - sizes: [] - } - }); - }); - - it('should filter all banner sizes and should disable the adUnit even if other mediaTypes are present', function () { - matchMediaOverride = (str) => str === '(min-width: 0px) and (max-width: 767px)' ? {matches: true} : {matches: false}; - let status = resolveStatus(undefined, Object.assign({}, testSizes, { - native: { - type: 'image' - } - }), undefined, sizeConfig); - expect(status.active).to.equal(false); - expect(status.mediaTypes).to.deep.equal({ - banner: { - sizes: [] - }, - native: { - type: 'image' - } - }); - }); - - it('if a mediaQuery matches and no sizesSupported specified, it should not affect adUnit.sizes', function () { - matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; - - let status = resolveStatus(undefined, testSizes, undefined, sizeConfigWithLabels); - expect(status.active).to.equal(true); - expect(status.mediaTypes).to.deep.equal(testSizes); - }); - }); - - describe('when handling labels', function () { - it('should activate/deactivate adUnits/bidders based on sizeConfig.labels', function () { - matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; - - let status = resolveStatus({ - labels: ['desktop'] - }, testSizes, undefined, sizeConfigWithLabels); - - expect(status).to.deep.equal({ - active: true, - mediaTypes: testSizes - }); - - status = resolveStatus({ - labels: ['tablet'] - }, testSizes, undefined, sizeConfigWithLabels); - - expect(status.active).to.equal(false); - expect(status.mediaTypes).to.deep.equal(testSizes); - }); - - it('should activate/decactivate adUnits/bidders based on labels with multiformat ads', function () { - matchMediaOverride = (str) => str === '(min-width: 768px) and (max-width: 1199px)' ? {matches: true} : {matches: false}; - - let multiFormatSizes = { - banner: { - sizes: [[728, 90], [300, 300]] - }, - native: { - type: 'image' - }, - video: { - context: 'outstream', - playerSize: [300, 300] - } - }; - - let status = resolveStatus({ - labels: ['tablet', 'test'], - labelAll: true - }, multiFormatSizes, undefined, sizeConfigWithLabels); - - expect(status.active).to.equal(false); - expect(status.mediaTypes).to.deep.equal({ - banner: { - sizes: [[728, 90]] - }, - native: { - type: 'image' - }, - video: { - context: 'outstream', - playerSize: [300, 300] - } - }); - - status = resolveStatus({ - labels: ['tablet'] - }, multiFormatSizes, undefined, sizeConfigWithLabels); - - expect(status.active).to.equal(true); - expect(status.mediaTypes).to.deep.equal({ - banner: { - sizes: [[728, 90]] - }, - native: { - type: 'image' - }, - video: { - context: 'outstream', - playerSize: [300, 300] - } - }); - - multiFormatSizes.banner.sizes.splice(0, 1, [728, 80]); - status = resolveStatus({ - labels: ['tablet'] - }, multiFormatSizes, undefined, sizeConfigWithLabels); - - expect(status.active).to.equal(false); - expect(status.mediaTypes).to.deep.equal({ - banner: { - sizes: [] - }, - native: { - type: 'image' - }, - video: { - context: 'outstream', - playerSize: [300, 300] - } - }); - - delete multiFormatSizes.banner; - status = resolveStatus({ - labels: ['tablet'] - }, multiFormatSizes, undefined, sizeConfigWithLabels); - - expect(status.active).to.equal(true); - expect(status.mediaTypes).to.deep.equal({ - native: { - type: 'image' - }, - video: { - context: 'outstream', - playerSize: [300, 300] - } - }); - }); - - it('should active/deactivate adUnits/bidders based on requestBids labels', function () { - let activeLabels = ['us-visitor', 'desktop', 'smart']; - - let status = resolveStatus({ - labels: ['uk-visitor'], // from adunit - activeLabels // from requestBids.labels - }, testSizes, undefined, sizeConfigWithLabels); - - expect(status.active).to.equal(false); - expect(status.mediaTypes).to.deep.equal(testSizes); - - status = resolveStatus({ - labels: ['us-visitor'], - activeLabels - }, testSizes, undefined, sizeConfigWithLabels); - - expect(status.active).to.equal(true); - expect(status.mediaTypes).to.deep.equal(testSizes); - - status = resolveStatus({ - labels: ['us-visitor', 'tablet'], - labelAll: true, - activeLabels - }, testSizes, undefined, sizeConfigWithLabels); - - expect(status.active).to.equal(false); - expect(status.mediaTypes).to.deep.equal(testSizes); - - status = resolveStatus({ - labels: ['us-visitor', 'desktop'], - labelAll: true, - activeLabels - }, testSizes, undefined, sizeConfigWithLabels); - - expect(status.active).to.equal(true); - expect(status.mediaTypes).to.deep.equal(testSizes); - }); - }); -}); diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index c60293bbf3f..cff26df2e4d 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -16,7 +16,7 @@ import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils.js'; import { config } from 'src/config.js'; import { registerBidder } from 'src/adapters/bidderFactory.js'; -import { setSizeConfig } from 'src/sizeMapping.js'; +import { setSizeConfig } from 'modules/sizeMapping.js'; import {find, includes} from 'src/polyfill.js'; import s2sTesting from 'modules/s2sTesting.js'; import {hook} from '../../../../src/hook.js'; @@ -354,103 +354,79 @@ describe('adapterManager tests', function () { }); }); // end callTimedOutBidders - describe('onBidWon', function () { - var criteoSpec = { onBidWon: sinon.stub() } - var criteoAdapter = { - bidder: 'criteo', - getSpec: function() { return criteoSpec; } - } + describe('bidder spec methods', () => { + let adUnits, bids, criteoSpec; before(function () { config.setConfig({s2sConfig: { enabled: false }}); }); - beforeEach(function () { - adapterManager.bidderRegistry['criteo'] = criteoAdapter; - }); - - afterEach(function () { - delete adapterManager.bidderRegistry['criteo']; - }); - - it('should call spec\'s onBidWon callback when a bid is won', function () { - const bids = [ + beforeEach(() => { + criteoSpec = {} + adapterManager.bidderRegistry['criteo'] = { + bidder: 'criteo', + getSpec: function() { return criteoSpec; }, + } + bids = [ {bidder: 'criteo', params: {placementId: 'id'}}, ]; - const adUnits = [{ + adUnits = [{ code: 'adUnit-code', sizes: [[728, 90]], bids }]; - - adapterManager.callBidWonBidder(bids[0].bidder, bids[0], adUnits); - sinon.assert.called(criteoSpec.onBidWon); - }); - }); // end onBidWon - - describe('onSetTargeting', function () { - var criteoSpec = { onSetTargeting: sinon.stub() } - var criteoAdapter = { - bidder: 'criteo', - getSpec: function() { return criteoSpec; } - } - before(function () { - config.setConfig({s2sConfig: { enabled: false }}); - }); - - beforeEach(function () { - adapterManager.bidderRegistry['criteo'] = criteoAdapter; }); afterEach(function () { delete adapterManager.bidderRegistry['criteo']; }); - it('should call spec\'s onSetTargeting callback when setTargeting is called', function () { - const bids = [ - {bidder: 'criteo', params: {placementId: 'id'}}, - ]; - const adUnits = [{ - code: 'adUnit-code', - sizes: [[728, 90]], - bids - }]; - adapterManager.callSetTargetingBidder(bids[0].bidder, bids[0], adUnits); - sinon.assert.called(criteoSpec.onSetTargeting); - }); - }); // end onSetTargeting + describe('onBidWon', function () { + beforeEach(() => { + criteoSpec.onBidWon = sinon.stub() + }); + it('should call spec\'s onBidWon callback when a bid is won', function () { + adapterManager.callBidWonBidder(bids[0].bidder, bids[0], adUnits); + sinon.assert.called(criteoSpec.onBidWon); + }); - describe('onBidViewable', function () { - var criteoSpec = { onBidViewable: sinon.stub() } - var criteoAdapter = { - bidder: 'criteo', - getSpec: function() { return criteoSpec; } - } - before(function () { - config.setConfig({s2sConfig: { enabled: false }}); + it('should NOT call onBidWon when the bid is S2S', () => { + bids[0].src = CONSTANTS.S2S.SRC + adapterManager.callBidWonBidder(bids[0].bidder, bids[0], adUnits); + sinon.assert.notCalled(criteoSpec.onBidWon); + }) }); - beforeEach(function () { - adapterManager.bidderRegistry['criteo'] = criteoAdapter; - }); + describe('onSetTargeting', function () { + beforeEach(() => { + criteoSpec.onSetTargeting = sinon.stub() + }) - afterEach(function () { - delete adapterManager.bidderRegistry['criteo']; - }); + it('should call spec\'s onSetTargeting callback when setTargeting is called', function () { + adapterManager.callSetTargetingBidder(bids[0].bidder, bids[0], adUnits); + sinon.assert.called(criteoSpec.onSetTargeting); + }); - it('should call spec\'s onBidViewable callback when callBidViewableBidder is called', function () { - const bids = [ - {bidder: 'criteo', params: {placementId: 'id'}}, - ]; - const adUnits = [{ - code: 'adUnit-code', - sizes: [[728, 90]], - bids - }]; - adapterManager.callBidViewableBidder(bids[0].bidder, bids[0]); - sinon.assert.called(criteoSpec.onBidViewable); + it('should NOT call onSetTargeting when bid is S2S', () => { + bids[0].src = CONSTANTS.S2S.SRC; + adapterManager.callSetTargetingBidder(bids[0].bidder, bids[0], adUnits); + sinon.assert.notCalled(criteoSpec.onSetTargeting); + }) + }); // end onSetTargeting + describe('onBidViewable', function () { + beforeEach(() => { + criteoSpec.onBidViewable = sinon.stub(); + }) + it('should call spec\'s onBidViewable callback when callBidViewableBidder is called', function () { + adapterManager.callBidViewableBidder(bids[0].bidder, bids[0]); + sinon.assert.called(criteoSpec.onBidViewable); + }); + it('should NOT call onBidViewable when bid is S2S', () => { + bids[0].src = CONSTANTS.S2S.SRC; + adapterManager.callBidViewableBidder(bids[0].bidder, bids[0]); + sinon.assert.notCalled(criteoSpec.onBidViewable); + }) }); - }); // end onBidViewable - + }) describe('onBidderError', function () { const bidder = 'appnexus'; const appnexusSpec = { onBidderError: sinon.stub() }; @@ -1886,6 +1862,23 @@ describe('adapterManager tests', function () { requests.appnexus.bids.forEach((bid) => expect(bid.ortb2).to.eql(requests.appnexus.ortb2)); }); + describe('source.tid', () => { + beforeEach(() => { + sinon.stub(dep, 'redact').returns({ + ortb2: (o) => o, + bidRequest: (b) => b, + }); + }); + afterEach(() => { + dep.redact.restore(); + }); + + it('should be populated with auctionId', () => { + const reqs = adapterManager.makeBidRequests(adUnits, 0, 'mockAuctionId', 1000, [], {global: {}}); + expect(reqs[0].ortb2.source.tid).to.equal('mockAuctionId'); + }) + }); + it('should merge in bid-level ortb2Imp with adUnit-level ortb2Imp', () => { const adUnit = { ...adUnits[1], @@ -2126,45 +2119,6 @@ describe('adapterManager tests', function () { expect(appnexusBidRequests.bids[1].mediaTypes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[1].adUnitCode).mediaTypes); }); - it('should not filter video bids', function () { - setSizeConfig([{ - 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', - 'sizesSupported': [ - [728, 90], - [300, 250] - ], - 'labels': ['tablet', 'phone'] - }]); - - let videoAdUnits = [{ - code: 'test_video', - mediaTypes: { - video: { - playerSize: [300, 300], - context: 'outstream' - } - }, - bids: [{ - bidder: 'appnexus', - params: { - placementId: 13232385, - video: { - skippable: true, - playback_method: ['auto_play_sound_off'] - } - } - }] - }]; - let bidRequests = adapterManager.makeBidRequests( - videoAdUnits, - Date.now(), - utils.getUniqueIdentifierStr(), - function callback() {}, - [] - ); - expect(bidRequests[0].bids[0].sizes).to.deep.equal([300, 300]); - }); - it('should not filter native bids', function () { setSizeConfig([{ 'mediaQuery': '(min-width: 768px) and (max-width: 1199px)', diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index 568c3bfdd09..751c90af50f 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -1,18 +1,10 @@ -import { - addComponentAuction, - isValid, - newBidder, - preloadBidderMappingFile, - registerBidder, - storage -} from 'src/adapters/bidderFactory.js'; +import {addComponentAuction, isValid, newBidder, registerBidder} from 'src/adapters/bidderFactory.js'; import adapterManager from 'src/adapterManager.js'; import * as ajax from 'src/ajax.js'; import {expect} from 'chai'; import {userSync} from 'src/userSync.js'; import * as utils from 'src/utils.js'; import {config} from 'src/config.js'; -import {server} from 'test/mocks/xhr.js'; import CONSTANTS from 'src/constants.json'; import * as events from 'src/events.js'; import {hook} from '../../../../src/hook.js'; @@ -20,6 +12,10 @@ import {auctionManager} from '../../../../src/auctionManager.js'; import {stubAuctionIndex} from '../../../helpers/indexStub.js'; import {bidderSettings} from '../../../../src/bidderSettings.js'; import {decorateAdUnitsWithNativeParams} from '../../../../src/native.js'; +import * as activityRules from 'src/activities/rules.js'; +import {sandbox} from 'sinon'; +import {MODULE_TYPE_BIDDER} from '../../../../src/activities/modules.js'; +import {ACTIVITY_TRANSMIT_TID} from '../../../../src/activities/activities.js'; const CODE = 'sampleBidder'; const MOCK_BIDS_REQUEST = { @@ -74,24 +70,25 @@ describe('bidders created by newBidder', function () { }); describe('when the ajax response is irrelevant', function () { + let sandbox; let ajaxStub; let getConfigSpy; let aliasRegistryStub, aliasRegistry; beforeEach(function () { - ajaxStub = sinon.stub(ajax, 'ajax'); + sandbox = sinon.sandbox.create(); + sandbox.stub(activityRules, 'isActivityAllowed').callsFake(() => true); + ajaxStub = sandbox.stub(ajax, 'ajax'); addBidResponseStub.reset(); - getConfigSpy = sinon.spy(config, 'getConfig'); + getConfigSpy = sandbox.spy(config, 'getConfig'); doneStub.reset(); aliasRegistry = {}; - aliasRegistryStub = sinon.stub(adapterManager, 'aliasRegistry'); + aliasRegistryStub = sandbox.stub(adapterManager, 'aliasRegistry'); aliasRegistryStub.get(() => aliasRegistry); }); afterEach(function () { - ajaxStub.restore(); - getConfigSpy.restore(); - aliasRegistryStub.restore(); + sandbox.restore(); }); it('should let registerSyncs run with invalid alias and aliasSync enabled', function () { @@ -143,6 +140,74 @@ describe('bidders created by newBidder', function () { expect(getConfigSpy.withArgs('userSync.filterSettings').calledOnce).to.equal(false); }); + describe('transaction IDs', () => { + Object.entries({ + 'be hidden': false, + 'not be hidden': true, + }).forEach(([t, allowed]) => { + const expectation = allowed ? (val) => expect(val).to.exist : (val) => expect(val).to.not.exist; + + function checkBidRequest(br) { + ['auctionId', 'transactionId'].forEach((prop) => expectation(br[prop])); + } + + function checkBidderRequest(br) { + expectation(br.auctionId); + br.bids.forEach(checkBidRequest); + } + + it(`should ${t} from the spec logic when the transmitTid activity is${allowed ? '' : ' not'} allowed`, () => { + spec.isBidRequestValid.callsFake(br => { + checkBidRequest(br); + return true; + }); + spec.buildRequests.callsFake((bidReqs, bidderReq) => { + checkBidderRequest(bidderReq); + bidReqs.forEach(checkBidRequest); + return {method: 'POST'}; + }); + spec.interpretResponse.callsFake(() => [ + { + requestId: 'bid', + cpm: 123, + ttl: 300, + creativeId: 'crid', + netRevenue: true, + currency: 'USD' + } + ]) + activityRules.isActivityAllowed.reset(); + activityRules.isActivityAllowed.callsFake(() => allowed); + + ajaxStub.callsFake((_, callback) => callback.success(null, {getResponseHeader: sinon.stub()})); + + const bidder = newBidder(spec); + + bidder.callBids({ + bidderCode: 'mockBidder', + auctionId: 'aid', + bids: [ + { + adUnitCode: 'mockAU', + bidId: 'bid', + transactionId: 'tid', + auctionId: 'aid' + } + ] + }, addBidResponseStub, doneStub, ajaxStub, onTimelyResponseStub, wrappedCallback); + + sinon.assert.calledWithMatch(activityRules.isActivityAllowed, ACTIVITY_TRANSMIT_TID, { + componentType: MODULE_TYPE_BIDDER, + componentName: 'mockBidder' + }); + sinon.assert.calledWithMatch(addBidResponseStub, sinon.match.any, { + transactionId: 'tid', + auctionId: 'aid' + }) + }); + }); + }); + it('should handle bad bid requests gracefully', function () { const bidder = newBidder(spec); @@ -1283,143 +1348,6 @@ describe('validate bid response: ', function () { }) }); -describe('preload mapping url hook', function() { - if (!FEATURES.VIDEO) { - return - } - - let fakeTranslationServer; - let getLocalStorageStub; - let adapterManagerStub; - let adUnits = [{ - code: 'midroll_1', - mediaTypes: { - video: { - context: 'adpod' - } - }, - bids: [ - { - bidder: 'sampleBidder1', - params: { - placementId: 14542875, - } - } - ] - }]; - - beforeEach(function () { - fakeTranslationServer = server; - getLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage'); - adapterManagerStub = sinon.stub(adapterManager, 'getBidAdapter'); - config.setConfig({ - 'adpod': { - 'brandCategoryExclusion': true - } - }); - adapterManagerStub.withArgs('sampleBidder1').returns({ - getSpec: function() { - return { - 'getMappingFileInfo': function() { - return { - url: 'http://sample.com', - refreshInDays: 7, - key: `sampleBidder1MappingFile` - } - } - } - } - }); - }); - - afterEach(function() { - getLocalStorageStub.restore(); - adapterManagerStub.restore(); - config.resetConfig(); - }); - - it('should preload mapping url file', function() { - getLocalStorageStub.returns(null); - preloadBidderMappingFile(sinon.spy(), adUnits); - expect(fakeTranslationServer.requests.length).to.equal(1); - }); - - it('should preload mapping url file for all bidders', function() { - let adUnits = [{ - code: 'midroll_1', - mediaTypes: { - video: { - context: 'adpod' - } - }, - bids: [ - { - bidder: 'sampleBidder1', - params: { - placementId: 14542875, - } - }, - { - bidder: 'sampleBidder2', - params: { - placementId: 123456, - } - } - ] - }]; - getLocalStorageStub.returns(null); - adapterManagerStub.withArgs('sampleBidder2').returns({ - getSpec: function() { - return { - 'getMappingFileInfo': function() { - return { - url: 'http://sample.com', - refreshInDays: 7, - key: `sampleBidder2MappingFile` - } - } - } - } - }); - preloadBidderMappingFile(sinon.spy(), adUnits); - expect(fakeTranslationServer.requests.length).to.equal(2); - - config.setConfig({ - 'adpod': { - 'brandCategoryExclusion': false - } - }); - preloadBidderMappingFile(sinon.spy(), adUnits); - expect(fakeTranslationServer.requests.length).to.equal(2); - }); - - it('should make ajax call to update mapping file if data found in localstorage is expired', function() { - let clock = sinon.useFakeTimers(utils.timestamp()); - getLocalStorageStub.returns(JSON.stringify({ - lastUpdated: utils.timestamp() - 8 * 24 * 60 * 60 * 1000, - mapping: { - 'iab-1': '1' - } - })); - preloadBidderMappingFile(sinon.spy(), adUnits); - expect(fakeTranslationServer.requests.length).to.equal(1); - clock.restore(); - }); - - it('should not make ajax call to update mapping file if data found in localstorage and is not expired', function () { - let clock = sinon.useFakeTimers(utils.timestamp()); - getLocalStorageStub.returns(JSON.stringify({ - lastUpdated: utils.timestamp(), - mapping: { - 'iab-1': '1' - } - })); - preloadBidderMappingFile(sinon.spy(), adUnits); - expect(fakeTranslationServer.requests.length).to.equal(0); - clock.restore(); - }); -}); - describe('bid response isValid', () => { describe('size check', () => { let req, index; diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index f9fe2e398b0..f16d6208087 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -334,12 +334,6 @@ describe('targeting tests', function () { bidExpiryStub.restore(); }); - it('should filter out NO_BID bids', () => { - bidsReceived = [mkBid(sampleBid, CONSTANTS.STATUS.NO_BID)]; - const tg = targetingInstance.getAllTargeting(); - expect(tg[bidsReceived[0].adUnitCode]).to.eql({}); - }); - describe('when handling different adunit targeting value types', function () { const adUnitCode = '/123456/header-bid-tag-0'; const adServerTargeting = {}; diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 9199b259ad6..e26683074c8 100644 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -1,8 +1,8 @@ -import { getAdServerTargeting } from 'test/fixtures/fixtures.js'; -import { expect } from 'chai'; +import {getAdServerTargeting} from 'test/fixtures/fixtures.js'; +import {expect} from 'chai'; import CONSTANTS from 'src/constants.json'; import * as utils from 'src/utils.js'; -import {memoize, deepEqual, waitForElementToLoad} from 'src/utils.js'; +import {deepEqual, memoize, waitForElementToLoad} from 'src/utils.js'; var assert = require('assert'); @@ -894,93 +894,24 @@ describe('Utils', function () { }); }); - describe('transformBidderParamKeywords', function () { - it('returns an array of objects when keyvalue is an array', function () { - let keywords = { - genre: ['rock', 'pop'] - }; - let result = utils.transformBidderParamKeywords(keywords); - expect(result).to.deep.equal([{ - key: 'genre', - value: ['rock', 'pop'] - }]); - }); - - it('returns an array of objects when keyvalue is a string', function () { - let keywords = { - genre: 'opera' - }; - let result = utils.transformBidderParamKeywords(keywords); - expect(result).to.deep.equal([{ - key: 'genre', - value: ['opera'] - }]); - }); - - it('returns an array of objects when keyvalue is a number', function () { - let keywords = { - age: 15 - }; - let result = utils.transformBidderParamKeywords(keywords); - expect(result).to.deep.equal([{ - key: 'age', - value: ['15'] - }]); - }); - - it('returns an array of objects when using multiple keys with values of differing types', function () { - let keywords = { - genre: 'classical', - mix: ['1', 2, '3', 4], - age: 10 - }; - let result = utils.transformBidderParamKeywords(keywords); - expect(result).to.deep.equal([{ - key: 'genre', - value: ['classical'] - }, { - key: 'mix', - value: ['1', '2', '3', '4'] - }, { - key: 'age', - value: ['10'] - }]); - }); - - it('returns an array of objects when the keyvalue uses an empty string', function() { - let keywords = { - test: [''], - test2: '' - }; - let result = utils.transformBidderParamKeywords(keywords); - expect(result).to.deep.equal([{ - key: 'test', - value: [''] - }, { - key: 'test2', - value: [''] - }]); - }); - - describe('insertElement', function () { - it('returns a node at the top of the target by default', function () { - const toInsert = document.createElement('div'); - const target = document.getElementsByTagName('body')[0]; - const inserted = utils.insertElement(toInsert, document, 'body'); - expect(inserted).to.equal(target.firstChild); - }); - it('returns a node at bottom of target if 4th argument is true', function () { - const toInsert = document.createElement('div'); - const target = document.getElementsByTagName('html')[0]; - const inserted = utils.insertElement(toInsert, document, 'html', true); - expect(inserted).to.equal(target.lastChild); - }); - it('returns a node at top of the head if no target is given', function () { - const toInsert = document.createElement('div'); - const target = document.getElementsByTagName('head')[0]; - const inserted = utils.insertElement(toInsert); - expect(inserted).to.equal(target.firstChild); - }); + describe('insertElement', function () { + it('returns a node at the top of the target by default', function () { + const toInsert = document.createElement('div'); + const target = document.getElementsByTagName('body')[0]; + const inserted = utils.insertElement(toInsert, document, 'body'); + expect(inserted).to.equal(target.firstChild); + }); + it('returns a node at bottom of target if 4th argument is true', function () { + const toInsert = document.createElement('div'); + const target = document.getElementsByTagName('html')[0]; + const inserted = utils.insertElement(toInsert, document, 'html', true); + expect(inserted).to.equal(target.lastChild); + }); + it('returns a node at top of the head if no target is given', function () { + const toInsert = document.createElement('div'); + const target = document.getElementsByTagName('head')[0]; + const inserted = utils.insertElement(toInsert); + expect(inserted).to.equal(target.firstChild); }); });