diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000000..fbf7e77e10f --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,50 @@ +# Javascript Node CircleCI 2.0 configuration file +# +# Check https://circleci.com/docs/2.0/language-javascript/ for more details +# +version: 2 +jobs: + build: + docker: + # specify the version you desire here + - image: circleci/node:7.10 + + # Specify service dependencies here if necessary + # CircleCI maintains a library of pre-built images + # documented at https://circleci.com/docs/2.0/circleci-images/ + # - image: circleci/mongo:3.4.4 + + working_directory: ~/Prebid.js + + steps: + - checkout + + # Download and cache dependencies + - restore_cache: + keys: + - v1-dependencies-{{ checksum "package.json" }} + # fallback to using the latest cache if no exact match is found + - v1-dependencies- + + - run: npm install + + - save_cache: + paths: + - node_modules + key: v1-dependencies-{{ checksum "package.json" }} + + - run: sudo npm install -g gulp-cli + # Download and run BrowserStack local + - run: + name : Download BrowserStack Local binary and start it. + command : | + # Download the browserstack binary file + wget "https://www.browserstack.com/browserstack-local/BrowserStackLocal-linux-x64.zip" + # Unzip it + unzip BrowserStackLocal-linux-x64.zip + # Run the file with user's access key + ./BrowserStackLocal ${BROWSERSTACK_ACCESS_KEY} & + # run tests! + - run: + name: BrowserStack testing + command: gulp test --browserstack diff --git a/.eslintrc.js b/.eslintrc.js index e6975951f06..02ff81614c7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -26,7 +26,6 @@ module.exports = { // Violations of these styles should be fixed, and the exceptions removed over time. // // See Issue #1111. - "camelcase": "off", "eqeqeq": "off", "no-return-assign": "off", "no-throw-literal": "off", diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 4501da64c99..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,29 +0,0 @@ -sudo: required -dist: trusty -language: node_js -node_js: -- '7.0' -env: -- BROWSERSTACK_USERNAME=info184 -addons: - chrome: stable, - browserstack: - username: info184 - access_key: - secure: Ru286R4pMcEIRKwb2AoaaJY6lEKIzeZraxY7CtbOP4ykNk7uqsnyitk4QwxpCCh0n35b71m30okW6ZmZnl0lJXhOMdYoSOYBAnUw2Vn7Y93oMSKIC5dc2/qmtF1t2b1qX65/Ont2iJUj+UY8VQw5Hk2vIT4/5wifYPBnV5ILK4AI7SVk/ma7OzK4rkp3WThlouddctAd7tx4O3YIyJKDi9lkfcMA0pnH4OZSOlDClRLIy50Q1NE+iyqHtWFZK1TwJ+IhQbSsCLbuyQJBRnyJJEftNmtrs5MCZt/9pwFDj7c8+o11F6HCsTBYFkehFRfbKnmhCc1G+bsNXY8OxIWwEHeuVmSGK7TDPYcPPQBc03mcQ1fY/IPNQOdsVJ/n8RsG2u0IU2CF2hhkuNFzeov7dOHljanc45NKOrLdjwzP1aZCAUvLquOTzvmdF23nJhMs8UO+Du4kTK5VfmKyz1MC91E40a0Q15+O4qmS39rNOlwhxPJSfuxxL1jKVPJ7PsFbTkGM8M/XPJ6dyGLufy225HjdLdJTAOa5BZ4st+nXH/AzqHzy6a2I5vTmAz1j4gHLgVU+iNxAkX8znb25s3Rs1ZuFVj+aBSBmNoQA1FA5f/uXWeruTdDig7ksp+XdjsjLm9Md8cWwYaEn04FYj1ztJrylrEMfnc0Kcs6zQ3fll1g= -before_install: -- npm install -g gulp -- google-chrome-stable --headless --disable-gpu --remote-debugging-port=9222 http://localhost & -script: |- - if [[ ${TRAVIS_PULL_REQUEST} == "false" ]]; then - gulp test --browserstack - else - gulp run-tests - fi -notifications: - slack: - on_success: never - on_failure: always - on_pull_requests: false - rooms: - - secure: C4O77VtABLE5DiPDeKGqUcsBdTBMNjQRLc8iBfSp231e95K1rA/JXJJEQN/lVhhiFJyPhxueE0i6cR0zD8uAMC8HRShGGfPjEZ7f6glawPzap2wFwjAyVkknYV+BMKcX0jvn7CiSKBj+zTbHQfn/Uj3nMSbDZQIdbNDiFGh4NuDr3/Yd/efhsw/miExlSPSWqGVCKV3WPpTrU3BRpLNDq4sZMXP9ORZxGK7ER3tsMiD2z05YpvC+mibESJxaY0qsuQu1y1Gu65QLPe5ocw405btJwqYn+b4YFpUd2GbLNhjtLzsc+OKrD0DWuEI0bxePQUYDga5wR6g4cdZaXU3ixDjee7sJbDeVJAuykGlfZ4A1k+fQIgPs3s9XMHaeG9AfDhFiZ/UoNdonzos1iSa/Y1TzHIXp1wnbHKT5HUWWPFNb5PzJxHEtHbm3jwOH4iK8VAq94ec16M2aqUAj7muiqcrTlYa5rs6jRlXo/TRymFnbQRdBT7eLmLNDQD35yR1Y+4mxHqKi+3189yG9RE+uwIlB+9HZFgNbioOApB+jarKC6M0qEgn0bHxkpJBP8JmNCA84U0ZUzyPvuMGsRbisAmKoUsU8C6cq59QDfBTcCTvKXK6r+6f23iRGieoGSbTxYQj46QkykpbWU0WstQDQsZL3L316uZecOVZmWKBRxPs= diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dc8d80ec384..7f4127cf3ba 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -55,7 +55,7 @@ When you are adding code to Prebid.js, or modifying code that isn't covered by a Prebid.js already has many tests. Read them to see how Prebid.js is tested, and for inspiration: - Look in `test/spec` and its subdirectories -- Tests for bidder adaptors are located in `test/spec/adapters` +- Tests for bidder adaptors are located in `test/spec/modules` A test module might have the following general structure: diff --git a/PREBID_VERSIONING_DEPRECATION.md b/PREBID_VERSIONING_DEPRECATION.md new file mode 100644 index 00000000000..f006922259b --- /dev/null +++ b/PREBID_VERSIONING_DEPRECATION.md @@ -0,0 +1,25 @@ +# Prebid versioning and deprecation policy + +## Goals +Provide clear definitions and policy around versioning and breaking changes to APIs that are both publisher and demand partner facing. + + - Limit the number of breaking changes. + - Ensure significant time for updates for breaking changes so that publisher or demand partners do not break. + - Provide a path to deprecation and reduce technical debt and increase security. + - Major versions should not be changed more than once per 30 days. + +## Versioning + +Follow semantic versioning so that all breaking changes occur within a major release. A breaking change includes both demand partner internal APIs* and publisher facing APIs (global APIs). + +*Demand partner APIs may be excluded from breaking change policy at the core teams discretion if the changes are made so to be transparent to the bidders (such as internal refactoring). + +## Deprecation process + + - Open an issue with an "intent to implement" and "API impact" labels. + - Allow 2 weeks for discussion. + - Announce breaking change to the mailing list (TBD needs to be created). + - At least 2 core members needs to provide explicit approval for the deprecation. + - Open a PR against current master for console warning for possible breakage. + - Support the previous major version for a minimum of 30 days. + - Coordinate with the core team to ensure clean merging into feature branch if applicable (future major version branch). diff --git a/PR_REVIEW.md b/PR_REVIEW.md index 012a2d8b501..d5799472377 100644 --- a/PR_REVIEW.md +++ b/PR_REVIEW.md @@ -18,6 +18,7 @@ For modules and core platform updates, the initial reviewer should request an ad - Once there is 2 `LGTM` on the PR, merge to master - Ask the submitter to add a PR for documentation if applicable. - Add a line into the [draft release](https://github.com/prebid/Prebid.js/releases) notes for this submission. If no draft release is available, create one using [this template]( https://gist.github.com/mkendall07/c3af6f4691bed8a46738b3675cb5a479) +- Add the PR to the appropriate project board (I.E. 1.23.0 Release) for the week, [see](https://github.com/prebid/Prebid.js/projects) ### New Adapter or updates to adapter process - Follow steps above for general review process. In addition, please verify the following: @@ -39,9 +40,9 @@ For modules and core platform updates, the initial reviewer should request an ad ## Ticket Coordinator Each week, Prebid Org assigns one person to keep an eye on incoming issues and PRs. That person should: -- Review issues and PRs at least once per weekday for new items. +- Review issues and PRs at least once per weekday for new items. Encourage a 48 "SLA" on PRs/issues assigned. Aim for touchpoint once every 48/hours. - For PRs: assign PRs to individuals on the PR review list. Try to be equitable -- not all PRs are created equally. Use the "Assigned" field and add the "Needs Review" label. -- For Issues: try to address questions and troubleshooting requests on your own, assigning them to others as needed. +- For Issues: try to address questions and troubleshooting requests on your own, assigning them to others as needed. Please add labels as appropriate (I.E. bug, question, backlog etc). - Issues that are questions or troubleshooting requests may be closed if the originator doesn't respond within a week to requests for confirmation or details. - Issues that are bug reports should be left open and assigned to someone in PR rotation to confirm or deny the bug status. - It's polite to check with others before assigning them large tasks. diff --git a/README.md b/README.md index 946d6755774..a89f68b8abc 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ -[![Build Status](https://travis-ci.org/prebid/Prebid.js.svg?branch=master)](https://travis-ci.org/prebid/Prebid.js) +[![Build Status](https://circleci.com/gh/prebid/Prebid.js.svg?style=svg)](https://circleci.com/gh/prebid/Prebid.js) [![Percentage of issues still open](http://isitmaintained.com/badge/open/prebid/Prebid.js.svg)](http://isitmaintained.com/project/prebid/Prebid.js "Percentage of issues still open") [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/prebid/Prebid.js.svg)](http://isitmaintained.com/project/prebid/Prebid.js "Average time to resolve an issue") [![Code Climate](https://codeclimate.com/github/prebid/Prebid.js/badges/gpa.svg)](https://codeclimate.com/github/prebid/Prebid.js) [![Coverage Status](https://coveralls.io/repos/github/prebid/Prebid.js/badge.svg)](https://coveralls.io/github/prebid/Prebid.js) [![devDependencies Status](https://david-dm.org/prebid/Prebid.js/dev-status.svg)](https://david-dm.org/prebid/Prebid.js?type=dev) +[![Total Alerts](https://img.shields.io/lgtm/alerts/g/prebid/Prebid.js.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/prebid/Prebid.js/alerts/) # Prebid.js @@ -29,6 +30,8 @@ Working examples can be found in [the developer docs](http://prebid.org/dev-docs $ npm install *Note:* You need to have `NodeJS` 4.x or greater installed. +*Note:* Because we have transitioned to using gulp 4.0 - you need to have `gulp-cli` installed globally prior to running the general `npm install`. Run the following command to perform the install: `npm install gulp-cli -g` +If you have a previous version of `gulp` installed globally, you'll need to remove it before installing `gulp-cli`. This removal can be done with the command: `npm rm gulp -g` @@ -167,7 +170,7 @@ Many SSPs, bidders, and publishers have contributed to this project. [60+ Bidder For guidelines, see [Contributing](./CONTRIBUTING.md). -Our PR review process can be found [here](https://github.com/prebid/Prebid.js/tree/master/pr_review.md). +Our PR review process can be found [here](https://github.com/prebid/Prebid.js/tree/master/PR_REVIEW.md). ### Add a Bidder Adapter diff --git a/RELEASE_SCHEDULE.md b/RELEASE_SCHEDULE.md index efdc45f7f9f..611a98473ff 100644 --- a/RELEASE_SCHEDULE.md +++ b/RELEASE_SCHEDULE.md @@ -1,6 +1,7 @@ **Table of Contents** - [Release Schedule](#release-schedule) - [Release Process](#release-process) +- [Beta Releases](#beta-releases) - [FAQs](#faqs) ## Release Schedule @@ -16,13 +17,17 @@ Announcements regarding releases will be made to the #headerbidding-dev channel ## Release Process -1. Make Sure all browserstack tests are passing. On PR merge to master travis will run unit tests on browserstack. Checking the last travis build [here](https://travis-ci.org/prebid/Prebid.js/branches) for master branch will show you detailed results. +_Note: If `github.com/prebid/Prebid.js` is not configured as the git origin for your repo, all of the following git commands will have to be modified to reference the proper remote (e.g. `upstream`)_ + +1. Make Sure all browserstack tests are passing. On PR merge to master CircleCI will run unit tests on browserstack. Checking the last CircleCI build [here](https://circleci.com/gh/prebid/Prebid.js) for master branch will show you detailed results. In case of failure do following, - Try to fix the failing tests. - If you are not able to fix tests in time. Skip the test, create issue and tag contributor. #### How to run tests in browserstack + + _Note: the following browserstack information is only relevant for debugging purposes, if you will not be debugging then it can be skipped._ Set the environment variables. You may want to add these to your `~/.bashrc` for convenience. @@ -58,11 +63,12 @@ Announcements regarding releases will be made to the #headerbidding-dev channel Pull these changes locally by running command ``` git pull + git fetch --tags ``` and verify the tag. -5. Update coveralls +5. Update coveralls _(skip for legacy)_ We use https://coveralls.io/ to show parts of code covered by unit tests. @@ -74,7 +80,9 @@ Announcements regarding releases will be made to the #headerbidding-dev channel Run `gulp coveralls` to update code coverage history. -6. Distribute the code +6. Distribute the code + + _Note: do not go to step 7 until step 6 has been verified completed._ Reach out to any of the Appnexus folks to trigger the jenkins job. @@ -82,7 +90,7 @@ Announcements regarding releases will be made to the #headerbidding-dev channel Jenkins job is moving files to appnexus cdn, pushing prebid.js to npm, purging cache and sending notification to slack. Move all the files from Appnexus CDN to jsDelivr and create bash script to do above tasks. -7. Post Release Steps +7. Post Release Version Update the version Manually edit Prebid's package.json to become "1.x.x-pre" (using the values for the next release). Then commit your changes. @@ -90,6 +98,32 @@ Announcements regarding releases will be made to the #headerbidding-dev channel git commit -m "Increment pre version" git push ``` + +8. Create new release draft + + Go to [github releases](https://github.com/prebid/Prebid.js/releases) and add a new draft for the next version of Prebid.js with the following template: +``` +## 🚀New Features + +## 🛠Maintenance + +## 🐛Bug Fixes +``` + +## Beta Releases + +Prebid.js features may be released as Beta or as Generally Available (GA). + +Characteristics of a `Beta` release: +- May be a partial implementation (e.g. more work needed to flesh out the feature) +- May not be fully tested with other features +- Limited documentation, focused on technical aspects +- Few users + +Characteristics of a `GA` release: +- Complete set of functionality +- Significant user base with no major issues for at least a month +- Decent documentation that includes business need, use cases, and examples ## FAQs diff --git a/browsers.json b/browsers.json index cb523addc7e..703bf44d41d 100644 --- a/browsers.json +++ b/browsers.json @@ -62,21 +62,5 @@ "browser_version": "8.0", "device": null, "os": "OS X" - }, - "bs_ios_9": { - "base": "BrowserStack", - "os": "ios", - "os_version": "9.1", - "browser": "iphone", - "device": "iPhone 6S", - "browser_version": null - }, - "bs_ios_8": { - "base": "BrowserStack", - "os": "ios", - "os_version": "8.3", - "browser": "iphone", - "device": "iPhone 6", - "browser_version": null } } \ No newline at end of file diff --git a/governance.md b/governance.md index 9f8a1fe1e13..3d00f067194 100644 --- a/governance.md +++ b/governance.md @@ -2,10 +2,10 @@ This document describes the governance model for the Prebid project. The Prebid project’s stated mission is to facilitate fair, transparent, and effective header bidding across the industry, and is responsible for creating and maintaining such projects as [Prebid.js](https://github.com/prebid/Prebid.js). -1. A single Tech Lead oversees the technical direction of the project and appoints Core Team members +1. A single Tech Lead (PMC Chair) oversees the technical direction of the project and appoints Core Team members 2. The Core Team members maintain the project on an ongoing basis with direction from the Tech Lead. 3. In the event of any disagreements, the Tech Lead will make a final decision. -4. If there is no Tech Lead available to perform his/her duties, AppNexus Inc. will appoint one. +4. If there is no Tech Lead available to perform his/her duties, Prebid.org will appoint one. ### Roles and Responsibilities: - **User:** Any individual who consumes / uses the Prebid.js library. @@ -15,9 +15,9 @@ This document describes the governance model for the Prebid project. The Prebid ### Current Prebid.js Core Team - @mkendall07 (Tech Lead) -- @protonate +- @jsnellbaker - @matthewlane - @jaiminpanchal27 - @snapwich - @harpere -- @dbemiller +- @mike-chowla diff --git a/gulpfile.js b/gulpfile.js index d2955f7d777..ced29b266a7 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -5,18 +5,15 @@ var argv = require('yargs').argv; var gulp = require('gulp'); var gutil = require('gulp-util'); var connect = require('gulp-connect'); -var path = require('path'); var webpack = require('webpack'); var webpackStream = require('webpack-stream'); var uglify = require('gulp-uglify'); -var clean = require('gulp-clean'); +var gulpClean = require('gulp-clean'); var KarmaServer = require('karma').Server; var karmaConfMaker = require('./karma.conf.maker'); var opens = require('open'); var webpackConfig = require('./webpack.conf'); var helpers = require('./gulpHelpers'); -var del = require('del'); -var gulpDocumentation = require('gulp-documentation'); var concat = require('gulp-concat'); var header = require('gulp-header'); var footer = require('gulp-footer'); @@ -36,23 +33,131 @@ var banner = '/* <%= prebid.name %> v<%= prebid.version %>\n' + dateString + ' * var analyticsDirectory = '../analytics'; var port = 9999; -// Tasks -gulp.task('default', ['webpack']); +// these modules must be explicitly listed in --modules to be included in the build, won't be part of "all" modules +var explicitModules = [ + 'pre1api' +]; -gulp.task('serve', ['lint', 'build-bundle-dev', 'watch', 'test']); +// all the following functions are task functions +function bundleToStdout() { + nodeBundle().then(file => console.log(file)); +} +bundleToStdout.displayName = 'bundle-to-stdout'; -gulp.task('serve-nw', ['lint', 'watch', 'e2etest']); +function clean() { + return gulp.src(['build'], { + read: false, + allowEmpty: true + }) + .pipe(gulpClean()); +} + +function e2etestReport() { + var reportPort = 9010; + var targetDestinationDir = './e2etest-report'; + helpers.createEnd2EndTestReport(targetDestinationDir); + connect.server({ + port: reportPort, + root: './', + livereload: true + }); -gulp.task('run-tests', ['lint', 'test-coverage']); + setTimeout(function() { + opens('http://localhost:' + reportPort + '/' + targetDestinationDir.slice(2) + '/results.html'); + }, 5000); +}; +e2etestReport.displayName = 'e2etest-report'; -gulp.task('build', ['build-bundle-prod']); +// Dependant task for building postbid. It escapes postbid-config file. +function escapePostbidConfig() { + gulp.src('./integrationExamples/postbid/oas/postbid-config.js') + .pipe(jsEscape()) + .pipe(gulp.dest('build/postbid/')); +}; +escapePostbidConfig.displayName = 'escape-postbid-config'; -gulp.task('clean', function () { - return gulp.src(['build'], { - read: false - }) - .pipe(clean()); -}); +function lint() { + return gulp.src(['src/**/*.js', 'modules/**/*.js', 'test/**/*.js']) + .pipe(eslint()) + .pipe(eslint.format('stylish')) + .pipe(eslint.failAfterError()); +}; + +// View the code coverage report in the browser. +function viewCoverage(done) { + var coveragePort = 1999; + + connect.server({ + port: coveragePort, + root: 'build/coverage/karma_html', + livereload: false + }); + opens('http://localhost:' + coveragePort); + done(); +}; +viewCoverage.displayName = 'view-coverage'; + +// Watch Task with Live Reload +function watch(done) { + var mainWatcher = gulp.watch([ + 'src/**/*.js', + 'modules/**/*.js', + 'test/spec/**/*.js', + '!test/spec/loaders/**/*.js' + ]); + var loaderWatcher = gulp.watch([ + 'loaders/**/*.js', + 'test/spec/loaders/**/*.js' + ]); + + connect.server({ + https: argv.https, + port: port, + root: './', + livereload: true + }); + + mainWatcher.on('all', gulp.series(clean, gulp.parallel(lint, 'build-bundle-dev', test))); + loaderWatcher.on('all', gulp.series(lint)); + done(); +}; + +function makeDevpackPkg() { + var cloned = _.cloneDeep(webpackConfig); + cloned.devtool = 'source-map'; + var externalModules = helpers.getArgModules(); + + const analyticsSources = helpers.getAnalyticsSources(analyticsDirectory); + const moduleSources = helpers.getModulePaths(externalModules); + + return gulp.src([].concat(moduleSources, analyticsSources, 'src/prebid.js')) + .pipe(helpers.nameModules(externalModules)) + .pipe(webpackStream(cloned, webpack)) + .pipe(replace('$prebid.version$', prebid.version)) + .pipe(gulp.dest('build/dev')) + .pipe(connect.reload()); +} + +function makeWebpackPkg() { + var cloned = _.cloneDeep(webpackConfig); + + delete cloned.devtool; + + var externalModules = helpers.getArgModules(); + + const analyticsSources = helpers.getAnalyticsSources(analyticsDirectory); + const moduleSources = helpers.getModulePaths(externalModules); + + return gulp.src([].concat(moduleSources, analyticsSources, 'src/prebid.js')) + .pipe(helpers.nameModules(externalModules)) + .pipe(webpackStream(cloned, webpack)) + .pipe(replace('$prebid.version$', prebid.version)) + .pipe(uglify()) + .pipe(gulpif(file => file.basename === 'prebid-core.js', header(banner, { prebid: prebid }))) + .pipe(optimizejs()) + .pipe(gulp.dest('build/dist')) + .pipe(connect.reload()); +} function gulpBundle(dev) { return bundle(dev).pipe(gulp.dest('build/' + (dev ? 'dev' : 'dist'))); @@ -71,20 +176,15 @@ function nodeBundle(modules) { }); } -// these modules must be explicitly listed in --modules to be included in the build, won't be part of "all" modules -var explicitModules = [ - 'pre1api' -]; - function bundle(dev, moduleArr) { - var modules = moduleArr || helpers.getArgModules(), - allModules = helpers.getModuleNames(modules); + var modules = moduleArr || helpers.getArgModules(); + var allModules = helpers.getModuleNames(modules); - if(modules.length === 0) { - modules = allModules.filter(module => !explicitModules.includes(module)); + if (modules.length === 0) { + modules = allModules.filter(module => explicitModules.indexOf(module) === -1); } else { var diff = _.difference(modules, allModules); - if(diff.length !== 0) { + if (diff.length !== 0) { throw new gutil.PluginError({ plugin: 'bundle', message: 'invalid modules: ' + diff.join(', ') @@ -106,13 +206,13 @@ function bundle(dev, moduleArr) { gutil.log('Generating bundle:', outputFileName); return gulp.src( - entries - ) + entries + ) .pipe(gulpif(dev, sourcemaps.init({loadMaps: true}))) .pipe(concat(outputFileName)) .pipe(gulpif(!argv.manualEnable, footer('\n<%= global %>.processQueue();', { - global: prebid.globalVarName - } + global: prebid.globalVarName + } ))) .pipe(gulpif(dev, sourcemaps.write('.'))); } @@ -125,7 +225,8 @@ function newKarmaCallback(done) { done(new Error('Karma tests failed with exit code ' + exitCode)); } else { if (argv.browserstack) { - process.exit(0); + // process.exit(0); + done(); // test this with travis (or circleci) } else { done(); } @@ -133,51 +234,6 @@ function newKarmaCallback(done) { } } -gulp.task('build-bundle-dev', ['devpack'], gulpBundle.bind(null, true)); -gulp.task('build-bundle-prod', ['webpack'], gulpBundle.bind(null, false)); -gulp.task('bundle', gulpBundle.bind(null, false)); // used for just concatenating pre-built files with no build step - -gulp.task('bundle-to-stdout', function() { - nodeBundle().then(file => console.log(file)); -}); - -gulp.task('devpack', ['clean'], function () { - var cloned = _.cloneDeep(webpackConfig); - cloned.devtool = 'source-map'; - var externalModules = helpers.getArgModules(); - - const analyticsSources = helpers.getAnalyticsSources(analyticsDirectory); - const moduleSources = helpers.getModulePaths(externalModules); - - return gulp.src([].concat(moduleSources, analyticsSources, 'src/prebid.js')) - .pipe(helpers.nameModules(externalModules)) - .pipe(webpackStream(cloned, webpack)) - .pipe(replace('$prebid.version$', prebid.version)) - .pipe(gulp.dest('build/dev')) - .pipe(connect.reload()); -}); - -gulp.task('webpack', ['clean'], function () { - var cloned = _.cloneDeep(webpackConfig); - - delete cloned.devtool; - - var externalModules = helpers.getArgModules(); - - const analyticsSources = helpers.getAnalyticsSources(analyticsDirectory); - const moduleSources = helpers.getModulePaths(externalModules); - - return gulp.src([].concat(moduleSources, analyticsSources, 'src/prebid.js')) - .pipe(helpers.nameModules(externalModules)) - .pipe(webpackStream(cloned, webpack)) - .pipe(replace('$prebid.version$', prebid.version)) - .pipe(uglify()) - .pipe(gulpif(file => file.basename === 'prebid-core.js', header(banner, { prebid: prebid }))) - .pipe(optimizejs()) - .pipe(gulp.dest('build/dist')) - .pipe(connect.reload()); -}); - // Run the unit tests. // // By default, this runs in headless chrome. @@ -186,41 +242,33 @@ gulp.task('webpack', ['clean'], function () { // If --file "" is given, the task will only run tests in the specified file. // If --browserstack is given, it will run the full suite of currently supported browsers. // If --browsers is given, browsers can be chosen explicitly. e.g. --browsers=chrome,firefox,ie9 -gulp.task('test', ['clean'], function (done) { - var karmaConf = karmaConfMaker(false, argv.browserstack, argv.watch, argv.file); +// If --notest is given, it will immediately skip the test task (useful for developing changes with `gulp serve --notest`) +function test(done) { + if (argv.notest) { + done(); + } else { + var karmaConf = karmaConfMaker(false, argv.browserstack, argv.watch, argv.file); - var browserOverride = helpers.parseBrowserArgs(argv).map(helpers.toCapitalCase); - if (browserOverride.length > 0) { - karmaConf.browsers = browserOverride; - } + var browserOverride = helpers.parseBrowserArgs(argv).map(helpers.toCapitalCase); + if (browserOverride.length > 0) { + karmaConf.browsers = browserOverride; + } - new KarmaServer(karmaConf, newKarmaCallback(done)).start(); -}); + new KarmaServer(karmaConf, newKarmaCallback(done)).start(); + } +} // If --file "" is given, the task will only run tests in the specified file. -gulp.task('test-coverage', ['clean'], function(done) { +function testCoverage(done) { new KarmaServer(karmaConfMaker(true, false, false, argv.file), newKarmaCallback(done)).start(); -}); - -// View the code coverage report in the browser. -gulp.task('view-coverage', function (done) { - var coveragePort = 1999; - - connect.server({ - port: coveragePort, - root: 'build/coverage/karma_html', - livereload: false - }); - opens('http://localhost:' + coveragePort); - done(); -}); +} -gulp.task('coveralls', ['test-coverage'], function() { // 2nd arg is a dependency: 'test' must be finished +function coveralls() { // 2nd arg is a dependency: 'test' must be finished // first send results of istanbul's test coverage to coveralls.io. return gulp.src('gulpfile.js', { read: false }) // You have to give it a file, but you don't // have to read it. .pipe(shell('cat build/coverage/lcov.info | node_modules/coveralls/bin/coveralls.js')); -}); +} // Watch Task with Live Reload gulp.task('watch', function () { @@ -229,7 +277,7 @@ gulp.task('watch', function () { 'modules/**/*.js', 'test/spec/**/*.js', '!test/spec/loaders/**/*.js' - ], ['lint', 'build-bundle-dev', 'test']); + ], ['build-bundle-dev', 'test']); gulp.watch([ 'loaders/**/*.js', 'test/spec/loaders/**/*.js' @@ -242,29 +290,9 @@ gulp.task('watch', function () { }); }); -gulp.task('lint', () => { - return gulp.src(['src/**/*.js', 'modules/**/*.js', 'test/**/*.js']) - .pipe(eslint()) - .pipe(eslint.format('stylish')) - .pipe(eslint.failAfterError()); -}); - -gulp.task('clean-docs', function () { - del(['docs']); -}); - -gulp.task('docs', ['clean-docs'], function () { - return gulp.src('src/prebid.js') - .pipe(gulpDocumentation('md')) - .on('error', function (err) { - gutil.log('`gulp-documentation` failed:', err.message); - }) - .pipe(gulp.dest('docs')); -}); - -gulp.task('e2etest', ['devpack', 'webpack'], function() { +function e2eTest() { var cmdQueue = []; - if(argv.browserstack) { + if (argv.browserstack) { var browsers = require('./browsers.json'); delete browsers['bs_ie_9_windows_7']; @@ -276,11 +304,11 @@ gulp.task('e2etest', ['devpack', 'webpack'], function() { var startWith = 'bs'; - Object.keys(browsers).filter(function(v){ + Object.keys(browsers).filter(function(v) { return v.substring(0, startWith.length) === startWith && browsers[v].browser !== 'iphone'; - }).map(function(v,i,arr) { - var newArr = (i%2 === 0) ? arr.slice(i,i+2) : null; - if(newArr) { + }).map(function(v, i, arr) { + var newArr = (i % 2 === 0) ? arr.slice(i, i + 2) : null; + if (newArr) { var cmd = 'nightwatch --env ' + newArr.join(',') + cmdStr; cmdQueue.push(cmd); } @@ -289,38 +317,50 @@ gulp.task('e2etest', ['devpack', 'webpack'], function() { return gulp.src('') .pipe(shell(cmdQueue.join(';'))); -}); - -gulp.task('e2etest-report', function() { - var reportPort = 9010; - var targetDestinationDir = './e2etest-report'; - helpers.createEnd2EndTestReport(targetDestinationDir); - connect.server({ - port: reportPort, - root: './', - livereload: true - }); - - setTimeout(function() { - opens('http://localhost:' + reportPort + '/' + targetDestinationDir.slice(2) + '/results.html'); - }, 5000); -}); +} // This task creates postbid.js. Postbid setup is different from prebid.js // More info can be found here http://prebid.org/overview/what-is-post-bid.html -gulp.task('build-postbid', ['escape-postbid-config'], function() { + +function buildPostbid() { var fileContent = fs.readFileSync('./build/postbid/postbid-config.js', 'utf8'); return gulp.src('./integrationExamples/postbid/oas/postbid.js') .pipe(replace('\[%%postbid%%\]', fileContent)) .pipe(gulp.dest('build/postbid/')); -}); +} -// Dependant task for building postbid. It escapes postbid-config file. -gulp.task('escape-postbid-config', function() { - gulp.src('./integrationExamples/postbid/oas/postbid-config.js') - .pipe(jsEscape()) - .pipe(gulp.dest('build/postbid/')); -}); +// support tasks +gulp.task(lint); +gulp.task(watch); + +gulp.task(clean); + +gulp.task(escapePostbidConfig); + +gulp.task('build-bundle-dev', gulp.series(makeDevpackPkg, gulpBundle.bind(null, true))); +gulp.task('build-bundle-prod', gulp.series(makeWebpackPkg, gulpBundle.bind(null, false))); + +// public tasks (dependencies are needed for each task since they can be ran on their own) +gulp.task('test', gulp.series(clean, lint, test)); + +gulp.task('test-coverage', gulp.series(clean, testCoverage)); +gulp.task(viewCoverage); + +gulp.task('coveralls', gulp.series('test-coverage', coveralls)); + +gulp.task('build', gulp.series(clean, 'build-bundle-prod')); +gulp.task('build-postbid', gulp.series(escapePostbidConfig, buildPostbid)); + +gulp.task('serve', gulp.series(clean, lint, gulp.parallel('build-bundle-dev', watch, test))); +gulp.task('default', gulp.series(clean, makeWebpackPkg)); + +gulp.task(e2etestReport); +gulp.task('e2etest', gulp.series(clean, gulp.parallel(makeDevpackPkg, makeWebpackPkg), e2eTest)); + +// other tasks +gulp.task(bundleToStdout); +gulp.task('bundle', gulpBundle.bind(null, false)); // used for just concatenating pre-built files with no build step +gulp.task('serve-nw', gulp.parallel(lint, watch, 'e2etest')); module.exports = nodeBundle; diff --git a/integrationExamples/gpt/hello_world.html b/integrationExamples/gpt/hello_world.html index a5949b87c56..e1cdaa0dc29 100644 --- a/integrationExamples/gpt/hello_world.html +++ b/integrationExamples/gpt/hello_world.html @@ -1,98 +1,101 @@ - - - - - - - - - - - - - - - -

Prebid.js Test

-
Div-1
-
- -
- + + + + + + + + + + + + + + + +

Prebid.js Test

+
Div-1
+
+ +
+ \ No newline at end of file diff --git a/integrationExamples/gpt/pbjs_example_gpt.html b/integrationExamples/gpt/pbjs_example_gpt.html index f1ec912fd26..536bc5a655d 100644 --- a/integrationExamples/gpt/pbjs_example_gpt.html +++ b/integrationExamples/gpt/pbjs_example_gpt.html @@ -269,6 +269,13 @@ placement_id: 0 } }, + { + bidder: 'weborama', + params: { + placementId: 0, + traffic: 'banner' + } + }, { bidder: 'pollux', params: { @@ -281,7 +288,22 @@ pubId: 50357, //REQUIRED host: 'dsp-staging.adkernel.com' //OPTIONAL } + }, + { + bidder: 'bizzclick', + params: { + placementId: 0, + type: "banner" + } + }, + { + bidder: 'zedo', + params: { + channelCode: 2264002816, //REQUIRED + dimId: 9 //REQUIRED + } } + ] }, { code: 'div-gpt-ad-12345678-1', @@ -413,6 +435,13 @@ params: { zone: '276' // REQUIRED Zone Id (276 is a test zone) } + }, + { + bidder: 'bizzclick', + params: { + placementId: 0, + type: "banner" + } } ] } diff --git a/integrationExamples/gpt/pbjs_ucfunnel_gpt.html b/integrationExamples/gpt/pbjs_ucfunnel_gpt.html deleted file mode 100644 index cda2af03b18..00000000000 --- a/integrationExamples/gpt/pbjs_ucfunnel_gpt.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - -

Prebid.js Test

-
Div-1
- - -
- -
- - - diff --git a/integrationExamples/gpt/prebidServer_example.html b/integrationExamples/gpt/prebidServer_example.html index 2f91c2b966f..f13c93963c6 100644 --- a/integrationExamples/gpt/prebidServer_example.html +++ b/integrationExamples/gpt/prebidServer_example.html @@ -4,7 +4,6 @@ var PREBID_TIMEOUT = 3000; var googletag = googletag || {}; - var sizes = [[728, 90],[300, 250], [300,600]]; googletag.cmd = googletag.cmd || []; function initAdserver() { @@ -37,12 +36,12 @@ pbjs.que.push(function() { var adUnits = [{ code: 'div-gpt-ad-1460505748561-0', - sizes: [[300, 250], [300,600]], + sizes: [[300, 250]], bids: [ { bidder: 'appnexus', params: { - placementId: '10433394' + placementId: '13144370' } } ] @@ -56,7 +55,7 @@ bidders : ['appnexus'], timeout : 1000, //default value is 1000 adapter : 'prebidServer', //if we have any other s2s adapter, default value is s2s - endpoint : 'https://prebid.adnxs.com/pbs/v1/auction?url_override=http%3A%2F%2Fwww.nytimes.com' + endpoint : 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' } }); @@ -72,7 +71,7 @@ - + \');'; }; -describe('AolAdapter', () => { +describe('AolAdapter', function () { const MARKETPLACE_URL = '//adserver-us.adtech.advertising.com/pubapi/3.0/'; const NEXAGE_URL = '//hb.nexage.com/bidRequest?'; const ONE_DISPLAY_TTL = 60; @@ -92,15 +92,14 @@ describe('AolAdapter', () => { return bidderRequest; } - describe('interpretResponse()', () => { + describe('interpretResponse()', function () { let bidderSettingsBackup; let bidResponse; let bidRequest; let logWarnSpy; - let formatPixelsStub; let isOneMobileBidderStub; - beforeEach(() => { + beforeEach(function () { bidderSettingsBackup = $$PREBID_GLOBAL$$.bidderSettings; bidRequest = { bidderCode: 'test-bidder-code', @@ -111,18 +110,16 @@ describe('AolAdapter', () => { body: getDefaultBidResponse() }; logWarnSpy = sinon.spy(utils, 'logWarn'); - formatPixelsStub = sinon.stub(spec, 'formatPixels'); isOneMobileBidderStub = sinon.stub(spec, 'isOneMobileBidder'); }); - afterEach(() => { + afterEach(function () { $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsBackup; logWarnSpy.restore(); - formatPixelsStub.restore(); isOneMobileBidderStub.restore(); }); - it('should return formatted bid response with required properties', () => { + it('should return formatted bid response with required properties', function () { let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); expect(formattedBidResponse).to.deep.equal({ bidderCode: bidRequest.bidderCode, @@ -139,47 +136,26 @@ describe('AolAdapter', () => { ttl: bidRequest.ttl }); }); - - it('should add pixels to ad content when pixels are present in the response', () => { - bidResponse.body.ext = { - pixels: 'pixels-content' - }; - - formatPixelsStub.returns('pixels-content'); - let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); - - expect(formattedBidResponse.ad).to.equal(DEFAULT_AD_CONTENT + 'pixels-content'); - }); - - it('should show warning in the console', function() { - $$PREBID_GLOBAL$$.bidderSettings = { - aol: { - bidCpmAdjustment: function() {} - } - }; - spec.interpretResponse(bidResponse, bidRequest); - expect(utils.logWarn.calledOnce).to.be.true; - }); }); - describe('buildRequests()', () => { - it('method exists and is a function', () => { + describe('buildRequests()', function () { + it('method exists and is a function', function () { expect(spec.buildRequests).to.exist.and.to.be.a('function'); }); - describe('Marketplace', () => { - it('should not return request when no bids are present', () => { + describe('Marketplace', function () { + it('should not return request when no bids are present', function () { let [request] = spec.buildRequests([]); expect(request).to.be.empty; }); - it('should return request for Marketplace endpoint', () => { + it('should return request for Marketplace endpoint', function () { let bidRequest = getDefaultBidRequest(); let [request] = spec.buildRequests(bidRequest.bids); expect(request.url).to.contain(MARKETPLACE_URL); }); - it('should return request for Marketplace via onedisplay bidder code', () => { + it('should return request for Marketplace via onedisplay bidder code', function () { let bidRequest = createCustomBidRequest({ bids: [{ bidder: 'onedisplay' @@ -233,7 +209,7 @@ describe('AolAdapter', () => { expect(request).to.be.empty; }); - it('should return Marketplace URL for eu region', () => { + it('should return Marketplace URL for eu region', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -245,7 +221,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/'); }); - it('should return Marketplace URL for eu region when server option is present', () => { + it('should return Marketplace URL for eu region when server option is present', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -257,7 +233,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain('adserver-eu.adtech.advertising.com/pubapi/3.0/'); }); - it('should return default Marketplace URL in case of unknown region config option', () => { + it('should return default Marketplace URL in case of unknown region config option', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -269,25 +245,25 @@ describe('AolAdapter', () => { expect(request.url).to.contain(MARKETPLACE_URL); }); - it('should return url with pubapi bid option', () => { + 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', () => { + 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', () => { + 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', () => { + it('should return url with default pageId and sizeId', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -298,7 +274,7 @@ describe('AolAdapter', () => { 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', () => { + it('should return url with custom pageId and sizeId when options are present', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -311,13 +287,13 @@ describe('AolAdapter', () => { 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', () => { + 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', () => { + it('should return url with custom alias if it is present', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -329,13 +305,13 @@ describe('AolAdapter', () => { expect(request.url).to.contain('alias=desktop_articlepage_something_box_300_250'); }); - it('should return url without bidfloor option if is is missing', () => { + 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 bidFloor option if it is present', () => { + it('should return url with bidFloor option if it is present', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -347,7 +323,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain('bidfloor=0.8'); }); - it('should return url with key values if keyValues param is present', () => { + it('should return url with key values if keyValues param is present', function () { let bidRequest = createCustomBidRequest({ params: { placement: 1234567, @@ -363,7 +339,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain('kvage=25;kvheight=3.42;kvtest=key'); }); - it('should return request object for One Display when configuration is present', () => { + 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'); @@ -371,8 +347,8 @@ describe('AolAdapter', () => { }); }); - describe('One Mobile', () => { - it('should return One Mobile url when One Mobile get params are present', () => { + describe('One Mobile', function () { + it('should return One Mobile url when One Mobile get params are present', function () { let bidRequest = createCustomBidRequest({ params: getNexageGetBidParams() }); @@ -380,7 +356,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain(NEXAGE_URL); }); - it('should return One Mobile url with different host when host option is present', () => { + it('should return One Mobile url with different host when host option is present', function () { let bidParams = Object.assign({ host: 'qa-hb.nexage.com' }, getNexageGetBidParams()); @@ -391,7 +367,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain('qa-hb.nexage.com/bidRequest?'); }); - it('should return One Mobile url when One Mobile and Marketplace params are present', () => { + 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 @@ -425,7 +401,7 @@ describe('AolAdapter', () => { expect(request).to.be.empty; }); - it('should return One Mobile url with required params - dcn & pos', () => { + it('should return One Mobile url with required params - dcn & pos', function () { let bidRequest = createCustomBidRequest({ params: getNexageGetBidParams() }); @@ -433,7 +409,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain(NEXAGE_URL + 'dcn=2c9d2b50015c5ce9db6aeeed8b9500d6&pos=header'); }); - it('should return One Mobile url with cmd=bid option', () => { + it('should return One Mobile url with cmd=bid option', function () { let bidRequest = createCustomBidRequest({ params: getNexageGetBidParams() }); @@ -441,7 +417,7 @@ describe('AolAdapter', () => { expect(request.url).to.contain('cmd=bid'); }); - it('should return One Mobile url with generic params if ext option is present', () => { + it('should return One Mobile url with generic params if ext option is present', function () { let bidRequest = createCustomBidRequest({ params: { dcn: '54321123', @@ -459,7 +435,7 @@ describe('AolAdapter', () => { '¶m1=val1¶m2=val2¶m3=val3¶m4=val4'); }); - it('should return request object for One Mobile POST endpoint when POST configuration is present', () => { + it('should return request object for One Mobile POST endpoint when POST configuration is present', function () { let bidConfig = getNexagePostBidParams(); let bidRequest = createCustomBidRequest({ params: bidConfig @@ -491,101 +467,71 @@ describe('AolAdapter', () => { }); }); - describe('getUserSyncs()', () => { + describe('getUserSyncs()', function () { + let serverResponses; let bidResponse; - let bidRequest; - beforeEach(() => { - $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = false; - config.setConfig({ - aol: { - userSyncOn: 'bidResponse' - }, - }); + beforeEach(function () { bidResponse = getDefaultBidResponse(); bidResponse.ext = { pixels: getPixels() }; + + serverResponses = [ + {body: bidResponse} + ]; }); - it('should return user syncs only if userSyncOn equals to "bidResponse"', () => { - let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); + it('should return user syncs if pixels are present in the response', function () { + let userSyncs = spec.getUserSyncs({}, serverResponses); - expect($$PREBID_GLOBAL$$.aolGlobals.pixelsDropped).to.be.true; expect(userSyncs).to.deep.equal([ {type: 'image', url: 'img.org'}, {type: 'iframe', url: 'pixels1.org'} ]); }); - it('should not return user syncs if it has already been returned', () => { - $$PREBID_GLOBAL$$.aolGlobals.pixelsDropped = true; - - let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); - - expect($$PREBID_GLOBAL$$.aolGlobals.pixelsDropped).to.be.true; - expect(userSyncs).to.deep.equal([]); - }); - - it('should not return user syncs if pixels are not present', () => { + it('should not return user syncs if pixels are not present', function () { bidResponse.ext.pixels = null; + let userSyncs = spec.getUserSyncs({}, serverResponses); - let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); - - expect($$PREBID_GLOBAL$$.aolGlobals.pixelsDropped).to.be.false; expect(userSyncs).to.deep.equal([]); }); }); - describe('formatPixels()', () => { - it('should return pixels wrapped for dropping them once and within nested frames ', () => { - let pixels = ''; - let formattedPixels = spec.formatPixels(pixels); - - expect(formattedPixels).to.equal( - ''); - }); - }); - - describe('isOneMobileBidder()', () => { + 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', () => { + it('should return false for unknown bidder code', function () { expect(spec.isOneMobileBidder('unknownBidder')).to.be.false; }); - it('should return true for aol bidder code', () => { + 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', () => { + it('should return true for one mobile bidder code', function () { expect(spec.isOneMobileBidder('onemobile')).to.be.true; }); }); - describe('isConsentRequired()', () => { - it('should return false when consentData object is not present', () => { + describe('isConsentRequired()', function () { + it('should return false when consentData object is not present', function () { expect(spec.isConsentRequired(null)).to.be.false; }); - it('should return false when gdprApplies equals true and consentString is not present', () => { + it('should return true when gdprApplies equals true and consentString is not present', function () { let consentData = { consentString: null, gdprApplies: true }; - expect(spec.isConsentRequired(consentData)).to.be.false; + expect(spec.isConsentRequired(consentData)).to.be.true; }); - it('should return false when consentString is present and gdprApplies equals false', () => { + it('should return false when consentString is present and gdprApplies equals false', function () { let consentData = { consentString: 'consent-string', gdprApplies: false @@ -594,7 +540,7 @@ describe('AolAdapter', () => { expect(spec.isConsentRequired(consentData)).to.be.false; }); - it('should return true when consentString is present and gdprApplies equals true', () => { + it('should return true when consentString is present and gdprApplies equals true', function () { let consentData = { consentString: 'consent-string', gdprApplies: true @@ -604,50 +550,68 @@ describe('AolAdapter', () => { }); }); - describe('formatMarketplaceConsentData()', () => { - let consentRequiredStub; + describe('formatMarketplaceDynamicParams()', function () { + let formatConsentDataStub; + let formatKeyValuesStub; - beforeEach(() => { - consentRequiredStub = sinon.stub(spec, 'isConsentRequired'); + beforeEach(function () { + formatConsentDataStub = sinon.stub(spec, 'formatConsentData'); + formatKeyValuesStub = sinon.stub(spec, 'formatKeyValues'); }); - afterEach(() => { - consentRequiredStub.restore(); + afterEach(function () { + formatConsentDataStub.restore(); + formatKeyValuesStub.restore(); }); - it('should return empty string when consent is not required', () => { - consentRequiredStub.returns(false); - expect(spec.formatMarketplaceConsentData()).to.be.equal(''); + it('should return empty string when params are not present', function () { + expect(spec.formatMarketplaceDynamicParams()).to.be.equal(''); }); - it('should return formatted consent data when consent is required', () => { - consentRequiredStub.returns(true); - let formattedConsentData = spec.formatMarketplaceConsentData({ - consentString: 'test-consent' + it('should return formatted params when formatConsentData returns data', function () { + formatConsentDataStub.returns({ + euconsent: 'test-consent', + gdpr: 1 }); - expect(formattedConsentData).to.be.equal(';euconsent=test-consent;gdpr=1'); + expect(spec.formatMarketplaceDynamicParams()).to.be.equal('euconsent=test-consent;gdpr=1;'); + }); + + 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;'); + }); + + it('should return formatted bid floor param when it is present', function () { + let params = { + bidFloor: 0.45 + }; + expect(spec.formatMarketplaceDynamicParams(params)).to.be.equal('bidfloor=0.45;'); }); }); - describe('formatOneMobileDynamicParams()', () => { + describe('formatOneMobileDynamicParams()', function () { let consentRequiredStub; let secureProtocolStub; - beforeEach(() => { + beforeEach(function () { consentRequiredStub = sinon.stub(spec, 'isConsentRequired'); secureProtocolStub = sinon.stub(spec, 'isSecureProtocol'); }); - afterEach(() => { + afterEach(function () { consentRequiredStub.restore(); secureProtocolStub.restore(); }); - it('should return empty string when params are not present', () => { + 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', () => { + it('should return formatted params when params are present', function () { let params = { param1: 'val1', param2: 'val2', @@ -656,15 +620,15 @@ describe('AolAdapter', () => { expect(spec.formatOneMobileDynamicParams(params)).to.contain('¶m1=val1¶m2=val2¶m3=val3'); }); - it('should return formatted gdpr params when isConsentRequired returns true', () => { + it('should return formatted gdpr params when isConsentRequired returns true', function () { let consentData = { consentString: 'test-consent' }; consentRequiredStub.returns(true); - expect(spec.formatOneMobileDynamicParams({}, consentData)).to.be.equal('&euconsent=test-consent&gdpr=1'); + expect(spec.formatOneMobileDynamicParams({}, consentData)).to.be.equal('&gdpr=1&euconsent=test-consent'); }); - it('should return formatted secure param when isSecureProtocol returns true', () => { + 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/appnexusBidAdapter_spec.js b/test/spec/modules/appnexusBidAdapter_spec.js index abfd50d1746..9be87ac8628 100644 --- a/test/spec/modules/appnexusBidAdapter_spec.js +++ b/test/spec/modules/appnexusBidAdapter_spec.js @@ -5,16 +5,16 @@ import { deepClone } from 'src/utils'; const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; -describe('AppNexusAdapter', () => { +describe('AppNexusAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'appnexus', 'params': { @@ -27,11 +27,11 @@ describe('AppNexusAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when required params found', () => { + it('should return true when required params found', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -42,7 +42,7 @@ describe('AppNexusAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -52,7 +52,7 @@ describe('AppNexusAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'appnexus', @@ -67,7 +67,7 @@ describe('AppNexusAdapter', () => { } ]; - it('should parse out private sizes', () => { + it('should parse out private sizes', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -85,7 +85,7 @@ describe('AppNexusAdapter', () => { expect(payload.tags[0].private_sizes).to.deep.equal([{width: 300, height: 250}]); }); - it('should add source and verison to the tag', () => { + it('should add source and verison to the tag', function () { const request = spec.buildRequests(bidRequests); const payload = JSON.parse(request.data); expect(payload.sdk).to.exist; @@ -95,7 +95,7 @@ describe('AppNexusAdapter', () => { }); }); - it('should populate the ad_types array on all requests', () => { + it('should populate the ad_types array on all requests', function () { ['banner', 'video', 'native'].forEach(type => { const bidRequest = Object.assign({}, bidRequests[0]); bidRequest.mediaTypes = {}; @@ -108,7 +108,7 @@ describe('AppNexusAdapter', () => { }); }); - it('should populate the ad_types array on outstream requests', () => { + it('should populate the ad_types array on outstream requests', function () { const bidRequest = Object.assign({}, bidRequests[0]); bidRequest.mediaTypes = {}; bidRequest.mediaTypes.video = {context: 'outstream'}; @@ -119,13 +119,13 @@ describe('AppNexusAdapter', () => { expect(payload.tags[0].ad_types).to.deep.equal(['video']); }); - it('sends bid request to ENDPOINT via POST', () => { + it('sends bid request to ENDPOINT via POST', function () { const request = spec.buildRequests(bidRequests); expect(request.url).to.equal(ENDPOINT); expect(request.method).to.equal('POST'); }); - it('should attach valid video params to the tag', () => { + it('should attach valid video params to the tag', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -148,7 +148,7 @@ describe('AppNexusAdapter', () => { }); }); - it('should attach valid user params to the tag', () => { + it('should attach valid user params to the tag', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -171,7 +171,7 @@ describe('AppNexusAdapter', () => { }); }); - it('should attach native params to the request', () => { + it('should attach native params to the request', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -198,7 +198,7 @@ describe('AppNexusAdapter', () => { }); }); - it('sets minimum native asset params when not provided on adunit', () => { + it('sets minimum native asset params when not provided on adunit', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -217,7 +217,7 @@ describe('AppNexusAdapter', () => { }); }); - it('does not overwrite native ad unit params with mimimum params', () => { + it('does not overwrite native ad unit params with mimimum params', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -249,7 +249,7 @@ describe('AppNexusAdapter', () => { }); }); - it('should convert keyword params to proper form and attaches to request', () => { + it('should convert keyword params to proper form and attaches to request', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -288,7 +288,7 @@ describe('AppNexusAdapter', () => { }]); }); - it('should add payment rules to the request', () => { + it('should add payment rules to the request', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -305,7 +305,7 @@ describe('AppNexusAdapter', () => { expect(payload.tags[0].use_pmt_rule).to.equal(true); }); - it('should add gdpr consent information to the request', () => { + it('should add gdpr consent information to the request', function () { let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; let bidderRequest = { 'bidderCode': 'appnexus', @@ -326,9 +326,79 @@ describe('AppNexusAdapter', () => { expect(payload.gdpr_consent.consent_string).to.exist.and.to.equal(consentString); expect(payload.gdpr_consent.consent_required).to.exist.and.to.be.true; }); + + it('supports sending hybrid mobile app parameters', function () { + let appRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + app: { + id: 'B1O2W3M4AN.com.prebid.webview', + geo: { + lat: 40.0964439, + lng: -75.3009142 + }, + device_id: { + idfa: '4D12078D-3246-4DA4-AD5E-7610481E7AE', // Apple advertising identifier + aaid: '38400000-8cf0-11bd-b23e-10b96e40000d', // Android advertising identifier + md5udid: '5756ae9022b2ea1e47d84fead75220c8', // MD5 hash of the ANDROID_ID + sha1udid: '4DFAA92388699AC6539885AEF1719293879985BF', // SHA1 hash of the ANDROID_ID + windowsadid: '750c6be243f1c4b5c9912b95a5742fc5' // Windows advertising identifier + } + } + } + } + ); + const request = spec.buildRequests([appRequest]); + const payload = JSON.parse(request.data); + expect(payload.app).to.exist; + expect(payload.app).to.deep.equal({ + appid: 'B1O2W3M4AN.com.prebid.webview' + }); + expect(payload.device.device_id).to.exist; + expect(payload.device.device_id).to.deep.equal({ + aaid: '38400000-8cf0-11bd-b23e-10b96e40000d', + idfa: '4D12078D-3246-4DA4-AD5E-7610481E7AE', + md5udid: '5756ae9022b2ea1e47d84fead75220c8', + sha1udid: '4DFAA92388699AC6539885AEF1719293879985BF', + windowsadid: '750c6be243f1c4b5c9912b95a5742fc5' + }); + expect(payload.device.geo).to.exist; + expect(payload.device.geo).to.deep.equal({ + lat: 40.0964439, + lng: -75.3009142 + }); + }); + + it('should add referer info to payload', function () { + const bidRequest = Object.assign({}, bidRequests[0]) + const bidderRequest = { + refererInfo: { + referer: 'http://example.com/page.html', + reachedTop: true, + numIframes: 2, + stack: [ + 'http://example.com/page.html', + 'http://example.com/iframe1.html', + 'http://example.com/iframe2.html' + ] + } + } + const request = spec.buildRequests([bidRequest], bidderRequest); + const payload = JSON.parse(request.data); + + expect(payload.referrer_detection).to.exist; + expect(payload.referrer_detection).to.deep.equal({ + rd_ref: 'http%3A%2F%2Fexample.com%2Fpage.html', + rd_top: true, + rd_ifs: 2, + rd_stk: bidderRequest.refererInfo.stack.map((url) => encodeURIComponent(url)).join(',') + }); + }); }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { 'version': '3.0.0', 'tags': [ @@ -373,7 +443,7 @@ describe('AppNexusAdapter', () => { ] }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { 'requestId': '3db3773286ee59', @@ -397,7 +467,7 @@ describe('AppNexusAdapter', () => { expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = { 'version': '0.0.1', 'tags': [{ @@ -413,7 +483,7 @@ describe('AppNexusAdapter', () => { expect(result.length).to.equal(0); }); - it('handles non-banner media responses', () => { + it('handles non-banner media responses', function () { let response = { 'tags': [{ 'uuid': '84ab500420319d', @@ -437,7 +507,7 @@ describe('AppNexusAdapter', () => { expect(result[0]).to.have.property('mediaType', 'video'); }); - it('handles native responses', () => { + it('handles native responses', function () { let response1 = deepClone(response); response1.tags[0].ads[0].ad_type = 'native'; response1.tags[0].ads[0].rtb.native = { @@ -471,7 +541,7 @@ describe('AppNexusAdapter', () => { expect(result[0].native.image.url).to.equal('http://cdn.adnxs.com/img.png'); }); - it('supports configuring outstream renderers', () => { + it('supports configuring outstream renderers', function () { const outstreamResponse = deepClone(response); outstreamResponse.tags[0].ads[0].rtb.video = {}; outstreamResponse.tags[0].ads[0].renderer_url = 'renderer.js'; diff --git a/test/spec/modules/arteebeeBidAdapter_spec.js b/test/spec/modules/arteebeeBidAdapter_spec.js index 041b48b0bc9..013e1bd6c0c 100644 --- a/test/spec/modules/arteebeeBidAdapter_spec.js +++ b/test/spec/modules/arteebeeBidAdapter_spec.js @@ -1,9 +1,9 @@ import {expect} from 'chai'; import {spec} from 'modules/arteebeeBidAdapter'; -describe('Arteebee adapater', () => { - describe('Test validate req', () => { - it('should accept minimum valid bid', () => { +describe('Arteebee adapater', function () { + describe('Test validate req', function () { + it('should accept minimum valid bid', function () { let bid = { bidder: 'arteebee', params: { @@ -16,7 +16,7 @@ describe('Arteebee adapater', () => { expect(isValid).to.equal(true); }); - it('should reject missing pub', () => { + it('should reject missing pub', function () { let bid = { bidder: 'arteebee', params: { @@ -28,7 +28,7 @@ describe('Arteebee adapater', () => { expect(isValid).to.equal(false); }); - it('should reject missing source', () => { + it('should reject missing source', function () { let bid = { bidder: 'arteebee', params: { @@ -41,8 +41,8 @@ describe('Arteebee adapater', () => { }); }); - describe('Test build request', () => { - it('minimum request', () => { + describe('Test build request', function () { + it('minimum request', function () { let bid = { bidder: 'arteebee', params: { @@ -59,7 +59,7 @@ describe('Arteebee adapater', () => { expect(req.imp[0]).to.not.have.property('secure'); }); - it('make test request', () => { + it('make test request', function () { let bid = { bidder: 'arteebee', params: { @@ -77,7 +77,7 @@ describe('Arteebee adapater', () => { expect(req.imp[0]).to.not.have.property('secure'); }); - it('test coppa', () => { + it('test coppa', function () { let bid = { bidder: 'arteebee', params: { @@ -95,7 +95,7 @@ describe('Arteebee adapater', () => { expect(req.imp[0]).to.not.have.property('secure'); }); - it('test gdpr', () => { + it('test gdpr', function () { let bid = { bidder: 'arteebee', params: { @@ -124,8 +124,8 @@ describe('Arteebee adapater', () => { }); }); - describe('Test interpret response', () => { - it('General banner response', () => { + describe('Test interpret response', function () { + it('General banner response', function () { let resp = spec.interpretResponse({ body: { id: 'abcd', diff --git a/test/spec/modules/atomxBidAdapter_spec.js b/test/spec/modules/atomxBidAdapter_spec.js index fdbb01a1838..fdcdb55ec7f 100644 --- a/test/spec/modules/atomxBidAdapter_spec.js +++ b/test/spec/modules/atomxBidAdapter_spec.js @@ -1,9 +1,9 @@ import { expect } from 'chai'; import { spec } from 'modules/atomxBidAdapter'; -describe('atomxAdapterTest', () => { - describe('bidRequestValidity', () => { - it('bidRequest with id param', () => { +describe('atomxAdapterTest', function () { + describe('bidRequestValidity', function () { + it('bidRequest with id param', function () { expect(spec.isBidRequestValid({ bidder: 'atomx', params: { @@ -12,7 +12,7 @@ describe('atomxAdapterTest', () => { })).to.equal(true); }); - it('bidRequest with no id param', () => { + it('bidRequest with no id param', function () { expect(spec.isBidRequestValid({ bidder: 'atomx', params: { @@ -21,7 +21,7 @@ describe('atomxAdapterTest', () => { }); }); - describe('bidRequest', () => { + describe('bidRequest', function () { const bidRequests = [{ 'bidder': 'atomx', 'params': { @@ -47,21 +47,21 @@ describe('atomxAdapterTest', () => { 'auctionId': 'e97cafd0-ebfc-4f5c-b7c9-baa0fd335a4a' }]; - it('bidRequest HTTP method', () => { + it('bidRequest HTTP method', function () { const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { expect(requestItem.method).to.equal('GET'); }); }); - it('bidRequest url', () => { + it('bidRequest url', function () { const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { expect(requestItem.url).to.match(new RegExp('p\\.ato\\.mx/placement')); }); }); - it('bidRequest data', () => { + it('bidRequest data', function () { const requests = spec.buildRequests(bidRequests); expect(requests[0].data.id).to.equal('123'); expect(requests[0].data.size).to.equal('300x250'); @@ -72,7 +72,7 @@ describe('atomxAdapterTest', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const bidRequest = { 'method': 'GET', 'url': 'https://p.ato.mx/placement', @@ -103,7 +103,7 @@ describe('atomxAdapterTest', () => { headers: {} }; - it('result is correct', () => { + it('result is correct', function () { const result = spec.interpretResponse(bidResponse, bidRequest); expect(result[0].requestId).to.equal('22aidtbx5eabd9'); diff --git a/test/spec/modules/audienceNetworkBidAdapter_spec.js b/test/spec/modules/audienceNetworkBidAdapter_spec.js index f9d46e100b1..2f7e5776354 100644 --- a/test/spec/modules/audienceNetworkBidAdapter_spec.js +++ b/test/spec/modules/audienceNetworkBidAdapter_spec.js @@ -19,36 +19,37 @@ const placementId = 'test-placement-id'; const playerwidth = 320; const playerheight = 180; const requestId = 'test-request-id'; -const pbv = '$prebid.version$'; +const debug = 'adapterver=1.1.0&platform=241394079772386&platver=$prebid.version$&cb=test-uuid'; +const pageUrl = encodeURIComponent(utils.getTopWindowUrl()); -describe('AudienceNetwork adapter', () => { - describe('Public API', () => { - it('code', () => { +describe('AudienceNetwork adapter', function () { + describe('Public API', function () { + it('code', function () { expect(code).to.equal(bidder); }); - it('supportedMediaTypes', () => { + it('supportedMediaTypes', function () { expect(supportedMediaTypes).to.deep.equal(['banner', 'video']); }); - it('isBidRequestValid', () => { + it('isBidRequestValid', function () { expect(isBidRequestValid).to.be.a('function'); }); - it('buildRequests', () => { + it('buildRequests', function () { expect(buildRequests).to.be.a('function'); }); - it('interpretResponse', () => { + it('interpretResponse', function () { expect(interpretResponse).to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - it('missing placementId parameter', () => { + describe('isBidRequestValid', function () { + it('missing placementId parameter', function () { expect(isBidRequestValid({ bidder, sizes: [[300, 250]] })).to.equal(false); }); - it('invalid sizes parameter', () => { + it('invalid sizes parameter', function () { expect(isBidRequestValid({ bidder, sizes: ['', undefined, null, '300x100', [300, 100], [300], {}], @@ -56,7 +57,7 @@ describe('AudienceNetwork adapter', () => { })).to.equal(false); }); - it('valid when at least one valid size', () => { + it('valid when at least one valid size', function () { expect(isBidRequestValid({ bidder, sizes: [[1, 1], [300, 250]], @@ -64,7 +65,7 @@ describe('AudienceNetwork adapter', () => { })).to.equal(true); }); - it('valid parameters', () => { + it('valid parameters', function () { expect(isBidRequestValid({ bidder, sizes: [[300, 250], [320, 50]], @@ -72,7 +73,7 @@ describe('AudienceNetwork adapter', () => { })).to.equal(true); }); - it('fullwidth', () => { + it('fullwidth', function () { expect(isBidRequestValid({ bidder, sizes: [[300, 250], [336, 280]], @@ -83,7 +84,7 @@ describe('AudienceNetwork adapter', () => { })).to.equal(true); }); - it('native', () => { + it('native', function () { expect(isBidRequestValid({ bidder, sizes: [[300, 250]], @@ -94,7 +95,7 @@ describe('AudienceNetwork adapter', () => { })).to.equal(true); }); - it('native with non-IAB size', () => { + it('native with non-IAB size', function () { expect(isBidRequestValid({ bidder, sizes: [[728, 90]], @@ -105,7 +106,7 @@ describe('AudienceNetwork adapter', () => { })).to.equal(true); }); - it('video', () => { + it('video', function () { expect(isBidRequestValid({ bidder, sizes: [[playerwidth, playerheight]], @@ -117,21 +118,22 @@ describe('AudienceNetwork adapter', () => { }); }); - describe('buildRequests', () => { - let isSafariBrowserStub; - before(() => { - isSafariBrowserStub = sinon.stub(utils, 'isSafariBrowser'); + describe('buildRequests', function () { + before(function () { + sinon + .stub(utils, 'generateUUID') + .returns('test-uuid'); }); - after(() => { - isSafariBrowserStub.restore(); + after(function () { + utils.generateUUID.restore(); }); - it('can build URL for IAB unit', () => { + it('can build URL for IAB unit', function () { expect(buildRequests([{ bidder, bidId: requestId, - sizes: [[300, 250], [320, 50]], + sizes: [[300, 50], [300, 250], [320, 50]], params: { placementId } }])).to.deep.equal([{ adformats: ['300x250'], @@ -139,11 +141,11 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['300x250'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=&sdk[]=5.5.web&pbv=${pbv}` + data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&${debug}` }]); }); - it('can build URL for video unit', () => { + it('can build URL for video unit', function () { expect(buildRequests([{ bidder, bidId: requestId, @@ -158,11 +160,11 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['640x480'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=video&testmode=false&pageurl=&sdk[]=&pbv=${pbv}&playerwidth=640&playerheight=480` + data: `placementids[]=test-placement-id&adformats[]=video&testmode=false&pageurl=${pageUrl}&sdk[]=&${debug}&playerwidth=640&playerheight=480` }]); }); - it('can build URL for native unit in non-IAB size', () => { + it('can build URL for native unit in non-IAB size', function () { expect(buildRequests([{ bidder, bidId: requestId, @@ -177,42 +179,36 @@ describe('AudienceNetwork adapter', () => { requestIds: [requestId], sizes: ['728x90'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=native&testmode=false&pageurl=&sdk[]=5.5.web&pbv=${pbv}` + data: `placementids[]=test-placement-id&adformats[]=native&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&${debug}` }]); }); - it('can build URL for fullwidth 300x250 unit', () => { + it('can build URL for deprecated fullwidth unit, overriding platform', function () { + const platform = 'test-platform'; + const debugPlatform = debug.replace('241394079772386', platform); + expect(buildRequests([{ bidder, bidId: requestId, sizes: [[300, 250]], params: { placementId, + platform, format: 'fullwidth' } }])).to.deep.equal([{ - adformats: ['fullwidth'], + adformats: ['300x250'], method: 'GET', requestIds: [requestId], sizes: ['300x250'], url: 'https://an.facebook.com/v2/placementbid.json', - data: `placementids[]=test-placement-id&adformats[]=fullwidth&testmode=false&pageurl=&sdk[]=5.5.web&pbv=${pbv}` + data: `placementids[]=test-placement-id&adformats[]=300x250&testmode=false&pageurl=${pageUrl}&sdk[]=5.5.web&${debugPlatform}` }]); }); - - it('can build URL on Safari that includes a cachebuster param', () => { - isSafariBrowserStub.returns(true); - expect(buildRequests([{ - bidder, - bidId: requestId, - sizes: [[300, 250]], - params: { placementId } - }])[0].data).to.contain('&cb='); - }); }); - describe('interpretResponse', () => { - it('error in response', () => { + describe('interpretResponse', function () { + it('error in response', function () { expect(interpretResponse({ body: { errors: ['test-error-message'] @@ -220,7 +216,7 @@ describe('AudienceNetwork adapter', () => { }, {})).to.deep.equal([]); }); - it('valid native bid in response', () => { + it('valid native bid in response', function () { const [bidResponse] = interpretResponse({ body: { errors: [], @@ -248,6 +244,7 @@ describe('AudienceNetwork adapter', () => { .to.contain(`placementid:'${placementId}',format:'native',bidid:'test-bid-id'`, 'ad missing parameters') .and.to.contain('getElementsByTagName("style")', 'ad missing native styles') .and.to.contain('
', 'ad missing native container'); + expect(bidResponse.ttl).to.equal(600); expect(bidResponse.creativeId).to.equal(placementId); expect(bidResponse.netRevenue).to.equal(true); expect(bidResponse.currency).to.equal('USD'); @@ -258,7 +255,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponse.fb_placementid).to.equal(placementId); }); - it('valid IAB bid in response', () => { + it('valid IAB bid in response', function () { const [bidResponse] = interpretResponse({ body: { errors: [], @@ -286,6 +283,7 @@ describe('AudienceNetwork adapter', () => { .to.contain(`placementid:'${placementId}',format:'300x250',bidid:'test-bid-id'`, 'ad missing parameters') .and.not.to.contain('getElementsByTagName("style")', 'ad should not contain native styles') .and.not.to.contain('
', 'ad should not contain native container'); + expect(bidResponse.ttl).to.equal(600); expect(bidResponse.creativeId).to.equal(placementId); expect(bidResponse.netRevenue).to.equal(true); expect(bidResponse.currency).to.equal('USD'); @@ -295,7 +293,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponse.fb_placementid).to.equal(placementId); }); - it('filters invalid slot sizes', () => { + it('filters invalid slot sizes', function () { const [bidResponse] = interpretResponse({ body: { errors: [], @@ -319,6 +317,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponse.requestId).to.equal(requestId); expect(bidResponse.width).to.equal(300); expect(bidResponse.height).to.equal(250); + expect(bidResponse.ttl).to.equal(600); expect(bidResponse.creativeId).to.equal(placementId); expect(bidResponse.netRevenue).to.equal(true); expect(bidResponse.currency).to.equal('USD'); @@ -328,7 +327,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponse.fb_placementid).to.equal(placementId); }); - it('valid multiple bids in response', () => { + it('valid multiple bids in response', function () { const placementIdNative = 'test-placement-id-native'; const placementIdIab = 'test-placement-id-iab'; @@ -363,6 +362,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponseNative.width).to.equal(300); expect(bidResponseNative.height).to.equal(250); expect(bidResponseNative.ad).to.contain(`placementid:'${placementIdNative}',format:'native',bidid:'test-bid-id-native'`, 'ad missing parameters'); + expect(bidResponseNative.ttl).to.equal(600); expect(bidResponseNative.creativeId).to.equal(placementIdNative); expect(bidResponseNative.netRevenue).to.equal(true); expect(bidResponseNative.currency).to.equal('USD'); @@ -376,6 +376,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponseIab.width).to.equal(300); expect(bidResponseIab.height).to.equal(250); expect(bidResponseIab.ad).to.contain(`placementid:'${placementIdIab}',format:'300x250',bidid:'test-bid-id-iab'`, 'ad missing parameters'); + expect(bidResponseIab.ttl).to.equal(600); expect(bidResponseIab.creativeId).to.equal(placementIdIab); expect(bidResponseIab.netRevenue).to.equal(true); expect(bidResponseIab.currency).to.equal('USD'); @@ -385,7 +386,7 @@ describe('AudienceNetwork adapter', () => { expect(bidResponseIab.fb_placementid).to.equal(placementIdIab); }); - it('valid video bid in response', () => { + it('valid video bid in response', function () { const bidId = 'test-bid-id-video'; const [bidResponse] = interpretResponse({ @@ -409,13 +410,14 @@ describe('AudienceNetwork adapter', () => { expect(bidResponse.cpm).to.equal(1.23); expect(bidResponse.requestId).to.equal(requestId); + expect(bidResponse.ttl).to.equal(3600); expect(bidResponse.mediaType).to.equal('video'); - expect(bidResponse.vastUrl).to.equal(`https://an.facebook.com/v1/instream/vast.xml?placementid=${placementId}&pageurl=&playerwidth=${playerwidth}&playerheight=${playerheight}&bidid=${bidId}`); + expect(bidResponse.vastUrl).to.equal(`https://an.facebook.com/v1/instream/vast.xml?placementid=${placementId}&pageurl=${pageUrl}&playerwidth=${playerwidth}&playerheight=${playerheight}&bidid=${bidId}`); expect(bidResponse.width).to.equal(playerwidth); expect(bidResponse.height).to.equal(playerheight); }); - it('mixed video and native bids', () => { + it('mixed video and native bids', function () { const videoPlacementId = 'test-video-placement-id'; const videoBidId = 'test-video-bid-id'; const nativePlacementId = 'test-native-placement-id'; @@ -449,19 +451,21 @@ describe('AudienceNetwork adapter', () => { expect(bidResponseVideo.cpm).to.equal(1.23); expect(bidResponseVideo.requestId).to.equal(requestId); + expect(bidResponseVideo.ttl).to.equal(3600); expect(bidResponseVideo.mediaType).to.equal('video'); - expect(bidResponseVideo.vastUrl).to.equal(`https://an.facebook.com/v1/instream/vast.xml?placementid=${videoPlacementId}&pageurl=&playerwidth=${playerwidth}&playerheight=${playerheight}&bidid=${videoBidId}`); + expect(bidResponseVideo.vastUrl).to.equal(`https://an.facebook.com/v1/instream/vast.xml?placementid=${videoPlacementId}&pageurl=${pageUrl}&playerwidth=${playerwidth}&playerheight=${playerheight}&bidid=${videoBidId}`); expect(bidResponseVideo.width).to.equal(playerwidth); expect(bidResponseVideo.height).to.equal(playerheight); expect(bidResponseNative.cpm).to.equal(4.56); expect(bidResponseNative.requestId).to.equal(requestId); + expect(bidResponseNative.ttl).to.equal(600); expect(bidResponseNative.width).to.equal(300); expect(bidResponseNative.height).to.equal(250); expect(bidResponseNative.ad).to.contain(`placementid:'${nativePlacementId}',format:'native',bidid:'${nativeBidId}'`); }); - it('mixture of valid native bid and error in response', () => { + it('mixture of valid native bid and error in response', function () { const [bidResponse] = interpretResponse({ body: { errors: ['test-error-message'], @@ -489,6 +493,7 @@ describe('AudienceNetwork adapter', () => { .to.contain(`placementid:'${placementId}',format:'native',bidid:'test-bid-id'`, 'ad missing parameters') .and.to.contain('getElementsByTagName("style")', 'ad missing native styles') .and.to.contain('
', 'ad missing native container'); + expect(bidResponse.ttl).to.equal(600); expect(bidResponse.creativeId).to.equal(placementId); expect(bidResponse.netRevenue).to.equal(true); expect(bidResponse.currency).to.equal('USD'); diff --git a/test/spec/modules/beachfrontBidAdapter_spec.js b/test/spec/modules/beachfrontBidAdapter_spec.js index a3ecccba6cb..21e175a5b82 100644 --- a/test/spec/modules/beachfrontBidAdapter_spec.js +++ b/test/spec/modules/beachfrontBidAdapter_spec.js @@ -2,10 +2,10 @@ import { expect } from 'chai'; import { spec, VIDEO_ENDPOINT, BANNER_ENDPOINT, OUTSTREAM_SRC, DEFAULT_MIMES } from 'modules/beachfrontBidAdapter'; import * as utils from 'src/utils'; -describe('BeachfrontAdapter', () => { +describe('BeachfrontAdapter', function () { let bidRequests; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { bidder: 'beachfront', @@ -31,13 +31,13 @@ describe('BeachfrontAdapter', () => { ]; }); - describe('spec.isBidRequestValid', () => { - it('should return true when the required params are passed', () => { + describe('spec.isBidRequestValid', function () { + it('should return true when the required params are passed', function () { const bidRequest = bidRequests[0]; expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return false when the "bidfloor" param is missing', () => { + it('should return false when the "bidfloor" param is missing', function () { const bidRequest = bidRequests[0]; bidRequest.params = { appId: '11bc5dd5-7421-4dd8-c926-40fa653bec76' @@ -45,7 +45,7 @@ describe('BeachfrontAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when the "appId" param is missing', () => { + it('should return false when the "appId" param is missing', function () { const bidRequest = bidRequests[0]; bidRequest.params = { bidfloor: 5.00 @@ -53,19 +53,19 @@ describe('BeachfrontAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when no bid params are passed', () => { + it('should return false when no bid params are passed', function () { const bidRequest = bidRequests[0]; bidRequest.params = {}; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when a bid request is not passed', () => { + it('should return false when a bid request is not passed', function () { expect(spec.isBidRequestValid()).to.equal(false); expect(spec.isBidRequestValid({})).to.equal(false); }); - describe('for multi-format bids', () => { - it('should return true when the required params are passed for video', () => { + describe('for multi-format bids', function () { + it('should return true when the required params are passed for video', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} @@ -79,7 +79,7 @@ describe('BeachfrontAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return false when the required params are missing for video', () => { + it('should return false when the required params are missing for video', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} @@ -93,7 +93,7 @@ describe('BeachfrontAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return true when the required params are passed for banner', () => { + it('should return true when the required params are passed for banner', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: {} @@ -107,7 +107,7 @@ describe('BeachfrontAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return false when the required params are missing for banner', () => { + it('should return false when the required params are missing for banner', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: {} @@ -123,9 +123,9 @@ describe('BeachfrontAdapter', () => { }); }); - describe('spec.buildRequests', () => { - describe('for video bids', () => { - it('should attach the bid request object', () => { + describe('spec.buildRequests', function () { + describe('for video bids', function () { + it('should attach the bid request object', function () { bidRequests[0].mediaTypes = { video: {} }; bidRequests[1].mediaTypes = { video: {} }; const requests = spec.buildRequests(bidRequests); @@ -133,7 +133,7 @@ describe('BeachfrontAdapter', () => { expect(requests[1].bidRequest).to.equal(bidRequests[1]); }); - it('should create a POST request for each bid', () => { + it('should create a POST request for each bid', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} }; const requests = spec.buildRequests([ bidRequest ]); @@ -141,7 +141,7 @@ describe('BeachfrontAdapter', () => { expect(requests[0].url).to.equal(VIDEO_ENDPOINT + bidRequest.params.appId); }); - it('should attach request data', () => { + it('should attach request data', function () { const width = 640; const height = 480; const bidRequest = bidRequests[0]; @@ -164,7 +164,7 @@ describe('BeachfrontAdapter', () => { expect(data.cur).to.deep.equal(['USD']); }); - it('must parse bid size from a nested array', () => { + it('must parse bid size from a nested array', function () { const width = 640; const height = 480; const bidRequest = bidRequests[0]; @@ -178,7 +178,7 @@ describe('BeachfrontAdapter', () => { expect(data.imp[0].video).to.deep.contain({ w: width, h: height }); }); - it('must parse bid size from a string', () => { + it('must parse bid size from a string', function () { const width = 640; const height = 480; const bidRequest = bidRequests[0]; @@ -192,7 +192,7 @@ describe('BeachfrontAdapter', () => { expect(data.imp[0].video).to.deep.contain({ w: width, h: height }); }); - it('must handle an empty bid size', () => { + it('must handle an empty bid size', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: { @@ -204,7 +204,7 @@ describe('BeachfrontAdapter', () => { expect(data.imp[0].video).to.deep.contain({ w: undefined, h: undefined }); }); - it('must fall back to the size on the bid object', () => { + it('must fall back to the size on the bid object', function () { const width = 640; const height = 480; const bidRequest = bidRequests[0]; @@ -215,23 +215,25 @@ describe('BeachfrontAdapter', () => { expect(data.imp[0].video).to.deep.contain({ w: width, h: height }); }); - it('must override video targeting params', () => { + it('must override video targeting params', function () { const bidRequest = bidRequests[0]; const mimes = ['video/webm']; + const playbackmethod = 2; + const maxduration = 30; bidRequest.mediaTypes = { video: {} }; - bidRequest.params.video = { mimes }; + bidRequest.params.video = { mimes, playbackmethod, maxduration }; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; - expect(data.imp[0].video).to.deep.contain({ mimes }); + expect(data.imp[0].video).to.deep.contain({ mimes, playbackmethod, maxduration }); }); - it('must add GDPR consent data to the request', () => { + it('must add GDPR consent data to the request', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} }; const consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; const bidderRequest = { gdprConsent: { - consentRequired: true, + gdprApplies: true, consentString } }; @@ -242,15 +244,15 @@ describe('BeachfrontAdapter', () => { }); }); - describe('for banner bids', () => { - it('should attach the bid requests array', () => { + describe('for banner bids', function () { + it('should attach the bid requests array', function () { bidRequests[0].mediaTypes = { banner: {} }; bidRequests[1].mediaTypes = { banner: {} }; const requests = spec.buildRequests(bidRequests); expect(requests[0].bidRequest).to.deep.equal(bidRequests); }); - it('should create a single POST request for all bids', () => { + it('should create a single POST request for all bids', function () { bidRequests[0].mediaTypes = { banner: {} }; bidRequests[1].mediaTypes = { banner: {} }; const requests = spec.buildRequests(bidRequests); @@ -259,7 +261,7 @@ describe('BeachfrontAdapter', () => { expect(requests[0].url).to.equal(BANNER_ENDPOINT); }); - it('should attach request data', () => { + it('should attach request data', function () { const width = 300; const height = 250; const bidRequest = bidRequests[0]; @@ -285,7 +287,7 @@ describe('BeachfrontAdapter', () => { expect(data.ua).to.equal(navigator.userAgent); }); - it('must parse bid size from a nested array', () => { + it('must parse bid size from a nested array', function () { const width = 300; const height = 250; const bidRequest = bidRequests[0]; @@ -301,7 +303,7 @@ describe('BeachfrontAdapter', () => { ]); }); - it('must parse bid size from a string', () => { + it('must parse bid size from a string', function () { const width = 300; const height = 250; const bidRequest = bidRequests[0]; @@ -317,7 +319,7 @@ describe('BeachfrontAdapter', () => { ]); }); - it('must handle an empty bid size', () => { + it('must handle an empty bid size', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: { @@ -329,7 +331,7 @@ describe('BeachfrontAdapter', () => { expect(data.slots[0].sizes).to.deep.equal([]); }); - it('must fall back to the size on the bid object', () => { + it('must fall back to the size on the bid object', function () { const width = 300; const height = 250; const bidRequest = bidRequests[0]; @@ -340,13 +342,13 @@ describe('BeachfrontAdapter', () => { expect(data.slots[0].sizes).to.deep.contain({ w: width, h: height }); }); - it('must add GDPR consent data to the request', () => { + it('must add GDPR consent data to the request', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: {} }; const consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; const bidderRequest = { gdprConsent: { - consentRequired: true, + gdprApplies: true, consentString } }; @@ -357,8 +359,8 @@ describe('BeachfrontAdapter', () => { }); }); - describe('for multi-format bids', () => { - it('should create a POST request for each bid format', () => { + describe('for multi-format bids', function () { + it('should create a POST request for each bid format', function () { const width = 300; const height = 250; const bidRequest = bidRequests[0]; @@ -386,7 +388,7 @@ describe('BeachfrontAdapter', () => { expect(requests[1].url).to.contain(BANNER_ENDPOINT); }); - it('must parse bid sizes for each bid format', () => { + it('must parse bid sizes for each bid format', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: { @@ -413,16 +415,16 @@ describe('BeachfrontAdapter', () => { }); }); - describe('spec.interpretResponse', () => { - describe('for video bids', () => { - it('should return no bids if the response is not valid', () => { + describe('spec.interpretResponse', function () { + describe('for video bids', function () { + it('should return no bids if the response is not valid', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} }; const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response "url" is missing', () => { + it('should return no bids if the response "url" is missing', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} }; const serverResponse = { @@ -432,7 +434,7 @@ describe('BeachfrontAdapter', () => { expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response "bidPrice" is missing', () => { + it('should return no bids if the response "bidPrice" is missing', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} }; const serverResponse = { @@ -442,7 +444,7 @@ describe('BeachfrontAdapter', () => { expect(bidResponse.length).to.equal(0); }); - it('should return a valid video bid response', () => { + it('should return a valid video bid response', function () { const width = 640; const height = 480; const bidRequest = bidRequests[0]; @@ -473,7 +475,7 @@ describe('BeachfrontAdapter', () => { }); }); - it('should return a renderer for outstream video bids', () => { + it('should return a renderer for outstream video bids', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: { @@ -493,22 +495,22 @@ describe('BeachfrontAdapter', () => { }); }); - describe('for banner bids', () => { - it('should return no bids if the response is not valid', () => { + describe('for banner bids', function () { + it('should return no bids if the response is not valid', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: {} }; const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response is empty', () => { + it('should return no bids if the response is empty', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: {} }; const bidResponse = spec.interpretResponse({ body: [] }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return valid banner bid responses', () => { + it('should return valid banner bid responses', function () { bidRequests[0].mediaTypes = { banner: { sizes: [[ 300, 250 ], [ 728, 90 ]] @@ -554,4 +556,119 @@ describe('BeachfrontAdapter', () => { }); }); }); + + describe('spec.getUserSyncs', function () { + describe('for video bids', function () { + let bidResponse; + + beforeEach(function () { + bidResponse = { + bidPrice: 5.00, + url: 'http://reachms.bfmio.com/getmu?aid=bid:19c4a196-fb21-4c81-9a1a-ecc5437a39da', + cmpId: '123abc' + }; + }); + + it('should return an iframe user sync if iframes are enabled', function () { + const syncOptions = { + iframeEnabled: true, + pixelEnabled: true + }; + const serverResponses = [{ + body: bidResponse + }]; + const userSyncs = spec.getUserSyncs(syncOptions, serverResponses); + expect(userSyncs.length).to.equal(1); + expect(userSyncs[0].type).to.equal('iframe'); + }); + + it('should return an image user sync if iframes are disabled', function () { + const syncOptions = { + iframeEnabled: false, + pixelEnabled: true + }; + const serverResponses = [{ + body: bidResponse + }]; + const userSyncs = spec.getUserSyncs(syncOptions, serverResponses); + expect(userSyncs.length).to.equal(1); + expect(userSyncs[0].type).to.equal('image'); + }); + + it('should not return user syncs if none are enabled', function () { + const syncOptions = { + iframeEnabled: false, + pixelEnabled: false + }; + const serverResponses = [{ + body: bidResponse + }]; + const userSyncs = spec.getUserSyncs(syncOptions, serverResponses); + expect(userSyncs).to.deep.equal([]); + }); + }); + + describe('for banner bids', function () { + let bidResponse; + + beforeEach(function () { + bidResponse = { + slot: bidRequests[0].adUnitCode, + adm: '
', + crid: 'crid_1', + price: 3.02, + w: 728, + h: 90 + }; + }); + + it('should return user syncs defined the bid response', function () { + const syncUrl = 'http://sync.bfmio.com/sync_iframe?ifpl=5&ifg=1&id=test&gdpr=0&gc=&gce=0'; + const syncOptions = { + iframeEnabled: true, + pixelEnabled: true + }; + const serverResponses = [{ + body: [ + { sync: syncUrl }, + bidResponse + ] + }]; + const userSyncs = spec.getUserSyncs(syncOptions, serverResponses); + expect(userSyncs).to.deep.equal([ + { type: 'iframe', url: syncUrl } + ]); + }); + + it('should not return user syncs if iframes are disabled', function () { + const syncUrl = 'http://sync.bfmio.com/sync_iframe?ifpl=5&ifg=1&id=test&gdpr=0&gc=&gce=0'; + const syncOptions = { + iframeEnabled: false, + pixelEnabled: true + }; + const serverResponses = [{ + body: [ + { sync: syncUrl }, + bidResponse + ] + }]; + const userSyncs = spec.getUserSyncs(syncOptions, serverResponses); + expect(userSyncs).to.deep.equal([]); + }); + + it('should not return user syncs if there are none in the bid response', function () { + const syncOptions = { + iframeEnabled: true, + pixelEnabled: true + }; + const serverResponses = [{ + body: [ + bidResponse + ] + }]; + const userSyncs = spec.getUserSyncs(syncOptions, serverResponses); + expect(userSyncs).to.deep.equal([]); + }); + }); + }); }); diff --git a/test/spec/modules/betweenBidAdapter_spec.js b/test/spec/modules/betweenBidAdapter_spec.js new file mode 100644 index 00000000000..f2d770805c5 --- /dev/null +++ b/test/spec/modules/betweenBidAdapter_spec.js @@ -0,0 +1,69 @@ +import { expect } from 'chai'; +import { spec } from 'modules/betweenBidAdapter'; + +describe('betweenBidAdapterTests', function () { + it('validate_pub_params', function () { + expect(spec.isBidRequestValid({ + bidder: 'between', + params: { + w: 240, + h: 400, + s: 1112 + } + })).to.equal(true); + }); + it('validate_generated_params', function () { + let bidRequestData = [{ + bidId: 'bid1234', + bidder: 'between', + params: {w: 240, h: 400, s: 1112}, + sizes: [[240, 400]] + }] + let request = spec.buildRequests(bidRequestData); + let req_data = request[0].data; + expect(req_data.bidid).to.equal('bid1234'); + }); + it('validate_response_params', function () { + let serverResponse = { + body: [{ + bidid: 'bid1234', + cpm: 1.12, + w: 240, + h: 400, + currency: 'USD', + ad: 'Ad html' + }] + }; + let bids = spec.interpretResponse(serverResponse); + expect(bids).to.have.lengthOf(1); + let bid = bids[0]; + expect(bid.cpm).to.equal(1.12); + expect(bid.currency).to.equal('USD'); + expect(bid.width).to.equal(240); + expect(bid.height).to.equal(400); + expect(bid.netRevenue).to.equal(true); + expect(bid.requestId).to.equal('bid1234'); + expect(bid.ad).to.equal('Ad html'); + }); + it('validate_response_params', function () { + let serverResponse = { + body: [{ + bidid: 'bid1234', + w: 240, + h: 400, + currency: 'USD', + ad: 'Ad html' + }] + }; + let bids = spec.interpretResponse(serverResponse); + expect(bids).to.have.lengthOf(1); + let bid = bids[0]; + expect(bid.cpm).to.equal(0); + expect(bid.currency).to.equal('USD'); + expect(bid.width).to.equal(240); + expect(bid.height).to.equal(400); + expect(bid.netRevenue).to.equal(true); + expect(bid.requestId).to.equal('bid1234'); + expect(bid.ad).to.equal('Ad html'); + }); +}); diff --git a/test/spec/modules/bizzclickBidAdapter_spec.js b/test/spec/modules/bizzclickBidAdapter_spec.js new file mode 100644 index 00000000000..6f518f32ccf --- /dev/null +++ b/test/spec/modules/bizzclickBidAdapter_spec.js @@ -0,0 +1,117 @@ +import {expect} from 'chai'; +import {spec} from '../../../modules/bizzclickBidAdapter'; + +describe('BizzclickBidAdapter', function () { + let bid = { + bidId: '67d581a232281d', + bidder: 'bizzclickBidAdapter', + bidderRequestId: 'a7837c9145e136', + params: { + placementId: 0, + type: 'banner' + }, + placementCode: 'placementId', + auctionId: 'bfe951372e62-a92d-4cf1-869f-d24029', + sizes: [[300, 250]], + transactionId: '3bb2f6da-87a6-4029-aeb0-1b244bbfb5' + }; + + describe('isBidRequestValid', function () { + it('Should return true when placement_id can be cast to a number', function () { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + it('Should return false when placement_id is not a number', function () { + bid.params.placementId = 'aaa'; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + + describe('buildRequests', function () { + let serverRequest = spec.buildRequests([bid]); + it('Creates a ServerRequest object with method, URL and data', function () { + expect(serverRequest).to.exist; + expect(serverRequest.method).to.exist; + expect(serverRequest.url).to.exist; + expect(serverRequest.data).to.exist; + }); + it('Returns POST method', function () { + expect(serverRequest.method).to.equal('POST'); + }); + it('Returns valid URL', function () { + expect(serverRequest.url).to.equal('//supply.bizzclick.com/?c=o&m=multi'); + }); + it('Returns valid data if array of bids is valid', function () { + let data = serverRequest.data; + expect(data).to.be.an('object'); + expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'secure', 'host', 'page', 'placements'); + expect(data.deviceWidth).to.be.a('number'); + expect(data.deviceHeight).to.be.a('number'); + expect(data.secure).to.be.within(0, 1); + expect(data.host).to.be.a('string'); + expect(data.page).to.be.a('string'); + let placements = data['placements']; + for (let i = 0; i < placements.length; i++) { + let placement = placements[i]; + expect(placement).to.have.all.keys('placementId', 'bidId', 'type', 'sizes'); + expect(placement.placementId).to.be.a('number'); + expect(placement.bidId).to.be.a('string'); + expect(placement.type).to.be.a('string'); + expect(placement.sizes).to.be.an('array'); + } + }); + it('Returns empty data if no valid requests are passed', function () { + serverRequest = spec.buildRequests([]); + let data = serverRequest.data; + expect(data.placements).to.be.an('array').that.is.empty; + }); + }); + describe('interpretResponse', function () { + let resObject = { + body: [ { + requestId: '123', + mediaType: 'banner', + cpm: 0.3, + width: 320, + height: 50, + ad: '

Hello ad

', + ttl: 1000, + creativeId: '123asd', + netRevenue: true, + currency: 'USD' + }] + }; + let serverResponses = spec.interpretResponse(resObject); + it('Returns an array of valid server responses if response object is valid', function () { + expect(serverResponses).to.be.an('array').that.is.not.empty; + for (let i = 0; i < serverResponses.length; i++) { + let dataItem = serverResponses[i]; + expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'ad', 'ttl', 'creativeId', 'netRevenue', 'currency', 'mediaType'); + expect(dataItem.requestId).to.be.a('string'); + expect(dataItem.cpm).to.be.a('number'); + expect(dataItem.width).to.be.a('number'); + expect(dataItem.height).to.be.a('number'); + expect(dataItem.ad).to.be.a('string'); + expect(dataItem.ttl).to.be.a('number'); + expect(dataItem.creativeId).to.be.a('string'); + expect(dataItem.netRevenue).to.be.a('boolean'); + expect(dataItem.currency).to.be.a('string'); + expect(dataItem.mediaType).to.be.a('string'); + } + it('Returns an empty array if invalid response is passed', function () { + serverResponses = spec.interpretResponse('invalid_response'); + expect(serverResponses).to.be.an('array').that.is.empty; + }); + }); + }); + + describe('getUserSyncs', function () { + let userSync = spec.getUserSyncs(); + it('Returns valid URL and type', function () { + expect(userSync).to.be.an('array').with.lengthOf(1); + expect(userSync[0].type).to.exist; + expect(userSync[0].url).to.exist; + expect(userSync[0].type).to.be.equal('image'); + expect(userSync[0].url).to.be.equal('//supply.bizzclick.com/?c=o&m=cookie'); + }); + }); +}); diff --git a/test/spec/modules/brainyBidAdapter_spec.js b/test/spec/modules/brainyBidAdapter_spec.js index 8dc74435263..a3ce90d927a 100644 --- a/test/spec/modules/brainyBidAdapter_spec.js +++ b/test/spec/modules/brainyBidAdapter_spec.js @@ -31,27 +31,50 @@ const bidReq = [{ const correctReq = { accountID: '12345', slotID: '12345' -} +}; const bidResponse = { ad_id: '1036e9746c-d186-49ae-90cb-2796d0f9b223', adm: '', + syncUrl: '//testparm.com/ssp-sync/p/sync?uid=2110180601155125000059&buyer=2&slot=34', cpm: 100, height: 250, width: 300 }; -describe('brainy Adapter', () => { - describe('request', () => { - it('should validate bid request', () => { +const bidSyncResponse = [{ + body: { + ad_id: '1036e9746c-d186-49ae-90cb-2796d0f9b223', + adm: '', + syncUrl: '//testparm.com/ssp-sync/p/sync?uid=2110180601155125000059&buyer=2&slot=34', + cpm: 100, + height: 250, + width: 300 + } +}]; + +const invalidSyncBidResponse = [{ + body: { + ad_id: '1036e9746c-d186-49ae-90cb-2796d0f9b223', + adm: '', + syncUrl: 'null', + cpm: 100, + height: 250, + width: 300 + } +}]; + +describe('brainy Adapter', function () { + describe('request', function () { + it('should validate bid request', function () { expect(spec.isBidRequestValid(validBidReq)).to.equal(true); }); - it('should not validate incorrect bid request', () => { + it('should not validate incorrect bid request', function () { expect(spec.isBidRequestValid(invalidBidReq)).to.equal(false); }); }); - describe('build request', () => { - it('Verify bid request', () => { + describe('build request', function () { + it('Verify bid request', function () { const request = spec.buildRequests(bidReq); expect(request[0].method).to.equal('GET'); expect(request[0].url).to.equal(URL); @@ -60,14 +83,14 @@ describe('brainy Adapter', () => { }); }); - describe('interpretResponse', () => { - it('should build bid array', () => { + describe('interpretResponse', function () { + it('should build bid array', function () { const request = spec.buildRequests(bidReq); const result = spec.interpretResponse({body: bidResponse}, request[0]); expect(result.length).to.equal(1); }); - it('should have all relevant fields', () => { + it('should have all relevant fields', function () { const request = spec.buildRequests(bidReq); const result = spec.interpretResponse({body: bidResponse}, request[0]); const bid = result[0]; @@ -77,4 +100,29 @@ describe('brainy Adapter', () => { expect(bid.height).to.equal(bidResponse.height); }); }); + + describe('spec.getUserSyncs', function () { + let syncOptions + beforeEach(function () { + syncOptions = { + enabledBidders: ['brainy'], + pixelEnabled: true + } + }); + it('sucess with usersync url', function () { + const result = []; + result.push({type: 'image', url: '//testparm.com/ssp-sync/p/sync?uid=2110180601155125000059&buyer=2&slot=34'}); + expect(spec.getUserSyncs(syncOptions, bidSyncResponse)).to.deep.equal(result); + }); + + it('sucess without usersync url', function () { + const result = []; + expect(spec.getUserSyncs(syncOptions, invalidSyncBidResponse)).to.deep.equal(result); + }); + it('empty response', function () { + const serverResponse = [{body: {}}]; + const result = []; + expect(spec.getUserSyncs(syncOptions, serverResponse)).to.deep.equal(result); + }); + }); }); diff --git a/test/spec/modules/bridgewellBidAdapter_spec.js b/test/spec/modules/bridgewellBidAdapter_spec.js index 5dae3c474ac..6ca9675a1bb 100644 --- a/test/spec/modules/bridgewellBidAdapter_spec.js +++ b/test/spec/modules/bridgewellBidAdapter_spec.js @@ -169,13 +169,13 @@ describe('bridgewellBidAdapter', function () { ]; const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bidWithoutCpmWeight = { 'bidder': 'bridgewell', 'params': { @@ -227,18 +227,18 @@ describe('bridgewellBidAdapter', function () { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bidWithoutCpmWeight)).to.equal(true); expect(spec.isBidRequestValid(bidWithCorrectCpmWeight)).to.equal(true); expect(spec.isBidRequestValid(bidWithUncorrectCpmWeight)).to.equal(false); expect(spec.isBidRequestValid(bidWithZeroCpmWeight)).to.equal(false); }); - it('should return false when required params not found', () => { + it('should return false when required params not found', function () { expect(spec.isBidRequestValid({})).to.equal(false); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bidWithoutCpmWeight = Object.assign({}, bidWithoutCpmWeight); let bidWithCorrectCpmWeight = Object.assign({}, bidWithCorrectCpmWeight); let bidWithUncorrectCpmWeight = Object.assign({}, bidWithUncorrectCpmWeight); @@ -272,8 +272,8 @@ describe('bridgewellBidAdapter', function () { }); }); - describe('buildRequests', () => { - it('should attach valid params to the tag', () => { + describe('buildRequests', function () { + it('should attach valid params to the tag', function () { const request = spec.buildRequests(bidRequests); const payload = request.data; const adUnits = payload.adUnits; @@ -286,14 +286,14 @@ describe('bridgewellBidAdapter', function () { } }); - it('should attach validBidRequests to the tag', () => { + it('should attach validBidRequests to the tag', function () { const request = spec.buildRequests(bidRequests); const validBidRequests = request.validBidRequests; expect(validBidRequests).to.deep.equal(bidRequests); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const request = spec.buildRequests(bidRequests); const serverResponses = [ { @@ -440,7 +440,7 @@ describe('bridgewellBidAdapter', function () { } ]; - it('should return all required parameters', () => { + it('should return all required parameters', function () { const result = spec.interpretResponse({'body': serverResponses}, request); result.every(res => expect(res.cpm).to.be.a('number')); result.every(res => expect(res.width).to.be.a('number')); @@ -457,12 +457,12 @@ describe('bridgewellBidAdapter', function () { }); }); - it('should give up bid if server response is undefiend', () => { + it('should give up bid if server response is undefiend', function () { const result = spec.interpretResponse({'body': undefined}, request); expect(result).to.deep.equal([]); }); - it('should give up bid if request sizes is missing', () => { + it('should give up bid if request sizes is missing', function () { let target = Object.assign({}, serverResponses[0]); target.consumed = false; const result = spec.interpretResponse({'body': [target]}, spec.buildRequests([{ @@ -478,7 +478,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if response sizes is invalid', () => { + it('should give up bid if response sizes is invalid', function () { let target = { 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', 'bidder_code': 'bridgewell', @@ -495,7 +495,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if cpm is missing', () => { + it('should give up bid if cpm is missing', function () { let target = { 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', 'bidder_code': 'bridgewell', @@ -511,7 +511,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if width or height is missing', () => { + it('should give up bid if width or height is missing', function () { let target = { 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', 'bidder_code': 'bridgewell', @@ -526,7 +526,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if ad is missing', () => { + it('should give up bid if ad is missing', function () { let target = { 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', 'bidder_code': 'bridgewell', @@ -543,7 +543,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if revenue mode is missing', () => { + it('should give up bid if revenue mode is missing', function () { let target = { 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', 'bidder_code': 'bridgewell', @@ -559,7 +559,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if currency is missing', () => { + it('should give up bid if currency is missing', function () { let target = { 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', 'bidder_code': 'bridgewell', @@ -575,7 +575,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if mediaType is missing', () => { + it('should give up bid if mediaType is missing', function () { let target = { 'id': 'e5b10774-32bf-4931-85ee-05095e8cff21', 'bidder_code': 'bridgewell', @@ -592,7 +592,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if property native of mediaType native is missing', () => { + it('should give up bid if property native of mediaType native is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -609,7 +609,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native title is missing', () => { + it('should give up bid if native title is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -643,7 +643,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native title is too long', () => { + it('should give up bid if native title is too long', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -678,7 +678,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native body is missing', () => { + it('should give up bid if native body is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -711,7 +711,7 @@ describe('bridgewellBidAdapter', function () { const result = spec.interpretResponse({'body': [target]}, request); expect(result).to.deep.equal([]); - it('should give up bid if native image url is missing', () => { + it('should give up bid if native image url is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -746,7 +746,7 @@ describe('bridgewellBidAdapter', function () { }); }); - it('should give up bid if native image is missing', () => { + it('should give up bid if native image is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -776,7 +776,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native image url is missing', () => { + it('should give up bid if native image url is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -808,7 +808,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native image sizes is unmatch', () => { + it('should give up bid if native image sizes is unmatch', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -841,7 +841,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native sponsoredBy is missing', () => { + it('should give up bid if native sponsoredBy is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -875,7 +875,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native icon is missing', () => { + it('should give up bid if native icon is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -905,7 +905,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native icon url is missing', () => { + it('should give up bid if native icon url is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -939,7 +939,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native icon sizes is unmatch', () => { + it('should give up bid if native icon sizes is unmatch', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -972,7 +972,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native clickUrl is missing', () => { + it('should give up bid if native clickUrl is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -1006,7 +1006,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native clickTrackers is missing', () => { + it('should give up bid if native clickTrackers is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -1040,7 +1040,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native clickTrackers is empty', () => { + it('should give up bid if native clickTrackers is empty', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -1075,7 +1075,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native impressionTrackers is missing', () => { + it('should give up bid if native impressionTrackers is missing', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -1109,7 +1109,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if native impressionTrackers is empty', () => { + it('should give up bid if native impressionTrackers is empty', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', @@ -1144,7 +1144,7 @@ describe('bridgewellBidAdapter', function () { expect(result).to.deep.equal([]); }); - it('should give up bid if mediaType is not support', () => { + it('should give up bid if mediaType is not support', function () { let target = { 'id': '0e4048d3-5c74-4380-a21a-00ba35629f7d', 'bidder_code': 'bridgewell', diff --git a/test/spec/modules/c1xBidAdapter_spec.js b/test/spec/modules/c1xBidAdapter_spec.js index 0517668ea0d..268ad46d0ce 100644 --- a/test/spec/modules/c1xBidAdapter_spec.js +++ b/test/spec/modules/c1xBidAdapter_spec.js @@ -5,16 +5,16 @@ import { newBidder } from 'src/adapters/bidderFactory'; const ENDPOINT = 'https://ht.c1exchange.com/ht'; const BIDDER_CODE = 'c1x'; -describe('C1XAdapter', () => { +describe('C1XAdapter', function () { const adapter = newBidder(c1xAdapter); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': BIDDER_CODE, 'adUnitCode': 'adunit-code', @@ -24,11 +24,11 @@ describe('C1XAdapter', () => { } }; - it('should return true when required params are passed', () => { + it('should return true when required params are passed', function () { expect(c1xAdapter.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not found', () => { + it('should return false when required params are not found', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -38,7 +38,7 @@ describe('C1XAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': BIDDER_CODE, @@ -61,19 +61,19 @@ describe('C1XAdapter', () => { return parsedData; }; - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { const request = c1xAdapter.buildRequests(bidRequests); expect(request.url).to.equal(ENDPOINT); expect(request.method).to.equal('GET'); }); - it('should generate correct bid Id tag', () => { + it('should generate correct bid Id tag', function () { const request = c1xAdapter.buildRequests(bidRequests); expect(request.bids[0].adUnitCode).to.equal('adunit-code'); expect(request.bids[0].bidId).to.equal('30b31c1838de1e'); }); - it('should convert params to proper form and attach to request', () => { + it('should convert params to proper form and attach to request', function () { const request = c1xAdapter.buildRequests(bidRequests); const originalPayload = parseRequest(request.data); const payloadObj = JSON.parse(originalPayload); @@ -83,7 +83,7 @@ describe('C1XAdapter', () => { expect(payloadObj.site).to.equal('9999'); }); - it('should convert floor price to proper form and attach to request', () => { + it('should convert floor price to proper form and attach to request', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -100,7 +100,7 @@ describe('C1XAdapter', () => { expect(payloadObj.a1p).to.equal('4.35'); }); - it('should convert pageurl to proper form and attach to request', () => { + it('should convert pageurl to proper form and attach to request', function () { let bidRequest = Object.assign({}, bidRequests[0], { @@ -114,9 +114,27 @@ describe('C1XAdapter', () => { const payloadObj = JSON.parse(originalPayload); expect(payloadObj.pageurl).to.equal('http://c1exchange.com/'); }); + + it('should convert GDPR Consent to proper form and attach to request', function () { + let consentString = 'BOP2gFWOQIFovABABAENBGAAAAAAMw'; + let bidderRequest = { + 'bidderCode': 'c1x', + 'gdprConsent': { + 'consentString': consentString, + 'gdprApplies': true + } + } + bidderRequest.bids = bidRequests; + + const request = c1xAdapter.buildRequests(bidRequests, bidderRequest); + const originalPayload = parseRequest(request.data); + const payloadObj = JSON.parse(originalPayload); + expect(payloadObj['consent_string']).to.equal('BOP2gFWOQIFovABABAENBGAAAAAAMw'); + expect(payloadObj['consent_required']).to.equal('true'); + }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { 'bid': true, 'cpm': 1.5, @@ -128,7 +146,7 @@ describe('C1XAdapter', () => { 'bidType': 'GROSS_BID' }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { width: 300, @@ -151,7 +169,7 @@ describe('C1XAdapter', () => { expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = { bid: false, adId: 'c1x-test' diff --git a/test/spec/modules/ccxBidAdapter_spec.js b/test/spec/modules/ccxBidAdapter_spec.js index 535b3906a27..292503c9e04 100644 --- a/test/spec/modules/ccxBidAdapter_spec.js +++ b/test/spec/modules/ccxBidAdapter_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import { spec } from 'modules/ccxBidAdapter'; import * as utils from 'src/utils'; -describe('ccxAdapter', () => { +describe('ccxAdapter', function () { let bids = [ { adUnitCode: 'banner', @@ -39,17 +39,17 @@ describe('ccxAdapter', () => { transactionId: 'aefddd38-cfa0-48ab-8bdd-325de4bab5f9' } ]; - describe('isBidRequestValid', () => { - it('Valid bid requests', () => { + describe('isBidRequestValid', function () { + it('Valid bid requests', function () { expect(spec.isBidRequestValid(bids[0])).to.be.true; expect(spec.isBidRequestValid(bids[1])).to.be.true; }); - it('Invalid bid reqeusts - no placementId', () => { + it('Invalid bid reqeusts - no placementId', function () { let bidsClone = utils.deepClone(bids); bidsClone[0].params = undefined; expect(spec.isBidRequestValid(bidsClone[0])).to.be.false; }); - it('Invalid bid reqeusts - invalid banner sizes', () => { + it('Invalid bid reqeusts - invalid banner sizes', function () { let bidsClone = utils.deepClone(bids); bidsClone[0].mediaTypes.banner.sizes = [300, 250]; expect(spec.isBidRequestValid(bidsClone[0])).to.be.false; @@ -58,14 +58,14 @@ describe('ccxAdapter', () => { bidsClone[0].mediaTypes.banner.sizes = []; expect(spec.isBidRequestValid(bidsClone[0])).to.be.false; }); - it('Invalid bid reqeusts - invalid video sizes', () => { + it('Invalid bid reqeusts - invalid video sizes', function () { let bidsClone = utils.deepClone(bids); bidsClone[1].mediaTypes.video.playerSize = []; expect(spec.isBidRequestValid(bidsClone[1])).to.be.false; bidsClone[1].mediaTypes.video.sizes = [640, 480]; expect(spec.isBidRequestValid(bidsClone[1])).to.be.false; }); - it('Valid bid reqeust - old style sizes', () => { + it('Valid bid reqeust - old style sizes', function () { let bidsClone = utils.deepClone(bids); delete (bidsClone[0].mediaTypes); delete (bidsClone[1].mediaTypes); diff --git a/test/spec/modules/clickforceBidAdapter_spec.js b/test/spec/modules/clickforceBidAdapter_spec.js index 8b0955590a0..3d4fc70c057 100644 --- a/test/spec/modules/clickforceBidAdapter_spec.js +++ b/test/spec/modules/clickforceBidAdapter_spec.js @@ -2,16 +2,16 @@ import { expect } from 'chai'; import { spec } from 'modules/clickforceBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -describe('ClickforceAdapter', () => { +describe('ClickforceAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'clickforce', 'params': { @@ -26,11 +26,11 @@ describe('ClickforceAdapter', () => { 'auctionId': '1d1a030790a475' }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -40,7 +40,7 @@ describe('ClickforceAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [{ 'bidder': 'clickforce', 'params': { @@ -57,12 +57,12 @@ describe('ClickforceAdapter', () => { const request = spec.buildRequests(bidRequests); - it('sends bid request to our endpoint via POST', () => { + it('sends bid request to our endpoint via POST', function () { expect(request.method).to.equal('POST'); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = [{ 'cpm': 0.5, 'width': '300', @@ -78,25 +78,88 @@ describe('ClickforceAdapter', () => { 'zone': '6682' }]; - it('should get the correct bid response', () => { - let expectedResponse = [{ - 'requestId': '220ed41385952a', - 'cpm': 0.5, - 'width': '300', - 'height': '250', - 'creativeId': '1f99ac5c3ef10a4097499a5686b30aff-6682', - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 60, - 'ad': '' - }]; + let response1 = [{ + 'cpm': 0.0625, + 'width': '3', + 'height': '3', + 'callback_uid': '2e27ec595bf1a', + 'type': 'public Bid', + 'tag': { + 'content': { + 'title': 'title', + 'content': 'content', + 'advertiser': 'advertiser', + 'button_text': 'button_text', + 'image': 'image', + 'icon': 'icon' + }, + 'cu': ['cu'], + 'iu': ['iu'], + 'p': '6878:11062:32586:8380573788dad9b9fc17edde444c4dcf:2795' + }, + 'creativeId': '8380573788dad9b9fc17edde444c4dcf-6878', + 'requestId': '2e27ec595bf1a', + 'currency': 'USD', + 'ttl': 60, + 'netRevenue': true, + 'zone': '6878' + }]; + + let expectedResponse = [{ + 'requestId': '220ed41385952a', + 'cpm': 0.5, + 'width': '300', + 'height': '250', + 'creativeId': '1f99ac5c3ef10a4097499a5686b30aff-6682', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 60, + 'ad': '', + 'mediaType': 'banner', + }]; + + let expectedResponse1 = [{ + 'requestId': '2e27ec595bf1a', + 'cpm': 0.0625, + 'width': '3', + 'height': '3', + 'creativeId': '8380573788dad9b9fc17edde444c4dcf-6878', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 60, + 'mediaType': 'native', + 'native': { + 'image': { + 'url': 'image', + 'width': 1600, + 'height': 900 + }, + 'title': 'title', + 'sponsoredBy': 'advertiser', + 'body': 'content', + 'icon': { + 'url': 'icon', + 'width': 900, + 'height': 900 + }, + 'clickUrl': 'cu', + 'impressionTrackers': ['iu'] + } + }]; + it('should get the correct bid response by display ad', function () { let bidderRequest; let result = spec.interpretResponse({ body: response }, {bidderRequest}); expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('handles empty bid response', () => { + it('should get the correct bid response by native ad', function () { + let bidderRequest; + let result = spec.interpretResponse({ body: response1 }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse1[0])); + }); + + it('handles empty bid response', function () { let response = { body: {} }; @@ -105,8 +168,8 @@ describe('ClickforceAdapter', () => { }); }); - describe('getUserSyncs function', () => { - it('should register type is iframe', () => { + describe('getUserSyncs function', function () { + it('should register type is iframe', function () { const syncOptions = { 'iframeEnabled': 'true' } @@ -115,7 +178,7 @@ describe('ClickforceAdapter', () => { expect(userSync[0].url).to.equal('https://cdn.doublemax.net/js/capmapping.htm'); }); - it('should register type is image', () => { + it('should register type is image', function () { const syncOptions = { 'pixelEnabled': 'true' } diff --git a/test/spec/modules/colombiaBidAdapter_spec.js b/test/spec/modules/colombiaBidAdapter_spec.js new file mode 100644 index 00000000000..5a8678e866c --- /dev/null +++ b/test/spec/modules/colombiaBidAdapter_spec.js @@ -0,0 +1,152 @@ +import { expect } from 'chai'; +import { spec } from 'modules/colombiaBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const HOST_NAME = document.location.protocol + '//' + window.location.host; +const ENDPOINT = 'https://ade.clmbtech.com/cde/prebid.htm'; + +describe('colombiaBidAdapter', function() { + const adapter = newBidder(spec); + + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'colombia', + 'params': { + placementId: '307466' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250] + ], + 'bidId': '23beaa6af6cdde', + 'bidderRequestId': '19c0c1efdf37e7', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when placementId not passed correctly', function () { + bid.params.placementId = ''; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when require params are not passed', function () { + let bid = Object.assign({}, bid); + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [ + { + 'bidder': 'colombia', + 'params': { + placementId: '307466' + }, + 'adUnitCode': 'adunit-code1', + 'sizes': [ + [300, 250] + ], + 'bidId': '23beaa6af6cdde', + 'bidderRequestId': '19c0c1efdf37e7', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + }, + { + 'bidder': 'colombia', + 'params': { + placementId: '307466' + }, + 'adUnitCode': 'adunit-code2', + 'sizes': [ + [300, 250] + ], + 'bidId': '382091349b149f"', + 'bidderRequestId': '"1f9c98192de251"', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + } + ]; + + const request = spec.buildRequests(bidRequests); + + it('sends bid request to our endpoint via POST', function () { + expect(request[0].method).to.equal('POST'); + expect(request[1].method).to.equal('POST'); + }); + + it('attaches source and version to endpoint URL as query params', function () { + expect(request[0].url).to.equal(ENDPOINT); + expect(request[1].url).to.equal(ENDPOINT); + }); + }); + + describe('interpretResponse', function () { + let bidRequest = [ + { + 'method': 'POST', + 'url': ENDPOINT, + 'data': { + 'v': 'hb1', + 'p': '307466', + 'w': '300', + 'h': '250', + 'cb': 12892917383, + 'r': 'http%3A%2F%2Flocalhost%3A9876%2F%3Fid%3D74552836', + 'uid': '23beaa6af6cdde', + 't': 'i', + 'd': HOST_NAME + } + } + ]; + + let serverResponse = { + body: { + 'ad': '
This is test case
', + 'cpm': 3.14, + 'creativeId': '6b958110-612c-4b03-b6a9-7436c9f746dc-1sk24', + 'currency': 'USD', + 'statusMessage': 'Bid available', + 'uid': '23beaa6af6cdde', + 'width': 300, + 'height': 250, + 'netRevenue': true, + 'ttl': 600 + } + }; + + it('should get the correct bid response', function () { + let expectedResponse = [{ + 'requestId': '23beaa6af6cdde', + 'cpm': 3.14, + 'width': 300, + 'height': 250, + 'creativeId': '6b958110-612c-4b03-b6a9-7436c9f746dc-1sk24', + 'dealId': '', + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 3000, + 'referrer': '', + 'ad': '
This is test case
' + }]; + let result = spec.interpretResponse(serverResponse, bidRequest[0]); + expect(Object.keys(result)).to.deep.equal(Object.keys(expectedResponse)); + }); + + it('handles empty bid response', function () { + let response = { + body: { + 'uid': '2c0b634db95a01', + 'height': 0, + 'crid': '', + 'statusMessage': 'Bid returned empty or error response', + 'width': 0, + 'cpm': 0 + } + }; + let result = spec.interpretResponse(response, bidRequest[0]); + expect(result.length).to.equal(0); + }); + }); +}); diff --git a/test/spec/modules/colossussspBidAdapter_spec.js b/test/spec/modules/colossussspBidAdapter_spec.js index 54952fbf4b5..62b4158676e 100644 --- a/test/spec/modules/colossussspBidAdapter_spec.js +++ b/test/spec/modules/colossussspBidAdapter_spec.js @@ -1,7 +1,7 @@ import {expect} from 'chai'; import {spec} from '../../../modules/colossussspBidAdapter'; -describe('ColossussspAdapter', () => { +describe('ColossussspAdapter', function () { let bid = { bidId: '2dd581a2b6281d', bidder: 'colossusssp', @@ -15,31 +15,31 @@ describe('ColossussspAdapter', () => { transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62' }; - describe('isBidRequestValid', () => { - it('Should return true when placement_id can be cast to a number', () => { + describe('isBidRequestValid', function () { + it('Should return true when placement_id can be cast to a number', function () { expect(spec.isBidRequestValid(bid)).to.be.true; }); - it('Should return false when placement_id is not a number', () => { + it('Should return false when placement_id is not a number', function () { bid.params.placement_id = 'aaa'; expect(spec.isBidRequestValid(bid)).to.be.false; }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let serverRequest = spec.buildRequests([bid]); - it('Creates a ServerRequest object with method, URL and data', () => { + it('Creates a ServerRequest object with method, URL and data', function () { expect(serverRequest).to.exist; expect(serverRequest.method).to.exist; expect(serverRequest.url).to.exist; expect(serverRequest.data).to.exist; }); - it('Returns POST method', () => { + it('Returns POST method', function () { expect(serverRequest.method).to.equal('POST'); }); - it('Returns valid URL', () => { + it('Returns valid URL', function () { expect(serverRequest.url).to.equal('//colossusssp.com/?c=o&m=multi'); }); - it('Returns valid data if array of bids is valid', () => { + it('Returns valid data if array of bids is valid', function () { let data = serverRequest.data; expect(data).to.be.an('object'); expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements'); @@ -59,13 +59,13 @@ describe('ColossussspAdapter', () => { expect(placement.sizes).to.be.an('array'); } }); - it('Returns empty data if no valid requests are passed', () => { + it('Returns empty data if no valid requests are passed', function () { serverRequest = spec.buildRequests([]); let data = serverRequest.data; expect(data.placements).to.be.an('array').that.is.empty; }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let resObject = { body: [ { requestId: '123', @@ -81,7 +81,7 @@ describe('ColossussspAdapter', () => { } ] }; let serverResponses = spec.interpretResponse(resObject); - it('Returns an array of valid server responses if response object is valid', () => { + it('Returns an array of valid server responses if response object is valid', function () { expect(serverResponses).to.be.an('array').that.is.not.empty; for (let i = 0; i < serverResponses.length; i++) { let dataItem = serverResponses[i]; @@ -98,16 +98,16 @@ describe('ColossussspAdapter', () => { expect(dataItem.currency).to.be.a('string'); expect(dataItem.mediaType).to.be.a('string'); } - it('Returns an empty array if invalid response is passed', () => { + it('Returns an empty array if invalid response is passed', function () { serverResponses = spec.interpretResponse('invalid_response'); expect(serverResponses).to.be.an('array').that.is.empty; }); }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { let userSync = spec.getUserSyncs(); - it('Returns valid URL and type', () => { + it('Returns valid URL and type', function () { expect(userSync).to.be.an('array').with.lengthOf(1); expect(userSync[0].type).to.exist; expect(userSync[0].url).to.exist; diff --git a/test/spec/modules/consentManagement_spec.js b/test/spec/modules/consentManagement_spec.js index e825de2a184..6af8c8a4478 100644 --- a/test/spec/modules/consentManagement_spec.js +++ b/test/spec/modules/consentManagement_spec.js @@ -1,4 +1,4 @@ -import {setConfig, requestBidsHook, resetConsentData, userCMP, consentTimeout, allowAuction} from 'modules/consentManagement'; +import {setConfig, requestBidsHook, resetConsentData, userCMP, consentTimeout, allowAuction, staticConsentData} from 'modules/consentManagement'; import {gdprDataHandler} from 'src/adaptermanager'; import * as utils from 'src/utils'; import { config } from 'src/config'; @@ -7,32 +7,32 @@ let assert = require('chai').assert; let expect = require('chai').expect; describe('consentManagement', function () { - describe('setConfig tests:', () => { - describe('empty setConfig value', () => { - beforeEach(() => { + describe('setConfig tests:', function () { + describe('empty setConfig value', function () { + beforeEach(function () { sinon.stub(utils, 'logInfo'); }); - afterEach(() => { + afterEach(function () { utils.logInfo.restore(); config.resetConfig(); }); - it('should use system default values', () => { + it('should use system default values', function () { setConfig({}); expect(userCMP).to.be.equal('iab'); expect(consentTimeout).to.be.equal(10000); expect(allowAuction).to.be.true; - sinon.assert.callCount(utils.logInfo, 3); + sinon.assert.callCount(utils.logInfo, 4); }); }); - describe('valid setConfig value', () => { - afterEach(() => { + describe('valid setConfig value', function () { + afterEach(function () { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); }); - it('results in all user settings overriding system defaults', () => { + it('results in all user settings overriding system defaults', function () { let allConfig = { cmpApi: 'iab', timeout: 7500, @@ -45,9 +45,418 @@ describe('consentManagement', function () { expect(allowAuction).to.be.false; }); }); + + describe('static consent string setConfig value', () => { + afterEach(() => { + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + }); + it('results in user settings overriding system defaults', () => { + let staticConfig = { + cmpApi: 'static', + timeout: 7500, + allowAuctionWithoutConsent: false, + consentData: { + getConsentData: { + 'gdprApplies': true, + 'hasGlobalScope': false, + 'consentData': 'BOOgjO9OOgjO9APABAENAi-AAAAWd7_______9____7_9uz_Gv_r_ff_3nW0739P1A_r_Oz_rm_-zzV44_lpQQRCEA' + }, + getVendorConsents: { + 'metadata': 'BOOgjO9OOgjO9APABAENAi-AAAAWd7_______9____7_9uz_Gv_r_ff_3nW0739P1A_r_Oz_rm_-zzV44_lpQQRCEA', + 'gdprApplies': true, + 'hasGlobalScope': false, + 'isEU': true, + 'cookieVersion': 1, + 'created': '2018-05-29T07:45:48.522Z', + 'lastUpdated': '2018-05-29T07:45:48.522Z', + 'cmpId': 15, + 'cmpVersion': 1, + 'consentLanguage': 'EN', + 'vendorListVersion': 34, + 'maxVendorId': 359, + 'purposeConsents': { + '1': true, + '2': true, + '3': true, + '4': true, + '5': true + }, + 'vendorConsents': { + '1': true, + '2': true, + '3': true, + '4': true, + '5': false, + '6': true, + '7': true, + '8': true, + '9': true, + '10': true, + '11': true, + '12': true, + '13': true, + '14': true, + '15': true, + '16': true, + '17': true, + '18': true, + '19': true, + '20': true, + '21': true, + '22': true, + '23': true, + '24': true, + '25': true, + '26': true, + '27': true, + '28': true, + '29': true, + '30': true, + '31': true, + '32': true, + '33': true, + '34': true, + '35': true, + '36': true, + '37': true, + '38': true, + '39': true, + '40': true, + '41': true, + '42': true, + '43': true, + '44': true, + '45': true, + '46': true, + '47': true, + '48': true, + '49': true, + '50': true, + '51': true, + '52': true, + '53': true, + '54': false, + '55': true, + '56': true, + '57': true, + '58': true, + '59': true, + '60': true, + '61': true, + '62': true, + '63': true, + '64': true, + '65': true, + '66': true, + '67': true, + '68': true, + '69': true, + '70': true, + '71': true, + '72': true, + '73': true, + '74': true, + '75': true, + '76': true, + '77': true, + '78': true, + '79': true, + '80': true, + '81': true, + '82': true, + '83': false, + '84': true, + '85': true, + '86': true, + '87': true, + '88': true, + '89': true, + '90': true, + '91': true, + '92': true, + '93': true, + '94': true, + '95': true, + '96': false, + '97': true, + '98': true, + '99': false, + '100': true, + '101': true, + '102': true, + '103': false, + '104': true, + '105': true, + '106': false, + '107': false, + '108': true, + '109': true, + '110': true, + '111': true, + '112': true, + '113': true, + '114': true, + '115': true, + '116': false, + '117': false, + '118': false, + '119': true, + '120': true, + '121': false, + '122': true, + '123': false, + '124': true, + '125': true, + '126': true, + '127': true, + '128': true, + '129': true, + '130': true, + '131': true, + '132': true, + '133': true, + '134': true, + '135': false, + '136': true, + '137': false, + '138': true, + '139': true, + '140': true, + '141': true, + '142': true, + '143': true, + '144': true, + '145': true, + '146': false, + '147': true, + '148': true, + '149': true, + '150': true, + '151': true, + '152': false, + '153': true, + '154': true, + '155': true, + '156': true, + '157': true, + '158': true, + '159': true, + '160': true, + '161': true, + '162': true, + '163': true, + '164': true, + '165': true, + '166': false, + '167': true, + '168': true, + '169': true, + '170': true, + '171': false, + '172': false, + '173': true, + '174': true, + '175': true, + '176': false, + '177': true, + '178': false, + '179': true, + '180': true, + '181': false, + '182': true, + '183': true, + '184': false, + '185': true, + '186': false, + '187': false, + '188': true, + '189': true, + '190': true, + '191': false, + '192': true, + '193': true, + '194': true, + '195': true, + '196': false, + '197': true, + '198': true, + '199': true, + '200': true, + '201': true, + '202': true, + '203': true, + '204': false, + '205': true, + '206': false, + '207': false, + '208': true, + '209': true, + '210': true, + '211': true, + '212': true, + '213': true, + '214': false, + '215': true, + '216': false, + '217': true, + '218': false, + '219': false, + '220': false, + '221': false, + '222': false, + '223': false, + '224': true, + '225': true, + '226': true, + '227': true, + '228': true, + '229': true, + '230': true, + '231': false, + '232': true, + '233': false, + '234': true, + '235': true, + '236': true, + '237': true, + '238': true, + '239': true, + '240': true, + '241': true, + '242': false, + '243': false, + '244': true, + '245': true, + '246': true, + '247': false, + '248': true, + '249': true, + '250': false, + '251': false, + '252': true, + '253': true, + '254': true, + '255': true, + '256': true, + '257': true, + '258': true, + '259': true, + '260': true, + '261': false, + '262': true, + '263': false, + '264': true, + '265': true, + '266': true, + '267': false, + '268': false, + '269': true, + '270': true, + '271': false, + '272': true, + '273': true, + '274': true, + '275': true, + '276': true, + '277': true, + '278': true, + '279': true, + '280': true, + '281': true, + '282': true, + '283': false, + '284': true, + '285': true, + '286': false, + '287': false, + '288': true, + '289': true, + '290': true, + '291': true, + '292': false, + '293': false, + '294': true, + '295': true, + '296': false, + '297': true, + '298': false, + '299': true, + '300': false, + '301': true, + '302': true, + '303': true, + '304': true, + '305': false, + '306': false, + '307': false, + '308': true, + '309': true, + '310': true, + '311': false, + '312': false, + '313': false, + '314': true, + '315': true, + '316': true, + '317': true, + '318': true, + '319': true, + '320': true, + '321': false, + '322': false, + '323': true, + '324': false, + '325': true, + '326': true, + '327': false, + '328': true, + '329': false, + '330': false, + '331': true, + '332': false, + '333': true, + '334': false, + '335': false, + '336': false, + '337': false, + '338': false, + '339': true, + '340': false, + '341': false, + '342': false, + '343': false, + '344': false, + '345': true, + '346': false, + '347': false, + '348': false, + '349': true, + '350': false, + '351': false, + '352': false, + '353': false, + '354': true, + '355': false, + '356': false, + '357': false, + '358': false, + '359': true + } + } + } + }; + + setConfig(staticConfig); + expect(userCMP).to.be.equal('static'); + expect(consentTimeout).to.be.equal(0); // should always return without a timeout when config is used + expect(allowAuction).to.be.false; + expect(staticConsentData).to.be.equal(staticConfig.consentData); + }); + }); }); - describe('requestBidsHook tests:', () => { + describe('requestBidsHook tests:', function () { let goodConfigWithCancelAuction = { cmpApi: 'iab', timeout: 7500, @@ -62,53 +471,65 @@ describe('consentManagement', function () { let didHookReturn; - afterEach(() => { + afterEach(function () { gdprDataHandler.consentData = null; resetConsentData(); }); - describe('error checks:', () => { - describe('unknown CMP framework ID:', () => { - beforeEach(() => { - sinon.stub(utils, 'logWarn'); - }); + describe('error checks:', function () { + beforeEach(function () { + didHookReturn = false; + sinon.stub(utils, 'logWarn'); + sinon.stub(utils, 'logError'); + }); - afterEach(() => { - utils.logWarn.restore(); - config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); - resetConsentData(); - }); + afterEach(function () { + utils.logWarn.restore(); + utils.logError.restore(); + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + resetConsentData(); + }); - it('should return Warning message and return to hooked function', () => { - let badCMPConfig = { - cmpApi: 'bad' - }; - setConfig(badCMPConfig); - expect(userCMP).to.be.equal(badCMPConfig.cmpApi); + it('should throw a warning and return to hooked function when an unknown CMP framework ID is used', function () { + let badCMPConfig = { + cmpApi: 'bad' + }; + setConfig(badCMPConfig); + expect(userCMP).to.be.equal(badCMPConfig.cmpApi); - didHookReturn = false; + requestBidsHook({}, () => { + didHookReturn = true; + }); + let consent = gdprDataHandler.getConsentData(); + sinon.assert.calledOnce(utils.logWarn); + expect(didHookReturn).to.be.true; + expect(consent).to.be.null; + }); - requestBidsHook({}, () => { - didHookReturn = true; - }); - let consent = gdprDataHandler.getConsentData(); - sinon.assert.calledOnce(utils.logWarn); - expect(didHookReturn).to.be.true; - expect(consent).to.be.null; + it('should throw proper errors when CMP is not found', function () { + setConfig(goodConfigWithCancelAuction); + + requestBidsHook({}, () => { + didHookReturn = true; }); + let consent = gdprDataHandler.getConsentData(); + // throw 2 errors; one for no bidsBackHandler and for CMP not being found (this is an error due to gdpr config) + sinon.assert.calledTwice(utils.logError); + expect(didHookReturn).to.be.false; + expect(consent).to.be.null; }); }); - describe('already known consentData:', () => { + describe('already known consentData:', function () { let cmpStub = sinon.stub(); - beforeEach(() => { + beforeEach(function () { didHookReturn = false; window.__cmp = function() {}; }); - afterEach(() => { + afterEach(function () { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); cmpStub.restore(); @@ -116,7 +537,7 @@ describe('consentManagement', function () { resetConsentData(); }); - it('should bypass CMP and simply use previously stored consentData', () => { + it('should bypass CMP and simply use previously stored consentData', function () { let testConsentData = { gdprApplies: true, consentData: 'xyz' @@ -146,10 +567,10 @@ describe('consentManagement', function () { }); }); - describe('CMP workflow for safeframe page', () => { + describe('CMP workflow for safeframe page', function () { let registerStub = sinon.stub(); - beforeEach(() => { + beforeEach(function () { didHookReturn = false; window.$sf = { ext: { @@ -161,7 +582,7 @@ describe('consentManagement', function () { sinon.stub(utils, 'logWarn'); }); - afterEach(() => { + afterEach(function () { delete window.$sf; config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); @@ -171,7 +592,7 @@ describe('consentManagement', function () { resetConsentData(); }); - it('should return the consent data from a safeframe callback', () => { + it('should return the consent data from a safeframe callback', function () { var testConsentData = { data: { msgName: 'cmpReturn', @@ -203,18 +624,18 @@ describe('consentManagement', function () { }); }); - describe('CMP workflow for iframed page', () => { + describe('CMP workflow for iframed page', function () { let ifr = null; let stringifyResponse = false; - beforeEach(() => { + beforeEach(function () { sinon.stub(utils, 'logError'); sinon.stub(utils, 'logWarn'); ifr = createIFrameMarker(); window.addEventListener('message', cmpMessageHandler, false); }); - afterEach(() => { + afterEach(function () { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); delete window.__cmp; @@ -276,17 +697,17 @@ describe('consentManagement', function () { } }); - describe('CMP workflow for normal pages:', () => { + describe('CMP workflow for normal pages:', function () { let cmpStub = sinon.stub(); - beforeEach(() => { + beforeEach(function () { didHookReturn = false; sinon.stub(utils, 'logError'); sinon.stub(utils, 'logWarn'); window.__cmp = function() {}; }); - afterEach(() => { + afterEach(function () { config.resetConfig(); $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); cmpStub.restore(); @@ -296,7 +717,7 @@ describe('consentManagement', function () { resetConsentData(); }); - it('performs lookup check and stores consentData for a valid existing user', () => { + it('performs lookup check and stores consentData for a valid existing user', function () { let testConsentData = { gdprApplies: true, consentData: 'BOJy+UqOJy+UqABAB+AAAAAZ+A==' @@ -319,7 +740,7 @@ describe('consentManagement', function () { expect(consent.gdprApplies).to.be.true; }); - it('throws an error when processCmpData check failed while config had allowAuction set to false', () => { + it('throws an error when processCmpData check failed while config had allowAuction set to false', function () { let testConsentData = {}; let bidsBackHandlerReturn = false; @@ -340,7 +761,7 @@ describe('consentManagement', function () { expect(consent).to.be.null; }); - it('throws a warning + stores consentData + calls callback when processCmpData check failed while config had allowAuction set to true', () => { + it('throws a warning + stores consentData + calls callback when processCmpData check failed while config had allowAuction set to true', function () { let testConsentData = {}; cmpStub = sinon.stub(window, '__cmp').callsFake((...args) => { diff --git a/test/spec/modules/consumableBidAdapter_spec.js b/test/spec/modules/consumableBidAdapter_spec.js index b87ce6634f6..d13c3c56398 100644 --- a/test/spec/modules/consumableBidAdapter_spec.js +++ b/test/spec/modules/consumableBidAdapter_spec.js @@ -1,215 +1,269 @@ -import {expect} from 'chai'; -import * as utils from 'src/utils'; -import {spec} from 'modules/consumableBidAdapter'; -import {config} from 'src/config'; - -const DEFAULT_OAD_CONTENT = ''; -const DEFAULT_AD_CONTENT = '' - -let getDefaultBidResponse = () => { - return { - id: '245730051428950632', - cur: 'USD', - seatbid: [{ - bid: [{ - id: 1, - impid: '245730051428950632', - price: 0.09, - adm: DEFAULT_OAD_CONTENT, - crid: 'creative-id', - h: 90, - w: 728, - dealid: 'deal-id', - ext: {sizeid: 225} - }] - }] - }; -}; +import { expect } from 'chai'; +import { spec } from 'modules/consumableBidAdapter'; -let getBidParams = () => { - return { - placement: 1234567, - network: '9599.1', - unitId: '987654', - unitName: 'unitname', - zoneId: '9599.1' - }; -}; +var bidFactory = require('src/bidfactory.js'); -let getDefaultBidRequest = () => { - return { - bidderCode: 'consumable', - auctionId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', - bidderRequestId: '7101db09af0db2', - start: new Date().getTime(), - bids: [{ - bidder: 'consumable', - bidId: '84ab500420319d', - bidderRequestId: '7101db09af0db2', - auctionId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', - placementCode: 'foo', - params: getBidParams() - }] - }; -}; +const ENDPOINT = 'https://e.serverbid.com/api/v2'; +const SMARTSYNC_CALLBACK = 'serverbidCallBids'; -let getPixels = () => { - return ''; +const REQUEST = { + 'bidderCode': 'consumable', + 'auctionId': 'a4713c32-3762-4798-b342-4ab810ca770d', + 'bidderRequestId': '109f2a181342a9', + 'bidRequest': [{ + 'bidder': 'consumable', + 'params': { + 'networkId': 9969, + 'siteId': 730181, + 'unitId': 123456, + 'unitName': 'cnsmbl-unit' + }, + 'placementCode': 'div-gpt-ad-1487778092495-0', + 'sizes': [ + [728, 90], + [970, 90] + ], + 'bidId': '2b0f82502298c9', + 'bidderRequestId': '109f2a181342a9', + 'auctionId': 'a4713c32-3762-4798-b342-4ab810ca770d' + }, + { + 'bidder': 'consumable', + 'params': { + 'networkId': 9969, + 'siteId': 730181, + 'unitId': 123456, + 'unitName': 'cnsmbl-unit' + }, + 'placementCode': 'div-gpt-ad-1487778092495-0', + 'sizes': [ + [728, 90], + [970, 90] + ], + 'bidId': '123', + 'bidderRequestId': '109f2a181342a9', + 'auctionId': 'a4713c32-3762-4798-b342-4ab810ca770d' + }], + 'start': 1487883186070, + 'auctionStart': 1487883186069, + 'timeout': 3000 }; -describe('ConsumableAdapter', () => { - const CONSUMABLE_URL = '//adserver-us.adtech.advertising.com/pubapi/3.0/'; - const CONSUMABLE_TTL = 60; - - function createCustomBidRequest({bids, params} = {}) { - var bidderRequest = getDefaultBidRequest(); - if (bids && Array.isArray(bids)) { - bidderRequest.bids = bids; - } - if (params) { - bidderRequest.bids.forEach(bid => bid.params = params); +const RESPONSE = { + 'headers': null, + 'body': { + 'user': { 'key': 'ue1-2d33e91b71e74929b4aeecc23f4376f1' }, + 'decisions': { + '2b0f82502298c9': { + 'adId': 2364764, + 'creativeId': 1950991, + 'flightId': 2788300, + 'campaignId': 542982, + 'clickUrl': 'https://e.serverbid.com/r', + 'impressionUrl': 'https://e.serverbid.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://e.serverbid.com/r', + 'impressionUrl': 'https://e.serverbid.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} + } } - return bidderRequest; } +}; - describe('interpretResponse()', () => { - let bidderSettingsBackup; - let bidResponse; - let bidRequest; - let logWarnSpy; - - beforeEach(() => { - bidderSettingsBackup = $$PREBID_GLOBAL$$.bidderSettings; - bidRequest = { - bidderCode: 'test-bidder-code', - bidId: 'bid-id', - unitName: 'unitname', - unitId: '987654', - zoneId: '9599.1', - network: '9599.1' - }; - bidResponse = { - body: getDefaultBidResponse() +describe('Consumable BidAdapter', function () { + let bidRequests; + let adapter = spec; + + beforeEach(function () { + bidRequests = [ + { + bidder: 'consumable', + params: { + networkId: '9969', + siteId: '730181', + unitId: '123456', + unitName: 'cnsmbl-unit' + }, + placementCode: 'header-bid-tag-1', + sizes: [[300, 250], [300, 600]], + bidId: '23acc48ad47af5', + auctionId: '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: 'consumable', + params: { + networkId: '9969', + siteId: '123', + unitId: '123456', + unitName: 'cnsmbl-unit' + } }; - logWarnSpy = sinon.spy(utils, 'logWarn'); + expect(spec.isBidRequestValid(bid)).to.equal(true); }); - afterEach(() => { - $$PREBID_GLOBAL$$.bidderSettings = bidderSettingsBackup; - logWarnSpy.restore(); + it('should accept valid bid requests with extra fields', function () { + let bid = { + bidder: 'consumable', + params: { + networkId: '9969', + siteId: '123', + unitId: '123456', + unitName: 'cnsmbl-unit', + zoneId: '123' + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return formatted bid response with required properties', () => { - 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, - ttl: 60 - }); + it('should reject bid requests without siteId', function () { + let bid = { + bidder: 'consumable', + params: { + networkId: '9969', + unitId: '123456', + unitName: 'cnsmbl-unit' + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should add formatted pixels to ad content when pixels are present in the response', () => { - bidResponse.body.ext = { - pixels: 'pixels-content' + it('should reject bid requests without networkId', function () { + let bid = { + bidder: 'consumable', + params: { + siteId: '9969', + unitId: '123456', + unitName: 'cnsmbl-unit' + } }; - - let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); - - expect(formattedBidResponse.ad).to.equal(DEFAULT_AD_CONTENT + ''); - return true; + expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); - describe('buildRequests()', () => { - it('method exists and is a function', () => { - expect(spec.buildRequests).to.exist.and.to.be.a('function'); + describe('buildRequests validation', function () { + it('creates request data', function () { + let request = spec.buildRequests(bidRequests); + + expect(request).to.exist.and.to.be.a('object'); }); - describe('Consumable', () => { - it('should not return request when no bids are present', () => { - let [request] = spec.buildRequests([]); - expect(request).to.be.empty; - }); + it('request to consumable should contain a url', function () { + let request = spec.buildRequests(bidRequests); - it('should return request for endpoint', () => { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain(CONSUMABLE_URL); - }); + expect(request.url).to.have.string('serverbid.com'); + }); - it('should return url with pubapi bid option', () => { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('cmd=bid;'); - }); + it('requires valid bids to make request', function () { + let request = spec.buildRequests([]); + expect(request.bidRequest).to.be.empty; + }); - it('should return url with version 2 of pubapi', () => { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.contain('v=2;'); - }); + it('sends bid request to ENDPOINT via POST', function () { + let request = spec.buildRequests(bidRequests); - it('should return url with cache busting option', () => { - let bidRequest = getDefaultBidRequest(); - let [request] = spec.buildRequests(bidRequest.bids); - expect(request.url).to.match(/misc=\d+/); - }); + expect(request.method).to.have.string('POST'); }); }); + describe('interpretResponse validation', function () { + it('response should have valid bidderCode', function () { + let bidRequest = spec.buildRequests(REQUEST.bidRequest); + let bid = bidFactory.createBid(1, bidRequest.bidRequest[0]); + + expect(bid.bidderCode).to.equal('consumable'); + }); - describe('getUserSyncs()', () => { - let bidResponse; - let bidRequest; + it('response should include objects for all bids', function () { + let bids = spec.interpretResponse(RESPONSE, REQUEST); + expect(bids.length).to.equal(2); + }); - beforeEach(() => { - $$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped = false; - config.setConfig({ - consumable: { - userSyncOn: 'bidResponse' - }, + 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('unitId'); + expect(b).to.have.property('unitName'); + 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).to.have.property('netRevenue', true); + expect(b).to.have.property('referrer'); }); - bidResponse = getDefaultBidResponse(); - bidResponse.ext = { - pixels: getPixels() - }; }); - it('should return user syncs only if userSyncOn equals to "bidResponse"', () => { - let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); + it('handles nobid responses', function () { + let EMPTY_RESP = Object.assign({}, RESPONSE, {'body': {'decisions': null}}) + let bids = spec.interpretResponse(EMPTY_RESP, REQUEST); - expect($$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped).to.be.true; - expect(userSyncs).to.deep.equal([ - {type: 'image', url: 'img.org'}, - {type: 'iframe', url: 'pixels1.org'} - ]); + expect(bids).to.be.empty; }); - it('should not return user syncs if it has already been returned', () => { - $$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped = true; + it('handles no server response', function () { + let bids = spec.interpretResponse(null, REQUEST); - let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); - - expect($$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped).to.be.true; - expect(userSyncs).to.deep.equal([]); + expect(bids).to.be.empty; }); + }); + describe('getUserSyncs', function () { + let syncOptions = {'iframeEnabled': true}; - it('should not return user syncs if pixels are not present', () => { - bidResponse.ext.pixels = null; + it('handles empty sync options', function () { + let opts = spec.getUserSyncs({}); + + expect(opts).to.be.empty; + }); - let userSyncs = spec.getUserSyncs({}, [bidResponse], bidRequest); + it('should return a sync url if iframe syncs are enabled', function () { + let opts = spec.getUserSyncs(syncOptions); - expect($$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped).to.be.false; - expect(userSyncs).to.deep.equal([]); + expect(opts.length).to.equal(1); }); }); }); diff --git a/test/spec/modules/contentigniteBidAdapter_spec.js b/test/spec/modules/contentigniteBidAdapter_spec.js index cdf70e15615..1867791a234 100644 --- a/test/spec/modules/contentigniteBidAdapter_spec.js +++ b/test/spec/modules/contentigniteBidAdapter_spec.js @@ -1,10 +1,10 @@ import { expect } from 'chai'; import { spec } from '../../../modules/contentigniteBidAdapter'; -describe('Content Ignite adapter', () => { +describe('Content Ignite adapter', function () { let bidRequests; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { bidder: 'contentignite', @@ -25,9 +25,9 @@ describe('Content Ignite adapter', () => { ]; }); - describe('implementation', () => { - describe('for requests', () => { - it('should accept valid bid', () => { + describe('implementation', function () { + describe('for requests', function () { + it('should accept valid bid', function () { const validBid = { bidder: 'contentignite', params: { @@ -40,7 +40,7 @@ describe('Content Ignite adapter', () => { expect(isValid).to.equal(true); }); - it('should reject invalid bid', () => { + it('should reject invalid bid', function () { const invalidBid = { bidder: 'contentignite', params: { @@ -52,14 +52,14 @@ describe('Content Ignite adapter', () => { expect(isValid).to.equal(false); }); - it('should set the keyword parameter', () => { + it('should set the keyword parameter', function () { const requests = spec.buildRequests(bidRequests), requestURL = requests[0].url; expect(requestURL).to.have.string(';kw=business;'); }); - it('should increment the count for the same zone', () => { + it('should increment the count for the same zone', function () { const bidRequests = [ { sizes: [[728, 90]], @@ -87,8 +87,8 @@ describe('Content Ignite adapter', () => { }); }); - describe('bid responses', () => { - it('should return complete bid response', () => { + describe('bid responses', function () { + it('should return complete bid response', function () { const serverResponse = { body: { status: 'SUCCESS', @@ -116,7 +116,7 @@ describe('Content Ignite adapter', () => { expect(bids[0].ad).to.have.length.above(1); }); - it('should return empty bid response', () => { + it('should return empty bid response', function () { const serverResponse = { status: 'NO_ELIGIBLE_ADS', zone_id: 299680, @@ -131,7 +131,7 @@ describe('Content Ignite adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response on incorrect size', () => { + it('should return empty bid response on incorrect size', function () { const serverResponse = { status: 'SUCCESS', account_id: 168237, @@ -148,7 +148,7 @@ describe('Content Ignite adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response with CPM too low', () => { + it('should return empty bid response with CPM too low', function () { const serverResponse = { status: 'SUCCESS', account_id: 168237, @@ -165,7 +165,7 @@ describe('Content Ignite adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response with CPM too high', () => { + it('should return empty bid response with CPM too high', function () { const serverResponse = { status: 'SUCCESS', account_id: 168237, diff --git a/test/spec/modules/coxBidAdapter_spec.js b/test/spec/modules/coxBidAdapter_spec.js index 9dd5a5a92b4..8d8b29ed4d7 100644 --- a/test/spec/modules/coxBidAdapter_spec.js +++ b/test/spec/modules/coxBidAdapter_spec.js @@ -3,10 +3,10 @@ import { spec } from 'modules/coxBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; import { deepClone } from 'src/utils'; -describe('CoxBidAdapter', () => { +describe('CoxBidAdapter', function () { const adapter = newBidder(spec); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { const CONFIG = { 'bidder': 'cox', 'params': { @@ -16,18 +16,18 @@ describe('CoxBidAdapter', () => { } }; - it('should return true when required params present', () => { + it('should return true when required params present', function () { expect(spec.isBidRequestValid(CONFIG)).to.equal(true); }); - it('should return false when id param is missing', () => { + it('should return false when id param is missing', function () { let config = deepClone(CONFIG); config.params.id = null; expect(spec.isBidRequestValid(config)).to.equal(false); }); - it('should return false when size param is missing', () => { + it('should return false when size param is missing', function () { let config = deepClone(CONFIG); config.params.size = null; @@ -35,7 +35,7 @@ describe('CoxBidAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const PROD_DOMAIN = 'ad.afy11.net'; const PPE_DOMAIN = 'ppe-ad.afy11.net'; const STG_DOMAIN = 'staging-ad.afy11.net'; @@ -52,13 +52,13 @@ describe('CoxBidAdapter', () => { 'bidId': 'bId-bar' }]; - it('should send bid request to PROD_DOMAIN via GET', () => { + it('should send bid request to PROD_DOMAIN via GET', function () { let request = spec.buildRequests(BID_INFO); expect(request.url).to.have.string(PROD_DOMAIN); expect(request.method).to.equal('GET'); }); - it('should send bid request to PPE_DOMAIN when configured', () => { + it('should send bid request to PPE_DOMAIN when configured', function () { let clone = deepClone(BID_INFO); clone[0].params.env = 'PPE'; @@ -66,7 +66,7 @@ describe('CoxBidAdapter', () => { expect(request.url).to.have.string(PPE_DOMAIN); }); - it('should send bid request to STG_DOMAIN when configured', () => { + it('should send bid request to STG_DOMAIN when configured', function () { let clone = deepClone(BID_INFO); clone[0].params.env = 'STG'; @@ -74,7 +74,7 @@ describe('CoxBidAdapter', () => { expect(request.url).to.have.string(STG_DOMAIN); }); - it('should return empty when id is invalid', () => { + it('should return empty when id is invalid', function () { let clone = deepClone(BID_INFO); clone[0].params.id = null; @@ -82,7 +82,7 @@ describe('CoxBidAdapter', () => { expect(request).to.be.an('object').that.is.empty; }); - it('should return empty when size is invalid', () => { + it('should return empty when size is invalid', function () { let clone = deepClone(BID_INFO); clone[0].params.size = 'FOO'; @@ -91,7 +91,7 @@ describe('CoxBidAdapter', () => { }); }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { const BID_INFO_1 = [{ 'bidder': 'cox', 'params': { @@ -157,12 +157,12 @@ describe('CoxBidAdapter', () => { 'ad': '

2000005658887
300x250

' }; - it('should return correct pbjs bid', () => { + it('should return correct pbjs bid', function () { let result = spec.interpretResponse(RESPONSE_2, spec.buildRequests(BID_INFO_2)); expect(result[0]).to.eql(PBJS_BID_2); }); - it('should handle multiple bid instances', () => { + it('should handle multiple bid instances', function () { let request1 = spec.buildRequests(BID_INFO_1); let request2 = spec.buildRequests(BID_INFO_2); @@ -173,7 +173,7 @@ describe('CoxBidAdapter', () => { expect(result1[0]).to.eql(PBJS_BID_1); }); - it('should return empty when price is zero', () => { + it('should return empty when price is zero', function () { let clone = deepClone(RESPONSE_1); clone.body.zones.as2000005657007.price = 0; @@ -181,7 +181,7 @@ describe('CoxBidAdapter', () => { expect(result).to.be.an('array').that.is.empty; }); - it('should return empty when there is no ad', () => { + it('should return empty when there is no ad', function () { let clone = deepClone(RESPONSE_1); clone.body.zones.as2000005657007.ad = null; @@ -189,7 +189,7 @@ describe('CoxBidAdapter', () => { expect(result).to.be.an('array').that.is.empty; }); - it('should return empty when there is no ad unit info', () => { + it('should return empty when there is no ad unit info', function () { let clone = deepClone(RESPONSE_1); delete (clone.body.zones.as2000005657007); @@ -198,26 +198,26 @@ describe('CoxBidAdapter', () => { }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { const RESPONSE = [{ body: { 'zones': {}, 'tpCookieSync': ['http://pixel.foo.com/', 'http://pixel.bar.com/'] }}]; - it('should return correct pbjs syncs when pixels are enabled', () => { + it('should return correct pbjs syncs when pixels are enabled', function () { let syncs = spec.getUserSyncs({ pixelEnabled: true }, RESPONSE); expect(syncs.map(x => x.type)).to.eql(['image', 'image']); expect(syncs.map(x => x.url)).to.have.members(['http://pixel.bar.com/', 'http://pixel.foo.com/']); }); - it('should return empty when pixels are not enabled', () => { + it('should return empty when pixels are not enabled', function () { let syncs = spec.getUserSyncs({ pixelEnabled: false }, RESPONSE); expect(syncs).to.be.an('array').that.is.empty; }); - it('should return empty when response has no sync data', () => { + it('should return empty when response has no sync data', function () { let clone = deepClone(RESPONSE); delete (clone[0].body.tpCookieSync); @@ -225,7 +225,7 @@ describe('CoxBidAdapter', () => { expect(syncs).to.be.an('array').that.is.empty; }); - it('should return empty when response is empty', () => { + it('should return empty when response is empty', function () { let syncs = spec.getUserSyncs({ pixelEnabled: true }, [{}]); expect(syncs).to.be.an('array').that.is.empty; }); diff --git a/test/spec/modules/criteoBidAdapter_spec.js b/test/spec/modules/criteoBidAdapter_spec.js index e855c828b1f..e232bf0e3d9 100755 --- a/test/spec/modules/criteoBidAdapter_spec.js +++ b/test/spec/modules/criteoBidAdapter_spec.js @@ -2,9 +2,9 @@ import { expect } from 'chai'; import { spec } from 'modules/criteoBidAdapter'; import * as utils from 'src/utils'; -describe('The Criteo bidding adapter', () => { - describe('isBidRequestValid', () => { - it('should return false when given an invalid bid', () => { +describe('The Criteo bidding adapter', function () { + describe('isBidRequestValid', function () { + it('should return false when given an invalid bid', function () { const bid = { bidder: 'criteo', }; @@ -12,7 +12,7 @@ describe('The Criteo bidding adapter', () => { expect(isValid).to.equal(false); }); - it('should return true when given a zoneId bid', () => { + it('should return true when given a zoneId bid', function () { const bid = { bidder: 'criteo', params: { @@ -23,7 +23,7 @@ describe('The Criteo bidding adapter', () => { expect(isValid).to.equal(true); }); - it('should return true when given a networkId bid', () => { + it('should return true when given a networkId bid', function () { const bid = { bidder: 'criteo', params: { @@ -34,7 +34,7 @@ describe('The Criteo bidding adapter', () => { expect(isValid).to.equal(true); }); - it('should return true when given a mixed bid with both a zoneId and a networkId', () => { + it('should return true when given a mixed bid with both a zoneId and a networkId', function () { const bid = { bidder: 'criteo', params: { @@ -47,7 +47,7 @@ describe('The Criteo bidding adapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const bidderRequest = { timeout: 3000, gdprConsent: { gdprApplies: 1, @@ -60,7 +60,7 @@ describe('The Criteo bidding adapter', () => { }, }; - it('should properly build a zoneId request', () => { + it('should properly build a zoneId request', function () { const bidRequests = [ { bidder: 'criteo', @@ -73,7 +73,7 @@ describe('The Criteo bidding adapter', () => { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&cb=\d/); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); expect(request.method).to.equal('POST'); const ortbRequest = request.data; expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); @@ -88,7 +88,7 @@ describe('The Criteo bidding adapter', () => { expect(ortbRequest.gdprConsent.consentGiven).to.equal(true); }); - it('should properly build a networkId request', () => { + it('should properly build a networkId request', function () { const bidderRequest = { timeout: 3000, gdprConsent: { @@ -113,7 +113,7 @@ describe('The Criteo bidding adapter', () => { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&cb=\d/); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); expect(request.method).to.equal('POST'); const ortbRequest = request.data; expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); @@ -129,7 +129,7 @@ describe('The Criteo bidding adapter', () => { expect(ortbRequest.gdprConsent.consentGiven).to.equal(undefined); }); - it('should properly build a mixed request', () => { + it('should properly build a mixed request', function () { const bidderRequest = { timeout: 3000 }; const bidRequests = [ { @@ -152,7 +152,7 @@ describe('The Criteo bidding adapter', () => { }, ]; const request = spec.buildRequests(bidRequests, bidderRequest); - expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&cb=\d/); + expect(request.url).to.match(/^\/\/bidder\.criteo\.com\/cdb\?profileId=207&av=\d+&wv=[^&]+&cb=\d/); expect(request.method).to.equal('POST'); const ortbRequest = request.data; expect(ortbRequest.publisher.url).to.equal(utils.getTopWindowUrl()); @@ -170,7 +170,7 @@ describe('The Criteo bidding adapter', () => { expect(ortbRequest.gdprConsent).to.equal(undefined); }); - it('should properly build request with undefined gdpr consent fields when they are not provided', () => { + it('should properly build request with undefined gdpr consent fields when they are not provided', function () { const bidRequests = [ { bidder: 'criteo', @@ -194,15 +194,15 @@ describe('The Criteo bidding adapter', () => { }); }); - describe('interpretResponse', () => { - it('should return an empty array when parsing a no bid response', () => { + describe('interpretResponse', function () { + it('should return an empty array when parsing a no bid response', function () { const response = {}; const request = { bidRequests: [] }; const bids = spec.interpretResponse(response, request); expect(bids).to.have.lengthOf(0); }); - it('should properly parse a bid response with a networkId', () => { + it('should properly parse a bid response with a networkId', function () { const response = { body: { slots: [{ @@ -232,7 +232,7 @@ describe('The Criteo bidding adapter', () => { expect(bids[0].height).to.equal(90); }); - it('should properly parse a bid responsewith with a zoneId', () => { + it('should properly parse a bid responsewith with a zoneId', function () { const response = { body: { slots: [{ @@ -263,7 +263,7 @@ describe('The Criteo bidding adapter', () => { expect(bids[0].height).to.equal(90); }); - it('should properly parse a bid responsewith with a zoneId passed as a string', () => { + it('should properly parse a bid responsewith with a zoneId passed as a string', function () { const response = { body: { slots: [{ diff --git a/test/spec/modules/currency_spec.js b/test/spec/modules/currency_spec.js index a4ef643fece..e96b15d11e9 100644 --- a/test/spec/modules/currency_spec.js +++ b/test/spec/modules/currency_spec.js @@ -21,21 +21,21 @@ describe('currency', function () { let fn = sinon.spy(); let hookFn = createHook('asyncSeries', fn, 'addBidResponse'); - beforeEach(() => { + beforeEach(function () { fakeCurrencyFileServer = sinon.fakeServer.create(); }); - afterEach(() => { + afterEach(function () { fakeCurrencyFileServer.restore(); }); - describe('setConfig', () => { - it('results in currencySupportEnabled = false when currency not configured', () => { + describe('setConfig', function () { + it('results in currencySupportEnabled = false when currency not configured', function () { setConfig({}); expect(currencySupportEnabled).to.equal(false); }); - it('results in currencySupportEnabled = true and currencyRates being loaded when configured', () => { + it('results in currencySupportEnabled = true and currencyRates being loaded when configured', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'JPY' }); fakeCurrencyFileServer.respond(); @@ -44,8 +44,8 @@ describe('currency', function () { }); }); - describe('bidder override', () => { - it('allows setConfig to set bidder currency', () => { + describe('bidder override', function () { + it('allows setConfig to set bidder currency', function () { setConfig({}); var bid = { cpm: 1, bidder: 'rubicon' }; @@ -62,10 +62,12 @@ describe('currency', function () { innerBid = bid; }); - expect(innerBid.currency).to.equal('GBP') + expect(innerBid.currency).to.equal('GBP'); + expect(typeof innerBid.getCpmInNewCurrency).to.equal('function'); + expect(innerBid.getCpmInNewCurrency('GBP')).to.equal('1.000'); }); - it('uses adapter currency over currency override if specified', () => { + it('uses adapter currency over currency override if specified', function () { setConfig({}); var bid = { cpm: 1, currency: 'JPY', bidder: 'rubicon' }; @@ -82,10 +84,12 @@ describe('currency', function () { innerBid = bid; }); - expect(innerBid.currency).to.equal('JPY') + expect(innerBid.currency).to.equal('JPY'); + expect(typeof innerBid.getCpmInNewCurrency).to.equal('function'); + expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('1.000'); }); - it('uses rates specified in json when provided', () => { + it('uses rates specified in json when provided', function () { setConfig({ adServerCurrency: 'USD', rates: { @@ -103,9 +107,11 @@ describe('currency', function () { }); expect(innerBid.cpm).to.equal('1.0000'); + expect(typeof innerBid.getCpmInNewCurrency).to.equal('function'); + expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('100.000'); }); - it('uses default rates when currency file fails to load', () => { + it('uses default rates when currency file fails to load', function () { setConfig({}); setConfig({ @@ -128,11 +134,13 @@ describe('currency', function () { }); expect(innerBid.cpm).to.equal('1.0000'); + expect(typeof innerBid.getCpmInNewCurrency).to.equal('function'); + expect(innerBid.getCpmInNewCurrency('JPY')).to.equal('100.000'); }); }); - describe('currency.addBidResponseDecorator bidResponseQueue', () => { - it('not run until currency rates file is loaded', () => { + describe('currency.addBidResponseDecorator bidResponseQueue', function () { + it('not run until currency rates file is loaded', function () { setConfig({}); fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); @@ -153,8 +161,8 @@ describe('currency', function () { }); }); - describe('currency.addBidResponseDecorator', () => { - it('should leave bid at 1 when currency support is not enabled and fromCurrency is USD', () => { + describe('currency.addBidResponseDecorator', function () { + it('should leave bid at 1 when currency support is not enabled and fromCurrency is USD', function () { setConfig({}); var bid = { 'cpm': 1, 'currency': 'USD' }; var innerBid; @@ -164,7 +172,7 @@ 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', () => { + it('should result in NO_BID when currency support is not enabled and fromCurrency is not USD', function () { setConfig({}); var bid = { 'cpm': 1, 'currency': 'GBP' }; var innerBid; @@ -174,7 +182,7 @@ describe('currency', function () { expect(innerBid.statusMessage).to.equal('Bid returned empty or error response'); }); - it('should not buffer bid when currency is already in desired currency', () => { + it('should not buffer bid when currency is already in desired currency', function () { setConfig({ 'adServerCurrency': 'USD' }); @@ -186,7 +194,7 @@ describe('currency', function () { expect(bid).to.equal(innerBid); }); - it('should result in NO_BID when fromCurrency is not supported in file', () => { + it('should result in NO_BID when fromCurrency is not supported in file', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'JPY' }); fakeCurrencyFileServer.respond(); @@ -198,7 +206,7 @@ describe('currency', function () { expect(innerBid.statusMessage).to.equal('Bid returned empty or error response'); }); - it('should result in NO_BID when adServerCurrency is not supported in file', () => { + it('should result in NO_BID when adServerCurrency is not supported in file', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'ABC' }); fakeCurrencyFileServer.respond(); @@ -210,7 +218,7 @@ describe('currency', function () { expect(innerBid.statusMessage).to.equal('Bid returned empty or error response'); }); - it('should return 1 when currency support is enabled and same currency code is requested as is set to adServerCurrency', () => { + it('should return 1 when currency support is enabled and same currency code is requested as is set to adServerCurrency', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'JPY' }); fakeCurrencyFileServer.respond(); @@ -223,7 +231,7 @@ describe('currency', function () { expect(innerBid.currency).to.equal('JPY'); }); - it('should return direct conversion rate when fromCurrency is one of the configured bases', () => { + it('should return direct conversion rate when fromCurrency is one of the configured bases', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'GBP' }); fakeCurrencyFileServer.respond(); @@ -236,7 +244,7 @@ describe('currency', function () { expect(innerBid.currency).to.equal('GBP'); }); - it('should return reciprocal conversion rate when adServerCurrency is one of the configured bases, but fromCurrency is not', () => { + it('should return reciprocal conversion rate when adServerCurrency is one of the configured bases, but fromCurrency is not', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'GBP' }); fakeCurrencyFileServer.respond(); @@ -249,7 +257,7 @@ describe('currency', function () { expect(innerBid.currency).to.equal('GBP'); }); - it('should return intermediate conversion rate when neither fromCurrency nor adServerCurrency is one of the configured bases', () => { + it('should return intermediate conversion rate when neither fromCurrency nor adServerCurrency is one of the configured bases', function () { fakeCurrencyFileServer.respondWith(JSON.stringify(getCurrencyRates())); setConfig({ 'adServerCurrency': 'CNY' }); fakeCurrencyFileServer.respond(); diff --git a/test/spec/modules/danmarketBidAdapter_spec.js b/test/spec/modules/danmarketBidAdapter_spec.js index 243e2fdfb66..973cd2afb1c 100644 --- a/test/spec/modules/danmarketBidAdapter_spec.js +++ b/test/spec/modules/danmarketBidAdapter_spec.js @@ -5,13 +5,13 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('DAN_Marketplace Adapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'danmarket', 'params': { @@ -24,11 +24,11 @@ describe('DAN_Marketplace Adapter', function () { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -38,7 +38,7 @@ describe('DAN_Marketplace Adapter', function () { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'danmarket', @@ -75,7 +75,7 @@ describe('DAN_Marketplace Adapter', function () { } ]; - it('should attach valid params to the tag', () => { + it('should attach valid params to the tag', function () { const request = spec.buildRequests([bidRequests[0]]); const payload = request.data; expect(payload).to.be.an('object'); @@ -84,7 +84,7 @@ describe('DAN_Marketplace Adapter', function () { expect(payload).to.have.property('auids', '5'); }); - it('auids must not be duplicated', () => { + it('auids must not be duplicated', function () { const request = spec.buildRequests(bidRequests); const payload = request.data; expect(payload).to.be.an('object'); @@ -93,7 +93,7 @@ describe('DAN_Marketplace Adapter', function () { expect(payload).to.have.property('auids', '5,6'); }); - it('pt parameter must be "gross" if params.priceType === "gross"', () => { + it('pt parameter must be "gross" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; const request = spec.buildRequests(bidRequests); const payload = request.data; @@ -104,7 +104,7 @@ describe('DAN_Marketplace Adapter', function () { delete bidRequests[1].params.priceType; }); - it('pt parameter must be "net" or "gross"', () => { + it('pt parameter must be "net" or "gross"', function () { bidRequests[1].params.priceType = 'some'; const request = spec.buildRequests(bidRequests); const payload = request.data; @@ -115,7 +115,7 @@ describe('DAN_Marketplace Adapter', function () { delete bidRequests[1].params.priceType; }); - it('if gdprConsent is present payload must have gdpr params', () => { + it('if gdprConsent is present payload must have gdpr params', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); const payload = request.data; expect(payload).to.be.an('object'); @@ -123,7 +123,7 @@ describe('DAN_Marketplace Adapter', function () { expect(payload).to.have.property('gdpr_applies', 1); }); - it('if gdprApplies is false gdpr_applies must be 0', () => { + it('if gdprApplies is false gdpr_applies must be 0', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: false}}); const payload = request.data; expect(payload).to.be.an('object'); @@ -131,7 +131,7 @@ describe('DAN_Marketplace Adapter', function () { expect(payload).to.have.property('gdpr_applies', 0); }); - it('if gdprApplies is undefined gdpr_applies must be 1', () => { + it('if gdprApplies is undefined gdpr_applies must be 1', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA'}}); const payload = request.data; expect(payload).to.be.an('object'); @@ -140,7 +140,7 @@ describe('DAN_Marketplace Adapter', function () { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const responses = [ {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 4, 'h': 250, 'w': 300}], 'seat': '1'}, {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 5, 'h': 90, 'w': 728}], 'seat': '1'}, @@ -151,7 +151,7 @@ describe('DAN_Marketplace Adapter', function () { {'seat': '1'}, ]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const bidRequests = [ { 'bidder': 'danmarket', @@ -185,7 +185,7 @@ describe('DAN_Marketplace Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should get correct multi bid response', () => { + it('should get correct multi bid response', function () { const bidRequests = [ { 'bidder': 'danmarket', @@ -265,7 +265,7 @@ describe('DAN_Marketplace Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('handles wrong and nobid responses', () => { + it('handles wrong and nobid responses', function () { const bidRequests = [ { 'bidder': 'danmarket', diff --git a/test/spec/modules/dfpAdServerVideo_spec.js b/test/spec/modules/dfpAdServerVideo_spec.js index c4a799b0b0a..8afc597d3b4 100644 --- a/test/spec/modules/dfpAdServerVideo_spec.js +++ b/test/spec/modules/dfpAdServerVideo_spec.js @@ -4,14 +4,17 @@ import parse from 'url-parse'; import buildDfpVideoUrl from 'modules/dfpAdServerVideo'; import { parseQS } from 'src/url'; import adUnit from 'test/fixtures/video/adUnit'; +import * as utils from 'src/utils'; +import { config } from 'src/config'; +import { targeting } from 'src/targeting'; const bid = { videoCacheKey: 'abc', adserverTargeting: { }, }; -describe('The DFP video support module', () => { - it('should make a legal request URL when given the required params', () => { +describe('The DFP video support module', function () { + it('should make a legal request URL when given the required params', function () { const url = parse(buildDfpVideoUrl({ adUnit: adUnit, bid: bid, @@ -36,7 +39,7 @@ describe('The DFP video support module', () => { expect(queryParams).to.have.property('url'); }); - it('can take an adserver url as a parameter', () => { + it('can take an adserver url as a parameter', function () { const bidCopy = Object.assign({ }, bid); bidCopy.vastUrl = 'vastUrl.example'; @@ -52,7 +55,7 @@ describe('The DFP video support module', () => { expect(queryObject.description_url).to.equal('vastUrl.example'); }); - it('requires a params object or url', () => { + it('requires a params object or url', function () { const url = buildDfpVideoUrl({ adUnit: adUnit, bid: bid, @@ -61,7 +64,7 @@ describe('The DFP video support module', () => { expect(url).to.be.undefined; }); - it('overwrites url params when both url and params object are given', () => { + it('overwrites url params when both url and params object are given', function () { const url = parse(buildDfpVideoUrl({ adUnit: adUnit, bid: bid, @@ -73,7 +76,7 @@ describe('The DFP video support module', () => { expect(queryObject.iu).to.equal('my/adUnit'); }); - it('should override param defaults with user-provided ones', () => { + it('should override param defaults with user-provided ones', function () { const url = parse(buildDfpVideoUrl({ adUnit: adUnit, bid: bid, @@ -86,7 +89,7 @@ describe('The DFP video support module', () => { expect(parseQS(url.query)).to.have.property('output', 'vast'); }); - it('should include the cache key and adserver targeting in cust_params', () => { + it('should include the cache key and adserver targeting in cust_params', function () { const bidCopy = Object.assign({ }, bid); bidCopy.adserverTargeting = { hb_adid: 'ad_id', @@ -107,7 +110,80 @@ describe('The DFP video support module', () => { expect(customParams).to.have.property('hb_cache_id', bid.videoCacheKey); }); - it('should merge the user-provided cust_params with the default ones', () => { + describe('special targeting unit test', function () { + const allTargetingData = { + 'hb_format': 'video', + 'hb_source': 'client', + 'hb_size': '640x480', + 'hb_pb': '5.00', + 'hb_adid': '2c4f6cc3ba128a', + 'hb_bidder': 'testBidder2', + 'hb_format_testBidder2': 'video', + 'hb_source_testBidder2': 'client', + 'hb_size_testBidder2': '640x480', + 'hb_pb_testBidder2': '5.00', + 'hb_adid_testBidder2': '2c4f6cc3ba128a', + 'hb_bidder_testBidder2': 'testBidder2', + 'hb_format_appnexus': 'video', + 'hb_source_appnexus': 'client', + 'hb_size_appnexus': '640x480', + 'hb_pb_appnexus': '5.00', + 'hb_adid_appnexus': '44e0b5f2e5cace', + 'hb_bidder_appnexus': 'appnexus' + }; + let targetingStub; + + before(function () { + targetingStub = sinon.stub(targeting, 'getAllTargeting'); + targetingStub.returns({'video1': allTargetingData}); + + config.setConfig({ + enableSendAllBids: true + }); + }); + + after(function () { + config.resetConfig(); + targetingStub.restore(); + }); + + it('should include all adserver targeting in cust_params if pbjs.enableSendAllBids is true', function () { + const adUnitsCopy = utils.deepClone(adUnit); + adUnitsCopy.bids.push({ + 'bidder': 'testBidder2', + 'params': { + 'placementId': '9333431', + 'video': { + 'skipppable': false, + 'playback_methods': ['auto_play_sound_off'] + } + } + }); + + const bidCopy = Object.assign({ }, bid); + bidCopy.adserverTargeting = { + hb_adid: 'ad_id', + }; + + const url = parse(buildDfpVideoUrl({ + adUnit: adUnitsCopy, + bid: bidCopy, + params: { + 'iu': 'my/adUnit' + } + })); + const queryObject = parseQS(url.query); + const customParams = parseQS('?' + decodeURIComponent(queryObject.cust_params)); + + expect(customParams).to.have.property('hb_adid', 'ad_id'); + expect(customParams).to.have.property('hb_uuid', bid.videoCacheKey); + expect(customParams).to.have.property('hb_cache_id', bid.videoCacheKey); + expect(customParams).to.have.property('hb_bidder_appnexus', 'appnexus'); + expect(customParams).to.have.property('hb_bidder_testBidder2', 'testBidder2'); + }); + }); + + it('should merge the user-provided cust_params with the default ones', function () { const bidCopy = Object.assign({ }, bid); bidCopy.adserverTargeting = { hb_adid: 'ad_id', @@ -130,7 +206,7 @@ describe('The DFP video support module', () => { expect(customParams).to.have.property('my_targeting', 'foo'); }); - it('should merge the user-provided cust-params with the default ones when using url object', () => { + it('should merge the user-provided cust-params with the default ones when using url object', function () { const bidCopy = Object.assign({ }, bid); bidCopy.adserverTargeting = { hb_adid: 'ad_id', @@ -152,7 +228,7 @@ describe('The DFP video support module', () => { expect(customParams).to.have.property('hb_cache_id', 'abc'); }); - it('should not overwrite an existing description_url for object input and cache disabled', () => { + it('should not overwrite an existing description_url for object input and cache disabled', function () { const bidCopy = Object.assign({}, bid); bidCopy.vastUrl = 'vastUrl.example'; @@ -169,7 +245,7 @@ describe('The DFP video support module', () => { expect(queryObject.description_url).to.equal('descriptionurl.example'); }); - it('should work with nobid responses', () => { + it('should work with nobid responses', function () { const url = buildDfpVideoUrl({ adUnit: adUnit, params: { 'iu': 'my/adUnit' } diff --git a/test/spec/modules/dgadsBidAdapter_spec.js b/test/spec/modules/dgadsBidAdapter_spec.js index 89affd94880..2454885217d 100644 --- a/test/spec/modules/dgadsBidAdapter_spec.js +++ b/test/spec/modules/dgadsBidAdapter_spec.js @@ -1,20 +1,21 @@ import {expect} from 'chai'; import * as utils from 'src/utils'; -import {spec} from 'modules/dgadsBidAdapter'; +import {spec, getCookieUid} from 'modules/dgadsBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; import { BANNER, NATIVE } from 'src/mediaTypes'; -describe('dgadsBidAdapter', () => { +describe('dgadsBidAdapter', function () { const adapter = newBidder(spec); + const UID_NAME = 'dgads_uid'; const VALID_ENDPOINT = 'https://ads-tr.bigmining.com/ad/p/bid'; - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'dgads', params: { @@ -22,11 +23,11 @@ describe('dgadsBidAdapter', () => { location_id: '1' } }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params(location_id) are not passed', () => { + it('should return false when required params(location_id) are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -35,7 +36,7 @@ describe('dgadsBidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when required params(site_id) are not passed', () => { + it('should return false when required params(site_id) are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -45,7 +46,7 @@ describe('dgadsBidAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const bidRequests = [ { // banner bidder: 'dgads', @@ -97,31 +98,38 @@ describe('dgadsBidAdapter', () => { transactionId: 'c1f1eff6-23c6-4844-a321-575212939e37' } ]; - it('no bidRequests', () => { + it('no bidRequests', function () { const noBidRequests = []; expect(Object.keys(spec.buildRequests(noBidRequests)).length).to.equal(0); }); + it('getCookieUid return empty if cookie not found', function () { + expect(getCookieUid(UID_NAME)).to.equal(''); + }); const data = { location_id: '1', site_id: '1', transaction_id: 'c1f1eff6-23c6-4844-a321-575212939e37', - bid_id: '2db3101abaec66' + bid_id: '2db3101abaec66', + referer: utils.getTopWindowUrl(), + _uid: '' }; - it('sends bid request to VALID_ENDPOINT via POST', () => { + it('sends bid request to VALID_ENDPOINT via GET', function () { const request = spec.buildRequests(bidRequests)[0]; expect(request.url).to.equal(VALID_ENDPOINT); - expect(request.method).to.equal('POST'); + expect(request.method).to.equal('GET'); }); - it('should attache params to the request', () => { + it('should attache params to the request', function () { const request = spec.buildRequests(bidRequests)[0]; - expect(request.data['location_id']).to.equal(data['location_id']); - expect(request.data['site_id']).to.equal(data['site_id']); + expect(request.data['_loc']).to.equal(data['location_id']); + expect(request.data['_medium']).to.equal(data['site_id']); expect(request.data['transaction_id']).to.equal(data['transaction_id']); expect(request.data['bid_id']).to.equal(data['bid_id']); + expect(request.data['referer']).to.equal(data['referer']); + expect(request.data['_uid']).to.equal(data['_uid']); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const bidRequests = { banner: { bidRequest: { @@ -252,11 +260,11 @@ describe('dgadsBidAdapter', () => { } }; - it('no bid responses', () => { + it('no bid responses', function () { const result = spec.interpretResponse({body: serverResponse.noAd}, bidRequests.banner); expect(result.length).to.equal(0); }); - it('handles banner responses', () => { + it('handles banner responses', function () { const result = spec.interpretResponse({body: serverResponse.banner}, bidRequests.banner)[0]; expect(result.requestId).to.equal(bidResponses.banner.requestId); expect(result.width).to.equal(bidResponses.banner.width); @@ -269,7 +277,7 @@ describe('dgadsBidAdapter', () => { expect(result.ad).to.equal(bidResponses.banner.ad); }); - it('handles native responses', () => { + it('handles native responses', function () { const result = spec.interpretResponse({body: serverResponse.native}, bidRequests.native)[0]; expect(result.requestId).to.equal(bidResponses.native.requestId); expect(result.creativeId).to.equal(bidResponses.native.creativeId); diff --git a/test/spec/modules/districtmDmxBidAdapter_spec.js b/test/spec/modules/districtmDmxBidAdapter_spec.js new file mode 100644 index 00000000000..64f76eb026d --- /dev/null +++ b/test/spec/modules/districtmDmxBidAdapter_spec.js @@ -0,0 +1,533 @@ +import {expect} from 'chai'; +import * as _ from 'lodash'; +import {spec, matchRequest, checkDeepArray, defaultSize} from '../../../modules/districtmDMXBidAdapter'; + +const bidRequest = [{ + 'bidder': 'districtmDMX', + 'params': { + 'dmxid': 100001, + 'memberid': 100003 + }, + 'adUnitCode': 'div-gpt-ad-12345678-1', + 'transactionId': 'f6d13fa6-ebc1-41ac-9afa-d8171d22d2c2', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '29a28a1bbc8a8d', + 'bidderRequestId': '124b579a136515', + 'auctionId': '3d62f2d3-56a2-4991-888e-f7754619ddcf' +}]; + +const bidderRequest = { + 'bidderCode': 'districtmDMX', + 'auctionId': '3d62f2d3-56a2-4991-888e-f7754619ddcf', + 'bidderRequestId': '124b579a136515', + 'bids': [{ + 'bidder': 'districtmDMX', + 'params': { + 'dmxid': 100001, + 'memberid': 100003 + }, + 'adUnitCode': 'div-gpt-ad-12345678-1', + 'transactionId': 'f6d13fa6-ebc1-41ac-9afa-d8171d22d2c2', + 'sizes': [ + [300, 250], + [300, 600] + ], + 'bidId': '29a28a1bbc8a8d', + 'bidderRequestId': '124b579a136515', + 'auctionId': '3d62f2d3-56a2-4991-888e-f7754619ddcf' + }], + 'auctionStart': 1529511035677, + 'timeout': 700, + 'gdprConsent': { + 'consentString': 'BOPqNzUOPqNzUAHABBAAA5AAAAAAAA', + 'vendorData': { + 'metadata': 'BOPqNzUOPqNzUAHABBAAA5AAAAAAAA', + 'hasGlobalScope': false, + 'gdprApplies': true, + 'purposeConsents': { + '1': false, + '2': false, + '3': false, + '4': false, + '5': false + }, + 'vendorConsents': { + '1': false, + '2': false, + '3': false, + '4': false, + '6': false, + '7': false, + '8': false, + '9': false, + '10': false, + '11': false, + '12': false, + '13': false, + '14': false, + '15': false, + '16': false, + '17': false, + '18': false, + '19': false, + '20': false, + '21': false, + '22': false, + '23': false, + '24': false, + '25': false, + '26': false, + '27': false, + '28': false, + '29': false, + '30': false, + '31': false, + '32': false, + '33': false, + '34': false, + '35': false, + '36': false, + '37': false, + '38': false, + '39': false, + '40': false, + '41': false, + '42': false, + '43': false, + '44': false, + '45': false, + '46': false, + '47': false, + '48': false, + '49': false, + '50': false, + '51': false, + '52': false, + '53': false, + '55': false, + '56': false, + '57': false, + '58': false, + '59': false, + '60': false, + '61': false, + '62': false, + '63': false, + '64': false, + '65': false, + '66': false, + '67': false, + '68': false, + '69': false, + '70': false, + '71': false, + '72': false, + '73': false, + '74': false, + '75': false, + '76': false, + '77': false, + '78': false, + '79': false, + '80': false, + '81': false, + '82': false, + '83': false, + '84': false, + '85': false, + '86': false, + '87': false, + '88': false, + '89': false, + '90': false, + '91': false, + '92': false, + '93': false, + '94': false, + '95': false, + '97': false, + '98': false, + '100': false, + '101': false, + '102': false, + '104': false, + '105': false, + '108': false, + '109': false, + '110': false, + '111': false, + '112': false, + '113': false, + '114': false, + '115': false, + '119': false, + '120': false, + '122': false, + '124': false, + '125': false, + '126': false, + '127': false, + '128': false, + '129': false, + '130': false, + '131': false, + '132': false, + '133': false, + '134': false, + '136': false, + '138': false, + '139': false, + '140': false, + '141': false, + '142': false, + '143': false, + '144': false, + '145': false, + '147': false, + '148': false, + '149': false, + '150': false, + '151': false, + '152': false, + '153': false, + '154': false, + '155': false, + '156': false, + '157': false, + '158': false, + '159': false, + '160': false, + '161': false, + '162': false, + '163': false, + '164': false, + '165': false, + '167': false, + '168': false, + '169': false, + '170': false, + '171': false, + '173': false, + '174': false, + '175': false, + '177': false, + '178': false, + '179': false, + '180': false, + '182': false, + '183': false, + '184': false, + '185': false, + '188': false, + '189': false, + '190': false, + '191': false, + '192': false, + '193': false, + '194': false, + '195': false, + '197': false, + '198': false, + '199': false, + '200': false, + '201': false, + '202': false, + '203': false, + '205': false, + '206': false, + '208': false, + '209': false, + '210': false, + '211': false, + '212': false, + '213': false, + '214': false, + '215': false, + '216': false, + '217': false, + '218': false, + '223': false, + '224': false, + '225': false, + '226': false, + '227': false, + '228': false, + '229': false, + '230': false, + '231': false, + '232': false, + '234': false, + '235': false, + '236': false, + '237': false, + '238': false, + '239': false, + '240': false, + '241': false, + '242': false, + '244': false, + '245': false, + '246': false, + '248': false, + '249': false, + '250': false, + '251': false, + '252': false, + '253': false, + '254': false, + '255': false, + '256': false, + '257': false, + '258': false, + '259': false, + '260': false, + '261': false, + '262': false, + '263': false, + '264': false, + '265': false, + '266': false, + '269': false, + '270': false, + '272': false, + '273': false, + '274': false, + '275': false, + '276': false, + '277': false, + '278': false, + '279': false, + '280': false, + '281': false, + '282': false, + '284': false, + '285': false, + '288': false, + '289': false, + '290': false, + '291': false, + '294': false, + '295': false, + '297': false, + '299': false, + '301': false, + '302': false, + '303': false, + '304': false, + '308': false, + '309': false, + '310': false, + '311': false, + '312': false, + '314': false, + '315': false, + '316': false, + '317': false, + '318': false, + '319': false, + '320': false, + '323': false, + '325': false, + '326': false, + '328': false, + '329': false, + '330': false, + '331': false, + '333': false, + '337': false, + '339': false, + '341': false, + '343': false, + '344': false, + '345': false, + '347': false, + '349': false, + '350': false, + '351': false, + '354': false, + '358': false, + '359': false, + '360': false, + '361': false, + '368': false, + '369': false, + '371': false, + '373': false, + '376': false, + '377': false, + '378': false, + '380': false, + '382': false, + '384': false, + '385': false, + '387': false, + '388': false, + '389': false, + '390': false, + '391': false, + '398': false, + '400': false, + '402': false, + '403': false, + '404': false, + '413': false, + '415': false, + '421': false, + '422': false + } + }, + 'gdprApplies': true + }, + 'start': 1529511035686, + 'doneCbCallCount': 0 +}; + +const responses = { + 'body': { + 'id': '1f45b37c-5298-4934-b517-4d911aadabfd', + 'cur': 'USD', + 'seatbid': [{ + 'bid': [{ + 'id': '29a28a1bbc8a8d', + 'impid': '29a28a1bbc8a8d', + 'price': '6.42', + 'adm': '
' + }] + }] + }, + 'headers': {} +}; + +const responsesNegative = { + 'body': { + 'id': '1f45b37c-5298-4934-b517-4d911aadabfd', + 'cur': 'USD', + 'seatbid': [{ + 'bid': [{ + 'id': '29a28a1bbc8a8d', + 'impid': '29a28a1bbc8a8d', + 'price': '-0.10', + 'adm': '
' + }] + }] + }, + 'headers': {} +}; + +const emptyResponse = { body: {} }; +const emptyResponseSeatBid = { body: { seatbid: [] } }; + +describe('DistrictM Adaptor', function () { + const districtm = spec; + describe('All needed functions are available', function () { + it(`isBidRequestValid is present and type function`, function () { + expect(districtm.isBidRequestValid).to.exist.and.to.be.a('function') + }); + + it(`BuildRequests is present and type function`, function () { + expect(districtm.buildRequests).to.exist.and.to.be.a('function') + }); + + it(`interpretResponse is present and type function`, function () { + expect(districtm.interpretResponse).to.exist.and.to.be.a('function') + }); + + it(`getUserSyncs is present and type function`, function () { + expect(districtm.getUserSyncs).to.exist.and.to.be.a('function') + }); + }); + + describe(`these properties are available or not`, function () { + it(`code should have a value of districtmDMX`, function () { + expect(districtm.code).to.be.equal('districtmDMX'); + }); + + it(`timeout should not be defined`, function () { + expect(districtm.onTimeout).to.be.an('undefined'); + }); + }); + + describe(`isBidRequestValid test response`, function () { + let params = { + dmxid: 10001, + memberid: 10003, + }; + it(`function should return true`, function () { + expect(districtm.isBidRequestValid({params})).to.be.equal(true); + }); + it(`function should return false`, function () { + expect(districtm.isBidRequestValid({ params: { memberid: 12345 } })).to.be.equal(false); + }); + it(`expect to have two property available dmxid and memberid`, function () { + expect(params).to.have.property('dmxid'); + expect(params).to.have.property('memberid'); + }); + }); + + describe(`getUserSyncs test usage`, function () { + it(`return value should be an array`, function () { + expect(districtm.getUserSyncs({ iframeEnabled: true })).to.be.an('array'); + }); + it(`array should have only one object and it should have a property type = 'iframe'`, function () { + expect(districtm.getUserSyncs({ iframeEnabled: true }).length).to.be.equal(1); + let [userSync] = districtm.getUserSyncs({ iframeEnabled: true }); + expect(userSync).to.have.property('type'); + expect(userSync.type).to.be.equal('iframe'); + }); + }); + + describe(`buildRequests test usage`, function () { + const buildRequestResults = districtm.buildRequests(bidRequest, bidderRequest); + it(`the function should return an array`, function () { + expect(buildRequestResults).to.be.an('object'); + }); + it(`the function should return array length of 1`, function () { + expect(buildRequestResults.data).to.be.a('string'); + }); + }); + + describe(`interpretResponse test usage`, function () { + const responseResults = districtm.interpretResponse(responses, {bidderRequest}); + const emptyResponseResults = districtm.interpretResponse(emptyResponse, {bidderRequest}); + const emptyResponseResultsNegation = districtm.interpretResponse(responsesNegative, {bidderRequest}); + const emptyResponseResultsEmptySeat = districtm.interpretResponse(emptyResponseSeatBid, {bidderRequest}); + it(`the function should return an array`, function () { + expect(responseResults).to.be.an('array'); + }); + it(`the function should return array length of 1`, function () { + expect(responseResults.length).to.be.equal(1); + }); + it(`the response return nothing`, function () { + expect(emptyResponseResults.length).to.be.equal(0); + }); + it(`the response seatbid return nothing`, function () { + expect(emptyResponseResultsEmptySeat.length).to.be.equal(0); + }); + + it(`on invalid CPM`, function () { + expect(emptyResponseResultsNegation.length).to.be.equal(0); + }); + }); + + describe(`Helper function testing`, function () { + const bid = matchRequest('29a28a1bbc8a8d', {bidderRequest}); + const {width, height} = defaultSize(bid); + it(`test matchRequest`, function () { + expect(matchRequest('29a28a1bbc8a8d', {bidderRequest})).to.be.an('object'); + }); + it(`test checkDeepArray`, function () { + expect(_.isEqual(checkDeepArray([728, 90]), [728, 90])).to.be.equal(true); + expect(_.isEqual(checkDeepArray([[728, 90]]), [728, 90])).to.be.equal(true); + expect(_.isEqual(checkDeepArray([[728, 90], [300, 250]]), [728, 90])).to.be.equal(true); + expect(_.isEqual(checkDeepArray([[300, 250], [300, 250]]), [728, 90])).to.be.equal(false); + expect(_.isEqual(checkDeepArray([300, 250]), [300, 250])).to.be.equal(true); + }); + it(`test defaultSize`, function () { + expect(width).to.be.equal(300); + expect(height).to.be.equal(250); + }); + }); +}); diff --git a/test/spec/modules/divreachBidAdapter_spec.js b/test/spec/modules/divreachBidAdapter_spec.js new file mode 100644 index 00000000000..f874a206a87 --- /dev/null +++ b/test/spec/modules/divreachBidAdapter_spec.js @@ -0,0 +1,117 @@ +import {expect} from 'chai'; +import {spec} from 'modules/divreachBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'divreach'; +const ENDPOINT_URL = '//ads.divreach.com/prebid.1.0.aspx'; +const ZONE_ID = '2eb6bd58-865c-47ce-af7f-a918108c3fd2'; + +describe('DivReachAdapter', function () { + const adapter = newBidder(spec); + + describe('inherited functions', function () { + it('exists and is a function', function () { + expect(adapter.callBids).to.be.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', function () { + let bid = { + 'bidder': BIDDER_CODE, + 'params': { + 'zone': ZONE_ID + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [ + { + 'bidder': BIDDER_CODE, + 'params': { + 'zone': ZONE_ID + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should add referrer and imp to be equal bidRequest', function () { + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data.substr(5)); + expect(payload.referrer).to.not.be.undefined; + expect(payload.imps[0]).to.deep.equal(bidRequests[0]); + }); + + it('sends bid request to ENDPOINT via GET', function () { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal(ENDPOINT_URL); + expect(request.method).to.equal('GET'); + }); + }); + + describe('interpretResponse', function () { + let response = { + body: [{ + 'currency': 'USD', + 'cpm': 6.210000, + 'ad': '
ad
', + 'width': 300, + 'height': 600, + 'creativeId': 'ccca3e5e-0c54-4761-9667-771322fbdffc', + 'ttl': 360, + 'netRevenue': false, + 'bidId': '5e4e763b6bc60b' + }] + }; + + it('should get correct bid response', function () { + const body = response.body; + let expectedResponse = [ + { + 'requestId': body[0].bidId, + 'cpm': body[0].cpm, + 'creativeId': body[0].creativeId, + 'width': body[0].width, + 'height': body[0].height, + 'ad': body[0].ad, + 'vastUrl': undefined, + 'currency': body[0].currency, + 'netRevenue': body[0].netRevenue, + 'ttl': body[0].ttl, + } + ]; + + let result = spec.interpretResponse(response); + expect(result[0]).to.deep.equal(expectedResponse[0]); + }); + + it('handles nobid responses', function () { + let response = []; + + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); +}); diff --git a/test/spec/modules/ebdrBidAdapter_spec.js b/test/spec/modules/ebdrBidAdapter_spec.js index 3ec5a4f0a81..d742e28f2e6 100644 --- a/test/spec/modules/ebdrBidAdapter_spec.js +++ b/test/spec/modules/ebdrBidAdapter_spec.js @@ -3,10 +3,10 @@ import { spec } from 'modules/ebdrBidAdapter'; import { VIDEO, BANNER } from 'src/mediaTypes'; import * as utils from 'src/utils'; -describe('ebdrBidAdapter', () => { +describe('ebdrBidAdapter', function () { let bidRequests; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { code: 'div-gpt-ad-1460505748561-0', @@ -51,13 +51,13 @@ describe('ebdrBidAdapter', () => { ]; }); - describe('spec.isBidRequestValid', () => { - it('should return true when the required params are passed', () => { + describe('spec.isBidRequestValid', function () { + it('should return true when the required params are passed', function () { const bidRequest = bidRequests[0]; expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return true when the only required param is missing', () => { + it('should return true when the only required param is missing', function () { const bidRequest = bidRequests[0]; bidRequest.params = { zoneid: '99998', @@ -66,7 +66,7 @@ describe('ebdrBidAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return true when the "bidfloor" param is missing', () => { + it('should return true when the "bidfloor" param is missing', function () { const bidRequest = bidRequests[0]; bidRequest.params = { zoneid: '99998', @@ -74,34 +74,34 @@ describe('ebdrBidAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return false when no bid params are passed', () => { + it('should return false when no bid params are passed', function () { const bidRequest = bidRequests[0]; bidRequest.params = {}; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when a bid request is not passed', () => { + it('should return false when a bid request is not passed', function () { expect(spec.isBidRequestValid()).to.equal(false); expect(spec.isBidRequestValid({})).to.equal(false); }); }); - describe('spec.buildRequests', () => { - describe('for banner bids', () => { - it('must handle an empty bid size', () => { + describe('spec.buildRequests', function () { + describe('for banner bids', function () { + it('must handle an empty bid size', function () { bidRequests[0].mediaTypes = { banner: {} }; const requests = spec.buildRequests(bidRequests); const bidRequest = {}; bidRequest['2c5e8a1a84522d'] = { mediaTypes: BANNER, w: null, h: null }; expect(requests.bids['2c5e8a1a84522d']).to.deep.equals(bidRequest['2c5e8a1a84522d']); }); - it('should create a single GET', () => { + it('should create a single GET', function () { bidRequests[0].mediaTypes = { banner: {} }; bidRequests[1].mediaTypes = { banner: {} }; const requests = spec.buildRequests(bidRequests); expect(requests.method).to.equal('GET'); }); - it('must parse bid size from a nested array', () => { + it('must parse bid size from a nested array', function () { const width = 640; const height = 480; const bidRequest = bidRequests[0]; @@ -112,8 +112,8 @@ describe('ebdrBidAdapter', () => { expect(requests.bids['2c5e8a1a84522d']).to.deep.equal(data['2c5e8a1a84522d']); }); }); - describe('for video bids', () => { - it('must handle an empty bid size', () => { + describe('for video bids', function () { + it('must handle an empty bid size', function () { bidRequests[1].mediaTypes = { video: {} }; const requests = spec.buildRequests(bidRequests); const bidRequest = {}; @@ -121,7 +121,7 @@ describe('ebdrBidAdapter', () => { expect(requests.bids['23a01e95856577']).to.deep.equals(bidRequest['23a01e95856577']); }); - it('should create a GET request for each bid', () => { + it('should create a GET request for each bid', function () { const bidRequest = bidRequests[1]; const requests = spec.buildRequests([ bidRequest ]); expect(requests.method).to.equal('GET'); @@ -129,16 +129,16 @@ describe('ebdrBidAdapter', () => { }); }); - describe('spec.interpretResponse', () => { - describe('for video bids', () => { - it('should return no bids if the response is not valid', () => { + describe('spec.interpretResponse', function () { + describe('for video bids', function () { + it('should return no bids if the response is not valid', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { video: {} }; const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return a valid video bid response', () => { + it('should return a valid video bid response', function () { const ebdrReq = {bids: {}}; bidRequests.forEach(bid => { let _mediaTypes = (bid.mediaTypes && bid.mediaTypes.video ? VIDEO : BANNER); @@ -165,22 +165,22 @@ describe('ebdrBidAdapter', () => { }); }); - describe('for banner bids', () => { - it('should return no bids if the response is not valid', () => { + describe('for banner bids', function () { + it('should return no bids if the response is not valid', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: {} }; const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response is empty', () => { + it('should return no bids if the response is empty', function () { const bidRequest = bidRequests[0]; bidRequest.mediaTypes = { banner: {} }; const bidResponse = spec.interpretResponse({ body: [] }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return valid banner bid responses', () => { + it('should return valid banner bid responses', function () { const ebdrReq = {bids: {}}; bidRequests.forEach(bid => { let _mediaTypes = (bid.mediaTypes && bid.mediaTypes.video ? VIDEO : BANNER); @@ -206,27 +206,27 @@ describe('ebdrBidAdapter', () => { }); }); }); - describe('spec.getUserSyncs', () => { + describe('spec.getUserSyncs', function () { let syncOptions - beforeEach(() => { + beforeEach(function () { syncOptions = { enabledBidders: ['ebdr'], // only these bidders are allowed to sync pixelEnabled: true } }); - it('sucess with usersync url', () => { + it('sucess with usersync url', function () { const serverResponse = {id: '1d0c4017f02458', seatbid: [{bid: [{id: '2c5e8a1a84522d', impid: '2c5e8a1a84522d', price: 0.81, adid: 'abcde-12345', nurl: '', adm: '
', adomain: ['advertiserdomain.com'], iurl: '//match.bnmla.com/usersync?sspid=59&redir=', cid: 'campaign1', crid: 'abcde-12345', w: 300, h: 250}], seat: '19513bcfca8006'}], bidid: '19513bcfca8006', cur: 'USD', w: 300, h: 250}; const result = []; result.push({type: 'image', url: '//match.bnmla.com/usersync?sspid=59&redir='}); expect(spec.getUserSyncs(syncOptions, { body: serverResponse })).to.deep.equal(result); }); - it('sucess without usersync url', () => { + it('sucess without usersync url', function () { const serverResponse = {id: '1d0c4017f02458', seatbid: [{bid: [{id: '2c5e8a1a84522d', impid: '2c5e8a1a84522d', price: 0.81, adid: 'abcde-12345', nurl: '', adm: '
', adomain: ['advertiserdomain.com'], iurl: '', cid: 'campaign1', crid: 'abcde-12345', w: 300, h: 250}], seat: '19513bcfca8006'}], bidid: '19513bcfca8006', cur: 'USD', w: 300, h: 250}; const result = []; expect(spec.getUserSyncs(syncOptions, { body: serverResponse })).to.deep.equal(result); }); - it('empty response', () => { + it('empty response', function () { const serverResponse = {}; const result = []; expect(spec.getUserSyncs(syncOptions, { body: serverResponse })).to.deep.equal(result); diff --git a/test/spec/modules/eplanningAnalyticsAdapter_spec.js b/test/spec/modules/eplanningAnalyticsAdapter_spec.js index cd538815954..2b10f10adf2 100644 --- a/test/spec/modules/eplanningAnalyticsAdapter_spec.js +++ b/test/spec/modules/eplanningAnalyticsAdapter_spec.js @@ -6,25 +6,25 @@ let adaptermanager = require('src/adaptermanager'); let events = require('src/events'); let constants = require('src/constants.json'); -describe('eplanning analytics adapter', () => { +describe('eplanning analytics adapter', function () { let xhr; let requests; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = request => { requests.push(request) }; sinon.stub(events, 'getEvents').returns([]); }); - afterEach(() => { + afterEach(function () { xhr.restore(); events.getEvents.restore(); eplAnalyticsAdapter.disableAnalytics(); }); - describe('track', () => { - it('builds and sends auction data', () => { + describe('track', function () { + it('builds and sends auction data', function () { sinon.spy(eplAnalyticsAdapter, 'track'); let auctionTimestamp = 1496510254313; diff --git a/test/spec/modules/eplanningBidAdapter_spec.js b/test/spec/modules/eplanningBidAdapter_spec.js index 68b9e1b263f..80129a03bd2 100644 --- a/test/spec/modules/eplanningBidAdapter_spec.js +++ b/test/spec/modules/eplanningBidAdapter_spec.js @@ -3,7 +3,7 @@ import { spec } from 'modules/eplanningBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; import * as utils from 'src/utils'; -describe('E-Planning Adapter', () => { +describe('E-Planning Adapter', function () { const adapter = newBidder('spec'); const CI = '12345'; const ADUNIT_CODE = 'adunit-code'; @@ -167,55 +167,55 @@ describe('E-Planning Adapter', () => { } }; - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - it('should return true when bid has ci parameter', () => { + describe('isBidRequestValid', function () { + it('should return true when bid has ci parameter', function () { expect(spec.isBidRequestValid(validBid)).to.equal(true); }); - it('should return false when bid does not have ci parameter and is not a test bid', () => { + it('should return false when bid does not have ci parameter and is not a test bid', function () { expect(spec.isBidRequestValid(invalidBid)).to.equal(false); }); - it('should return true when bid does not have ci parameter but is a test bid', () => { + it('should return true when bid does not have ci parameter but is a test bid', function () { expect(spec.isBidRequestValid(testBid)).to.equal(true); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [validBid]; - it('should create the url correctly', () => { + it('should create the url correctly', function () { const url = spec.buildRequests(bidRequests).url; expect(url).to.equal('//ads.us.e-planning.net/hb/1/' + CI + '/1/localhost/ROS'); }); - it('should return GET method', () => { + it('should return GET method', function () { const method = spec.buildRequests(bidRequests).method; expect(method).to.equal('GET'); }); - it('should return r parameter with value pbjs', () => { + it('should return r parameter with value pbjs', function () { const r = spec.buildRequests(bidRequests).data.r; expect(r).to.equal('pbjs'); }); - it('should return pbv parameter with value prebid version', () => { + it('should return pbv parameter with value prebid version', function () { const pbv = spec.buildRequests(bidRequests).data.pbv; expect(pbv).to.equal('$prebid.version$'); }); - it('should return e parameter with value according to the adunit sizes', () => { + it('should return e parameter with value according to the adunit sizes', function () { const e = spec.buildRequests(bidRequests).data.e; expect(e).to.equal(CLEAN_ADUNIT_CODE + ':300x250,300x600'); }); - it('should return correct e parameter with more than one adunit', () => { + it('should return correct e parameter with more than one adunit', function () { const NEW_CODE = ADUNIT_CODE + '2'; const CLEAN_NEW_CODE = CLEAN_ADUNIT_CODE + '2'; const anotherBid = { @@ -232,7 +232,7 @@ describe('E-Planning Adapter', () => { expect(e).to.equal(CLEAN_ADUNIT_CODE + ':300x250,300x600+' + CLEAN_NEW_CODE + ':100x100'); }); - it('should return correct e parameter when the adunit has no size', () => { + it('should return correct e parameter when the adunit has no size', function () { const noSizeBid = { 'bidder': 'eplanning', 'params': { @@ -245,12 +245,12 @@ describe('E-Planning Adapter', () => { expect(e).to.equal(CLEAN_ADUNIT_CODE + ':1x1'); }); - it('should return ur parameter with current window url', () => { + it('should return ur parameter with current window url', function () { const ur = spec.buildRequests(bidRequests).data.ur; expect(ur).to.equal(utils.getTopWindowUrl()); }); - it('should return fr parameter when there is a referrer', () => { + it('should return fr parameter when there is a referrer', function () { const referrer = 'thisisafakereferrer'; const stubGetReferrer = sinon.stub(utils, 'getTopWindowReferrer'); stubGetReferrer.returns(referrer); @@ -259,30 +259,43 @@ describe('E-Planning Adapter', () => { stubGetReferrer.restore() }); - it('should return the testing url when the request has the t parameter', () => { + it('should return crs parameter with document charset', function () { + let expected; + try { + expected = window.top.document.characterSet; + } catch (e) { + expected = document.characterSet; + } + + const chset = spec.buildRequests(bidRequests).data.crs; + + expect(chset).to.equal(expected); + }); + + it('should return the testing url when the request has the t parameter', function () { const url = spec.buildRequests([testBid]).url; const expectedUrl = '//' + TEST_ISV + '/layers/t_pbjs_2.json'; expect(url).to.equal(expectedUrl); }); - it('should return the parameter ncb with value 1', () => { + it('should return the parameter ncb with value 1', function () { const ncb = spec.buildRequests(bidRequests).data.ncb; expect(ncb).to.equal('1'); }); }); - describe('interpretResponse', () => { - it('should return an empty array when there is no ads in the response', () => { + describe('interpretResponse', function () { + it('should return an empty array when there is no ads in the response', function () { const bidResponses = spec.interpretResponse(responseWithNoAd); expect(bidResponses).to.be.empty; }); - it('should return an empty array when there is no spaces in the response', () => { + it('should return an empty array when there is no spaces in the response', function () { const bidResponses = spec.interpretResponse(responseWithNoSpace); expect(bidResponses).to.be.empty; }); - it('should correctly map the parameters in the response', () => { + it('should correctly map the parameters in the response', function () { const bidResponse = spec.interpretResponse(response, { adUnitToBidId: { [CLEAN_ADUNIT_CODE]: BID_ID } })[0]; const expectedResponse = { requestId: BID_ID, @@ -299,7 +312,7 @@ describe('E-Planning Adapter', () => { }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { const sOptionsAllEnabled = { pixelEnabled: true, iframeEnabled: true @@ -317,30 +330,30 @@ describe('E-Planning Adapter', () => { iframeEnabled: true }; - it('should return an empty array if the response has no syncs', () => { + it('should return an empty array if the response has no syncs', function () { const noSyncsResponse = { cs: [] }; const syncs = spec.getUserSyncs(sOptionsAllEnabled, [noSyncsResponse]); expect(syncs).to.be.empty; }); - it('should return an empty array if there is no sync options enabled', () => { + it('should return an empty array if there is no sync options enabled', function () { const syncs = spec.getUserSyncs(sOptionsAllDisabled, [response]); expect(syncs).to.be.empty; }); - it('should only return pixels if iframe is not enabled', () => { + it('should only return pixels if iframe is not enabled', function () { const syncs = spec.getUserSyncs(sOptionsOnlyPixel, [response]); syncs.forEach(sync => expect(sync.type).to.equal('image')); }); - it('should only return iframes if pixel is not enabled', () => { + it('should only return iframes if pixel is not enabled', function () { const syncs = spec.getUserSyncs(sOptionsOnlyIframe, [response]); syncs.forEach(sync => expect(sync.type).to.equal('iframe')); }); }); - describe('adUnits mapping to bidId', () => { - it('should correctly map the bidId to the adunit', () => { + describe('adUnits mapping to bidId', function () { + it('should correctly map the bidId to the adunit', function () { const requests = spec.buildRequests([validBid, validBid2]); const responses = spec.interpretResponse(responseWithTwoAdunits, requests); expect(responses[0].requestId).to.equal(BID_ID); diff --git a/test/spec/modules/etargetBidAdapter_spec.js b/test/spec/modules/etargetBidAdapter_spec.js new file mode 100644 index 00000000000..e4cccbf5cf3 --- /dev/null +++ b/test/spec/modules/etargetBidAdapter_spec.js @@ -0,0 +1,433 @@ +import {assert, expect} from 'chai'; +import * as url from 'src/url'; +import {spec} from 'modules/etargetBidAdapter'; +import { BANNER, VIDEO } from 'src/mediaTypes'; + +describe('etarget adapter', function () { + let serverResponse, bidRequest, bidResponses; + let bids = []; + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'etarget', + 'params': { + 'refid': '55410', + 'country': '1' + } + }; + + it('should return true when required params found', function () { + assert(spec.isBidRequestValid(bid)); + }); + }); + + describe('buildRequests', function () { + it('should pass multiple bids via single request', function () { + let request = spec.buildRequests(bids); + let parsedUrl = parseUrl(request.url); + assert.lengthOf(parsedUrl.items, 7); + }); + + it('should handle global request parameters', function () { + let parsedUrl = parseUrl(spec.buildRequests([bids[0]]).url); + assert.equal(parsedUrl.path, '//sk.search.etargetnet.com/hb'); + }); + + it('should set correct request method', function () { + let request = spec.buildRequests([bids[0]]); + assert.equal(request.method, 'POST'); + }); + + it('should correctly form bid items', function () { + let bidList = bids; + let request = spec.buildRequests(bidList); + let parsedUrl = parseUrl(request.url); + assert.deepEqual(parsedUrl.items, [ + { + refid: '1', + country: '1', + transactionId: '5f33781f-9552-4ca1', + url: 'some// there' + }, + { + refid: '2', + country: '1', + someVar: 'someValue', + pt: 'gross', + transactionId: '5f33781f-9552-4iuy' + }, + { + refid: '3', + country: '1', + pdom: 'home', + transactionId: '5f33781f-9552-7ev3' + }, + { + refid: '3', + country: '1', + pdom: 'home', + transactionId: '5f33781f-9552-7ev3' + }, + { + refid: '3', + country: '1', + pdom: 'home', + transactionId: '5f33781f-9552-7ev3' + }, + { + refid: '5', + country: '1', + pt: 'net', + transactionId: '5f33781f-9552-7ev3', + }, + { + refid: '6', + country: '1', + pt: 'gross', + transactionId: '5f33781f-9552-7ev3' + } + ]); + }); + + it('should not change original validBidRequests object', function () { + var resultBids = JSON.parse(JSON.stringify(bids[0])); + let request = spec.buildRequests([bids[0]]); + assert.deepEqual(resultBids, bids[0]); + }); + + describe('gdpr', function () { + it('should send GDPR Consent data to etarget if gdprApplies', function () { + let resultBids = JSON.parse(JSON.stringify(bids[0])); + let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: true, consentString: 'concentDataString'}}); + let parsedUrl = parseUrl(request.url).query; + + assert.equal(parsedUrl.gdpr, 'true'); + assert.equal(parsedUrl.gdpr_consent, 'concentDataString'); + }); + + it('should not send GDPR Consent data to etarget if gdprApplies is false or undefined', function () { + let resultBids = JSON.parse(JSON.stringify(bids[0])); + let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: false, consentString: 'concentDataString'}}); + let parsedUrl = parseUrl(request.url).query; + + assert.ok(!parsedUrl.gdpr); + assert.ok(!parsedUrl.gdpr_consent); + + request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: undefined, consentString: 'concentDataString'}}); + assert.ok(!parsedUrl.gdpr); + assert.ok(!parsedUrl.gdpr_consent); + }); + + it('should return GDPR Consent data with request data', function () { + let request = spec.buildRequests([bids[0]], {gdprConsent: {gdprApplies: true, consentString: 'concentDataString'}}); + + assert.deepEqual(request.gdpr, { + gdpr: true, + gdpr_consent: 'concentDataString' + }); + + request = spec.buildRequests([bids[0]]); + assert.ok(!request.gdpr); + }); + }); + }); + + describe('interpretResponse', function () { + it('should respond with empty response when there is empty serverResponse', function () { + let result = spec.interpretResponse({ body: {} }, {}); + assert.deepEqual(result, []); + }); + it('should respond with empty response when response from server is not banner', function () { + serverResponse.body[0].response = 'not banner'; + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + let result = spec.interpretResponse(serverResponse, bidRequest); + + assert.deepEqual(result, []); + }); + it('should interpret server response correctly with one bid', function () { + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + let result = spec.interpretResponse(serverResponse, bidRequest)[0]; + + assert.equal(result.requestId, '2a0cf4e'); + assert.equal(result.cpm, 13.9); + assert.equal(result.width, 300); + assert.equal(result.height, 250); + assert.equal(result.currency, 'EUR'); + assert.equal(result.netRevenue, true); + assert.equal(result.ttl, 360); + assert.equal(result.ad, ''); + assert.equal(result.transactionId, '5f33781f-9552-4ca1'); + }); + + it('should set correct netRevenue', function () { + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[1]]; + bidRequest.netRevenue = 'net'; + let result = spec.interpretResponse(serverResponse, bidRequest)[0]; + + assert.equal(result.netRevenue, true); + }); + + it('should create bid response item for every requested item', function () { + let result = spec.interpretResponse(serverResponse, bidRequest); + assert.lengthOf(result, 5); + }); + + it('should create bid response with vast xml', function () { + const result = spec.interpretResponse(serverResponse, bidRequest)[3]; + assert.equal(result.vastXml, ''); + }); + + it('should create bid response with vast url', function () { + const result = spec.interpretResponse(serverResponse, bidRequest)[4]; + assert.equal(result.vastUrl, 'vast://url'); + }); + + it('should set mediaType on bid response', function () { + const expected = [ BANNER, BANNER, BANNER, VIDEO, VIDEO ]; + const result = spec.interpretResponse(serverResponse, bidRequest); + for (let i = 0; i < result.length; i++) { + assert.equal(result[i].mediaType, expected[i]); + } + }); + + it('should set default netRevenue as gross', function () { + bidRequest.netRevenue = 'gross'; + const result = spec.interpretResponse(serverResponse, bidRequest); + for (let i = 0; i < result.length; i++) { + assert.equal(result[i].netRevenue, true); + } + }); + + it('should set gdpr if it exist in bidRequest', function () { + bidRequest.gdpr = { + gdpr: true, + gdpr_consent: 'ERW342EIOWT34234KMGds' + }; + let result = spec.interpretResponse(serverResponse, bidRequest); + for (let i = 0; i < result.length; i++) { + assert.equal(result[i].gdpr, true); + assert.equal(result[i].gdpr_consent, 'ERW342EIOWT34234KMGds'); + }; + + bidRequest.gdpr = undefined; + result = spec.interpretResponse(serverResponse, bidRequest); + for (let i = 0; i < result.length; i++) { + assert.ok(!result[i].gdpr); + assert.ok(!result[i].gdpr_consent); + }; + }); + + describe('verifySizes', function () { + it('should respond with empty response when sizes doesn\'t match', function () { + serverResponse.body[0].response = 'banner'; + serverResponse.body[0].width = 100; + serverResponse.body[0].height = 150; + + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + let result = spec.interpretResponse(serverResponse, bidRequest); + + assert.equal(serverResponse.body.length, 1); + assert.equal(serverResponse.body[0].response, 'banner'); + assert.deepEqual(result, []); + }); + it('should respond with empty response when sizes as a strings doesn\'t match', function () { + serverResponse.body[0].response = 'banner'; + serverResponse.body[0].width = 100; + serverResponse.body[0].height = 150; + + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + + bidRequest.bids[0].sizes = [['101', '150']]; + let result = spec.interpretResponse(serverResponse, bidRequest); + + assert.equal(serverResponse.body.length, 1); + assert.equal(serverResponse.body[0].response, 'banner'); + assert.deepEqual(result, []); + }); + it('should support size dimensions as a strings', function () { + serverResponse.body[0].response = 'banner'; + serverResponse.body[0].width = 300; + serverResponse.body[0].height = 600; + + serverResponse.body = [serverResponse.body[0]]; + bidRequest.bids = [bidRequest.bids[0]]; + + bidRequest.bids[0].sizes = [['300', '250'], ['250', '300'], ['300', '600'], ['600', '300']] + let result = spec.interpretResponse(serverResponse, bidRequest); + + assert.equal(result[0].width, 300); + assert.equal(result[0].height, 600); + }); + }) + }); + + beforeEach(function () { + let sizes = [[250, 300], [300, 250], [300, 600]]; + let placementCode = ['div-01', 'div-02', 'div-03', 'div-04', 'div-05']; + let params = [{refid: 1, country: 1, url: 'some// there'}, {refid: 2, country: 1, someVar: 'someValue', pt: 'gross'}, {refid: 3, country: 1, pdom: 'home'}, {refid: 5, country: 1, pt: 'net'}, {refid: 6, country: 1, pt: 'gross'}]; + bids = [ + { + adUnitCode: placementCode[0], + auctionId: '7aefb970-2045', + bidId: '2a0cf4e', + bidder: 'etarget', + bidderRequestId: '1ab8d9', + params: params[0], + tid: 45, + placementCode: placementCode[0], + sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], + transactionId: '5f33781f-9552-4ca1' + }, + { + adUnitCode: placementCode[1], + auctionId: '7aefb970-2045', + bidId: '2a0cf5b', + bidder: 'etarget', + bidderRequestId: '1ab8d9', + params: params[1], + placementCode: placementCode[1], + sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], + transactionId: '5f33781f-9552-4iuy' + }, + { + adUnitCode: placementCode[2], + auctionId: '7aefb970-2045', + bidId: '2a0cf6n', + bidder: 'etarget', + bidderRequestId: '1ab8d9', + params: params[2], + placementCode: placementCode[2], + sizes: [[300, 250], [250, 300], [300, 600], [600, 300]], + transactionId: '5f33781f-9552-7ev3' + }, + { + adUnitCode: placementCode[3], + auctionId: '7aefb970-2045', + bidId: '2a0cf6n', + bidder: 'etarget', + bidderRequestId: '1ab8d9', + params: params[2], + placementCode: placementCode[2], + sizes: [], + transactionId: '5f33781f-9552-7ev3' + }, + { + adUnitCode: placementCode[4], + auctionId: '7aefb970-2045', + bidId: '2a0cf6n', + bidder: 'etarget', + bidderRequestId: '1ab8d9', + params: params[2], + placementCode: placementCode[2], + sizes: [], + transactionId: '5f33781f-9552-7ev3' + }, + { + adUnitCode: placementCode[4], + auctionId: '7aefb970-2045', + bidId: '2a0cf6n', + bidder: 'etarget', + bidderRequestId: '1ab8d9', + params: params[3], + placementCode: placementCode[2], + sizes: [], + transactionId: '5f33781f-9552-7ev3' + }, + { + adUnitCode: placementCode[4], + auctionId: '7aefb970-2045', + bidId: '2a0cf6n', + bidder: 'etarget', + bidderRequestId: '1ab8d9', + params: params[4], + placementCode: placementCode[2], + sizes: [], + transactionId: '5f33781f-9552-7ev3' + } + ]; + serverResponse = { + body: [ + { + banner: '', + deal_id: '123abc', + height: 250, + response: 'banner', + width: 300, + win_bid: 13.9, + win_cur: 'EUR' + }, + { + banner: '', + deal_id: '123abc', + height: 300, + response: 'banner', + width: 250, + win_bid: 13.9, + win_cur: 'EUR' + }, + { + banner: '', + deal_id: '123abc', + height: 300, + response: 'banner', + width: 600, + win_bid: 10, + win_cur: 'EUR' + }, + { + deal_id: '123abc', + height: 300, + response: 'video', + width: 600, + win_bid: 10, + win_cur: 'EUR', + vast_content: '' + }, + { + deal_id: '123abc', + height: 300, + response: 'video', + width: 600, + win_bid: 10, + win_cur: 'EUR', + vast_link: 'vast://url' + } + ], + headers: {} + }; + bidRequest = { + bidder: 'etarget', + bids: bids, + method: 'POST', + url: 'url', + netRevenue: 'net' + }; + }); +}); + +function parseUrl(url) { + const parts = url.split('/'); + const query = parts.pop().split('&'); + return { + path: parts.join('/'), + items: query + .filter((i) => !~i.indexOf('=')) + .map((i) => atob(decodeURIComponent(i)) + .split('&') + .reduce(toObject, {})), + query: query + .filter((i) => ~i.indexOf('=')) + .map((i) => i.replace('?', '')) + .reduce(toObject, {}) + }; +} + +function toObject(cache, string) { + const keyValue = string.split('='); + cache[keyValue[0]] = keyValue[1]; + return cache; +} diff --git a/test/spec/modules/fairtradeBidAdapter_spec.js b/test/spec/modules/fairtradeBidAdapter_spec.js index 07c26e8f0c1..ecd5db3c051 100644 --- a/test/spec/modules/fairtradeBidAdapter_spec.js +++ b/test/spec/modules/fairtradeBidAdapter_spec.js @@ -5,13 +5,13 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('FairTradeAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'fairtrade', 'params': { @@ -24,11 +24,11 @@ describe('FairTradeAdapter', function () { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -38,7 +38,7 @@ describe('FairTradeAdapter', function () { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'fairtrade', @@ -75,7 +75,7 @@ describe('FairTradeAdapter', function () { } ]; - it('should attach valid params to the tag', () => { + it('should attach valid params to the tag', function () { const request = spec.buildRequests([bidRequests[0]]); const payload = request.data; expect(payload).to.be.an('object'); @@ -85,7 +85,7 @@ describe('FairTradeAdapter', function () { expect(payload).to.have.property('r', '22edbae2733bf6'); }); - it('auids must not be duplicated', () => { + it('auids must not be duplicated', function () { const request = spec.buildRequests(bidRequests); const payload = request.data; expect(payload).to.be.an('object'); @@ -95,7 +95,7 @@ describe('FairTradeAdapter', function () { expect(payload).to.have.property('r', '22edbae2733bf6'); }); - it('pt parameter must be "gross" if params.priceType === "gross"', () => { + it('pt parameter must be "gross" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; const request = spec.buildRequests(bidRequests); const payload = request.data; @@ -107,7 +107,7 @@ describe('FairTradeAdapter', function () { delete bidRequests[1].params.priceType; }); - it('pt parameter must be "net" or "gross"', () => { + it('pt parameter must be "net" or "gross"', function () { bidRequests[1].params.priceType = 'some'; const request = spec.buildRequests(bidRequests); const payload = request.data; @@ -120,7 +120,7 @@ describe('FairTradeAdapter', function () { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const responses = [ {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 165, 'h': 250, 'w': 300}], 'seat': '1'}, {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 166, 'h': 90, 'w': 728}], 'seat': '1'}, @@ -131,7 +131,7 @@ describe('FairTradeAdapter', function () { {'seat': '1'}, ]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const bidRequests = [ { 'bidder': 'fairtrade', @@ -165,7 +165,7 @@ describe('FairTradeAdapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should get correct multi bid response', () => { + it('should get correct multi bid response', function () { const bidRequests = [ { 'bidder': 'fairtrade', @@ -245,7 +245,7 @@ describe('FairTradeAdapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('handles wrong and nobid responses', () => { + it('handles wrong and nobid responses', function () { const bidRequests = [ { 'bidder': 'fairtrade', diff --git a/test/spec/modules/fidelityBidAdapter_spec.js b/test/spec/modules/fidelityBidAdapter_spec.js index 28ea18aacac..e8e008103e6 100644 --- a/test/spec/modules/fidelityBidAdapter_spec.js +++ b/test/spec/modules/fidelityBidAdapter_spec.js @@ -2,16 +2,16 @@ import { expect } from 'chai'; import { spec } from 'modules/fidelityBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -describe('FidelityAdapter', () => { +describe('FidelityAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'fidelity', 'params': { @@ -26,11 +26,11 @@ describe('FidelityAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when required params found', () => { + it('should return true when required params found', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -39,7 +39,7 @@ describe('FidelityAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -49,10 +49,10 @@ describe('FidelityAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidderRequest = { bidderCode: 'fidelity', - auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', bidderRequestId: '178e34bad3658f', bids: [ { @@ -66,7 +66,7 @@ describe('FidelityAdapter', () => { sizes: [[300, 250], [320, 50]], bidId: '2ffb201a808da7', bidderRequestId: '178e34bad3658f', - auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', + requestId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', transactionId: 'd45dd707-a418-42ec-b8a7-b70a6c6fab0b' } ], @@ -75,7 +75,7 @@ describe('FidelityAdapter', () => { timeout: 5000 }; - it('should add source and verison to the tag', () => { + it('should add source and verison to the tag', function () { const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); const payload = request.data; expect(payload.from).to.exist; @@ -85,21 +85,41 @@ describe('FidelityAdapter', () => { expect(payload.zoneid).to.exist; expect(payload.floor).to.exist; expect(payload.charset).to.exist; - expect(payload.defloc).to.exist; - expect(payload.altloc).to.exist; expect(payload.subid).to.exist; expect(payload.flashver).to.exist; expect(payload.tmax).to.exist; + expect(payload.defloc).to.exist; + }); + + it('should add gdpr consent information to the request', function () { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + bidderRequest.gdprConsent = { + gdprApplies: true, + consentString: consentString, + vendorData: { + vendorConsents: { + '408': 1 + }, + }, + }; + const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + const payload = request.data; + expect(payload.gdpr).to.exist.and.to.be.a('number'); + expect(payload.gdpr).to.equal(1); + expect(payload.consent_str).to.exist.and.to.be.a('string'); + expect(payload.consent_str).to.equal(consentString); + expect(payload.consent_given).to.exist.and.to.be.a('number'); + expect(payload.consent_given).to.equal(1); }); - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); expect(request.url).to.equal('//t.fidelity-media.com/delivery/hb.php'); expect(request.method).to.equal('GET'); }); }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { 'id': '543210', 'seatbid': [ { @@ -114,7 +134,7 @@ describe('FidelityAdapter', () => { } ] }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { requestId: 'bidId-123456-1', @@ -133,7 +153,7 @@ describe('FidelityAdapter', () => { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = { 'id': '543210', 'seatbid': [ ] @@ -144,10 +164,10 @@ describe('FidelityAdapter', () => { }); }); - describe('user sync', () => { + describe('user sync', function () { const syncUrl = '//x.fidelity-media.com/delivery/matches.php?type=iframe'; - it('should register the sync iframe', () => { + it('should register the sync iframe', function () { expect(spec.getUserSyncs({})).to.be.undefined; expect(spec.getUserSyncs({iframeEnabled: false})).to.be.undefined; const options = spec.getUserSyncs({iframeEnabled: true}); diff --git a/test/spec/modules/freewheelSSPBidAdapter_spec.js b/test/spec/modules/freewheel-sspBidAdapter_spec.js similarity index 80% rename from test/spec/modules/freewheelSSPBidAdapter_spec.js rename to test/spec/modules/freewheel-sspBidAdapter_spec.js index 33bd647efaa..a1123cee151 100644 --- a/test/spec/modules/freewheelSSPBidAdapter_spec.js +++ b/test/spec/modules/freewheel-sspBidAdapter_spec.js @@ -1,191 +1,197 @@ -import { expect } from 'chai'; -import { spec } from 'modules/freewheelSSPBidAdapter'; -import { newBidder } from 'src/adapters/bidderFactory'; - -const ENDPOINT = '//ads.stickyadstv.com/www/delivery/swfIndex.php'; - -describe('freewheelSSP BidAdapter Test', () => { - const adapter = newBidder(spec); - - describe('inherited functions', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid', () => { - let bid = { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - }; - - it('should return true when required params found', () => { - expect(spec.isBidRequestValid(bid)).to.equal(true); - }); - - it('should return false when required params are not passed', () => { - let bid = Object.assign({}, bid); - delete bid.params; - bid.params = { - wrong: 'missing zone id' - }; - expect(spec.isBidRequestValid(bid)).to.equal(false); - }); - }); - - describe('buildRequests', () => { - let bidRequests = [ - { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - } - ]; - - it('should add parameters to the tag', () => { - const request = spec.buildRequests(bidRequests); - const payload = request.data; - expect(payload.reqType).to.equal('AdsSetup'); - expect(payload.protocolVersion).to.equal('2.0'); - expect(payload.zoneId).to.equal('277225'); - expect(payload.componentId).to.equal('mustang'); - expect(payload.playerSize).to.equal('300x600'); - }); - - it('sends bid request to ENDPOINT via GET', () => { - const request = spec.buildRequests(bidRequests); - expect(request.url).to.contain(ENDPOINT); - expect(request.method).to.equal('GET'); - }); - }) - - describe('interpretResponse', () => { - let bidRequests = [ - { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475', - } - ]; - - let formattedBidRequests = [ - { - 'bidder': 'freewheel-ssp', - 'params': { - 'zoneId': '277225', - 'format': 'floorad' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[600, 250], [300, 600]], - 'bidId': '30b3other1c1838de1e', - 'bidderRequestId': '22edbae273other3bf6', - 'auctionId': '1d1a03079test0a475', - }, - { - 'bidder': 'stickyadstv', - 'params': { - 'zoneId': '277225', - 'format': 'test' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [[300, 600]], - 'bidId': '2', - 'bidderRequestId': '3', - 'auctionId': '4', - } - ]; - - let response = '' + - '' + - ' ' + - ' Adswizz' + - ' ' + - ' ' + - ' ' + - ' 00:00:09' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' 0.2000' + - ' ' + - ' ' + - ' ' + - ''; - - let ad = '
'; - let formattedAd = '
'; - - it('should get correct bid response', () => { - var request = spec.buildRequests(bidRequests); - - let expectedResponse = [ - { - requestId: '30b31c1838de1e', - cpm: '0.2000', - width: 300, - height: 600, - creativeId: '28517153', - currency: 'EUR', - netRevenue: true, - ttl: 360, - ad: ad - } - ]; - - let result = spec.interpretResponse(response, request); - expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); - }); - - it('should get correct bid response with formated ad', () => { - var request = spec.buildRequests(formattedBidRequests); - - let expectedResponse = [ - { - requestId: '30b31c1838de1e', - cpm: '0.2000', - width: 300, - height: 600, - creativeId: '28517153', - currency: 'EUR', - netRevenue: true, - ttl: 360, - ad: formattedAd - } - ]; - - let result = spec.interpretResponse(response, request); - expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); - }); - - it('handles nobid responses', () => { - var reqest = spec.buildRequests(formattedBidRequests); - let response = ''; - - let result = spec.interpretResponse(response, reqest); - expect(result.length).to.equal(0); - }); - }); -}); +import { expect } from 'chai'; +import { spec } from 'modules/freewheel-sspBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//ads.stickyadstv.com/www/delivery/swfIndex.php'; + +describe('freewheel-ssp BidAdapter Test', function () { + 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 () { + let bid = { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + wrong: 'missing zone id' + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + 'gdprConsent': { + 'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + 'gdprApplies': true + } + } + ]; + + it('should add parameters to the tag', function () { + const request = spec.buildRequests(bidRequests, bidRequests[0]); + const payload = request.data; + expect(payload.reqType).to.equal('AdsSetup'); + expect(payload.protocolVersion).to.equal('2.0'); + expect(payload.zoneId).to.equal('277225'); + expect(payload.componentId).to.equal('mustang'); + expect(payload.playerSize).to.equal('300x600'); + expect(payload._fw_gdpr).to.equal(true); + expect(payload._fw_gdpr_consent).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); + }); + + it('sends bid request to ENDPOINT via GET', function () { + const request = spec.buildRequests(bidRequests, bidRequests[0]); + expect(request.url).to.contain(ENDPOINT); + expect(request.method).to.equal('GET'); + }); + }) + + describe('interpretResponse', function () { + let bidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + let formattedBidRequests = [ + { + 'bidder': 'freewheel-ssp', + 'params': { + 'zoneId': '277225', + 'format': 'floorad' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[600, 250], [300, 600]], + 'bidId': '30b3other1c1838de1e', + 'bidderRequestId': '22edbae273other3bf6', + 'auctionId': '1d1a03079test0a475', + }, + { + 'bidder': 'stickyadstv', + 'params': { + 'zoneId': '277225', + 'format': 'test' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 600]], + 'bidId': '2', + 'bidderRequestId': '3', + 'auctionId': '4', + } + ]; + + let response = '' + + '' + + ' ' + + ' Adswizz' + + ' ' + + ' ' + + ' ' + + ' 00:00:09' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' ' + + ' 0.2000' + + ' ' + + ' ' + + ' ' + + ''; + + let ad = '
'; + let formattedAd = '
'; + + it('should get correct bid response', function () { + var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + + let expectedResponse = [ + { + requestId: '30b31c1838de1e', + cpm: '0.2000', + width: 300, + height: 600, + creativeId: '28517153', + currency: 'EUR', + netRevenue: true, + ttl: 360, + ad: ad + } + ]; + + let result = spec.interpretResponse(response, request); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('should get correct bid response with formated ad', function () { + var request = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + + let expectedResponse = [ + { + requestId: '30b31c1838de1e', + cpm: '0.2000', + width: 300, + height: 600, + creativeId: '28517153', + currency: 'EUR', + netRevenue: true, + ttl: 360, + ad: formattedAd + } + ]; + + let result = spec.interpretResponse(response, request); + expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', function () { + var reqest = spec.buildRequests(formattedBidRequests, formattedBidRequests[0]); + let response = ''; + + let result = spec.interpretResponse(response, reqest); + expect(result.length).to.equal(0); + }); + }); +}); diff --git a/test/spec/modules/fyberBidAdapter_spec.js b/test/spec/modules/fyberBidAdapter_spec.js new file mode 100644 index 00000000000..a16c069d2a0 --- /dev/null +++ b/test/spec/modules/fyberBidAdapter_spec.js @@ -0,0 +1,154 @@ +import { expect } from 'chai'; +import { spec } from 'modules/fyberBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import bidRequest from '../../fixtures/video/bidRequest.json'; + +const bidId = '21b2499bf34cf8'; +const mock = { + bid: { + bidder: 'fyber', + params: { + appId: 'MyCompany_MyApp', + spotType: 'rectangle', + gdprPrivacyConsent: true, + qa: { + // url: 'http://ia-test08.inner-active.mobi:8080/simpleM2M/requestJsonAd', + cpm: 10 + }, + customParams: { + // referrer: 'referrer', + // page: 'aaaa', + portal: 7002 + // KEYWORDS: 'bbb' + } + } + }, + bidsRequest: [ + { + adUnitCode: '/19968336/header-bid-tag-1', + auctionId: 'f270d8dd-29c6-4aca-8648-7d722590b899', + bidId, + bidder: 'fyber', + bidderRequestId: '1bcd667e09f48e', + params: { + spotType: 'rectangle', + gdprPrivacyConsent: true, + qa: {cpm: 10}, + customParams: {portal: 7002}, + appId: 'MyCompany_MyApp' + }, + sizes: [[300, 250], [300, 600]], + transactionId: 'a0253346-df4e-4f1a-b004-1f50e8e6af69' + } + ], + validResponse: { + body: { + ad: { + html: '

Fyber Ad

' + }, + config: { + tracking: { + clicks: ['c1'], + impressions: ['i1'] + } + } + }, + headers: { + get(headerName) { + if (headerName === 'X-IA-Pricing-Value') { + return 10; + } + return headerName; + } + } + }, + invalidResponse: { + body: {}, + headers: { + get(headerName) { + return headerName; + } + } + } +}; + +describe('FyberAdapter', function () { + const adapter = newBidder(spec); + + describe('inherited functions', function () { + it('callBids exists and is a function', function () { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('Verifies bidder code', function () { + it('Verifies bidder code', function () { + expect(spec.code).to.equal('fyber'); + }); + }); + + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { + const bid = Object.assign({}, mock.bid); + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params{spotType} not found', function () { + const bid = Object.assign({}, mock.bid); + delete bid.params.spotType; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when required{appId} params not found', function () { + const bid = Object.assign({}, mock.bid); + delete bid.params.appId; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + const bidsRequest = Object.assign([], mock.bidsRequest); + const requests = spec.buildRequests(bidsRequest); + + it('Verify only one build request', function () { + expect(requests.length).to.equal(1); + }); + + const request = requests[0]; + + it('Verify build request http method', function () { + expect(request.method).to.equal('GET'); + }); + + it('Verify build request bidId', function () { + expect(request.bidId).to.equal(bidId); + }); + }); + + describe('interpretResponse', function () { + const request = Object.assign([], mock.bidsRequest)[0]; + const validResponse = Object.assign({}, mock.validResponse); + const validResult = spec.interpretResponse(validResponse, request); + + it('Verify only one bid response', function () { + expect(validResult.length).to.equal(1); + }); + + const bidResponse = validResult[0]; + + it('Verify CPM', function () { + expect(bidResponse.cpm).to.equal(10000); + }); + + it('Verify requestId', function () { + expect(bidResponse.requestId).to.equal(bidId); + }); + + const invalidResponse = Object.assign({}, mock.invalidResponse); + const invalidResult = spec.interpretResponse(invalidResponse, request); + + it('Verify empty bid response', function () { + expect(invalidResult.length).to.equal(0); + }); + }); +}); diff --git a/test/spec/modules/gambidBidAdapter_spec.js b/test/spec/modules/gambidBidAdapter_spec.js index 54b9c518e2b..06118f7f7d8 100644 --- a/test/spec/modules/gambidBidAdapter_spec.js +++ b/test/spec/modules/gambidBidAdapter_spec.js @@ -4,29 +4,29 @@ import * as utils from 'src/utils'; const supplyPartnerId = '123'; -describe('GambidAdapter', () => { - describe('isBidRequestValid', () => { - it('should validate supply-partner ID', () => { +describe('GambidAdapter', function () { + describe('isBidRequestValid', function () { + it('should validate supply-partner ID', function () { expect(spec.isBidRequestValid({ params: {} })).to.equal(false); expect(spec.isBidRequestValid({ params: { supplyPartnerId: 123 } })).to.equal(false); expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); }); - it('should validate RTB endpoint', () => { + it('should validate RTB endpoint', function () { expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); // RTB endpoint has a default expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', rtbEndpoint: 123 } })).to.equal(false); expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', rtbEndpoint: 'https://some.url.com' } })).to.equal(true); }); - it('should validate bid floor', () => { + it('should validate bid floor', function () { expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); // bidfloor has a default expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', bidfloor: '123' } })).to.equal(false); expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', bidfloor: 0.1 } })).to.equal(true); }); - it('should validate adpos', () => { + it('should validate adpos', function () { expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); // adpos has a default expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', adpos: '123' } })).to.equal(false); expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', adpos: 0.1 } })).to.equal(true); }); - it('should validate instl', () => { + it('should validate instl', function () { expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123' } })).to.equal(true); // adpos has a default expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', instl: '123' } })).to.equal(false); expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', instl: -1 } })).to.equal(false); @@ -35,7 +35,7 @@ describe('GambidAdapter', () => { expect(spec.isBidRequestValid({ params: { supplyPartnerId: '123', instl: 2 } })).to.equal(false); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const bidRequest = { 'adUnitCode': 'adunit-code', 'auctionId': '1d1a030790a475', @@ -49,7 +49,7 @@ describe('GambidAdapter', () => { 'transactionId': 'a123456789' }; - it('returns an array', () => { + it('returns an array', function () { let response; response = spec.buildRequests([]); @@ -67,21 +67,21 @@ describe('GambidAdapter', () => { expect(response.length).to.equal(2); }); - it('targets correct endpoint', () => { + it('targets correct endpoint', function () { let response; response = spec.buildRequests([ bidRequest ])[ 0 ]; expect(response.method).to.equal('POST'); - expect(response.url).to.match(new RegExp(`^https://rtb\\.gambid\\.io/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&bidder=prebid$`, 'g')); + expect(response.url).to.match(new RegExp(`^https://rtb\\.gambid\\.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.gambid.io/a12'; response = spec.buildRequests([ bidRequestWithEndpoint ])[ 0 ]; - expect(response.url).to.match(new RegExp(`^https://rtb2\\.gambid\\.io/a12/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&bidder=prebid$`, 'g')); + expect(response.url).to.match(new RegExp(`^https://rtb2\\.gambid\\.io/a12/r/${supplyPartnerId}/bidr\\?rformat=open_rtb&reqformat=rtb_json&bidder=prebid$`, 'g')); }); - it('builds request correctly', () => { + it('builds request correctly', function () { let stub = sinon.stub(utils, 'getTopWindowUrl').returns('http://www.test.com/page.html'); let response; @@ -114,7 +114,7 @@ describe('GambidAdapter', () => { stub.restore(); }); - it('builds request banner object correctly', () => { + it('builds request banner object correctly', function () { let response; const bidRequestWithBanner = utils.deepClone(bidRequest); @@ -136,7 +136,7 @@ describe('GambidAdapter', () => { expect(response.data.imp[ 0 ].banner.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); - it('builds request video object correctly', () => { + it('builds request video object correctly', function () { let response; const bidRequestWithVideo = utils.deepClone(bidRequest); @@ -158,7 +158,7 @@ describe('GambidAdapter', () => { expect(response.data.imp[ 0 ].video.pos).to.equal(bidRequestWithPosEquals1.params.pos); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const bannerBidRequest = { 'adUnitCode': 'adunit-code', 'auctionId': '1d1a030790a475', @@ -214,6 +214,7 @@ describe('GambidAdapter', () => { 'h': 600, 'w': 120, 'ext': { + 'vast_url': 'http://my.vast.com', 'utrk': [ { 'type': 'iframe', 'url': '//p.partner1.io/user/sync/1' } ] @@ -248,7 +249,7 @@ describe('GambidAdapter', () => { } ] }; - it('returns an empty array on missing response', () => { + it('returns an empty array on missing response', function () { let response; response = spec.interpretResponse(undefined, { bidRequest: bannerBidRequest }); @@ -259,7 +260,7 @@ describe('GambidAdapter', () => { expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(0); }); - it('aggregates banner bids from all seat bids', () => { + it('aggregates banner bids from all seat bids', function () { const response = spec.interpretResponse({ body: rtbResponse }, { bidRequest: bannerBidRequest }); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(2); @@ -290,7 +291,7 @@ describe('GambidAdapter', () => { // expect(ad1.ad).to.be.an('undefined'); // expect(ad1.vastXml).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); }); - it('aggregates video bids from all seat bids', () => { + it('aggregates video bids from all seat bids', function () { const response = spec.interpretResponse({ body: rtbResponse }, { bidRequest: videoBidRequest }); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(2); @@ -306,6 +307,7 @@ describe('GambidAdapter', () => { expect(ad0.currency).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); expect(ad0.ad).to.be.an('undefined'); expect(ad0.vastXml).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].adm); + expect(ad0.vastUrl).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].ext.vast_url); expect(ad1.requestId).to.equal(videoBidRequest.bidId); expect(ad1.cpm).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].price); @@ -317,8 +319,9 @@ describe('GambidAdapter', () => { expect(ad1.currency).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); expect(ad1.ad).to.be.an('undefined'); expect(ad1.vastXml).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); + expect(ad1.vastUrl).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.vast_url); }); - it('aggregates user-sync pixels', () => { + it('aggregates user-sync pixels', function () { const response = spec.getUserSyncs({}, [ { body: rtbResponse } ]); expect(Array.isArray(response)).to.equal(true); expect(response.length).to.equal(4); diff --git a/test/spec/modules/gammaBidAdapter_spec.js b/test/spec/modules/gammaBidAdapter_spec.js index 1f3f225336e..99593e6e06f 100644 --- a/test/spec/modules/gammaBidAdapter_spec.js +++ b/test/spec/modules/gammaBidAdapter_spec.js @@ -6,92 +6,78 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('gammaBidAdapter', function() { const adapter = newBidder(spec); - describe('isBidRequestValid', () => { - let bid = { - 'bidder': 'gamma', - 'params': { - siteId: '1465446377', - zoneId: '1515999290' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [ - [300, 250] - ], - 'bidId': '23beaa6af6cdde', - 'bidderRequestId': '19c0c1efdf37e7', - 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', - }; + let bid = { + 'bidder': 'gamma', + 'params': { + siteId: '1465446377', + zoneId: '1515999290' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250] + ], + 'bidId': '23beaa6af6cdde', + 'bidderRequestId': '19c0c1efdf37e7', + 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', + }; + let bidArray = [bid]; - it('should return true when required params found', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when require params are not passed', () => { + it('should return false when require params are not passed', function () { let bid = Object.assign({}, bid); bid.params = {}; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when params not passed correctly', () => { + it('should return false when params not passed correctly', function () { bid.params.siteId = ''; bid.params.zoneId = ''; expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); - describe('buildRequests', () => { - let bidRequests = [ - { - 'bidder': 'gamma', - 'params': { - siteId: '1465446377', - zoneId: '1515999290' - }, - 'adUnitCode': 'adunit-code', - 'sizes': [ - [300, 250] - ], - 'bidId': '23beaa6af6cdde', - 'bidderRequestId': '19c0c1efdf37e7', - 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1' - } - ]; - - const request = spec.buildRequests(bidRequests); - - it('sends bid request to our endpoint via GET', () => { - expect(request.method).to.equal('GET'); - }); - - it('bidRequest url', () => { - expect(request.url).to.match(new RegExp(`hb.gammaplatform.com`)); + describe('buildRequests', function () { + it('should attempt to send bid requests to the endpoint via GET', function () { + const requests = spec.buildRequests(bidArray); + requests.forEach(function(requestItem) { + expect(requestItem.method).to.equal('GET'); + expect(requestItem.url).to.match(new RegExp(`hb.gammaplatform.com`)); + }); }); }); - describe('interpretResponse', () => { - let serverResponse = { - body: { - 'id': '23beaa6af6cdde', - 'bid': '5611802021800040585', - 'type': 'banner', - 'cur': 'USD', - 'seatbid': [{ - 'seat': '5611802021800040585', - 'bid': [{ - 'id': '1515999070', - 'impid': '1', - 'price': 0.45, - 'adm': '', - 'adid': '1515999070', - 'dealid': 'gax-paj2qarjf2g', - 'h': 250, - 'w': 300 + describe('interpretResponse', function () { + let serverResponse; + + beforeEach(function () { + serverResponse = { + body: { + 'id': '23beaa6af6cdde', + 'bid': '5611802021800040585', + 'type': 'banner', + 'cur': 'USD', + 'seatbid': [{ + 'seat': '5611802021800040585', + 'bid': [{ + 'id': '1515999070', + 'impid': '1', + 'price': 0.45, + 'adm': '', + 'adid': '1515999070', + 'dealid': 'gax-paj2qarjf2g', + 'h': 250, + 'w': 300 + }] }] - }] - } - }; + } + }; + }) - it('should get the correct bid response', () => { + it('should get the correct bid response', function () { let expectedResponse = [{ 'requestId': '23beaa6af6cdde', 'cpm': 0.45, @@ -108,7 +94,7 @@ describe('gammaBidAdapter', function() { expect(Object.keys(result)).to.deep.equal(Object.keys(expectedResponse)); }); - it('handles empty bid response', () => { + it('handles empty bid response', function () { let response = { body: {} }; diff --git a/test/spec/modules/getintentBidAdapter_spec.js b/test/spec/modules/getintentBidAdapter_spec.js index 17f9a95fec4..ebbda7e108e 100644 --- a/test/spec/modules/getintentBidAdapter_spec.js +++ b/test/spec/modules/getintentBidAdapter_spec.js @@ -1,7 +1,7 @@ import { expect } from 'chai' import { spec } from 'modules/getintentBidAdapter' -describe('GetIntent Adapter Tests:', () => { +describe('GetIntent Adapter Tests:', function () { const bidRequests = [{ bidId: 'bid12345', params: { @@ -34,7 +34,7 @@ describe('GetIntent Adapter Tests:', () => { mediaType: 'video' }; - it('Verify build request', () => { + it('Verify build request', function () { const serverRequests = spec.buildRequests(bidRequests); let serverRequest = serverRequests[0]; expect(serverRequest.url).to.equal('//px.adhigh.net/rtb/direct_banner'); @@ -48,7 +48,7 @@ describe('GetIntent Adapter Tests:', () => { expect(serverRequest.data.size).to.equal('50x50,100x100'); }); - it('Verify build video request', () => { + it('Verify build video request', function () { const serverRequests = spec.buildRequests([videoBidRequest]); let serverRequest = serverRequests[0]; expect(serverRequest.url).to.equal('//px.adhigh.net/rtb/direct_vast'); @@ -64,7 +64,7 @@ describe('GetIntent Adapter Tests:', () => { expect(serverRequest.data.skippable).to.equal(true); }); - it('Verify parse response', () => { + it('Verify parse response', function () { const serverResponse = { body: { bid_id: 'bid12345', @@ -90,7 +90,7 @@ describe('GetIntent Adapter Tests:', () => { expect(bid.ad).to.equal('Ad markup'); }); - it('Verify parse video response', () => { + it('Verify parse video response', function () { const serverResponse = { body: { bid_id: 'bid789', @@ -116,22 +116,22 @@ describe('GetIntent Adapter Tests:', () => { expect(bid.vastUrl).to.equal('//vast.xml/url'); }); - it('Verify bidder code', () => { + it('Verify bidder code', function () { expect(spec.code).to.equal('getintent'); }); - it('Verify bidder aliases', () => { + it('Verify bidder aliases', function () { expect(spec.aliases).to.have.lengthOf(1); expect(spec.aliases[0]).to.equal('getintentAdapter'); }); - it('Verify supported media types', () => { + it('Verify supported media types', function () { expect(spec.supportedMediaTypes).to.have.lengthOf(2); expect(spec.supportedMediaTypes[0]).to.equal('video'); expect(spec.supportedMediaTypes[1]).to.equal('banner'); }); - it('Verify if bid request valid', () => { + it('Verify if bid request valid', function () { expect(spec.isBidRequestValid(bidRequests[0])).to.equal(true); expect(spec.isBidRequestValid(bidRequests[1])).to.equal(true); expect(spec.isBidRequestValid({})).to.equal(false); diff --git a/test/spec/modules/giantsBidAdapter_spec.js b/test/spec/modules/giantsBidAdapter_spec.js new file mode 100644 index 00000000000..bab2415745d --- /dev/null +++ b/test/spec/modules/giantsBidAdapter_spec.js @@ -0,0 +1,301 @@ +import { expect } from 'chai'; +import { spec } from 'modules/giantsBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { deepClone } from 'src/utils'; +import * as utils from 'src/utils'; + +const ENDPOINT = '//d.admp.io/hb/multi?url='; + +describe('GiantsAdapter', function () { + 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 () { + let bid = { + 'bidder': 'giants', + 'params': { + 'zoneId': '584072408' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'zoneId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [ + { + 'bidder': 'giants', + 'params': { + 'zoneId': '584072408' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should parse out private sizes', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + zoneId: '584072408', + privateSizes: [300, 250] + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].private_sizes).to.exist; + expect(payload.tags[0].private_sizes).to.deep.equal([{width: 300, height: 250}]); + }); + + it('should add source and verison to the tag', function () { + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.sdk).to.exist; + expect(payload.sdk).to.deep.equal({ + source: 'pbjs', + version: '$prebid.version$' + }); + }); + + it('should populate the ad_types array on all requests', function () { + ['banner', 'video', 'native'].forEach(type => { + const bidRequest = Object.assign({}, bidRequests[0]); + bidRequest.mediaTypes = {}; + bidRequest.mediaTypes[type] = {}; + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].ad_types).to.deep.equal([type]); + }); + }); + + it('should populate the ad_types array on outstream requests', function () { + const bidRequest = Object.assign({}, bidRequests[0]); + bidRequest.mediaTypes = {}; + bidRequest.mediaTypes.video = {context: 'outstream'}; + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].ad_types).to.deep.equal(['video']); + }); + + it('sends bid request to ENDPOINT via POST', function () { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal(ENDPOINT + utils.getTopWindowUrl()); + expect(request.method).to.equal('POST'); + }); + + it('should attach valid video params to the tag', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + zoneId: '584072408', + video: { + id: 123, + minduration: 100, + foobar: 'invalid' + } + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + expect(payload.tags[0].video).to.deep.equal({ + id: 123, + minduration: 100 + }); + }); + + it('sets minimum native asset params when not provided on adunit', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + image: {required: true}, + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ + main_image: {required: true, sizes: [{}]}, + }); + }); + + it('does not overwrite native ad unit params with mimimum params', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + image: { + aspect_ratios: [{ + min_width: 100, + ratio_width: 2, + ratio_height: 3, + }] + } + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ + main_image: { + required: true, + aspect_ratios: [{ + min_width: 100, + ratio_width: 2, + ratio_height: 3, + }] + }, + }); + }); + + it('should convert keyword params to proper form and attaches to request', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + zoneId: '584072408', + keywords: { + single: 'val', + singleArr: ['val'], + singleArrNum: [5], + multiValMixed: ['value1', 2, 'value3'], + singleValNum: 123, + badValue: {'foo': 'bar'} // should be dropped + } + } + } + ); + + 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'] + }]); + }); + + it('should add payment rules to the request', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + zoneId: '584072408', + usePaymentRule: true + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].use_pmt_rule).to.equal(true); + }); + }) + + describe('interpretResponse', function () { + let response = { + 'version': '3.0.0', + 'tags': [ + { + 'uuid': '3db3773286ee59', + 'creative_id': '584944065', + 'height': 600, + 'width': 300, + 'zoneId': '584072408', + 'adUrl': '//d.admp.io/pbc/v1/cache-banner/f7aca005-8171-4299-90bf-0750a864a61c', + 'cpm': 0.5 + } + ] + }; + + it('should get correct bid response', function () { + let expectedResponse = [ + { + 'requestId': '3db3773286ee59', + 'cpm': 0.5, + 'creativeId': 29681110, + 'currency': 'USD', + 'netRevenue': true, + 'ttl': 300, + 'width': 300, + 'height': 250, + 'ad': '', + 'mediaType': 'banner' + } + ]; + let bidderRequest; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', function () { + let response = { + 'version': '0.0.1', + 'tags': [{ + 'uuid': '84ab500420319d', + 'tag_id': 5976557, + 'auction_id': '297492697822162468', + 'nobid': true + }] + }; + let bidderRequest; + + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(result.length).to.equal(0); + }); + }); +}); diff --git a/test/spec/modules/gjirafaBidAdapter_spec.js b/test/spec/modules/gjirafaBidAdapter_spec.js index 542e8185db5..d3aaf9765b2 100644 --- a/test/spec/modules/gjirafaBidAdapter_spec.js +++ b/test/spec/modules/gjirafaBidAdapter_spec.js @@ -1,9 +1,9 @@ import { expect } from 'chai'; import { spec } from 'modules/gjirafaBidAdapter'; -describe('gjirafaAdapterTest', () => { - describe('bidRequestValidity', () => { - it('bidRequest with placementId, minCPM and minCPC params', () => { +describe('gjirafaAdapterTest', function () { + describe('bidRequestValidity', function () { + it('bidRequest with placementId, minCPM and minCPC params', function () { expect(spec.isBidRequestValid({ bidder: 'gjirafa', params: { @@ -14,7 +14,7 @@ describe('gjirafaAdapterTest', () => { })).to.equal(true); }); - it('bidRequest with only placementId param', () => { + it('bidRequest with only placementId param', function () { expect(spec.isBidRequestValid({ bidder: 'gjirafa', params: { @@ -23,7 +23,7 @@ describe('gjirafaAdapterTest', () => { })).to.equal(true); }); - it('bidRequest with minCPM and minCPC params', () => { + it('bidRequest with minCPM and minCPC params', function () { expect(spec.isBidRequestValid({ bidder: 'gjirafa', params: { @@ -33,7 +33,7 @@ describe('gjirafaAdapterTest', () => { })).to.equal(true); }); - it('bidRequest with no placementId, minCPM or minCPC params', () => { + it('bidRequest with no placementId, minCPM or minCPC params', function () { expect(spec.isBidRequestValid({ bidder: 'gjirafa', params: { @@ -42,7 +42,7 @@ describe('gjirafaAdapterTest', () => { }); }); - describe('bidRequest', () => { + describe('bidRequest', function () { const bidRequests = [{ 'bidder': 'gjirafa', 'params': { @@ -74,14 +74,14 @@ describe('gjirafaAdapterTest', () => { 'consent_required': 'true' }]; - it('bidRequest HTTP method', () => { + it('bidRequest HTTP method', function () { const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { expect(requestItem.method).to.equal('GET'); }); }); - it('bidRequest url', () => { + it('bidRequest url', function () { const endpointUrl = 'https://gjc.gjirafa.com/Home/GetBid'; const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { @@ -89,20 +89,20 @@ describe('gjirafaAdapterTest', () => { }); }); - it('bidRequest data', () => { + it('bidRequest data', function () { const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { expect(requestItem.data).to.exists; }); }); - it('bidRequest sizes', () => { + it('bidRequest sizes', function () { const requests = spec.buildRequests(bidRequests); expect(requests[0].data.sizes).to.equal('728x90;980x200;980x150;970x90;970x250'); expect(requests[1].data.sizes).to.equal('300x250'); }); - it('should add GDPR data', () => { + it('should add GDPR data', function () { const requests = spec.buildRequests(bidRequests); expect(requests[0].data.consent_string).to.exists; expect(requests[0].data.consent_required).to.exists; @@ -111,7 +111,7 @@ describe('gjirafaAdapterTest', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const bidRequest = { 'method': 'GET', 'url': 'https://gjc.gjirafa.com/Home/GetBid', @@ -143,7 +143,7 @@ describe('gjirafaAdapterTest', () => { headers: {} }; - it('all keys present', () => { + it('all keys present', function () { const result = spec.interpretResponse(bidResponse, bidRequest); let keys = [ diff --git a/test/spec/modules/gumgumBidAdapter_spec.js b/test/spec/modules/gumgumBidAdapter_spec.js index 8a59d61e2bc..0c1431b71a5 100644 --- a/test/spec/modules/gumgumBidAdapter_spec.js +++ b/test/spec/modules/gumgumBidAdapter_spec.js @@ -4,33 +4,33 @@ import { spec } from 'modules/gumgumBidAdapter'; const ENDPOINT = 'https://g2.gumgum.com/hbid/imp'; -describe('gumgumAdapter', () => { +describe('gumgumAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'gumgum', 'params': { 'inScreen': '10433394' }, 'adUnitCode': 'adunit-code', - 'sizes': [[300, 250], [300, 600]], + 'sizes': [[300, 250], [300, 600], [1, 1]], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when required params found', () => { + it('should return true when required params found', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -40,7 +40,7 @@ describe('gumgumAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -50,7 +50,7 @@ describe('gumgumAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'gumgum', @@ -63,20 +63,20 @@ describe('gumgumAdapter', () => { } ]; - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { const request = spec.buildRequests(bidRequests)[0]; expect(request.url).to.equal(ENDPOINT); expect(request.method).to.equal('GET'); expect(request.id).to.equal('30b31c1838de1e'); }); - it('should add consent parameters if gdprConsent is present', () => { + it('should add consent parameters if gdprConsent is present', function () { const gdprConsent = { consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', gdprApplies: true }; const fakeBidRequest = { gdprConsent: gdprConsent }; const bidRequest = spec.buildRequests(bidRequests, fakeBidRequest)[0]; expect(bidRequest.data.gdprApplies).to.eq(true); expect(bidRequest.data.gdprConsent).to.eq('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); }); - it('should handle gdprConsent is present but values are undefined case', () => { + it('should handle gdprConsent is present but values are undefined case', function () { const gdprConsent = { consent_string: undefined, gdprApplies: undefined }; const fakeBidRequest = { gdprConsent: gdprConsent }; const bidRequest = spec.buildRequests(bidRequests, fakeBidRequest)[0]; @@ -84,7 +84,7 @@ describe('gumgumAdapter', () => { }); }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { let serverResponse = { 'ad': { 'id': 29593, @@ -109,13 +109,13 @@ describe('gumgumAdapter', () => { } let bidRequest = { id: 12345, - sizes: [[300, 250]], + sizes: [[300, 250], [1, 1]], url: ENDPOINT, method: 'GET', pi: 3 } - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = { 'ad': '

I am an ad

', 'cpm': 0, @@ -132,7 +132,7 @@ describe('gumgumAdapter', () => { expect(spec.interpretResponse({ body: serverResponse }, bidRequest)).to.deep.equal([expectedResponse]); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = { 'ad': {}, 'pag': { @@ -146,8 +146,45 @@ describe('gumgumAdapter', () => { let result = spec.interpretResponse({ body: response }, bidRequest); expect(result.length).to.equal(0); }); + + it('returns 1x1 when eligible product and size available', function () { + let inscreenBidRequest = { + id: 12346, + sizes: [[300, 250], [1, 1]], + url: ENDPOINT, + method: 'GET', + data: { + pi: 2, + t: 'ggumtest' + } + } + let inscreenServerResponse = { + 'ad': { + 'id': 2065333, + 'height': 90, + 'ipd': 2000, + 'markup': '

I am an inscreen ad

', + 'ii': true, + 'du': null, + 'price': 1, + 'zi': 0, + 'impurl': 'http://g2.gumgum.com/ad/view', + 'clsurl': 'http://g2.gumgum.com/ad/close' + }, + 'pag': { + 't': 'ggumtest', + 'pvid': 'aa8bbb65-427f-4689-8cee-e3eed0b89eec', + 'css': 'html { overflow-y: auto }', + 'js': 'console.log("environment", env);' + }, + 'thms': 10000 + } + let result = spec.interpretResponse({ body: inscreenServerResponse }, inscreenBidRequest); + expect(result[0].width).to.equal('1'); + expect(result[0].height).to.equal('1'); + }) }) - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { const syncOptions = { 'iframeEnabled': 'true' } diff --git a/test/spec/modules/gxoneBidAdapter_spec.js b/test/spec/modules/gxoneBidAdapter_spec.js index f34f4358490..afeb2c781f5 100644 --- a/test/spec/modules/gxoneBidAdapter_spec.js +++ b/test/spec/modules/gxoneBidAdapter_spec.js @@ -5,13 +5,13 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('GXOne Adapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'gxone', 'params': { @@ -24,11 +24,11 @@ describe('GXOne Adapter', function () { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -38,7 +38,7 @@ describe('GXOne Adapter', function () { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { function parseRequest(url) { const res = {}; url.split('&').forEach((it) => { @@ -83,7 +83,7 @@ describe('GXOne Adapter', function () { } ]; - it('should attach valid params to the tag', () => { + it('should attach valid params to the tag', function () { const request = spec.buildRequests([bidRequests[0]]); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); @@ -92,7 +92,7 @@ describe('GXOne Adapter', function () { expect(payload).to.have.property('auids', '5'); }); - it('auids must not be duplicated', () => { + it('auids must not be duplicated', function () { const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); @@ -101,7 +101,7 @@ describe('GXOne Adapter', function () { expect(payload).to.have.property('auids', '5,6'); }); - it('pt parameter must be "gross" if params.priceType === "gross"', () => { + it('pt parameter must be "gross" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); @@ -112,7 +112,7 @@ describe('GXOne Adapter', function () { delete bidRequests[1].params.priceType; }); - it('pt parameter must be "net" or "gross"', () => { + it('pt parameter must be "net" or "gross"', function () { bidRequests[1].params.priceType = 'some'; const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); @@ -124,7 +124,7 @@ describe('GXOne Adapter', function () { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const responses = [ {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 4, 'h': 250, 'w': 300}], 'seat': '1'}, {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 5, 'h': 90, 'w': 728}], 'seat': '1'}, @@ -135,7 +135,7 @@ describe('GXOne Adapter', function () { {'seat': '1'}, ]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const bidRequests = [ { 'bidder': 'gxone', @@ -169,7 +169,7 @@ describe('GXOne Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should get correct multi bid response', () => { + it('should get correct multi bid response', function () { const bidRequests = [ { 'bidder': 'gxone', @@ -249,7 +249,7 @@ describe('GXOne Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('handles wrong and nobid responses', () => { + it('handles wrong and nobid responses', function () { const bidRequests = [ { 'bidder': 'gxone', diff --git a/test/spec/modules/huddledmassesBidAdapter_spec.js b/test/spec/modules/huddledmassesBidAdapter_spec.js index f98bc06d0da..7823ae53c12 100644 --- a/test/spec/modules/huddledmassesBidAdapter_spec.js +++ b/test/spec/modules/huddledmassesBidAdapter_spec.js @@ -1,7 +1,7 @@ import {expect} from 'chai'; import {spec} from '../../../modules/huddledmassesBidAdapter'; -describe('HuddledmassesAdapter', () => { +describe('HuddledmassesAdapter', function () { let bid = { bidId: '2dd581a2b6281d', bidder: 'huddledmasses', @@ -15,35 +15,35 @@ describe('HuddledmassesAdapter', () => { transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62' }; - describe('isBidRequestValid', () => { - it('Should return true when placement_id can be cast to a number, and when at least one of the sizes passed is allowed', () => { + describe('isBidRequestValid', function () { + it('Should return true when placement_id can be cast to a number, and when at least one of the sizes passed is allowed', function () { expect(spec.isBidRequestValid(bid)).to.be.true; }); - it('Should return false when placement_id is not a number', () => { + it('Should return false when placement_id is not a number', function () { bid.params.placement_id = 'aaa'; expect(spec.isBidRequestValid(bid)).to.be.false; }); - it('Should return false when the sizes are not allowed', () => { + it('Should return false when the sizes are not allowed', function () { bid.sizes = [[1, 1]]; expect(spec.isBidRequestValid(bid)).to.be.false; }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let serverRequest = spec.buildRequests([bid]); - it('Creates a ServerRequest object with method, URL and data', () => { + it('Creates a ServerRequest object with method, URL and data', function () { expect(serverRequest).to.exist; expect(serverRequest.method).to.exist; expect(serverRequest.url).to.exist; expect(serverRequest.data).to.exist; }); - it('Returns POST method', () => { + it('Returns POST method', function () { expect(serverRequest.method).to.equal('POST'); }); - it('Returns valid URL', () => { + it('Returns valid URL', function () { expect(serverRequest.url).to.equal('//huddledmassessupply.com/?c=o&m=multi'); }); - it('Returns valid data if array of bids is valid', () => { + it('Returns valid data if array of bids is valid', function () { let data = serverRequest.data; expect(data).to.be.an('object'); expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'language', 'secure', 'host', 'page', 'placements'); @@ -62,13 +62,13 @@ describe('HuddledmassesAdapter', () => { expect(placement.sizes).to.be.an('array'); } }); - it('Returns empty data if no valid requests are passed', () => { + it('Returns empty data if no valid requests are passed', function () { serverRequest = spec.buildRequests([]); let data = serverRequest.data; expect(data.placements).to.be.an('array').that.is.empty; }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let resObject = { body: [ { requestId: '123', @@ -83,7 +83,7 @@ describe('HuddledmassesAdapter', () => { } ] }; let serverResponses = spec.interpretResponse(resObject); - it('Returns an array of valid server responses if response object is valid', () => { + it('Returns an array of valid server responses if response object is valid', function () { expect(serverResponses).to.be.an('array').that.is.not.empty; for (let i = 0; i < serverResponses.length; i++) { let dataItem = serverResponses[i]; @@ -99,16 +99,16 @@ describe('HuddledmassesAdapter', () => { expect(dataItem.netRevenue).to.be.a('boolean'); expect(dataItem.currency).to.be.a('string'); } - it('Returns an empty array if invalid response is passed', () => { + it('Returns an empty array if invalid response is passed', function () { serverResponses = spec.interpretResponse('invalid_response'); expect(serverResponses).to.be.an('array').that.is.empty; }); }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { let userSync = spec.getUserSyncs(); - it('Returns valid URL and type', () => { + it('Returns valid URL and type', function () { expect(userSync).to.be.an('array').with.lengthOf(1); expect(userSync[0].type).to.exist; expect(userSync[0].url).to.exist; diff --git a/test/spec/modules/iasBidAdapter_spec.js b/test/spec/modules/iasBidAdapter_spec.js index 4f335ab22ba..21ef9f8e15a 100644 --- a/test/spec/modules/iasBidAdapter_spec.js +++ b/test/spec/modules/iasBidAdapter_spec.js @@ -1,15 +1,15 @@ import { expect } from 'chai'; import { spec } from 'modules/iasBidAdapter'; -describe('iasBidAdapter is an adapter that', () => { - it('has the correct bidder code', () => { +describe('iasBidAdapter is an adapter that', function () { + it('has the correct bidder code', function () { expect(spec.code).to.equal('ias'); }); - describe('has a method `isBidRequestValid` that', () => { - it('exists', () => { + describe('has a method `isBidRequestValid` that', function () { + it('exists', function () { expect(spec.isBidRequestValid).to.be.a('function'); }); - it('returns false if bid params misses `pubId`', () => { + it('returns false if bid params misses `pubId`', function () { expect(spec.isBidRequestValid( { params: { @@ -17,7 +17,7 @@ describe('iasBidAdapter is an adapter that', () => { } })).to.equal(false); }); - it('returns false if bid params misses `adUnitPath`', () => { + it('returns false if bid params misses `adUnitPath`', function () { expect(spec.isBidRequestValid( { params: { @@ -25,7 +25,7 @@ describe('iasBidAdapter is an adapter that', () => { } })).to.equal(false); }); - it('returns true otherwise', () => { + it('returns true otherwise', function () { expect(spec.isBidRequestValid( { params: { @@ -37,13 +37,13 @@ describe('iasBidAdapter is an adapter that', () => { }); }); - describe('has a method `buildRequests` that', () => { - it('exists', () => { + describe('has a method `buildRequests` that', function () { + it('exists', function () { expect(spec.buildRequests).to.be.a('function'); }); - describe('given bid requests, returns a `ServerRequest` instance that', () => { + describe('given bid requests, returns a `ServerRequest` instance that', function () { let bidRequests, IAS_HOST; - beforeEach(() => { + beforeEach(function () { IAS_HOST = '//pixel.adsafeprotected.com/services/pub'; bidRequests = [ { @@ -79,17 +79,20 @@ describe('iasBidAdapter is an adapter that', () => { } ]; }); - it('has property `method` of `GET`', () => { + it('has property `method` of `GET`', function () { expect(spec.buildRequests(bidRequests)).to.deep.include({ method: 'GET' }); }); - it('has property `url` to be the correct IAS endpoint', () => { + it('has property `url` to be the correct IAS endpoint', function () { expect(spec.buildRequests(bidRequests)).to.deep.include({ url: IAS_HOST }); }); - describe('has property `data` that is an encode query string containing information such as', () => { + it('only includes the first `bidRequest` as the bidRequest variable on a multiple slot request', function () { + expect(spec.buildRequests(bidRequests).bidRequest.adUnitCode).to.equal(bidRequests[0].adUnitCode); + }); + describe('has property `data` that is an encode query string containing information such as', function () { let val; const ANID_PARAM = 'anId'; const SLOT_PARAM = 'slot'; @@ -97,35 +100,70 @@ describe('iasBidAdapter is an adapter that', () => { const SLOT_SIZE_PARAM = 'ss'; const SLOT_AD_UNIT_PATH_PARAM = 'p'; - beforeEach(() => val = decodeURI(spec.buildRequests(bidRequests).data)); - it('publisher id', () => { + beforeEach(function () { + val = decodeURI(spec.buildRequests(bidRequests).data); + }); + it('publisher id', function () { expect(val).to.have.string(`${ANID_PARAM}=1234`); }); - it('ad slot`s id, size and ad unit path', () => { + it('ad slot`s id, size and ad unit path', function () { expect(val).to.have.string(`${SLOT_PARAM}={${SLOT_ID_PARAM}:one-div-id,${SLOT_SIZE_PARAM}:[10.20,300.400],${SLOT_AD_UNIT_PATH_PARAM}:/a/b/c}`); expect(val).to.have.string(`${SLOT_PARAM}={${SLOT_ID_PARAM}:two-div-id,${SLOT_SIZE_PARAM}:[50.60],${SLOT_AD_UNIT_PATH_PARAM}:/d/e/f}`); }); - it('window size', () => { + it('window size', function () { expect(val).to.match(/.*wr=[0-9]*\.[0-9]*/); }); - it('screen size', () => { + it('screen size', function () { expect(val).to.match(/.*sr=[0-9]*\.[0-9]*/); }); }); - it('has property `bidRequest` that is the first passed in bid request', () => { + it('has property `bidRequest` that is the first passed in bid request', function () { expect(spec.buildRequests(bidRequests)).to.deep.include({ bidRequest: bidRequests[0] }); }); }); }); - describe('has a method `interpretResponse` that', () => { - it('exists', () => { + describe('has a method `interpretResponse` that', function () { + it('exists', function () { expect(spec.interpretResponse).to.be.a('function'); }); - describe('returns a list of bid response that', () => { - let bidResponse, slots; - beforeEach(() => { + describe('returns a list of bid response that', function () { + let bidRequests, bidResponse, slots, serverResponse; + beforeEach(function () { + bidRequests = [ + { + adUnitCode: 'one-div-id', + auctionId: 'someAuctionId', + bidId: 'someBidId1', + bidder: 'ias', + bidderRequestId: 'someBidderRequestId', + params: { + pubId: '1234', + adUnitPath: '/a/b/c' + }, + sizes: [ + [10, 20], + [300, 400] + ], + transactionId: 'someTransactionId' + }, + { + adUnitCode: 'two-div-id', + auctionId: 'someAuctionId', + bidId: 'someBidId2', + bidder: 'ias', + bidderRequestId: 'someBidderRequestId', + params: { + pubId: '1234', + adUnitPath: '/d/e/f' + }, + sizes: [ + [50, 60] + ], + transactionId: 'someTransactionId' + } + ]; const request = { bidRequest: { bidId: '102938' @@ -140,7 +178,7 @@ describe('iasBidAdapter is an adapter that', () => { id: '5678', vw: ['80', '90'] }; - const serverResponse = { + serverResponse = { body: { brandSafety: { adt: 'adtVal', @@ -158,33 +196,38 @@ describe('iasBidAdapter is an adapter that', () => { }; bidResponse = spec.interpretResponse(serverResponse, request); }); - it('has IAS keyword `adt` as property', () => { + it('has IAS keyword `adt` as property', function () { expect(bidResponse[0]).to.deep.include({ adt: 'adtVal' }); }); - it('has IAS keyword `alc` as property', () => { + it('has IAS keyword `alc` as property', function () { expect(bidResponse[0]).to.deep.include({ alc: 'alcVal' }); }); - it('has IAS keyword `dlm` as property', () => { + it('has IAS keyword `dlm` as property', function () { expect(bidResponse[0]).to.deep.include({ dlm: 'dlmVal' }); }); - it('has IAS keyword `drg` as property', () => { + it('has IAS keyword `drg` as property', function () { expect(bidResponse[0]).to.deep.include({ drg: 'drgVal' }); }); - it('has IAS keyword `hat` as property', () => { + it('has IAS keyword `hat` as property', function () { expect(bidResponse[0]).to.deep.include({ hat: 'hatVal' }); }); - it('has IAS keyword `off` as property', () => { + it('has IAS keyword `off` as property', function () { expect(bidResponse[0]).to.deep.include({ off: 'offVal' }); }); - it('has IAS keyword `vio` as property', () => { + it('has IAS keyword `vio` as property', function () { expect(bidResponse[0]).to.deep.include({ vio: 'vioVal' }); }); - it('has IAS keyword `fr` as property', () => { + it('has IAS keyword `fr` as property', function () { expect(bidResponse[0]).to.deep.include({ fr: 'false' }); }); - it('has property `slots`', () => { + it('has property `slots`', function () { expect(bidResponse[0]).to.deep.include({ slots: slots }); }); + it('response is the same for multiple slots', function () { + var adapter = spec; + var requests = adapter.buildRequests(bidRequests); + expect(adapter.interpretResponse(serverResponse, requests)).to.length(2); + }); }); }); }); diff --git a/test/spec/modules/improvedigitalBidAdapter_spec.js b/test/spec/modules/improvedigitalBidAdapter_spec.js index d7595934194..bab469b936e 100644 --- a/test/spec/modules/improvedigitalBidAdapter_spec.js +++ b/test/spec/modules/improvedigitalBidAdapter_spec.js @@ -40,22 +40,22 @@ describe('Improve Digital Adapter Tests', function () { }, }; - describe('isBidRequestValid', () => { - it('should return false when no bid', () => { + describe('isBidRequestValid', function () { + it('should return false when no bid', function () { expect(spec.isBidRequestValid()).to.equal(false); }); - it('should return false when no bid.params', () => { + it('should return false when no bid.params', function () { let bid = {}; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when both placementId and placementKey + publisherId are missing', () => { + it('should return false when both placementId and placementKey + publisherId are missing', function () { let bid = { 'params': {} }; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when only one of placementKey and publisherId is present', () => { + it('should return false when only one of placementKey and publisherId is present', function () { let bid = { params: { publisherId: 1234 @@ -70,19 +70,19 @@ describe('Improve Digital Adapter Tests', function () { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return true when placementId is passed', () => { + it('should return true when placementId is passed', function () { let bid = { 'params': {} }; expect(spec.isBidRequestValid(simpleBidRequest)).to.equal(true); }); - it('should return true when both placementKey and publisherId are passed', () => { + it('should return true when both placementKey and publisherId are passed', function () { let bid = { 'params': {} }; expect(spec.isBidRequestValid(simpleSmartTagBidRequest)).to.equal(true); }); }); - describe('buildRequests', () => { - it('should make a well-formed request objects', () => { + describe('buildRequests', function () { + it('should make a well-formed request objects', function () { const requests = spec.buildRequests([simpleBidRequest]); expect(requests).to.be.an('array'); expect(requests.length).to.equal(1); @@ -106,14 +106,14 @@ describe('Improve Digital Adapter Tests', function () { ]); }); - it('should set placementKey and publisherId for smart tags', () => { + it('should set placementKey and publisherId for smart tags', function () { const requests = spec.buildRequests([simpleSmartTagBidRequest]); const params = JSON.parse(requests[0].data.substring(PARAM_PREFIX.length)); expect(params.bid_request.imp[0].pubid).to.equal(1032); expect(params.bid_request.imp[0].pkey).to.equal('data_team_test_hb_smoke_test'); }); - it('should add keyValues', () => { + it('should add keyValues', function () { let bidRequest = Object.assign({}, simpleBidRequest); const keyValues = { testKey: [ @@ -126,7 +126,7 @@ describe('Improve Digital Adapter Tests', function () { expect(params.bid_request.imp[0].kvw).to.deep.equal(keyValues); }); - it('should add size', () => { + it('should add size', function () { let bidRequest = Object.assign({}, simpleBidRequest); const size = { w: 800, @@ -138,7 +138,7 @@ describe('Improve Digital Adapter Tests', function () { expect(params.bid_request.imp[0].banner).to.deep.equal(size); }); - it('should add currency', () => { + it('should add currency', function () { const bidRequest = Object.assign({}, simpleBidRequest); const getConfigStub = sinon.stub(config, 'getConfig').returns('JPY'); const request = spec.buildRequests([bidRequest])[0]; @@ -147,14 +147,14 @@ describe('Improve Digital Adapter Tests', function () { getConfigStub.restore(); }); - it('should add GDPR consent string', () => { + it('should add GDPR consent string', function () { const bidRequest = Object.assign({}, simpleBidRequest); const request = spec.buildRequests([bidRequest], bidderRequest)[0]; const params = JSON.parse(request.data.substring(PARAM_PREFIX.length)); expect(params.bid_request.gdpr).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); }); - it('should return 2 requests', () => { + it('should return 2 requests', function () { const requests = spec.buildRequests([ simpleBidRequest, simpleSmartTagBidRequest @@ -164,61 +164,61 @@ describe('Improve Digital Adapter Tests', function () { }); }); - describe('interpretResponse', () => { - const serverResponse = { - 'body': { - 'id': '687a06c541d8d1', - 'site_id': 191642, - 'bid': [ - { - 'isNet': false, - 'id': '33e9500b21129f', - 'advid': '5279', - 'price': 1.45888594164456, - 'nurl': 'http://ad.360yield.com/imp_pixel?ic=wVmhKI07hCVyGC1sNdFp.6buOSiGYOw8jPyZLlcMY2RCwD4ek3Fy6.xUI7U002skGBs3objMBoNU-Frpvmb9js3NKIG0YZJgWaNdcpXY9gOXE9hY4-wxybCjVSNzhOQB-zic73hzcnJnKeoGgcfvt8fMy18-yD0aVdYWt4zbqdoITOkKNCPBEgbPFu1rcje-o7a64yZ7H3dKvtnIixXQYc1Ep86xGSBGXY6xW2KfUOMT6vnkemxO72divMkMdhR8cAuqIubbx-ZID8-xf5c9k7p6DseeBW0I8ionrlTHx.rGosgxhiFaMqtr7HiA7PBzKvPdeEYN0hQ8RYo8JzYL82hA91A3V2m9Ij6y0DfIJnnrKN8YORffhxmJ6DzwEl1zjrVFbD01bqB3Vdww8w8PQJSkKQkd313tr-atU8LS26fnBmOngEkVHwAr2WCKxuUvxHmuVBTA-Lgz7wKwMoOJCA3hFxMavVb0ZFB7CK0BUTVU6z0De92Q.FJKNCHLMbjX3vcAQ90=', - 'h': 290, - 'pid': 1053688, - 'sync': [ - 'http://link1', - 'http://link2' - ], - 'crid': '422031', - 'w': 600, - 'cid': '99006', - 'adm': 'document.writeln(\"
\\\"\\\"\\/<\\/a>\");document.writeln(\"<\\/improvedigital_ad_output_information>\");' - } - ], - 'debug': '' - } - }; - - const serverResponseTwoBids = { - 'body': { - 'id': '687a06c541d8d1', - 'site_id': 191642, - 'bid': [ - serverResponse.body.bid[0], - { - 'isNet': true, - 'id': '1234', - 'advid': '5280', - 'price': 1.23, - 'nurl': 'http://link/imp_pixel?ic=wVmhKI07hCVyGC1sNdFp.6buOSiGYOw8jPyZLlcMY2RCwD4ek3Fy6.xUI7U002skGBs3objMBoNU-Frpvmb9js3NKIG0YZJgWaNdcpXY9gOXE9hY4-wxybCjVSNzhOQB-zic73hzcnJnKeoGgcfvt8fMy18-yD0aVdYWt4zbqdoITOkKNCPBEgbPFu1rcje-o7a64yZ7H3dKvtnIixXQYc1Ep86xGSBGXY6xW2KfUOMT6vnkemxO72divMkMdhR8cAuqIubbx-ZID8-xf5c9k7p6DseeBW0I8ionrlTHx.rGosgxhiFaMqtr7HiA7PBzKvPdeEYN0hQ8RYo8JzYL82hA91A3V2m9Ij6y0DfIJnnrKN8YORffhxmJ6DzwEl1zjrVFbD01bqB3Vdww8w8PQJSkKQkd313tr-atU8LS26fnBmOngEkVHwAr2WCKxuUvxHmuVBTA-Lgz7wKwMoOJCA3hFxMavVb0ZFB7CK0BUTVU6z0De92Q.FJKNCHLMbjX3vcAQ90=', - 'h': 400, - 'pid': 1053688, - 'sync': [ - 'http://link3' - ], - 'crid': '422033', - 'w': 700, - 'cid': '99006', - 'adm': 'document.writeln(\"\\\"\\\"\\/<\\/a>\");document.writeln(\"<\\/improvedigital_ad_output_information>\");' - } - ], - 'debug': '' - } - }; + const serverResponse = { + 'body': { + 'id': '687a06c541d8d1', + 'site_id': 191642, + 'bid': [ + { + 'isNet': false, + 'id': '33e9500b21129f', + 'advid': '5279', + 'price': 1.45888594164456, + 'nurl': 'http://ad.360yield.com/imp_pixel?ic=wVmhKI07hCVyGC1sNdFp.6buOSiGYOw8jPyZLlcMY2RCwD4ek3Fy6.xUI7U002skGBs3objMBoNU-Frpvmb9js3NKIG0YZJgWaNdcpXY9gOXE9hY4-wxybCjVSNzhOQB-zic73hzcnJnKeoGgcfvt8fMy18-yD0aVdYWt4zbqdoITOkKNCPBEgbPFu1rcje-o7a64yZ7H3dKvtnIixXQYc1Ep86xGSBGXY6xW2KfUOMT6vnkemxO72divMkMdhR8cAuqIubbx-ZID8-xf5c9k7p6DseeBW0I8ionrlTHx.rGosgxhiFaMqtr7HiA7PBzKvPdeEYN0hQ8RYo8JzYL82hA91A3V2m9Ij6y0DfIJnnrKN8YORffhxmJ6DzwEl1zjrVFbD01bqB3Vdww8w8PQJSkKQkd313tr-atU8LS26fnBmOngEkVHwAr2WCKxuUvxHmuVBTA-Lgz7wKwMoOJCA3hFxMavVb0ZFB7CK0BUTVU6z0De92Q.FJKNCHLMbjX3vcAQ90=', + 'h': 290, + 'pid': 1053688, + 'sync': [ + 'http://link1', + 'http://link2' + ], + 'crid': '422031', + 'w': 600, + 'cid': '99006', + 'adm': 'document.writeln(\"\\\"\\\"\\/<\\/a>\");document.writeln(\"<\\/improvedigital_ad_output_information>\");' + } + ], + 'debug': '' + } + }; + + const serverResponseTwoBids = { + 'body': { + 'id': '687a06c541d8d1', + 'site_id': 191642, + 'bid': [ + serverResponse.body.bid[0], + { + 'isNet': true, + 'id': '1234', + 'advid': '5280', + 'price': 1.23, + 'nurl': 'http://link/imp_pixel?ic=wVmhKI07hCVyGC1sNdFp.6buOSiGYOw8jPyZLlcMY2RCwD4ek3Fy6.xUI7U002skGBs3objMBoNU-Frpvmb9js3NKIG0YZJgWaNdcpXY9gOXE9hY4-wxybCjVSNzhOQB-zic73hzcnJnKeoGgcfvt8fMy18-yD0aVdYWt4zbqdoITOkKNCPBEgbPFu1rcje-o7a64yZ7H3dKvtnIixXQYc1Ep86xGSBGXY6xW2KfUOMT6vnkemxO72divMkMdhR8cAuqIubbx-ZID8-xf5c9k7p6DseeBW0I8ionrlTHx.rGosgxhiFaMqtr7HiA7PBzKvPdeEYN0hQ8RYo8JzYL82hA91A3V2m9Ij6y0DfIJnnrKN8YORffhxmJ6DzwEl1zjrVFbD01bqB3Vdww8w8PQJSkKQkd313tr-atU8LS26fnBmOngEkVHwAr2WCKxuUvxHmuVBTA-Lgz7wKwMoOJCA3hFxMavVb0ZFB7CK0BUTVU6z0De92Q.FJKNCHLMbjX3vcAQ90=', + 'h': 400, + 'pid': 1053688, + 'sync': [ + 'http://link3' + ], + 'crid': '422033', + 'w': 700, + 'cid': '99006', + 'adm': 'document.writeln(\"\\\"\\\"\\/<\\/a>\");document.writeln(\"<\\/improvedigital_ad_output_information>\");' + } + ], + 'debug': '' + } + }; + describe('interpretResponse', function () { let expectedBid = [ { 'ad': '', @@ -250,25 +250,17 @@ describe('Improve Digital Adapter Tests', function () { } ]; - it('should return a well-formed bid', () => { + it('should return a well-formed bid', function () { const bids = spec.interpretResponse(serverResponse); expect(bids).to.deep.equal(expectedBid); }); - it('should return two bids', () => { + it('should return two bids', function () { const bids = spec.interpretResponse(serverResponseTwoBids); expect(bids).to.deep.equal(expectedTwoBids); }); - it('should register user syncs', () => { - const registerSyncSpy = sinon.spy(userSync, 'registerSync'); - const bids = spec.interpretResponse(serverResponse); - expect(registerSyncSpy.withArgs('image', 'improvedigital', 'http://link1').calledOnce).to.equal(true); - expect(registerSyncSpy.withArgs('image', 'improvedigital', 'http://link2').calledOnce).to.equal(true); - registerSyncSpy.restore(); - }); - - it('should set dealId correctly', () => { + it('should set dealId correctly', function () { let response = JSON.parse(JSON.stringify(serverResponse)); let bids; @@ -287,14 +279,14 @@ describe('Improve Digital Adapter Tests', function () { expect(bids[0].dealId).to.equal(268515); }); - it('should set currency', () => { + it('should set currency', function () { let response = JSON.parse(JSON.stringify(serverResponse)); response.body.bid[0].currency = 'eur'; const bids = spec.interpretResponse(response); expect(bids[0].currency).to.equal('EUR'); }); - it('should return empty array for bad response or no price', () => { + it('should return empty array for bad response or no price', function () { let response = JSON.parse(JSON.stringify(serverResponse)); let bids; @@ -331,11 +323,30 @@ describe('Improve Digital Adapter Tests', function () { expect(bids).to.deep.equal([]); }); - it('should set netRevenue', () => { + it('should set netRevenue', function () { let response = JSON.parse(JSON.stringify(serverResponse)); response.body.bid[0].isNet = true; const bids = spec.interpretResponse(response); expect(bids[0].netRevenue).to.equal(true); }); }); + + describe('getUserSyncs', function () { + const serverResponses = [ serverResponseTwoBids ]; + + it('should return no syncs when pixel syncing is disabled', function () { + const syncs = spec.getUserSyncs({ pixelEnabled: false }, serverResponses); + expect(syncs).to.deep.equal([]); + }); + + it('should return user syncs', function () { + const syncs = spec.getUserSyncs({ pixelEnabled: true }, serverResponses); + const expected = [ + { type: 'image', url: 'http://link1' }, + { type: 'image', url: 'http://link2' }, + { type: 'image', url: 'http://link3' } + ]; + expect(syncs).to.deep.equal(expected); + }); + }); }); diff --git a/test/spec/modules/innityBidAdapter_spec.js b/test/spec/modules/innityBidAdapter_spec.js index 87042ca6a6d..0132f093ca1 100644 --- a/test/spec/modules/innityBidAdapter_spec.js +++ b/test/spec/modules/innityBidAdapter_spec.js @@ -1,9 +1,9 @@ import { expect } from 'chai'; import { spec } from 'modules/innityBidAdapter'; -describe('innityAdapterTest', () => { - describe('bidRequestValidity', () => { - it('bidRequest with pub ID and zone ID param', () => { +describe('innityAdapterTest', function () { + describe('bidRequestValidity', function () { + it('bidRequest with pub ID and zone ID param', function () { expect(spec.isBidRequestValid({ bidder: 'innity', params: { @@ -13,7 +13,7 @@ describe('innityAdapterTest', () => { })).to.equal(true); }); - it('bidRequest with no required params', () => { + it('bidRequest with no required params', function () { expect(spec.isBidRequestValid({ bidder: 'innity', params: { @@ -22,7 +22,7 @@ describe('innityAdapterTest', () => { }); }); - describe('bidRequest', () => { + describe('bidRequest', function () { const bidRequests = [{ 'bidder': 'innity', 'params': { @@ -37,14 +37,14 @@ describe('innityAdapterTest', () => { 'auctionId': '18fd8b8b0bd757' }]; - it('bidRequest HTTP method', () => { + it('bidRequest HTTP method', function () { const requests = spec.buildRequests(bidRequests); requests.forEach(function(requestItem) { expect(requestItem.method).to.equal('GET'); }); }); - it('bidRequest data', () => { + it('bidRequest data', function () { const requests = spec.buildRequests(bidRequests); expect(requests[0].data.pub).to.equal(267); expect(requests[0].data.zone).to.equal(62546); @@ -54,7 +54,7 @@ describe('innityAdapterTest', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const bidRequest = { 'method': 'GET', 'url': 'https://as.innity.com/synd/?', @@ -85,7 +85,7 @@ describe('innityAdapterTest', () => { headers: {} }; - it('result is correct', () => { + it('result is correct', function () { const result = spec.interpretResponse(bidResponse, bidRequest); expect(result[0].requestId).to.equal('51ef8751f9aead'); expect(result[0].cpm).to.equal(1); diff --git a/test/spec/modules/inskinBidAdapter_spec.js b/test/spec/modules/inskinBidAdapter_spec.js index 40a84525ffa..24ae9321954 100644 --- a/test/spec/modules/inskinBidAdapter_spec.js +++ b/test/spec/modules/inskinBidAdapter_spec.js @@ -99,11 +99,11 @@ const RESPONSE = { } }; -describe('InSkin BidAdapter', () => { +describe('InSkin BidAdapter', function () { let bidRequests; let adapter = spec; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { bidder: 'inskin', @@ -121,8 +121,8 @@ describe('InSkin BidAdapter', () => { ]; }); - describe('bid request validation', () => { - it('should accept valid bid requests', () => { + describe('bid request validation', function () { + it('should accept valid bid requests', function () { let bid = { bidder: 'inskin', params: { @@ -133,7 +133,7 @@ describe('InSkin BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should accept valid bid requests with extra fields', () => { + it('should accept valid bid requests with extra fields', function () { let bid = { bidder: 'inskin', params: { @@ -145,7 +145,7 @@ describe('InSkin BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should reject bid requests without siteId', () => { + it('should reject bid requests without siteId', function () { let bid = { bidder: 'inskin', params: { @@ -155,7 +155,7 @@ describe('InSkin BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should reject bid requests without networkId', () => { + it('should reject bid requests without networkId', function () { let bid = { bidder: 'inskin', params: { @@ -166,31 +166,31 @@ describe('InSkin BidAdapter', () => { }); }); - describe('buildRequests validation', () => { - it('creates request data', () => { + describe('buildRequests validation', function () { + it('creates request data', function () { let request = spec.buildRequests(bidRequests); expect(request).to.exist.and.to.be.a('object'); }); - it('request to inskin should contain a url', () => { + it('request to inskin should contain a url', function () { let request = spec.buildRequests(bidRequests); expect(request.url).to.have.string('inskinad.com'); }); - it('requires valid bids to make request', () => { + it('requires valid bids to make request', function () { let request = spec.buildRequests([]); expect(request.bidRequest).to.be.empty; }); - it('sends bid request to ENDPOINT via POST', () => { + it('sends bid request to ENDPOINT via POST', function () { let request = spec.buildRequests(bidRequests); expect(request.method).to.have.string('POST'); }); - it('should add gdpr consent information to the request', () => { + it('should add gdpr consent information to the request', function () { let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; let bidderRequest = { 'bidderCode': 'inskin', @@ -210,21 +210,21 @@ describe('InSkin BidAdapter', () => { expect(payload.consent.gdprConsentRequired).to.exist.and.to.be.true; }); }); - describe('interpretResponse validation', () => { - it('response should have valid bidderCode', () => { + describe('interpretResponse validation', function () { + it('response should have valid bidderCode', function () { let bidRequest = spec.buildRequests(REQUEST.bidRequest); let bid = bidFactory.createBid(1, bidRequest.bidRequest[0]); expect(bid.bidderCode).to.equal('inskin'); }); - it('response should include objects for all bids', () => { + it('response should include objects for all bids', function () { let bids = spec.interpretResponse(RESPONSE, REQUEST); expect(bids.length).to.equal(2); }); - it('registers bids', () => { + it('registers bids', function () { let bids = spec.interpretResponse(RESPONSE, REQUEST); bids.forEach(b => { expect(b).to.have.property('cpm'); @@ -242,34 +242,34 @@ describe('InSkin BidAdapter', () => { }); }); - it('handles nobid responses', () => { + 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', () => { + it('handles no server response', function () { let bids = spec.interpretResponse(null, REQUEST); expect(bids).to.be.empty; }); }); - describe('getUserSyncs', () => { - it('handles empty sync options', () => { + 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', () => { + 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', () => { + 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); diff --git a/test/spec/modules/interactiveOffersBidAdapter_spec.js b/test/spec/modules/interactiveOffersBidAdapter_spec.js new file mode 100644 index 00000000000..8921a302738 --- /dev/null +++ b/test/spec/modules/interactiveOffersBidAdapter_spec.js @@ -0,0 +1,177 @@ +import {expect} from 'chai'; +import {spec} from 'modules/interactiveOffersBidAdapter'; + +describe('interactiveOffers adapter', function () { + describe('implementation', function () { + describe('for requests', function () { + it('should accept valid bid', function () { + let validBid = { + bidder: 'interactiveOffers', + params: { + pubId: '42' + } + }, + isValid = spec.isBidRequestValid(validBid); + + expect(isValid).to.equal(true); + }); + + it('should reject invalid bid', function () { + let invalidBid = { + bidder: 'interactiveOffers' + }, + isValid = spec.isBidRequestValid(invalidBid); + + expect(isValid).to.equal(false); + }); + }); + describe('for requests', function () { + it('should accept valid bid with optional params', function () { + let validBid = { + bidder: 'interactiveOffers', + params: { + pubId: '42', + loc: 'http://test.com/prebid', + tmax: 1500 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + + let buildRequest = spec.buildRequests([validBid])[0]; + let requestUrlCustomParams = buildRequest.data; + expect(requestUrlCustomParams).have.property('loc', 'http://test.com/prebid'); + expect(requestUrlCustomParams).have.property('tmax', 1500); + }); + + it('should accept valid bid without optional params', function () { + let validBid = { + bidder: 'interactiveOffers', + params: { + pubId: '42' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + + let buildRequest = spec.buildRequests([validBid])[0]; + let requestUrlCustomParams = buildRequest.data; + expect(requestUrlCustomParams).have.property('loc'); + expect(requestUrlCustomParams).have.property('tmax'); + }); + + it('should reject invalid bid without pubId', function () { + let invalidBid = { + bidder: 'interactiveOffers', + params: {} + }, + isValid = spec.isBidRequestValid(invalidBid); + + expect(isValid).to.equal(false); + }); + }); + describe('bid responses', function () { + it('should return complete bid response', function () { + let serverResponse = { + body: { + 'success': 'true', + 'message': 'Request Valid', + 'payloadData': { + bidId: '3842b02f7ec0fd', + cpm: 0.5, + width: 300, + height: 600, + ad: '
...
', + } + } + }; + + let bidRequests = [ + { + bidder: 'interactiveOffers', + params: { + pubId: '42' + } + } + ]; + let bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + expect(bids).to.be.lengthOf(1); + expect(bids[0].cpm).to.equal(0.5); + expect(bids[0].width).to.equal(300); + expect(bids[0].height).to.equal(600); + expect(bids[0].currency).to.equal('USD'); + expect(bids[0].netRevenue).to.equal(true); + expect(bids[0].ad).to.have.length.above(1); + }); + + it('should return empty bid response', function () { + let bidRequests = [ + { + bidder: 'interactiveOffers', + params: { + pubId: '42' + } + } + ]; + let serverResponse = { + body: { + 'success': 'true', + 'message': 'Request Valid', + 'payloadData': { + bidId: '3842b02f7ec0fd', + cpm: 0 + } + } + }, + bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + + expect(bids).to.be.lengthOf(0); + }); + + it('should return empty bid response with error', function () { + let bidRequests = [ + { + bidder: 'interactiveOffers', + params: { + pubId: '42' + } + } + ]; + let serverResponse = {body: {'success': 'false', 'message': 'Request Error'}}, + bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + + expect(bids).to.be.lengthOf(0); + }); + + it('should return empty bid response without payload', function () { + let bidRequests = [ + { + bidder: 'interactiveOffers', + params: { + pubId: '42' + } + } + ]; + let serverResponse = {body: {'success': 'true', 'message': 'Empty Payload', 'payloadData': []}}, + bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + + expect(bids).to.be.lengthOf(0); + }); + + it('should return empty bid response on empty body', function () { + let bidRequests = [ + { + bidder: 'interactiveOffers', + params: { + pubId: '42' + } + } + ]; + let serverResponse, + bids = spec.interpretResponse(serverResponse, {'bidRequest': bidRequests[0]}); + + expect(bids).to.be.lengthOf(0); + }); + }); + }); +}); diff --git a/test/spec/modules/invibesBidAdapter_spec.js b/test/spec/modules/invibesBidAdapter_spec.js index f6f601e0efc..d0fa627929e 100644 --- a/test/spec/modules/invibesBidAdapter_spec.js +++ b/test/spec/modules/invibesBidAdapter_spec.js @@ -86,19 +86,19 @@ describe('invibesBidAdapter:', function () { }); }); - describe('buildRequests', () => { - it('sends bid request to ENDPOINT via GET', () => { + describe('buildRequests', function () { + it('sends bid request to ENDPOINT via GET', function () { const request = spec.buildRequests(bidRequests); expect(request.url).to.equal(ENDPOINT); expect(request.method).to.equal('GET'); }); - it('sends cookies with the bid request', () => { + it('sends cookies with the bid request', function () { const request = spec.buildRequests(bidRequests); expect(request.options.withCredentials).to.equal(true); }); - it('has location, html id, placement and width/height', () => { + it('has location, html id, placement and width/height', function () { const request = spec.buildRequests(bidRequests, { auctionStart: Date.now() }); const parsedData = request.data; expect(parsedData.location).to.exist; @@ -108,53 +108,53 @@ describe('invibesBidAdapter:', function () { expect(parsedData.height).to.exist; }); - it('sends all Placement Ids', () => { + it('sends all Placement Ids', function () { const request = spec.buildRequests(bidRequests); expect(JSON.parse(request.data.bidParamsJson).placementIds).to.contain(bidRequests[0].params.placementId); expect(JSON.parse(request.data.bidParamsJson).placementIds).to.contain(bidRequests[1].params.placementId); }); - it('uses cookies', () => { + it('uses cookies', function () { global.document.cookie = 'ivNoCookie=1'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.be.undefined; }); - it('doesnt send the domain id if not graduated', () => { + it('doesnt send the domain id if not graduated', function () { global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":1522929537626,"hc":1}'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.not.exist; }); - it('graduate and send the domain id', () => { + it('graduate and send the domain id', function () { top.window.invibes.optIn = 1; global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":1521818537626,"hc":7}'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.exist; }); - it('send the domain id if already graduated', () => { + it('send the domain id if already graduated', function () { top.window.invibes.optIn = 1; global.document.cookie = 'ivbsdid={"id":"f8zoh044p9oi"}'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.exist; }); - it('send the domain id after replacing it with new format', () => { + it('send the domain id after replacing it with new format', function () { top.window.invibes.optIn = 1; global.document.cookie = 'ivbsdid={"id":"f8zoh044p9oi.8537626"}'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.exist; }); - it('try to graduate but not enough count - doesnt send the domain id', () => { + it('try to graduate but not enough count - doesnt send the domain id', function () { top.window.invibes.optIn = 1; global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":1521818537626,"hc":5}'; let request = spec.buildRequests(bidRequests); expect(request.data.lId).to.not.exist; }); - it('try to graduate but not old enough - doesnt send the domain id', () => { + it('try to graduate but not old enough - doesnt send the domain id', function () { top.window.invibes.optIn = 1; global.document.cookie = 'ivbsdid={"id":"dvdjkams6nkq","cr":' + Date.now() + ',"hc":5}'; let request = spec.buildRequests(bidRequests); @@ -194,55 +194,55 @@ describe('invibesBidAdapter:', function () { }]; context('when the response is not valid', function () { - it('handles response with no bids requested', () => { + it('handles response with no bids requested', function () { let emptyResult = spec.interpretResponse({ body: response }); expect(emptyResult).to.be.empty; }); - it('handles empty response', () => { + it('handles empty response', function () { let emptyResult = spec.interpretResponse(null, { bidRequests }); expect(emptyResult).to.be.empty; }); - it('handles response with bidding is not configured', () => { + it('handles response with bidding is not configured', function () { let emptyResult = spec.interpretResponse({ body: { Ads: [{ BidPrice: 1 }] } }, { bidRequests }); expect(emptyResult).to.be.empty; }); - it('handles response with no ads are received', () => { + it('handles response with no ads are received', function () { let emptyResult = spec.interpretResponse({ body: { BidModel: { PlacementId: '12345' }, AdReason: 'No ads' } }, { bidRequests }); expect(emptyResult).to.be.empty; }); - it('handles response with no ads are received - no ad reason', () => { + it('handles response with no ads are received - no ad reason', function () { let emptyResult = spec.interpretResponse({ body: { BidModel: { PlacementId: '12345' } } }, { bidRequests }); expect(emptyResult).to.be.empty; }); - it('handles response when no placement Id matches', () => { + it('handles response when no placement Id matches', function () { let emptyResult = spec.interpretResponse({ body: { BidModel: { PlacementId: '123456' }, Ads: [{ BidPrice: 1 }] } }, { bidRequests }); expect(emptyResult).to.be.empty; }); - it('handles response when placement Id is not present', () => { + it('handles response when placement Id is not present', function () { let emptyResult = spec.interpretResponse({ BidModel: { }, Ads: [{ BidPrice: 1 }] }, { bidRequests }); expect(emptyResult).to.be.empty; }); }); context('when the response is valid', function () { - it('responds with a valid bid', () => { + it('responds with a valid bid', function () { let result = spec.interpretResponse({ body: response }, { bidRequests }); expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('responds with a valid bid and uses logger', () => { + it('responds with a valid bid and uses logger', function () { localStorage.InvibesDEBUG = true; let result = spec.interpretResponse({ body: response }, { bidRequests }); expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('does not make multiple bids', () => { + it('does not make multiple bids', function () { localStorage.InvibesDEBUG = false; let result = spec.interpretResponse({ body: response }, { bidRequests }); let secondResult = spec.interpretResponse({ body: response }, { bidRequests }); @@ -252,13 +252,13 @@ describe('invibesBidAdapter:', function () { }); describe('getUserSyncs', function () { - it('returns an iframe if enabled', () => { + it('returns an iframe if enabled', function () { let response = spec.getUserSyncs({iframeEnabled: true}); expect(response.type).to.equal('iframe'); expect(response.url).to.include(SYNC_ENDPOINT); }); - it('returns an iframe with params if enabled', () => { + it('returns an iframe with params if enabled', function () { top.window.invibes.optIn = 1; global.document.cookie = 'ivvbks=17639.0,1,2'; let response = spec.getUserSyncs({ iframeEnabled: true }); @@ -269,7 +269,7 @@ describe('invibesBidAdapter:', function () { expect(response.url).to.include('ivbsdid'); }); - it('returns undefined if iframe not enabled ', () => { + it('returns undefined if iframe not enabled ', function () { let response = spec.getUserSyncs({ iframeEnabled: false }); expect(response).to.equal(undefined); }); diff --git a/test/spec/modules/iqmBidAdapter_spec.js b/test/spec/modules/iqmBidAdapter_spec.js index 8958a4dfc45..5535c52af9b 100644 --- a/test/spec/modules/iqmBidAdapter_spec.js +++ b/test/spec/modules/iqmBidAdapter_spec.js @@ -2,7 +2,7 @@ import {expect} from 'chai'; import {spec} from 'modules/iqmBidAdapter' import * as utils from 'src/utils'; -describe('iqmBidAdapter', () => { +describe('iqmBidAdapter', function () { const ENDPOINT_URL = 'https://pbd.bids.iqm.com'; const bidRequests = [{ bidder: 'iqm', @@ -80,15 +80,15 @@ describe('iqmBidAdapter', () => { headers: {} }; - describe('Request verification', () => { - it('basic property verification', () => { + describe('Request verification', function () { + it('basic property verification', function () { expect(spec.code).to.equal('iqm'); expect(spec.aliases).to.be.an('array'); // expect(spec.aliases).to.be.ofSize(1); expect(spec.aliases).to.have.lengthOf(1); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'iqm', 'params': { @@ -103,17 +103,17 @@ describe('iqmBidAdapter', () => { 'auctionId': '1d1a030790a475' }; - it('should return false for empty object', () => { + it('should return false for empty object', function () { expect(spec.isBidRequestValid({})).to.equal(false); }); - it('should return false for request without param', () => { + it('should return false for request without param', function () { let bid = Object.assign({}, bid); delete bid.params; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false for invalid params', () => { + it('should return false for invalid params', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -122,13 +122,13 @@ describe('iqmBidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return true for proper request', () => { + it('should return true for proper request', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); }); - describe('buildRequests', () => { - it('sends every bid request to ENDPOINT_URL via POST method', () => { + describe('buildRequests', function () { + it('sends every bid request to ENDPOINT_URL via POST method', function () { const requests = spec.buildRequests(bidRequests); expect(requests[0].method).to.equal('POST'); expect(requests[0].url).to.equal(ENDPOINT_URL); @@ -136,7 +136,7 @@ describe('iqmBidAdapter', () => { // expect(requests[1].url).to.equal(ENDPOINT_URL); }); - it('should send request data with every request', () => { + it('should send request data with every request', function () { const requests = spec.buildRequests(bidRequests); const data = requests[0].data; expect(data.id).to.equal(bidRequests[0].requestId); @@ -175,31 +175,31 @@ describe('iqmBidAdapter', () => { }); }); - describe('interpretResponse', () => { - it('should handle no bid response', () => { + describe('interpretResponse', function () { + it('should handle no bid response', function () { const response = spec.interpretResponse({ body: null }, { bidRequests }); expect(response.length).to.equal(0); }); - it('should have at least one Seat Object', () => { + it('should have at least one Seat Object', function () { const request = spec.buildRequests(bidRequests); const response = spec.interpretResponse(bidResponseEmptySeat, request); expect(response.length).to.equal(0); }); - it('should have at least one Bid Object', () => { + it('should have at least one Bid Object', function () { const request = spec.buildRequests(bidRequests); const response = spec.interpretResponse(bidResponseEmptyBid, request); expect(response.length).to.equal(0); }); - it('should have impId in Bid Object', () => { + it('should have impId in Bid Object', function () { const request = spec.buildRequests(bidRequests); const response = spec.interpretResponse(bidResponseNoImpId, request); expect(response.length).to.equal(0); }); - it('should handle valid response', () => { + it('should handle valid response', function () { const request = spec.buildRequests(bidRequests); const response = spec.interpretResponse(bidResponses, request); expect(response).to.be.an('array').to.have.lengthOf(1); diff --git a/test/spec/modules/ixBidAdapter_spec.js b/test/spec/modules/ixBidAdapter_spec.js index 0e00a64aab4..8e0df9959ef 100644 --- a/test/spec/modules/ixBidAdapter_spec.js +++ b/test/spec/modules/ixBidAdapter_spec.js @@ -4,7 +4,7 @@ import { expect } from 'chai'; import { newBidder } from 'src/adapters/bidderFactory'; import { spec } from 'modules/ixBidAdapter'; -describe('IndexexchangeAdapter', () => { +describe('IndexexchangeAdapter', function () { const IX_ENDPOINT = 'http://as.casalemedia.com/cygnus'; const BIDDER_VERSION = 7.2; @@ -58,44 +58,44 @@ describe('IndexexchangeAdapter', () => { ] }; - describe('inherited functions', () => { - it('should exists and is a function', () => { + describe('inherited functions', function () { + it('should exists and is a function', function () { const adapter = newBidder(spec); expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - it('should return true when required params found for a banner ad', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found for a banner ad', function () { expect(spec.isBidRequestValid(DEFAULT_BANNER_VALID_BID[0])).to.equal(true); }); - it('should return true when optional params found for a banner ad', () => { + it('should return true when optional params found for a banner ad', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 'USD'; expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when siteID is number', () => { + it('should return true when siteID is number', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.siteId = 123; - expect(spec.isBidRequestValid(bid)).to.equal(false); + expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when siteID is missing', () => { + it('should return false when siteID is missing', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); delete bid.params.siteId; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when size is missing', () => { + it('should return false when size is missing', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); delete bid.params.size; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when size array is wrong length', () => { + it('should return false when size array is wrong length', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.size = [ 300, @@ -105,32 +105,91 @@ describe('IndexexchangeAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when size array is array of strings', () => { + it('should return false when size array is array of strings', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.size = ['300', '250']; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when there is only bidFloor', () => { + it('should return false when mediaTypes is not banner', function () { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + bid.mediaTypes = { + video: { + sizes: [[300, 250]] + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when mediaTypes.banner does not have sizes', function () { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + bid.mediaTypes = { + banner: { + size: [[300, 250]] + } + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when mediaType is not banner', function () { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + delete bid.params.mediaTypes; + bid.mediaType = 'banne'; + bid.sizes = [[300, 250]]; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when mediaType is video', function () { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + delete bid.params.mediaTypes; + bid.mediaType = 'video'; + bid.sizes = [[300, 250]]; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when mediaType is native', function () { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + delete bid.params.mediaTypes; + bid.mediaType = 'native'; + bid.sizes = [[300, 250]]; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return true when mediaType is missing and has sizes', function () { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + delete bid.mediaTypes; + bid.sizes = [[300, 250]]; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return true when mediaType is banner', function () { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + delete bid.mediaTypes; + bid.mediaType = 'banner'; + bid.sizes = [[300, 250]]; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when there is only bidFloor', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when there is only bidFloorCur', () => { + it('should return false when there is only bidFloorCur', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloorCur = 'USD'; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when bidFloor is string', () => { + it('should return false when bidFloor is string', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = '50'; bid.params.bidFloorCur = 'USD'; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when bidFloorCur is number', () => { + it('should return false when bidFloorCur is number', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 70; @@ -138,18 +197,24 @@ describe('IndexexchangeAdapter', () => { }); }); - describe('buildRequestsBanner', () => { + describe('buildRequestsBanner', function () { const request = spec.buildRequests(DEFAULT_BANNER_VALID_BID); const requestUrl = request.url; const requestMethod = request.method; const query = request.data; - it('request should be made to IX endpoint with GET method', () => { + const bidWithoutMediaType = utils.deepClone(DEFAULT_BANNER_VALID_BID); + delete bidWithoutMediaType[0].mediaTypes; + bidWithoutMediaType[0].sizes = [[300, 250], [300, 600]]; + const requestWithoutMediaType = spec.buildRequests(bidWithoutMediaType); + const queryWithoutMediaType = requestWithoutMediaType.data; + + it('request should be made to IX endpoint with GET method', function () { expect(requestMethod).to.equal('GET'); expect(requestUrl).to.equal(IX_ENDPOINT); }); - it('query object (version, siteID and request) should be correct', () => { + it('query object (version, siteID and request) should be correct', function () { expect(query.v).to.equal(BIDDER_VERSION); expect(query.s).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId); expect(query.r).to.exist; @@ -157,7 +222,7 @@ describe('IndexexchangeAdapter', () => { expect(query.sd).to.equal(1); }); - it('payload should have correct format and value', () => { + it('payload should have correct format and value', function () { const payload = JSON.parse(query.r); expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); @@ -173,7 +238,7 @@ describe('IndexexchangeAdapter', () => { expect(payload.imp).to.have.lengthOf(1); }); - it('impression should have correct format and value', () => { + it('impression should have correct format and value', function () { const impression = JSON.parse(query.r).imp[0]; const sidValue = `${DEFAULT_BANNER_VALID_BID[0].params.size[0].toString()}x${DEFAULT_BANNER_VALID_BID[0].params.size[1].toString()}`; @@ -188,7 +253,7 @@ describe('IndexexchangeAdapter', () => { expect(impression.ext.sid).to.equal(sidValue); }); - it('impression should have bidFloor and bidFloorCur if configured', () => { + it('impression should have bidFloor and bidFloorCur if configured', function () { const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); bid.params.bidFloor = 50; bid.params.bidFloorCur = 'USD'; @@ -199,7 +264,71 @@ describe('IndexexchangeAdapter', () => { expect(impression.bidfloorcur).to.equal(bid.params.bidFloorCur); }); - it('should add first party data to page url in bid request if it exists in config', () => { + it('payload without mediaType should have correct format and value', function () { + const payload = JSON.parse(queryWithoutMediaType.r); + + expect(payload.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidderRequestId); + expect(payload.site).to.exist; + expect(payload.site.page).to.exist; + expect(payload.site.page).to.contain('http'); + expect(payload.site.ref).to.exist; + expect(payload.site.ref).to.be.a('string'); + expect(payload.ext).to.exist; + expect(payload.ext.source).to.equal('prebid'); + expect(payload.imp).to.exist; + expect(payload.imp).to.be.an('array'); + expect(payload.imp).to.have.lengthOf(1); + }); + + it('impression without mediaType should have correct format and value', function () { + const impression = JSON.parse(queryWithoutMediaType.r).imp[0]; + const sidValue = `${DEFAULT_BANNER_VALID_BID[0].params.size[0].toString()}x${DEFAULT_BANNER_VALID_BID[0].params.size[1].toString()}`; + + expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); + expect(impression.banner).to.exist; + expect(impression.banner.w).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[0]); + expect(impression.banner.h).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[1]); + expect(impression.banner.topframe).to.exist; + expect(impression.banner.topframe).to.be.oneOf([0, 1]); + expect(impression.ext).to.exist; + expect(impression.ext.siteID).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId.toString()); + expect(impression.ext.sid).to.equal(sidValue); + }); + + it('impression should have sid if id is configured as number', function () { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + bid.params.id = 50; + const requestBidFloor = spec.buildRequests([bid]); + const impression = JSON.parse(requestBidFloor.data.r).imp[0]; + + expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); + expect(impression.banner).to.exist; + expect(impression.banner.w).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[0]); + expect(impression.banner.h).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[1]); + expect(impression.banner.topframe).to.exist; + expect(impression.banner.topframe).to.be.oneOf([0, 1]); + expect(impression.ext).to.exist; + expect(impression.ext.siteID).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId.toString()); + expect(impression.ext.sid).to.equal('50'); + }); + + it('impression should have sid if id is configured as string', function () { + const bid = utils.deepClone(DEFAULT_BANNER_VALID_BID[0]); + bid.params.id = 'abc'; + const requestBidFloor = spec.buildRequests([bid]); + const impression = JSON.parse(requestBidFloor.data.r).imp[0]; + expect(impression.id).to.equal(DEFAULT_BANNER_VALID_BID[0].bidId); + expect(impression.banner).to.exist; + expect(impression.banner.w).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[0]); + expect(impression.banner.h).to.equal(DEFAULT_BANNER_VALID_BID[0].params.size[1]); + expect(impression.banner.topframe).to.exist; + expect(impression.banner.topframe).to.be.oneOf([0, 1]); + expect(impression.ext).to.exist; + expect(impression.ext.siteID).to.equal(DEFAULT_BANNER_VALID_BID[0].params.siteId.toString()); + expect(impression.ext.sid).to.equal('abc'); + }); + + it('should add first party data to page url in bid request if it exists in config', function () { config.setConfig({ ix: { firstPartyData: { @@ -218,7 +347,7 @@ describe('IndexexchangeAdapter', () => { expect(pageUrl).to.equal(expectedPageUrl); }); - it('should not set first party data if it is not an object', () => { + it('should not set first party data if it is not an object', function () { config.setConfig({ ix: { firstPartyData: 500 @@ -231,7 +360,7 @@ describe('IndexexchangeAdapter', () => { expect(pageUrl).to.equal(utils.getTopWindowUrl()); }); - it('should not set first party or timeout if it is not present', () => { + it('should not set first party or timeout if it is not present', function () { config.setConfig({ ix: {} }); @@ -243,7 +372,7 @@ describe('IndexexchangeAdapter', () => { expect(requestWithoutConfig.data.t).to.be.undefined; }); - it('should not set first party or timeout if it is setConfig is not called', () => { + it('should not set first party or timeout if it is setConfig is not called', function () { const requestWithoutConfig = spec.buildRequests(DEFAULT_BANNER_VALID_BID); const pageUrl = JSON.parse(requestWithoutConfig.data.r).site.page; @@ -251,7 +380,7 @@ describe('IndexexchangeAdapter', () => { expect(requestWithoutConfig.data.t).to.be.undefined; }); - it('should set timeout if publisher set it through setConfig', () => { + it('should set timeout if publisher set it through setConfig', function () { config.setConfig({ ix: { timeout: 500 @@ -262,7 +391,7 @@ describe('IndexexchangeAdapter', () => { expect(requestWithTimeout.data.t).to.equal(500); }); - it('should set timeout if timeout is a string', () => { + it('should set timeout if timeout is a string', function () { config.setConfig({ ix: { timeout: '500' @@ -274,8 +403,8 @@ describe('IndexexchangeAdapter', () => { }); }); - describe('interpretResponseBanner', () => { - it('should get correct bid response', () => { + describe('interpretResponseBanner', function () { + it('should get correct bid response', function () { const expectedParse = [ { requestId: '1a2b3c4d', @@ -285,7 +414,7 @@ describe('IndexexchangeAdapter', () => { height: 250, ad: '
', currency: 'USD', - ttl: 60, + ttl: 35, netRevenue: true, dealId: undefined } @@ -294,7 +423,7 @@ describe('IndexexchangeAdapter', () => { expect(result[0]).to.deep.equal(expectedParse[0]); }); - it('should set creativeId to default value if not provided', () => { + it('should set creativeId to default value if not provided', function () { const bidResponse = utils.deepClone(DEFAULT_BANNER_BID_RESPONSE); delete bidResponse.seatbid[0].bid[0].crid; const expectedParse = [ @@ -306,7 +435,7 @@ describe('IndexexchangeAdapter', () => { height: 250, ad: '', currency: 'USD', - ttl: 60, + ttl: 35, netRevenue: true, dealId: undefined } @@ -315,7 +444,7 @@ describe('IndexexchangeAdapter', () => { expect(result[0]).to.deep.equal(expectedParse[0]); }); - it('should set Japanese price correctly', () => { + it('should set Japanese price correctly', function () { const bidResponse = utils.deepClone(DEFAULT_BANNER_BID_RESPONSE); bidResponse.cur = 'JPY'; const expectedParse = [ @@ -327,7 +456,7 @@ describe('IndexexchangeAdapter', () => { height: 250, ad: '', currency: 'JPY', - ttl: 60, + ttl: 35, netRevenue: true, dealId: undefined } @@ -336,7 +465,7 @@ describe('IndexexchangeAdapter', () => { expect(result[0]).to.deep.equal(expectedParse[0]); }); - it('should set dealId correctly', () => { + it('should set dealId correctly', function () { const bidResponse = utils.deepClone(DEFAULT_BANNER_BID_RESPONSE); bidResponse.seatbid[0].bid[0].ext.dealid = 'deal'; const expectedParse = [ @@ -348,7 +477,7 @@ describe('IndexexchangeAdapter', () => { height: 250, ad: '', currency: 'USD', - ttl: 60, + ttl: 35, netRevenue: true, dealId: 'deal' } @@ -357,7 +486,7 @@ describe('IndexexchangeAdapter', () => { expect(result[0]).to.deep.equal(expectedParse[0]); }); - it('bidrequest should have consent info if gdprApplies and consentString exist', () => { + it('bidrequest should have consent info if gdprApplies and consentString exist', function () { const options = { gdprConsent: { gdprApplies: true, @@ -372,7 +501,7 @@ describe('IndexexchangeAdapter', () => { expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); }); - it('bidrequest should not have consent field if consentString is undefined', () => { + it('bidrequest should not have consent field if consentString is undefined', function () { const options = { gdprConsent: { gdprApplies: true, @@ -386,7 +515,7 @@ describe('IndexexchangeAdapter', () => { expect(requestWithConsent.user).to.be.undefined; }); - it('bidrequest should not have gdpr field if gdprApplies is undefined', () => { + it('bidrequest should not have gdpr field if gdprApplies is undefined', function () { const options = { gdprConsent: { consentString: '3huaa11=qu3198ae', @@ -400,7 +529,7 @@ describe('IndexexchangeAdapter', () => { expect(requestWithConsent.user.ext.consent).to.equal('3huaa11=qu3198ae'); }); - it('bidrequest should not have consent info if options.gdprConsent is undefined', () => { + it('bidrequest should not have consent info if options.gdprConsent is undefined', function () { const options = {}; const validBidWithConsent = spec.buildRequests(DEFAULT_BANNER_VALID_BID, options); const requestWithConsent = JSON.parse(validBidWithConsent.data.r); diff --git a/test/spec/modules/jcmBidAdapter_spec.js b/test/spec/modules/jcmBidAdapter_spec.js index 27784def4f9..0b467e1ecfb 100644 --- a/test/spec/modules/jcmBidAdapter_spec.js +++ b/test/spec/modules/jcmBidAdapter_spec.js @@ -4,16 +4,16 @@ import { newBidder } from 'src/adapters/bidderFactory'; const ENDPOINT = '//media.adfrontiers.com/'; -describe('jcmAdapter', () => { +describe('jcmAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'jcm', 'params': { @@ -26,18 +26,18 @@ describe('jcmAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'jcm', @@ -55,11 +55,11 @@ describe('jcmAdapter', () => { const request = spec.buildRequests(bidRequests); - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { expect(request.method).to.equal('GET'); }); - it('sends correct bid parameters', () => { + it('sends correct bid parameters', function () { const payloadArr = request.data.split('&'); expect(request.method).to.equal('GET'); expect(payloadArr.length).to.equal(4); @@ -75,8 +75,8 @@ describe('jcmAdapter', () => { }); }); - describe('interpretResponse', () => { - it('should get correct bid response', () => { + describe('interpretResponse', function () { + it('should get correct bid response', function () { let serverResponse = {'bids': [{'width': 300, 'height': 250, 'creativeId': '29681110', 'ad': '', 'cpm': 0.5, 'callbackId': '30b31c1838de1e'}]}; let expectedResponse = [ @@ -109,15 +109,15 @@ describe('jcmAdapter', () => { expect(Object.keys(result[0]).ad).to.equal(Object.keys(expectedResponse[0]).ad); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let serverResponse = {'bids': []}; let result = spec.interpretResponse({ body: serverResponse }); expect(result.length).to.equal(0); }); }); - describe('getUserSyncs', () => { - it('Verifies sync iframe option', () => { + describe('getUserSyncs', function () { + it('Verifies sync iframe option', function () { expect(spec.getUserSyncs({})).to.be.undefined; expect(spec.getUserSyncs({ iframeEnabled: false })).to.be.undefined; const options = spec.getUserSyncs({ iframeEnabled: true }); @@ -127,7 +127,7 @@ describe('jcmAdapter', () => { expect(options[0].url).to.equal('//media.adfrontiers.com/hb/jcm_usersync.html'); }); - it('Verifies sync image option', () => { + it('Verifies sync image option', function () { expect(spec.getUserSyncs({ image: false })).to.be.undefined; const options = spec.getUserSyncs({ image: true }); expect(options).to.not.be.undefined; diff --git a/test/spec/modules/justpremiumBidAdapter_spec.js b/test/spec/modules/justpremiumBidAdapter_spec.js index 769810a3f3f..3c1048143d2 100644 --- a/test/spec/modules/justpremiumBidAdapter_spec.js +++ b/test/spec/modules/justpremiumBidAdapter_spec.js @@ -1,9 +1,10 @@ import { expect } from 'chai' import { spec } from 'modules/justpremiumBidAdapter' -describe('justpremium adapter', () => { +describe('justpremium adapter', function () { let adUnits = [ { + adUnitCode: 'div-gpt-ad-1471513102552-1', bidder: 'justpremium', params: { zone: 28313, @@ -11,6 +12,7 @@ describe('justpremium adapter', () => { } }, { + adUnitCode: 'div-gpt-ad-1471513102552-2', bidder: 'justpremium', params: { zone: 32831, @@ -19,12 +21,12 @@ describe('justpremium adapter', () => { }, ] - describe('isBidRequestValid', () => { - it('Verifies bidder code', () => { + describe('isBidRequestValid', function () { + it('Verifies bidder code', function () { expect(spec.code).to.equal('justpremium') }) - it('Verify build request', () => { + it('Verify build request', function () { expect(spec.isBidRequestValid({bidder: 'justpremium', params: {}})).to.equal(false) expect(spec.isBidRequestValid({})).to.equal(false) expect(spec.isBidRequestValid(adUnits[0])).to.equal(true) @@ -32,8 +34,8 @@ describe('justpremium adapter', () => { }) }) - describe('buildRequests', () => { - it('Verify build request and parameters', () => { + describe('buildRequests', function () { + it('Verify build request and parameters', function () { const request = spec.buildRequests(adUnits) expect(request.method).to.equal('POST') expect(request.url).to.match(/pre.ads.justpremium.com\/v\/2.0\/t\/xhr/) @@ -50,12 +52,14 @@ describe('justpremium adapter', () => { expect(jpxRequest.c).to.not.equal('undefined') expect(jpxRequest.id).to.equal(adUnits[0].params.zone) expect(jpxRequest.sizes).to.not.equal('undefined') + expect(jpxRequest.version.prebid).to.equal('$prebid.version$') + expect(jpxRequest.version.jp_adapter).to.equal('1.3') }) }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { const request = spec.buildRequests(adUnits) - it('Verify server response', () => { + it('Verify server response', function () { let response = { 'bid': { '28313': [{ @@ -83,7 +87,8 @@ describe('justpremium adapter', () => { cpm: 0.52, netRevenue: true, currency: 'USD', - ttl: 60000 + ttl: 60000, + format: 'lb' } ] @@ -99,9 +104,10 @@ describe('justpremium adapter', () => { expect(result[0].ttl).to.equal(60000) expect(result[0].creativeId).to.equal(3213123) expect(result[0].netRevenue).to.equal(true) + expect(result[0].format).to.equal('lb') }) - it('Verify wrong server response', () => { + it('Verify wrong server response', function () { let response = { 'bid': { '28313': [] @@ -116,12 +122,40 @@ describe('justpremium adapter', () => { }) }) - describe('getUserSyncs', () => { - it('Verifies sync options', () => { + describe('getUserSyncs', function () { + it('Verifies sync options', function () { const options = spec.getUserSyncs({iframeEnabled: true}) expect(options).to.not.be.undefined expect(options[0].type).to.equal('iframe') expect(options[0].url).to.match(/\/\/pre.ads.justpremium.com\/v\/1.0\/t\/sync/) }) }) + + describe('onTimeout', function () { + it('onTimeout', (done) => { + spec.onTimeout([{ + 'bidId': '25cd3ec3fd6ed7', + 'bidder': 'justpremium', + 'adUnitCode': 'div-gpt-ad-1471513102552-1', + 'auctionId': '6fbd0562-f613-4151-a6df-6cb446fc717b', + 'params': [{ + 'adType': 'iab', + 'zone': 21521 + }], + 'timeout': 1 + }, { + 'bidId': '3b51df1f254e32', + 'bidder': 'justpremium', + 'adUnitCode': 'div-gpt-ad-1471513102552-3', + 'auctionId': '6fbd0562-f613-4151-a6df-6cb446fc717b', + 'params': [{ + 'adType': 'iab', + 'zone': 21521 + }], + 'timeout': 1 + }]) + + done() + }) + }) }) diff --git a/test/spec/modules/kargoBidAdapter_spec.js b/test/spec/modules/kargoBidAdapter_spec.js index 0e896b4fc04..680b402392a 100644 --- a/test/spec/modules/kargoBidAdapter_spec.js +++ b/test/spec/modules/kargoBidAdapter_spec.js @@ -4,14 +4,16 @@ import {registerBidder} from 'src/adapters/bidderFactory'; import {config} from 'src/config'; describe('kargo adapter tests', function () { - var sandbox; + var sandbox, clock, frozenNow = new Date(); - beforeEach(() => { + beforeEach(function () { sandbox = sinon.sandbox.create(); + clock = sinon.useFakeTimers(frozenNow.getTime()); }); - afterEach(() => { + afterEach(function () { sandbox.restore(); + clock.restore(); }); describe('bid request validity', function() { @@ -33,12 +35,20 @@ describe('kargo adapter tests', function () { }); describe('build request', function() { - var bids, cookies = [], localStorageItems = []; + var bids, undefinedCurrency, noAdServerCurrency, cookies = [], localStorageItems = []; - beforeEach(() => { + beforeEach(function () { + undefinedCurrency = false; + noAdServerCurrency = false; sandbox.stub(config, 'getConfig').callsFake(function(key) { if (key === 'currency') { - return 'USD'; + if (undefinedCurrency) { + return undefined; + } + if (noAdServerCurrency) { + return {}; + } + return {adServerCurrency: 'USD'}; } throw new Error(`Config stub incomplete! Missing key "${key}"`) }); @@ -48,18 +58,24 @@ describe('kargo adapter tests', function () { params: { placementId: 'foo' }, - placementCode: 1 + bidId: 1 + }, + { + params: { + placementId: 'bar' + }, + bidId: 2 }, { params: { placementId: 'bar' }, - placementCode: 2 + bidId: 3 } ]; }); - afterEach(() => { + afterEach(function () { for (let key in cookies) { let cookie = cookies[key]; removeCookie(cookie); @@ -101,6 +117,16 @@ describe('kargo adapter tests', function () { return sandbox.stub(localStorage, 'getItem').throws(); } + function simulateNoCurrencyObject() { + undefinedCurrency = true; + noAdServerCurrency = false; + } + + function simulateNoAdServerCurrency() { + undefinedCurrency = false; + noAdServerCurrency = true; + } + function initializeKruxUser() { setLocalStorageItem('kxkar_user', 'rsgr9pnij'); } @@ -166,14 +192,16 @@ describe('kargo adapter tests', function () { timeout: 200, currency: 'USD', cpmGranularity: 1, + timestamp: frozenNow.getTime(), cpmRange: { floor: 0, ceil: 20 }, - adSlotIds: [ - 'foo', - 'bar' - ], + bidIDs: { + 1: 'foo', + 2: 'bar', + 3: 'bar' + }, userIDs: { kargoID: '5f108831-302d-11e7-bf6b-4595acd3bf6c', clientID: '2410d8f2-c111-4811-88a5-7b5e190e475f', @@ -232,7 +260,7 @@ describe('kargo adapter tests', function () { var request = spec.buildRequests(bids, {timeout: 200, foo: 'bar'}); var krakenParams = JSON.parse(decodeURIComponent(request.data.slice(5))); expect(request.data.slice(0, 5)).to.equal('json='); - expect(request.url).to.equal('https://krk.kargo.com/api/v1/bid'); + expect(request.url).to.equal('https://krk.kargo.com/api/v2/bid'); expect(request.method).to.equal('GET'); expect(request.currency).to.equal('USD'); expect(request.timeout).to.equal(200); @@ -298,18 +326,45 @@ describe('kargo adapter tests', function () { initializeInvalidKrgCrbType3(); testBuildRequests(getExpectedKrakenParams({crb: true}, undefined, getInvalidKrgCrbType3())); }); + + it('handles a non-existant currency object on the config', function() { + simulateNoCurrencyObject(); + initializeKruxUser(); + initializeKruxSegments(); + initializeKrgUid(); + initializeKrgCrb(); + testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb())); + }); + + it('handles no ad server currency being set on the currency object in the config', function() { + simulateNoAdServerCurrency(); + initializeKruxUser(); + initializeKruxSegments(); + initializeKrgUid(); + initializeKrgCrb(); + testBuildRequests(getExpectedKrakenParams(undefined, undefined, getKrgCrb())); + }); }); describe('response handler', function() { it('handles bid responses', function() { var resp = spec.interpretResponse({body: { - foo: { + 1: { + id: 'foo', cpm: 3, adm: '
', width: 320, height: 50 }, - bar: { + 2: { + id: 'bar', + cpm: 2.5, + adm: '
', + width: 300, + height: 250 + }, + 3: { + id: 'bar', cpm: 2.5, adm: '
', width: 300, @@ -318,19 +373,24 @@ describe('kargo adapter tests', function () { }}, { currency: 'USD', bids: [{ - bidId: 'fake bid id 1', + bidId: 1, params: { placementId: 'foo' } }, { - bidId: 'fake bid id 2', + bidId: 2, + params: { + placementId: 'bar' + } + }, { + bidId: 3, params: { placementId: 'bar' } }] }); var expectation = [{ - requestId: 'fake bid id 1', + requestId: '1', cpm: 3, width: 320, height: 50, @@ -340,7 +400,17 @@ describe('kargo adapter tests', function () { netRevenue: true, currency: 'USD' }, { - requestId: 'fake bid id 2', + requestId: '2', + cpm: 2.5, + width: 300, + height: 250, + ad: '
', + ttl: 300, + creativeId: 'bar', + netRevenue: true, + currency: 'USD' + }, { + requestId: '3', cpm: 2.5, width: 300, height: 250, @@ -353,4 +423,97 @@ describe('kargo adapter tests', function () { expect(resp).to.deep.equal(expectation); }); }); + + describe('user sync handler', function() { + const clientId = '74c81cbb-7d07-46d9-be9b-68ccb291c949'; + var shouldSimulateOutdatedBrowser, uid, isActuallyOutdatedBrowser; + + beforeEach(() => { + uid = {}; + shouldSimulateOutdatedBrowser = false; + isActuallyOutdatedBrowser = false; + + // IE11 fails these tests in the Prebid test suite. Since this + // browser won't support any of this stuff we expect all user + // syncing to fail gracefully. Kargo is mobile only, so this + // doesn't really matter. + if (!window.crypto) { + isActuallyOutdatedBrowser = true; + } else { + sandbox.stub(crypto, 'getRandomValues').callsFake(function(buf) { + if (shouldSimulateOutdatedBrowser) { + throw new Error('Could not generate random values'); + } + var bytes = [50, 5, 232, 133, 141, 55, 49, 57, 244, 126, 248, 44, 255, 38, 128, 0]; + for (var i = 0; i < bytes.length; i++) { + buf[i] = bytes[i]; + } + return buf; + }); + } + + sandbox.stub(spec, '_getUid').callsFake(function() { + return uid; + }); + }); + + function getUserSyncsWhenAllowed() { + return spec.getUserSyncs({iframeEnabled: true}); + } + + function getUserSyncsWhenForbidden() { + return spec.getUserSyncs({}); + } + + function turnOnClientId() { + uid.clientId = clientId; + } + + function simulateOutdatedBrowser() { + shouldSimulateOutdatedBrowser = true; + } + + function getSyncUrl(index) { + return { + type: 'iframe', + url: `https://crb.kargo.com/api/v1/initsyncrnd/${clientId}?seed=3205e885-8d37-4139-b47e-f82cff268000&idx=${index}` + }; + } + + function getSyncUrls() { + var syncs = []; + for (var i = 0; i < 5; i++) { + syncs[i] = getSyncUrl(i); + } + return syncs; + } + + function safelyRun(runExpectation) { + if (isActuallyOutdatedBrowser) { + expect(getUserSyncsWhenAllowed()).to.be.an('array').that.is.empty; + } else { + runExpectation(); + } + } + + it('handles user syncs when there is a client id', function() { + turnOnClientId(); + safelyRun(() => expect(getUserSyncsWhenAllowed()).to.deep.equal(getSyncUrls())); + }); + + it('no user syncs when there is no client id', function() { + safelyRun(() => expect(getUserSyncsWhenAllowed()).to.be.an('array').that.is.empty); + }); + + it('no user syncs when there is outdated browser', function() { + turnOnClientId(); + simulateOutdatedBrowser(); + safelyRun(() => expect(getUserSyncsWhenAllowed()).to.be.an('array').that.is.empty); + }); + + it('no user syncs when no iframe syncing allowed', function() { + turnOnClientId(); + safelyRun(() => expect(getUserSyncsWhenForbidden()).to.be.an('array').that.is.empty); + }); + }); }); diff --git a/test/spec/modules/komoonaBidAdapter_spec.js b/test/spec/modules/komoonaBidAdapter_spec.js index f7038505db3..b6d17c7b20c 100644 --- a/test/spec/modules/komoonaBidAdapter_spec.js +++ b/test/spec/modules/komoonaBidAdapter_spec.js @@ -1,7 +1,7 @@ import { expect } from 'chai'; import { spec } from 'modules/komoonaBidAdapter'; -describe('Komoona.com Adapter Tests', () => { +describe('Komoona.com Adapter Tests', function () { const bidsRequest = [ { bidder: 'komoona', @@ -54,11 +54,11 @@ describe('Komoona.com Adapter Tests', () => { } }; - it('Verifies komoonaAdapter bidder code', () => { + it('Verifies komoonaAdapter bidder code', function () { expect(spec.code).to.equal('komoona'); }); - it('Verifies komoonaAdapter bid request validation', () => { + it('Verifies komoonaAdapter bid request validation', function () { expect(spec.isBidRequestValid(bidsRequest[0])).to.equal(true); expect(spec.isBidRequestValid(bidsRequest[1])).to.equal(true); expect(spec.isBidRequestValid({})).to.equal(false); @@ -69,7 +69,7 @@ describe('Komoona.com Adapter Tests', () => { expect(spec.isBidRequestValid({ params: { hbid: 12345, placementId: 67890, floorPrice: 0.8 } })).to.equal(true); }); - it('Verify komoonaAdapter build request', () => { + it('Verify komoonaAdapter build request', function () { var startTime = new Date().getTime(); const request = spec.buildRequests(bidsRequest); @@ -127,7 +127,7 @@ describe('Komoona.com Adapter Tests', () => { expect(kbConf.hb_placements[1]).to.equal(bids[1].placementid); }); - it('Verify komoonaAdapter build response', () => { + it('Verify komoonaAdapter build response', function () { const request = spec.buildRequests(bidsRequest); const bids = spec.interpretResponse(bidsResponse, request); @@ -150,7 +150,7 @@ describe('Komoona.com Adapter Tests', () => { expect(bid.creativeId).to.equal(responseBids[0].creativeId); }); - it('Verifies komoonaAdapter sync options', () => { + it('Verifies komoonaAdapter sync options', function () { // user sync disabled expect(spec.getUserSyncs({})).to.be.undefined; expect(spec.getUserSyncs({ iframeEnabled: false })).to.be.undefined; diff --git a/test/spec/modules/kummaBidAdapter_spec.js b/test/spec/modules/kummaBidAdapter_spec.js index d90063820b7..82076717dcc 100644 --- a/test/spec/modules/kummaBidAdapter_spec.js +++ b/test/spec/modules/kummaBidAdapter_spec.js @@ -1,29 +1,83 @@ import {expect} from 'chai'; import {spec} from 'modules/kummaBidAdapter'; -import {getTopWindowLocation, getTopWindowReferrer} from 'src/utils'; +import {getTopWindowLocation} from 'src/utils'; +import {newBidder} from 'src/adapters/bidderFactory'; -describe('Kumma Adapter Tests', () => { +describe('Kumma Adapter Tests', function () { const slotConfigs = [{ placementCode: '/DfpAccount1/slot1', sizes: [[300, 250]], bidId: 'bid12345', + mediaType: 'banner', params: { - pubId: '55879', + pubId: '29521', siteId: '26047', placementId: '123', - bidFloor: '0.001' + bidFloor: '0.001', + ifa: 'IFA', + latitude: '40.712775', + longitude: '-74.005973' } }, { placementCode: '/DfpAccount2/slot2', - sizes: [[250, 250]], + sizes: [[728, 90]], bidId: 'bid23456', + mediaType: 'banner', params: { - pubId: '55879', + pubId: '29521', siteId: '26047', - placementId: '456' + placementId: '1234', + bidFloor: '0.000001', } }]; - it('Verify build request', () => { + const nativeSlotConfig = [{ + placementCode: '/DfpAccount1/slot3', + bidId: 'bid12345', + mediaType: 'native', + nativeParams: { + title: { required: true, len: 200 }, + body: {}, + image: { wmin: 100 }, + sponsoredBy: { }, + icon: { } + }, + params: { + pubId: '29521', + placementId: '123', + siteId: '26047' + } + }]; + const videoSlotConfig = [{ + placementCode: '/DfpAccount1/slot4', + sizes: [[640, 480]], + bidId: 'bid12345678', + mediaType: 'video', + video: { + skippable: true + }, + params: { + pubId: '29521', + placementId: '1234567', + siteId: '26047', + } + }]; + const appSlotConfig = [{ + placementCode: '/DfpAccount1/slot5', + bidId: 'bid12345', + params: { + pubId: '29521', + placementId: '1234', + app: { + id: '1111', + name: 'app name', + bundle: 'com.kumma.apps', + storeUrl: 'http://kumma.com/apps', + domain: 'kumma.com' + } + } + }]; + + it('Verify build request', function () { const request = spec.buildRequests(slotConfigs); expect(request.url).to.equal('//hb.kumma.com/'); expect(request.method).to.equal('POST'); @@ -31,13 +85,16 @@ describe('Kumma Adapter Tests', () => { // site object expect(ortbRequest.site).to.not.equal(null); expect(ortbRequest.site.publisher).to.not.equal(null); - expect(ortbRequest.site.publisher.id).to.equal('55879'); - expect(ortbRequest.site.ref).to.equal(getTopWindowReferrer()); + expect(ortbRequest.site.publisher.id).to.equal('29521'); + expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); expect(ortbRequest.imp).to.have.lengthOf(2); // device object expect(ortbRequest.device).to.not.equal(null); expect(ortbRequest.device.ua).to.equal(navigator.userAgent); + expect(ortbRequest.device.ifa).to.equal('IFA'); + expect(ortbRequest.device.geo.lat).to.equal('40.712775'); + expect(ortbRequest.device.geo.lon).to.equal('-74.005973'); // slot 1 expect(ortbRequest.imp[0].tagid).to.equal('123'); expect(ortbRequest.imp[0].banner).to.not.equal(null); @@ -45,14 +102,14 @@ describe('Kumma Adapter Tests', () => { expect(ortbRequest.imp[0].banner.h).to.equal(250); expect(ortbRequest.imp[0].bidfloor).to.equal('0.001'); // slot 2 - expect(ortbRequest.imp[1].tagid).to.equal('456'); + expect(ortbRequest.imp[1].tagid).to.equal('1234'); expect(ortbRequest.imp[1].banner).to.not.equal(null); - expect(ortbRequest.imp[1].banner.w).to.equal(250); - expect(ortbRequest.imp[1].banner.h).to.equal(250); + expect(ortbRequest.imp[1].banner.w).to.equal(728); + expect(ortbRequest.imp[1].banner.h).to.equal(90); expect(ortbRequest.imp[1].bidfloor).to.equal('0.000001'); }); - it('Verify parse response', () => { + it('Verify parse response', function () { const request = spec.buildRequests(slotConfigs); const ortbRequest = JSON.parse(request.data); const ortbResponse = { @@ -60,8 +117,7 @@ describe('Kumma Adapter Tests', () => { bid: [{ impid: ortbRequest.imp[0].id, price: 1.25, - adm: 'This is an Ad', - adid: '471810', + adm: 'This is an Ad' }] }], cur: 'USD' @@ -74,24 +130,206 @@ describe('Kumma Adapter Tests', () => { expect(bid.ad).to.equal('This is an Ad'); expect(bid.width).to.equal(300); expect(bid.height).to.equal(250); - expect(bid.creativeId).to.equal('471810'); + expect(bid.adId).to.equal('bid12345'); + expect(bid.creativeId).to.equal('bid12345'); + expect(bid.netRevenue).to.equal(true); expect(bid.currency).to.equal('USD'); expect(bid.ttl).to.equal(360); }); - it('Verify full passback', () => { + it('Verify full passback', function () { const request = spec.buildRequests(slotConfigs); const bids = spec.interpretResponse({ body: null }, request) expect(bids).to.have.lengthOf(0); }); - it('Verifies bidder code', () => { + it('Verify Native request', function () { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//hb.kumma.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // native impression + expect(ortbRequest.imp[0].tagid).to.equal('123'); + const nativePart = ortbRequest.imp[0]['native']; + expect(nativePart).to.not.equal(null); + expect(nativePart.ver).to.equal('1.1'); + expect(nativePart.request).to.not.equal(null); + // native request assets + const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); + expect(nativeRequest).to.not.equal(null); + expect(nativeRequest.assets).to.have.lengthOf(5); + expect(nativeRequest.assets[0].id).to.equal(1); + expect(nativeRequest.assets[1].id).to.equal(2); + expect(nativeRequest.assets[2].id).to.equal(3); + expect(nativeRequest.assets[3].id).to.equal(4); + expect(nativeRequest.assets[4].id).to.equal(5); + expect(nativeRequest.assets[0].required).to.equal(1); + expect(nativeRequest.assets[0].title).to.not.equal(null); + expect(nativeRequest.assets[0].title.len).to.equal(200); + expect(nativeRequest.assets[1].title).to.be.undefined; + expect(nativeRequest.assets[1].data).to.not.equal(null); + expect(nativeRequest.assets[1].data.type).to.equal(2); + expect(nativeRequest.assets[1].data.len).to.equal(200); + expect(nativeRequest.assets[2].required).to.equal(0); + expect(nativeRequest.assets[3].img).to.not.equal(null); + expect(nativeRequest.assets[3].img.wmin).to.equal(50); + expect(nativeRequest.assets[3].img.hmin).to.equal(50); + expect(nativeRequest.assets[3].img.type).to.equal(1); + expect(nativeRequest.assets[4].img).to.not.equal(null); + expect(nativeRequest.assets[4].img.wmin).to.equal(100); + expect(nativeRequest.assets[4].img.hmin).to.equal(150); + expect(nativeRequest.assets[4].img.type).to.equal(3); + }); + + it('Verify Native response', function () { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//hb.kumma.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + const nativeResponse = { + 'native': { + assets: [ + { id: 1, title: { text: 'Ad Title' } }, + { id: 2, data: { value: 'Test description' } }, + { id: 3, data: { value: 'Brand' } }, + { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png', w: 100, h: 100 } }, + { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png', w: 300, h: 300 } } + ], + link: { url: 'http://brand.com/' } + } + }; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + nurl: 'http://rtb.adx1.com/log', + adm: JSON.stringify(nativeResponse) + }] + }], + cur: 'USD', + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + // verify bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.adId).to.equal('bid12345'); + expect(bid.ad).to.be.undefined; + expect(bid.mediaType).to.equal('native'); + const nativeBid = bid['native']; + expect(nativeBid).to.not.equal(null); + expect(nativeBid.title).to.equal('Ad Title'); + expect(nativeBid.sponsoredBy).to.equal('Brand'); + expect(nativeBid.icon.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); + expect(nativeBid.image.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); + expect(nativeBid.image.width).to.equal(300); + expect(nativeBid.image.height).to.equal(300); + expect(nativeBid.icon.width).to.equal(100); + expect(nativeBid.icon.height).to.equal(100); + expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.com/')); + expect(nativeBid.impressionTrackers).to.have.lengthOf(1); + expect(nativeBid.impressionTrackers[0]).to.equal('http://rtb.adx1.com/log'); + }); + + it('Verify Video request', function () { + const request = spec.buildRequests(videoSlotConfig); + expect(request.url).to.equal('//hb.kumma.com/'); + expect(request.method).to.equal('POST'); + const videoRequest = JSON.parse(request.data); + // site object + expect(videoRequest.site).to.not.equal(null); + expect(videoRequest.site.publisher.id).to.equal('29521'); + expect(videoRequest.site.ref).to.equal(window.top.document.referrer); + expect(videoRequest.site.page).to.equal(getTopWindowLocation().href); + // device object + expect(videoRequest.device).to.not.equal(null); + expect(videoRequest.device.ua).to.equal(navigator.userAgent); + // slot 1 + expect(videoRequest.imp[0].tagid).to.equal('1234567'); + expect(videoRequest.imp[0].video).to.not.equal(null); + expect(videoRequest.imp[0].video.w).to.equal(640); + expect(videoRequest.imp[0].video.h).to.equal(480); + expect(videoRequest.imp[0].banner).to.equal(null); + expect(videoRequest.imp[0].native).to.equal(null); + }); + + it('Verify parse video response', function () { + const request = spec.buildRequests(videoSlotConfig); + const videoRequest = JSON.parse(request.data); + const videoResponse = { + seatbid: [{ + bid: [{ + impid: videoRequest.imp[0].id, + price: 1.90, + adm: 'http://vid.example.com/9876', + crid: '510511_754567308' + }] + }], + cur: 'USD' + }; + const bids = spec.interpretResponse({ body: videoResponse }, request); + expect(bids).to.have.lengthOf(1); + // verify first bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.90); + expect(bid.vastUrl).to.equal('http://vid.example.com/9876'); + expect(bid.crid).to.equal('510511_754567308'); + expect(bid.width).to.equal(640); + expect(bid.height).to.equal(480); + expect(bid.adId).to.equal('bid12345678'); + expect(bid.netRevenue).to.equal(true); + expect(bid.currency).to.equal('USD'); + expect(bid.ttl).to.equal(360); + }); + + it('Verifies bidder code', function () { expect(spec.code).to.equal('kumma'); }); - it('Verifies if bid request valid', () => { + it('Verifies supported media types', function () { + expect(spec.supportedMediaTypes).to.have.lengthOf(3); + expect(spec.supportedMediaTypes[0]).to.equal('banner'); + expect(spec.supportedMediaTypes[1]).to.equal('native'); + expect(spec.supportedMediaTypes[2]).to.equal('video'); + }); + + it('Verifies if bid request valid', function () { expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); - expect(spec.isBidRequestValid({})).to.equal(false); - expect(spec.isBidRequestValid({ params: {} })).to.equal(false); + expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); + expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); + expect(spec.isBidRequestValid(videoSlotConfig[0])).to.equal(true); + }); + + it('Verify app requests', function () { + const request = spec.buildRequests(appSlotConfig); + const ortbRequest = JSON.parse(request.data); + expect(ortbRequest.site).to.equal(null); + expect(ortbRequest.app).to.not.be.null; + expect(ortbRequest.app.publisher).to.not.equal(null); + expect(ortbRequest.app.publisher.id).to.equal('29521'); + expect(ortbRequest.app.id).to.equal('1111'); + expect(ortbRequest.app.name).to.equal('app name'); + expect(ortbRequest.app.bundle).to.equal('com.kumma.apps'); + expect(ortbRequest.app.storeurl).to.equal('http://kumma.com/apps'); + expect(ortbRequest.app.domain).to.equal('kumma.com'); + }); + + it('Verify GDPR', function () { + const bidderRequest = { + gdprConsent: { + gdprApplies: true, + consentString: 'serialized_gpdr_data' + } + }; + const request = spec.buildRequests(slotConfigs, bidderRequest); + expect(request.url).to.equal('//hb.kumma.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + expect(ortbRequest.user).to.not.equal(null); + expect(ortbRequest.user.ext).to.not.equal(null); + expect(ortbRequest.user.ext.consent).to.equal('serialized_gpdr_data'); + expect(ortbRequest.regs).to.not.equal(null); + expect(ortbRequest.regs.ext).to.not.equal(null); + expect(ortbRequest.regs.ext.gdpr).to.equal(1); }); }); diff --git a/test/spec/modules/lifestreetBidAdapter_spec.js b/test/spec/modules/lifestreetBidAdapter_spec.js index 2c48a0f1892..6c9c6eeba31 100644 --- a/test/spec/modules/lifestreetBidAdapter_spec.js +++ b/test/spec/modules/lifestreetBidAdapter_spec.js @@ -56,45 +56,45 @@ let getDefaultBidResponse = (isBanner, noBid = 0) => { }; }; -describe('LifestreetAdapter', () => { +describe('LifestreetAdapter', function () { const LIFESTREET_URL = '//ads.lfstmedia.com/gate/'; const ADAPTER_VERSION = 'prebidJS-2.0'; - describe('buildRequests()', () => { - it('method exists and is a function', () => { + describe('buildRequests()', function () { + it('method exists and is a function', function () { expect(spec.buildRequests).to.exist.and.to.be.a('function'); }); - it('should not return request when no bids are present', () => { + it('should not return request when no bids are present', function () { let [request] = spec.buildRequests([]); expect(request).to.be.empty; }); let bidRequest = getDefaultBidRequest(); let [request] = spec.buildRequests(bidRequest.bids); - it('should return request for Lifestreet endpoint', () => { + it('should return request for Lifestreet endpoint', function () { expect(request.url).to.contain(LIFESTREET_URL); }); - it('should use json adapter', () => { + it('should use json adapter', function () { expect(request.url).to.contain('/prebid/'); }); - it('should contain slot', () => { + it('should contain slot', function () { expect(request.url).to.contain('slot166704'); }); - it('should contain adkey', () => { + it('should contain adkey', function () { expect(request.url).to.contain('adkey=78c'); }); - it('should contain ad_size', () => { + it('should contain ad_size', function () { expect(request.url).to.contain('ad_size=160x600'); }); - it('should contain location and rferrer paramters', () => { + it('should contain location and rferrer paramters', function () { expect(request.url).to.contain('__location='); expect(request.url).to.contain('__referrer='); }); - it('should contain info parameters', () => { + it('should contain info parameters', function () { expect(request.url).to.contain('__wn='); expect(request.url).to.contain('__sf='); expect(request.url).to.contain('__fif='); @@ -103,24 +103,24 @@ describe('LifestreetAdapter', () => { expect(request.url).to.contain('__pp='); }); - it('should contain HB enabled', () => { + it('should contain HB enabled', function () { expect(request.url).to.contain('__hb=1'); }); - it('should include gzip', () => { + it('should include gzip', function () { expect(request.url).to.contain('__gz=1'); }); - it('should not contain __gdpr parameter', () => { + it('should not contain __gdpr parameter', function () { expect(request.url).to.not.contain('__gdpr'); }); - it('should not contain __concent parameter', () => { + it('should not contain __concent parameter', function () { expect(request.url).to.not.contain('__consent'); }); - it('should contain the right version of adapter', () => { + it('should contain the right version of adapter', function () { expect(request.url).to.contain('__hbver=' + ADAPTER_VERSION); }); - it('should contain __gdpr and __consent parameters', () => { + it('should contain __gdpr and __consent parameters', function () { const options = { gdprConsent: { gdprApplies: true, @@ -132,7 +132,7 @@ describe('LifestreetAdapter', () => { expect(request.url).to.contain('__gdpr=1'); expect(request.url).to.contain('__consent=test'); }); - it('should contain __gdpr parameters', () => { + it('should contain __gdpr parameters', function () { const options = { gdprConsent: { gdprApplies: true, @@ -143,7 +143,7 @@ describe('LifestreetAdapter', () => { expect(request.url).to.contain('__gdpr=1'); expect(request.url).to.not.contain('__consent'); }); - it('should contain __consent parameters', () => { + it('should contain __consent parameters', function () { const options = { gdprConsent: { consentString: 'test', @@ -155,8 +155,8 @@ describe('LifestreetAdapter', () => { expect(request.url).to.contain('__consent=test'); }); }); - describe('interpretResponse()', () => { - it('should return formatted bid response with required properties', () => { + describe('interpretResponse()', function () { + it('should return formatted bid response with required properties', function () { let bidRequest = getDefaultBidRequest().bids[0]; let bidResponse = { body: getDefaultBidResponse(true) }; let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); @@ -174,7 +174,7 @@ describe('LifestreetAdapter', () => { mediaType: 'banner' }]); }); - it('should return formatted VAST bid response with required properties', () => { + it('should return formatted VAST bid response with required properties', function () { let bidRequest = getDefaultBidRequest().bids[0]; let bidResponse = { body: getDefaultBidResponse(false) }; let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); @@ -192,7 +192,7 @@ describe('LifestreetAdapter', () => { mediaType: 'video' }]); }); - it('should return formatted VAST bid response with vastUrl', () => { + it('should return formatted VAST bid response with vastUrl', function () { let bidRequest = getDefaultBidRequest().bids[0]; let bidResponse = { body: getDefaultBidResponse(false) }; bidResponse.body.vastUrl = 'http://lifestreet.com'; // set vastUrl @@ -212,7 +212,7 @@ describe('LifestreetAdapter', () => { }]); }); - it('should return no-bid', () => { + it('should return no-bid', function () { let bidRequest = getDefaultBidRequest().bids[0]; let bidResponse = { body: getDefaultBidResponse(true, true) }; let formattedBidResponse = spec.interpretResponse(bidResponse, bidRequest); diff --git a/test/spec/modules/lkqdBidAdapter_spec.js b/test/spec/modules/lkqdBidAdapter_spec.js index d3e16f0c99a..0cebb2651a9 100644 --- a/test/spec/modules/lkqdBidAdapter_spec.js +++ b/test/spec/modules/lkqdBidAdapter_spec.js @@ -2,16 +2,16 @@ import { spec } from 'modules/lkqdBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; const { expect } = require('chai'); -describe('LKQD Bid Adapter Test', () => { +describe('LKQD Bid Adapter Test', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'lkqd', 'params': { @@ -26,11 +26,11 @@ describe('LKQD Bid Adapter Test', () => { 'transactionId': 'd6f6b392-54a9-454c-85fb-a2fd882c4a2d', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -40,8 +40,8 @@ describe('LKQD Bid Adapter Test', () => { }); }); - describe('buildRequests', () => { - const ENDPOINT = 'https://ssp.lkqd.net/ad?'; + describe('buildRequests', function () { + const ENDPOINT = 'https://v.lkqd.net/ad'; let bidRequests = [ { 'bidder': 'lkqd', @@ -73,47 +73,63 @@ describe('LKQD Bid Adapter Test', () => { } ]; - it('should populate available parameters', () => { + it('should populate available parameters', function () { const requests = spec.buildRequests(bidRequests); expect(requests.length).to.equal(2); - const r1 = requests[0].url; - expect(r1).to.contain('?pid=263'); - expect(r1).to.contain('&sid=662921'); - expect(r1).to.contain('&width=300'); - expect(r1).to.contain('&height=250'); - const r2 = requests[1].url; - expect(r2).to.contain('?pid=263'); - expect(r2).to.contain('&sid=662921'); - expect(r2).to.contain('&width=640'); - expect(r2).to.contain('&height=480'); + const r1 = requests[0].data; + expect(r1).to.have.property('pid'); + expect(r1.pid).to.equal('263'); + expect(r1).to.have.property('sid'); + expect(r1.sid).to.equal('662921'); + expect(r1).to.have.property('width'); + expect(r1.width).to.equal(300); + expect(r1).to.have.property('height'); + expect(r1.height).to.equal(250); + const r2 = requests[1].data; + expect(r2).to.have.property('pid'); + expect(r2.pid).to.equal('263'); + expect(r2).to.have.property('sid'); + expect(r2.sid).to.equal('662921'); + expect(r2).to.have.property('width'); + expect(r2.width).to.equal(640); + expect(r2).to.have.property('height'); + expect(r2.height).to.equal(480); }); - it('should not populate unspecified parameters', () => { + it('should not populate unspecified parameters', function () { const requests = spec.buildRequests(bidRequests); expect(requests.length).to.equal(2); - const r1 = requests[0].url; - expect(r1).to.contain('‌&contentid=[CONTENT_ID]'); - expect(r1).to.contain('‌&contenttitle=[CONTENT_TITLE]'); - expect(r1).to.contain('‌&contentlength=[CONTENT_LENGTH]'); - expect(r1).to.contain('&height=250'); - const r2 = requests[1].url; - expect(r2).to.contain('‌&contentid=[CONTENT_ID]'); - expect(r2).to.contain('‌&contenttitle=[CONTENT_TITLE]'); - expect(r2).to.contain('‌&contentlength=[CONTENT_LENGTH]'); - expect(r2).to.contain('‌&contenturl=[CONTENT_URL]'); + const r1 = requests[0].data; + expect(r1).to.not.have.property('dnt'); + expect(r1).to.not.have.property('pageurl'); + expect(r1).to.not.have.property('contentid'); + expect(r1).to.not.have.property('contenttitle'); + expect(r1).to.not.have.property('contentlength'); + expect(r1).to.not.have.property('contenturl'); + const r2 = requests[1].data; + expect(r2).to.not.have.property('dnt'); + expect(r2).to.not.have.property('pageurl'); + expect(r2).to.not.have.property('contentid'); + expect(r2).to.not.have.property('contenttitle'); + expect(r2).to.not.have.property('contentlength'); + expect(r2).to.not.have.property('contenturl'); }); - it('should handle single size request', () => { + it('should handle single size request', function () { const requests = spec.buildRequests(bidRequest); expect(requests.length).to.equal(1); - const r1 = requests[0].url; - expect(r1).to.contain('?pid=263'); - expect(r1).to.contain('&sid=662921'); - expect(r1).to.contain('&width=640'); - expect(r1).to.contain('&height=480'); + const r1 = requests[0].data; + expect(r1).to.have.property('pid'); + expect(r1.pid).to.equal('263'); + expect(r1).to.have.property('sid'); + expect(r1.sid).to.equal('662921'); + expect(r1).to.have.property('width'); + expect(r1.width).to.equal(640); + expect(r1).to.have.property('height'); + expect(r1.height).to.equal(480); }); - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { const requests = spec.buildRequests(bidRequests); expect(requests.length).to.equal(2); const r1 = requests[0]; @@ -125,7 +141,7 @@ describe('LKQD Bid Adapter Test', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let bidRequest = { 'url': 'https://ssp.lkqd.net/ad?pid=263&sid=662921&output=vast&execution=any&placement=&playinit=auto&volume=100&timeout=&width=300%E2%80%8C&height=250&pbt=[PREBID_TOKEN]%E2%80%8C&dnt=[DO_NOT_TRACK]%E2%80%8C&pageurl=[PAGEURL]%E2%80%8C&contentid=[CONTENT_ID]%E2%80%8C&contenttitle=[CONTENT_TITLE]%E2%80%8C&contentlength=[CONTENT_LENGTH]%E2%80%8C&contenturl=[CONTENT_URL]&prebid=true%E2%80%8C&rnd=874313435?bidId=253dcb69fb2577&bidWidth=300&bidHeight=250&', 'data': { @@ -306,7 +322,7 @@ https://creative.lkqd.net/internal/lkqd_300x250.mp4 `; - it('should correctly parse valid bid response', () => { + it('should correctly parse valid bid response', function () { const BIDDER_CODE = 'lkqd'; let bidResponses = spec.interpretResponse(serverResponse, bidRequest); expect(bidResponses.length).to.equal(1); @@ -324,7 +340,7 @@ https://creative.lkqd.net/internal/lkqd_300x250.mp4 expect(bidResponse.mediaType).to.equal('video'); }); - it('safely handles XML parsing failure from invalid bid response', () => { + it('safely handles XML parsing failure from invalid bid response', function () { let invalidServerResponse = {}; invalidServerResponse.body = ''; @@ -332,7 +348,7 @@ https://creative.lkqd.net/internal/lkqd_300x250.mp4 expect(result.length).to.equal(0); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let nobidResponse = {}; nobidResponse.body = ''; diff --git a/test/spec/modules/lockerdomeBidAdapter_spec.js b/test/spec/modules/lockerdomeBidAdapter_spec.js index 84f0dd43e72..1cd6778b01f 100644 --- a/test/spec/modules/lockerdomeBidAdapter_spec.js +++ b/test/spec/modules/lockerdomeBidAdapter_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import { spec } from '../../../modules/lockerdomeBidAdapter'; import * as utils from 'src/utils'; -describe('LockerDomeAdapter', () => { +describe('LockerDomeAdapter', function () { const bidRequests = [{ bidder: 'lockerdome', params: { @@ -37,20 +37,20 @@ describe('LockerDomeAdapter', () => { auctionId: 'd4c83108-615d-4c2c-9384-dac9ffd4fd72' }]; - describe('isBidRequestValid', () => { - it('should return true if the adUnitId parameter is present', () => { + describe('isBidRequestValid', function () { + it('should return true if the adUnitId parameter is present', function () { expect(spec.isBidRequestValid(bidRequests[0])).to.be.true; expect(spec.isBidRequestValid(bidRequests[1])).to.be.true; }); - it('should return false if the adUnitId parameter is not present', () => { + it('should return false if the adUnitId parameter is not present', function () { let bidRequest = utils.deepClone(bidRequests[0]); delete bidRequest.params.adUnitId; expect(spec.isBidRequestValid(bidRequest)).to.be.false; }); }); - describe('buildRequests', () => { - it('should generate a valid single POST request for multiple bid requests', () => { + describe('buildRequests', function () { + it('should generate a valid single POST request for multiple bid requests', function () { const request = spec.buildRequests(bidRequests); expect(request.method).to.equal('POST'); expect(request.url).to.equal('https://lockerdome.com/ladbid/prebid'); @@ -65,19 +65,21 @@ describe('LockerDomeAdapter', () => { expect(bids).to.have.lengthOf(2); expect(bids[0].requestId).to.equal('2652ca954bce9'); + expect(bids[0].adUnitCode).to.equal('ad-1'); expect(bids[0].adUnitId).to.equal(10809467961050726); expect(bids[0].sizes).to.have.lengthOf(1); expect(bids[0].sizes[0][0]).to.equal(300); expect(bids[0].sizes[0][1]).to.equal(250); expect(bids[1].requestId).to.equal('4510f2834773ce'); + expect(bids[1].adUnitCode).to.equal('ad-2'); expect(bids[1].adUnitId).to.equal(9434769725128806); expect(bids[1].sizes).to.have.lengthOf(1); expect(bids[1].sizes[0][0]).to.equal(300); expect(bids[1].sizes[0][1]).to.equal(600); }); - it('should add GDPR data to request if available', () => { + it('should add GDPR data to request if available', function () { const bidderRequest = { gdprConsent: { consentString: 'AAABBB', @@ -93,13 +95,13 @@ describe('LockerDomeAdapter', () => { }); }); - describe('interpretResponse', () => { - it('should return an empty array if an invalid response is passed', () => { + describe('interpretResponse', function () { + it('should return an empty array if an invalid response is passed', function () { const interpretedResponse = spec.interpretResponse({ body: {} }); expect(interpretedResponse).to.be.an('array').that.is.empty; }); - it('should return valid response when passed valid server response', () => { + it('should return valid response when passed valid server response', function () { const serverResponse = { body: { bids: [{ diff --git a/test/spec/modules/madvertiseBidAdapter_spec.js b/test/spec/modules/madvertiseBidAdapter_spec.js index 64ecf556aa5..b2a08410532 100644 --- a/test/spec/modules/madvertiseBidAdapter_spec.js +++ b/test/spec/modules/madvertiseBidAdapter_spec.js @@ -1,9 +1,11 @@ import {expect} from 'chai'; +import {config} from 'src/config'; +import * as utils from 'src/utils'; import {spec} from 'modules/madvertiseBidAdapter'; -describe('madvertise adapater', () => { - describe('Test validate req', () => { - it('should accept minimum valid bid', () => { +describe('madvertise adapater', function () { + describe('Test validate req', function () { + it('should accept minimum valid bid', function () { let bid = { bidder: 'madvertise', sizes: [[728, 90]], @@ -15,7 +17,7 @@ describe('madvertise adapater', () => { expect(isValid).to.equal(true); }); - it('should reject no sizes', () => { + it('should reject no sizes', function () { let bid = { bidder: 'madvertise', params: { @@ -26,7 +28,7 @@ describe('madvertise adapater', () => { expect(isValid).to.equal(false); }); - it('should reject empty sizes', () => { + it('should reject empty sizes', function () { let bid = { bidder: 'madvertise', sizes: [], @@ -38,7 +40,7 @@ describe('madvertise adapater', () => { expect(isValid).to.equal(false); }); - it('should reject wrong format sizes', () => { + it('should reject wrong format sizes', function () { let bid = { bidder: 'madvertise', sizes: [['728x90']], @@ -49,7 +51,7 @@ describe('madvertise adapater', () => { const isValid = spec.isBidRequestValid(bid); expect(isValid).to.equal(false); }); - it('should reject no params', () => { + it('should reject no params', function () { let bid = { bidder: 'madvertise', sizes: [[728, 90]] @@ -58,7 +60,7 @@ describe('madvertise adapater', () => { expect(isValid).to.equal(false); }); - it('should reject missing s', () => { + it('should reject missing s', function () { let bid = { bidder: 'madvertise', params: {} @@ -69,32 +71,76 @@ describe('madvertise adapater', () => { }); }); - describe('Test build request', () => { - it('minimum request', () => { - let bid = [{ - bidder: 'madvertise', - sizes: [[728, 90], [300, 100]], - bidId: '51ef8751f9aead', - adUnitCode: 'div-gpt-ad-1460505748561-0', - transactionId: 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', - auctionId: '18fd8b8b0bd757', - bidderRequestId: '418b37f85e772c', - params: { - s: 'test', + describe('Test build request', function () { + beforeEach(function () { + let mockConfig = { + consentManagement: { + cmpApi: 'IAB', + timeout: 1111, + allowAuctionWithoutConsent: 'cancel' } - }]; - const req = spec.buildRequests(bid); + }; + + sinon.stub(config, 'getConfig').callsFake((key) => { + return utils.deepAccess(mockConfig, key); + }); + }); + afterEach(function () { + config.getConfig.restore(); + }); + let bid = [{ + bidder: 'madvertise', + sizes: [[728, 90], [300, 100]], + bidId: '51ef8751f9aead', + adUnitCode: 'div-gpt-ad-1460505748561-0', + transactionId: 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + auctionId: '18fd8b8b0bd757', + bidderRequestId: '418b37f85e772c', + params: { + s: 'test', + } + }]; + it('minimum request with gdpr consent', function () { + let bidderRequest = { + gdprConsent: { + consentString: 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', + vendorData: {}, + gdprApplies: true + } + }; + const req = spec.buildRequests(bid, bidderRequest); + + expect(req).to.exist.and.to.be.a('array'); + expect(req[0]).to.have.property('method'); + expect(req[0].method).to.equal('GET'); + expect(req[0]).to.have.property('url'); + expect(req[0].url).to.contain('//mobile.mng-ads.com/?rt=bid_request&v=1.0'); + expect(req[0].url).to.contain(`&s=test`); + expect(req[0].url).to.contain(`&sizes[0]=728x90`); + expect(req[0].url).to.contain(`&gdpr=1`); + expect(req[0].url).to.contain(`&consent[0][format]=IAB`); + expect(req[0].url).to.contain(`&consent[0][value]=BOJ/P2HOJ/P2HABABMAAAAAZ+A==`) + }); + + it('minimum request without gdpr consent', function () { + let bidderRequest = {}; + const req = spec.buildRequests(bid, bidderRequest); expect(req).to.exist.and.to.be.a('array'); expect(req[0]).to.have.property('method'); expect(req[0].method).to.equal('GET'); expect(req[0]).to.have.property('url'); - expect(req[0].url).to.contain('//mobile.mng-ads.com/?rt=bid_request&v=1.0').and.to.contain(`&s=test`).and.to.contain(`&sizes[0]=728x90`) + expect(req[0].url).to.contain('//mobile.mng-ads.com/?rt=bid_request&v=1.0'); + expect(req[0].url).to.contain(`&s=test`); + expect(req[0].url).to.contain(`&sizes[0]=728x90`); + expect(req[0].url).not.to.contain(`&gdpr=1`); + expect(req[0].url).not.to.contain(`&consent[0][format]=`); + expect(req[0].url).not.to.contain(`&consent[0][value]=`) }); }); - describe('Test interpret response', () => { - it('General banner response', () => { + describe('Test interpret response', function () { + it('General banner response', function () { let bid = { bidder: 'madvertise', sizes: [[728, 90]], @@ -134,7 +180,7 @@ describe('madvertise adapater', () => { expect(resp[0]).to.have.property('currency', 'EUR'); expect(resp[0]).to.have.property('dealId', 'DEAL_ID'); }); - it('No response', () => { + it('No response', function () { let bid = { bidder: 'madvertise', sizes: [[728, 90]], diff --git a/test/spec/modules/mantisBidAdapter_spec.js b/test/spec/modules/mantisBidAdapter_spec.js index e2cd4df9a07..464cea2aab3 100644 --- a/test/spec/modules/mantisBidAdapter_spec.js +++ b/test/spec/modules/mantisBidAdapter_spec.js @@ -2,10 +2,10 @@ import {expect} from 'chai'; import {spec} from 'modules/mantisBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; -describe('MantisAdapter', () => { +describe('MantisAdapter', function () { const adapter = newBidder(spec); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'mantis', 'params': { @@ -19,11 +19,11 @@ describe('MantisAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = {}; @@ -31,7 +31,7 @@ describe('MantisAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'mantis', @@ -47,7 +47,7 @@ describe('MantisAdapter', () => { } ]; - it('domain override', () => { + it('domain override', function () { window.mantis_domain = 'http://foo'; const request = spec.buildRequests(bidRequests); @@ -56,7 +56,7 @@ describe('MantisAdapter', () => { delete window.mantis_domain; }); - it('standard request', () => { + it('standard request', function () { const request = spec.buildRequests(bidRequests); expect(request.url).to.include('property=10433394'); @@ -68,7 +68,7 @@ describe('MantisAdapter', () => { expect(request.url).to.include('bids[0][sizes][1][height]=600'); }); - it('use window uuid', () => { + it('use window uuid', function () { window.mantis_uuid = 'foo'; const request = spec.buildRequests(bidRequests); @@ -78,7 +78,7 @@ describe('MantisAdapter', () => { delete window.mantis_uuid; }); - it('use storage uuid', () => { + it('use storage uuid', function () { window.localStorage.setItem('mantis:uuid', 'bar'); const request = spec.buildRequests(bidRequests); @@ -88,7 +88,7 @@ describe('MantisAdapter', () => { window.localStorage.removeItem('mantis:uuid'); }); - it('detect amp', () => { + it('detect amp', function () { var oldContext = window.context; window.context = {}; @@ -107,8 +107,8 @@ describe('MantisAdapter', () => { }); }); - describe('getUserSyncs', () => { - it('iframe', () => { + describe('getUserSyncs', function () { + it('iframe', function () { let result = spec.getUserSyncs({ iframeEnabled: true }); @@ -117,7 +117,7 @@ describe('MantisAdapter', () => { expect(result[0].url).to.include('https://mantodea.mantisadnetwork.com/prebid/iframe'); }); - it('pixel', () => { + it('pixel', function () { let result = spec.getUserSyncs({ pixelEnabled: true }); @@ -127,10 +127,11 @@ describe('MantisAdapter', () => { }); }); - describe('interpretResponse', () => { - it('display ads returned', () => { + describe('interpretResponse', function () { + it('display ads returned', function () { let response = { body: { + uuid: 'uuid', ads: [ { bid: 'bid', @@ -161,9 +162,11 @@ describe('MantisAdapter', () => { let result = spec.interpretResponse(response, {bidderRequest}); expect(result[0]).to.deep.equal(expectedResponse[0]); + expect(window.mantis_uuid).to.equal(response.body.uuid); + expect(window.localStorage.getItem('mantis:uuid')).to.equal(response.body.uuid); }); - it('no ads returned', () => { + it('no ads returned', function () { let response = { body: { ads: [] diff --git a/test/spec/modules/medianetBidAdapter_spec.js b/test/spec/modules/medianetBidAdapter_spec.js index a10dcb2624d..331b36b3217 100644 --- a/test/spec/modules/medianetBidAdapter_spec.js +++ b/test/spec/modules/medianetBidAdapter_spec.js @@ -17,7 +17,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 250]], 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1 }, { 'bidder': 'medianet', 'params': { @@ -33,7 +34,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 251]], 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1 }], VALID_BID_REQUEST_INVALID_BIDFLOOR = [{ 'bidder': 'medianet', @@ -51,7 +53,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 250]], 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1 }, { 'bidder': 'medianet', 'params': { @@ -67,7 +70,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [[300, 251]], 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1 }], VALID_AUCTIONDATA = { 'timeout': config.getConfig('bidderTimeout'), @@ -82,12 +86,29 @@ let VALID_BID_REQUEST = [{ 'customer_id': 'customer_id', 'prebid_version': $$PREBID_GLOBAL$$.version, 'gdpr_applies': false, + 'screen': { + 'w': 1000, + 'h': 1000 + } }, 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'imp': [{ 'id': '28f8f8130a583e', 'ext': { - 'dfp_id': 'div-gpt-ad-1460505748561-0' + 'dfp_id': 'div-gpt-ad-1460505748561-0', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -105,7 +126,20 @@ let VALID_BID_REQUEST = [{ }, { 'id': '3f97ca71b1e5c2', 'ext': { - 'dfp_id': 'div-gpt-ad-1460505748561-123' + 'dfp_id': 'div-gpt-ad-1460505748561-123', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -131,13 +165,30 @@ let VALID_BID_REQUEST = [{ 'ext': { 'customer_id': 'customer_id', 'prebid_version': $$PREBID_GLOBAL$$.version, - 'gdpr_applies': false + 'gdpr_applies': false, + 'screen': { + 'w': 1000, + 'h': 1000 + } }, 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'imp': [{ 'id': '28f8f8130a583e', 'ext': { - 'dfp_id': 'div-gpt-ad-1460505748561-0' + 'dfp_id': 'div-gpt-ad-1460505748561-0', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -154,7 +205,20 @@ let VALID_BID_REQUEST = [{ }, { 'id': '3f97ca71b1e5c2', 'ext': { - 'dfp_id': 'div-gpt-ad-1460505748561-123' + 'dfp_id': 'div-gpt-ad-1460505748561-123', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -316,7 +380,8 @@ let VALID_BID_REQUEST = [{ 'sizes': [300, 250], 'bidId': '28f8f8130a583e', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1 }, { 'bidder': 'medianet', 'params': { @@ -332,14 +397,15 @@ let VALID_BID_REQUEST = [{ 'sizes': [300, 251], 'bidId': '3f97ca71b1e5c2', 'bidderRequestId': '1e9b1f07797c1c', - 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d' + 'auctionId': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', + 'bidRequestsCount': 1 }], VALID_BIDDER_REQUEST_WITH_GDPR = { 'gdprConsent': { 'consentString': 'consentString', 'gdprApplies': true, }, - 'timeout': 3000, + 'timeout': 3000 }, VALID_PAYLOAD_FOR_GDPR = { 'site': { @@ -352,12 +418,29 @@ let VALID_BID_REQUEST = [{ 'prebid_version': $$PREBID_GLOBAL$$.version, 'gdpr_consent_string': 'consentString', 'gdpr_applies': true, + 'screen': { + 'w': 1000, + 'h': 1000 + } }, 'id': 'aafabfd0-28c0-4ac0-aa09-99689e88b81d', 'imp': [{ 'id': '28f8f8130a583e', 'ext': { - 'dfp_id': 'div-gpt-ad-1460505748561-0' + 'dfp_id': 'div-gpt-ad-1460505748561-0', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -374,7 +457,20 @@ let VALID_BID_REQUEST = [{ }, { 'id': '3f97ca71b1e5c2', 'ext': { - 'dfp_id': 'div-gpt-ad-1460505748561-123' + 'dfp_id': 'div-gpt-ad-1460505748561-123', + 'visibility': 1, + 'viewability': 1, + 'coordinates': { + 'top_left': { + x: 50, + y: 50 + }, + 'bottom_right': { + x: 100, + y: 100 + } + }, + 'display_count': 1 }, 'banner': [{ 'w': 300, @@ -392,53 +488,85 @@ let VALID_BID_REQUEST = [{ 'tmax': 3000, }; -describe('Media.net bid adapter', () => { - describe('isBidRequestValid', () => { - it('should accept valid bid params', () => { +describe('Media.net bid adapter', function () { + let sandbox; + beforeEach(function () { + sandbox = sinon.sandbox.create(); + }); + + afterEach(function () { + sandbox.restore(); + }); + + describe('isBidRequestValid', function () { + it('should accept valid bid params', function () { let isValid = spec.isBidRequestValid(VALID_PARAMS); expect(isValid).to.equal(true); }); - it('should reject bid if cid is not present', () => { + it('should reject bid if cid is not present', function () { let isValid = spec.isBidRequestValid(PARAMS_WITHOUT_CID); expect(isValid).to.equal(false); }); - it('should reject bid if cid is not a string', () => { + it('should reject bid if cid is not a string', function () { let isValid = spec.isBidRequestValid(PARAMS_WITH_INTEGER_CID); expect(isValid).to.equal(false); }); - it('should reject bid if cid is a empty string', () => { + it('should reject bid if cid is a empty string', function () { let isValid = spec.isBidRequestValid(PARAMS_WITH_EMPTY_CID); expect(isValid).to.equal(false); }); }); - describe('buildRequests', () => { - it('should build valid payload on bid', () => { + describe('buildRequests', function () { + beforeEach(function () { + let documentStub = sandbox.stub(document, 'getElementById'); + let boundingRect = { + top: 50, + left: 50, + bottom: 100, + right: 100 + }; + documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ + getBoundingClientRect: () => boundingRect + }); + documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + getBoundingClientRect: () => boundingRect + }); + let windowSizeStub = sandbox.stub(spec, 'getWindowSize'); + windowSizeStub.returns({ + w: 1000, + h: 1000 + }); + }); + + 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); }); - it('should accept size as a one dimensional array', () => { + it('should accept size as a one dimensional array', function () { let bidReq = spec.buildRequests(BID_REQUEST_SIZE_AS_1DARRAY, VALID_AUCTIONDATA); expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD); }); - it('should ignore bidfloor if not a valid number', () => { + it('should ignore bidfloor if not a valid number', function () { let bidReq = spec.buildRequests(VALID_BID_REQUEST_INVALID_BIDFLOOR, VALID_AUCTIONDATA); expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_INVALID_BIDFLOOR); }); - it('should add gdpr to response ext', () => { + it('should add gdpr to response ext', function () { let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_BIDDER_REQUEST_WITH_GDPR); expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_FOR_GDPR); }); describe('build requests: when page meta-data is available', () => { + beforeEach(() => { + spec.clearMnData(); + }); it('should pass canonical, twitter and fb paramters if available', () => { - let sandbox = sinon.sandbox.create(); let documentStub = sandbox.stub(window.top.document, 'querySelector'); documentStub.withArgs('link[rel="canonical"]').returns({ href: 'http://localhost:9999/canonical-test' @@ -451,45 +579,117 @@ describe('Media.net bid adapter', () => { }); let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); expect(JSON.parse(bidReq.data)).to.deep.equal(VALID_PAYLOAD_PAGE_META); - sandbox.restore(); }); }); }); - describe('getUserSyncs', () => { - it('should exclude iframe syncs if iframe is disabled', () => { + describe('slot visibility', function () { + let documentStub; + beforeEach(function () { + let windowSizeStub = sandbox.stub(spec, 'getWindowSize'); + windowSizeStub.returns({ + w: 1000, + h: 1000 + }); + documentStub = sandbox.stub(document, 'getElementById'); + }); + it('slot visibility should be 2 and ratio 0 when ad unit is BTF', function () { + let boundingRect = { + top: 1010, + left: 1010, + bottom: 1050, + right: 1050 + }; + documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ + getBoundingClientRect: () => boundingRect + }); + documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + getBoundingClientRect: () => boundingRect + }); + + let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); + let data = JSON.parse(bidReq.data); + expect(data.imp[0].ext.visibility).to.equal(2); + expect(data.imp[0].ext.viewability).to.equal(0); + }); + it('slot visibility should be 2 and ratio < 0.5 when ad unit is partially inside viewport', function () { + let boundingRect = { + top: 990, + left: 990, + bottom: 1050, + right: 1050 + }; + documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ + getBoundingClientRect: () => boundingRect + }); + documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + getBoundingClientRect: () => boundingRect + }); + let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); + let data = JSON.parse(bidReq.data); + expect(data.imp[0].ext.visibility).to.equal(2); + expect(data.imp[0].ext.viewability).to.equal(100 / 75000); + }); + it('slot visibility should be 1 and ratio > 0.5 when ad unit mostly in viewport', function () { + let boundingRect = { + top: 800, + left: 800, + bottom: 1050, + right: 1050 + }; + documentStub.withArgs('div-gpt-ad-1460505748561-123').returns({ + getBoundingClientRect: () => boundingRect + }); + documentStub.withArgs('div-gpt-ad-1460505748561-0').returns({ + getBoundingClientRect: () => boundingRect + }); + let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); + let data = JSON.parse(bidReq.data); + expect(data.imp[0].ext.visibility).to.equal(1); + expect(data.imp[0].ext.viewability).to.equal(40000 / 75000); + }); + it('co-ordinates should not be sent and slot visibility should be 0 when ad unit is not present', function () { + let bidReq = spec.buildRequests(VALID_BID_REQUEST, VALID_AUCTIONDATA); + let data = JSON.parse(bidReq.data); + expect(data.imp[1].ext).to.not.have.ownPropertyDescriptor('viewability'); + expect(data.imp[1].ext.visibility).to.equal(0); + }); + }); + + describe('getUserSyncs', function () { + it('should exclude iframe syncs if iframe is disabled', function () { let userSyncs = spec.getUserSyncs(SYNC_OPTIONS_PIXEL_ENABLED, SERVER_CSYNC_RESPONSE); expect(userSyncs).to.deep.equal(ENABLED_SYNC_PIXEL); }); - it('should exclude pixel syncs if pixel is disabled', () => { + it('should exclude pixel syncs if pixel is disabled', function () { let userSyncs = spec.getUserSyncs(SYNC_OPTIONS_IFRAME_ENABLED, SERVER_CSYNC_RESPONSE); expect(userSyncs).to.deep.equal(ENABLED_SYNC_IFRAME); }); - it('should choose iframe sync urls if both sync options are enabled', () => { + it('should choose iframe sync urls if both sync options are enabled', function () { let userSyncs = spec.getUserSyncs(SYNC_OPTIONS_BOTH_ENABLED, SERVER_CSYNC_RESPONSE); expect(userSyncs).to.deep.equal(ENABLED_SYNC_IFRAME); }); }); - describe('interpretResponse', () => { - it('should not push bid response if cpm missing', () => { + describe('interpretResponse', function () { + it('should not push bid response if cpm missing', function () { let validBids = []; let bids = spec.interpretResponse(SERVER_RESPONSE_CPM_MISSING, []); expect(bids).to.deep.equal(validBids); }); - it('should not push bid response if cpm 0', () => { + it('should not push bid response if cpm 0', function () { let validBids = []; let bids = spec.interpretResponse(SERVER_RESPONSE_CPM_ZERO, []); expect(bids).to.deep.equal(validBids); }); - it('should not push response if no-bid', () => { + it('should not push response if no-bid', function () { let validBids = []; let bids = spec.interpretResponse(SERVER_RESPONSE_NOBID, []); - expect(bids).to.deep.equal(validBids) + expect(bids).to.deep.equal(validBids); }); }); }); diff --git a/test/spec/modules/mobfoxBidAdapter_spec.js b/test/spec/modules/mobfoxBidAdapter_spec.js index 54a057991e3..90125f3e0d0 100644 --- a/test/spec/modules/mobfoxBidAdapter_spec.js +++ b/test/spec/modules/mobfoxBidAdapter_spec.js @@ -1,4 +1,4 @@ -describe('mobfox adapter tests', () => { +describe('mobfox adapter tests', function () { const expect = require('chai').expect; const utils = require('src/utils'); const adapter = require('modules/mobfoxBidAdapter'); @@ -18,7 +18,7 @@ describe('mobfox adapter tests', () => { transactionId: '31f42cba-5920-4e47-adad-69c79d0d4fb4' }]; - describe('validRequests', () => { + describe('validRequests', function () { let bidRequestInvalid1 = [{ code: 'div-gpt-ad-1460505748561-0', sizes: [[320, 480], [300, 250], [300, 600]], @@ -33,19 +33,19 @@ describe('mobfox adapter tests', () => { transactionId: '31f42cba-5920-4e47-adad-69c79d0d4fb4' }]; - it('test valid MF request success', () => { + it('test valid MF request success', function () { let isValid = adapter.spec.isBidRequestValid(bidRequest[0]); expect(isValid).to.equal(true); }); - it('test valid MF request failed1', () => { + it('test valid MF request failed1', function () { let isValid = adapter.spec.isBidRequestValid(bidRequestInvalid1[0]); expect(isValid).to.equal(false); }); }) - describe('buildRequests', () => { - it('test build MF request', () => { + describe('buildRequests', function () { + it('test build MF request', function () { let request = adapter.spec.buildRequests(bidRequest); let payload = request.data.split('&'); expect(payload[0]).to.equal('rt=api-fetchip'); @@ -57,7 +57,7 @@ describe('mobfox adapter tests', () => { expect(payload[7]).to.equal('imp_instl=1'); }); - it('test build MF request', () => { + it('test build MF request', function () { let request = adapter.spec.buildRequests(bidRequest); let payload = request.data.split('&'); expect(payload[0]).to.equal('rt=api-fetchip'); @@ -70,7 +70,7 @@ describe('mobfox adapter tests', () => { }); }) - describe('interceptResponse', () => { + describe('interceptResponse', function () { let mockServerResponse = { body: { request: { @@ -93,7 +93,7 @@ describe('mobfox adapter tests', () => { } } }; - it('test intercept response', () => { + it('test intercept response', function () { let request = adapter.spec.buildRequests(bidRequest); let bidResponses = adapter.spec.interpretResponse(mockServerResponse, request); expect(bidResponses.length).to.equal(1); @@ -109,7 +109,7 @@ describe('mobfox adapter tests', () => { expect(bidResponses[0].width).to.equal('320'); }); - it('test intercept response with empty server response', () => { + it('test intercept response with empty server response', function () { let request = adapter.spec.buildRequests(bidRequest); let serverResponse = { request: { diff --git a/test/spec/modules/my6senseBidAdapter_spec.js b/test/spec/modules/my6senseBidAdapter_spec.js new file mode 100644 index 00000000000..80671305aca --- /dev/null +++ b/test/spec/modules/my6senseBidAdapter_spec.js @@ -0,0 +1,151 @@ +import { expect } from 'chai'; +import spec from 'modules/my6senseBidAdapter'; + +describe('My6sense Bid adapter test', function () { + let bidRequests, serverResponses; + beforeEach(function () { + bidRequests = [ + { + // valid 1 + bidder: 'my6sense', + params: { + key: 'DTAeOJN67pCjY36dbhrM3G', + dataVersion: 3, + pageUrl: 'liran.com', + zone: '[ZONE]', + dataParams: '', + dataView: '', + organicClicks: '', + paidClicks: '' + } + }, + { + // invalid 2- no params + bidder: 'my6sense' + }, + { + // invalid 3 - no key in params + bidder: 'my6sense', + params: { + dataVersion: 3, + pageUrl: 'liran.com', + zone: '[ZONE]', + dataParams: '', + dataView: '', + organicClicks: '', + paidClicks: '' + } + }, + { + // invalid 3 - wrong bidder name + bidder: 'test', + params: { + key: 'ZxA0bNhlO9tf5EZ1Q9ZYdS', + dataVersion: 3, + pageUrl: 'liran.com', + zone: '[ZONE]', + dataParams: '', + dataView: '', + organicClicks: '', + paidClicks: '' + } + } + ]; + serverResponses = [ + { + headers: {}, + body: { + cpm: 1.5, + width: 300, + height: 250, + placement_id: 1, + adm: '' + } + }, + { + headers: {}, + body: { + cpm: 0, + width: 0, + height: 0, + placement_id: 1, + adm: '' + } + }, + { + headers: {}, + body: { + cpm: 0, + width: 0, + height: 0, + placement_id: 0, + adm: '' + } + }, + { + headers: {}, + body: { + cpm: 5, + creativeId: '5b29f5d1e4b086e3ee8de36b', + currency: 'USD', + height: 250, + netRevenue: false, + requestId: '2954a0957643bb', + ttl: 360, + width: 300, + adm: '' + } + } + ] + }); + + describe('test if requestIsValid function', function () { + it('with valid data 1', function () { + expect(spec.isBidRequestValid(bidRequests[0])).to.equal(true); + }); + it('with invalid data 2', function () { + expect(spec.isBidRequestValid(bidRequests[1])).to.equal(false); + }); + it('with invalid data 3', function () { + expect(spec.isBidRequestValid(bidRequests[2])).to.equal(false); + }); + it('with invalid data 3', function () { + expect(spec.isBidRequestValid(bidRequests[3])).to.equal(false); + }); + }); + + describe('test if buildRequests function', function () { + it('normal', function () { + var requests = spec.buildRequests([bidRequests[0]]); + expect(requests).to.be.lengthOf(1); + }); + }); + describe('test bid responses', function () { + it('success 1', function () { + var bids = spec.interpretResponse(serverResponses[0], {'bidRequest': bidRequests[0]}); + expect(bids).to.be.lengthOf(1); + expect(bids[0].cpm).to.equal(1.5); + expect(bids[0].width).to.equal(300); + expect(bids[0].height).to.equal(250); + expect(bids[0].adm).to.have.length.above(1); + }); + it('success 2', function () { + var bids = spec.interpretResponse(serverResponses[3]); + expect(bids).to.be.lengthOf(1); + expect(bids[0].cpm).to.equal(5); + expect(bids[0].width).to.equal(300); + expect(bids[0].height).to.equal(250); + expect(bids[0].netRevenue).to.equal(false); + expect(bids[0].ttl).to.equal(360); + expect(bids[0].currency).to.equal('USD'); + }); + it('fail 1 (cpm=0)', function () { + var bids = spec.interpretResponse(serverResponses[1]); + expect(bids).to.be.lengthOf(1); + }); + it('fail 2 (no response)', function () { + var bids = spec.interpretResponse([]); + expect(bids).to.be.lengthOf(0); + }); + }); +}); diff --git a/test/spec/modules/nanointeractiveBidAdapter_spec.js b/test/spec/modules/nanointeractiveBidAdapter_spec.js index 92b6fe8d797..3731535b88a 100644 --- a/test/spec/modules/nanointeractiveBidAdapter_spec.js +++ b/test/spec/modules/nanointeractiveBidAdapter_spec.js @@ -1,109 +1,535 @@ import { expect } from 'chai'; import * as utils from 'src/utils'; +import * as sinon from 'sinon'; import { - BIDDER_CODE, CATEGORY, DATA_PARTNER_PIXEL_ID, ENGINE_BASE_URL, NQ, NQ_NAME, SUB_ID, - spec + BIDDER_CODE, + CATEGORY, + CATEGORY_NAME, + DATA_PARTNER_PIXEL_ID, + ENGINE_BASE_URL, + NQ, + NQ_NAME, + REF, + spec, + SUB_ID } from '../../../modules/nanointeractiveBidAdapter'; describe('nanointeractive adapter tests', function () { - const SEARCH_QUERY = 'rumpelstiltskin'; - const WIDTH = 300; - const HEIGHT = 250; - const SIZES = [[WIDTH, HEIGHT]]; + const SIZES_PARAM = 'sizes'; + const BID_ID_PARAM = 'bidId'; + const BID_ID_VALUE = '24a1c9ec270973'; + const CORS_PARAM = 'cors'; + const LOC_PARAM = 'loc'; + const DATA_PARTNER_PIXEL_ID_VALUE = 'testPID'; + const NQ_VALUE = 'rumpelstiltskin'; + const NQ_NAME_QUERY_PARAM = 'nqName'; + const CATEGORY_VALUE = 'some category'; + const CATEGORY_NAME_QUERY_PARAM = 'catName'; + const SUB_ID_VALUE = '123'; + const REF_NO_VALUE = 'none'; + const REF_OTHER_VALUE = 'other'; + const WIDTH1 = 300; + const HEIGHT1 = 250; + const WIDTH2 = 468; + const HEIGHT2 = 60; + const SIZES_VALUE = [[WIDTH1, HEIGHT1], [WIDTH2, HEIGHT2]]; const AD = ' '; const CPM = 1; - function getBid(isValid) { + function getBidResponse (pid, nq, category, subId, cors, ref, loc) { + return { + [DATA_PARTNER_PIXEL_ID]: pid, + [NQ]: nq, + [CATEGORY]: category, + [SUB_ID]: subId, + [REF]: ref, + [SIZES_PARAM]: [WIDTH1 + 'x' + HEIGHT1, WIDTH2 + 'x' + HEIGHT2], + [BID_ID_PARAM]: BID_ID_VALUE, + [CORS_PARAM]: cors, + [LOC_PARAM]: loc, + }; + } + + function getBidRequest (params) { return { bidder: BIDDER_CODE, - params: (function () { - return { - [DATA_PARTNER_PIXEL_ID]: isValid === true ? 'pid1' : null, - [NQ]: SEARCH_QUERY, - [NQ_NAME]: null, - [CATEGORY]: null, - [SUB_ID]: null, - } - })(), + params: params, placementCode: 'div-gpt-ad-1460505748561-0', transactionId: 'ee335735-ddd3-41f2-b6c6-e8aa99f81c0f', - sizes: SIZES, - bidId: '24a1c9ec270973', + [SIZES_PARAM]: SIZES_VALUE, + [BID_ID_PARAM]: BID_ID_VALUE, bidderRequestId: '189135372acd55', auctionId: 'ac15bb68-4ef0-477f-93f4-de91c47f00a9' - } - } - - const SINGLE_BID_REQUEST = { - [DATA_PARTNER_PIXEL_ID]: 'pid1', - [NQ]: [SEARCH_QUERY, null], - [SUB_ID]: null, - sizes: [WIDTH + 'x' + HEIGHT], - bidId: '24a1c9ec270973', - cors: 'http://localhost' - }; - - function getSingleBidResponse(isValid) { - return { - id: '24a1c9ec270973', - cpm: isValid === true ? CPM : null, - width: WIDTH, - height: HEIGHT, - ad: AD, - ttl: 360, - creativeId: 'TEST_ID', - netRevenue: false, - currency: 'EUR', - } + }; } - const VALID_BID = { - requestId: '24a1c9ec270973', - cpm: CPM, - width: WIDTH, - height: HEIGHT, - ad: AD, - ttl: 360, - creativeId: 'TEST_ID', - netRevenue: false, - currency: 'EUR', - }; - - describe('NanoAdapter', () => { + describe('NanoAdapter', function () { let nanoBidAdapter = spec; - describe('Methods', () => { - it('Test isBidRequestValid() with valid param', function () { - expect(nanoBidAdapter.isBidRequestValid(getBid(true))).to.equal(true); + describe('Methods', function () { + it('Test isBidRequestValid() with valid param(s): pid', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nq', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nq, category', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ, + [CATEGORY]: CATEGORY_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nq, categoryName', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ, + [CATEGORY_NAME_QUERY_PARAM]: CATEGORY_NAME_QUERY_PARAM, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nq, subId', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ, + [SUB_ID]: SUB_ID_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nqName', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ_NAME]: NQ_NAME_QUERY_PARAM, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nqName, category', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ_NAME]: NQ_NAME_QUERY_PARAM, + [CATEGORY]: CATEGORY_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nqName, categoryName', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ_NAME]: NQ_NAME_QUERY_PARAM, + [CATEGORY_NAME_QUERY_PARAM]: CATEGORY_NAME_QUERY_PARAM, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nqName, subId', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ_NAME]: NQ_NAME_QUERY_PARAM, + [SUB_ID]: SUB_ID_VALUE, + }))).to.equal(true); }); - it('Test isBidRequestValid() with invalid param', function () { - expect(nanoBidAdapter.isBidRequestValid(getBid(false))).to.equal(false); + it('Test isBidRequestValid() with valid param(s): pid, category', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [CATEGORY]: CATEGORY_VALUE, + }))).to.equal(true); }); - it('Test buildRequests()', function () { - let stub = sinon.stub(utils, 'getOrigin').callsFake(() => 'http://localhost'); + it('Test isBidRequestValid() with valid param(s): pid, category, subId', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, subId', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nq, category, subId', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nqName, categoryName, subId', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ_NAME]: NQ_NAME_QUERY_PARAM, + [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, + [SUB_ID]: SUB_ID_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nq, category, subId, ref (value none)', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + [REF]: REF_NO_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with valid param(s): pid, nq, category, subId, ref (value other)', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + [REF]: REF_OTHER_VALUE, + }))).to.equal(true); + }); + it('Test isBidRequestValid() with invalid param(s): empty', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({}))).to.equal(false); + }); + it('Test isBidRequestValid() with invalid param(s): pid missing', function () { + expect(nanoBidAdapter.isBidRequestValid(getBidRequest({ + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }))).to.equal(false); + }); + + let sandbox; - let request = nanoBidAdapter.buildRequests([getBid(true)]); + function getMocks () { + let mockWindowLocationAddress = 'http://some-location.test'; + let mockOriginAddress = 'http://localhost'; + let mockRefAddress = 'http://some-ref.test'; + return { + 'windowLocationAddress': mockWindowLocationAddress, + 'originAddress': mockOriginAddress, + 'refAddress': mockRefAddress, + }; + } + + function setUpMocks (mockRefAddress = null) { + sandbox = sinon.sandbox.create(); + sandbox.stub(utils, 'getOrigin').callsFake(() => getMocks()['originAddress']); + sandbox.stub(utils, 'getTopWindowLocation').callsFake(() => { + return { + 'href': getMocks()['windowLocationAddress'] + }; + }); + if (mockRefAddress == null) { + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => getMocks()['refAddress']); + } else { + sandbox.stub(utils, 'getTopWindowReferrer').callsFake(() => mockRefAddress); + } + sandbox.stub(utils, 'getParameterByName').callsFake((arg) => { + switch (arg) { + case CATEGORY_NAME_QUERY_PARAM: + return CATEGORY_VALUE; + case NQ_NAME_QUERY_PARAM: + return NQ_VALUE; + } + }); + } + + function assert ( + request, + expectedPid, + expectedNq, + expectedCategory, + expectedSubId, + expectedRef = getMocks()['refAddress'], + expectedOrigin = getMocks()['originAddress'], + expectedLocation = getMocks()['windowLocationAddress'] + ) { expect(request.method).to.equal('POST'); expect(request.url).to.equal(ENGINE_BASE_URL); - expect(request.data).to.equal(JSON.stringify([SINGLE_BID_REQUEST])); + expect(request.data).to.equal(JSON.stringify([ + getBidResponse( + expectedPid, + expectedNq, + expectedCategory, + expectedSubId, + expectedOrigin, + expectedRef, + expectedLocation, + ), + ])); + } + + function tearDownMocks () { + sandbox.restore(); + } + + it('Test buildRequest() - pid', function () { + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [null]; + let expectedCategory = [null]; + let expectedSubId = null; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); + }); + it('Test buildRequest() - pid, nq', function () { + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [null]; + let expectedSubId = null; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); + }); + it('Test buildRequest() - pid, nq, category', function () { + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = null; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); + }); + it('Test buildRequest() - pid, nq, categoryName', function () { + setUpMocks(); + + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = null; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); + }); + it('Test buildRequest() - pid, nq, subId', function () { + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [null]; + let expectedSubId = SUB_ID_VALUE; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); + }); + it('Test buildRequest() - pid, category', function () { + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [CATEGORY]: CATEGORY_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [null]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = null; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); + }); + it('Test buildRequest() - pid, category, subId', function () { + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [null]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = SUB_ID_VALUE; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); + }); + it('Test buildRequest() - pid, subId', function () { + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [null]; + let expectedCategory = [null]; + let expectedSubId = SUB_ID_VALUE; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); + }); + it('Test buildRequest() - pid, nq, category, subId', function () { + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = SUB_ID_VALUE; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); + }); + it('Test buildRequest() - pid, nqName, categoryName, subId', function () { + setUpMocks(); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ_NAME]: NQ_NAME_QUERY_PARAM, + [CATEGORY_NAME]: CATEGORY_NAME_QUERY_PARAM, + [SUB_ID]: SUB_ID_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = SUB_ID_VALUE; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId); + tearDownMocks(); + }); + it('Test buildRequest() - pid, nq, category, subId, ref (value none)', function () { + setUpMocks(null); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + [REF]: REF_NO_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = SUB_ID_VALUE; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); + + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId, null); + tearDownMocks(); + }); + it('Test buildRequest() - pid, nq, category, subId, ref (value other)', function () { + setUpMocks(null); + let requestParams = { + [DATA_PARTNER_PIXEL_ID]: DATA_PARTNER_PIXEL_ID_VALUE, + [NQ]: NQ_VALUE, + [CATEGORY]: CATEGORY_VALUE, + [SUB_ID]: SUB_ID_VALUE, + [REF]: REF_OTHER_VALUE, + }; + let expectedPid = DATA_PARTNER_PIXEL_ID_VALUE; + let expectedNq = [NQ_VALUE]; + let expectedCategory = [CATEGORY_VALUE]; + let expectedSubId = SUB_ID_VALUE; + + let request = nanoBidAdapter.buildRequests([getBidRequest(requestParams)]); - stub.restore(); + assert(request, expectedPid, expectedNq, expectedCategory, expectedSubId, null); + tearDownMocks(); }); it('Test interpretResponse() length', function () { - let bids = nanoBidAdapter.interpretResponse({body: [getSingleBidResponse(true), getSingleBidResponse(false)]}); + let bids = nanoBidAdapter.interpretResponse({ + body: [ + // valid + { + id: '24a1c9ec270973', + cpm: CPM, + width: WIDTH1, + height: HEIGHT1, + ad: AD, + ttl: 360, + creativeId: 'TEST_ID', + netRevenue: false, + currency: 'EUR', + }, + // invalid + { + id: '24a1c9ec270973', + cpm: null, + width: WIDTH1, + height: HEIGHT1, + ad: AD, + ttl: 360, + creativeId: 'TEST_ID', + netRevenue: false, + currency: 'EUR', + } + ] + }); expect(bids.length).to.equal(1); }); it('Test interpretResponse() bids', function () { - let bid = nanoBidAdapter.interpretResponse({body: [getSingleBidResponse(true), getSingleBidResponse(false)]})[0]; - expect(bid.requestId).to.equal(VALID_BID.requestId); - expect(bid.cpm).to.equal(VALID_BID.cpm); - expect(bid.width).to.equal(VALID_BID.width); - expect(bid.height).to.equal(VALID_BID.height); - expect(bid.ad).to.equal(VALID_BID.ad); - expect(bid.ttl).to.equal(VALID_BID.ttl); - expect(bid.creativeId).to.equal(VALID_BID.creativeId); - expect(bid.currency).to.equal(VALID_BID.currency); + let bid = nanoBidAdapter.interpretResponse({ + body: [ + // valid + { + id: '24a1c9ec270973', + cpm: CPM, + width: WIDTH1, + height: HEIGHT1, + ad: AD, + ttl: 360, + creativeId: 'TEST_ID', + netRevenue: false, + currency: 'EUR', + }, + // invalid + { + id: '24a1c9ec270973', + cpm: null, + width: WIDTH1, + height: HEIGHT1, + ad: AD, + ttl: 360, + creativeId: 'TEST_ID', + netRevenue: false, + currency: 'EUR', + } + ] + })[0]; + expect(bid.requestId).to.equal('24a1c9ec270973'); + expect(bid.cpm).to.equal(CPM); + expect(bid.width).to.equal(WIDTH1); + expect(bid.height).to.equal(HEIGHT1); + expect(bid.ad).to.equal(AD); + expect(bid.ttl).to.equal(360); + expect(bid.creativeId).to.equal('TEST_ID'); + expect(bid.currency).to.equal('EUR'); }); }); }); diff --git a/test/spec/modules/nasmediaAdmixerBidAdapter_spec.js b/test/spec/modules/nasmediaAdmixerBidAdapter_spec.js index 7ed65718657..dd6ed4686d1 100644 --- a/test/spec/modules/nasmediaAdmixerBidAdapter_spec.js +++ b/test/spec/modules/nasmediaAdmixerBidAdapter_spec.js @@ -2,16 +2,16 @@ import {expect} from 'chai'; import {spec} from 'modules/nasmediaAdmixerBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; -describe('nasmediaAdmixerBidAdapter', () => { +describe('nasmediaAdmixerBidAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { const bid = { 'bidder': 'nasmediaAdmixer', 'params': { @@ -24,11 +24,11 @@ describe('nasmediaAdmixerBidAdapter', () => { 'auctionId': '124cb070528662', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { const bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -38,7 +38,7 @@ describe('nasmediaAdmixerBidAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const bidRequests = [ { 'bidder': 'nasmediaAdmixer', @@ -53,14 +53,14 @@ describe('nasmediaAdmixerBidAdapter', () => { } ]; - it('sends bid request to url via GET', () => { + it('sends bid request to url via GET', function () { const request = spec.buildRequests(bidRequests)[0]; expect(request.method).to.equal('GET'); expect(request.url).to.match(new RegExp(`https://adn.admixer.co.kr`)); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const response = { 'body': { 'bidder': 'nasmedia_admixer', @@ -94,7 +94,7 @@ describe('nasmediaAdmixerBidAdapter', () => { 'auctionId': '169827a33f03cc', }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const expectedResponse = [ { 'requestId': '861a8e7952c82c', @@ -122,7 +122,7 @@ describe('nasmediaAdmixerBidAdapter', () => { }); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { response.body = { 'bidder': 'nasmedia_admixer', 'req_id': '861a8e7952c82c', diff --git a/test/spec/modules/oneVideoBidAdapter_spec.js b/test/spec/modules/oneVideoBidAdapter_spec.js index 3d7bba417f9..f67105751df 100644 --- a/test/spec/modules/oneVideoBidAdapter_spec.js +++ b/test/spec/modules/oneVideoBidAdapter_spec.js @@ -1,11 +1,14 @@ import { expect } from 'chai'; import { spec } from 'modules/oneVideoBidAdapter'; import * as utils from 'src/utils'; +import {config} from 'src/config'; -describe('OneVideoBidAdapter', () => { +describe('OneVideoBidAdapter', function () { let bidRequest; + let bidderRequest; + let mockConfig; - beforeEach(() => { + beforeEach(function () { bidRequest = { bidder: 'oneVideo', sizes: [640, 480], @@ -30,19 +33,19 @@ describe('OneVideoBidAdapter', () => { }; }); - describe('spec.isBidRequestValid', () => { - it('should return true when the required params are passed', () => { + describe('spec.isBidRequestValid', function () { + it('should return true when the required params are passed', function () { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return false when the "video" param is missing', () => { + it('should return false when the "video" param is missing', function () { bidRequest.params = { pubId: 'brxd' }; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when the "pubId" param is missing', () => { + it('should return false when the "pubId" param is missing', function () { bidRequest.params = { video: { playerWidth: 480, @@ -57,25 +60,25 @@ describe('OneVideoBidAdapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when no bid params are passed', () => { + it('should return false when no bid params are passed', function () { bidRequest.params = {}; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); }); - describe('spec.buildRequests', () => { - it('should create a POST request for every bid', () => { + describe('spec.buildRequests', function () { + it('should create a POST request for every bid', function () { const requests = spec.buildRequests([ bidRequest ]); expect(requests[0].method).to.equal('POST'); expect(requests[0].url).to.equal(location.protocol + spec.ENDPOINT + bidRequest.params.pubId); }); - it('should attach the bid request object', () => { + it('should attach the bid request object', function () { const requests = spec.buildRequests([ bidRequest ]); expect(requests[0].bidRequest).to.equal(bidRequest); }); - it('should attach request data', () => { + it('should attach request data', function () { const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; const [ width, height ] = bidRequest.sizes; @@ -84,7 +87,7 @@ describe('OneVideoBidAdapter', () => { expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor); }); - it('must parse bid size from a nested array', () => { + it('must parse bid size from a nested array', function () { const width = 640; const height = 480; bidRequest.sizes = [[ width, height ]]; @@ -95,25 +98,25 @@ describe('OneVideoBidAdapter', () => { }); }); - describe('spec.interpretResponse', () => { - it('should return no bids if the response is not valid', () => { + describe('spec.interpretResponse', function () { + it('should return no bids if the response is not valid', function () { const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response "nurl" and "adm" are missing', () => { + it('should return no bids if the response "nurl" and "adm" are missing', function () { const serverResponse = {seatbid: [{bid: [{price: 6.01}]}]}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response "price" is missing', () => { + it('should return no bids if the response "price" is missing', function () { const serverResponse = {seatbid: [{bid: [{adm: ''}]}]}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return a valid bid response with just "adm"', () => { + it('should return a valid bid response with just "adm"', function () { const serverResponse = {seatbid: [{bid: [{id: 1, price: 6.01, adm: ''}]}], cur: 'USD'}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); let o = { @@ -132,4 +135,33 @@ describe('OneVideoBidAdapter', () => { expect(bidResponse).to.deep.equal(o); }); }); + + describe('when GDPR applies', function () { + beforeEach(function () { + bidderRequest = { + gdprConsent: { + consentString: 'test-gdpr-consent-string', + gdprApplies: true + } + }; + + mockConfig = { + consentManagement: { + cmpApi: 'iab', + timeout: 1111, + allowAuctionWithoutConsent: 'cancel' + } + }; + }); + + it('should send a signal to specify that GDPR applies to this request', function () { + const request = spec.buildRequests([ bidRequest ], bidderRequest); + expect(request[0].data.regs.ext.gdpr).to.equal(1); + }); + + it('should send the consent string', function () { + const request = spec.buildRequests([ bidRequest ], bidderRequest); + expect(request[0].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString); + }); + }); }); diff --git a/test/spec/modules/oneplanetonlyBidAdapter_spec.js b/test/spec/modules/oneplanetonlyBidAdapter_spec.js index 4a42b471b6f..fbcec66ef51 100644 --- a/test/spec/modules/oneplanetonlyBidAdapter_spec.js +++ b/test/spec/modules/oneplanetonlyBidAdapter_spec.js @@ -1,7 +1,7 @@ import {expect} from 'chai'; import {spec} from '../../../modules/oneplanetonlyBidAdapter'; -describe('OnePlanetOnlyAdapter', () => { +describe('OnePlanetOnlyAdapter', function () { let bid = { bidId: '51ef8751f9aead', bidder: 'oneplanetonly', @@ -16,31 +16,31 @@ describe('OnePlanetOnlyAdapter', () => { auctionId: '18fd8b8b0bd757' }; - describe('isBidRequestValid', () => { - it('Should return true if there are params.siteId and params.adUnitId parameters present', () => { + describe('isBidRequestValid', function () { + it('Should return true if there are params.siteId and params.adUnitId parameters present', function () { expect(spec.isBidRequestValid(bid)).to.be.true; }); - it('Should return false if at least one of parameters is not present', () => { + it('Should return false if at least one of parameters is not present', function () { delete bid.params.adUnitId; expect(spec.isBidRequestValid(bid)).to.be.false; }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let serverRequest = spec.buildRequests([bid]); - it('Creates a ServerRequest object with method, URL and data', () => { + it('Creates a ServerRequest object with method, URL and data', function () { expect(serverRequest).to.exist; expect(serverRequest.method).to.exist; expect(serverRequest.url).to.exist; expect(serverRequest.data).to.exist; }); - it('Returns POST method', () => { + it('Returns POST method', function () { expect(serverRequest.method).to.equal('POST'); }); - it('Returns valid URL', () => { + it('Returns valid URL', function () { expect(serverRequest.url).to.equal('//show.oneplanetonly.com/prebid?siteId=5'); }); - it('Returns valid data if array of bids is valid', () => { + it('Returns valid data if array of bids is valid', function () { let data = serverRequest.data; expect(data).to.be.an('object'); expect(data).to.have.all.keys('id', 'ver', 'prebidVer', 'transactionId', 'currency', 'timeout', 'siteId', @@ -52,14 +52,14 @@ describe('OnePlanetOnlyAdapter', () => { expect(adUnit.bidId).to.equal('51ef8751f9aead'); expect(adUnit.sizes).to.have.members(['300x250', '300x600']); }); - it('Returns empty data if no valid requests are passed', () => { + it('Returns empty data if no valid requests are passed', function () { serverRequest = spec.buildRequests([]); let data = serverRequest.data; expect(data.adUnits).to.be.an('array').that.is.empty; }); }); - describe('interpretResponse', () => { - it('Should interpret banner response', () => { + describe('interpretResponse', function () { + it('Should interpret banner response', function () { const serverResponse = { body: { bids: [{ @@ -89,7 +89,7 @@ describe('OnePlanetOnlyAdapter', () => { expect(bidObject.netRevenue).to.be.true; expect(bidObject.currency).to.equal('USD'); }); - it('Should return an empty array if invalid response is passed', () => { + it('Should return an empty array if invalid response is passed', function () { const invalid = { body: {} }; diff --git a/test/spec/modules/onetagBidAdapter_spec.js b/test/spec/modules/onetagBidAdapter_spec.js index 85597a0c6c6..d56ad9e6dc5 100644 --- a/test/spec/modules/onetagBidAdapter_spec.js +++ b/test/spec/modules/onetagBidAdapter_spec.js @@ -1,7 +1,7 @@ import { spec } from 'modules/onetagBidAdapter'; import { expect } from 'chai'; -describe('onetag', () => { +describe('onetag', function () { let bid = { 'bidder': 'onetag', 'params': { @@ -15,43 +15,43 @@ describe('onetag', () => { 'transactionId': 'qwerty123' }; - describe('isBidRequestValid', () => { - it('Should return true when required params are found', () => { + describe('isBidRequestValid', function () { + it('Should return true when required params are found', function () { expect(spec.isBidRequestValid(bid)).to.be.true; }); - it('Should return false when pubId is not a string', () => { + it('Should return false when pubId is not a string', function () { bid.params.pubId = 30; expect(spec.isBidRequestValid(bid)).to.be.false; }); - it('Should return false when pubId is undefined', () => { + it('Should return false when pubId is undefined', function () { bid.params.pubId = undefined; expect(spec.isBidRequestValid(bid)).to.be.false; }); - it('Should return false when the sizes array is empty', () => { + it('Should return false when the sizes array is empty', function () { bid.sizes = []; expect(spec.isBidRequestValid(bid)).to.be.false; }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let serverRequest = spec.buildRequests([bid]); - it('Creates a ServerRequest object with method, URL and data', () => { + it('Creates a ServerRequest object with method, URL and data', function () { expect(serverRequest).to.exist; expect(serverRequest.method).to.exist; expect(serverRequest.url).to.exist; expect(serverRequest.data).to.exist; }); - it('Returns POST method', () => { + it('Returns POST method', function () { expect(serverRequest.method).to.equal('POST'); }); - it('Returns valid URL', () => { + it('Returns valid URL', function () { expect(serverRequest.url).to.equal('https://onetag-sys.com/prebid-request'); }); const d = serverRequest.data; try { const data = JSON.parse(d); - it('Should contains all keys', () => { + it('Should contains all keys', function () { expect(data).to.be.an('object'); expect(data).to.have.all.keys('location', 'masked', 'referrer', 'sHeight', 'sWidth', 'timeOffset', 'date', 'wHeight', 'wWidth', 'bids'); expect(data.location).to.be.a('string'); @@ -76,7 +76,7 @@ describe('onetag', () => { } catch (e) { console.log('Error while parsing'); } - it('Returns empty data if no valid requests are passed', () => { + it('Returns empty data if no valid requests are passed', function () { serverRequest = spec.buildRequests([]); let dataString = serverRequest.data; try { @@ -86,7 +86,7 @@ describe('onetag', () => { console.log('Error while parsing'); } }); - it('should send GDPR consent data', () => { + it('should send GDPR consent data', function () { let consentString = 'consentString'; let bidderRequest = { 'bidderCode': 'onetag', @@ -107,7 +107,7 @@ describe('onetag', () => { expect(payload.gdprConsent.consentRequired).to.exist.and.to.be.true; }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const resObject = { body: { nobid: false, @@ -123,7 +123,7 @@ describe('onetag', () => { }] } }; - it('Returns an array of valid server responses if response object is valid', () => { + it('Returns an array of valid server responses if response object is valid', function () { const serverResponses = spec.interpretResponse(resObject); expect(serverResponses).to.be.an('array').that.is.not.empty; @@ -140,7 +140,7 @@ describe('onetag', () => { expect(dataItem.netRevenue).to.be.a('boolean'); expect(dataItem.currency).to.be.a('string'); } - it('Returns an empty array if invalid response is passed', () => { + it('Returns an empty array if invalid response is passed', function () { const serverResponses = spec.interpretResponse('invalid_response'); expect(serverResponses).to.be.an('array').that.is.empty; }); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 3585987e045..bce6b2e4acf 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -8,7 +8,7 @@ import * as utils from 'src/utils'; const URLBASE = '/w/1.0/arj'; const URLBASEVIDEO = '/v/1.0/avjp'; -describe('OpenxAdapter', () => { +describe('OpenxAdapter', function () { const adapter = newBidder(spec); /** @@ -121,42 +121,60 @@ describe('OpenxAdapter', () => { } }; - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - describe('when request is for a banner ad', () => { - const bannerBid = { - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: {banner: {}}, - sizes: [[300, 250], [300, 600]], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475' - }; - - it('should return true when required params found', () => { - expect(spec.isBidRequestValid(bannerBid)).to.equal(true); + 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', () => { - let bid = Object.assign({}, bannerBid); - bid.params = {'unit': '12345678'}; - expect(spec.isBidRequestValid(bid)).to.equal(false); + it('should return false when there is no delivery domain', function () { + bannerBid.params = {'unit': '12345678'}; + expect(spec.isBidRequestValid(bannerBid)).to.equal(false); }); - it('should return false when there is no ad unit id ', () => { - let bid = Object.assign({}, bannerBid); - bid.params = {delDomain: 'test-del-domain'}; - expect(spec.isBidRequestValid(bid)).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); + }); }); }); @@ -186,28 +204,28 @@ describe('OpenxAdapter', () => { 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', - 'mediaTypes': 'video', + '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', () => { + 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', () => { + 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); }); - it('should return true when required params found', () => { + 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', () => { + it('should return false when required params are not passed', function () { let videoBidWithMediaType = Object.assign({}, videoBidWithMediaType); delete videoBidWithMediaType.params; videoBidWithMediaType.params = {}; @@ -216,7 +234,7 @@ describe('OpenxAdapter', () => { }); }); - describe('buildRequests for banner ads', () => { + describe('buildRequests for banner ads', function () { const bidRequestsWithMediaType = [{ 'bidder': 'openx', 'params': { @@ -233,32 +251,121 @@ describe('OpenxAdapter', () => { const bidRequestsWithMediaTypes = [{ 'bidder': 'openx', 'params': { - 'unit': '12345678', + 'unit': '11', 'delDomain': 'test-del-domain' }, - 'adUnitCode': 'adunit-code', + 'adUnitCode': '/adunit-code/test-path', mediaTypes: { banner: { sizes: [[300, 250], [300, 600]] } }, - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475' + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'unit': '22', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' }]; - it('should send bid request to openx url via GET, with mediaType specified as banner', () => { + it('should send bid request to openx url via GET, with mediaType specified as banner', function () { const request = spec.buildRequests(bidRequestsWithMediaType); expect(request[0].url).to.equal('//' + bidRequestsWithMediaType[0].params.delDomain + URLBASE); expect(request[0].method).to.equal('GET'); }); - it('should send bid request to openx url via GET, with mediaTypes specified with banner type', () => { + it('should send bid request to openx url via GET, with mediaTypes specified with banner type', function () { const request = spec.buildRequests(bidRequestsWithMediaTypes); expect(request[0].url).to.equal('//' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASE); expect(request[0].method).to.equal('GET'); }); + it('should send the adunit codes', function () { + const request = spec.buildRequests(bidRequestsWithMediaTypes); + expect(request[0].data.divIds).to.equal(`${encodeURIComponent(bidRequestsWithMediaTypes[0].adUnitCode)},${encodeURIComponent(bidRequestsWithMediaTypes[1].adUnitCode)}`); + }); + + it('should send ad unit ids when any are defined', function () { + const bidRequestsWithUnitIds = [{ + 'bidder': 'openx', + 'params': { + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'unit': '22', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithUnitIds); + expect(request[0].data.auid).to.equal(`,${bidRequestsWithUnitIds[1].params.unit}`); + }); + + it('should not send any ad unit ids when none are defined', function () { + const bidRequestsWithoutUnitIds = [{ + 'bidder': 'openx', + 'params': { + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithoutUnitIds); + expect(request[0].data).to.not.have.any.keys('auid'); + }); + describe('when there is a legacy request with no media type', function () { const deprecatedBidRequestsFormatWithNoMediaType = [{ 'bidder': 'openx', @@ -279,7 +386,7 @@ describe('OpenxAdapter', () => { requestData = spec.buildRequests(deprecatedBidRequestsFormatWithNoMediaType)[0].data; }); - it('should have an ad unit id', () => { + it('should have an ad unit id', function () { expect(requestData.auid).to.equal('12345678'); }); @@ -288,7 +395,7 @@ describe('OpenxAdapter', () => { }); }); - it('should send out custom params on bids that have customParams specified', () => { + it('should send out custom params on bids that have customParams specified', function () { const bidRequest = Object.assign({}, bidRequestsWithMediaTypes[0], { @@ -307,7 +414,7 @@ describe('OpenxAdapter', () => { expect(dataParams.tps).to.equal(btoa('test1=testval1.&test2=testval2_,testval3')); }); - it('should send out custom floors on bids that have customFloors specified', () => { + it('should send out custom floors on bids that have customFloors specified', function () { const bidRequest = Object.assign({}, bidRequestsWithMediaTypes[0], { @@ -326,7 +433,7 @@ describe('OpenxAdapter', () => { expect(dataParams.aumfs).to.equal('1500'); }); - it('should send out custom bc parameter, if override is present', () => { + it('should send out custom bc parameter, if override is present', function () { const bidRequest = Object.assign({}, bidRequestsWithMediaTypes[0], { @@ -352,13 +459,13 @@ describe('OpenxAdapter', () => { expect(request[0].data.x_gdpr_f).to.equal(undefined); }); - describe('when there is a consent management framework', () => { + describe('when there is a consent management framework', function () { let bidRequests; let mockConfig; let bidderRequest; const IAB_CONSENT_FRAMEWORK_CODE = 1; - beforeEach(() => { + beforeEach(function () { bidRequests = [{ bidder: 'openx', params: { @@ -524,9 +631,159 @@ describe('OpenxAdapter', () => { }); }); }); + + it('should not send a coppa query param when there are no coppa param settings in the bid requests', function () { + const bidRequestsWithoutCoppa = [{ + bidder: 'openx', + params: { + unit: '11', + delDomain: 'test-del-domain', + coppa: false + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id-1', + bidderRequestId: 'test-bid-request-1', + auctionId: 'test-auction-1' + }, { + bidder: 'openx', + params: { + unit: '22', + delDomain: 'test-del-domain' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + bidId: 'test-bid-id-2', + bidderRequestId: 'test-bid-request-2', + auctionId: 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithoutCoppa); + expect(request[0].data).to.not.have.any.keys('tfcd'); + }); + + it('should send a coppa flag there is when there is coppa param settings in the bid requests', function () { + const bidRequestsWithCoppa = [{ + bidder: 'openx', + params: { + unit: '11', + delDomain: 'test-del-domain', + coppa: false + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id-1', + bidderRequestId: 'test-bid-request-1', + auctionId: 'test-auction-1' + }, { + bidder: 'openx', + params: { + unit: '22', + delDomain: 'test-del-domain', + coppa: true + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + bidId: 'test-bid-id-2', + bidderRequestId: 'test-bid-request-2', + auctionId: 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithCoppa); + expect(request[0].data.tfcd).to.equal(1); + }); + + it('should not send a "no segmentation" flag there no DoNotTrack setting that is set to true', function () { + const bidRequestsWithoutDnt = [{ + bidder: 'openx', + params: { + unit: '11', + delDomain: 'test-del-domain', + doNotTrack: false + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id-1', + bidderRequestId: 'test-bid-request-1', + auctionId: 'test-auction-1' + }, { + bidder: 'openx', + params: { + unit: '22', + delDomain: 'test-del-domain' + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + bidId: 'test-bid-id-2', + bidderRequestId: 'test-bid-request-2', + auctionId: 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithoutDnt); + expect(request[0].data).to.not.have.any.keys('ns'); + }); + + it('should send a "no segmentation" flag there is any DoNotTrack setting that is set to true', function () { + const bidRequestsWithDnt = [{ + bidder: 'openx', + params: { + unit: '11', + delDomain: 'test-del-domain', + doNotTrack: false + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + bidId: 'test-bid-id-1', + bidderRequestId: 'test-bid-request-1', + auctionId: 'test-auction-1' + }, { + bidder: 'openx', + params: { + unit: '22', + delDomain: 'test-del-domain', + doNotTrack: true + }, + adUnitCode: 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + bidId: 'test-bid-id-2', + bidderRequestId: 'test-bid-request-2', + auctionId: 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithDnt); + expect(request[0].data.ns).to.equal(1); + }); }); - describe('buildRequests for video', () => { + describe('buildRequests for video', function () { const bidRequestsWithMediaTypes = [{ 'bidder': 'openx', 'mediaTypes': { @@ -561,19 +818,19 @@ describe('OpenxAdapter', () => { 'transactionId': '4008d88a-8137-410b-aa35-fbfdabcb478e' }]; - it('should send bid request to openx url via GET, with mediaType as video', () => { + it('should send bid request to openx url via GET, with mediaType as video', function () { const request = spec.buildRequests(bidRequestsWithMediaType); expect(request[0].url).to.equal('//' + bidRequestsWithMediaType[0].params.delDomain + URLBASEVIDEO); expect(request[0].method).to.equal('GET'); }); - it('should send bid request to openx url via GET, with mediaTypes having video parameter', () => { + it('should send bid request to openx url via GET, with mediaTypes having video parameter', function () { const request = spec.buildRequests(bidRequestsWithMediaTypes); expect(request[0].url).to.equal('//' + bidRequestsWithMediaTypes[0].params.delDomain + URLBASEVIDEO); expect(request[0].method).to.equal('GET'); }); - it('should have the correct parameters', () => { + it('should have the correct parameters', function () { const request = spec.buildRequests(bidRequestsWithMediaTypes); const dataParams = request[0].data; @@ -582,6 +839,13 @@ describe('OpenxAdapter', () => { expect(dataParams.vwd).to.equal(640); }); + it('should send a bc parameter', function () { + const request = spec.buildRequests(bidRequestsWithMediaTypes); + const dataParams = request[0].data; + + expect(dataParams.bc).to.have.string('hb_pb'); + }); + describe('when using the video param', function () { let videoBidRequest; @@ -669,8 +933,8 @@ describe('OpenxAdapter', () => { }); }); - describe('interpretResponse for banner ads', () => { - beforeEach(() => { + describe('interpretResponse for banner ads', function () { + beforeEach(function () { sinon.spy(userSync, 'registerSync'); }); @@ -766,7 +1030,7 @@ describe('OpenxAdapter', () => { expect(bid.ts).to.equal(adUnitOverride.ts); }); - it('should register a beacon', () => { + it('should register a beacon', function () { resetBoPixel(); spec.interpretResponse({body: bidResponse}, bidRequest); sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(new RegExp(`\/\/openx-d\.openx\.net.*\/bo\?.*ts=${adUnitOverride.ts}`))); @@ -843,7 +1107,7 @@ describe('OpenxAdapter', () => { }; }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { const bidResponse = { 'ads': { @@ -951,8 +1215,8 @@ describe('OpenxAdapter', () => { }); }); - describe('interpretResponse for video ads', () => { - beforeEach(() => { + describe('interpretResponse for video ads', function () { + beforeEach(function () { sinon.spy(userSync, 'registerSync'); }); @@ -1009,7 +1273,7 @@ describe('OpenxAdapter', () => { 'pixels': 'http://testpixels.net' }; - it('should return correct bid response with MediaTypes', () => { + it('should return correct bid response with MediaTypes', function () { const expectedResponse = [ { 'requestId': '30b31c1838de1e', @@ -1030,7 +1294,7 @@ describe('OpenxAdapter', () => { expect(JSON.stringify(Object.keys(result[0]).sort())).to.eql(JSON.stringify(Object.keys(expectedResponse[0]).sort())); }); - it('should return correct bid response with MediaType', () => { + it('should return correct bid response with MediaType', function () { const expectedResponse = [ { 'requestId': '30b31c1838de1e', @@ -1051,19 +1315,19 @@ describe('OpenxAdapter', () => { expect(JSON.stringify(Object.keys(result[0]).sort())).to.eql(JSON.stringify(Object.keys(expectedResponse[0]).sort())); }); - it('should handle nobid responses for bidRequests with MediaTypes', () => { + it('should handle nobid responses for bidRequests with MediaTypes', function () { const bidResponse = {'vastUrl': '', 'pub_rev': '', 'width': '', 'height': '', 'adid': '', 'pixels': ''}; const result = spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaTypes); expect(result.length).to.equal(0); }); - it('should handle nobid responses for bidRequests with MediaType', () => { + it('should handle nobid responses for bidRequests with MediaType', function () { const bidResponse = {'vastUrl': '', 'pub_rev': '', 'width': '', 'height': '', 'adid': '', 'pixels': ''}; const result = spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaType); expect(result.length).to.equal(0); }); - it('should register a beacon', () => { + it('should register a beacon', function () { resetBoPixel(); spec.interpretResponse({body: bidResponse}, bidRequestsWithMediaTypes); sinon.assert.calledWith(userSync.registerSync, 'image', 'openx', sinon.match(/^\/\/test-colo\.com/)) @@ -1072,18 +1336,18 @@ describe('OpenxAdapter', () => { }); }); - describe('user sync', () => { + describe('user sync', function () { const syncUrl = 'http://testpixels.net'; - it('should register the pixel iframe from banner ad response', () => { + it('should register the pixel iframe from banner ad response', function () { let syncs = spec.getUserSyncs( - { iframeEnabled: true }, - [{ body: { ads: { pixels: syncUrl } } }] + {iframeEnabled: true}, + [{body: {ads: {pixels: syncUrl}}}] ); - expect(syncs).to.deep.equal([{ type: 'iframe', url: syncUrl }]); + expect(syncs).to.deep.equal([{type: 'iframe', url: syncUrl}]); }); - it('should register the pixel iframe from video ad response', () => { + it('should register the pixel iframe from video ad response', function () { let syncs = spec.getUserSyncs( {iframeEnabled: true}, [{body: {pixels: syncUrl}}] @@ -1091,7 +1355,7 @@ describe('OpenxAdapter', () => { expect(syncs).to.deep.equal([{type: 'iframe', url: syncUrl}]); }); - it('should register the default iframe if no pixels available', () => { + it('should register the default iframe if no pixels available', function () { let syncs = spec.getUserSyncs( {iframeEnabled: true}, [] diff --git a/test/spec/modules/optimaticBidAdapter_spec.js b/test/spec/modules/optimaticBidAdapter_spec.js index d701d981f37..3dd7ca79cc7 100644 --- a/test/spec/modules/optimaticBidAdapter_spec.js +++ b/test/spec/modules/optimaticBidAdapter_spec.js @@ -2,10 +2,10 @@ import { expect } from 'chai'; import { spec, ENDPOINT } from 'modules/optimaticBidAdapter'; import * as utils from 'src/utils'; -describe('OptimaticBidAdapter', () => { +describe('OptimaticBidAdapter', function () { let bidRequest; - beforeEach(() => { + beforeEach(function () { bidRequest = { bidder: 'optimatic', params: { @@ -20,49 +20,49 @@ describe('OptimaticBidAdapter', () => { }; }); - describe('spec.isBidRequestValid', () => { - it('should return true when the required params are passed', () => { + describe('spec.isBidRequestValid', function () { + it('should return true when the required params are passed', function () { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return false when the "bidfloor" param is missing', () => { + it('should return false when the "bidfloor" param is missing', function () { bidRequest.params = { placement: '2chy7Gc2eSQL' }; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when the "placement" param is missing', () => { + it('should return false when the "placement" param is missing', function () { bidRequest.params = { bidfloor: 5.00 }; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when no bid params are passed', () => { + it('should return false when no bid params are passed', function () { bidRequest.params = {}; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when a bid request is not passed', () => { + it('should return false when a bid request is not passed', function () { expect(spec.isBidRequestValid()).to.equal(false); expect(spec.isBidRequestValid({})).to.equal(false); }); }); - describe('spec.buildRequests', () => { - it('should create a POST request for every bid', () => { + describe('spec.buildRequests', function () { + it('should create a POST request for every bid', function () { const requests = spec.buildRequests([ bidRequest ]); expect(requests[0].method).to.equal('POST'); expect(requests[0].url).to.equal(ENDPOINT + bidRequest.params.placement); }); - it('should attach the bid request object', () => { + it('should attach the bid request object', function () { const requests = spec.buildRequests([ bidRequest ]); expect(requests[0].bidRequest).to.equal(bidRequest); }); - it('should attach request data', () => { + it('should attach request data', function () { const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; const [ width, height ] = bidRequest.sizes; @@ -71,7 +71,7 @@ describe('OptimaticBidAdapter', () => { expect(data.imp[0].bidfloor).to.equal(bidRequest.params.bidfloor); }); - it('must parse bid size from a nested array', () => { + it('must parse bid size from a nested array', function () { const width = 640; const height = 480; bidRequest.sizes = [[ width, height ]]; @@ -81,7 +81,7 @@ describe('OptimaticBidAdapter', () => { expect(data.imp[0].video.h).to.equal(height); }); - it('must parse bid size from a string', () => { + it('must parse bid size from a string', function () { const width = 640; const height = 480; bidRequest.sizes = `${width}x${height}`; @@ -91,7 +91,7 @@ describe('OptimaticBidAdapter', () => { expect(data.imp[0].video.h).to.equal(height); }); - it('must handle an empty bid size', () => { + it('must handle an empty bid size', function () { bidRequest.sizes = []; const requests = spec.buildRequests([ bidRequest ]); const data = requests[0].data; @@ -100,25 +100,25 @@ describe('OptimaticBidAdapter', () => { }); }); - describe('spec.interpretResponse', () => { - it('should return no bids if the response is not valid', () => { + describe('spec.interpretResponse', function () { + it('should return no bids if the response is not valid', function () { const bidResponse = spec.interpretResponse({ body: null }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response "nurl" and "adm" are missing', () => { + it('should return no bids if the response "nurl" and "adm" are missing', function () { const serverResponse = {seatbid: [{bid: [{price: 5.01}]}]}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return no bids if the response "price" is missing', () => { + it('should return no bids if the response "price" is missing', function () { const serverResponse = {seatbid: [{bid: [{adm: ''}]}]}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); expect(bidResponse.length).to.equal(0); }); - it('should return a valid bid response with just "adm"', () => { + it('should return a valid bid response with just "adm"', function () { const serverResponse = {seatbid: [{bid: [{id: 1, price: 5.01, adm: ''}]}], cur: 'USD'}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); let o = { @@ -137,7 +137,7 @@ describe('OptimaticBidAdapter', () => { expect(bidResponse).to.deep.equal(o); }); - it('should return a valid bid response with just "nurl"', () => { + it('should return a valid bid response with just "nurl"', function () { const serverResponse = {seatbid: [{bid: [{id: 1, price: 5.01, nurl: 'https://mg-bid-win.optimatic.com/win/134eb262-948a-463e-ad93-bc8b622d399c?wp=${AUCTION_PRICE}'}]}], cur: 'USD'}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); let o = { @@ -156,7 +156,7 @@ describe('OptimaticBidAdapter', () => { expect(bidResponse).to.deep.equal(o); }); - it('should return a valid bid response with "nurl" when both nurl and adm exist', () => { + it('should return a valid bid response with "nurl" when both nurl and adm exist', function () { const serverResponse = {seatbid: [{bid: [{id: 1, price: 5.01, adm: '', nurl: 'https://mg-bid-win.optimatic.com/win/134eb262-948a-463e-ad93-bc8b622d399c?wp=${AUCTION_PRICE}'}]}], cur: 'USD'}; const bidResponse = spec.interpretResponse({ body: serverResponse }, { bidRequest }); let o = { diff --git a/test/spec/modules/optimeraBidAdapter_spec.js b/test/spec/modules/optimeraBidAdapter_spec.js index 413a52d2d7f..ff5793b5040 100644 --- a/test/spec/modules/optimeraBidAdapter_spec.js +++ b/test/spec/modules/optimeraBidAdapter_spec.js @@ -2,16 +2,16 @@ import { expect } from 'chai'; import { spec } from 'modules/optimeraBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -describe('OptimeraAdapter', () => { +describe('OptimeraAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }) - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'optimera', 'params': { @@ -24,12 +24,12 @@ describe('OptimeraAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); }) - describe('buildRequests', () => { + describe('buildRequests', function () { let bid = [ { 'adUnitCode': 'div-0', @@ -42,7 +42,7 @@ describe('OptimeraAdapter', () => { } } ]; - it('buildRequests fires', () => { + it('buildRequests fires', function () { let request = spec.buildRequests(bid); expect(request).to.exist; expect(request.method).to.equal('GET'); @@ -51,7 +51,7 @@ describe('OptimeraAdapter', () => { }); }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { let serverResponse = {}; serverResponse.body = JSON.parse('{"div-0":["RB_K","728x90K"], "timestamp":["RB_K","1507565666"]}'); var bidRequest = { @@ -67,7 +67,7 @@ describe('OptimeraAdapter', () => { } ] } - it('interpresResponse fires', () => { + it('interpresResponse fires', function () { let bidResponses = spec.interpretResponse(serverResponse, bidRequest); expect(bidResponses[0].dealId[0]).to.equal('RB_K'); expect(bidResponses[0].dealId[1]).to.equal('728x90K'); diff --git a/test/spec/modules/orbitsoftBidAdapter_spec.js b/test/spec/modules/orbitsoftBidAdapter_spec.js index 50145a1e72e..18ba9a6e8f3 100644 --- a/test/spec/modules/orbitsoftBidAdapter_spec.js +++ b/test/spec/modules/orbitsoftBidAdapter_spec.js @@ -2,10 +2,10 @@ import {expect} from 'chai'; import {spec} from 'modules/orbitsoftBidAdapter'; const ENDPOINT_URL = 'https://orbitsoft.com/php/ads/hb.phps'; -describe('Orbitsoft adapter', () => { - describe('implementation', () => { - describe('for requests', () => { - it('should accept valid bid', () => { +describe('Orbitsoft adapter', function () { + describe('implementation', function () { + describe('for requests', function () { + it('should accept valid bid', function () { let validBid = { bidder: 'orbitsoft', params: { @@ -18,7 +18,7 @@ describe('Orbitsoft adapter', () => { expect(isValid).to.equal(true); }); - it('should reject invalid bid', () => { + it('should reject invalid bid', function () { let invalidBid = { bidder: 'orbitsoft' }, @@ -27,8 +27,8 @@ describe('Orbitsoft adapter', () => { expect(isValid).to.equal(false); }); }); - describe('for requests', () => { - it('should accept valid bid with styles', () => { + describe('for requests', function () { + it('should accept valid bid with styles', function () { let validBid = { bidder: 'orbitsoft', params: { @@ -91,7 +91,7 @@ describe('Orbitsoft adapter', () => { expect(requestUrlParams).have.property('c6', '5B99FE'); }); - it('should accept valid bid with custom params', () => { + it('should accept valid bid with custom params', function () { let validBid = { bidder: 'orbitsoft', params: { @@ -112,7 +112,7 @@ describe('Orbitsoft adapter', () => { expect(requestUrlCustomParams).have.property('c.clickUrl', 'http://testclickurl.com'); }); - it('should reject invalid bid without requestUrl', () => { + it('should reject invalid bid without requestUrl', function () { let invalidBid = { bidder: 'orbitsoft', params: { @@ -124,7 +124,7 @@ describe('Orbitsoft adapter', () => { expect(isValid).to.equal(false); }); - it('should reject invalid bid without placementId', () => { + it('should reject invalid bid without placementId', function () { let invalidBid = { bidder: 'orbitsoft', params: { @@ -136,8 +136,8 @@ describe('Orbitsoft adapter', () => { expect(isValid).to.equal(false); }); }); - describe('bid responses', () => { - it('should return complete bid response', () => { + describe('bid responses', function () { + it('should return complete bid response', function () { let serverResponse = { body: { callback_uid: '265b29b70cc106', @@ -168,7 +168,7 @@ describe('Orbitsoft adapter', () => { expect(bids[0].adUrl).to.have.string('https://orbitsoft.com/php/ads/hb.html'); }); - it('should return empty bid response', () => { + it('should return empty bid response', function () { let bidRequests = [ { bidder: 'orbitsoft', @@ -189,7 +189,7 @@ describe('Orbitsoft adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response on incorrect size', () => { + it('should return empty bid response on incorrect size', function () { let bidRequests = [ { bidder: 'orbitsoft', @@ -212,7 +212,7 @@ describe('Orbitsoft adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response with error', () => { + it('should return empty bid response with error', function () { let bidRequests = [ { bidder: 'orbitsoft', @@ -228,7 +228,7 @@ describe('Orbitsoft adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response on empty body', () => { + it('should return empty bid response on empty body', function () { let bidRequests = [ { bidder: 'orbitsoft', diff --git a/test/spec/modules/papyrusBidAdapter_spec.js b/test/spec/modules/papyrusBidAdapter_spec.js index a61a1c55269..289da56379a 100644 --- a/test/spec/modules/papyrusBidAdapter_spec.js +++ b/test/spec/modules/papyrusBidAdapter_spec.js @@ -4,8 +4,8 @@ import { spec } from 'modules/papyrusBidAdapter'; const ENDPOINT = '//prebid.papyrus.global'; const BIDDER_CODE = 'papyrus'; -describe('papyrus Adapter', () => { - describe('isBidRequestValid', () => { +describe('papyrus Adapter', function () { + describe('isBidRequestValid', function () { let validBidReq = { bidder: BIDDER_CODE, params: { @@ -14,7 +14,7 @@ describe('papyrus Adapter', () => { } }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(validBidReq)).to.equal(true); }); @@ -25,12 +25,12 @@ describe('papyrus Adapter', () => { } }; - it('should not validate incorrect bid request', () => { + it('should not validate incorrect bid request', function () { expect(spec.isBidRequestValid(invalidBidReq)).to.equal(false); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { bidder: BIDDER_CODE, @@ -46,29 +46,29 @@ describe('papyrus Adapter', () => { } ]; - it('sends bid request to ENDPOINT via POST', () => { + it('sends bid request to ENDPOINT via POST', function () { const request = spec.buildRequests(bidRequests); expect(request.url).to.equal(ENDPOINT); expect(request.method).to.equal('POST'); }); - it('sends valid bids count', () => { + it('sends valid bids count', function () { const request = spec.buildRequests(bidRequests); expect(request.data.length).to.equal(1); }); - it('sends all bid parameters', () => { + it('sends all bid parameters', function () { const request = spec.buildRequests(bidRequests); expect(request.data[0]).to.have.all.keys(['address', 'placementId', 'sizes', 'bidId', 'transactionId']); }); - it('sedns valid sizes parameter', () => { + it('sedns valid sizes parameter', function () { const request = spec.buildRequests(bidRequests); expect(request.data[0].sizes[0]).to.equal('300x250'); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let bidRequests = [ { bidder: BIDDER_CODE, @@ -96,13 +96,13 @@ describe('papyrus Adapter', () => { ] }; - it('should build bid array', () => { + it('should build bid array', function () { const request = spec.buildRequests(bidRequests); const result = spec.interpretResponse({body: bidResponse}, request[0]); expect(result.length).to.equal(1); }); - it('should have all relevant fields', () => { + it('should have all relevant fields', function () { const request = spec.buildRequests(bidRequests); const result = spec.interpretResponse({body: bidResponse}, request[0]); const bid = result[0]; diff --git a/test/spec/modules/peak226BidAdapter_spec.js b/test/spec/modules/peak226BidAdapter_spec.js index f85e46c4289..8b8157225bb 100644 --- a/test/spec/modules/peak226BidAdapter_spec.js +++ b/test/spec/modules/peak226BidAdapter_spec.js @@ -4,11 +4,11 @@ import { newBidder } from 'src/adapters/bidderFactory'; const URL = 'a.ad216.com/header_bid'; -describe('PeakAdapter', () => { +describe('PeakAdapter', function () { const adapter = newBidder(spec); - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { const bid = { params: { uid: 123 @@ -18,7 +18,7 @@ describe('PeakAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { const bid = { params: {} }; @@ -27,7 +27,7 @@ describe('PeakAdapter', () => { }); }); - // xdescribe('buildRequests', () => { + // xdescribe('buildRequests', function () { // const bidRequests = [ // { // params: { @@ -36,7 +36,7 @@ describe('PeakAdapter', () => { // } // ]; - // it('sends bid request to URL via GET', () => { + // it('sends bid request to URL via GET', function () { // const request = spec.buildRequests(bidRequests); // expect(request.url).to.equal(`${URL}?uids=1234`); @@ -44,8 +44,8 @@ describe('PeakAdapter', () => { // }); // }); - describe('interpretResponse', () => { - it('should handle empty response', () => { + describe('interpretResponse', function () { + it('should handle empty response', function () { let bids = spec.interpretResponse( {}, { @@ -56,7 +56,7 @@ describe('PeakAdapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should handle no seatbid returned', () => { + it('should handle no seatbid returned', function () { let response = {}; let bids = spec.interpretResponse( @@ -69,7 +69,7 @@ describe('PeakAdapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should handle empty seatbid returned', () => { + it('should handle empty seatbid returned', function () { let response = { seatbid: [] }; let bids = spec.interpretResponse( @@ -82,7 +82,7 @@ describe('PeakAdapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should handle seatbid returned bids', () => { + it('should handle seatbid returned bids', function () { const bidsMap = { 1: [{ bidId: 11 }] }; const bid = { price: 0.2, diff --git a/test/spec/modules/piximediaBidAdapter_spec.js b/test/spec/modules/piximediaBidAdapter_spec.js new file mode 100644 index 00000000000..02cf80c614f --- /dev/null +++ b/test/spec/modules/piximediaBidAdapter_spec.js @@ -0,0 +1,102 @@ +import { expect } from 'chai'; +import { spec } from 'modules/piximediaBidAdapter'; + +describe('piximediaAdapterTest', function() { + describe('bidRequestValidity', function() { + it('bidRequest with site ID and placement ID param', function() { + expect(spec.isBidRequestValid({ + bidder: 'piximedia', + params: { + 'siteId': 'PIXIMEDIA_PREBID10', + 'placementId': 'RG' + }, + })).to.equal(true); + }); + + it('bidRequest with no required params', function() { + expect(spec.isBidRequestValid({ + bidder: 'piximedia', + params: { + }, + })).to.equal(false); + }); + }); + + describe('bidRequest', function() { + const bidRequests = [{ + 'bidder': 'piximedia', + 'params': { + 'siteId': 'PIXIMEDIA_PREBID10', + 'placementId': 'RG' + }, + 'adUnitCode': 'div-gpt-ad-1460505748561-0', + 'transactionId': 'd7b773de-ceaa-484d-89ca-d9f51b8d61ec', + 'sizes': [300, 250], + 'bidId': '51ef8751f9aead', + 'bidderRequestId': '418b37f85e772c', + 'auctionId': '18fd8b8b0bd757' + }]; + + it('bidRequest HTTP method', function() { + const requests = spec.buildRequests(bidRequests); + requests.forEach(function(requestItem) { + expect(requestItem.method).to.equal('GET'); + }); + }); + + it('bidRequest data', function() { + const requests = spec.buildRequests(bidRequests); + expect(typeof requests[0].data.timestamp).to.equal('number'); + expect(requests[0].data.pver).to.equal('1.0'); + expect(requests[0].data.pbparams).to.equal(JSON.stringify(bidRequests[0].params)); + expect(requests[0].data.pbwidth).to.equal('300'); + expect(requests[0].data.pbheight).to.equal('250'); + expect(requests[0].data.pbbidid).to.equal('51ef8751f9aead'); + }); + }); + + describe('interpretResponse', function() { + const bidRequest = { + 'method': 'GET', + 'url': 'https://ad.piximedia.com/', + 'data': { + 'ver': 2, + 'hb': 1, + 'output': 'js', + 'pub': 267, + 'zone': 62546, + 'width': '300', + 'height': '250', + 'callback': 'json', + 'callback_uid': '51ef8751f9aead', + 'url': 'https://example.com', + 'cb': '', + } + }; + + const bidResponse = { + body: { + 'bidId': '51ef8751f9aead', + 'cpm': 4.2, + 'width': '300', + 'height': '250', + 'creative_id': '1234', + 'currency': 'EUR', + 'adm': '
', + }, + headers: {} + }; + + it('result is correct', function() { + const result = spec.interpretResponse(bidResponse, bidRequest); + expect(result[0].requestId).to.equal('51ef8751f9aead'); + expect(result[0].cpm).to.equal(4.2); + expect(result[0].width).to.equal('300'); + expect(result[0].height).to.equal('250'); + expect(result[0].creativeId).to.equal('1234'); + expect(result[0].currency).to.equal('EUR'); + expect(result[0].ttl).to.equal(300); + expect(result[0].ad).to.equal('
'); + }); + }); +}); diff --git a/test/spec/modules/platformioBidAdapter_spec.js b/test/spec/modules/platformioBidAdapter_spec.js index fc8ba5bf45e..f3754654cf1 100644 --- a/test/spec/modules/platformioBidAdapter_spec.js +++ b/test/spec/modules/platformioBidAdapter_spec.js @@ -1,316 +1,335 @@ -import {expect} from 'chai'; -import {spec} from 'modules/platformioBidAdapter'; -import {getTopWindowLocation} from 'src/utils'; -import {newBidder} from 'src/adapters/bidderFactory'; - -describe('Platform.io Adapter Tests', () => { - const slotConfigs = [{ - placementCode: '/DfpAccount1/slot1', - bidId: 'bid12345', - mediaType: 'banner', - params: { - pubId: '29521', - siteId: '26047', - placementId: '123', - size: '300x250', - bidFloor: '0.001', - ifa: 'IFA', - latitude: '40.712775', - longitude: '-74.005973' - } - }, { - placementCode: '/DfpAccount2/slot2', - bidId: 'bid23456', - mediaType: 'banner', - params: { - pubId: '29521', - siteId: '26047', - placementId: '1234', - size: '728x90', - bidFloor: '0.000001', - } - }]; - const nativeSlotConfig = [{ - placementCode: '/DfpAccount1/slot3', - bidId: 'bid12345', - mediaType: 'native', - nativeParams: { - title: { required: true, len: 200 }, - body: {}, - image: { wmin: 100 }, - sponsoredBy: { }, - icon: { } - }, - params: { - pubId: '29521', - placementId: '123', - siteId: '26047' - } - }]; - const videoSlotConfig = [{ - placementCode: '/DfpAccount1/slot4', - bidId: 'bid12345678', - mediaType: 'video', - video: { - skippable: true - }, - params: { - pubId: '29521', - placementId: '1234567', - siteId: '26047', - size: '640x480' - } - }]; - const appSlotConfig = [{ - placementCode: '/DfpAccount1/slot5', - bidId: 'bid12345', - params: { - pubId: '29521', - placementId: '1234', - app: { - id: '1111', - name: 'app name', - bundle: 'io.platform.apps', - storeUrl: 'http://platform.io/apps', - domain: 'platform.io' - } - } - }]; - - it('Verify build request', () => { - const request = spec.buildRequests(slotConfigs); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - // site object - expect(ortbRequest.site).to.not.equal(null); - expect(ortbRequest.site.publisher).to.not.equal(null); - expect(ortbRequest.site.publisher.id).to.equal('29521'); - expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); - expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); - expect(ortbRequest.imp).to.have.lengthOf(2); - // device object - expect(ortbRequest.device).to.not.equal(null); - expect(ortbRequest.device.ua).to.equal(navigator.userAgent); - expect(ortbRequest.device.ifa).to.equal('IFA'); - expect(ortbRequest.device.geo.lat).to.equal('40.712775'); - expect(ortbRequest.device.geo.lon).to.equal('-74.005973'); - // slot 1 - expect(ortbRequest.imp[0].tagid).to.equal('123'); - expect(ortbRequest.imp[0].banner).to.not.equal(null); - expect(ortbRequest.imp[0].banner.w).to.equal(300); - expect(ortbRequest.imp[0].banner.h).to.equal(250); - expect(ortbRequest.imp[0].bidfloor).to.equal('0.001'); - // slot 2 - expect(ortbRequest.imp[1].tagid).to.equal('1234'); - expect(ortbRequest.imp[1].banner).to.not.equal(null); - expect(ortbRequest.imp[1].banner.w).to.equal(728); - expect(ortbRequest.imp[1].banner.h).to.equal(90); - expect(ortbRequest.imp[1].bidfloor).to.equal('0.000001'); - }); - - it('Verify parse response', () => { - const request = spec.buildRequests(slotConfigs); - const ortbRequest = JSON.parse(request.data); - const ortbResponse = { - seatbid: [{ - bid: [{ - impid: ortbRequest.imp[0].id, - price: 1.25, - adm: 'This is an Ad' - }] - }], - cur: 'USD' - }; - const bids = spec.interpretResponse({ body: ortbResponse }, request); - expect(bids).to.have.lengthOf(1); - // verify first bid - const bid = bids[0]; - expect(bid.cpm).to.equal(1.25); - expect(bid.ad).to.equal('This is an Ad'); - expect(bid.width).to.equal(300); - expect(bid.height).to.equal(250); - expect(bid.adId).to.equal('bid12345'); - expect(bid.creativeId).to.equal('bid12345'); - expect(bid.netRevenue).to.equal(true); - expect(bid.currency).to.equal('USD'); - expect(bid.ttl).to.equal(360); - }); - - it('Verify full passback', () => { - const request = spec.buildRequests(slotConfigs); - const bids = spec.interpretResponse({ body: null }, request) - expect(bids).to.have.lengthOf(0); - }); - - it('Verify Native request', () => { - const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - // native impression - expect(ortbRequest.imp[0].tagid).to.equal('123'); - const nativePart = ortbRequest.imp[0]['native']; - expect(nativePart).to.not.equal(null); - expect(nativePart.ver).to.equal('1.1'); - expect(nativePart.request).to.not.equal(null); - // native request assets - const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); - expect(nativeRequest).to.not.equal(null); - expect(nativeRequest.assets).to.have.lengthOf(5); - expect(nativeRequest.assets[0].id).to.equal(1); - expect(nativeRequest.assets[1].id).to.equal(2); - expect(nativeRequest.assets[2].id).to.equal(3); - expect(nativeRequest.assets[3].id).to.equal(4); - expect(nativeRequest.assets[4].id).to.equal(5); - expect(nativeRequest.assets[0].required).to.equal(1); - expect(nativeRequest.assets[0].title).to.not.equal(null); - expect(nativeRequest.assets[0].title.len).to.equal(200); - expect(nativeRequest.assets[1].title).to.be.undefined; - expect(nativeRequest.assets[1].data).to.not.equal(null); - expect(nativeRequest.assets[1].data.type).to.equal(2); - expect(nativeRequest.assets[1].data.len).to.equal(200); - expect(nativeRequest.assets[2].required).to.equal(0); - expect(nativeRequest.assets[3].img).to.not.equal(null); - expect(nativeRequest.assets[3].img.wmin).to.equal(50); - expect(nativeRequest.assets[3].img.hmin).to.equal(50); - expect(nativeRequest.assets[3].img.type).to.equal(1); - expect(nativeRequest.assets[4].img).to.not.equal(null); - expect(nativeRequest.assets[4].img.wmin).to.equal(100); - expect(nativeRequest.assets[4].img.hmin).to.equal(150); - expect(nativeRequest.assets[4].img.type).to.equal(3); - }); - - it('Verify Native response', () => { - const request = spec.buildRequests(nativeSlotConfig); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const ortbRequest = JSON.parse(request.data); - const nativeResponse = { - 'native': { - assets: [ - { id: 1, title: { text: 'Ad Title' } }, - { id: 2, data: { value: 'Test description' } }, - { id: 3, data: { value: 'Brand' } }, - { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png', w: 100, h: 100 } }, - { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png', w: 300, h: 300 } } - ], - link: { url: 'http://brand.com/' } - } - }; - const ortbResponse = { - seatbid: [{ - bid: [{ - impid: ortbRequest.imp[0].id, - price: 1.25, - nurl: 'http://rtb.adx1.com/log', - adm: JSON.stringify(nativeResponse) - }] - }], - cur: 'USD', - }; - const bids = spec.interpretResponse({ body: ortbResponse }, request); - // verify bid - const bid = bids[0]; - expect(bid.cpm).to.equal(1.25); - expect(bid.adId).to.equal('bid12345'); - expect(bid.ad).to.be.undefined; - expect(bid.mediaType).to.equal('native'); - const nativeBid = bid['native']; - expect(nativeBid).to.not.equal(null); - expect(nativeBid.title).to.equal('Ad Title'); - expect(nativeBid.sponsoredBy).to.equal('Brand'); - expect(nativeBid.icon.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); - expect(nativeBid.image.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); - expect(nativeBid.image.width).to.equal(300); - expect(nativeBid.image.height).to.equal(300); - expect(nativeBid.icon.width).to.equal(100); - expect(nativeBid.icon.height).to.equal(100); - expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.com/')); - expect(nativeBid.impressionTrackers).to.have.lengthOf(1); - expect(nativeBid.impressionTrackers[0]).to.equal('http://rtb.adx1.com/log'); - }); - - it('Verify Video request', () => { - const request = spec.buildRequests(videoSlotConfig); - expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); - expect(request.method).to.equal('POST'); - const videoRequest = JSON.parse(request.data); - // site object - expect(videoRequest.site).to.not.equal(null); - expect(videoRequest.site.publisher.id).to.equal('29521'); - expect(videoRequest.site.ref).to.equal(window.top.document.referrer); - expect(videoRequest.site.page).to.equal(getTopWindowLocation().href); - // device object - expect(videoRequest.device).to.not.equal(null); - expect(videoRequest.device.ua).to.equal(navigator.userAgent); - // slot 1 - expect(videoRequest.imp[0].tagid).to.equal('1234567'); - expect(videoRequest.imp[0].video).to.not.equal(null); - expect(videoRequest.imp[0].video.w).to.equal(640); - expect(videoRequest.imp[0].video.h).to.equal(480); - expect(videoRequest.imp[0].banner).to.equal(null); - expect(videoRequest.imp[0].native).to.equal(null); - }); - - it('Verify parse video response', () => { - const request = spec.buildRequests(videoSlotConfig); - const videoRequest = JSON.parse(request.data); - const videoResponse = { - seatbid: [{ - bid: [{ - impid: videoRequest.imp[0].id, - price: 1.90, - adm: 'http://vid.example.com/9876', - crid: '510511_754567308' - }] - }], - cur: 'USD' - }; - const bids = spec.interpretResponse({ body: videoResponse }, request); - expect(bids).to.have.lengthOf(1); - // verify first bid - const bid = bids[0]; - expect(bid.cpm).to.equal(1.90); - expect(bid.vastUrl).to.equal('http://vid.example.com/9876'); - expect(bid.crid).to.equal('510511_754567308'); - expect(bid.width).to.equal(640); - expect(bid.height).to.equal(480); - expect(bid.adId).to.equal('bid12345678'); - expect(bid.netRevenue).to.equal(true); - expect(bid.currency).to.equal('USD'); - expect(bid.ttl).to.equal(360); - }); - - it('Verifies bidder code', () => { - expect(spec.code).to.equal('platformio'); - }); - - it('Verifies supported media types', () => { - expect(spec.supportedMediaTypes).to.have.lengthOf(3); - expect(spec.supportedMediaTypes[0]).to.equal('banner'); - expect(spec.supportedMediaTypes[1]).to.equal('native'); - expect(spec.supportedMediaTypes[2]).to.equal('video'); - }); - - it('Verifies if bid request valid', () => { - expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); - expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); - expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); - expect(spec.isBidRequestValid(videoSlotConfig[0])).to.equal(true); - }); - - it('Verify app requests', () => { - const request = spec.buildRequests(appSlotConfig); - const ortbRequest = JSON.parse(request.data); - expect(ortbRequest.site).to.equal(null); - expect(ortbRequest.app).to.not.be.null; - expect(ortbRequest.app.publisher).to.not.equal(null); - expect(ortbRequest.app.publisher.id).to.equal('29521'); - expect(ortbRequest.app.id).to.equal('1111'); - expect(ortbRequest.app.name).to.equal('app name'); - expect(ortbRequest.app.bundle).to.equal('io.platform.apps'); - expect(ortbRequest.app.storeurl).to.equal('http://platform.io/apps'); - expect(ortbRequest.app.domain).to.equal('platform.io'); - }); -}); +import {expect} from 'chai'; +import {spec} from 'modules/platformioBidAdapter'; +import {getTopWindowLocation} from 'src/utils'; +import {newBidder} from 'src/adapters/bidderFactory'; + +describe('Platform.io Adapter Tests', function () { + const slotConfigs = [{ + placementCode: '/DfpAccount1/slot1', + bidId: 'bid12345', + mediaType: 'banner', + params: { + pubId: '29521', + siteId: '26047', + placementId: '123', + size: '300x250', + bidFloor: '0.001', + ifa: 'IFA', + latitude: '40.712775', + longitude: '-74.005973' + } + }, { + placementCode: '/DfpAccount2/slot2', + bidId: 'bid23456', + mediaType: 'banner', + params: { + pubId: '29521', + siteId: '26047', + placementId: '1234', + size: '728x90', + bidFloor: '0.000001', + } + }]; + const nativeSlotConfig = [{ + placementCode: '/DfpAccount1/slot3', + bidId: 'bid12345', + mediaType: 'native', + nativeParams: { + title: { required: true, len: 200 }, + body: {}, + image: { wmin: 100 }, + sponsoredBy: { }, + icon: { } + }, + params: { + pubId: '29521', + placementId: '123', + siteId: '26047' + } + }]; + const videoSlotConfig = [{ + placementCode: '/DfpAccount1/slot4', + bidId: 'bid12345678', + mediaType: 'video', + video: { + skippable: true + }, + params: { + pubId: '29521', + placementId: '1234567', + siteId: '26047', + size: '640x480' + } + }]; + const appSlotConfig = [{ + placementCode: '/DfpAccount1/slot5', + bidId: 'bid12345', + params: { + pubId: '29521', + placementId: '1234', + app: { + id: '1111', + name: 'app name', + bundle: 'io.platform.apps', + storeUrl: 'http://platform.io/apps', + domain: 'platform.io' + } + } + }]; + + it('Verify build request', function () { + const request = spec.buildRequests(slotConfigs); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // site object + expect(ortbRequest.site).to.not.equal(null); + expect(ortbRequest.site.publisher).to.not.equal(null); + expect(ortbRequest.site.publisher.id).to.equal('29521'); + expect(ortbRequest.site.ref).to.equal(window.top.document.referrer); + expect(ortbRequest.site.page).to.equal(getTopWindowLocation().href); + expect(ortbRequest.imp).to.have.lengthOf(2); + // device object + expect(ortbRequest.device).to.not.equal(null); + expect(ortbRequest.device.ua).to.equal(navigator.userAgent); + expect(ortbRequest.device.ifa).to.equal('IFA'); + expect(ortbRequest.device.geo.lat).to.equal('40.712775'); + expect(ortbRequest.device.geo.lon).to.equal('-74.005973'); + // slot 1 + expect(ortbRequest.imp[0].tagid).to.equal('123'); + expect(ortbRequest.imp[0].banner).to.not.equal(null); + expect(ortbRequest.imp[0].banner.w).to.equal(300); + expect(ortbRequest.imp[0].banner.h).to.equal(250); + expect(ortbRequest.imp[0].bidfloor).to.equal('0.001'); + // slot 2 + expect(ortbRequest.imp[1].tagid).to.equal('1234'); + expect(ortbRequest.imp[1].banner).to.not.equal(null); + expect(ortbRequest.imp[1].banner.w).to.equal(728); + expect(ortbRequest.imp[1].banner.h).to.equal(90); + expect(ortbRequest.imp[1].bidfloor).to.equal('0.000001'); + }); + + it('Verify parse response', function () { + const request = spec.buildRequests(slotConfigs); + const ortbRequest = JSON.parse(request.data); + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + adm: 'This is an Ad' + }] + }], + cur: 'USD' + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + expect(bids).to.have.lengthOf(1); + // verify first bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.ad).to.equal('This is an Ad'); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + expect(bid.adId).to.equal('bid12345'); + expect(bid.creativeId).to.equal('bid12345'); + expect(bid.netRevenue).to.equal(true); + expect(bid.currency).to.equal('USD'); + expect(bid.ttl).to.equal(360); + }); + + it('Verify full passback', function () { + const request = spec.buildRequests(slotConfigs); + const bids = spec.interpretResponse({ body: null }, request) + expect(bids).to.have.lengthOf(0); + }); + + it('Verify Native request', function () { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + // native impression + expect(ortbRequest.imp[0].tagid).to.equal('123'); + const nativePart = ortbRequest.imp[0]['native']; + expect(nativePart).to.not.equal(null); + expect(nativePart.ver).to.equal('1.1'); + expect(nativePart.request).to.not.equal(null); + // native request assets + const nativeRequest = JSON.parse(ortbRequest.imp[0]['native'].request); + expect(nativeRequest).to.not.equal(null); + expect(nativeRequest.assets).to.have.lengthOf(5); + expect(nativeRequest.assets[0].id).to.equal(1); + expect(nativeRequest.assets[1].id).to.equal(2); + expect(nativeRequest.assets[2].id).to.equal(3); + expect(nativeRequest.assets[3].id).to.equal(4); + expect(nativeRequest.assets[4].id).to.equal(5); + expect(nativeRequest.assets[0].required).to.equal(1); + expect(nativeRequest.assets[0].title).to.not.equal(null); + expect(nativeRequest.assets[0].title.len).to.equal(200); + expect(nativeRequest.assets[1].title).to.be.undefined; + expect(nativeRequest.assets[1].data).to.not.equal(null); + expect(nativeRequest.assets[1].data.type).to.equal(2); + expect(nativeRequest.assets[1].data.len).to.equal(200); + expect(nativeRequest.assets[2].required).to.equal(0); + expect(nativeRequest.assets[3].img).to.not.equal(null); + expect(nativeRequest.assets[3].img.wmin).to.equal(50); + expect(nativeRequest.assets[3].img.hmin).to.equal(50); + expect(nativeRequest.assets[3].img.type).to.equal(1); + expect(nativeRequest.assets[4].img).to.not.equal(null); + expect(nativeRequest.assets[4].img.wmin).to.equal(100); + expect(nativeRequest.assets[4].img.hmin).to.equal(150); + expect(nativeRequest.assets[4].img.type).to.equal(3); + }); + + it('Verify Native response', function () { + const request = spec.buildRequests(nativeSlotConfig); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + const nativeResponse = { + 'native': { + assets: [ + { id: 1, title: { text: 'Ad Title' } }, + { id: 2, data: { value: 'Test description' } }, + { id: 3, data: { value: 'Brand' } }, + { id: 4, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_icon.png', w: 100, h: 100 } }, + { id: 5, img: { url: 'https://s3.amazonaws.com/adx1public/creatives_image.png', w: 300, h: 300 } } + ], + link: { url: 'http://brand.com/' } + } + }; + const ortbResponse = { + seatbid: [{ + bid: [{ + impid: ortbRequest.imp[0].id, + price: 1.25, + nurl: 'http://rtb.adx1.com/log', + adm: JSON.stringify(nativeResponse) + }] + }], + cur: 'USD', + }; + const bids = spec.interpretResponse({ body: ortbResponse }, request); + // verify bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.25); + expect(bid.adId).to.equal('bid12345'); + expect(bid.ad).to.be.undefined; + expect(bid.mediaType).to.equal('native'); + const nativeBid = bid['native']; + expect(nativeBid).to.not.equal(null); + expect(nativeBid.title).to.equal('Ad Title'); + expect(nativeBid.sponsoredBy).to.equal('Brand'); + expect(nativeBid.icon.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_icon.png'); + expect(nativeBid.image.url).to.equal('https://s3.amazonaws.com/adx1public/creatives_image.png'); + expect(nativeBid.image.width).to.equal(300); + expect(nativeBid.image.height).to.equal(300); + expect(nativeBid.icon.width).to.equal(100); + expect(nativeBid.icon.height).to.equal(100); + expect(nativeBid.clickUrl).to.equal(encodeURIComponent('http://brand.com/')); + expect(nativeBid.impressionTrackers).to.have.lengthOf(1); + expect(nativeBid.impressionTrackers[0]).to.equal('http://rtb.adx1.com/log'); + }); + + it('Verify Video request', function () { + const request = spec.buildRequests(videoSlotConfig); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const videoRequest = JSON.parse(request.data); + // site object + expect(videoRequest.site).to.not.equal(null); + expect(videoRequest.site.publisher.id).to.equal('29521'); + expect(videoRequest.site.ref).to.equal(window.top.document.referrer); + expect(videoRequest.site.page).to.equal(getTopWindowLocation().href); + // device object + expect(videoRequest.device).to.not.equal(null); + expect(videoRequest.device.ua).to.equal(navigator.userAgent); + // slot 1 + expect(videoRequest.imp[0].tagid).to.equal('1234567'); + expect(videoRequest.imp[0].video).to.not.equal(null); + expect(videoRequest.imp[0].video.w).to.equal(640); + expect(videoRequest.imp[0].video.h).to.equal(480); + expect(videoRequest.imp[0].banner).to.equal(null); + expect(videoRequest.imp[0].native).to.equal(null); + }); + + it('Verify parse video response', function () { + const request = spec.buildRequests(videoSlotConfig); + const videoRequest = JSON.parse(request.data); + const videoResponse = { + seatbid: [{ + bid: [{ + impid: videoRequest.imp[0].id, + price: 1.90, + adm: 'http://vid.example.com/9876', + crid: '510511_754567308' + }] + }], + cur: 'USD' + }; + const bids = spec.interpretResponse({ body: videoResponse }, request); + expect(bids).to.have.lengthOf(1); + // verify first bid + const bid = bids[0]; + expect(bid.cpm).to.equal(1.90); + expect(bid.vastUrl).to.equal('http://vid.example.com/9876'); + expect(bid.crid).to.equal('510511_754567308'); + expect(bid.width).to.equal(640); + expect(bid.height).to.equal(480); + expect(bid.adId).to.equal('bid12345678'); + expect(bid.netRevenue).to.equal(true); + expect(bid.currency).to.equal('USD'); + expect(bid.ttl).to.equal(360); + }); + + it('Verifies bidder code', function () { + expect(spec.code).to.equal('platformio'); + }); + + it('Verifies supported media types', function () { + expect(spec.supportedMediaTypes).to.have.lengthOf(3); + expect(spec.supportedMediaTypes[0]).to.equal('banner'); + expect(spec.supportedMediaTypes[1]).to.equal('native'); + expect(spec.supportedMediaTypes[2]).to.equal('video'); + }); + + it('Verifies if bid request valid', function () { + expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); + expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); + expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); + expect(spec.isBidRequestValid(videoSlotConfig[0])).to.equal(true); + }); + + it('Verify app requests', function () { + const request = spec.buildRequests(appSlotConfig); + const ortbRequest = JSON.parse(request.data); + expect(ortbRequest.site).to.equal(null); + expect(ortbRequest.app).to.not.be.null; + expect(ortbRequest.app.publisher).to.not.equal(null); + expect(ortbRequest.app.publisher.id).to.equal('29521'); + expect(ortbRequest.app.id).to.equal('1111'); + expect(ortbRequest.app.name).to.equal('app name'); + expect(ortbRequest.app.bundle).to.equal('io.platform.apps'); + expect(ortbRequest.app.storeurl).to.equal('http://platform.io/apps'); + expect(ortbRequest.app.domain).to.equal('platform.io'); + }); + + it('Verify GDPR', function () { + const bidderRequest = { + gdprConsent: { + gdprApplies: true, + consentString: 'serialized_gpdr_data' + } + }; + const request = spec.buildRequests(slotConfigs, bidderRequest); + expect(request.url).to.equal('//piohbdisp.hb.adx1.com/'); + expect(request.method).to.equal('POST'); + const ortbRequest = JSON.parse(request.data); + expect(ortbRequest.user).to.not.equal(null); + expect(ortbRequest.user.ext).to.not.equal(null); + expect(ortbRequest.user.ext.consent).to.equal('serialized_gpdr_data'); + expect(ortbRequest.regs).to.not.equal(null); + expect(ortbRequest.regs.ext).to.not.equal(null); + expect(ortbRequest.regs.ext.gdpr).to.equal(1); + }); +}); diff --git a/test/spec/modules/playgroundxyzBidAdapter_spec.js b/test/spec/modules/playgroundxyzBidAdapter_spec.js new file mode 100644 index 00000000000..ac0922ef82e --- /dev/null +++ b/test/spec/modules/playgroundxyzBidAdapter_spec.js @@ -0,0 +1,185 @@ +import { expect } from 'chai'; +import { spec } from 'modules/playgroundxyzBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { deepClone } from 'src/utils'; + +const URL = 'https://ads.playground.xyz/host-config/prebid'; +const GDPR_CONSENT = 'XYZ-CONSENT'; + +describe('playgroundxyzBidAdapter', function () { + 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 () { + let bid = { + 'bidder': 'playgroundxyz', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [320, 50]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [ + { + 'bidder': 'playgroundxyz', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('sends bid request to ENDPOINT via POST', function () { + let bidRequest = Object.assign([], bidRequests); + + const request = spec.buildRequests(bidRequest); + const data = JSON.parse(request.data); + const banner = data.imp[0].banner; + + expect(Object.keys(data.imp[0].ext)).to.have.members(['appnexus']); + expect([banner.w, banner.h]).to.deep.equal([300, 250]); + expect(banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); + expect(request.url).to.equal(URL); + expect(request.method).to.equal('POST'); + }); + }) + + describe('interpretResponse', function () { + let response = { + 'id': 'bidd_id', + 'seatbid': [ { + 'bid': [ + { + 'id': '4434762738980910431', + 'impid': '221f2bdc1fbc31', + 'price': 1, + 'adid': '91673066', + 'adm': '', + 'adomain': [ 'pg.xyz' ], + 'iurl': 'http://pgxyz.com/cr?id=91673066', + 'cid': 'c_id', + 'crid': 'c_rid', + 'h': 50, + 'w': 320, + 'ext': { + 'appnexus': { + 'brand_id': 1, + 'auction_id': 1087655594852566000, + 'bidder_id': 2, + 'bid_ad_type': 0 + } + } + } + ], + 'seat': '4321' + }], + 'bidid': '6894227111893743356', + 'cur': 'USD' + }; + + let bidderRequest = { + 'bidderCode': 'playgroundxyz' + }; + + it('should get correct bid response', function () { + let expectedResponse = [ + { + 'requestId': '221f2bdc1fbc31', + 'cpm': 1, + 'creativeId': 91673066, + 'width': 300, + 'height': 50, + 'ad': '', + 'mediaType': 'banner', + 'currency': 'USD', + 'ttl': 300, + 'netRevenue': true + } + ]; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', function () { + let response = ''; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(result.length).to.equal(0); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [ + { + 'bidder': 'playgroundxyz', + 'params': { + 'publisherId': 'PUB_FAKE' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250]], + 'bidId': '321db112312as', + 'bidderRequestId': '23edabce2731sd6', + 'auctionId': '12as040790a475' + } + ]; + + it('should not populate GDPR', function () { + let bidRequest = Object.assign([], bidRequests); + const request = spec.buildRequests(bidRequest); + let data = JSON.parse(request.data); + expect(data).to.not.have.property('user'); + expect(data).to.not.have.property('regs'); + }); + + it('should populate GDPR and consent string when consetString is presented but not gdpApplies', function () { + let bidRequest = Object.assign([], bidRequests); + const request = spec.buildRequests(bidRequest, {gdprConsent: {consentString: GDPR_CONSENT}}); + let data = JSON.parse(request.data); + expect(data.regs.ext.gdpr).to.equal(0); + expect(data.user.ext.consent).to.equal('XYZ-CONSENT'); + }); + + it('should populate GDPR and consent string when gdpr is set to true', function () { + let bidRequest = Object.assign([], bidRequests); + const request = spec.buildRequests(bidRequest, {gdprConsent: {gdprApplies: true, consentString: GDPR_CONSENT}}); + let data = JSON.parse(request.data); + expect(data.regs.ext.gdpr).to.equal(1); + expect(data.user.ext.consent).to.equal('XYZ-CONSENT'); + }); + + it('should populate GDPR and consent string when gdpr is set to false', function () { + let bidRequest = Object.assign([], bidRequests); + const request = spec.buildRequests(bidRequest, {gdprConsent: {gdprApplies: false, consentString: GDPR_CONSENT}}); + let data = JSON.parse(request.data); + expect(data.regs.ext.gdpr).to.equal(0); + expect(data.user.ext.consent).to.equal('XYZ-CONSENT'); + }); + }); +}); diff --git a/test/spec/modules/polluxBidAdapter_spec.js b/test/spec/modules/polluxBidAdapter_spec.js index ea550fecd71..ad30771e15b 100644 --- a/test/spec/modules/polluxBidAdapter_spec.js +++ b/test/spec/modules/polluxBidAdapter_spec.js @@ -24,7 +24,7 @@ describe('POLLUX Bid Adapter tests', function () { params: {zone: '276'} }]; - it('TEST: verify buildRequests no valid bid requests', () => { + it('TEST: verify buildRequests no valid bid requests', function () { let request = spec.buildRequests(false); expect(request).to.not.equal(null); expect(request).to.not.have.property('method'); @@ -47,7 +47,7 @@ describe('POLLUX Bid Adapter tests', function () { expect(request).to.not.have.property('data'); }); - it('TEST: verify buildRequests single bid', () => { + it('TEST: verify buildRequests single bid', function () { const request = spec.buildRequests(setup_single_bid); expect(request.method).to.equal('POST'); const requested_bids = JSON.parse(request.data); @@ -70,7 +70,7 @@ describe('POLLUX Bid Adapter tests', function () { expect(requested_bids[0].zones).to.equal('1806,276'); }); - it('TEST: verify buildRequests multi bid', () => { + it('TEST: verify buildRequests multi bid', function () { const request = spec.buildRequests(setup_multi_bid); expect(request.method).to.equal('POST'); const requested_bids = JSON.parse(request.data); @@ -102,7 +102,7 @@ describe('POLLUX Bid Adapter tests', function () { expect(requested_bids[1].zones).to.equal('276'); }); - it('TEST: verify interpretResponse empty', () => { + it('TEST: verify interpretResponse empty', function () { let bids = spec.interpretResponse(false, {}); expect(bids).to.not.equal(null); expect(bids).to.have.lengthOf(0); @@ -117,7 +117,7 @@ describe('POLLUX Bid Adapter tests', function () { expect(bids).to.have.lengthOf(0); }); - it('TEST: verify interpretResponse ad_type url', () => { + it('TEST: verify interpretResponse ad_type url', function () { const serverResponse = { body: [ { @@ -147,7 +147,7 @@ describe('POLLUX Bid Adapter tests', function () { expect(bids[0]).to.not.have.property('ad'); }); - it('TEST: verify interpretResponse ad_type html', () => { + it('TEST: verify interpretResponse ad_type html', function () { const serverResponse = { body: [ { @@ -176,7 +176,7 @@ describe('POLLUX Bid Adapter tests', function () { expect(bids[0].ad).to.equal('

I am an ad

'); }); - it('TEST: verify url and query params', () => { + it('TEST: verify url and query params', function () { const URL = require('url-parse'); const querystringify = require('querystringify'); const request = spec.buildRequests(setup_single_bid); @@ -188,7 +188,7 @@ describe('POLLUX Bid Adapter tests', function () { expect(parsedQuery).to.have.property('domain').and.to.have.length.above(1); }); - it('TEST: verify isBidRequestValid', () => { + it('TEST: verify isBidRequestValid', function () { expect(spec.isBidRequestValid({})).to.equal(false); expect(spec.isBidRequestValid({params: {}})).to.equal(false); expect(spec.isBidRequestValid(setup_single_bid[0])).to.equal(true); @@ -196,11 +196,11 @@ describe('POLLUX Bid Adapter tests', function () { expect(spec.isBidRequestValid(setup_multi_bid[1])).to.equal(true); }); - it('TEST: verify bidder code', () => { + it('TEST: verify bidder code', function () { expect(spec.code).to.equal('pollux'); }); - it('TEST: verify bidder aliases', () => { + it('TEST: verify bidder aliases', function () { expect(spec.aliases).to.have.lengthOf(1); expect(spec.aliases[0]).to.equal('plx'); }); diff --git a/test/spec/modules/polymorphBidAdapter_spec.js b/test/spec/modules/polymorphBidAdapter_spec.js new file mode 100644 index 00000000000..e2df44e8cfc --- /dev/null +++ b/test/spec/modules/polymorphBidAdapter_spec.js @@ -0,0 +1,183 @@ +import { expect } from 'chai'; +import { polymorphAdapterSpec } from 'modules/polymorphBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const BIDDER_CODE = 'polymorph'; +const ENDPOINT_URL = '//api.adsnative.com/v1/ad-template.json'; +const PLACEMENT_ID = 'ping'; + +const spec = newBidder(polymorphAdapterSpec).getSpec(); + +const bidRequests = [{ + 'bidder': BIDDER_CODE, + 'params': { + 'placementId': PLACEMENT_ID + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', +}, +{ + 'bidder': BIDDER_CODE, + 'params': { + 'placementId': PLACEMENT_ID, + 'defaultWidth': 300, + 'defaultHeight': 600, + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[700, 250], [300, 600]], + 'bidId': '30b31c1838de1d', + 'bidderRequestId': '22edbae2733bf7', + 'auctionId': '1d1a030790a476', +}]; + +describe('Polymorph adapter test', function () { + describe('.code', function () { + it('should return a bidder code of polymorph', function () { + expect(spec.code).to.eql(BIDDER_CODE); + }); + }); + + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bidRequests[0])).to.equal(true); + }); + + it('should return false if req has no placementId', function () { + const invalidBidRequest = { + bidder: BIDDER_CODE, + params: { + someKey: 'abc123' + } + }; + expect(spec.isBidRequestValid(invalidBidRequest)).to.eql(false); + }); + + it('should return false if req has wrong bidder code', function () { + const invalidBidRequest = { + bidder: 'something', + params: { + someKey: 'abc123' + } + }; + expect(spec.isBidRequestValid(invalidBidRequest)).to.eql(false); + }); + }); + + describe('buildRequests', function () { + it('payload test', function () { + const requests = spec.buildRequests(bidRequests); + var payload1 = {}; + requests[0].data.replace(/([^=&]+)=([^&]*)/g, function(m, key, value) { + payload1[decodeURIComponent(key)] = decodeURIComponent(value); + }); + expect(payload1.ref).to.not.be.undefined; + expect(payload1.url).to.not.be.undefined; + expect(payload1.hb).to.equal('1'); + expect(payload1.hb_source).to.equal('prebid'); + expect(payload1.zid).to.equal(PLACEMENT_ID); + expect(payload1.sizes).to.equal('300,250,300,600'); + + var payload2 = {}; + requests[1].data.replace(/([^=&]+)=([^&]*)/g, function(m, key, value) { + payload2[decodeURIComponent(key)] = decodeURIComponent(value); + }); + expect(payload2.ref).to.not.be.undefined; + expect(payload2.url).to.not.be.undefined; + expect(payload2.hb).to.equal('1'); + expect(payload2.hb_source).to.equal('prebid'); + expect(payload2.zid).to.equal(PLACEMENT_ID); + expect(payload2.sizes).to.equal('700,250,300,600'); + }); + + it('sends bid request to ENDPOINT via GET', function () { + const requests = spec.buildRequests(bidRequests); + expect(requests[0].url).to.equal(ENDPOINT_URL); + expect(requests[0].method).to.equal('GET'); + }); + }); + + describe('interpretResponse', function () { + const response = { + body: { + 'status': 'OK', + 'crid': '5ISP4995', + 'ecpm': 10, + 'ad': { + 'html': '
', + 'height': 250, + 'width': 300 + } + } + }; + + const response2 = { + body: { + 'status': 'OK', + 'ecpm': 10, + 'html': '', + 'ads': [{ + 'crid': '5ISP4995', + 'ad': { + 'html': '
' + } + }, + { + 'crid': '5ISP4996', + 'ad': { + 'html': '
' + } + }] + } + }; + + it('should get correct bid response', function () { + const body = response.body; + const expectedResponse = [{ + requestId: bidRequests[0].bidId, + cpm: body.ecpm, + width: body.ad.width, + height: body.ad.height, + ad: body.ad.html, + ttl: 3600, + creativeId: body.crid, + netRevenue: false, + currency: 'USD', + mediaType: 'banner' + }]; + + let result = spec.interpretResponse(response, { 'bidderRequest': bidRequests[0] }); + expect(result).to.deep.equal(expectedResponse); + }); + + it('widget use case', function () { + const body = response2.body; + const expectedResponse = [ + { + requestId: bidRequests[1].bidId, + cpm: body.ecpm, + width: 300, + height: 600, + ad: body.html, + ttl: 3600, + creativeId: body.ads[0].crid, + netRevenue: false, + currency: 'USD', + mediaType: 'banner' + } + ]; + + let result = spec.interpretResponse(response2, { 'bidderRequest': bidRequests[1] }); + expect(result).to.deep.equal(expectedResponse); + }); + + it('handles nobid responses', function () { + let response = []; + + let result = spec.interpretResponse(response, { 'bidderRequest': bidRequests[0] }); + expect(result.length).to.equal(0); + }); + }); +}); diff --git a/test/spec/modules/prebidServerBidAdapter_spec.js b/test/spec/modules/prebidServerBidAdapter_spec.js index d528c9a3191..7c3a356c9e8 100644 --- a/test/spec/modules/prebidServerBidAdapter_spec.js +++ b/test/spec/modules/prebidServerBidAdapter_spec.js @@ -1,5 +1,5 @@ import { expect } from 'chai'; -import { PrebidServer as Adapter, resetSyncedStatus } from 'modules/prebidServerBidAdapter'; +import { PrebidServer as Adapter, resetSyncedStatus } from 'modules/prebidServerBidAdapter/index.js'; import adapterManager from 'src/adaptermanager'; import * as utils from 'src/utils'; import cookie from 'src/cookie'; @@ -246,7 +246,7 @@ const RESPONSE_OPENRTB = { 'bid': [ { 'id': '8750901685062148', - 'impid': '123', + 'impid': 'div-gpt-ad-1460505748561-0', 'price': 0.5, 'adm': '', 'adid': '29681110', @@ -285,7 +285,7 @@ const RESPONSE_OPENRTB_VIDEO = { bid: [ { id: '1987250005171537465', - impid: '/19968336/header-bid-tag-0', + impid: 'div-gpt-ad-1460505748561-0', price: 10, adm: 'adnxs', adid: '81877115', @@ -329,12 +329,12 @@ const RESPONSE_UNSUPPORTED_BIDDER = { }] }; -describe('S2S Adapter', () => { +describe('S2S Adapter', function () { let adapter, addBidResponse = sinon.spy(), done = sinon.spy(); - beforeEach(() => { + beforeEach(function () { adapter = new Adapter(); BID_REQUESTS = [ { @@ -347,7 +347,11 @@ describe('S2S Adapter', () => { 'bidder': 'appnexus', 'params': { 'placementId': '10433394', - 'member': 123 + 'member': 123, + 'keywords': { + 'foo': ['bar', 'baz'], + 'fizz': ['buzz'] + } }, 'bid_id': '123', 'adUnitCode': 'div-gpt-ad-1460505748561-0', @@ -366,16 +370,16 @@ describe('S2S Adapter', () => { ]; }); - afterEach(() => { + afterEach(function () { addBidResponse.resetHistory(); done.resetHistory(); }); - describe('request function', () => { + describe('request function', function () { let xhr; let requests; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = request => requests.push(request); @@ -383,13 +387,15 @@ describe('S2S Adapter', () => { resetSyncedStatus(); }); - afterEach(() => xhr.restore()); + afterEach(function () { + xhr.restore(); + }); - it('exists and is a function', () => { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); - it('exists converts types', () => { + it('exists converts types', function () { config.setConfig({s2sConfig: CONFIG}); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(requests[0].requestBody); @@ -398,100 +404,106 @@ describe('S2S Adapter', () => { expect(requestBid.ad_units[0].bids[0].params.member).to.exist.and.to.be.a('string'); }); - it('adds gdpr consent information to ortb2 request depending on presence of module', () => { - let ortb2Config = utils.deepClone(CONFIG); - ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' + describe('gdpr tests', function () { + afterEach(function () { + config.resetConfig(); + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); + }); - let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: ortb2Config }; - config.setConfig(consentConfig); + it('adds gdpr consent information to ortb2 request depending on presence of module', function () { + let ortb2Config = utils.deepClone(CONFIG); + ortb2Config.endpoint = 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' - let gdprBidRequest = utils.deepClone(BID_REQUESTS); - gdprBidRequest[0].gdprConsent = { - consentString: 'abc123', - gdprApplies: true - }; + let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: ortb2Config }; + config.setConfig(consentConfig); - adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); - let requestBid = JSON.parse(requests[0].requestBody); + let gdprBidRequest = utils.deepClone(BID_REQUESTS); + gdprBidRequest[0].gdprConsent = { + consentString: 'abc123', + gdprApplies: true + }; - expect(requestBid.regs.ext.gdpr).is.equal(1); - expect(requestBid.user.ext.consent).is.equal('abc123'); + adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); - config.resetConfig(); - config.setConfig({s2sConfig: CONFIG}); + expect(requestBid.regs.ext.gdpr).is.equal(1); + expect(requestBid.user.ext.consent).is.equal('abc123'); - adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); - requestBid = JSON.parse(requests[1].requestBody); + config.resetConfig(); + config.setConfig({s2sConfig: CONFIG}); - expect(requestBid.regs).to.not.exist; - expect(requestBid.user).to.not.exist; + adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); + requestBid = JSON.parse(requests[1].requestBody); - config.resetConfig(); - $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidsHook); - }); + expect(requestBid.regs).to.not.exist; + expect(requestBid.user).to.not.exist; + }); - it('check gdpr info gets added into cookie_sync request: have consent data', () => { - let cookieSyncConfig = utils.deepClone(CONFIG); - cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; + it('check gdpr info gets added into cookie_sync request: have consent data', function () { + let cookieSyncConfig = utils.deepClone(CONFIG); + cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; - let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; - config.setConfig(consentConfig); + let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; + config.setConfig(consentConfig); - let gdprBidRequest = utils.deepClone(BID_REQUESTS); + let gdprBidRequest = utils.deepClone(BID_REQUESTS); - gdprBidRequest[0].gdprConsent = { - consentString: 'abc123def', - gdprApplies: true - }; + gdprBidRequest[0].gdprConsent = { + consentString: 'abc123def', + gdprApplies: true + }; - adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); - let requestBid = JSON.parse(requests[0].requestBody); + adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); - expect(requestBid.gdpr).is.equal(1); - expect(requestBid.gdpr_consent).is.equal('abc123def'); - }); + expect(requestBid.gdpr).is.equal(1); + expect(requestBid.gdpr_consent).is.equal('abc123def'); + expect(requestBid.bidders).to.contain('appnexus').and.to.have.lengthOf(1); + expect(requestBid.account).is.equal('1'); + }); - it('check gdpr info gets added into cookie_sync request: have consent data but gdprApplies is false', () => { - let cookieSyncConfig = utils.deepClone(CONFIG); - cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; + it('check gdpr info gets added into cookie_sync request: have consent data but gdprApplies is false', function () { + let cookieSyncConfig = utils.deepClone(CONFIG); + cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; - let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; - config.setConfig(consentConfig); + let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; + config.setConfig(consentConfig); - let gdprBidRequest = utils.deepClone(BID_REQUESTS); - gdprBidRequest[0].gdprConsent = { - consentString: 'xyz789abcc', - gdprApplies: false - }; + let gdprBidRequest = utils.deepClone(BID_REQUESTS); + gdprBidRequest[0].gdprConsent = { + consentString: 'xyz789abcc', + gdprApplies: false + }; - adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); - let requestBid = JSON.parse(requests[0].requestBody); + adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); - expect(requestBid.gdpr).is.equal(0); - expect(requestBid.gdpr_consent).is.undefined; - }); + expect(requestBid.gdpr).is.equal(0); + expect(requestBid.gdpr_consent).is.undefined; + }); - it('checks gdpr info gets added to cookie_sync request: consent data unknown', () => { - let cookieSyncConfig = utils.deepClone(CONFIG); - cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; + it('checks gdpr info gets added to cookie_sync request: consent data unknown', function () { + let cookieSyncConfig = utils.deepClone(CONFIG); + cookieSyncConfig.syncEndpoint = 'https://prebid.adnxs.com/pbs/v1/cookie_sync'; - let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; - config.setConfig(consentConfig); + let consentConfig = { consentManagement: { cmpApi: 'iab' }, s2sConfig: cookieSyncConfig }; + config.setConfig(consentConfig); - let gdprBidRequest = utils.deepClone(BID_REQUESTS); - gdprBidRequest[0].gdprConsent = { - consentString: undefined, - gdprApplies: undefined - }; + let gdprBidRequest = utils.deepClone(BID_REQUESTS); + gdprBidRequest[0].gdprConsent = { + consentString: undefined, + gdprApplies: undefined + }; - adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); - let requestBid = JSON.parse(requests[0].requestBody); + adapter.callBids(REQUEST, gdprBidRequest, addBidResponse, done, ajax); + let requestBid = JSON.parse(requests[0].requestBody); - expect(requestBid.gdpr).is.undefined; - expect(requestBid.gdpr_consent).is.undefined; + expect(requestBid.gdpr).is.undefined; + expect(requestBid.gdpr_consent).is.undefined; + }); }); - it('sets invalid cacheMarkup value to 0', () => { + it('sets invalid cacheMarkup value to 0', function () { const s2sConfig = Object.assign({}, CONFIG, { cacheMarkup: 999 }); @@ -501,7 +513,7 @@ describe('S2S Adapter', () => { expect(requestBid).to.have.property('cache_markup', 0); }); - it('adds digitrust id is present and user is not optout', () => { + it('adds digitrust id is present and user is not optout', function () { let digiTrustObj = { success: true, identity: { @@ -536,7 +548,7 @@ describe('S2S Adapter', () => { delete window.DigiTrust; }); - it('adds device and app objects to request', () => { + it('adds device and app objects to request', function () { const _config = { s2sConfig: CONFIG, device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, app: { bundle: 'com.test.app' }, @@ -554,7 +566,7 @@ describe('S2S Adapter', () => { }); }); - it('adds device and app objects to request for ORTB', () => { + it('adds device and app objects to request for ORTB', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); @@ -577,7 +589,7 @@ describe('S2S Adapter', () => { }); }); - it('adds site if app is not present', () => { + it('adds site if app is not present', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); @@ -594,11 +606,11 @@ describe('S2S Adapter', () => { expect(requestBid.site.page).to.exist.and.to.be.a('string'); }); - it('adds appnexus aliases to request', () => { + it('adds appnexus aliases to request', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig}); + config.setConfig({s2sConfig: s2sConfig}); const aliasBidder = { bidder: 'brealtime', @@ -621,11 +633,11 @@ describe('S2S Adapter', () => { }); }); - it('adds dynamic aliases to request', () => { + it('adds dynamic aliases to request', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig}); + config.setConfig({s2sConfig: s2sConfig}); const alias = 'foobar'; const aliasBidder = { @@ -651,14 +663,18 @@ describe('S2S Adapter', () => { }); }); - it('converts appnexus params to expected format for PBS', () => { + it('converts appnexus params to expected format for PBS', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); - config.setConfig({s2sConfig}); + config.setConfig({s2sConfig: s2sConfig}); const myRequest = utils.deepClone(REQUEST); myRequest.ad_units[0].bids[0].params.usePaymentRule = true; + myRequest.ad_units[0].bids[0].params.keywords = { + foo: ['bar', 'baz'], + fizz: ['buzz'] + }; adapter.callBids(myRequest, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(requests[0].requestBody); @@ -667,14 +683,42 @@ describe('S2S Adapter', () => { expect(requestBid.imp[0].ext.appnexus.placement_id).to.exist.and.to.equal(10433394); expect(requestBid.imp[0].ext.appnexus.use_pmt_rule).to.exist.and.to.be.true; expect(requestBid.imp[0].ext.appnexus.member).to.exist; + expect(requestBid.imp[0].ext.appnexus.keywords).to.exist.and.to.deep.equal([{ + key: 'foo', + value: ['bar', 'baz'] + }, { + key: 'fizz', + value: ['buzz'] + }]); + + config.resetConfig(); + const oldS2sConfig = Object.assign({}, CONFIG); + config.setConfig({s2sConfig: oldS2sConfig}); + + const myRequest2 = utils.deepClone(REQUEST); + myRequest2.ad_units[0].bids[0].params.keywords = { + foo: ['bar', 'baz'], + fizz: ['buzz'] + }; + + adapter.callBids(myRequest2, BID_REQUESTS, addBidResponse, done, ajax); + const requestBid2 = JSON.parse(requests[1].requestBody); + + expect(requestBid2.ad_units[0].bids[0].params.keywords).to.exist.and.to.deep.equal([{ + key: 'foo', + value: ['bar', 'baz'] + }, { + key: 'fizz', + value: ['buzz'] + }]); }); }); - describe('response handler', () => { + describe('response handler', function () { let server; let logWarnSpy; - beforeEach(() => { + beforeEach(function () { server = sinon.fakeServer.create(); sinon.stub(utils, 'triggerPixel'); sinon.stub(utils, 'insertUserSyncIframe'); @@ -684,7 +728,7 @@ describe('S2S Adapter', () => { logWarnSpy = sinon.spy(utils, 'logWarn'); }); - afterEach(() => { + afterEach(function () { server.restore(); utils.triggerPixel.restore(); utils.insertUserSyncIframe.restore(); @@ -695,7 +739,7 @@ describe('S2S Adapter', () => { }); // TODO: test dependent on pbjs_api_spec. Needs to be isolated - it('registers bids and calls BIDDER_DONE', () => { + it('registers bids and calls BIDDER_DONE', function () { server.respondWith(JSON.stringify(RESPONSE)); config.setConfig({s2sConfig: CONFIG}); @@ -718,7 +762,7 @@ describe('S2S Adapter', () => { expect(response).to.not.have.property('vastUrl'); }); - it('registers video bids', () => { + it('registers video bids', function () { server.respondWith(JSON.stringify(VIDEO_RESPONSE)); config.setConfig({s2sConfig: CONFIG}); @@ -736,7 +780,7 @@ describe('S2S Adapter', () => { expect(response).to.have.property('vastUrl', 'video_cache_url'); }); - it('does not call addBidResponse and calls done when ad unit not set', () => { + it('does not call addBidResponse and calls done when ad unit not set', function () { server.respondWith(JSON.stringify(RESPONSE_NO_BID_NO_UNIT)); config.setConfig({s2sConfig: CONFIG}); @@ -747,7 +791,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(done); }); - it('does not call addBidResponse and calls done when server requests cookie sync', () => { + it('does not call addBidResponse and calls done when server requests cookie sync', function () { server.respondWith(JSON.stringify(RESPONSE_NO_COOKIE)); config.setConfig({s2sConfig: CONFIG}); @@ -758,7 +802,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(done); }); - it('does not call addBidResponse and calls done when ad unit is set', () => { + it('does not call addBidResponse and calls done when ad unit is set', function () { server.respondWith(JSON.stringify(RESPONSE_NO_BID_UNIT_SET)); config.setConfig({s2sConfig: CONFIG}); @@ -769,7 +813,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(done); }); - it('registers successful bids and calls done when there are less bids than requests', () => { + it('registers successful bids and calls done when there are less bids than requests', function () { server.respondWith(JSON.stringify(RESPONSE)); config.setConfig({s2sConfig: CONFIG}); @@ -787,7 +831,7 @@ describe('S2S Adapter', () => { .to.have.property('statusMessage', 'Bid available'); }); - it('should have dealId in bidObject', () => { + it('should have dealId in bidObject', function () { server.respondWith(JSON.stringify(RESPONSE)); config.setConfig({s2sConfig: CONFIG}); @@ -797,7 +841,7 @@ describe('S2S Adapter', () => { expect(response).to.have.property('dealId', 'test-dealid'); }); - it('should pass through default adserverTargeting if present in bidObject', () => { + it('should pass through default adserverTargeting if present in bidObject', function () { server.respondWith(JSON.stringify(RESPONSE)); config.setConfig({s2sConfig: CONFIG}); @@ -807,7 +851,7 @@ describe('S2S Adapter', () => { expect(response).to.have.property('adserverTargeting').that.deep.equals({'foo': 'bar'}); }); - it('registers client user syncs when client bid adapter is present', () => { + it('registers client user syncs when client bid adapter is present', function () { let rubiconAdapter = { registerSyncs: sinon.spy() }; @@ -824,7 +868,7 @@ describe('S2S Adapter', () => { adapterManager.getBidAdapter.restore(); }); - it('registers client user syncs when using OpenRTB endpoint', () => { + it('registers client user syncs when using OpenRTB endpoint', function () { let rubiconAdapter = { registerSyncs: sinon.spy() }; @@ -844,7 +888,7 @@ describe('S2S Adapter', () => { adapterManager.getBidAdapter.restore(); }); - it('registers bid responses when server requests cookie sync', () => { + it('registers bid responses when server requests cookie sync', function () { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); config.setConfig({s2sConfig: CONFIG}); @@ -863,7 +907,7 @@ describe('S2S Adapter', () => { expect(bid_request_passed).to.have.property('adId', '123'); }); - it('does not call cookieSet cookie sync when no_cookie response && not opted in', () => { + it('does not call cookieSet cookie sync when no_cookie response && not opted in', function () { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); let myConfig = Object.assign({}, CONFIG); @@ -874,7 +918,7 @@ describe('S2S Adapter', () => { sinon.assert.notCalled(cookie.cookieSet); }); - it('calls cookieSet cookie sync when no_cookie response && opted in', () => { + it('calls cookieSet cookie sync when no_cookie response && opted in', function () { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); let myConfig = Object.assign({ cookieSet: true, @@ -887,7 +931,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(cookie.cookieSet); }); - it('handles OpenRTB responses and call BIDDER_DONE', () => { + it('handles OpenRTB responses and call BIDDER_DONE', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebid.adnxs.com/pbs/v1/openrtb2/auction' }); @@ -910,7 +954,7 @@ describe('S2S Adapter', () => { expect(response).to.have.property('cpm', 0.5); }); - it('handles OpenRTB video responses', () => { + it('handles OpenRTB video responses', function () { const s2sConfig = Object.assign({}, CONFIG, { endpoint: 'https://prebidserverurl/openrtb2/auction?querystring=param' }); @@ -930,7 +974,7 @@ describe('S2S Adapter', () => { expect(response).to.have.property('cpm', 10); }); - it('should log warning for unsupported bidder', () => { + it('should log warning for unsupported bidder', function () { server.respondWith(JSON.stringify(RESPONSE_UNSUPPORTED_BIDDER)); const s2sConfig = Object.assign({}, CONFIG, { @@ -950,18 +994,18 @@ describe('S2S Adapter', () => { }); }); - describe('s2sConfig', () => { + describe('s2sConfig', function () { let logErrorSpy; - beforeEach(() => { + beforeEach(function () { logErrorSpy = sinon.spy(utils, 'logError'); }); - afterEach(() => { + afterEach(function () { utils.logError.restore(); }); - it('should log an error when accountId is missing', () => { + it('should log an error when accountId is missing', function () { const options = { enabled: true, bidders: ['appnexus'], @@ -974,7 +1018,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(logErrorSpy); }); - it('should log an error when bidders is missing', () => { + it('should log an error when bidders is missing', function () { const options = { accountId: '1', enabled: true, @@ -987,7 +1031,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(logErrorSpy); }); - it('should log an error when endpoint is missing', () => { + it('should log an error when endpoint is missing', function () { const options = { accountId: '1', bidders: ['appnexus'], @@ -1000,7 +1044,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(logErrorSpy); }); - it('should log an error when using an unknown vendor', () => { + it('should log an error when using an unknown vendor', function () { const options = { accountId: '1', bidders: ['appnexus'], @@ -1011,7 +1055,7 @@ describe('S2S Adapter', () => { sinon.assert.calledOnce(logErrorSpy); }); - it('should configure the s2sConfig object with appnexus vendor defaults unless specified by user', () => { + it('should configure the s2sConfig object with appnexus vendor defaults unless specified by user', function () { const options = { accountId: '123', bidders: ['appnexus'], @@ -1034,7 +1078,7 @@ describe('S2S Adapter', () => { expect(vendorConfig).to.have.property('timeout', 750); }); - it('should configure the s2sConfig object with rubicon vendor defaults unless specified by user', () => { + it('should configure the s2sConfig object with rubicon vendor defaults unless specified by user', function () { const options = { accountId: 'abc', bidders: ['rubicon'], @@ -1052,7 +1096,7 @@ describe('S2S Adapter', () => { expect(vendorConfig.cookieSet).to.be.false; expect(vendorConfig.cookieSetUrl).to.be.undefined; expect(vendorConfig.enabled).to.be.true; - expect(vendorConfig).to.have.property('endpoint', '//prebid-server.rubiconproject.com/auction'); + expect(vendorConfig).to.have.property('endpoint', '//prebid-server.rubiconproject.com/openrtb2/auction'); expect(vendorConfig).to.have.property('syncEndpoint', '//prebid-server.rubiconproject.com/cookie_sync'); expect(vendorConfig).to.have.property('timeout', 750); }); diff --git a/test/spec/modules/pubCommonId_spec.js b/test/spec/modules/pubCommonId_spec.js index 50ca4616a4b..aaf296cfb43 100644 --- a/test/spec/modules/pubCommonId_spec.js +++ b/test/spec/modules/pubCommonId_spec.js @@ -18,6 +18,9 @@ const COOKIE_NAME = '_pubcid'; const TIMEOUT = 2000; describe('Publisher Common ID', function () { + afterEach(function () { + $$PREBID_GLOBAL$$.requestBids.removeHook(requestBidHook); + }); describe('Decorate adUnits', function () { before(function() { window.document.cookie = COOKIE_NAME + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; @@ -156,7 +159,7 @@ describe('Publisher Common ID', function () { getUserSyncs: () => {} }; - beforeEach(() => { + beforeEach(function () { adUnits = [{ code: 'adUnit-code', mediaTypes: { @@ -176,7 +179,7 @@ describe('Publisher Common ID', function () { registerBidder(sampleSpec); }); - afterEach(() => { + afterEach(function () { auctionModule.newAuction.restore(); }); diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 09acbbe95a0..be3b59c1a80 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -3,11 +3,13 @@ import {spec} from 'modules/pubmaticBidAdapter'; import * as utils from 'src/utils'; const constants = require('src/constants.json'); -describe('PubMatic adapter', () => { +describe('PubMatic adapter', function () { let bidRequests; + let videoBidRequests; + let multipleMediaRequests; let bidResponses; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { bidder: 'pubmatic', @@ -23,7 +25,9 @@ describe('PubMatic adapter', () => { lon: '23.7', wiid: '1234567890', profId: '100', - verId: '200' + verId: '200', + currency: 'AUD', + dctr: 'key1:val1,val2|key2:val1' }, placementCode: '/19968336/header-bid-tag-1', sizes: [[300, 250], [300, 600]], @@ -34,6 +38,91 @@ describe('PubMatic adapter', () => { } ]; + videoBidRequests = + [ + { + code: 'video1', + mediaTypes: { + video: { + playerSize: [640, 480], + context: 'instream' + } + }, + bidder: 'pubmatic', + params: { + publisherId: '5890', + adSlot: 'Div1@0x0', // ad_id or tagid + video: { + mimes: ['video/mp4', 'video/x-flv'], + skippable: true, + minduration: 5, + maxduration: 30, + startdelay: 5, + playbackmethod: [1, 3], + api: [1, 2], + protocols: [2, 3], + battr: [13, 14], + linearity: 1, + placement: 2, + minbitrate: 10, + maxbitrate: 10 + } + } + } + ]; + + multipleMediaRequests = + [ + { + bidder: 'pubmatic', + params: { + publisherId: '301', + adSlot: '/15671365/DMDemo@300x250:0', + kadfloor: '1.2', + pmzoneid: 'aabc, ddef', + kadpageurl: 'www.publisher.com', + yob: '1986', + gender: 'M', + lat: '12.3', + lon: '23.7', + wiid: '1234567890', + profId: '100', + verId: '200' + } + }, + { + code: 'div-instream', + mediaTypes: { + video: { + context: 'instream', + playerSize: [300, 250] + }, + }, + bidder: 'pubmatic', + params: { + publisherId: '5890', + adSlot: 'Div1@640x480', // ad_id or tagid + video: { + mimes: ['video/mp4', 'video/x-flv'], + skippable: true, + minduration: 5, + maxduration: 30, + startdelay: 15, + playbackmethod: [1, 3], + api: [1, 2], + protocols: [2, 3], + w: 640, + h: 480, + battr: [13, 14], + linearity: 1, + placement: 2, + minbitrate: 100, + maxbitrate: 4096 + } + } + } + ]; + bidResponses = { 'body': { 'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865', @@ -66,9 +155,9 @@ describe('PubMatic adapter', () => { }; }); - describe('implementation', () => { - describe('Bid validations', () => { - it('valid bid case', () => { + describe('implementation', function () { + describe('Bid validations', function () { + it('valid bid case', function () { let validBid = { bidder: 'pubmatic', params: { @@ -80,7 +169,7 @@ describe('PubMatic adapter', () => { expect(isValid).to.equal(true); }); - it('invalid bid case: publisherId not passed', () => { + it('invalid bid case: publisherId not passed', function () { let validBid = { bidder: 'pubmatic', params: { @@ -91,7 +180,7 @@ describe('PubMatic adapter', () => { expect(isValid).to.equal(false); }); - it('invalid bid case: publisherId is not string', () => { + it('invalid bid case: publisherId is not string', function () { let validBid = { bidder: 'pubmatic', params: { @@ -103,7 +192,7 @@ describe('PubMatic adapter', () => { expect(isValid).to.equal(false); }); - it('invalid bid case: adSlot not passed', () => { + it('invalid bid case: adSlot not passed', function () { let validBid = { bidder: 'pubmatic', params: { @@ -114,7 +203,7 @@ describe('PubMatic adapter', () => { expect(isValid).to.equal(false); }); - it('invalid bid case: adSlot is not string', () => { + it('invalid bid case: adSlot is not string', function () { let validBid = { bidder: 'pubmatic', params: { @@ -127,14 +216,20 @@ describe('PubMatic adapter', () => { }); }); - describe('Request formation', () => { - it('Endpoint checking', () => { + describe('Request formation', function () { + it('buildRequests function should not modify original bidRequests object', function () { + let originalBidRequests = utils.deepClone(bidRequests); + let request = spec.buildRequests(bidRequests); + expect(bidRequests).to.deep.equal(originalBidRequests); + }); + + it('Endpoint checking', function () { let request = spec.buildRequests(bidRequests); expect(request.url).to.equal('//hbopenbid.pubmatic.com/translator?source=prebid-client'); expect(request.method).to.equal('POST'); }); - it('Request params check', () => { + it('Request params check', function () { let request = spec.buildRequests(bidRequests); let data = JSON.parse(request.data); expect(data.at).to.equal(1); // auction type @@ -142,6 +237,8 @@ describe('PubMatic adapter', () => { expect(data.site.domain).to.be.a('string'); // domain should be set expect(data.site.page).to.equal(bidRequests[0].params.kadpageurl); // forced pageURL expect(data.site.publisher.id).to.equal(bidRequests[0].params.publisherId); // publisher Id + expect(data.site.ext).to.exist.and.to.be.an('object'); // dctr parameter + expect(data.site.ext.key_val).to.exist.and.to.equal(bidRequests[0].params.dctr); 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 @@ -160,9 +257,162 @@ describe('PubMatic adapter', () => { expect(data.imp[0].banner.w).to.equal(300); // width expect(data.imp[0].banner.h).to.equal(250); // height expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid + expect(data.imp[0].bidfloorcur).to.equal(bidRequests[0].params.currency); }); - it('Request params check with GDPR Consent', () => { + it('Request params multi size format object check', function () { + let bidRequests = [ + { + bidder: 'pubmatic', + params: { + publisherId: '301', + adSlot: '/15671365/DMDemo@300x250:0', + kadfloor: '1.2', + pmzoneid: 'aabc, ddef', + kadpageurl: 'www.publisher.com', + yob: '1986', + gender: 'M', + lat: '12.3', + lon: '23.7', + wiid: '1234567890', + profId: '100', + verId: '200', + currency: 'AUD' + }, + placementCode: '/19968336/header-bid-tag-1', + bidId: '23acc48ad47af5', + requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', + bidderRequestId: '1c56ad30b9b8ca8', + transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' + } + ]; + /* case 1 - size passed in adslot */ + let request = spec.buildRequests(bidRequests); + let data = JSON.parse(request.data); + + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(250); // height + + /* case 2 - size passed in adslot as well as in sizes array */ + bidRequests[0].sizes = [[300, 600], [300, 250]]; + request = spec.buildRequests(bidRequests); + data = JSON.parse(request.data); + + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(250); // height + + /* case 3 - size passed in sizes but not in adslot */ + bidRequests[0].params.adSlot = '/15671365/DMDemo'; + bidRequests[0].sizes = [[300, 250], [300, 600]]; + request = spec.buildRequests(bidRequests); + data = JSON.parse(request.data); + + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(250); // height + expect(data.imp[0].banner.format).exist.and.to.be.an('array'); + expect(data.imp[0].banner.format[0]).exist.and.to.be.an('object'); + expect(data.imp[0].banner.format[0].w).to.equal(300); // width + expect(data.imp[0].banner.format[0].h).to.equal(600); // height + }); + + it('Request params currency check', function () { + let multipleBidRequests = [ + { + bidder: 'pubmatic', + params: { + publisherId: '301', + adSlot: '/15671365/DMDemo@300x250:0', + kadfloor: '1.2', + pmzoneid: 'aabc, ddef', + kadpageurl: 'www.publisher.com', + yob: '1986', + gender: 'M', + lat: '12.3', + lon: '23.7', + wiid: '1234567890', + profId: '100', + verId: '200', + currency: 'AUD' + }, + placementCode: '/19968336/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' + }, + { + bidder: 'pubmatic', + params: { + publisherId: '301', + adSlot: '/15671365/DMDemo@300x250:0', + kadfloor: '1.2', + pmzoneid: 'aabc, ddef', + kadpageurl: 'www.publisher.com', + yob: '1986', + gender: 'M', + lat: '12.3', + lon: '23.7', + wiid: '1234567890', + profId: '100', + verId: '200', + currency: 'GBP' + }, + placementCode: '/19968336/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' + } + ]; + + /* case 1 - + currency specified in both adunits + output: imp[0] and imp[1] both use currency specified in bidRequests[0].params.currency + + */ + let request = spec.buildRequests(multipleBidRequests); + let data = JSON.parse(request.data); + + expect(data.imp[0].bidfloorcur).to.equal(bidRequests[0].params.currency); + expect(data.imp[1].bidfloorcur).to.equal(bidRequests[0].params.currency); + + /* case 2 - + currency specified in only 1st adunit + output: imp[0] and imp[1] both use currency specified in bidRequests[0].params.currency + + */ + delete multipleBidRequests[1].params.currency; + request = spec.buildRequests(multipleBidRequests); + data = JSON.parse(request.data); + expect(data.imp[0].bidfloorcur).to.equal(bidRequests[0].params.currency); + expect(data.imp[1].bidfloorcur).to.equal(bidRequests[0].params.currency); + + /* case 3 - + currency specified in only 1st adunit + output: imp[0] and imp[1] both use default currency - USD + + */ + delete multipleBidRequests[0].params.currency; + request = spec.buildRequests(multipleBidRequests); + data = JSON.parse(request.data); + expect(data.imp[0].bidfloorcur).to.equal('USD'); + expect(data.imp[1].bidfloorcur).to.equal('USD'); + + /* case 4 - + currency not specified in 1st adunit but specified in 2nd adunit + output: imp[0] and imp[1] both use default currency - USD + + */ + multipleBidRequests[1].params.currency = 'AUD'; + request = spec.buildRequests(multipleBidRequests); + data = JSON.parse(request.data); + expect(data.imp[0].bidfloorcur).to.equal('USD'); + expect(data.imp[1].bidfloorcur).to.equal('USD'); + }); + + it('Request params check with GDPR Consent', function () { let bidRequest = { gdprConsent: { consentString: 'kjfdniwjnifwenrif3', @@ -198,15 +448,198 @@ describe('PubMatic adapter', () => { expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid }); - it('invalid adslot', () => { - bidRequests[0].params.adSlot = '/15671365/DMDemo'; - let request = spec.buildRequests(bidRequests); - expect(request).to.equal(undefined); - }); + it('Request params check for video ad', function () { + let request = spec.buildRequests(videoBidRequests); + let data = JSON.parse(request.data); + expect(data.imp[0].video).to.exist; + expect(data.imp[0].tagid).to.equal('Div1'); + expect(data.imp[0].video.ext['video_skippable']).to.equal(videoBidRequests[0].params.video.skippable ? 1 : 0); + expect(data.imp[0]['video']['mimes']).to.exist.and.to.be.an('array'); + expect(data.imp[0]['video']['mimes'][0]).to.equal(videoBidRequests[0].params.video['mimes'][0]); + expect(data.imp[0]['video']['mimes'][1]).to.equal(videoBidRequests[0].params.video['mimes'][1]); + expect(data.imp[0]['video']['minduration']).to.equal(videoBidRequests[0].params.video['minduration']); + expect(data.imp[0]['video']['maxduration']).to.equal(videoBidRequests[0].params.video['maxduration']); + expect(data.imp[0]['video']['startdelay']).to.equal(videoBidRequests[0].params.video['startdelay']); + + expect(data.imp[0]['video']['playbackmethod']).to.exist.and.to.be.an('array'); + expect(data.imp[0]['video']['playbackmethod'][0]).to.equal(videoBidRequests[0].params.video['playbackmethod'][0]); + expect(data.imp[0]['video']['playbackmethod'][1]).to.equal(videoBidRequests[0].params.video['playbackmethod'][1]); + + expect(data.imp[0]['video']['api']).to.exist.and.to.be.an('array'); + expect(data.imp[0]['video']['api'][0]).to.equal(videoBidRequests[0].params.video['api'][0]); + expect(data.imp[0]['video']['api'][1]).to.equal(videoBidRequests[0].params.video['api'][1]); + + expect(data.imp[0]['video']['protocols']).to.exist.and.to.be.an('array'); + expect(data.imp[0]['video']['protocols'][0]).to.equal(videoBidRequests[0].params.video['protocols'][0]); + expect(data.imp[0]['video']['protocols'][1]).to.equal(videoBidRequests[0].params.video['protocols'][1]); + + expect(data.imp[0]['video']['battr']).to.exist.and.to.be.an('array'); + expect(data.imp[0]['video']['battr'][0]).to.equal(videoBidRequests[0].params.video['battr'][0]); + expect(data.imp[0]['video']['battr'][1]).to.equal(videoBidRequests[0].params.video['battr'][1]); + + expect(data.imp[0]['video']['linearity']).to.equal(videoBidRequests[0].params.video['linearity']); + expect(data.imp[0]['video']['placement']).to.equal(videoBidRequests[0].params.video['placement']); + expect(data.imp[0]['video']['minbitrate']).to.equal(videoBidRequests[0].params.video['minbitrate']); + expect(data.imp[0]['video']['maxbitrate']).to.equal(videoBidRequests[0].params.video['maxbitrate']); + + expect(data.imp[0]['video']['w']).to.equal(videoBidRequests[0].mediaTypes.video.playerSize[0]); + expect(data.imp[0]['video']['h']).to.equal(videoBidRequests[0].mediaTypes.video.playerSize[1]); + }); + + it('Request params check for 1 banner and 1 video ad', function () { + let request = spec.buildRequests(multipleMediaRequests); + let data = JSON.parse(request.data); + + expect(data.imp).to.be.an('array') + expect(data.imp).with.length.above(1); + + expect(data.at).to.equal(1); // auction type + expect(data.cur[0]).to.equal('USD'); // currency + expect(data.site.domain).to.be.a('string'); // domain should be set + expect(data.site.page).to.equal(multipleMediaRequests[0].params.kadpageurl); // forced pageURL + 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.ext.wrapper.wv).to.equal(constants.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 + expect(data.ext.wrapper.profile).to.equal(parseInt(multipleMediaRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID + expect(data.ext.wrapper.version).to.equal(parseInt(multipleMediaRequests[0].params.verId)); // OpenWrap: Wrapper Profile Version ID + + // banner imp object check + expect(data.imp[0].id).to.equal(multipleMediaRequests[0].bidId); // Prebid bid id is passed as id + expect(data.imp[0].bidfloor).to.equal(parseFloat(multipleMediaRequests[0].params.kadfloor)); // kadfloor + expect(data.imp[0].tagid).to.equal('/15671365/DMDemo'); // tagid + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(250); // height + expect(data.imp[0].ext.pmZoneId).to.equal(multipleMediaRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid + + // video imp object check + expect(data.imp[1].video).to.exist; + expect(data.imp[1].tagid).to.equal('Div1'); + expect(data.imp[1].video.ext['video_skippable']).to.equal(multipleMediaRequests[1].params.video.skippable ? 1 : 0); + expect(data.imp[1]['video']['mimes']).to.exist.and.to.be.an('array'); + expect(data.imp[1]['video']['mimes'][0]).to.equal(multipleMediaRequests[1].params.video['mimes'][0]); + expect(data.imp[1]['video']['mimes'][1]).to.equal(multipleMediaRequests[1].params.video['mimes'][1]); + expect(data.imp[1]['video']['minduration']).to.equal(multipleMediaRequests[1].params.video['minduration']); + expect(data.imp[1]['video']['maxduration']).to.equal(multipleMediaRequests[1].params.video['maxduration']); + expect(data.imp[1]['video']['startdelay']).to.equal(multipleMediaRequests[1].params.video['startdelay']); + + expect(data.imp[1]['video']['playbackmethod']).to.exist.and.to.be.an('array'); + expect(data.imp[1]['video']['playbackmethod'][0]).to.equal(multipleMediaRequests[1].params.video['playbackmethod'][0]); + expect(data.imp[1]['video']['playbackmethod'][1]).to.equal(multipleMediaRequests[1].params.video['playbackmethod'][1]); + + expect(data.imp[1]['video']['api']).to.exist.and.to.be.an('array'); + expect(data.imp[1]['video']['api'][0]).to.equal(multipleMediaRequests[1].params.video['api'][0]); + expect(data.imp[1]['video']['api'][1]).to.equal(multipleMediaRequests[1].params.video['api'][1]); + + expect(data.imp[1]['video']['protocols']).to.exist.and.to.be.an('array'); + expect(data.imp[1]['video']['protocols'][0]).to.equal(multipleMediaRequests[1].params.video['protocols'][0]); + expect(data.imp[1]['video']['protocols'][1]).to.equal(multipleMediaRequests[1].params.video['protocols'][1]); + + expect(data.imp[1]['video']['battr']).to.exist.and.to.be.an('array'); + expect(data.imp[1]['video']['battr'][0]).to.equal(multipleMediaRequests[1].params.video['battr'][0]); + expect(data.imp[1]['video']['battr'][1]).to.equal(multipleMediaRequests[1].params.video['battr'][1]); + + expect(data.imp[1]['video']['linearity']).to.equal(multipleMediaRequests[1].params.video['linearity']); + expect(data.imp[1]['video']['placement']).to.equal(multipleMediaRequests[1].params.video['placement']); + expect(data.imp[1]['video']['minbitrate']).to.equal(multipleMediaRequests[1].params.video['minbitrate']); + expect(data.imp[1]['video']['maxbitrate']).to.equal(multipleMediaRequests[1].params.video['maxbitrate']); + + expect(data.imp[1]['video']['w']).to.equal(multipleMediaRequests[1].mediaTypes.video.playerSize[0]); + expect(data.imp[1]['video']['h']).to.equal(multipleMediaRequests[1].mediaTypes.video.playerSize[1]); + }); }); - describe('Response checking', () => { - it('should check for valid response values', () => { + it('Request params dctr check', function () { + let multipleBidRequests = [ + { + bidder: 'pubmatic', + params: { + publisherId: '301', + adSlot: '/15671365/DMDemo@300x250:0', + kadfloor: '1.2', + pmzoneid: 'aabc, ddef', + kadpageurl: 'www.publisher.com', + yob: '1986', + gender: 'M', + lat: '12.3', + lon: '23.7', + wiid: '1234567890', + profId: '100', + verId: '200', + currency: 'AUD', + dctr: 'key1=val1|key2=val2,!val3' + }, + placementCode: '/19968336/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' + }, + { + bidder: 'pubmatic', + params: { + publisherId: '301', + adSlot: '/15671365/DMDemo@300x250:0', + kadfloor: '1.2', + pmzoneid: 'aabc, ddef', + kadpageurl: 'www.publisher.com', + yob: '1986', + gender: 'M', + lat: '12.3', + lon: '23.7', + wiid: '1234567890', + profId: '100', + verId: '200', + currency: 'GBP', + dctr: 'key1=val3|key2=val1,!val3|key3=val123' + }, + placementCode: '/19968336/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' + } + ]; + + let request = spec.buildRequests(multipleBidRequests); + let data = JSON.parse(request.data); + + /* case 1 - + dctr is found in adunit[0] + */ + + expect(data.site.ext).to.exist.and.to.be.an('object'); // dctr parameter + expect(data.site.ext.key_val).to.exist.and.to.equal(multipleBidRequests[0].params.dctr); + + /* case 2 - + dctr not present in adunit[0] + */ + delete multipleBidRequests[0].params.dctr; + request = spec.buildRequests(multipleBidRequests); + data = JSON.parse(request.data); + + expect(data.site.ext).to.not.exist; + + /* case 3 - + dctr is present in adunit[0], but is not a string value + */ + multipleBidRequests[0].params.dctr = 123; + request = spec.buildRequests(multipleBidRequests); + data = JSON.parse(request.data); + + expect(data.site.ext).to.not.exist; + }); + + describe('Response checking', function () { + it('should check for valid response values', function () { let request = spec.buildRequests(bidRequests); let response = spec.interpretResponse(bidResponses, request); expect(response).to.be.an('array').with.length.above(0); @@ -243,7 +676,7 @@ describe('PubMatic adapter', () => { expect(response[1].ad).to.equal(bidResponses.body.seatbid[1].bid[0].adm); }); - it('should check for dealChannel value selection', () => { + it('should check for dealChannel value selection', function () { let request = spec.buildRequests(bidRequests); let response = spec.interpretResponse(bidResponses, request); expect(response).to.be.an('array').with.length.above(0); @@ -251,7 +684,7 @@ describe('PubMatic adapter', () => { expect(response[1].dealChannel).to.equal('PREF'); }); - it('should check for unexpected dealChannel value selection', () => { + it('should check for unexpected dealChannel value selection', function () { let request = spec.buildRequests(bidRequests); let updateBiResponse = bidResponses; updateBiResponse.body.seatbid[0].bid[0].ext.deal_channel = 11; diff --git a/test/spec/modules/pubwiseAnalyticsAdapter_spec.js b/test/spec/modules/pubwiseAnalyticsAdapter_spec.js index ffb8d3c0570..e7e31fccc43 100644 --- a/test/spec/modules/pubwiseAnalyticsAdapter_spec.js +++ b/test/spec/modules/pubwiseAnalyticsAdapter_spec.js @@ -6,21 +6,21 @@ let constants = require('src/constants.json'); describe('PubWise Prebid Analytics', function () { let xhr; - before(() => { + before(function () { xhr = sinon.useFakeXMLHttpRequest(); }); - after(() => { + after(function () { xhr.restore(); pubwiseAnalytics.disableAnalytics(); }); describe('enableAnalytics', function () { - beforeEach(() => { + beforeEach(function () { sinon.stub(events, 'getEvents').returns([]); }); - afterEach(() => { + afterEach(function () { events.getEvents.restore(); }); diff --git a/test/spec/modules/pulsepointBidAdapter_spec.js b/test/spec/modules/pulsepointBidAdapter_spec.js index 709dbeb76a2..ebeedde7783 100644 --- a/test/spec/modules/pulsepointBidAdapter_spec.js +++ b/test/spec/modules/pulsepointBidAdapter_spec.js @@ -4,7 +4,7 @@ import {spec} from 'modules/pulsepointBidAdapter'; import {getTopWindowLocation} from 'src/utils'; import {newBidder} from 'src/adapters/bidderFactory'; -describe('PulsePoint Adapter Tests', () => { +describe('PulsePoint Adapter Tests', function () { const slotConfigs = [{ placementCode: '/DfpAccount1/slot1', bidId: 'bid12345', @@ -49,7 +49,7 @@ describe('PulsePoint Adapter Tests', () => { } }]; - it('Verify build request', () => { + it('Verify build request', function () { const request = spec.buildRequests(slotConfigs); expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); expect(request.method).to.equal('POST'); @@ -76,7 +76,7 @@ describe('PulsePoint Adapter Tests', () => { expect(ortbRequest.imp[1].banner.h).to.equal(90); }); - it('Verify parse response', () => { + it('Verify parse response', function () { const request = spec.buildRequests(slotConfigs); const ortbRequest = JSON.parse(request.data); const ortbResponse = { @@ -104,7 +104,7 @@ describe('PulsePoint Adapter Tests', () => { expect(bid.ttl).to.equal(20); }); - it('Verify use ttl in ext', () => { + it('Verify use ttl in ext', function () { const request = spec.buildRequests(slotConfigs); const ortbRequest = JSON.parse(request.data); const ortbResponse = { @@ -130,13 +130,13 @@ describe('PulsePoint Adapter Tests', () => { expect(bid.currency).to.equal('INR'); }); - it('Verify full passback', () => { + it('Verify full passback', function () { const request = spec.buildRequests(slotConfigs); const bids = spec.interpretResponse({ body: null }, request) expect(bids).to.have.lengthOf(0); }); - it('Verify Native request', () => { + it('Verify Native request', function () { const request = spec.buildRequests(nativeSlotConfig); expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); expect(request.method).to.equal('POST'); @@ -174,7 +174,7 @@ describe('PulsePoint Adapter Tests', () => { expect(nativeRequest.assets[2].img.type).to.equal(3); }); - it('Verify Native response', () => { + it('Verify Native response', function () { const request = spec.buildRequests(nativeSlotConfig); expect(request.url).to.equal('//bid.contextweb.com/header/ortb'); expect(request.method).to.equal('POST'); @@ -217,22 +217,22 @@ describe('PulsePoint Adapter Tests', () => { expect(nativeBid.impressionTrackers[1]).to.equal('http://imp1.contextweb.com/'); }); - it('Verifies bidder code', () => { + it('Verifies bidder code', function () { expect(spec.code).to.equal('pulsepoint'); }); - it('Verifies bidder aliases', () => { + it('Verifies bidder aliases', function () { expect(spec.aliases).to.have.lengthOf(2); expect(spec.aliases[0]).to.equal('pulseLite'); expect(spec.aliases[1]).to.equal('pulsepointLite'); }); - it('Verifies supported media types', () => { + it('Verifies supported media types', function () { expect(spec.supportedMediaTypes).to.have.lengthOf(2); expect(spec.supportedMediaTypes[1]).to.equal('native'); }); - it('Verifies if bid request valid', () => { + it('Verifies if bid request valid', function () { expect(spec.isBidRequestValid(slotConfigs[0])).to.equal(true); expect(spec.isBidRequestValid(slotConfigs[1])).to.equal(true); expect(spec.isBidRequestValid(nativeSlotConfig[0])).to.equal(true); @@ -243,7 +243,7 @@ describe('PulsePoint Adapter Tests', () => { expect(spec.isBidRequestValid({ params: { ct: 123, cp: 234 } })).to.equal(true); }); - it('Verifies sync options', () => { + it('Verifies sync options', function () { expect(spec.getUserSyncs({})).to.be.undefined; expect(spec.getUserSyncs({ iframeEnabled: false })).to.be.undefined; const options = spec.getUserSyncs({ iframeEnabled: true }); @@ -253,7 +253,7 @@ describe('PulsePoint Adapter Tests', () => { expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch'); }); - it('Verifies image pixel sync', () => { + it('Verifies image pixel sync', function () { const options = spec.getUserSyncs({ pixelEnabled: true }); expect(options).to.not.be.undefined; expect(options).to.have.lengthOf(1); @@ -261,7 +261,7 @@ describe('PulsePoint Adapter Tests', () => { expect(options[0].url).to.equal('//bh.contextweb.com/visitormatch/prebid'); }); - it('Verify app requests', () => { + it('Verify app requests', function () { const request = spec.buildRequests(appSlotConfig); const ortbRequest = JSON.parse(request.data); // site object @@ -274,7 +274,7 @@ describe('PulsePoint Adapter Tests', () => { expect(ortbRequest.app.domain).to.equal('pulsepoint.com'); }); - it('Verify GDPR', () => { + it('Verify GDPR', function () { const bidderRequest = { gdprConsent: { gdprApplies: true, diff --git a/test/spec/modules/quantcastBidAdapter_spec.js b/test/spec/modules/quantcastBidAdapter_spec.js index 6fd5c3abdf9..f5a7602c7ab 100644 --- a/test/spec/modules/quantcastBidAdapter_spec.js +++ b/test/spec/modules/quantcastBidAdapter_spec.js @@ -1,19 +1,23 @@ import * as utils from 'src/utils'; import { expect } from 'chai'; import { - QUANTCAST_CALLBACK_URL_TEST, - QUANTCAST_CALLBACK_URL, + QUANTCAST_DOMAIN, + QUANTCAST_TEST_DOMAIN, QUANTCAST_NET_REVENUE, QUANTCAST_TTL, + QUANTCAST_TEST_PUBLISHER, + QUANTCAST_PROTOCOL, + QUANTCAST_PORT, spec as qcSpec } from '../../../modules/quantcastBidAdapter'; import { newBidder } from '../../../src/adapters/bidderFactory'; +import { parse } from 'src/url'; -describe('Quantcast adapter', () => { +describe('Quantcast adapter', function () { const quantcastAdapter = newBidder(qcSpec); let bidRequest; - beforeEach(() => { + beforeEach(function () { bidRequest = { bidder: 'quantcast', bidId: '2f7b179d443f14', @@ -21,98 +25,83 @@ describe('Quantcast adapter', () => { bidderRequestId: '1cc026909c24c8', placementCode: 'div-gpt-ad-1438287399331-0', params: { - publisherId: 'test-publisher', // REQUIRED - Publisher ID provided by Quantcast + publisherId: QUANTCAST_TEST_PUBLISHER, // REQUIRED - Publisher ID provided by Quantcast battr: [1, 2] // OPTIONAL - Array of blocked creative attributes as per OpenRTB Spec List 5.3 }, sizes: [[300, 250]] }; }); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(quantcastAdapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('`isBidRequestValid`', () => { - it('should return `false` when bid is not passed', () => { + describe('`isBidRequestValid`', function () { + it('should return `false` when bid is not passed', function () { expect(qcSpec.isBidRequestValid()).to.equal(false); }); - it('should return `false` when bid `mediaType` is `video`', () => { + it('should return `false` when bid `mediaType` is `video`', function () { const bidRequest = { mediaType: 'video' }; expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return `true` when bid contains required params', () => { + it('should return `true` when bid contains required params', function () { const bidRequest = { mediaType: 'banner' }; expect(qcSpec.isBidRequestValid(bidRequest)).to.equal(true); }); }); - describe('`buildRequests`', () => { - it('sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`', () => { - const requests = qcSpec.buildRequests([bidRequest]); - + describe('`buildRequests`', function () { + it('selects protocol and port', function () { switch (window.location.protocol) { case 'https:': - expect(requests[0]['url']).to.equal( - `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb` - ); + expect(QUANTCAST_PROTOCOL).to.equal('https'); + expect(QUANTCAST_PORT).to.equal('8443'); break; default: - expect(requests[0]['url']).to.equal( - `http://${QUANTCAST_CALLBACK_URL_TEST}:8080/qchb` - ); + expect(QUANTCAST_PROTOCOL).to.equal('http'); + expect(QUANTCAST_PORT).to.equal('8080'); break; } }); - it('sends bid requests to Quantcast Global Endpoint for regular `publisherId`', () => { - const bidRequest = { - bidder: 'quantcast', - bidId: '2f7b179d443f14', - auctionId: '595ffa73-d78a-46c9-b18e-f99548a5be6b', - bidderRequestId: '1cc026909c24c8', - placementCode: 'div-gpt-ad-1438287399331-0', - params: { - publisherId: 'regular-publisher', // REQUIRED - Publisher ID provided by Quantcast - battr: [1, 2] // OPTIONAL - Array of blocked creative attributes as per OpenRTB Spec List 5.3 - }, - sizes: [[300, 250]] - }; + it('sends bid requests to Quantcast Canary Endpoint if `publisherId` is `test-publisher`', function () { const requests = qcSpec.buildRequests([bidRequest]); + const url = parse(requests[0]['url']); + expect(url.hostname).to.equal(QUANTCAST_TEST_DOMAIN); + }); - switch (window.location.protocol) { - case 'https:': - expect(requests[0]['url']).to.equal( - `https://${QUANTCAST_CALLBACK_URL}:8443/qchb` - ); - break; - default: - expect(requests[0]['url']).to.equal( - `http://${QUANTCAST_CALLBACK_URL}:8080/qchb` - ); - break; - } + it('sends bid requests to default endpoint for non standard publisher IDs', function () { + const modifiedBidRequest = Object.assign({}, bidRequest, { + params: Object.assign({}, bidRequest.params, { + publisherId: 'foo-bar', + }), + }); + const requests = qcSpec.buildRequests([modifiedBidRequest]); + expect(requests[0]['url']).to.equal( + `${QUANTCAST_PROTOCOL}://${QUANTCAST_DOMAIN}:${QUANTCAST_PORT}/qchb` + ); }); - it('sends bid requests to Quantcast Header Bidding Endpoints via POST', () => { + it('sends bid requests to Quantcast Header Bidding Endpoints via POST', function () { const requests = qcSpec.buildRequests([bidRequest]); expect(requests[0].method).to.equal('POST'); }); - it('sends bid requests contains all the required parameters', () => { + it('sends bid requests contains all the required parameters', function () { const referrer = utils.getTopWindowUrl(); const loc = utils.getTopWindowLocation(); const domain = loc.hostname; const requests = qcSpec.buildRequests([bidRequest]); const expectedBidRequest = { - publisherId: 'test-publisher', + publisherId: QUANTCAST_TEST_PUBLISHER, requestId: '2f7b179d443f14', imp: [ { @@ -129,14 +118,23 @@ describe('Quantcast adapter', () => { referrer, domain }, - bidId: '2f7b179d443f14' + bidId: '2f7b179d443f14', + gdprSignal: 0 }; expect(requests[0].data).to.equal(JSON.stringify(expectedBidRequest)); }); }); - describe('`interpretResponse`', () => { + it('propagates GDPR consent string and signal', function () { + const gdprConsent = { gdprApplies: true, consentString: 'consentString' } + const requests = qcSpec.buildRequests([bidRequest], { gdprConsent }); + const parsed = JSON.parse(requests[0].data) + expect(parsed.gdprSignal).to.equal(1); + expect(parsed.gdprConsent).to.equal(gdprConsent.consentString); + }); + + describe('`interpretResponse`', function () { // The sample response is from https://wiki.corp.qc/display/adinf/QCX const body = { bidderCode: 'qcx', // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name @@ -161,25 +159,25 @@ describe('Quantcast adapter', () => { headers: {} }; - it('should return an empty array if `serverResponse` is `undefined`', () => { + it('should return an empty array if `serverResponse` is `undefined`', function () { const interpretedResponse = qcSpec.interpretResponse(); expect(interpretedResponse.length).to.equal(0); }); - it('should return an empty array if the parsed response does NOT include `bids`', () => { + it('should return an empty array if the parsed response does NOT include `bids`', function () { const interpretedResponse = qcSpec.interpretResponse({}); expect(interpretedResponse.length).to.equal(0); }); - it('should return an empty array if the parsed response has an empty `bids`', () => { + it('should return an empty array if the parsed response has an empty `bids`', function () { const interpretedResponse = qcSpec.interpretResponse({ bids: [] }); expect(interpretedResponse.length).to.equal(0); }); - it('should get correct bid response', () => { + it('should get correct bid response', function () { const expectedResponse = { requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', cpm: 4.5, @@ -197,7 +195,7 @@ describe('Quantcast adapter', () => { expect(interpretedResponse[0]).to.deep.equal(expectedResponse); }); - it('handles no bid response', () => { + it('handles no bid response', function () { const body = { bidderCode: 'qcx', // Renaming it to use CamelCase since that is what is used in the Prebid.js variable name requestId: 'erlangcluster@qa-rtb002.us-ec.adtech.com-11417780270886458', // Added this field. This is not used now but could be useful in troubleshooting later on. Specially for sites using iFrames diff --git a/test/spec/modules/quantumBidAdapter_spec.js b/test/spec/modules/quantumBidAdapter_spec.js index 053ec98ffaa..d14d24ebfe1 100644 --- a/test/spec/modules/quantumBidAdapter_spec.js +++ b/test/spec/modules/quantumBidAdapter_spec.js @@ -203,44 +203,101 @@ const nativeServerResponse = { ] } -describe('quantumBidAdapter', () => { +describe('quantumBidAdapter', function () { const adapter = newBidder(spec) - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function') }) }) - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(REQUEST)).to.equal(true) }) - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, REQUEST) delete bid.params expect(spec.isBidRequestValid(bid)).to.equal(false) }) }) - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [REQUEST] const request = spec.buildRequests(bidRequests, {}) - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { expect(request[0].method).to.equal('GET') }) }) - describe('interpretResponse', () => { + describe('GDPR conformity', function () { + const bidRequests = [{ + 'bidder': 'quantum', + 'mediaType': 'native', + 'params': { + placementId: 21546 + }, + adUnitCode: 'aaa', + transactionId: '2b8389fe-615c-482d-9f1a-376fb8f7d6b0', + sizes: [[0, 0]], + bidId: '1abgs362e0x48a8', + bidderRequestId: '70deaff71c281d', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337' + }]; + + const bidderRequest = { + gdprConsent: { + consentString: 'awefasdfwefasdfasd', + gdprApplies: true + } + }; + + it('should transmit correct data', function () { + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests.length).to.equal(1); + expect(requests[0].data.quantx_gdpr).to.equal(1); + expect(requests[0].data.quantx_user_consent_string).to.equal('awefasdfwefasdfasd'); + }); + }); + + describe('GDPR absence conformity', function () { + const bidRequests = [{ + 'bidder': 'quantum', + 'mediaType': 'native', + 'params': { + placementId: 21546 + }, + adUnitCode: 'aaa', + transactionId: '2b8389fe-615c-482d-9f1a-376fb8f7d6b0', + sizes: [[0, 0]], + bidId: '1abgs362e0x48a8', + bidderRequestId: '70deaff71c281d', + auctionId: '5c66da22-426a-4bac-b153-77360bef5337' + }]; + + const bidderRequest = { + gdprConsent: undefined + }; + + it('should transmit correct data', function () { + const requests = spec.buildRequests(bidRequests, bidderRequest); + expect(requests.length).to.equal(1); + expect(requests[0].data.quantx_gdpr).to.be.undefined; + expect(requests[0].data.quantx_user_consent_string).to.be.undefined; + }); + }); + + describe('interpretResponse', function () { let bidderRequest = { bidderCode: 'bidderCode', bids: [] } - it('handles native request : should get correct bid response', () => { + it('handles native request : should get correct bid response', function () { const result = spec.interpretResponse({body: nativeServerResponse}, NATIVE_REQUEST) expect(result[0]).to.have.property('cpm').equal(0.3) expect(result[0]).to.have.property('width').to.be.below(2) @@ -249,7 +306,7 @@ describe('quantumBidAdapter', () => { expect(result[0]).to.have.property('native') }) - it('should get correct bid response', () => { + it('should get correct bid response', function () { const result = spec.interpretResponse({body: serverResponse}, REQUEST) expect(result[0]).to.have.property('cpm').equal(0.3) expect(result[0]).to.have.property('width').equal(300) @@ -258,7 +315,7 @@ describe('quantumBidAdapter', () => { expect(result[0]).to.have.property('ad') }) - it('handles nobid responses', () => { + it('handles nobid responses', function () { const nobidServerResponse = {bids: []} const nobidResult = spec.interpretResponse({body: nobidServerResponse}, bidderRequest) // console.log(nobidResult) diff --git a/test/spec/modules/rdnBidAdapter_spec.js b/test/spec/modules/rdnBidAdapter_spec.js new file mode 100644 index 00000000000..1c5958c8065 --- /dev/null +++ b/test/spec/modules/rdnBidAdapter_spec.js @@ -0,0 +1,128 @@ +import { expect } from 'chai' +import * as utils from 'src/utils' +import { spec } from 'modules/rdnBidAdapter' +import { newBidder } from 'src/adapters/bidderFactory' + +describe('rdnBidAdapter', function() { + const adapter = newBidder(spec); + const ENDPOINT = 'https://s-bid.rmp.rakuten.co.jp/h'; + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function') + }) + }); + + describe('isBidRequestValid', () => { + let bid = { + bidder: 'rdn', + params: { + adSpotId: '56789' + } + }; + + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(bid)).to.equal(true) + }); + + it('should return false when required params are not passed', () => { + bid.params.adSpotId = ''; + expect(spec.isBidRequestValid(bid)).to.equal(false) + }); + + it('should return false when required params are not passed', () => { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false) + }) + }); + + describe('buildRequests', () => { + const bidRequests = [ + { + // banner + params: { + adSpotId: '58278' + } + } + ]; + + it('sends bid request to ENDPOINT via GET', () => { + const request = spec.buildRequests(bidRequests)[0]; + expect(request.url).to.equal(ENDPOINT); + expect(request.method).to.equal('GET') + }) + }); + + describe('interpretResponse', () => { + const bidRequests = { + banner: { + method: 'GET', + url: '', + data: { + t: '56789', + s: 'https', + ua: + 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Mobile Safari/537.36', + l: 'ja', + d: 'examples.com', + tp: 'https://examples.com/foo/fuga', + pp: 'https://examples.com/hoge/muga' + } + } + }; + + const serverResponse = { + noAd: [], + banner: { + requestId: 'biequa9oaph4we', + cpm: 37.66, + width: 300, + height: 250, + creativeId: 140281, + dealId: 'phoh3pad-ai4ah-xoh7x-ahk7cheasae3oh', + currency: 'JPY', + netRevenue: 300, + ttl: 3000, + referrer: utils.getTopWindowUrl(), + ad: '' + } + }; + + it('handles nobid responses', () => { + const result = spec.interpretResponse( + { body: serverResponse.noAd }, + + bidRequests.banner + ); + expect(result.length).to.equal(1) + }) + }); + describe('spec.getUserSyncs', function () { + const syncResponse = [{ + body: { + request_id: 'biequa9oaph4we', + sync_urls: ['https://rdn1.test/sync?uid=9876543210', 'https://rdn2.test/sync?uid=9876543210'] + } + }]; + const nosyncResponse = [{ + body: { + request_id: 'biequa9oaph4we', + sync_urls: [] + } + }]; + let syncOptions + beforeEach(function () { + syncOptions = { + pixelEnabled: true + } + }); + it('sucess usersync url', function () { + const result = []; + result.push({type: 'image', url: 'https://rdn1.test/sync?uid=9876543210'}); + result.push({type: 'image', url: 'https://rdn2.test/sync?uid=9876543210'}); + expect(spec.getUserSyncs(syncOptions, syncResponse)).to.deep.equal(result); + }); + }); +}); diff --git a/test/spec/modules/readpeakBidAdapter_spec.js b/test/spec/modules/readpeakBidAdapter_spec.js index 776261c8db2..572c2b73f8c 100644 --- a/test/spec/modules/readpeakBidAdapter_spec.js +++ b/test/spec/modules/readpeakBidAdapter_spec.js @@ -2,12 +2,12 @@ import { expect } from 'chai'; import { spec, ENDPOINT } from 'modules/readpeakBidAdapter'; import * as utils from 'src/utils'; -describe('ReadPeakAdapter', () => { +describe('ReadPeakAdapter', function () { let bidRequest let serverResponse let serverRequest - beforeEach(() => { + beforeEach(function () { bidRequest = { bidder: 'readpeak', nativeParams: { @@ -113,42 +113,42 @@ describe('ReadPeakAdapter', () => { } }); - describe('spec.isBidRequestValid', () => { - it('should return true when the required params are passed', () => { + describe('spec.isBidRequestValid', function () { + it('should return true when the required params are passed', function () { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should return false when the native params are missing', () => { + it('should return false when the native params are missing', function () { bidRequest.nativeParams = undefined; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when the "publisherId" param is missing', () => { + it('should return false when the "publisherId" param is missing', function () { bidRequest.params = { bidfloor: 5.00 }; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when no bid params are passed', () => { + it('should return false when no bid params are passed', function () { bidRequest.params = {}; expect(spec.isBidRequestValid(bidRequest)).to.equal(false); }); - it('should return false when a bid request is not passed', () => { + it('should return false when a bid request is not passed', function () { expect(spec.isBidRequestValid()).to.equal(false); expect(spec.isBidRequestValid({})).to.equal(false); }); }); - describe('spec.buildRequests', () => { - it('should create a POST request for every bid', () => { + describe('spec.buildRequests', function () { + it('should create a POST request for every bid', function () { const request = spec.buildRequests([ bidRequest ]); expect(request.method).to.equal('POST'); expect(request.url).to.equal(ENDPOINT); }); - it('should attach request data', () => { + it('should attach request data', function () { const request = spec.buildRequests([ bidRequest ]); const data = JSON.parse(request.data); @@ -171,13 +171,13 @@ describe('ReadPeakAdapter', () => { }); }); - describe('spec.interpretResponse', () => { - it('should return no bids if the response is not valid', () => { + describe('spec.interpretResponse', function () { + it('should return no bids if the response is not valid', function () { const bidResponse = spec.interpretResponse({ body: null }, serverRequest); expect(bidResponse.length).to.equal(0); }); - it('should return a valid bid response', () => { + it('should return a valid bid response', function () { const bidResponse = spec.interpretResponse({ body: serverResponse }, serverRequest)[0]; expect(bidResponse).to.contain({ requestId: bidRequest.bidId, diff --git a/test/spec/modules/realvuAnalyticsAdapter_spec.js b/test/spec/modules/realvuAnalyticsAdapter_spec.js index 7bb43002939..1d0fcf9be1a 100644 --- a/test/spec/modules/realvuAnalyticsAdapter_spec.js +++ b/test/spec/modules/realvuAnalyticsAdapter_spec.js @@ -22,19 +22,19 @@ function addDiv(id) { return dv; } -describe('RealVu Analytics Adapter.', () => { - before(() => { +describe('RealVu Analytics Adapter.', function () { + before(function () { addDiv('ad1'); addDiv('ad2'); }); - after(() => { + after(function () { let a1 = document.getElementById('ad1'); document.body.removeChild(a1); let a2 = document.getElementById('ad2'); document.body.removeChild(a2); }); - it('enableAnalytics', () => { + it('enableAnalytics', function () { const config = { options: { partnerId: '1Y', @@ -46,7 +46,7 @@ describe('RealVu Analytics Adapter.', () => { expect(p).to.equal('1Y'); }); - it('checkIn', () => { + it('checkIn', function () { const bid = { adUnitCode: 'ad1', sizes: [ @@ -71,13 +71,13 @@ describe('RealVu Analytics Adapter.', () => { expect(inview).to.equal('yes'); }); - it('isInView return "NA"', () => { + it('isInView return "NA"', function () { const adUnitCode = '1234'; let result = realvuAnalyticsAdapter.isInView(adUnitCode); expect(result).to.equal('NA'); }); - it('bid response event', () => { + it('bid response event', function () { const config = { options: { partnerId: '1Y', @@ -112,12 +112,12 @@ describe('RealVu Analytics Adapter.', () => { }); }); -describe('RealVu Boost.', () => { - before(() => { +describe('RealVu Boost.', function () { + before(function () { addDiv('ad1'); addDiv('ad2'); }); - after(() => { + after(function () { let a1 = document.getElementById('ad1'); document.body.removeChild(a1); let a2 = document.getElementById('ad2'); @@ -126,25 +126,25 @@ describe('RealVu Boost.', () => { const boost = window.top1.realvu_aa; - it('brd', () => { + it('brd', function () { let a1 = document.getElementById('ad1'); let p = boost.brd(a1, 'Left'); expect(typeof p).to.not.equal('undefined'); }); - it('addUnitById', () => { + it('addUnitById', function () { let a1 = document.getElementById('ad1'); let p = boost.addUnitById('1Y', 'ad1'); expect(typeof p).to.not.equal('undefined'); }); - it('questA', () => { + it('questA', function () { const dv = document.getElementById('ad1'); let q = boost.questA(dv); expect(q).to.not.equal(null); }); - it('render', () => { + it('render', function () { let dv = document.getElementById('ad1'); // dv.style.width = '728px'; // dv.style.height = '90px'; @@ -155,7 +155,7 @@ describe('RealVu Boost.', () => { expect(q).to.not.equal(null); }); - it('readPos', () => { + it('readPos', function () { const a = boost.ads[boost.len - 1]; let r = boost.readPos(a); expect(r).to.equal(true); diff --git a/test/spec/modules/rhythmoneBidAdapter_spec.js b/test/spec/modules/rhythmoneBidAdapter_spec.js index dd7ce4c379d..2f06e7f8288 100644 --- a/test/spec/modules/rhythmoneBidAdapter_spec.js +++ b/test/spec/modules/rhythmoneBidAdapter_spec.js @@ -61,7 +61,7 @@ describe('rhythmone adapter tests', function () { assert.equal(mangoRequest.length, 1); }); - it('should send GDPR Consent data to RhythmOne tag', () => { + it('should send GDPR Consent data to RhythmOne tag', function () { let _consentString = 'testConsentString'; var request = z.buildRequests( [ diff --git a/test/spec/modules/rockyouBidAdapter_spec.js b/test/spec/modules/rockyouBidAdapter_spec.js index f929b50d581..65d87566c26 100644 --- a/test/spec/modules/rockyouBidAdapter_spec.js +++ b/test/spec/modules/rockyouBidAdapter_spec.js @@ -2,16 +2,16 @@ import { expect } from 'chai'; import { spec, internals } from 'modules/rockyouBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -describe('RockYouAdapter', () => { +describe('RockYouAdapter', function () { const adapter = newBidder(spec); - describe('bid validator', () => { - it('rejects a bid that is missing the placementId', () => { + describe('bid validator', function () { + it('rejects a bid that is missing the placementId', function () { let testBid = {}; expect(spec.isBidRequestValid(testBid)).to.be.false; }); - it('accepts a bid with all the expected parameters', () => { + it('accepts a bid with all the expected parameters', function () { let testBid = { params: { placementId: 'f39ba81609' @@ -22,7 +22,7 @@ describe('RockYouAdapter', () => { }); }); - describe('request builder', () => { + describe('request builder', function () { // Taken from the docs, so used as much as is valid const sampleBidRequest = { 'bidder': 'tests', @@ -43,7 +43,7 @@ describe('RockYouAdapter', () => { } }; - it('successfully generates a URL', () => { + it('successfully generates a URL', function () { const placementId = 'ZZZPLACEMENTZZZ'; let bidRequests = [ @@ -65,7 +65,7 @@ describe('RockYouAdapter', () => { expect(result.url).to.include('/servlet/rotator/' + placementId + '/0/vo?z=') }); - it('uses the bidId id as the openRtb request ID', () => { + it('uses the bidId id as the openRtb request ID', function () { const bidId = '51ef8751f9aead'; let bidRequests = [ @@ -84,7 +84,7 @@ describe('RockYouAdapter', () => { expect(payload.id).to.equal(bidId); }); - it('generates the device payload as expected', () => { + it('generates the device payload as expected', function () { let bidRequests = [ sampleBidRequest ]; @@ -103,7 +103,7 @@ describe('RockYouAdapter', () => { expect(userData).to.not.be.null; }); - it('generates multiple requests with single imp bodies', () => { + it('generates multiple requests with single imp bodies', function () { const SECOND_PLACEMENT_ID = 'YYYPLACEMENTIDYYY'; let firstBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); let secondBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); @@ -146,7 +146,7 @@ describe('RockYouAdapter', () => { expect(secondRequest.url.indexOf(SECOND_PLACEMENT_ID)).to.be.gt(0); }); - it('generates a banner request as expected', () => { + it('generates a banner request as expected', function () { // clone the sample for stability let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); @@ -172,7 +172,7 @@ describe('RockYouAdapter', () => { expect(bannerData.h).to.equal(50); }); - it('generates a banner request using a singular adSize instead of an array', () => { + it('generates a banner request using a singular adSize instead of an array', function () { // clone the sample for stability let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); localBidRequest.sizes = [320, 50]; @@ -200,7 +200,7 @@ describe('RockYouAdapter', () => { expect(bannerData.h).to.equal(50); }); - it('fails gracefully on an invalid size', () => { + it('fails gracefully on an invalid size', function () { // clone the sample for stability let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); localBidRequest.sizes = ['x', 'w']; @@ -229,7 +229,7 @@ describe('RockYouAdapter', () => { expect(bannerData.h).to.equal(null); }); - it('generates a video request as expected', () => { + it('generates a video request as expected', function () { // clone the sample for stability let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); @@ -259,7 +259,7 @@ describe('RockYouAdapter', () => { expect(videoData.h).to.equal(56); }); - it('propagates the mediaTypes object in the built request', () => { + it('propagates the mediaTypes object in the built request', function () { let localBidRequest = JSON.parse(JSON.stringify(sampleBidRequest)); localBidRequest.mediaTypes = { video: {} }; @@ -278,8 +278,8 @@ describe('RockYouAdapter', () => { }); }); - describe('response interpreter', () => { - it('returns an empty array when no bids present', () => { + describe('response interpreter', function () { + it('returns an empty array when no bids present', function () { // an empty JSON body indicates no ad was found let result = spec.interpretResponse({ body: '' }, {}) @@ -287,13 +287,13 @@ describe('RockYouAdapter', () => { expect(result).to.eql([]); }); - it('gracefully fails when a non-JSON body is present', () => { + it('gracefully fails when a non-JSON body is present', function () { let result = spec.interpretResponse({ body: 'THIS IS NOT ' }, {}) expect(result).to.eql([]); }); - it('returns a valid bid response on sucessful banner request', () => { + it('returns a valid bid response on sucessful banner request', function () { let incomingRequestId = 'XXtestingXX'; let responsePrice = 3.14 @@ -365,7 +365,7 @@ describe('RockYouAdapter', () => { expect(processedBid.currency).to.equal(responseCurrency); }); - it('returns an valid bid response on sucessful video request', () => { + it('returns an valid bid response on sucessful video request', function () { let incomingRequestId = 'XXtesting-275XX'; let responsePrice = 6 @@ -438,7 +438,7 @@ describe('RockYouAdapter', () => { expect(processedBid.vastXml).to.equal(responseCreative); }); - it('generates event callbacks as expected', () => { + it('generates event callbacks as expected', function () { let tally = {}; let renderer = { handleVideoEvent: (eventObject) => { @@ -466,7 +466,7 @@ describe('RockYouAdapter', () => { expect(tally['ended']).to.equal(2); }); - it('generates a renderer that will hide on complete', () => { + it('generates a renderer that will hide on complete', function () { let elementName = 'test_element_id'; let selector = `#${elementName}`; diff --git a/test/spec/modules/roxotAnalyticsAdapter_spec.js b/test/spec/modules/roxotAnalyticsAdapter_spec.js index f2db77892f6..cd48cb7f37d 100644 --- a/test/spec/modules/roxotAnalyticsAdapter_spec.js +++ b/test/spec/modules/roxotAnalyticsAdapter_spec.js @@ -1,61 +1,450 @@ import roxotAnalytic from 'modules/roxotAnalyticsAdapter'; -import { expect } from 'chai'; +import {expect} from 'chai'; + let events = require('src/events'); -let adaptermanager = require('src/adaptermanager'); let constants = require('src/constants.json'); describe('Roxot Prebid Analytic', function () { let xhr; - before(() => { + let requests; + + let roxotConfigServerUrl = 'config-server'; + let roxotEventServerUrl = 'event-server'; + let publisherId = 'test_roxot_prebid_analytics_publisher_id'; + + let auctionId = '0ea14159-2058-4b87-a966-9d7652176a56'; + let timeout = 3000; + let auctionStartTimestamp = Date.now(); + let bidder = 'rubicon'; + + let bidAdUnit = 'div_with_bid'; + let noBidAdUnit = 'div_no_bid'; + let bidAfterTimeoutAdUnit = 'div_after_timeout'; + + let auctionInit = { + timestamp: auctionStartTimestamp, + auctionId: auctionId, + timeout: timeout + }; + + let bidRequested = { + auctionId: auctionId, + auctionStart: auctionStartTimestamp, + bidderCode: bidder, + bidderRequestId: '10340af0c7dc72', + bids: [ + { + adUnitCode: bidAdUnit, + auctionId: auctionId, + bidId: '298bf14ecbafb', + bidder: bidder, + bidderRequestId: '10340af0c7dc72', + sizes: [[300, 250]], + startTime: auctionStartTimestamp + 50, + transactionId: '7aafa3ee-a80a-46d7-a4a0-cbcba463d97a' + }, + { + adUnitCode: bidAfterTimeoutAdUnit, + auctionId: auctionId, + bidId: '36c6375e2dceba', + bidder: bidder, + bidderRequestId: '10340af0c7dc72', + sizes: [[300, 250]], + startTime: auctionStartTimestamp + 70, + transactionId: 'cf627df3-5828-4d3e-9dd0-c1733d328142' + }, + { + adUnitCode: noBidAdUnit, + auctionId: auctionId, + bidId: '36c6375e2dce21', + bidder: bidder, + bidderRequestId: '10340af0c7dc72', + sizes: [[300, 250]], + startTime: auctionStartTimestamp + 90, + transactionId: 'cf627df3-5828-4d3e-9dd0-c1737aafa3ee' + } + ], + doneCbCallCount: 1, + start: auctionStartTimestamp, + timeout: timeout + }; + + let bidAdjustmentWithBid = { + ad: 'html', + adId: '298bf14ecbafb', + adUnitCode: bidAdUnit, + auctionId: auctionId, + bidder: bidder, + bidderCode: bidder, + cpm: 1.01, + creativeId: '2249:92806132', + currency: 'USD', + height: 250, + mediaType: 'banner', + requestId: '298bf14ecbafb', + requestTimestamp: auctionStartTimestamp + 50, + responseTimestamp: auctionStartTimestamp + 50 + 421, + size: '300x250', + source: 'client', + status: 'rendered', + statusMessage: 'Bid available', + timeToRespond: 421, + ttl: 300, + width: 300 + }; + + let bidAdjustmentAfterTimeout = { + ad: 'html', + adId: '36c6375e2dceba', + adUnitCode: bidAfterTimeoutAdUnit, + auctionId: auctionId, + bidder: bidder, + bidderCode: bidder, + cpm: 2.02, + creativeId: '2249:92806132', + currency: 'USD', + height: 250, + mediaType: 'banner', + requestId: '36c6375e2dceba', + requestTimestamp: auctionStartTimestamp + 70, + responseTimestamp: auctionStartTimestamp + 70 + 6141, + size: '300x250', + source: 'client', + status: 'rendered', + statusMessage: 'Bid available', + timeToRespond: 6141, + ttl: 300, + width: 300 + }; + + let bidAdjustmentNoBid = { + ad: 'html', + adId: '36c6375e2dce21', + adUnitCode: noBidAdUnit, + auctionId: auctionId, + bidder: bidder, + bidderCode: bidder, + cpm: 0, + creativeId: '2249:92806132', + currency: 'USD', + height: 0, + mediaType: 'banner', + requestId: '36c6375e2dce21', + requestTimestamp: auctionStartTimestamp + 90, + responseTimestamp: auctionStartTimestamp + 90 + 215, + size: '300x250', + source: 'client', + status: 'rendered', + statusMessage: 'Bid available', + timeToRespond: 215, + ttl: 300, + width: 0 + }; + + let auctionEnd = { + auctionId: auctionId + }; + + let bidTimeout = [ + { + adUnitCode: bidAfterTimeoutAdUnit, + auctionId: auctionId, + bidId: '389444beed7361', + bidder: bidder, + timeout: timeout + } + ]; + + let bidResponseWithBid = bidAdjustmentWithBid; + let bidResponseAfterTimeout = bidAdjustmentAfterTimeout; + let bidResponseNoBid = bidAdjustmentNoBid; + let bidderDone = bidRequested; + let bidWon = bidAdjustmentWithBid; + + before(function () { xhr = sinon.useFakeXMLHttpRequest(); - }) - after(() => { - roxotAnalytic.disableAnalytics(); + xhr.onCreate = request => requests.push(request); + }); + after(function () { xhr.restore(); }); - describe('enableAnalytics', function () { - beforeEach(() => { - sinon.spy(roxotAnalytic, 'track'); + describe('correct build and send events', function () { + beforeEach(function () { + requests = []; sinon.stub(events, 'getEvents').returns([]); }); - - afterEach(() => { - roxotAnalytic.track.restore(); + afterEach(function () { + roxotAnalytic.disableAnalytics(); events.getEvents.restore(); }); - it('should catch all events', function () { - adaptermanager.registerAnalyticsAdapter({ - code: 'roxot', - adapter: roxotAnalytic + it('should send prepared events to backend', function () { + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: { + publisherId: publisherId, + configServer: roxotConfigServerUrl, + server: roxotEventServerUrl + } }); - adaptermanager.enableAnalytics({ + expect(requests.length).to.equal(1); + expect(requests[0].url).to.equal('//' + roxotConfigServerUrl + '/c?publisherId=' + publisherId + '&host=localhost'); + requests[0].respond(200, {'Content-Type': 'application/json'}, '{"a": 1, "i": 1, "bat": 1}'); + + events.emit(constants.EVENTS.AUCTION_INIT, auctionInit); + events.emit(constants.EVENTS.BID_REQUESTED, bidRequested); + events.emit(constants.EVENTS.BID_ADJUSTMENT, bidAdjustmentWithBid); + events.emit(constants.EVENTS.BID_RESPONSE, bidResponseWithBid); + events.emit(constants.EVENTS.BID_ADJUSTMENT, bidAdjustmentNoBid); + events.emit(constants.EVENTS.BID_RESPONSE, bidResponseNoBid); + events.emit(constants.EVENTS.BID_TIMEOUT, bidTimeout); + events.emit(constants.EVENTS.AUCTION_END, auctionEnd); + events.emit(constants.EVENTS.BID_ADJUSTMENT, bidAdjustmentAfterTimeout); + events.emit(constants.EVENTS.BID_RESPONSE, bidResponseAfterTimeout); + events.emit(constants.EVENTS.BIDDER_DONE, bidderDone); + events.emit(constants.EVENTS.BID_WON, bidWon); + + expect(requests.length).to.equal(4); + + expect(requests[1].url).to.equal('//' + roxotEventServerUrl + '/a?publisherId=' + publisherId + '&host=localhost'); + expect(requests[2].url).to.equal('//' + roxotEventServerUrl + '/bat?publisherId=' + publisherId + '&host=localhost'); + expect(requests[3].url).to.equal('//' + roxotEventServerUrl + '/i?publisherId=' + publisherId + '&host=localhost'); + + let auction = JSON.parse(requests[1].requestBody); + expect(auction).to.include.all.keys('event', 'eventName', 'options', 'data'); + expect(auction.event).to.equal('a'); + + expect(auction.data).to.include.all.keys('id', 'start', 'finish', 'timeout', 'adUnits'); + expect(auction.data.id).to.equal(auctionId); + expect(auction.data.timeout).to.equal(timeout); + + expect(auction.data.adUnits).to.include.all.keys(bidAdUnit, bidAfterTimeoutAdUnit, noBidAdUnit); + expect(auction.data.adUnits[bidAdUnit].bidders).to.have.property(bidder); + expect(auction.data.adUnits[bidAfterTimeoutAdUnit].bidders).to.have.property(bidder); + expect(auction.data.adUnits[noBidAdUnit].bidders).to.have.property(bidder); + + expect(auction.data.adUnits[bidAdUnit].bidders[bidder].status).to.equal('bid'); + expect(auction.data.adUnits[bidAfterTimeoutAdUnit].bidders[bidder].status).to.equal('timeout'); + expect(auction.data.adUnits[noBidAdUnit].bidders[bidder].status).to.equal('noBid'); + + let bidAfterTimeout = JSON.parse(requests[2].requestBody); + expect(bidAfterTimeout).to.include.all.keys('event', 'eventName', 'options', 'data'); + expect(bidAfterTimeout.event).to.equal('bat'); + + expect(bidAfterTimeout.data).to.include.all.keys('start', 'finish', 'mediaType', 'adUnit', 'bidder', 'cpm', 'size', 'auction'); + expect(bidAfterTimeout.data.adUnit).to.equal(bidAfterTimeoutAdUnit); + expect(bidAfterTimeout.data.bidder).to.equal(bidder); + expect(bidAfterTimeout.data.cpm).to.equal(bidAdjustmentAfterTimeout.cpm); + + let impression = JSON.parse(requests[3].requestBody); + expect(impression).to.include.all.keys('event', 'eventName', 'options', 'data'); + expect(impression.event).to.equal('i'); + + expect(impression.data).to.include.all.keys('mediaType', 'adUnit', 'bidder', 'cpm', 'size', 'auction', 'isNew'); + expect(impression.data.adUnit).to.equal(bidAdUnit); + expect(impression.data.bidder).to.equal(bidder); + expect(impression.data.cpm).to.equal(bidAdjustmentWithBid.cpm); + }); + }); + + describe('support ad unit filter', function () { + beforeEach(function () { + requests = []; + sinon.stub(events, 'getEvents').returns([]); + }); + afterEach(function () { + roxotAnalytic.disableAnalytics(); + events.getEvents.restore(); + }); + it('should not send event for blocked ad unit', function () { + roxotAnalytic.enableAnalytics({ provider: 'roxot', options: { - publisherIds: ['test_roxot_prebid_analytid_publisher_id'] + publisherId: publisherId, + configServer: roxotConfigServerUrl, + server: roxotEventServerUrl, + adUnits: [noBidAdUnit, bidAfterTimeoutAdUnit] } }); - events.emit(constants.EVENTS.AUCTION_INIT, {}); - events.emit(constants.EVENTS.AUCTION_END, {}); - events.emit(constants.EVENTS.BID_REQUESTED, {}); - events.emit(constants.EVENTS.BID_RESPONSE, {}); - events.emit(constants.EVENTS.BID_WON, {}); + expect(requests.length).to.equal(1); + expect(requests[0].url).to.equal('//' + roxotConfigServerUrl + '/c?publisherId=' + publisherId + '&host=localhost'); + requests[0].respond(200, {'Content-Type': 'application/json'}, '{"a": 1, "i": 1, "bat": 1}'); + + events.emit(constants.EVENTS.AUCTION_INIT, auctionInit); + events.emit(constants.EVENTS.BID_REQUESTED, bidRequested); + events.emit(constants.EVENTS.BID_ADJUSTMENT, bidAdjustmentWithBid); + events.emit(constants.EVENTS.BID_RESPONSE, bidResponseWithBid); + events.emit(constants.EVENTS.BID_ADJUSTMENT, bidAdjustmentNoBid); + events.emit(constants.EVENTS.BID_RESPONSE, bidResponseNoBid); + events.emit(constants.EVENTS.BID_TIMEOUT, bidTimeout); + events.emit(constants.EVENTS.AUCTION_END, auctionEnd); + events.emit(constants.EVENTS.BID_ADJUSTMENT, bidAdjustmentAfterTimeout); + events.emit(constants.EVENTS.BID_RESPONSE, bidResponseAfterTimeout); + events.emit(constants.EVENTS.BIDDER_DONE, bidderDone); + events.emit(constants.EVENTS.BID_WON, bidWon); - sinon.assert.callCount(roxotAnalytic.track, 5); + expect(requests.length).to.equal(3); + + expect(requests[1].url).to.equal('//' + roxotEventServerUrl + '/a?publisherId=' + publisherId + '&host=localhost'); + expect(requests[2].url).to.equal('//' + roxotEventServerUrl + '/bat?publisherId=' + publisherId + '&host=localhost'); + + let auction = JSON.parse(requests[1].requestBody); + expect(auction.data.adUnits).to.include.all.keys(noBidAdUnit, bidAfterTimeoutAdUnit); + expect(auction.data.adUnits).to.not.include.all.keys(bidAdUnit); }); }); - describe('build utm tag data', () => { - beforeEach(() => { + + describe('should correct parse config', function () { + beforeEach(function () { + requests = []; + sinon.stub(events, 'getEvents').returns([]); + }); + + afterEach(function () { + roxotAnalytic.disableAnalytics(); + events.getEvents.restore(); + }); + + it('correct parse publisher config', function () { + let publisherOptions = { + publisherId: publisherId, + configServer: roxotConfigServerUrl, + server: roxotEventServerUrl, + anything: 'else', + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + expect(roxotAnalytic.getOptions().options).to.deep.equal(publisherOptions); + }); + + it('support deprecated options', function () { + let publisherOptions = { + publisherIds: [publisherId], + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + expect(roxotAnalytic.getOptions().options).to.deep.equal(publisherOptions); + expect(roxotAnalytic.getOptions().publisherId).to.equal(publisherId); + }); + + it('support default end-points', function () { + let publisherOptions = { + publisherId: publisherId, + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + expect(roxotAnalytic.getOptions().configServer).to.equal('pa.rxthdr.com/v3'); + expect(roxotAnalytic.getOptions().server).to.equal('pa.rxthdr.com/v3'); + }); + + it('support custom config end-point', function () { + let publisherOptions = { + publisherId: publisherId, + configServer: roxotConfigServerUrl + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + expect(roxotAnalytic.getOptions().configServer).to.equal(roxotConfigServerUrl); + expect(roxotAnalytic.getOptions().server).to.equal('pa.rxthdr.com/v3'); + }); + + it('support custom config and event end-point', function () { + let publisherOptions = { + publisherId: publisherId, + server: roxotEventServerUrl + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + expect(roxotAnalytic.getOptions().configServer).to.equal(roxotEventServerUrl); + expect(roxotAnalytic.getOptions().server).to.equal(roxotEventServerUrl); + }); + + it('support different config and event end-points', function () { + let publisherOptions = { + publisherId: publisherId, + configServer: roxotConfigServerUrl, + server: roxotEventServerUrl + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + expect(roxotAnalytic.getOptions().configServer).to.equal(roxotConfigServerUrl); + expect(roxotAnalytic.getOptions().server).to.equal(roxotEventServerUrl); + }); + + it('support adUnit filter', function () { + let publisherOptions = { + publisherId: publisherId, + adUnits: ['div1', 'div2'] + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + expect(roxotAnalytic.getOptions().adUnits).to.deep.equal(['div1', 'div2']); + }); + + it('support fail loading server config', function () { + let publisherOptions = { + publisherId: publisherId + }; + + roxotAnalytic.enableAnalytics({ + provider: 'roxot', + options: publisherOptions + }); + + requests[0].respond(500); + + expect(roxotAnalytic.getOptions().serverConfig).to.deep.equal({a: 1, i: 1, bat: 1, isError: 1}); + }); + }); + + describe('build utm tag data', function () { + beforeEach(function () { localStorage.setItem('roxot_analytics_utm_source', 'utm_source'); localStorage.setItem('roxot_analytics_utm_medium', 'utm_medium'); localStorage.setItem('roxot_analytics_utm_campaign', ''); localStorage.setItem('roxot_analytics_utm_term', ''); localStorage.setItem('roxot_analytics_utm_content', ''); - localStorage.setItem('roxot_analytics_utm_timeout', Date.now()); + localStorage.setItem('roxot_analytics_utm_ttl', Date.now()); + }); + afterEach(function () { + localStorage.removeItem('roxot_analytics_utm_source'); + localStorage.removeItem('roxot_analytics_utm_medium'); + localStorage.removeItem('roxot_analytics_utm_campaign'); + localStorage.removeItem('roxot_analytics_utm_term'); + localStorage.removeItem('roxot_analytics_utm_content'); + localStorage.removeItem('roxot_analytics_utm_ttl'); }); - it('should build utm data from local storage', () => { + it('should build utm data from local storage', function () { let utmTagData = roxotAnalytic.buildUtmTagData(); expect(utmTagData.utm_source).to.equal('utm_source'); expect(utmTagData.utm_medium).to.equal('utm_medium'); diff --git a/test/spec/modules/rtbdemandBidAdapter_spec.js b/test/spec/modules/rtbdemandBidAdapter_spec.js index 20d3e410aee..25178c21d88 100644 --- a/test/spec/modules/rtbdemandBidAdapter_spec.js +++ b/test/spec/modules/rtbdemandBidAdapter_spec.js @@ -2,16 +2,16 @@ import { expect } from 'chai'; import { spec } from 'modules/rtbdemandBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -describe('rtbdemandAdapter', () => { +describe('rtbdemandAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'rtbdemand', 'params': { @@ -26,11 +26,11 @@ describe('rtbdemandAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return true when required params found', () => { + it('should return true when required params found', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -39,7 +39,7 @@ describe('rtbdemandAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -49,7 +49,7 @@ describe('rtbdemandAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidderRequest = { bidderCode: 'rtbdemand', auctionId: 'c45dd708-a418-42ec-b8a7-b70a6c6fab0a', @@ -89,7 +89,7 @@ describe('rtbdemandAdapter', () => { timeout: 5000 }; - it('should add source and verison to the tag', () => { + it('should add source and verison to the tag', function () { const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); const payload = request.data; expect(payload.from).to.exist; @@ -106,14 +106,14 @@ describe('rtbdemandAdapter', () => { expect(payload.tmax).to.exist; }); - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { const [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); expect(request.url).to.equal('//bidding.rtbdemand.com/hb'); expect(request.method).to.equal('GET'); }); }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { 'id': '543210', 'seatbid': [ { @@ -128,7 +128,7 @@ describe('rtbdemandAdapter', () => { } ] }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { requestId: 'bidId-123456-1', @@ -147,7 +147,7 @@ describe('rtbdemandAdapter', () => { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = { 'id': '543210', 'seatbid': [ ] @@ -158,10 +158,10 @@ describe('rtbdemandAdapter', () => { }); }); - describe('user sync', () => { + describe('user sync', function () { const syncUrl = '//bidding.rtbdemand.com/delivery/matches.php?type=iframe'; - it('should register the sync iframe', () => { + it('should register the sync iframe', function () { expect(spec.getUserSyncs({})).to.be.undefined; expect(spec.getUserSyncs({iframeEnabled: false})).to.be.undefined; const options = spec.getUserSyncs({iframeEnabled: true}); diff --git a/test/spec/modules/rtbdemandadkBidAdapter_spec.js b/test/spec/modules/rtbdemandadkBidAdapter_spec.js index 8e49c2b85da..c1fbd35d6c9 100644 --- a/test/spec/modules/rtbdemandadkBidAdapter_spec.js +++ b/test/spec/modules/rtbdemandadkBidAdapter_spec.js @@ -2,7 +2,7 @@ import {expect} from 'chai'; import {spec} from 'modules/rtbdemandadkBidAdapter'; import * as utils from 'src/utils'; -describe('rtbdemandadk adapter', () => { +describe('rtbdemandadk adapter', function () { const bid1_zone1 = { bidder: 'rtbdemandadk', bidId: 'Bid_01', @@ -107,29 +107,29 @@ describe('rtbdemandadk adapter', () => { } }; - describe('input parameters validation', () => { - it('empty request shouldn\'t generate exception', () => { + describe('input parameters validation', function () { + it('empty request shouldn\'t generate exception', function () { expect(spec.isBidRequestValid({ bidderCode: 'rtbdemandadk' })).to.be.equal(false); }); - it('request without zone shouldn\'t issue a request', () => { + it('request without zone shouldn\'t issue a request', function () { expect(spec.isBidRequestValid(bid_without_zone)).to.be.equal(false); }); - it('request without host shouldn\'t issue a request', () => { + it('request without host shouldn\'t issue a request', function () { expect(spec.isBidRequestValid(bid_without_host)).to.be.equal(false); }); - it('empty request shouldn\'t generate exception', () => { + it('empty request shouldn\'t generate exception', function () { expect(spec.isBidRequestValid(bid_with_wrong_zoneId)).to.be.equal(false); }); }); - describe('banner request building', () => { + describe('banner request building', function () { let bidRequest; - before(() => { + before(function () { let wmock = sinon.stub(utils, 'getTopWindowLocation').callsFake(() => ({ protocol: 'https:', hostname: 'example.com', @@ -144,33 +144,33 @@ describe('rtbdemandadk adapter', () => { dntmock.restore(); }); - it('should be a first-price auction', () => { + it('should be a first-price auction', function () { expect(bidRequest).to.have.property('at', 1); }); - it('should have banner object', () => { + it('should have banner object', function () { expect(bidRequest.imp[0]).to.have.property('banner'); }); - it('should have w/h', () => { + it('should have w/h', function () { expect(bidRequest.imp[0].banner).to.have.property('format'); expect(bidRequest.imp[0].banner.format).to.be.eql([{w: 300, h: 250}, {w: 300, h: 200}]); }); - it('should respect secure connection', () => { + it('should respect secure connection', function () { expect(bidRequest.imp[0]).to.have.property('secure', 1); }); - it('should have tagid', () => { + it('should have tagid', function () { expect(bidRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); }); - it('should create proper site block', () => { + it('should create proper site block', function () { expect(bidRequest.site).to.have.property('domain', 'example.com'); expect(bidRequest.site).to.have.property('page', 'https://example.com/index.html'); }); - it('should fill device with caller macro', () => { + it('should fill device with caller macro', function () { expect(bidRequest).to.have.property('device'); expect(bidRequest.device).to.have.property('ip', 'caller'); expect(bidRequest.device).to.have.property('ua', 'caller'); @@ -178,37 +178,37 @@ describe('rtbdemandadk adapter', () => { }); }); - describe('video request building', () => { + describe('video request building', function () { let bidRequest; - before(() => { + before(function () { let request = spec.buildRequests([bid_video])[0]; bidRequest = JSON.parse(request.data.r); }); - it('should have video object', () => { + it('should have video object', function () { expect(bidRequest.imp[0]).to.have.property('video'); }); - it('should have h/w', () => { + it('should have h/w', function () { expect(bidRequest.imp[0].video).to.have.property('w', 640); expect(bidRequest.imp[0].video).to.have.property('h', 480); }); - it('should have tagid', () => { + it('should have tagid', function () { expect(bidRequest.imp[0]).to.have.property('tagid', 'ad-unit-1'); }); }); - describe('requests routing', () => { - it('should issue a request for each host', () => { + describe('requests routing', function () { + it('should issue a request for each host', function () { let pbRequests = spec.buildRequests([bid1_zone1, bid3_host2]); expect(pbRequests).to.have.length(2); expect(pbRequests[0].url).to.have.string(`//${bid1_zone1.params.host}/`); expect(pbRequests[1].url).to.have.string(`//${bid3_host2.params.host}/`); }); - it('should issue a request for each zone', () => { + it('should issue a request for each zone', function () { let pbRequests = spec.buildRequests([bid1_zone1, bid2_zone2]); expect(pbRequests).to.have.length(2); expect(pbRequests[0].data.zone).to.be.equal(bid1_zone1.params.zoneId); @@ -216,8 +216,8 @@ describe('rtbdemandadk adapter', () => { }); }); - describe('responses processing', () => { - it('should return fully-initialized banner bid-response', () => { + describe('responses processing', function () { + it('should return fully-initialized banner bid-response', function () { let request = spec.buildRequests([bid1_zone1])[0]; let resp = spec.interpretResponse({body: bidResponse1}, request)[0]; expect(resp).to.have.property('requestId', 'Bid_01'); @@ -232,7 +232,7 @@ describe('rtbdemandadk adapter', () => { expect(resp.ad).to.have.string(''); }); - it('should return fully-initialized video bid-response', () => { + it('should return fully-initialized video bid-response', function () { let request = spec.buildRequests([bid_video])[0]; let resp = spec.interpretResponse({body: videoBidResponse}, request)[0]; expect(resp).to.have.property('requestId', 'Bid_Video'); @@ -243,20 +243,20 @@ describe('rtbdemandadk adapter', () => { expect(resp.height).to.equal(480); }); - it('should add nurl as pixel for banner response', () => { + it('should add nurl as pixel for banner response', function () { let request = spec.buildRequests([bid1_zone1])[0]; let resp = spec.interpretResponse({body: bidResponse1}, request)[0]; let expectedNurl = bidResponse1.seatbid[0].bid[0].nurl + '&px=1'; expect(resp.ad).to.have.string(expectedNurl); }); - it('should handle bidresponse with user-sync only', () => { + it('should handle bidresponse with user-sync only', function () { let request = spec.buildRequests([bid1_zone1])[0]; let resp = spec.interpretResponse({body: usersyncOnlyResponse}, request); expect(resp).to.have.length(0); }); - it('should perform usersync', () => { + it('should perform usersync', function () { let syncs = spec.getUserSyncs({iframeEnabled: false}, [{body: bidResponse1}]); expect(syncs).to.have.length(0); syncs = spec.getUserSyncs({iframeEnabled: true}, [{body: bidResponse1}]); diff --git a/test/spec/modules/rtbhouseBidAdapter_spec.js b/test/spec/modules/rtbhouseBidAdapter_spec.js index 70f21d2c868..b1d20ebc203 100644 --- a/test/spec/modules/rtbhouseBidAdapter_spec.js +++ b/test/spec/modules/rtbhouseBidAdapter_spec.js @@ -17,16 +17,16 @@ function buildEndpointUrl(region) { * endof Helpers */ -describe('RTBHouseAdapter', () => { +describe('RTBHouseAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'rtbhouse', 'params': { @@ -40,11 +40,11 @@ describe('RTBHouseAdapter', () => { 'auctionId': '1d1a030790a475' }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -54,7 +54,7 @@ describe('RTBHouseAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'rtbhouse', @@ -71,12 +71,12 @@ describe('RTBHouseAdapter', () => { } ]; - it('should build test param into the request', () => { + it('should build test param into the request', function () { let builtTestRequest = spec.buildRequests(bidRequests).data; expect(JSON.parse(builtTestRequest).test).to.equal(1); }); - it('sends bid request to ENDPOINT via POST', () => { + it('sends bid request to ENDPOINT via POST', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; const request = spec.buildRequests(bidRequest); @@ -84,7 +84,7 @@ describe('RTBHouseAdapter', () => { expect(request.method).to.equal('POST'); }); - it('should not populate GDPR if for non-EEA users', () => { + it('should not populate GDPR if for non-EEA users', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; const request = spec.buildRequests(bidRequest); @@ -93,7 +93,7 @@ describe('RTBHouseAdapter', () => { expect(data).to.not.have.property('user'); }); - it('should populate GDPR and consent string if available for EEA users', () => { + it('should populate GDPR and consent string if available for EEA users', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; const request = spec.buildRequests(bidRequest, {gdprConsent: {gdprApplies: true, consentString: consentStr}}); @@ -102,7 +102,7 @@ describe('RTBHouseAdapter', () => { expect(data.user.ext.consent).to.equal('BOJ8RZsOJ8RZsABAB8AAAAAZ-A'); }); - it('should populate GDPR and empty consent string if available for EEA users without consent string but with consent', () => { + it('should populate GDPR and empty consent string if available for EEA users without consent string but with consent', function () { let bidRequest = Object.assign([], bidRequests); delete bidRequest[0].params.test; const request = spec.buildRequests(bidRequest, {gdprConsent: {gdprApplies: true}}); @@ -112,7 +112,7 @@ describe('RTBHouseAdapter', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = [{ 'id': 'bidder_imp_identifier', 'impid': '552b8922e28f27', @@ -125,7 +125,7 @@ describe('RTBHouseAdapter', () => { 'h': 250 }]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { 'requestId': '552b8922e28f27', @@ -145,7 +145,7 @@ describe('RTBHouseAdapter', () => { expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = ''; let bidderRequest; let result = spec.interpretResponse({ body: response }, {bidderRequest}); diff --git a/test/spec/modules/rubiconAnalyticsAdapter_spec.js b/test/spec/modules/rubiconAnalyticsAdapter_spec.js index 21ed1cfa522..fa64513730a 100644 --- a/test/spec/modules/rubiconAnalyticsAdapter_spec.js +++ b/test/spec/modules/rubiconAnalyticsAdapter_spec.js @@ -1,4 +1,3 @@ -import adaptermanager from 'src/adaptermanager'; import rubiconAnalyticsAdapter, { SEND_TIMEOUT } from 'modules/rubiconAnalyticsAdapter'; import CONSTANTS from 'src/constants.json'; import { config } from 'src/config'; @@ -410,14 +409,14 @@ function performStandardAuction() { events.emit(BID_WON, MOCK.BID_WON[1]); } -describe('rubicon analytics adapter', () => { +describe('rubicon analytics adapter', function () { let sandbox; let xhr; let requests; let oldScreen; let clock; - beforeEach(() => { + beforeEach(function () { sandbox = sinon.sandbox.create(); xhr = sandbox.useFakeXMLHttpRequest(); @@ -438,12 +437,12 @@ describe('rubicon analytics adapter', () => { }) }); - afterEach(() => { + afterEach(function () { sandbox.restore(); config.resetConfig(); }); - it('should require accountId', () => { + it('should require accountId', function () { sandbox.stub(utils, 'logError'); rubiconAnalyticsAdapter.enableAnalytics({ @@ -455,7 +454,7 @@ describe('rubicon analytics adapter', () => { expect(utils.logError.called).to.equal(true); }); - it('should require endpoint', () => { + it('should require endpoint', function () { sandbox.stub(utils, 'logError'); rubiconAnalyticsAdapter.enableAnalytics({ @@ -467,18 +466,18 @@ describe('rubicon analytics adapter', () => { expect(utils.logError.called).to.equal(true); }); - describe('sampling', () => { - beforeEach(() => { + describe('sampling', function () { + beforeEach(function () { sandbox.stub(Math, 'random').returns(0.08); sandbox.stub(utils, 'logError'); }); - afterEach(() => { + afterEach(function () { rubiconAnalyticsAdapter.disableAnalytics(); }); - describe('with options.samplingFactor', () => { - it('should sample', () => { + describe('with options.samplingFactor', function () { + it('should sample', function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', @@ -492,7 +491,7 @@ describe('rubicon analytics adapter', () => { expect(requests.length).to.equal(1); }); - it('should unsample', () => { + it('should unsample', function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', @@ -506,7 +505,7 @@ describe('rubicon analytics adapter', () => { expect(requests.length).to.equal(0); }); - it('should throw errors for invalid samplingFactor', () => { + it('should throw errors for invalid samplingFactor', function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', @@ -521,8 +520,8 @@ describe('rubicon analytics adapter', () => { expect(utils.logError.called).to.equal(true); }); }); - describe('with options.sampling', () => { - it('should sample', () => { + describe('with options.sampling', function () { + it('should sample', function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', @@ -536,7 +535,7 @@ describe('rubicon analytics adapter', () => { expect(requests.length).to.equal(1); }); - it('should unsample', () => { + it('should unsample', function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', @@ -550,7 +549,7 @@ describe('rubicon analytics adapter', () => { expect(requests.length).to.equal(0); }); - it('should throw errors for invalid samplingFactor', () => { + it('should throw errors for invalid samplingFactor', function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', @@ -567,8 +566,8 @@ describe('rubicon analytics adapter', () => { }); }); - describe('when handling events', () => { - beforeEach(() => { + describe('when handling events', function () { + beforeEach(function () { rubiconAnalyticsAdapter.enableAnalytics({ options: { endpoint: '//localhost:9999/event', @@ -577,11 +576,11 @@ describe('rubicon analytics adapter', () => { }); }); - afterEach(() => { + afterEach(function () { rubiconAnalyticsAdapter.disableAnalytics(); }); - it('should build a batched message from prebid events', () => { + it('should build a batched message from prebid events', function () { performStandardAuction(); expect(requests.length).to.equal(1); @@ -595,7 +594,7 @@ describe('rubicon analytics adapter', () => { expect(message).to.deep.equal(ANALYTICS_MESSAGE); }); - it('should send batched message without BID_WON if necessary and further BID_WON events individually', () => { + 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]); @@ -624,7 +623,7 @@ describe('rubicon analytics adapter', () => { expect(message.bidsWon[0]).to.deep.equal(ANALYTICS_MESSAGE.bidsWon[1]); }); - it('should properly mark bids as timed out', () => { + 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); diff --git a/test/spec/modules/rubiconBidAdapter_spec.js b/test/spec/modules/rubiconBidAdapter_spec.js index e6418d715e1..76859729455 100644 --- a/test/spec/modules/rubiconBidAdapter_spec.js +++ b/test/spec/modules/rubiconBidAdapter_spec.js @@ -1,6 +1,6 @@ import {expect} from 'chai'; import adapterManager from 'src/adaptermanager'; -import {spec, masSizeOrdering, resetUserSync} from 'modules/rubiconBidAdapter'; +import {spec, masSizeOrdering, resetUserSync, hasVideoMediaType, FASTLANE_ENDPOINT} from 'modules/rubiconBidAdapter'; import {parse as parseQuery} from 'querystring'; import {newBidder} from 'src/adapters/bidderFactory'; import {userSync} from 'src/userSync'; @@ -12,7 +12,7 @@ var CONSTANTS = require('src/constants.json'); const INTEGRATION = `pbjs_lite_v$prebid.version$`; // $prebid.version$ will be substituted in by gulp in built prebid -describe('the rubicon adapter', () => { +describe('the rubicon adapter', function () { let sandbox, bidderRequest, sizeMap; @@ -215,7 +215,7 @@ describe('the rubicon adapter', () => { 'p_aso.video.ext.skipdelay': 15, 'playerHeight': 320, 'playerWidth': 640, - 'size_id': 201, + 'size_id': 203, 'aeParams': { 'p_aso.video.ext.skip': '1', 'p_aso.video.ext.skipdelay': '15' @@ -257,7 +257,7 @@ describe('the rubicon adapter', () => { }; } - beforeEach(() => { + beforeEach(function () { sandbox = sinon.sandbox.create(); bidderRequest = { @@ -275,11 +275,12 @@ describe('the rubicon adapter', () => { keywords: ['a', 'b', 'c'], inventory: { rating: '5-star', - prodtype: 'tech' + prodtype: ['tech', 'mobile'] }, visitor: { ucat: 'new', - lastsearch: 'iphone' + lastsearch: 'iphone', + likes: ['sports', 'video games'] }, position: 'atf', referrer: 'localhost', @@ -326,17 +327,17 @@ describe('the rubicon adapter', () => { }); }); - afterEach(() => { + afterEach(function () { sandbox.restore(); }); - describe('MAS mapping / ordering', () => { - it('should sort values without any MAS priority sizes in regular ascending order', () => { + describe('MAS mapping / ordering', function () { + it('should sort values without any MAS priority sizes in regular ascending order', function () { let ordering = masSizeOrdering([126, 43, 65, 16]); expect(ordering).to.deep.equal([16, 43, 65, 126]); }); - it('should sort MAS priority sizes in the proper order w/ rest ascending', () => { + it('should sort MAS priority sizes in the proper order w/ rest ascending', function () { let ordering = masSizeOrdering([43, 9, 65, 15, 16, 126]); expect(ordering).to.deep.equal([15, 9, 16, 43, 65, 126]); @@ -348,10 +349,10 @@ describe('the rubicon adapter', () => { }); }); - describe('buildRequests implementation', () => { - describe('for requests', () => { - describe('to fastlane', () => { - it('should make a well-formed request objects', () => { + describe('buildRequests implementation', function () { + describe('for requests', function () { + describe('to fastlane', function () { + it('should make a well-formed request objects', function () { sandbox.stub(Math, 'random').callsFake(() => 0.1); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -375,8 +376,9 @@ describe('the rubicon adapter', () => { 'kw': 'a,b,c', 'tg_v.ucat': 'new', 'tg_v.lastsearch': 'iphone', + 'tg_v.likes': 'sports,video games', 'tg_i.rating': '5-star', - 'tg_i.prodtype': 'tech', + 'tg_i.prodtype': 'tech,mobile', 'tg_fl.eid': 'div-1', 'rf': 'localhost' }; @@ -392,7 +394,18 @@ describe('the rubicon adapter', () => { }); }); - it('should make a well-formed request object without latLong', () => { + it('ad engine query params should be ordered correctly', function () { + sandbox.stub(Math, 'random').callsFake(() => 0.1); + let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); + + const referenceOrdering = ['account_id', 'site_id', 'zone_id', 'size_id', 'alt_size_ids', 'p_pos', 'rf', 'p_geo.latitude', 'p_geo.longitude', 'kw', 'tg_v.ucat', 'tg_v.lastsearch', 'tg_v.likes', 'tg_i.rating', 'tg_i.prodtype', 'tk_flint', 'x_source.tid', 'p_screen_res', 'rp_floor', 'rp_secure', 'tk_user_key', 'tg_fl.eid', 'slots', 'rand']; + + request.data.split('&').forEach((item, i) => { + expect(item.split('=')[0]).to.equal(referenceOrdering[i]); + }); + }); + + it('should make a well-formed request object without latLong', function () { let expectedQuery = { 'account_id': '14062', 'site_id': '70608', @@ -410,8 +423,9 @@ describe('the rubicon adapter', () => { 'kw': 'a,b,c', 'tg_v.ucat': 'new', 'tg_v.lastsearch': 'iphone', + 'tg_v.likes': 'sports,video games', 'tg_i.rating': '5-star', - 'tg_i.prodtype': 'tech', + 'tg_i.prodtype': 'tech,mobile', 'rf': 'localhost', 'p_geo.latitude': undefined, 'p_geo.longitude': undefined @@ -452,7 +466,7 @@ describe('the rubicon adapter', () => { }); }); - it('page_url should use params.referrer, config.getConfig("pageUrl"), utils.getTopWindowUrl() in that order', () => { + it('page_url should use params.referrer, config.getConfig("pageUrl"), utils.getTopWindowUrl() in that order', function () { sandbox.stub(utils, 'getTopWindowUrl').callsFake(() => 'http://www.prebid.org'); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); @@ -477,7 +491,7 @@ describe('the rubicon adapter', () => { expect(parseQuery(request.data).rf).to.equal('https://www.rubiconproject.com'); }); - it('should use rubicon sizes if present (including non-mappable sizes)', () => { + it('should use rubicon sizes if present (including non-mappable sizes)', function () { var sizesBidderRequest = clone(bidderRequest); sizesBidderRequest.bids[0].params.sizes = [55, 57, 59, 801]; @@ -488,7 +502,7 @@ describe('the rubicon adapter', () => { expect(data['alt_size_ids']).to.equal('57,59,801'); }); - it('should not validate bid request if no valid sizes', () => { + it('should not validate bid request if no valid sizes', function () { var sizesBidderRequest = clone(bidderRequest); sizesBidderRequest.bids[0].sizes = [[621, 250], [300, 251]]; @@ -497,7 +511,7 @@ describe('the rubicon adapter', () => { expect(result).to.equal(false); }); - it('should not validate bid request if no account id is present', () => { + it('should not validate bid request if no account id is present', function () { var noAccountBidderRequest = clone(bidderRequest); delete noAccountBidderRequest.bids[0].params.accountId; @@ -506,7 +520,7 @@ describe('the rubicon adapter', () => { expect(result).to.equal(false); }); - it('should allow a floor override', () => { + it('should allow a floor override', function () { var floorBidderRequest = clone(bidderRequest); floorBidderRequest.bids[0].params.floor = 2; @@ -516,7 +530,7 @@ describe('the rubicon adapter', () => { expect(data['rp_floor']).to.equal('2'); }); - it('should send digitrust params', () => { + it('should send digitrust params', function () { window.DigiTrust = { getUser: function () { } @@ -550,7 +564,7 @@ describe('the rubicon adapter', () => { delete window.DigiTrust; }); - it('should not send digitrust params when DigiTrust not loaded', () => { + it('should not send digitrust params when DigiTrust not loaded', function () { let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -562,7 +576,7 @@ describe('the rubicon adapter', () => { }); }); - it('should not send digitrust params due to optout', () => { + it('should not send digitrust params due to optout', function () { window.DigiTrust = { getUser: function () { } @@ -591,7 +605,7 @@ describe('the rubicon adapter', () => { delete window.DigiTrust; }); - it('should not send digitrust params due to failure', () => { + it('should not send digitrust params due to failure', function () { window.DigiTrust = { getUser: function () { } @@ -620,19 +634,19 @@ describe('the rubicon adapter', () => { delete window.DigiTrust; }); - describe('digiTrustId config', () => { + describe('digiTrustId config', function () { var origGetConfig; - beforeEach(() => { + beforeEach(function () { window.DigiTrust = { getUser: sandbox.spy() }; }); - afterEach(() => { + afterEach(function () { delete window.DigiTrust; }); - it('should send digiTrustId config params', () => { + it('should send digiTrustId config params', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { var config = { digiTrustId: { @@ -665,7 +679,7 @@ describe('the rubicon adapter', () => { expect(window.DigiTrust.getUser.notCalled).to.equal(true); }); - it('should not send digiTrustId config params due to optout', () => { + it('should not send digiTrustId config params due to optout', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { var config = { digiTrustId: { @@ -694,7 +708,7 @@ describe('the rubicon adapter', () => { expect(window.DigiTrust.getUser.notCalled).to.equal(true); }); - it('should not send digiTrustId config params due to failure', () => { + it('should not send digiTrustId config params due to failure', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { var config = { digiTrustId: { @@ -723,7 +737,7 @@ describe('the rubicon adapter', () => { expect(window.DigiTrust.getUser.notCalled).to.equal(true); }); - it('should not send digiTrustId config params if they do not exist', () => { + it('should not send digiTrustId config params if they do not exist', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { var config = {}; return config[key]; @@ -744,8 +758,8 @@ describe('the rubicon adapter', () => { }); }); - describe('GDPR consent config', () => { - it('should send "gdpr" and "gdpr_consent", when gdprConsent defines consentString and gdprApplies', () => { + describe('GDPR consent config', function () { + it('should send "gdpr" and "gdpr_consent", when gdprConsent defines consentString and gdprApplies', function () { createGdprBidderRequest(true); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -754,7 +768,7 @@ describe('the rubicon adapter', () => { expect(data['gdpr_consent']).to.equal('BOJ/P2HOJ/P2HABABMAAAAAZ+A=='); }); - it('should send only "gdpr_consent", when gdprConsent defines only consentString', () => { + it('should send only "gdpr_consent", when gdprConsent defines only consentString', function () { createGdprBidderRequest(); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -763,7 +777,7 @@ describe('the rubicon adapter', () => { expect(data['gdpr']).to.equal(undefined); }); - it('should not send GDPR params if gdprConsent is not defined', () => { + it('should not send GDPR params if gdprConsent is not defined', function () { let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -771,7 +785,7 @@ describe('the rubicon adapter', () => { expect(data['gdpr_consent']).to.equal(undefined); }); - it('should set "gdpr" value as 1 or 0, using "gdprApplies" value of either true/false', () => { + it('should set "gdpr" value as 1 or 0, using "gdprApplies" value of either true/false', function () { createGdprBidderRequest(true); let [request] = spec.buildRequests(bidderRequest.bids, bidderRequest); let data = parseQuery(request.data); @@ -784,8 +798,8 @@ describe('the rubicon adapter', () => { }); }); - describe('singleRequest config', () => { - it('should group all bid requests with the same site id', () => { + describe('singleRequest config', function () { + it('should group all bid requests with the same site id', function () { sandbox.stub(Math, 'random').callsFake(() => 0.1); sandbox.stub(config, 'getConfig').callsFake((key) => { @@ -812,8 +826,9 @@ describe('the rubicon adapter', () => { 'kw': 'a,b,c', 'tg_v.ucat': 'new', 'tg_v.lastsearch': 'iphone', + 'tg_v.likes': 'sports,video games', 'tg_i.rating': '5-star', - 'tg_i.prodtype': 'tech', + 'tg_i.prodtype': 'tech,mobile', 'tg_fl.eid': 'div-1', 'rf': 'localhost' }; @@ -899,7 +914,7 @@ describe('the rubicon adapter', () => { }); }); - it('should not send more than 10 bids in a request', () => { + it('should not send more than 10 bids in a request', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { const config = { 'rubicon.singleRequest': true @@ -930,7 +945,7 @@ describe('the rubicon adapter', () => { expect(data.zone_id.split(';')).to.have.lengthOf(10); }); - it('should not group bid requests if singleRequest does not equal true', () => { + it('should not group bid requests if singleRequest does not equal true', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { const config = { 'rubicon.singleRequest': false @@ -953,7 +968,7 @@ describe('the rubicon adapter', () => { expect(serverRequests).that.is.an('array').of.length(4); }); - it('should not group video bid requests', () => { + it('should not group video bid requests', function () { sandbox.stub(config, 'getConfig').callsFake((key) => { const config = { 'rubicon.singleRequest': true @@ -994,8 +1009,8 @@ describe('the rubicon adapter', () => { }); }); - describe('for video requests', () => { - it('should make a well-formed video request with legacy mediaType config', () => { + describe('for video requests', function () { + it('should make a well-formed video request with legacy mediaType config', function () { createLegacyVideoBidderRequest(); sandbox.stub(Date, 'now').callsFake(() => @@ -1046,7 +1061,7 @@ describe('the rubicon adapter', () => { expect(slot).to.have.property('inventory').that.is.an('object'); expect(slot.inventory).to.have.property('rating').that.equals('5-star'); - expect(slot.inventory).to.have.property('prodtype').that.equals('tech'); + expect(slot.inventory).to.have.property('prodtype').that.deep.equals(['tech', 'mobile']); expect(slot).to.have.property('keywords') .that.is.an('array') @@ -1056,9 +1071,10 @@ describe('the rubicon adapter', () => { expect(slot).to.have.property('visitor').that.is.an('object'); expect(slot.visitor).to.have.property('ucat').that.equals('new'); expect(slot.visitor).to.have.property('lastsearch').that.equals('iphone'); + expect(slot.visitor).to.have.property('likes').that.deep.equals(['sports', 'video games']); }); - it('should make a well-formed video request', () => { + it('should make a well-formed video request', function () { createVideoBidderRequest(); sandbox.stub(Date, 'now').callsFake(() => @@ -1109,7 +1125,7 @@ describe('the rubicon adapter', () => { expect(slot).to.have.property('inventory').that.is.an('object'); expect(slot.inventory).to.have.property('rating').that.equals('5-star'); - expect(slot.inventory).to.have.property('prodtype').that.equals('tech'); + expect(slot.inventory).to.have.property('prodtype').that.deep.equals(['tech', 'mobile']); expect(slot).to.have.property('keywords') .that.is.an('array') @@ -1119,9 +1135,10 @@ describe('the rubicon adapter', () => { expect(slot).to.have.property('visitor').that.is.an('object'); expect(slot.visitor).to.have.property('ucat').that.equals('new'); expect(slot.visitor).to.have.property('lastsearch').that.equals('iphone'); + expect(slot.visitor).to.have.property('likes').that.deep.equals(['sports', 'video games']); }); - it('should send request with proper ad position', () => { + it('should send request with proper ad position', function () { createVideoBidderRequest(); var positionBidderRequest = clone(bidderRequest); positionBidderRequest.bids[0].params.position = 'atf'; @@ -1165,7 +1182,7 @@ describe('the rubicon adapter', () => { expect(slot.position).to.equal('unknown'); }); - it('should allow a floor price override', () => { + it('should allow a floor price override', function () { createVideoBidderRequest(); sandbox.stub(Date, 'now').callsFake(() => @@ -1185,7 +1202,7 @@ describe('the rubicon adapter', () => { expect(floor).to.equal(3.25); }); - it('should validate bid request with invalid video if a mediaTypes banner property is defined', () => { + it('should validate bid request with invalid video if a mediaTypes banner property is defined', function () { const bidRequest = { mediaTypes: { video: { @@ -1197,7 +1214,9 @@ describe('the rubicon adapter', () => { }, params: { accountId: 1001, - video: {} + video: { + size_id: 201 + } }, sizes: [[300, 250]] } @@ -1207,7 +1226,7 @@ describe('the rubicon adapter', () => { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); - it('should not validate bid request when a invalid video object and no banner object is passed in', () => { + it('should not validate bid request when a invalid video object and no banner object is passed in', function () { createVideoBidderRequestNoVideo(); sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 @@ -1232,7 +1251,7 @@ describe('the rubicon adapter', () => { expect(spec.isBidRequestValid(bidRequestCopy)).to.equal(false); }); - it('should not validate bid request when an invalid video object is passed in with legacy config mediaType', () => { + it('should not validate bid request when an invalid video object is passed in with legacy config mediaType', function () { createLegacyVideoBidderRequestNoVideo(); sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 @@ -1254,13 +1273,36 @@ describe('the rubicon adapter', () => { expect(spec.isBidRequestValid(bidderRequestCopy.bids[0])).to.equal(false); }); - it('should not validate bid request when video is outstream', () => { + it('bid request is valid when video context is outstream', function () { createVideoBidderRequestOutstream(); sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 ); - expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(false); + const bidRequestCopy = clone(bidderRequest); + + let [request] = spec.buildRequests(bidRequestCopy.bids, bidRequestCopy); + expect(spec.isBidRequestValid(bidderRequest.bids[0])).to.equal(true); + expect(request.data.slots[0].size_id).to.equal(203); + }); + + it('should send request as banner when invalid video bid in multiple mediaType bidRequest', function () { + createVideoBidderRequestNoVideo(); + + let bid = bidderRequest.bids[0]; + bid.mediaTypes.banner = { + sizes: [[300, 250]] + }; + + sandbox.stub(Date, 'now').callsFake(() => + bidderRequest.auctionStart + 100 + ); + + const bidRequestCopy = clone(bidderRequest); + + let requests = spec.buildRequests(bidRequestCopy.bids, bidRequestCopy); + expect(requests.length).to.equal(1); + expect(requests[0].url).to.equal(FASTLANE_ENDPOINT); }); it('should get size from bid.sizes too', () => { @@ -1277,7 +1319,7 @@ describe('the rubicon adapter', () => { expect(request.data.slots[0].height).to.equal(250); }); - it('should get size from bid.sizes too with legacy config mediaType', () => { + it('should get size from bid.sizes too with legacy config mediaType', function () { createLegacyVideoBidderRequestNoPlayer(); sandbox.stub(Date, 'now').callsFake(() => bidderRequest.auctionStart + 100 @@ -1292,8 +1334,8 @@ describe('the rubicon adapter', () => { }); }); - describe('combineSlotUrlParams', () => { - it('should combine an array of slot url params', () => { + describe('combineSlotUrlParams', function () { + it('should combine an array of slot url params', function () { expect(spec.combineSlotUrlParams([])).to.deep.equal({}); expect(spec.combineSlotUrlParams([{p1: 'foo', p2: 'test', p3: ''}])).to.deep.equal({p1: 'foo', p2: 'test', p3: ''}); @@ -1318,8 +1360,8 @@ describe('the rubicon adapter', () => { }); }); - describe('createSlotParams', () => { - it('should return a valid slot params object', () => { + describe('createSlotParams', function () { + it('should return a valid slot params object', function () { let expectedQuery = { 'account_id': '14062', 'site_id': '70608', @@ -1336,8 +1378,9 @@ describe('the rubicon adapter', () => { 'kw': 'a,b,c', 'tg_v.ucat': 'new', 'tg_v.lastsearch': 'iphone', + 'tg_v.likes': 'sports,video games', 'tg_i.rating': '5-star', - 'tg_i.prodtype': 'tech', + 'tg_i.prodtype': 'tech,mobile', 'tg_fl.eid': 'div-1', 'rf': 'localhost' }; @@ -1356,15 +1399,15 @@ describe('the rubicon adapter', () => { }); }); - describe('hasVideoMediaType', () => { - it('should return true if mediaType is video and size_id is set', () => { + describe('hasVideoMediaType', function () { + it('should return true if mediaType is video and size_id is set', function () { createVideoBidderRequest(); - const legacyVideoTypeBidRequest = spec.hasVideoMediaType(bidderRequest.bids[0]); + const legacyVideoTypeBidRequest = hasVideoMediaType(bidderRequest.bids[0]); expect(legacyVideoTypeBidRequest).is.equal(true); }); - it('should return false if mediaType is video and size_id is not defined', () => { - expect(spec.hasVideoMediaType({ + it('should return false if mediaType is video and size_id is not defined', function () { + expect(spec.isBidRequestValid({ bid: 99, mediaType: 'video', params: { @@ -1373,18 +1416,18 @@ describe('the rubicon adapter', () => { })).is.equal(false); }); - it('should return false if bidRequest.mediaType is not equal to video', () => { - expect(spec.hasVideoMediaType({ + it('should return false if bidRequest.mediaType is not equal to video', function () { + expect(hasVideoMediaType({ mediaType: 'banner' })).is.equal(false); }); - it('should return false if bidRequest.mediaType is not defined', () => { - expect(spec.hasVideoMediaType({})).is.equal(false); + it('should return false if bidRequest.mediaType is not defined', function () { + expect(hasVideoMediaType({})).is.equal(false); }); - it('should return true if bidRequest.mediaTypes.video.context is instream and size_id is defined', () => { - expect(spec.hasVideoMediaType({ + it('should return true if bidRequest.mediaTypes.video.context is instream and size_id is defined', function () { + expect(hasVideoMediaType({ mediaTypes: { video: { context: 'instream' @@ -1398,8 +1441,8 @@ describe('the rubicon adapter', () => { })).is.equal(true); }); - it('should return false if bidRequest.mediaTypes.video.context is instream but size_id is not defined', () => { - expect(spec.hasVideoMediaType({ + it('should return false if bidRequest.mediaTypes.video.context is instream but size_id is not defined', function () { + expect(spec.isBidRequestValid({ mediaTypes: { video: { context: 'instream' @@ -1413,9 +1456,9 @@ describe('the rubicon adapter', () => { }); }); - describe('interpretResponse', () => { - describe('for fastlane', () => { - it('should handle a success response and sort by cpm', () => { + describe('interpretResponse', function () { + describe('for fastlane', function () { + it('should handle a success response and sort by cpm', function () { let response = { 'status': 'ok', 'account_id': 14062, @@ -1510,7 +1553,130 @@ describe('the rubicon adapter', () => { expect(bids[1].rubiconTargeting.rpfl_14062).to.equal('15_tier_all_test'); }); - it('should be fine with a CPM of 0', () => { + it('should use "network-advertiser" if no creative_id', function () { + let response = { + 'status': 'ok', + 'account_id': 14062, + 'site_id': 70608, + 'zone_id': 530022, + 'size_id': 15, + 'alt_size_ids': [ + 43, 10, 2 + ], + 'tracking': '', + 'inventory': {} + }; + + response.ads = [ + { + 'status': 'ok', + 'impression_id': '153dc240-8229-4604-b8f5-256933b9374c', + 'size_id': '15', + 'ad_id': '6', + 'advertiser': 7, + 'network': 8, + 'type': 'script', + 'script': 'alert(\'foo\')', + 'campaign_id': 10, + 'cpm': 0.811, + 'targeting': [ + { + 'key': 'rpfl_14062', + 'values': [ + '15_tier_all_test' + ] + } + ] + } + ]; + + let bids = spec.interpretResponse({body: response}, { + bidRequest: bidderRequest.bids[0] + }); + expect(bids[0].creativeId).to.equal('8-7'); + + response.ads = [ + { + 'status': 'ok', + 'impression_id': '153dc240-8229-4604-b8f5-256933b9374d', + 'size_id': '43', + 'ad_id': '7', + 'type': 'script', + 'script': 'alert(\'foo\')', + 'campaign_id': 10, + 'cpm': 0.911, + 'targeting': [ + { + 'key': 'rpfl_14062', + 'values': [ + '43_tier_all_test' + ] + } + ] + } + ]; + + bids = spec.interpretResponse({body: response}, { + bidRequest: bidderRequest.bids[0] + }); + expect(bids[0].creativeId).to.equal('-'); + + response.ads = [ + { + 'status': 'ok', + 'impression_id': '153dc240-8229-4604-b8f5-256933b9374d', + 'size_id': '10', + 'ad_id': '7', + 'network': 8, + 'type': 'script', + 'script': 'alert(\'foo\')', + 'campaign_id': 10, + 'cpm': 0.911, + 'targeting': [ + { + 'key': 'rpfl_14062', + 'values': [ + '10_tier_all_test' + ] + } + ] + } + ]; + + bids = spec.interpretResponse({body: response}, { + bidRequest: bidderRequest.bids[0] + }); + expect(bids[0].creativeId).to.equal('8-'); + + response.ads = [ + { + 'status': 'ok', + 'impression_id': '153dc240-8229-4604-b8f5-256933b9374d', + 'size_id': '2', + 'ad_id': '7', + 'advertiser': 7, + 'type': 'script', + 'script': 'alert(\'foo\')', + 'campaign_id': 10, + 'cpm': 0.911, + 'targeting': [ + { + 'key': 'rpfl_14062', + 'values': [ + '2_tier_all_test' + ] + } + ] + } + ]; + + bids = spec.interpretResponse({body: response}, { + bidRequest: bidderRequest.bids[0] + }); + expect(bids[0].creativeId).to.equal('-7'); + }); + + it('should be fine with a CPM of 0', function () { let response = { 'status': 'ok', 'account_id': 14062, @@ -1537,7 +1703,7 @@ describe('the rubicon adapter', () => { expect(bids[0].cpm).to.be.equal(0); }); - it('should handle an error with no ads returned', () => { + it('should handle an error with no ads returned', function () { let response = { 'status': 'ok', 'account_id': 14062, @@ -1559,7 +1725,7 @@ describe('the rubicon adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should handle an error', () => { + it('should handle an error', function () { let response = { 'status': 'ok', 'account_id': 14062, @@ -1583,7 +1749,7 @@ describe('the rubicon adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should handle an error because of malformed json response', () => { + it('should handle an error because of malformed json response', function () { let response = '{test{'; let bids = spec.interpretResponse({body: response}, { @@ -1593,7 +1759,7 @@ describe('the rubicon adapter', () => { expect(bids).to.be.lengthOf(0); }); - it('should handle a bidRequest argument of type Array', () => { + it('should handle a bidRequest argument of type Array', function () { let response = { 'status': 'ok', 'account_id': 14062, @@ -1620,8 +1786,8 @@ describe('the rubicon adapter', () => { expect(bids[0].cpm).to.be.equal(0); }); - describe('singleRequest enabled', () => { - it('handles bidRequest of type Array and returns associated adUnits', () => { + describe('singleRequest enabled', function () { + it('handles bidRequest of type Array and returns associated adUnits', function () { const overrideMap = []; overrideMap[0] = { impression_id: '1' }; @@ -1676,7 +1842,7 @@ describe('the rubicon adapter', () => { }); }); - it('handles incorrect adUnits length by returning all bids with matching ads', () => { + it('handles incorrect adUnits length by returning all bids with matching ads', function () { const overrideMap = []; overrideMap[0] = { impression_id: '1' }; @@ -1706,7 +1872,7 @@ describe('the rubicon adapter', () => { expect(bids).to.be.a('array').with.lengthOf(6); }); - it('skips adUnits with error status and returns all bids with ok status', () => { + it('skips adUnits with error status and returns all bids with ok status', function () { const stubAds = []; // Create overrides to break associations between bids and ads // Each override should cause one less bid to be returned by interpretResponse @@ -1771,12 +1937,12 @@ describe('the rubicon adapter', () => { }); }); - describe('for video', () => { - beforeEach(() => { + describe('for video', function () { + beforeEach(function () { createVideoBidderRequest(); }); - it('should register a successful bid', () => { + it('should register a successful bid', function () { let response = { 'status': 'ok', 'ads': { @@ -1825,14 +1991,14 @@ describe('the rubicon adapter', () => { }); }); - describe('user sync', () => { + describe('user sync', function () { const emilyUrl = 'https://eus.rubiconproject.com/usync.html'; - beforeEach(() => { + beforeEach(function () { resetUserSync(); }); - it('should register the Emily iframe', () => { + it('should register the Emily iframe', function () { let syncs = spec.getUserSyncs({ iframeEnabled: true }); @@ -1840,7 +2006,7 @@ describe('the rubicon adapter', () => { expect(syncs).to.deep.equal({type: 'iframe', url: emilyUrl}); }); - it('should not register the Emily iframe more than once', () => { + it('should not register the Emily iframe more than once', function () { let syncs = spec.getUserSyncs({ iframeEnabled: true }); @@ -1851,7 +2017,7 @@ describe('the rubicon adapter', () => { expect(syncs).to.equal(undefined); }); - it('should pass gdpr params if consent is true', () => { + it('should pass gdpr params if consent is true', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { gdprApplies: true, consentString: 'foo' })).to.deep.equal({ @@ -1859,7 +2025,7 @@ describe('the rubicon adapter', () => { }); }); - it('should pass gdpr params if consent is false', () => { + it('should pass gdpr params if consent is false', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { gdprApplies: false, consentString: 'foo' })).to.deep.equal({ @@ -1867,7 +2033,7 @@ describe('the rubicon adapter', () => { }); }); - it('should pass gdpr param gdpr_consent only when gdprApplies is undefined', () => { + it('should pass gdpr param gdpr_consent only when gdprApplies is undefined', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { consentString: 'foo' })).to.deep.equal({ @@ -1875,13 +2041,13 @@ describe('the rubicon adapter', () => { }); }); - it('should pass no params if gdpr consentString is not defined', () => { + it('should pass no params if gdpr consentString is not defined', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, {})).to.deep.equal({ type: 'iframe', url: `${emilyUrl}` }); }); - it('should pass no params if gdpr consentString is a number', () => { + it('should pass no params if gdpr consentString is a number', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { consentString: 0 })).to.deep.equal({ @@ -1889,7 +2055,7 @@ describe('the rubicon adapter', () => { }); }); - it('should pass no params if gdpr consentString is null', () => { + it('should pass no params if gdpr consentString is null', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { consentString: null })).to.deep.equal({ @@ -1897,7 +2063,7 @@ describe('the rubicon adapter', () => { }); }); - it('should pass no params if gdpr consentString is a object', () => { + it('should pass no params if gdpr consentString is a object', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, { consentString: {} })).to.deep.equal({ @@ -1905,7 +2071,7 @@ describe('the rubicon adapter', () => { }); }); - it('should pass no params if gdpr is not defined', () => { + it('should pass no params if gdpr is not defined', function () { expect(spec.getUserSyncs({ iframeEnabled: true }, {}, undefined)).to.deep.equal({ type: 'iframe', url: `${emilyUrl}` }); diff --git a/test/spec/modules/rxrtbBidAdapter_spec.js b/test/spec/modules/rxrtbBidAdapter_spec.js index 0785c6f144b..b56ef0544b2 100644 --- a/test/spec/modules/rxrtbBidAdapter_spec.js +++ b/test/spec/modules/rxrtbBidAdapter_spec.js @@ -1,9 +1,9 @@ import {expect} from 'chai'; import {spec} from 'modules/rxrtbBidAdapter'; -describe('rxrtb adapater', () => { - describe('Test validate req', () => { - it('should accept minimum valid bid', () => { +describe('rxrtb adapater', function () { + describe('Test validate req', function () { + it('should accept minimum valid bid', function () { let bid = { bidder: 'rxrtb', params: { @@ -17,7 +17,7 @@ describe('rxrtb adapater', () => { expect(isValid).to.equal(true); }); - it('should reject missing id', () => { + it('should reject missing id', function () { let bid = { bidder: 'rxrtb', params: { @@ -30,7 +30,7 @@ describe('rxrtb adapater', () => { expect(isValid).to.equal(false); }); - it('should reject id not Integer', () => { + it('should reject id not Integer', function () { let bid = { bidder: 'rxrtb', params: { @@ -44,7 +44,7 @@ describe('rxrtb adapater', () => { expect(isValid).to.equal(false); }); - it('should reject missing source', () => { + it('should reject missing source', function () { let bid = { bidder: 'rxrtb', params: { @@ -58,8 +58,8 @@ describe('rxrtb adapater', () => { }); }); - describe('Test build request', () => { - it('minimum request', () => { + describe('Test build request', function () { + it('minimum request', function () { let bid = { bidder: 'rxrtb', sizes: [[728, 90]], @@ -88,8 +88,8 @@ describe('rxrtb adapater', () => { }); }); - describe('Test interpret response', () => { - it('General banner response', () => { + describe('Test interpret response', function () { + it('General banner response', function () { let resp = spec.interpretResponse({ body: { id: 'abcd', diff --git a/test/spec/modules/s2sTesting_spec.js b/test/spec/modules/s2sTesting_spec.js index 33552011aa1..b2b35a585c7 100644 --- a/test/spec/modules/s2sTesting_spec.js +++ b/test/spec/modules/s2sTesting_spec.js @@ -12,15 +12,15 @@ describe('s2sTesting', function () { let mathRandomStub; let randomNumber = 0; - beforeEach(() => { + beforeEach(function () { mathRandomStub = sinon.stub(Math, 'random').callsFake(() => { return randomNumber; }); }); - afterEach(() => { + afterEach(function () { mathRandomStub.restore(); }); - describe('getSource', () => { + describe('getSource', function () { // helper function to set random number and get the source function getExpectedSource(randNumber, sourceWeights, sources) { // set random number for testing @@ -28,18 +28,18 @@ describe('s2sTesting', function () { return getSource(sourceWeights, sources); } - it('returns undefined if no sources', () => { + it('returns undefined if no sources', function () { expect(getExpectedSource(0, {})).to.be.undefined; expect(getExpectedSource(0.5, {})).to.be.undefined; expect(getExpectedSource(0.9999, {})).to.be.undefined; }); - it('returns undefined if no weights', () => { + it('returns undefined if no weights', function () { expect(getExpectedSource(0, {server: 0, client: 0})).to.be.undefined; expect(getExpectedSource(0.5, {client: 0})).to.be.undefined; }); - it('gets the expected source from 3 sources', () => { + it('gets the expected source from 3 sources', function () { var sources = ['server', 'client', 'both']; expect(getExpectedSource(0, {server: 1, client: 1, both: 2}, sources)).to.equal('server'); expect(getExpectedSource(0.2499999, {server: 1, client: 1, both: 2}, sources)).to.equal('server'); @@ -49,7 +49,7 @@ describe('s2sTesting', function () { expect(getExpectedSource(0.99999, {server: 1, client: 1, both: 2}, sources)).to.equal('both'); }); - it('gets the expected source from 2 sources', () => { + it('gets the expected source from 2 sources', function () { expect(getExpectedSource(0, {server: 2, client: 3})).to.equal('server'); expect(getExpectedSource(0.39999, {server: 2, client: 3})).to.equal('server'); expect(getExpectedSource(0.4, {server: 2, client: 3})).to.equal('client'); @@ -61,19 +61,19 @@ describe('s2sTesting', function () { expect(getExpectedSource(0.9, {server: 2, client: 3}, sources)).to.equal('client'); }); - it('gets the expected source from 1 source', () => { + it('gets the expected source from 1 source', function () { expect(getExpectedSource(0, {client: 2})).to.equal('client'); expect(getExpectedSource(0.5, {client: 2})).to.equal('client'); expect(getExpectedSource(0.99999, {client: 2})).to.equal('client'); }); - it('ignores an invalid source', () => { + it('ignores an invalid source', function () { expect(getExpectedSource(0, {client: 2, cache: 2})).to.equal('client'); expect(getExpectedSource(0.3333, {server: 1, cache: 1, client: 2})).to.equal('server'); expect(getExpectedSource(0.34, {server: 1, cache: 1, client: 2})).to.equal('client'); }); - it('ignores order of sources', () => { + it('ignores order of sources', function () { var sources = ['server', 'client', 'both']; expect(getExpectedSource(0, {client: 1, server: 1, both: 2}, sources)).to.equal('server'); expect(getExpectedSource(0.2499999, {both: 2, client: 1, server: 1}, sources)).to.equal('server'); @@ -82,21 +82,21 @@ describe('s2sTesting', function () { expect(getExpectedSource(0.5, {both: 2, server: 1, client: 1}, sources)).to.equal('both'); }); - it('accepts an array of sources', () => { + it('accepts an array of sources', function () { expect(getExpectedSource(0.3333, {second: 2, first: 1}, ['first', 'second'])).to.equal('first'); expect(getExpectedSource(0.34, {second: 2, first: 1}, ['first', 'second'])).to.equal('second'); expect(getExpectedSource(0.9999, {second: 2, first: 1}, ['first', 'second'])).to.equal('second'); }); }); - describe('getSourceBidderMap', () => { - describe('setting source through s2sConfig', () => { - beforeEach(() => { + describe('getSourceBidderMap', function () { + describe('setting source through s2sConfig', function () { + beforeEach(function () { // set random number for testing randomNumber = 0.7; }); - it('does not work if testing is "false"', () => { + it('does not work if testing is "false"', function () { config.setConfig({s2sConfig: { bidders: ['rubicon'], testing: false, @@ -108,7 +108,7 @@ describe('s2sTesting', function () { }); }); - it('sets one client bidder', () => { + it('sets one client bidder', function () { config.setConfig({s2sConfig: { bidders: ['rubicon'], testing: true, @@ -120,7 +120,7 @@ describe('s2sTesting', function () { }); }); - it('sets one server bidder', () => { + it('sets one server bidder', function () { config.setConfig({s2sConfig: { bidders: ['rubicon'], testing: true, @@ -132,7 +132,7 @@ describe('s2sTesting', function () { }); }); - it('defaults to server', () => { + it('defaults to server', function () { config.setConfig({s2sConfig: { bidders: ['rubicon'], testing: true @@ -143,7 +143,7 @@ describe('s2sTesting', function () { }); }); - it('sets two bidders', () => { + it('sets two bidders', function () { config.setConfig({s2sConfig: { bidders: ['rubicon', 'appnexus'], testing: true, @@ -157,15 +157,15 @@ describe('s2sTesting', function () { }); }); - describe('setting source through adUnits', () => { - beforeEach(() => { + describe('setting source through adUnits', function () { + beforeEach(function () { // reset s2sconfig bid sources config.setConfig({s2sConfig: {testing: true}}); // set random number for testing randomNumber = 0.7; }); - it('sets one bidder source from one adUnit', () => { + it('sets one bidder source from one adUnit', function () { var adUnits = [ {bids: [ {bidder: 'rubicon', bidSource: {server: 4, client: 1}} @@ -193,7 +193,7 @@ describe('s2sTesting', function () { expect(adUnits[0].bids[0].finalSource).to.equal('client'); }); - it('defaults to client if no bidSource', () => { + it('defaults to client if no bidSource', function () { var adUnits = [ {bids: [ {bidder: 'rubicon', bidSource: {}} @@ -208,7 +208,7 @@ describe('s2sTesting', function () { expect(adUnits[0].bids[0].finalSource).to.equal('client'); }); - it('sets multiple bidders sources from one adUnit', () => { + it('sets multiple bidders sources from one adUnit', function () { var adUnits = [ {bids: [ {bidder: 'rubicon', bidSource: {server: 2, client: 1}}, @@ -225,7 +225,7 @@ describe('s2sTesting', function () { expect(adUnits[0].bids[1].finalSource).to.equal('server'); }); - it('sets multiple bidders sources from multiple adUnits', () => { + it('sets multiple bidders sources from multiple adUnits', function () { var adUnits = [ {bids: [ {bidder: 'rubicon', bidSource: {server: 2, client: 1}}, @@ -251,7 +251,7 @@ describe('s2sTesting', function () { expect(adUnits[1].bids[1].finalSource).to.equal('client'); }); - it('should reuse calculated sources', () => { + it('should reuse calculated sources', function () { var adUnits = [ {bids: [ {bidder: 'rubicon', calcSource: 'client', bidSource: {server: 4, client: 1}}, @@ -275,15 +275,15 @@ describe('s2sTesting', function () { }); }); - describe('setting source through s2sconfig and adUnits', () => { - beforeEach(() => { + describe('setting source through s2sconfig and adUnits', function () { + beforeEach(function () { // reset s2sconfig bid sources config.setConfig({s2sConfig: {testing: true}}); // set random number for testing randomNumber = 0.7; }); - it('should get sources from both', () => { + it('should get sources from both', function () { // set rubicon: server and appnexus: client var adUnits = [ {bids: [ diff --git a/test/spec/modules/saraBidAdapter_spec.js b/test/spec/modules/saraBidAdapter_spec.js index 1b5d75170ae..6614ec65265 100644 --- a/test/spec/modules/saraBidAdapter_spec.js +++ b/test/spec/modules/saraBidAdapter_spec.js @@ -5,13 +5,13 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('Sara Adapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'sara', 'params': { @@ -24,11 +24,11 @@ describe('Sara Adapter', function () { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -38,7 +38,7 @@ describe('Sara Adapter', function () { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { function parseRequest(url) { const res = {}; url.split('&').forEach((it) => { @@ -83,7 +83,7 @@ describe('Sara Adapter', function () { } ]; - it('should attach valid params to the tag', () => { + it('should attach valid params to the tag', function () { const request = spec.buildRequests([bidRequests[0]]); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); @@ -92,7 +92,7 @@ describe('Sara Adapter', function () { expect(payload).to.have.property('auids', '5'); }); - it('auids must not be duplicated', () => { + it('auids must not be duplicated', function () { const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); const payload = parseRequest(request.data); @@ -101,7 +101,7 @@ describe('Sara Adapter', function () { expect(payload).to.have.property('auids', '5,6'); }); - it('pt parameter must be "gross" if params.priceType === "gross"', () => { + it('pt parameter must be "gross" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); @@ -112,7 +112,7 @@ describe('Sara Adapter', function () { delete bidRequests[1].params.priceType; }); - it('pt parameter must be "net" or "gross"', () => { + it('pt parameter must be "net" or "gross"', function () { bidRequests[1].params.priceType = 'some'; const request = spec.buildRequests(bidRequests); expect(request.data).to.be.an('string'); @@ -124,7 +124,7 @@ describe('Sara Adapter', function () { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const responses = [ {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 4, 'h': 250, 'w': 300}], 'seat': '1'}, {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 5, 'h': 90, 'w': 728}], 'seat': '1'}, @@ -135,7 +135,7 @@ describe('Sara Adapter', function () { {'seat': '1'}, ]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const bidRequests = [ { 'bidder': 'sara', @@ -169,7 +169,7 @@ describe('Sara Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should get correct multi bid response', () => { + it('should get correct multi bid response', function () { const bidRequests = [ { 'bidder': 'sara', @@ -249,7 +249,7 @@ describe('Sara Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('handles wrong and nobid responses', () => { + it('handles wrong and nobid responses', function () { const bidRequests = [ { 'bidder': 'sara', diff --git a/test/spec/modules/sekindoUMBidAdapter_spec.js b/test/spec/modules/sekindoUMBidAdapter_spec.js index 8f275d7fc05..b699015bb3e 100644 --- a/test/spec/modules/sekindoUMBidAdapter_spec.js +++ b/test/spec/modules/sekindoUMBidAdapter_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import { spec } from 'modules/sekindoUMBidAdapter'; import { newBidder } from 'src/adapters/bidderFactory'; -describe('sekindoUMAdapter', () => { +describe('sekindoUMAdapter', function () { const adapter = newBidder(spec); const bannerParams = { @@ -29,34 +29,34 @@ describe('sekindoUMAdapter', () => { 'mediaType': 'banner' }; - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { bidRequests.mediaType = 'banner'; bidRequests.params = bannerParams; expect(spec.isBidRequestValid(bidRequests)).to.equal(true); }); - it('should return false when required video params are missing', () => { + it('should return false when required video params are missing', function () { bidRequests.mediaType = 'video'; bidRequests.params = bannerParams; expect(spec.isBidRequestValid(bidRequests)).to.equal(false); }); - it('should return true when required Video params found', () => { + it('should return true when required Video params found', function () { bidRequests.mediaType = 'video'; bidRequests.params = videoParams; expect(spec.isBidRequestValid(bidRequests)).to.equal(true); }); }); - describe('buildRequests', () => { - it('banner data should be a query string and method = GET', () => { + describe('buildRequests', function () { + it('banner data should be a query string and method = GET', function () { bidRequests.mediaType = 'banner'; bidRequests.params = bannerParams; const request = spec.buildRequests([bidRequests]); @@ -64,7 +64,7 @@ describe('sekindoUMAdapter', () => { expect(request[0].method).to.equal('GET'); }); - it('with gdprConsent, banner data should be a query string and method = GET', () => { + it('with gdprConsent, banner data should be a query string and method = GET', function () { bidRequests.mediaType = 'banner'; bidRequests.params = bannerParams; const request = spec.buildRequests([bidRequests], {'gdprConsent': {'consentString': 'BOJ/P2HOJ/P2HABABMAAAAAZ+A==', 'vendorData': {}, 'gdprApplies': true}}); @@ -72,7 +72,7 @@ describe('sekindoUMAdapter', () => { expect(request[0].method).to.equal('GET'); }); - it('video data should be a query string and method = GET', () => { + it('video data should be a query string and method = GET', function () { bidRequests.mediaType = 'video'; bidRequests.params = videoParams; const request = spec.buildRequests([bidRequests]); @@ -81,8 +81,8 @@ describe('sekindoUMAdapter', () => { }); }); - describe('interpretResponse', () => { - it('banner should get correct bid response', () => { + describe('interpretResponse', function () { + it('banner should get correct bid response', function () { let response = { 'headers': function(header) { return 'dummy header'; @@ -110,7 +110,7 @@ describe('sekindoUMAdapter', () => { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('vastXml video should get correct bid response', () => { + it('vastXml video should get correct bid response', function () { let response = { 'headers': function(header) { return 'dummy header'; @@ -138,7 +138,7 @@ describe('sekindoUMAdapter', () => { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('vastUrl video should get correct bid response', () => { + it('vastUrl video should get correct bid response', function () { let response = { 'headers': function(header) { return 'dummy header'; diff --git a/test/spec/modules/serverbidBidAdapter_spec.js b/test/spec/modules/serverbidBidAdapter_spec.js index d3dc64ae6df..aa40ee31ce5 100644 --- a/test/spec/modules/serverbidBidAdapter_spec.js +++ b/test/spec/modules/serverbidBidAdapter_spec.js @@ -100,11 +100,11 @@ const RESPONSE = { } }; -describe('Serverbid BidAdapter', () => { +describe('Serverbid BidAdapter', function () { let bidRequests; let adapter = spec; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { bidder: 'serverbid', @@ -122,8 +122,8 @@ describe('Serverbid BidAdapter', () => { ]; }); - describe('bid request validation', () => { - it('should accept valid bid requests', () => { + describe('bid request validation', function () { + it('should accept valid bid requests', function () { let bid = { bidder: 'serverbid', params: { @@ -134,7 +134,7 @@ describe('Serverbid BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should accept valid bid requests with extra fields', () => { + it('should accept valid bid requests with extra fields', function () { let bid = { bidder: 'serverbid', params: { @@ -146,7 +146,7 @@ describe('Serverbid BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should reject bid requests without siteId', () => { + it('should reject bid requests without siteId', function () { let bid = { bidder: 'serverbid', params: { @@ -156,7 +156,7 @@ describe('Serverbid BidAdapter', () => { expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should reject bid requests without networkId', () => { + it('should reject bid requests without networkId', function () { let bid = { bidder: 'serverbid', params: { @@ -167,45 +167,45 @@ describe('Serverbid BidAdapter', () => { }); }); - describe('buildRequests validation', () => { - it('creates request data', () => { + describe('buildRequests validation', function () { + it('creates request data', function () { let request = spec.buildRequests(bidRequests); expect(request).to.exist.and.to.be.a('object'); }); - it('request to serverbid should contain a url', () => { + it('request to serverbid should contain a url', function () { let request = spec.buildRequests(bidRequests); expect(request.url).to.have.string('serverbid.com'); }); - it('requires valid bids to make request', () => { + it('requires valid bids to make request', function () { let request = spec.buildRequests([]); expect(request.bidRequest).to.be.empty; }); - it('sends bid request to ENDPOINT via POST', () => { + it('sends bid request to ENDPOINT via POST', function () { let request = spec.buildRequests(bidRequests); expect(request.method).to.have.string('POST'); }); }); - describe('interpretResponse validation', () => { - it('response should have valid bidderCode', () => { + describe('interpretResponse validation', function () { + it('response should have valid bidderCode', function () { let bidRequest = spec.buildRequests(REQUEST.bidRequest); let bid = bidFactory.createBid(1, bidRequest.bidRequest[0]); expect(bid.bidderCode).to.equal('serverbid'); }); - it('response should include objects for all bids', () => { + it('response should include objects for all bids', function () { let bids = spec.interpretResponse(RESPONSE, REQUEST); expect(bids.length).to.equal(2); }); - it('registers bids', () => { + it('registers bids', function () { let bids = spec.interpretResponse(RESPONSE, REQUEST); bids.forEach(b => { expect(b).to.have.property('cpm'); @@ -223,29 +223,29 @@ describe('Serverbid BidAdapter', () => { }); }); - it('handles nobid responses', () => { + 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', () => { + it('handles no server response', function () { let bids = spec.interpretResponse(null, REQUEST); expect(bids).to.be.empty; }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { let syncOptions = {'iframeEnabled': true}; - it('handles empty sync options', () => { + it('handles empty sync options', function () { let opts = spec.getUserSyncs({}); expect(opts).to.be.empty; }); - it('should return a sync url if iframe syncs are enabled', () => { + it('should return a sync url if iframe syncs are enabled', function () { let opts = spec.getUserSyncs(syncOptions); expect(opts.length).to.equal(1); diff --git a/test/spec/modules/serverbidServerBidAdapter_spec.js b/test/spec/modules/serverbidServerBidAdapter_spec.js index 29d35b921d6..7c428647f62 100644 --- a/test/spec/modules/serverbidServerBidAdapter_spec.js +++ b/test/spec/modules/serverbidServerBidAdapter_spec.js @@ -184,51 +184,55 @@ const REQUEST_TWO_UNITS = { ] }; -describe('ServerBid S2S Adapter', () => { +describe('ServerBid S2S Adapter', function () { let adapter, addBidResponse = sinon.spy(), done = sinon.spy(); - beforeEach(() => adapter = new Adapter()); + beforeEach(function () { + adapter = new Adapter() + }); - afterEach(() => { + afterEach(function () { addBidResponse.resetHistory(); done.resetHistory(); }); - describe('request function', () => { + describe('request function', function () { let xhr; let requests; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = request => requests.push(request); }); - afterEach(() => xhr.restore()); + afterEach(function () { + xhr.restore(); + }); - it('exists and is a function', () => { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('response handler', () => { + describe('response handler', function () { let server; - beforeEach(() => { + beforeEach(function () { server = sinon.fakeServer.create(); sinon.stub(utils, 'getBidRequest').returns({ bidId: '123' }); }); - afterEach(() => { + afterEach(function () { server.restore(); utils.getBidRequest.restore(); }); - it('registers bids', () => { + it('registers bids', function () { server.respondWith(JSON.stringify(RESPONSE)); config.setConfig(CONFIG_ARG); @@ -242,7 +246,7 @@ describe('ServerBid S2S Adapter', () => { expect(response).to.have.property('adId', '123'); }); - it('registers no-bid response when ad unit not set', () => { + it('registers no-bid response when ad unit not set', function () { server.respondWith(JSON.stringify(RESPONSE_NO_BID_NO_UNIT)); config.setConfig(CONFIG_ARG); @@ -260,7 +264,7 @@ describe('ServerBid S2S Adapter', () => { expect(bid_request_passed).to.have.property('adId', '123'); }); - it('registers no-bid response when ad unit is set', () => { + it('registers no-bid response when ad unit is set', function () { server.respondWith(JSON.stringify(RESPONSE_NO_BID_NO_UNIT)); config.setConfig(CONFIG_ARG); @@ -275,7 +279,7 @@ describe('ServerBid S2S Adapter', () => { expect(response).to.have.property('statusMessage', 'Bid returned empty or error response'); }); - it('registers no-bid response when there are less bids than requests', () => { + it('registers no-bid response when there are less bids than requests', function () { server.respondWith(JSON.stringify(RESPONSE)); config.setConfig(CONFIG_ARG); diff --git a/test/spec/modules/sharethroughBidAdapter_spec.js b/test/spec/modules/sharethroughBidAdapter_spec.js index 2aef88fe7eb..6a4ab016fdc 100644 --- a/test/spec/modules/sharethroughBidAdapter_spec.js +++ b/test/spec/modules/sharethroughBidAdapter_spec.js @@ -19,17 +19,63 @@ const bidderRequest = [ sizes: [[700, 400]], placementCode: 'bar', params: { - pkey: 'bbbb2222' + pkey: 'bbbb2222', + iframe: true } - }]; -const prebidRequest = [{ - method: 'GET', - url: document.location.protocol + '//btlr.sharethrough.com' + '/header-bid/v1', - data: { - bidId: 'bidId', - placement_key: 'pKey' - } -}]; + }, + { + bidder: 'sharethrough', + bidId: 'bidId3', + sizes: [[700, 400]], + placementCode: 'coconut', + params: { + pkey: 'cccc3333', + iframe: true, + iframeSize: [500, 500] + }, + }, +]; + +const prebidRequests = [ + { + method: 'GET', + url: document.location.protocol + '//btlr.sharethrough.com' + '/header-bid/v1', + data: { + bidId: 'bidId', + placement_key: 'pKey' + }, + strData: { + stayInIframe: false, + sizes: [] + } + }, + { + method: 'GET', + url: document.location.protocol + '//btlr.sharethrough.com' + '/header-bid/v1', + data: { + bidId: 'bidId', + placement_key: 'pKey' + }, + strData: { + stayInIframe: true, + sizes: [[300, 250], [300, 300], [250, 250], [600, 50]] + } + }, + { + method: 'GET', + url: document.location.protocol + '//btlr.sharethrough.com' + '/header-bid/v1', + data: { + bidId: 'bidId', + placement_key: 'pKey' + }, + strData: { + stayInIframe: true, + iframeSize: [500, 500], + sizes: [[300, 250], [300, 300], [250, 250], [600, 50]] + } + }, +]; + const bidderResponse = { body: { 'adserverRequestId': '40b6afd5-6134-4fbb-850a-bb8972a46994', @@ -48,6 +94,7 @@ const bidderResponse = { }, header: { get: (header) => header } }; + // Mirrors the one in modules/sharethroughBidAdapter.js as the function is unexported const b64EncodeUnicode = (str) => { return btoa( @@ -56,15 +103,16 @@ const b64EncodeUnicode = (str) => { return String.fromCharCode('0x' + p1); })); } -describe('sharethrough adapter spec', () => { - describe('.code', () => { - it('should return a bidder code of sharethrough', () => { + +describe('sharethrough adapter spec', function () { + describe('.code', function () { + it('should return a bidder code of sharethrough', function () { expect(spec.code).to.eql('sharethrough'); }); }) - describe('.isBidRequestValid', () => { - it('should return false if req has no pkey', () => { + describe('.isBidRequestValid', function () { + it('should return false if req has no pkey', function () { const invalidBidRequest = { bidder: 'sharethrough', params: { @@ -74,7 +122,7 @@ describe('sharethrough adapter spec', () => { expect(spec.isBidRequestValid(invalidBidRequest)).to.eql(false); }); - it('should return false if req has wrong bidder code', () => { + it('should return false if req has wrong bidder code', function () { const invalidBidRequest = { bidder: 'notSharethrough', params: { @@ -84,14 +132,14 @@ describe('sharethrough adapter spec', () => { expect(spec.isBidRequestValid(invalidBidRequest)).to.eql(false); }); - it('should return true if req is correct', () => { + it('should return true if req is correct', function () { expect(spec.isBidRequestValid(bidderRequest[0])).to.eq(true); expect(spec.isBidRequestValid(bidderRequest[1])).to.eq(true); }) }); - describe('.buildRequests', () => { - it('should return an array of requests', () => { + describe('.buildRequests', function () { + it('should return an array of requests', function () { const bidRequests = spec.buildRequests(bidderRequest); expect(bidRequests[0].url).to.eq( @@ -101,7 +149,7 @@ describe('sharethrough adapter spec', () => { expect(bidRequests[0].method).to.eq('GET'); }); - it('should add consent parameters if gdprConsent is present', () => { + it('should add consent parameters if gdprConsent is present', function () { const gdprConsent = { consentString: 'consent_string123', gdprApplies: true }; const fakeBidRequest = { gdprConsent: gdprConsent }; const bidRequest = spec.buildRequests(bidderRequest, fakeBidRequest)[0]; @@ -109,7 +157,7 @@ describe('sharethrough adapter spec', () => { expect(bidRequest.data.consent_string).to.eq('consent_string123'); }); - it('should handle gdprConsent is present but values are undefined case', () => { + it('should handle gdprConsent is present but values are undefined case', function () { const gdprConsent = { consent_string: undefined, gdprApplies: undefined }; const fakeBidRequest = { gdprConsent: gdprConsent }; const bidRequest = spec.buildRequests(bidderRequest, fakeBidRequest)[0]; @@ -117,38 +165,66 @@ describe('sharethrough adapter spec', () => { }); }); - describe('.interpretResponse', () => { - it('returns a correctly parsed out response', () => { - expect(spec.interpretResponse(bidderResponse, prebidRequest[0])[0]).to.include( + describe('.interpretResponse', function () { + it('returns a correctly parsed out response', function () { + expect(spec.interpretResponse(bidderResponse, prebidRequests[0])[0]).to.include( { width: 0, height: 0, cpm: 12.34, creativeId: 'aCreativeId', - deal_id: 'aDealId', + dealId: 'aDealId', + currency: 'USD', + netRevenue: true, + ttl: 360, + }); + }); + + it('returns a correctly parsed out response with largest size when strData.stayInIframe is true', function () { + expect(spec.interpretResponse(bidderResponse, prebidRequests[1])[0]).to.include( + { + width: 300, + height: 300, + cpm: 12.34, + creativeId: 'aCreativeId', + dealId: 'aDealId', currency: 'USD', netRevenue: true, ttl: 360, }); }); - it('returns a blank array if there are no creatives', () => { + it('returns a correctly parsed out response with explicitly defined size when strData.stayInIframe is true and strData.iframeSize is provided', function () { + expect(spec.interpretResponse(bidderResponse, prebidRequests[2])[0]).to.include( + { + width: 500, + height: 500, + cpm: 12.34, + creativeId: 'aCreativeId', + dealId: 'aDealId', + currency: 'USD', + netRevenue: true, + ttl: 360, + }); + }); + + it('returns a blank array if there are no creatives', function () { const bidResponse = { body: { creatives: [] } }; - expect(spec.interpretResponse(bidResponse, prebidRequest[0])).to.be.an('array').that.is.empty; + expect(spec.interpretResponse(bidResponse, prebidRequests[0])).to.be.an('array').that.is.empty; }); - it('returns a blank array if body object is empty', () => { + it('returns a blank array if body object is empty', function () { const bidResponse = { body: {} }; - expect(spec.interpretResponse(bidResponse, prebidRequest[0])).to.be.an('array').that.is.empty; + expect(spec.interpretResponse(bidResponse, prebidRequests[0])).to.be.an('array').that.is.empty; }); - it('returns a blank array if body is null', () => { + it('returns a blank array if body is null', function () { const bidResponse = { body: null }; - expect(spec.interpretResponse(bidResponse, prebidRequest[0])).to.be.an('array').that.is.empty; + expect(spec.interpretResponse(bidResponse, prebidRequests[0])).to.be.an('array').that.is.empty; }); - it('correctly sends back a sfp script tag', () => { - const adMarkup = spec.interpretResponse(bidderResponse, prebidRequest[0])[0].ad; + it('correctly generates ad markup', function () { + const adMarkup = spec.interpretResponse(bidderResponse, prebidRequests[0])[0].ad; let resp = null; expect(() => btoa(JSON.stringify(bidderResponse))).to.throw(); @@ -163,13 +239,26 @@ describe('sharethrough adapter spec', () => { expect(adMarkup).to.match( /window.top.document.getElementsByTagName\('body'\)\[0\].appendChild\(sfp_js\);/) }); + + it('correctly generates ad markup for staying in iframe', function () { + const adMarkup = spec.interpretResponse(bidderResponse, prebidRequests[1])[0].ad; + let resp = null; + + expect(() => btoa(JSON.stringify(bidderResponse))).to.throw(); + expect(() => resp = b64EncodeUnicode(JSON.stringify(bidderResponse))).not.to.throw(); + expect(adMarkup).to.match( + /data-str-native-key="pKey" data-stx-response-name=\"str_response_bidId\"/); + expect(!!adMarkup.indexOf(resp)).to.eql(true); + expect(adMarkup).to.match( + /', + 'ad': ``, 'ttl': 500, 'creativeId': '1234abcd', 'netRevenue': true, @@ -279,7 +306,7 @@ describe('SonobiBidAdapter', () => { 'cpm': 1.25, 'width': 300, 'height': 250, - 'ad': 'https://mco-1-apex.go.sonobi.com/vast.xml?vid=30292e432662bd5f86d90774b944b038&ref=localhost:9876', + 'ad': 'https://mco-1-apex.go.sonobi.com/vast.xml?vid=30292e432662bd5f86d90774b944b038&ref=http%3A%2F%2Flocalhost%2F', 'ttl': 500, 'creativeId': '30292e432662bd5f86d90774b944b038', 'netRevenue': true, @@ -289,13 +316,24 @@ describe('SonobiBidAdapter', () => { } ]; - it('should map bidResponse to prebidResponse', () => { + it('should map bidResponse to prebidResponse', function () { const response = spec.interpretResponse(bidResponse, bidRequests); - expect(response).to.deep.equal(prebidResponse); - }) - }) + response.forEach((resp, i) => { + expect(resp.requestId).to.equal(prebidResponse[i].requestId); + expect(resp.cpm).to.equal(prebidResponse[i].cpm); + expect(resp.width).to.equal(prebidResponse[i].width); + expect(resp.height).to.equal(prebidResponse[i].height); + expect(resp.ttl).to.equal(prebidResponse[i].ttl); + expect(resp.creativeId).to.equal(prebidResponse[i].creativeId); + expect(resp.netRevenue).to.equal(prebidResponse[i].netRevenue); + expect(resp.currency).to.equal(prebidResponse[i].currency); + expect(resp.aid).to.equal(prebidResponse[i].aid); + expect(resp.ad.indexOf('localhost')).to.be.greaterThan(0); + }); + }); + }); - describe('.getUserSyncs', () => { + describe('.getUserSyncs', function () { let bidResponse = [{ 'body': { 'sbi_px': [{ @@ -307,34 +345,35 @@ describe('SonobiBidAdapter', () => { } }]; - it('should return one sync pixel', () => { + it('should return one sync pixel', function () { expect(spec.getUserSyncs({ pixelEnabled: true }, bidResponse)).to.deep.equal([{ type: 'image', url: 'https://pixel-test' }]); }) - it('should return an empty array when sync is enabled but there are no bidResponses', () => { + it('should return an empty array when sync is enabled but there are no bidResponses', function () { expect(spec.getUserSyncs({ pixelEnabled: true }, [])).to.have.length(0); }) - it('should return an empty array when sync is enabled but no sync pixel returned', () => { + it('should return an empty array when sync is enabled but no sync pixel returned', function () { const pixel = Object.assign({}, bidResponse); delete pixel[0].body.sbi_px; expect(spec.getUserSyncs({ pixelEnabled: true }, bidResponse)).to.have.length(0); }) - it('should return an empty array', () => { + it('should return an empty array', function () { expect(spec.getUserSyncs({ pixelEnabled: false }, bidResponse)).to.have.length(0); - }) + expect(spec.getUserSyncs({ pixelEnabled: true }, [])).to.have.length(0); + }); }) - describe('_getPlatform', () => { - it('should return mobile', () => { + describe('_getPlatform', function () { + it('should return mobile', function () { expect(_getPlatform({innerWidth: 767})).to.equal('mobile') }) - it('should return tablet', () => { + it('should return tablet', function () { expect(_getPlatform({innerWidth: 800})).to.equal('tablet') }) - it('should return desktop', () => { + it('should return desktop', function () { expect(_getPlatform({innerWidth: 1000})).to.equal('desktop') }) }) diff --git a/test/spec/modules/sortableBidAdapter_spec.js b/test/spec/modules/sortableBidAdapter_spec.js new file mode 100644 index 00000000000..09f5b4f7514 --- /dev/null +++ b/test/spec/modules/sortableBidAdapter_spec.js @@ -0,0 +1,259 @@ +import { expect } from 'chai'; +import { spec } from 'modules/sortableBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { REPO_AND_VERSION } from 'src/constants'; +import * as utils from 'src/utils'; + +const ENDPOINT = `//c.deployads.com/openrtb2/auction?src=${REPO_AND_VERSION}&host=${utils.getTopWindowLocation().host}`; + +describe('sortableBidAdapter', function() { + const adapter = newBidder(spec); + + describe('isBidRequestValid', function () { + function makeBid() { + return { + 'bidder': 'sortable', + 'params': { + 'tagId': '403370', + 'siteId': 'example.com', + 'keywords': { + 'key1': 'val1', + 'key2': 'val2' + }, + 'floorSizeMap': { + '728x90': 0.15, + '300x250': 1.20 + } + }, + 'adUnitCode': 'adunit-code', + 'sizes': [ + [300, 250] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + } + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(makeBid())).to.equal(true); + }); + + it('should return false when tagId not passed correctly', function () { + let bid = makeBid(); + delete bid.params.tagId; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when sizes not passed correctly', function () { + let bid = makeBid(); + delete bid.sizes; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when sizes are wrong length', function () { + let bid = makeBid(); + bid.sizes = [[300]]; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when require params are not passed', function () { + let bid = makeBid(); + bid.params = {}; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return false when the floorSizeMap is invalid', function () { + let bid = makeBid(); + bid.params.floorSizeMap = { + 'sixforty by foureighty': 1234 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + bid.params.floorSizeMap = { + '728x90': 'three' + } + expect(spec.isBidRequestValid(bid)).to.equal(false); + bid.params.floorSizeMap = 'a'; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return true when the floorSizeMap is missing or empty', function () { + let bid = makeBid(); + bid.params.floorSizeMap = {}; + expect(spec.isBidRequestValid(bid)).to.equal(true); + delete bid.params.floorSizeMap; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + it('should return false when the keywords are invalid', function () { + let bid = makeBid(); + bid.params.keywords = { + 'badval': 1234 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + bid.params.keywords = 'a'; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + + it('should return true when the keywords are missing or empty', function () { + let bid = makeBid(); + bid.params.keywords = {}; + expect(spec.isBidRequestValid(bid)).to.equal(true); + delete bid.params.keywords; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + }); + + describe('buildRequests', function () { + const bidRequests = [{ + 'bidder': 'sortable', + 'params': { + 'tagId': '403370', + 'siteId': 'example.com', + 'floor': 0.21, + 'keywords': { + 'key1': 'val1', + 'key2': 'val2' + }, + 'floorSizeMap': { + '728x90': 0.15, + '300x250': 1.20 + } + }, + 'sizes': [ + [300, 250] + ], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475' + }]; + + const request = spec.buildRequests(bidRequests); + const requestBody = JSON.parse(request.data); + + it('sends bid request to our endpoint via POST', function () { + expect(request.method).to.equal('POST'); + }); + + it('attaches source and version to endpoint URL as query params', function () { + expect(request.url).to.equal(ENDPOINT); + }); + + it('sends screen dimensions', function () { + expect(requestBody.site.device.w).to.equal(screen.width); + expect(requestBody.site.device.h).to.equal(screen.height); + }); + + it('includes the ad size in the bid request', function () { + expect(requestBody.imp[0].banner.format[0].w).to.equal(300); + expect(requestBody.imp[0].banner.format[0].h).to.equal(250); + }); + + it('includes the params in the bid request', function () { + expect(requestBody.imp[0].ext.keywords).to.deep.equal( + {'key1': 'val1', + 'key2': 'val2'} + ); + expect(requestBody.site.publisher.id).to.equal('example.com'); + expect(requestBody.imp[0].tagid).to.equal('403370'); + expect(requestBody.imp[0].bidfloor).to.equal(0.21); + }); + + it('should have the floor size map set', function () { + expect(requestBody.imp[0].ext.floorSizeMap).to.deep.equal({ + '728x90': 0.15, + '300x250': 1.20 + }); + }); + }); + + describe('interpretResponse', function () { + function makeResponse() { + return { + body: { + 'id': '5e5c23a5ba71e78', + 'seatbid': [ + { + 'bid': [ + { + 'id': '6vmb3isptf', + 'crid': 'sortablescreative', + 'impid': '322add653672f68', + 'price': 1.22, + 'adm': '', + 'attr': [5], + 'h': 90, + 'nurl': 'http://nurl', + 'w': 728 + } + ], + 'seat': 'MOCK' + } + ], + 'bidid': '5e5c23a5ba71e78' + } + }; + } + + const expectedBid = { + 'requestId': '322add653672f68', + 'cpm': 1.22, + 'width': 728, + 'height': 90, + 'creativeId': 'sortablescreative', + 'dealId': null, + 'currency': 'USD', + 'netRevenue': true, + 'mediaType': 'banner', + 'ttl': 60, + 'ad': '
' + }; + + it('should get the correct bid response', function () { + let result = spec.interpretResponse(makeResponse()); + expect(result.length).to.equal(1); + expect(result[0]).to.deep.equal(expectedBid); + }); + + it('should handle a missing crid', function () { + let noCridResponse = makeResponse(); + delete noCridResponse.body.seatbid[0].bid[0].crid; + const fallbackCrid = noCridResponse.body.seatbid[0].bid[0].id; + let noCridResult = Object.assign({}, expectedBid, {'creativeId': fallbackCrid}); + let result = spec.interpretResponse(noCridResponse); + expect(result.length).to.equal(1); + expect(result[0]).to.deep.equal(noCridResult); + }); + + it('should handle a missing nurl', function () { + let noNurlResponse = makeResponse(); + delete noNurlResponse.body.seatbid[0].bid[0].nurl; + let noNurlResult = Object.assign({}, expectedBid); + noNurlResult.ad = ''; + let result = spec.interpretResponse(noNurlResponse); + expect(result.length).to.equal(1); + expect(result[0]).to.deep.equal(noNurlResult); + }); + + it('should handle a missing adm', function () { + let noAdmResponse = makeResponse(); + delete noAdmResponse.body.seatbid[0].bid[0].adm; + let noAdmResult = Object.assign({}, expectedBid); + delete noAdmResult.ad; + noAdmResult.adUrl = 'http://nurl'; + let result = spec.interpretResponse(noAdmResponse); + expect(result.length).to.equal(1); + expect(result[0]).to.deep.equal(noAdmResult); + }); + + it('handles empty bid response', function () { + let response = { + body: { + 'id': '5e5c23a5ba71e78', + 'seatbid': [] + } + }; + let result = spec.interpretResponse(response); + expect(result.length).to.equal(0); + }); + }); +}); diff --git a/test/spec/modules/sovrnBidAdapter_spec.js b/test/spec/modules/sovrnBidAdapter_spec.js index b19b79c7886..22c93505ecf 100644 --- a/test/spec/modules/sovrnBidAdapter_spec.js +++ b/test/spec/modules/sovrnBidAdapter_spec.js @@ -8,7 +8,7 @@ const ENDPOINT = `//ap.lijit.com/rtb/bid?src=${REPO_AND_VERSION}`; describe('sovrnBidAdapter', function() { const adapter = newBidder(spec); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'sovrn', 'params': { @@ -23,23 +23,23 @@ describe('sovrnBidAdapter', function() { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when tagid not passed correctly', () => { + it('should return false when tagid not passed correctly', function () { bid.params.tagid = 'ABCD'; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when require params are not passed', () => { + it('should return false when require params are not passed', function () { let bid = Object.assign({}, bid); bid.params = {}; expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { const bidRequests = [{ 'bidder': 'sovrn', 'params': { @@ -56,15 +56,15 @@ describe('sovrnBidAdapter', function() { const request = spec.buildRequests(bidRequests); - it('sends bid request to our endpoint via POST', () => { + it('sends bid request to our endpoint via POST', function () { expect(request.method).to.equal('POST'); }); - it('attaches source and version to endpoint URL as query params', () => { + it('attaches source and version to endpoint URL as query params', function () { expect(request.url).to.equal(ENDPOINT) }); - it('sends \'iv\' as query param if present', () => { + it('sends \'iv\' as query param if present', function () { const ivBidRequests = [{ 'bidder': 'sovrn', 'params': { @@ -81,10 +81,10 @@ describe('sovrnBidAdapter', function() { }]; const request = spec.buildRequests(ivBidRequests); - expect(request.data).to.contain('"iv":"vet"') + expect(request.url).to.contain('iv=vet') }); - it('sends gdpr info if exists', () => { + it('sends gdpr info if exists', function () { let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; let bidderRequest = { 'bidderCode': 'sovrn', @@ -107,7 +107,7 @@ describe('sovrnBidAdapter', function() { expect(payload.user.ext.consent).to.equal(consentString); }); - it('converts tagid to string', () => { + it('converts tagid to string', function () { const ivBidRequests = [{ 'bidder': 'sovrn', 'params': { @@ -128,9 +128,9 @@ describe('sovrnBidAdapter', function() { }) }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response; - beforeEach(() => { + beforeEach(function () { response = { body: { 'id': '37386aade21a71', @@ -150,7 +150,7 @@ describe('sovrnBidAdapter', function() { }; }); - it('should get the correct bid response', () => { + it('should get the correct bid response', function () { let expectedResponse = [{ 'requestId': '263c448586f5a1', 'cpm': 0.45882675, @@ -169,7 +169,7 @@ describe('sovrnBidAdapter', function() { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('crid should default to the bid id if not on the response', () => { + it('crid should default to the bid id if not on the response', function () { delete response.body.seatbid[0].bid[0].crid; let expectedResponse = [{ 'requestId': '263c448586f5a1', @@ -189,7 +189,7 @@ describe('sovrnBidAdapter', function() { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('should get correct bid response when dealId is passed', () => { + it('should get correct bid response when dealId is passed', function () { response.body.dealid = 'baking'; let expectedResponse = [{ @@ -210,7 +210,7 @@ describe('sovrnBidAdapter', function() { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('handles empty bid response', () => { + it('handles empty bid response', function () { let response = { body: { 'id': '37386aade21a71', @@ -221,4 +221,66 @@ describe('sovrnBidAdapter', function() { expect(result.length).to.equal(0); }); }); + + describe('getUserSyncs ', () => { + let syncOptions = {iframeEnabled: true, pixelEnabled: true}; + let iframeDisabledSyncOptions = {iframeEnabled: false, pixelEnabled: true}; + let serverResponse = [ + { + 'body': { + 'id': '546956d68c757f', + 'seatbid': [ + { + 'bid': [ + { + 'id': 'a_448326_16c2ada014224bee815a90d2248322f5', + 'impid': '2a3826aae345f4', + 'price': 1.0099999904632568, + 'nurl': 'http://localhost/rtb/impression?bannerid=220958&campaignid=3890&rtb_tid=15588614-75d2-40ab-b27e-13d2127b3c2e&rpid=1295&seatid=seat1&zoneid=448326&cb=26900712&tid=a_448326_16c2ada014224bee815a90d2248322f5', + 'adm': 'yo a creative', + 'crid': 'cridprebidrtb', + 'w': 160, + 'h': 600 + }, + { + 'id': 'a_430392_beac4c1515da4576acf6cb9c5340b40c', + 'impid': '3cf96fd26ed4c5', + 'price': 1.0099999904632568, + 'nurl': 'http://localhost/rtb/impression?bannerid=220957&campaignid=3890&rtb_tid=5bc0e68b-3492-448d-a6f9-26fa3fd0b646&rpid=1295&seatid=seat1&zoneid=430392&cb=62735099&tid=a_430392_beac4c1515da4576acf6cb9c5340b40c', + 'adm': 'yo a creative', + 'crid': 'cridprebidrtb', + 'w': 300, + 'h': 250 + }, + ] + } + ], + 'ext': { + 'iid': 13487408 + } + }, + 'headers': {} + } + ]; + it('should return if iid present on server response & iframe syncs enabled', () => { + let expectedReturnStatement = [ + { + 'type': 'iframe', + 'url': '//ap.lijit.com/beacon?informer=13487408&gdpr_consent=', + } + ]; + let returnStatement = spec.getUserSyncs(syncOptions, serverResponse); + expect(returnStatement[0]).to.deep.equal(expectedReturnStatement[0]); + }); + + it('should not return if iid missing on server response', () => { + let returnStatement = spec.getUserSyncs(syncOptions, []); + expect(returnStatement).to.be.empty; + }); + + it('should not return if iframe syncs disabled', () => { + let returnStatement = spec.getUserSyncs(iframeDisabledSyncOptions, serverResponse); + expect(returnStatement).to.be.empty; + }); + }); }); diff --git a/test/spec/modules/telariaBidAdapter_spec.js b/test/spec/modules/telariaBidAdapter_spec.js new file mode 100644 index 00000000000..6b5278c20ae --- /dev/null +++ b/test/spec/modules/telariaBidAdapter_spec.js @@ -0,0 +1,190 @@ +import {expect} from 'chai'; +import {newBidder} from 'src/adapters/bidderFactory'; +import {spec} from 'modules/telariaBidAdapter'; + +const ENDPOINT = '.ads.tremorhub.com/ad/tag'; +const AD_CODE = 'ssp-!demo!-lufip'; +const SUPPLY_CODE = 'ssp-demo-rm6rh'; +const SIZES = [640, 480]; +const REQUEST = { + 'code': 'video1', + 'sizes': [640, 480], + 'mediaType': 'video', + 'bids': [{ + 'bidder': 'tremor', + 'params': { + 'videoId': 'MyCoolVideo', + 'inclSync': true + } + }] +}; + +const RESPONSE = { + 'cur': 'USD', + 'id': '3dba13e35f3d42f998bc7e65fd871889', + 'seatbid': [{ + 'seat': 'TremorVideo', + 'bid': [{ + 'adomain': [], + 'price': 0.50000, + 'id': '3dba13e35f3d42f998bc7e65fd871889', + 'adm': '\n Tremor Video Test MP4 Creative \n\n \n\n\n\n\n\n \n\n \n\n', + 'impid': '1' + }] + }] +}; + +describe('TelariaAdapter', function () { + 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 () { + let bid = REQUEST.bids[0]; + + it('should return true when required params found', function () { + let tempBid = bid; + tempBid.params.adCode = 'ssp-!demo!-lufip'; + tempBid.params.supplyCode = 'ssp-demo-rm6rh'; + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return true when required params found', function () { + let tempBid = bid; + delete tempBid.params; + tempBid.params = { + supplyCode: 'ssp-demo-rm6rh', + adCode: 'ssp-!demo!-lufip', + }; + + expect(spec.isBidRequestValid(tempBid)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + let tempBid = bid; + tempBid.params = {}; + expect(spec.isBidRequestValid(tempBid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + const stub = [{ + bidder: 'tremor', + sizes: [[300, 250], [300, 600]], + params: { + supplyCode: 'ssp-demo-rm6rh', + adCode: 'ssp-!demo!-lufip', + videoId: 'MyCoolVideo' + } + }]; + + it('exists and is a function', function () { + expect(spec.buildRequests).to.exist.and.to.be.a('function'); + }); + + it('requires supply code, ad code and sizes to make a request', function () { + const tempRequest = spec.buildRequests(stub); + expect(tempRequest.length).to.equal(1); + }); + + it('generates an array of requests with 4 params, method, url, bidId and vastUrl', function () { + const tempRequest = spec.buildRequests(stub); + + expect(tempRequest.length).to.equal(1); + expect(tempRequest[0].method).to.equal('GET'); + expect(tempRequest[0].url).to.exist; + expect(tempRequest[0].bidId).to.equal(undefined); + expect(tempRequest[0].vastUrl).to.exist; + }); + + it('requires sizes to make a request', function () { + let tempBid = stub; + tempBid[0].sizes = null; + const tempRequest = spec.buildRequests(tempBid); + + expect(tempRequest.length).to.equal(0); + }); + + it('generates a valid request with sizes as an array of two elements', function () { + let tempBid = stub; + tempBid[0].sizes = [640, 480]; + expect(spec.buildRequests(tempBid).length).to.equal(1); + }); + + it('requires ad code and supply code to make a request', function () { + let tempBid = stub; + tempBid[0].params.adCode = null; + tempBid[0].params.supplyCode = null; + + const tempRequest = spec.buildRequests(tempBid); + + expect(tempRequest.length).to.equal(0); + }); + }); + + describe('interpretResponse', function () { + const responseStub = RESPONSE; + const stub = [{ + bidder: 'tremor', + sizes: [[300, 250], [300, 600]], + params: { + supplyCode: 'ssp-demo-rm6rh', + adCode: 'ssp-!demo!-lufip', + videoId: 'MyCoolVideo' + } + }]; + + it('should get correct bid response', function () { + let expectedResponseKeys = ['bidderCode', 'width', 'height', 'statusMessage', 'adId', 'mediaType', 'source', + 'getStatusCode', 'getSize', 'requestId', 'cpm', 'creativeId', 'vastXml', + 'vastUrl', 'currency', 'netRevenue', 'ttl', 'ad']; + + let bidRequest = spec.buildRequests(stub)[0]; + bidRequest.bidId = '1234'; + let result = spec.interpretResponse({body: responseStub}, bidRequest); + expect(Object.keys(result[0])).to.have.members(expectedResponseKeys); + }); + + it('handles nobid responses', function () { + let tempResponse = responseStub; + tempResponse.seatbid = []; + + let bidRequest = spec.buildRequests(stub)[0]; + bidRequest.bidId = '1234'; + + let result = spec.interpretResponse({body: tempResponse}, bidRequest); + expect(result.length).to.equal(0); + }); + + it('handles invalid responses', function () { + let result = spec.interpretResponse(null, {bbidderCode: 'telaria'}); + expect(result.length).to.equal(0); + }); + + it('handles error responses', function () { + let result = spec.interpretResponse({body: {error: 'Invalid request'}}, {bbidderCode: 'telaria'}); + expect(result.length).to.equal(0); + }); + }); + + describe('getUserSyncs', function () { + const responses = [{body: RESPONSE}]; + responses[0].body.ext = { + telaria: { + userSync: [ + 'https://url.com', + 'https://url2.com' + ] + } + }; + + it('should get the correct number of sync urls', function () { + let urls = spec.getUserSyncs({pixelEnabled: true}, responses); + expect(urls.length).to.equal(2); + }); + }); +}); diff --git a/test/spec/modules/trionBidAdapter_spec.js b/test/spec/modules/trionBidAdapter_spec.js index 559122a2772..805ae70a339 100644 --- a/test/spec/modules/trionBidAdapter_spec.js +++ b/test/spec/modules/trionBidAdapter_spec.js @@ -35,22 +35,24 @@ const TRION_BID_RESPONSE = { }; -describe('Trion adapter tests', () => { +describe('Trion adapter tests', function () { let adapter; - beforeEach(() => { + beforeEach(function () { // adapter = trionAdapter.createNew(); sinon.stub(document.body, 'appendChild'); }); - afterEach(() => document.body.appendChild.restore()); + afterEach(function () { + document.body.appendChild.restore(); + }); - describe('isBidRequestValid', () => { - it('should return true with correct params', () => { + describe('isBidRequestValid', function () { + it('should return true with correct params', function () { expect(spec.isBidRequestValid(TRION_BID)).to.equal(true); }); - it('should return false when params are missing', () => { + it('should return false when params are missing', function () { TRION_BID.params = {}; expect(spec.isBidRequestValid(TRION_BID)).to.equal(false); @@ -60,7 +62,7 @@ describe('Trion adapter tests', () => { }; }); - it('should return false when pubId is missing', () => { + it('should return false when pubId is missing', function () { TRION_BID.params = { sectionId: '2' }; @@ -72,7 +74,7 @@ describe('Trion adapter tests', () => { }; }); - it('should return false when sectionId is missing', () => { + it('should return false when sectionId is missing', function () { TRION_BID.params = { pubId: '1' }; @@ -85,20 +87,20 @@ describe('Trion adapter tests', () => { }); }); - describe('buildRequests', () => { - it('should return bids requests with empty params', () => { + describe('buildRequests', function () { + it('should return bids requests with empty params', function () { let bidRequests = spec.buildRequests([]); expect(bidRequests.length).to.equal(0); }); - it('should include the base bidrequest url', () => { + it('should include the base bidrequest url', function () { let bidRequests = spec.buildRequests(TRION_BID_REQUEST); let bidUrl = bidRequests[0].url; expect(bidUrl).to.include(BID_REQUEST_BASE_URL); }); - it('should call buildRequests with the correct required params', () => { + it('should call buildRequests with the correct required params', function () { let bidRequests = spec.buildRequests(TRION_BID_REQUEST); let bidUrlParams = bidRequests[0].data; @@ -107,7 +109,7 @@ describe('Trion adapter tests', () => { expect(bidUrlParams).to.include('sizes=300x250,300x600'); }); - it('should call buildRequests with the correct optional params', () => { + it('should call buildRequests with the correct optional params', function () { let params = TRION_BID_REQUEST[0].params; params.re = 1; let bidRequests = spec.buildRequests(TRION_BID_REQUEST); @@ -119,13 +121,13 @@ describe('Trion adapter tests', () => { }); }); - describe('interpretResponse', () => { - it('when there is no response do not bid', () => { + describe('interpretResponse', function () { + it('when there is no response do not bid', function () { let response = spec.interpretResponse(null, {bidRequest: TRION_BID}); expect(response).to.deep.equal([]); }); - it('when place bid is returned as false', () => { + it('when place bid is returned as false', function () { TRION_BID_RESPONSE.result.placeBid = false; let response = spec.interpretResponse({body: TRION_BID_RESPONSE}, {bidRequest: TRION_BID}); @@ -134,21 +136,21 @@ describe('Trion adapter tests', () => { TRION_BID_RESPONSE.result.placeBid = true; }); - it('when no cpm is in the response', () => { + it('when no cpm is in the response', function () { TRION_BID_RESPONSE.result.cpm = 0; let response = spec.interpretResponse({body: TRION_BID_RESPONSE}, {bidRequest: TRION_BID}); expect(response).to.deep.equal([]); TRION_BID_RESPONSE.result.cpm = 1; }); - it('when no ad is in the response', () => { + it('when no ad is in the response', function () { TRION_BID_RESPONSE.result.ad = null; let response = spec.interpretResponse({body: TRION_BID_RESPONSE}, {bidRequest: TRION_BID}); expect(response).to.deep.equal([]); TRION_BID_RESPONSE.result.ad = 'test'; }); - it('height and width are appropriately set', () => { + it('height and width are appropriately set', function () { let bidWidth = '1'; let bidHeight = '2'; TRION_BID_RESPONSE.result.width = bidWidth; @@ -160,7 +162,7 @@ describe('Trion adapter tests', () => { TRION_BID_RESPONSE.result.height = '250'; }); - it('cpm is properly set and transformed to cents', () => { + it('cpm is properly set and transformed to cents', function () { let bidCpm = 2; TRION_BID_RESPONSE.result.cpm = bidCpm * 100; let response = spec.interpretResponse({body: TRION_BID_RESPONSE}, {bidRequest: TRION_BID}); @@ -169,15 +171,15 @@ describe('Trion adapter tests', () => { }); }); - describe('getUserSyncs', () => { + describe('getUserSyncs', function () { const USER_SYNC_URL = 'https://in-appadvertising.com/api/userSync.html'; const BASE_KEY = '_trion_'; - beforeEach(() => { + beforeEach(function () { delete window.TR_INT_T; }); - it('trion int is included in bid url', () => { + it('trion int is included in bid url', function () { window.TR_INT_T = 'test_user_sync'; let userTag = encodeURIComponent(window.TR_INT_T); let bidRequests = spec.buildRequests(TRION_BID_REQUEST); @@ -186,7 +188,7 @@ describe('Trion adapter tests', () => { expect(bidUrlParams).to.include(userTag); }); - it('should register trion user script', () => { + it('should register trion user script', function () { let syncs = spec.getUserSyncs({iframeEnabled: true}); let url = utils.getTopWindowUrl(); let pubId = 1; @@ -195,7 +197,7 @@ describe('Trion adapter tests', () => { expect(syncs[0]).to.deep.equal({type: 'iframe', url: USER_SYNC_URL + syncString}); }); - it('should except posted messages from user sync script', () => { + it('should except posted messages from user sync script', function () { let testId = 'testId'; let message = BASE_KEY + 'userId=' + testId; setStorageData(BASE_KEY + 'int_t', null); @@ -204,7 +206,7 @@ describe('Trion adapter tests', () => { expect(newKey).to.equal(testId); }); - it('should not try to post messages not from trion', () => { + it('should not try to post messages not from trion', function () { let testId = 'testId'; let badId = 'badId'; let message = 'Not Trion: userId=' + testId; diff --git a/test/spec/modules/tripleliftBidAdapter_spec.js b/test/spec/modules/tripleliftBidAdapter_spec.js new file mode 100644 index 00000000000..d3013d9be22 --- /dev/null +++ b/test/spec/modules/tripleliftBidAdapter_spec.js @@ -0,0 +1,213 @@ +import { expect } from 'chai'; +import { tripleliftAdapterSpec } from 'modules/tripleliftBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { deepClone } from 'src/utils'; + +const ENDPOINT = document.location.protocol + '//tlx.3lift.com/header/auction?'; + +describe('triplelift adapter', function () { + const adapter = newBidder(tripleliftAdapterSpec); + + describe('inherited functions', function () { + it('exists and is a function', function () { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', function () { + let bid = { + bidder: 'triplelift', + params: { + inventoryCode: '12345', + floor: 1.0, + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + it('should return true for valid bid request', function () { + expect(tripleliftAdapterSpec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return true when required params found', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + inventoryCode: 'another_inv_code', + floor: 0.05 + }; + expect(tripleliftAdapterSpec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + floor: 1.0 + }; + expect(tripleliftAdapterSpec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [ + { + bidder: 'triplelift', + params: { + inventoryCode: '12345', + floor: 1.0, + }, + adUnitCode: 'adunit-code', + sizes: [[300, 250], [300, 600], [1, 1, 1], ['flex']], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475', + } + ]; + + it('exists and is an object', function () { + const request = tripleliftAdapterSpec.buildRequests(bidRequests); + expect(request).to.exist.and.to.be.a('object'); + }); + + it('should only parse sizes that are of the proper length and format', function () { + const request = tripleliftAdapterSpec.buildRequests(bidRequests); + expect(request.data.imp[0].banner.format).to.have.length(2); + expect(request.data.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); + }); + + it('should be a post request and populate the payload', function () { + const request = tripleliftAdapterSpec.buildRequests(bidRequests); + const payload = request.data; + expect(payload).to.exist; + expect(payload.imp[0].tagid).to.equal('12345'); + expect(payload.imp[0].floor).to.equal(1.0); + expect(payload.imp[0].banner.format).to.deep.equal([{w: 300, h: 250}, {w: 300, h: 600}]); + }); + + it('should return a query string for TL call', function () { + const request = tripleliftAdapterSpec.buildRequests(bidRequests); + const url = request.url; + expect(url).to.exist; + expect(url).to.be.a('string'); + expect(url).to.match(/(?:tlx.3lift.com\/header\/auction)/) + expect(url).to.match(/(?:lib=prebid)/) + expect(url).to.match(/(?:prebid.version)/) + // expect(url).to.match(/(?:fe=)/) // + expect(url).to.match(/(?:referrer)/) + }) + }); + + describe('interpretResponse', function () { + let response = { + body: { + bids: [ + { + imp_id: 0, + cpm: 1.062, + width: 300, + height: 250, + ad: 'ad-markup', + iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + } + ] + } + }; + let bidderRequest = { + bidderCode: 'triplelift', + auctionId: 'a7ebcd1d-66ff-4b5c-a82c-6a21a6ee5a18', + bidderRequestId: '5c55612f99bc11', + bids: [ + { + imp_id: 0, + cpm: 1.062, + width: 300, + height: 250, + ad: 'ad-markup', + iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + } + ], + gdprConsent: { + consentString: 'BOONm0NOONma-AAAARh7______b9_3__7_9uz_Kv_K7Vf7nnG072lPVOQ6gEaY', + gdprApplies: true + } + }; + + it('should get correct bid response', function () { + let expectedResponse = [ + { + requestId: '3db3773286ee59', + cpm: 1.062, + width: 300, + height: 250, + netRevenue: true, + ad: 'ad-markup', + creativeId: 29681110, + dealId: '', + currency: 'USD', + ttl: 33, + } + ]; + let result = tripleliftAdapterSpec.interpretResponse(response, {bidderRequest}); + expect(result).to.have.length(1); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('should return multile responses to support SRA', function () { + let response = { + body: { + bids: [ + { + imp_id: 0, + cpm: 1.062, + width: 300, + height: 250, + ad: 'ad-markup', + iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + }, + { + imp_id: 0, + cpm: 1.9, + width: 300, + height: 600, + ad: 'ad-markup-2', + iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + } + ] + } + }; + let bidderRequest = { + bidderCode: 'triplelift', + auctionId: 'a7ebcd1d-66ff-4b5c-a82c-6a21a6ee5a18', + bidderRequestId: '5c55612f99bc11', + bids: [ + { + imp_id: 0, + cpm: 1.062, + width: 300, + height: 600, + ad: 'ad-markup', + iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + }, + { + imp_id: 0, + cpm: 1.9, + width: 300, + height: 250, + ad: 'ad-markup-2', + iurl: 'https://s.adroll.com/a/IYR/N36/IYRN366MFVDITBAGNNT5U6.jpg' + } + ], + gdprConsent: { + consentString: 'BOONm0NOONm0NABABAENAa-AAAARh7______b9_3__7_9uz_Kv_K7Vf7nnG072lPVA9LTOQ6gEaY', + gdprApplies: true + } + }; + let result = tripleliftAdapterSpec.interpretResponse(response, {bidderRequest}); + expect(result).to.have.length(2); + }); + }); +}); diff --git a/test/spec/modules/trustxBidAdapter_spec.js b/test/spec/modules/trustxBidAdapter_spec.js index 75405850d7a..9f2fdca6a99 100644 --- a/test/spec/modules/trustxBidAdapter_spec.js +++ b/test/spec/modules/trustxBidAdapter_spec.js @@ -5,13 +5,13 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('TrustXAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'trustx', 'params': { @@ -24,11 +24,11 @@ describe('TrustXAdapter', function () { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -38,7 +38,15 @@ describe('TrustXAdapter', function () { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { + function parseRequest(url) { + const res = {}; + url.split('&').forEach((it) => { + const couple = it.split('='); + res[couple[0]] = decodeURIComponent(couple[1]); + }); + return res; + } let bidRequests = [ { 'bidder': 'trustx', @@ -75,31 +83,31 @@ describe('TrustXAdapter', function () { } ]; - it('should attach valid params to the tag', () => { + it('should attach valid params to the tag', function () { const request = spec.buildRequests([bidRequests[0]]); - const payload = request.data; - expect(payload).to.be.an('object'); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '43'); expect(payload).to.have.property('r', '22edbae2733bf6'); }); - it('auids must not be duplicated', () => { + it('auids must not be duplicated', function () { const request = spec.buildRequests(bidRequests); - const payload = request.data; - expect(payload).to.be.an('object'); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '43,45'); expect(payload).to.have.property('r', '22edbae2733bf6'); }); - it('pt parameter must be "gross" if params.priceType === "gross"', () => { + it('pt parameter must be "gross" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; const request = spec.buildRequests(bidRequests); - const payload = request.data; - expect(payload).to.be.an('object'); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'gross'); expect(payload).to.have.property('auids', '43,45'); @@ -107,11 +115,11 @@ describe('TrustXAdapter', function () { delete bidRequests[1].params.priceType; }); - it('pt parameter must be "net" or "gross"', () => { + it('pt parameter must be "net" or "gross"', function () { bidRequests[1].params.priceType = 'some'; const request = spec.buildRequests(bidRequests); - const payload = request.data; - expect(payload).to.be.an('object'); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); expect(payload).to.have.property('u').that.is.a('string'); expect(payload).to.have.property('pt', 'net'); expect(payload).to.have.property('auids', '43,45'); @@ -119,32 +127,32 @@ describe('TrustXAdapter', function () { delete bidRequests[1].params.priceType; }); - it('if gdprConsent is present payload must have gdpr params', () => { + it('if gdprConsent is present payload must have gdpr params', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); - const payload = request.data; - expect(payload).to.be.an('object'); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); expect(payload).to.have.property('gdpr_consent', 'AAA'); - expect(payload).to.have.property('gdpr_applies', 1); + expect(payload).to.have.property('gdpr_applies', '1'); }); - it('if gdprApplies is false gdpr_applies must be 0', () => { + it('if gdprApplies is false gdpr_applies must be 0', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: false}}); - const payload = request.data; - expect(payload).to.be.an('object'); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); expect(payload).to.have.property('gdpr_consent', 'AAA'); - expect(payload).to.have.property('gdpr_applies', 0); + expect(payload).to.have.property('gdpr_applies', '0'); }); - it('if gdprApplies is undefined gdpr_applies must be 1', () => { + it('if gdprApplies is undefined gdpr_applies must be 1', function () { const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA'}}); - const payload = request.data; - expect(payload).to.be.an('object'); + expect(request.data).to.be.an('string'); + const payload = parseRequest(request.data); expect(payload).to.have.property('gdpr_consent', 'AAA'); - expect(payload).to.have.property('gdpr_applies', 1); + expect(payload).to.have.property('gdpr_applies', '1'); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const responses = [ {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 43, 'h': 250, 'w': 300}], 'seat': '1'}, {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 44, 'h': 90, 'w': 728}], 'seat': '1'}, @@ -155,7 +163,7 @@ describe('TrustXAdapter', function () { {'seat': '1'}, ]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const bidRequests = [ { 'bidder': 'trustx', @@ -190,7 +198,7 @@ describe('TrustXAdapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should get correct multi bid response', () => { + it('should get correct multi bid response', function () { const bidRequests = [ { 'bidder': 'trustx', @@ -273,7 +281,7 @@ describe('TrustXAdapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('handles wrong and nobid responses', () => { + it('handles wrong and nobid responses', function () { const bidRequests = [ { 'bidder': 'trustx', diff --git a/test/spec/modules/ucfunnelBidAdapter_spec.js b/test/spec/modules/ucfunnelBidAdapter_spec.js index 152c7c39b1e..32daf5ecb96 100644 --- a/test/spec/modules/ucfunnelBidAdapter_spec.js +++ b/test/spec/modules/ucfunnelBidAdapter_spec.js @@ -1,19 +1,20 @@ import { expect } from 'chai'; import { spec } from 'modules/ucfunnelBidAdapter'; +import {BANNER, VIDEO, NATIVE} from 'src/mediaTypes'; const URL = '//hb.aralego.com/header'; const BIDDER_CODE = 'ucfunnel'; -const validBidReq = { +const validBannerBidReq = { bidder: BIDDER_CODE, params: { - adid: 'test-ad-83444226E44368D1E32E49EEBE6D29' + adid: 'ad-34BBD2AA24B678BBFD4E7B9EE3B872D' }, sizes: [[300, 250]], bidId: '263be71e91dd9d', auctionId: '9ad1fa8d-2297-4660-a018-b39945054746', }; -const invalidBidReq = { +const invalidBannerBidReq = { bidder: BIDDER_CODE, params: { adid: 123456789 @@ -23,86 +24,166 @@ const invalidBidReq = { auctionId: '9ad1fa8d-2297-4660-a018-b39945054746' }; -const bidReq = [{ +const validBannerBidRes = { + creative_type: BANNER, + ad_id: 'ad-34BBD2AA24B678BBFD4E7B9EE3B872D', + adm: '
', + cpm: 0.01, + height: 250, + width: 300 +}; + +const validVideoBidReq = { bidder: BIDDER_CODE, params: { - adid: 'test-ad-83444226E44368D1E32E49EEBE6D29' + adid: 'ad-9A22D466494297EAC443D967B2622DA9' }, - sizes: [[300, 250]], - bidId: '263be71e91dd9d', - auctionId: '9ad1fa8d-2297-4660-a018-b39945054746' -}]; + sizes: [[640, 360]], + bidId: '263be71e91dd9f', + auctionId: '9ad1fa8d-2297-4660-a018-b39945054746', +}; -const validBidRes = { - ad_id: 'ad-83444226E44368D1E32E49EEBE6D29', - adm: '
', +const validVideoBidRes = { + creative_type: VIDEO, + ad_id: 'ad-9A22D466494297EAC443D967B2622DA9', + vastUrl: 'https://ads.aralego.com/ads/58f9749f-0553-4993-8d9a-013a38b29e55', + vastXml: 'ucX I-Primo 00:00:30', cpm: 0.01, - height: 250, - width: 300 + width: 640, + height: 360 +}; + +const validNativeBidReq = { + bidder: BIDDER_CODE, + params: { + adid: 'ad-627736446B2BD3A60E8AEABDB7BD833E' + }, + sizes: [[1, 1]], + bidId: '263be71e91dda0', + auctionId: '9ad1fa8d-2297-4660-a018-b39945054746', }; -const bidResponse = validBidRes; - -const bidResArray = [ - validBidRes, - { - ad: '', - bidRequestId: '263be71e91dd9d', - cpm: 100, - adId: '123abc', - currency: 'USD', - netRevenue: true, - width: 300, - height: 250, - ttl: 360 +const validNativeBidRes = { + creative_type: NATIVE, + ad_id: 'ad-9A22D466494297EAC443D967B2622DA9', + native: { + title: 'ucfunnel adExchange', + body: 'We monetize your traffic via historic data driven protocol', + cta: 'Learn more', + sponsoredBy: 'ucfunnel Co., Ltd.', + image: { + url: 'https://cdn.aralego.net/img/main/AdGent-1200x627.jpg', + width: 1200, + height: 627 + }, + icon: { + url: 'https://cdn.aralego.net/img/logo/logo-84x84.jpg', + widt: 84, + heigh: 84 + }, + clickUrl: 'https://www.ucfunnel.com', + impressionTrackers: ['https://www.aralego.net/imp?mf=native&adid=ad-9A22D466494297EAC443D967B2622DA9&auc=9ad1fa8d-2297-4660-a018-b39945054746'], }, - { - ad: '
Hello
', - bidRequestId: '', - cpm: 0, - adId: '123abc', - currency: 'USD', - netRevenue: true, - width: 300, - height: 250, - ttl: 360 - } -]; - -describe('ucfunnel Adapter', () => { - describe('request', () => { - it('should validate bid request', () => { - expect(spec.isBidRequestValid(validBidReq)).to.equal(true); + cpm: 0.01, + height: 1, + width: 1 +}; + +describe('ucfunnel Adapter', function () { + describe('request', function () { + it('should validate bid request', function () { + expect(spec.isBidRequestValid(validBannerBidReq)).to.equal(true); }); - it('should not validate incorrect bid request', () => { - expect(spec.isBidRequestValid(invalidBidReq)).to.equal(false); + it('should not validate incorrect bid request', function () { + expect(spec.isBidRequestValid(invalidBannerBidReq)).to.equal(false); }); }); - describe('build request', () => { - it('Verify bid request', () => { - const request = spec.buildRequests(bidReq); + describe('build request', function () { + const request = spec.buildRequests([validBannerBidReq]); + it('should create a POST request for every bid', function () { expect(request[0].method).to.equal('GET'); - expect(request[0].url).to.equal(URL); - expect(request[0].data).to.match(new RegExp(`${bidReq[0].params.adid}`)); + expect(request[0].url).to.equal(location.protocol + spec.ENDPOINT); + }); + + it('should attach the bid request object', function () { + expect(request[0].bidRequest).to.equal(validBannerBidReq); + }); + + it('should attach request data', function () { + const data = request[0].data; + const [ width, height ] = validBannerBidReq.sizes[0]; + expect(data.w).to.equal(width); + expect(data.h).to.equal(height); + }); + + it('must parse bid size from a nested array', function () { + const width = 640; + const height = 480; + validBannerBidReq.sizes = [[ width, height ]]; + const requests = spec.buildRequests([ validBannerBidReq ]); + const data = requests[0].data; + expect(data.w).to.equal(width); + expect(data.h).to.equal(height); }); }); - describe('interpretResponse', () => { - it('should build bid array', () => { - const request = spec.buildRequests(bidReq); - const result = spec.interpretResponse({body: bidResponse}, request[0]); - expect(result.length).to.equal(1); + describe('interpretResponse', function () { + describe('should support banner', function () { + const request = spec.buildRequests([ validBannerBidReq ]); + const result = spec.interpretResponse({body: validBannerBidRes}, request[0]); + it('should build bid array for banner', function () { + expect(result.length).to.equal(1); + }); + + it('should have all relevant fields', function () { + const bid = result[0]; + + expect(bid.mediaType).to.equal(BANNER); + expect(bid.ad).to.exist; + expect(bid.requestId).to.equal('263be71e91dd9d'); + expect(bid.cpm).to.equal(0.01); + expect(bid.width).to.equal(300); + expect(bid.height).to.equal(250); + }); }); - it('should have all relevant fields', () => { - const request = spec.buildRequests(bidReq); - const result = spec.interpretResponse({body: bidResponse}, request[0]); - const bid = result[0]; + describe('should support video', function () { + const request = spec.buildRequests([ validVideoBidReq ]); + const result = spec.interpretResponse({body: validVideoBidRes}, request[0]); + it('should build bid array', function () { + expect(result.length).to.equal(1); + }); + + it('should have all relevant fields', function () { + const bid = result[0]; + + expect(bid.mediaType).to.equal(VIDEO); + expect(bid.vastUrl).to.exist; + expect(bid.vastXml).to.exist; + expect(bid.requestId).to.equal('263be71e91dd9f'); + expect(bid.cpm).to.equal(0.01); + expect(bid.width).to.equal(640); + expect(bid.height).to.equal(360); + }); + }); + + describe('should support native', function () { + const request = spec.buildRequests([ validNativeBidReq ]); + const result = spec.interpretResponse({body: validNativeBidRes}, request[0]); + it('should build bid array', function () { + expect(result.length).to.equal(1); + }); + + it('should have all relevant fields', function () { + const bid = result[0]; - expect(bid.requestId).to.equal('263be71e91dd9d'); - expect(bid.cpm).to.equal(0.01); - expect(bid.width).to.equal(300); - expect(bid.height).to.equal(250); + expect(bid.mediaType).to.equal(NATIVE); + expect(bid.native).to.exist; + expect(bid.requestId).to.equal('263be71e91dda0'); + expect(bid.cpm).to.equal(0.01); + expect(bid.width).to.equal(1); + expect(bid.height).to.equal(1); + }); }); }); }); diff --git a/test/spec/modules/underdogmediaBidAdapter_spec.js b/test/spec/modules/underdogmediaBidAdapter_spec.js index 5dc2a65399f..6f4df57d316 100644 --- a/test/spec/modules/underdogmediaBidAdapter_spec.js +++ b/test/spec/modules/underdogmediaBidAdapter_spec.js @@ -1,10 +1,11 @@ import { expect } from 'chai'; import { spec } from 'modules/underdogmediaBidAdapter'; -describe('UnderdogMedia adapter', () => { +describe('UnderdogMedia adapter', function () { let bidRequests; + let bidderRequest; - beforeEach(() => { + beforeEach(function () { bidRequests = [ { bidder: 'underdogmedia', @@ -19,11 +20,24 @@ describe('UnderdogMedia adapter', () => { transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' } ]; + + bidderRequest = { + timeout: 3000, + gdprConsent: { + gdprApplies: 1, + consentString: 'consentDataString', + vendorData: { + vendorConsents: { + '159': 1 + }, + }, + }, + } }); - describe('implementation', () => { - describe('for requests', () => { - it('should accept valid bid', () => { + describe('implementation', function () { + describe('for requests', function () { + it('should accept valid bid', function () { let validBid = { bidder: 'underdogmedia', params: { @@ -36,7 +50,7 @@ describe('UnderdogMedia adapter', () => { expect(isValid).to.equal(true); }); - it('should reject invalid bid missing sizes', () => { + it('should reject invalid bid missing sizes', function () { let invalidBid = { bidder: 'underdogmedia', params: { @@ -48,7 +62,7 @@ describe('UnderdogMedia adapter', () => { expect(isValid).to.equal(false); }); - it('should reject invalid bid missing siteId', () => { + it('should reject invalid bid missing siteId', function () { let invalidBid = { bidder: 'underdogmedia', params: {}, @@ -59,7 +73,7 @@ describe('UnderdogMedia adapter', () => { expect(isValid).to.equal(false); }); - it('request data should contain sid', () => { + it('request data should contain sid', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', @@ -72,12 +86,116 @@ describe('UnderdogMedia adapter', () => { adUnitCode: '/123456/header-bid-tag-1' } ]; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); + + expect(request.data.sid).to.equal('12143'); + }); + + it('request data should contain sizes', function () { + let bidRequests = [ + { + bidId: '3c9408cdbf2f68', + sizes: [[300, 250], [728, 90]], + bidder: 'underdogmedia', + params: { + siteId: '12143' + }, + auctionId: '10b327aa396609', + adUnitCode: '/123456/header-bid-tag-1' + } + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + + expect(request.data.sizes).to.equal('300x250,728x90'); + }); + + it('request data should contain gdpr info', function () { + let bidRequests = [ + { + bidId: '3c9408cdbf2f68', + sizes: [[300, 250], [728, 90]], + bidder: 'underdogmedia', + params: { + siteId: '12143' + }, + auctionId: '10b327aa396609', + adUnitCode: '/123456/header-bid-tag-1' + } + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + + expect(request.data.gdprApplies).to.equal(true); + expect(request.data.consentGiven).to.equal(true); + expect(request.data.consentData).to.equal('consentDataString'); + }); + + it('should not build a request if no vendorConsent', function () { + let bidRequests = [ + { + bidId: '3c9408cdbf2f68', + sizes: [[300, 250], [728, 90]], + bidder: 'underdogmedia', + params: { + siteId: '12143' + }, + auctionId: '10b327aa396609', + adUnitCode: '/123456/header-bid-tag-1' + } + ]; + + let bidderRequest = { + timeout: 3000, + gdprConsent: { + gdprApplies: 1, + consentString: 'consentDataString', + vendorData: { + vendorConsents: { + '159': 0 + }, + }, + }, + } + const request = spec.buildRequests(bidRequests, bidderRequest); + + expect(request).to.equal(undefined); + }); + + it('should properly build a request if no vendorConsent but no gdprApplies', function () { + let bidRequests = [ + { + bidId: '3c9408cdbf2f68', + sizes: [[300, 250], [728, 90]], + bidder: 'underdogmedia', + params: { + siteId: '12143' + }, + auctionId: '10b327aa396609', + adUnitCode: '/123456/header-bid-tag-1' + } + ]; - expect(request.data).to.have.string('sid=12143'); + let bidderRequest = { + timeout: 3000, + gdprConsent: { + gdprApplies: 0, + consentString: 'consentDataString', + vendorData: { + vendorConsents: { + '159': 0 + }, + }, + }, + } + const request = spec.buildRequests(bidRequests, bidderRequest); + + expect(request.data.sizes).to.equal('300x250,728x90'); + expect(request.data.sid).to.equal('12143'); + expect(request.data.gdprApplies).to.equal(false); + expect(request.data.consentGiven).to.equal(false); + expect(request.data.consentData).to.equal('consentDataString'); }); - it('request data should contain sizes', () => { + it('should properly build a request if gdprConsent empty', function () { let bidRequests = [ { bidId: '3c9408cdbf2f68', @@ -90,14 +208,20 @@ describe('UnderdogMedia adapter', () => { adUnitCode: '/123456/header-bid-tag-1' } ]; - const request = spec.buildRequests(bidRequests); - expect(request.data).to.have.string('sizes=300x250,728x90'); + let bidderRequest = { + timeout: 3000, + gdprConsent: {} + } + const request = spec.buildRequests(bidRequests, bidderRequest); + + expect(request.data.sizes).to.equal('300x250,728x90'); + expect(request.data.sid).to.equal('12143'); }); }); - describe('bid responses', () => { - it('should return complete bid response', () => { + describe('bid responses', function () { + it('should return complete bid response', function () { let serverResponse = { body: { mids: [ @@ -122,7 +246,7 @@ describe('UnderdogMedia adapter', () => { ] } }; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const bids = spec.interpretResponse(serverResponse, request); expect(bids).to.be.lengthOf(2); @@ -136,19 +260,19 @@ describe('UnderdogMedia adapter', () => { expect(bids[0].currency).to.equal('USD'); }); - it('should return empty bid response if mids empty', () => { + it('should return empty bid response if mids empty', function () { let serverResponse = { body: { mids: [] } }; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const bids = spec.interpretResponse(serverResponse, request); expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response on incorrect size', () => { + it('should return empty bid response on incorrect size', function () { let serverResponse = { body: { mids: [ @@ -164,13 +288,13 @@ describe('UnderdogMedia adapter', () => { ] } }; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const bids = spec.interpretResponse(serverResponse, request); expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response on 0 cpm', () => { + it('should return empty bid response on 0 cpm', function () { let serverResponse = { body: { mids: [ @@ -186,13 +310,13 @@ describe('UnderdogMedia adapter', () => { ] } }; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const bids = spec.interpretResponse(serverResponse, request); expect(bids).to.be.lengthOf(0); }); - it('should return empty bid response if no ad in response', () => { + it('should return empty bid response if no ad in response', function () { let serverResponse = { body: { mids: [ @@ -208,13 +332,13 @@ describe('UnderdogMedia adapter', () => { ] } }; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const bids = spec.interpretResponse(serverResponse, request); expect(bids).to.be.lengthOf(0); }); - it('ad html string should contain the notification urls', () => { + it('ad html string should contain the notification urls', function () { let serverResponse = { body: { mids: [ @@ -230,7 +354,7 @@ describe('UnderdogMedia adapter', () => { ] } }; - const request = spec.buildRequests(bidRequests); + const request = spec.buildRequests(bidRequests, bidderRequest); const bids = spec.interpretResponse(serverResponse, request); expect(bids[0].ad).to.have.string('notification_url'); diff --git a/test/spec/modules/undertoneBidAdapter_spec.js b/test/spec/modules/undertoneBidAdapter_spec.js index d86a1dc5735..4b816d851d9 100644 --- a/test/spec/modules/undertoneBidAdapter_spec.js +++ b/test/spec/modules/undertoneBidAdapter_spec.js @@ -33,6 +33,15 @@ const bidReq = [{ sizes: [[300, 250], [300, 600]], bidId: '263be71e91dd9d', auctionId: '9ad1fa8d-2297-4660-a018-b39945054746' +}, +{ + bidder: BIDDER_CODE, + params: { + publisherId: 12345 + }, + sizes: [[1, 1]], + bidId: '453cf42d72bb3c', + auctionId: '6c22f5a5-59df-4dc6-b92c-f433bcf0a874' }]; const validBidRes = { @@ -78,41 +87,47 @@ const bidResArray = [ } ]; -describe('Undertone Adapter', () => { - describe('request', () => { - it('should validate bid request', () => { +describe('Undertone Adapter', function () { + describe('request', function () { + it('should validate bid request', function () { expect(spec.isBidRequestValid(validBidReq)).to.equal(true); }); - it('should not validate incorrect bid request', () => { + it('should not validate incorrect bid request', function () { expect(spec.isBidRequestValid(invalidBidReq)).to.equal(undefined); }); }); - describe('build request', () => { - it('should send request to correct url via POST', () => { + describe('build request', function () { + it('should send request to correct url via POST', function () { const request = spec.buildRequests(bidReq); const domain = null; const REQ_URL = `${URL}?pid=${bidReq[0].params.publisherId}&domain=${domain}`; expect(request.url).to.equal(REQ_URL); expect(request.method).to.equal('POST'); }); - it('should have all relevant fields', () => { + it('should have all relevant fields', function () { const request = spec.buildRequests(bidReq); - const bid = JSON.parse(request.data)['x-ut-hb-params'][0]; - expect(bid.bidRequestId).to.equal('263be71e91dd9d'); - expect(bid.sizes.length > 0).to.equal(true); - expect(bid.placementId).to.equal('10433394'); - expect(bid.publisherId).to.equal(12345); - expect(bid.params).to.be.an('object'); + const bid1 = JSON.parse(request.data)['x-ut-hb-params'][0]; + expect(bid1.bidRequestId).to.equal('263be71e91dd9d'); + expect(bid1.sizes.length).to.equal(2); + expect(bid1.placementId).to.equal('10433394'); + expect(bid1.publisherId).to.equal(12345); + expect(bid1.params).to.be.an('object'); + const bid2 = JSON.parse(request.data)['x-ut-hb-params'][1]; + expect(bid2.bidRequestId).to.equal('453cf42d72bb3c'); + expect(bid2.sizes.length).to.equal(1); + expect(bid2.placementId === null).to.equal(true); + expect(bid2.publisherId).to.equal(12345); + expect(bid2.params).to.be.an('object'); }); }); - describe('interpretResponse', () => { - it('should build bid array', () => { + describe('interpretResponse', function () { + it('should build bid array', function () { let result = spec.interpretResponse({body: bidResponse}); expect(result.length).to.equal(1); }); - it('should have all relevant fields', () => { + it('should have all relevant fields', function () { const result = spec.interpretResponse({body: bidResponse}); const bid = result[0]; @@ -126,12 +141,12 @@ describe('Undertone Adapter', () => { expect(bid.ttl).to.equal(360); }); - it('should return empty array when response is incorrect', () => { + it('should return empty array when response is incorrect', function () { expect(spec.interpretResponse({body: {}}).length).to.equal(0); expect(spec.interpretResponse({body: []}).length).to.equal(0); }); - it('should only use valid bid responses', () => { + it('should only use valid bid responses', function () { expect(spec.interpretResponse({ body: bidResArray }).length).to.equal(1); }); }); diff --git a/test/spec/modules/unrulyBidAdapter_spec.js b/test/spec/modules/unrulyBidAdapter_spec.js index 3e39842bd0a..2c8fd9071d6 100644 --- a/test/spec/modules/unrulyBidAdapter_spec.js +++ b/test/spec/modules/unrulyBidAdapter_spec.js @@ -6,7 +6,7 @@ import { VIDEO } from 'src/mediaTypes' import { Renderer } from 'src/Renderer' import { adapter } from 'modules/unrulyBidAdapter' -describe('UnrulyAdapter', () => { +describe('UnrulyAdapter', function () { function createOutStreamExchangeBid({ adUnitCode = 'placement2', statusCode = 1, @@ -39,7 +39,7 @@ describe('UnrulyAdapter', () => { let sandbox; let fakeRenderer; - beforeEach(() => { + beforeEach(function () { sandbox = sinon.sandbox.create(); sandbox.stub(utils, 'logError'); sandbox.stub(Renderer, 'install'); @@ -50,12 +50,12 @@ describe('UnrulyAdapter', () => { Renderer.install.returns(fakeRenderer) }); - afterEach(() => { + afterEach(function () { sandbox.restore(); delete parent.window.unruly }); - it('should expose Unruly Bidder code', () => { + it('should expose Unruly Bidder code', function () { expect(adapter.code).to.equal('unruly') }); @@ -63,22 +63,22 @@ describe('UnrulyAdapter', () => { expect(adapter.supportedMediaTypes).to.deep.equal([ VIDEO ]) }); - describe('isBidRequestValid', () => { - it('should be a function', () => { + describe('isBidRequestValid', function () { + it('should be a function', function () { expect(typeof adapter.isBidRequestValid).to.equal('function') }); - it('should return false if bid is falsey', () => { + it('should return false if bid is falsey', function () { expect(adapter.isBidRequestValid()).to.be.false; }); - it('should return true if bid.mediaType is "video"', () => { + it('should return true if bid.mediaType is "video"', function () { const mockBid = { mediaType: 'video' }; expect(adapter.isBidRequestValid(mockBid)).to.be.true; }); - it('should return true if bid.mediaTypes.video.context is "outstream"', () => { + it('should return true if bid.mediaTypes.video.context is "outstream"', function () { const mockBid = { mediaTypes: { video: { @@ -91,19 +91,19 @@ describe('UnrulyAdapter', () => { }); }); - describe('buildRequests', () => { - it('should be a function', () => { + describe('buildRequests', function () { + it('should be a function', function () { expect(typeof adapter.buildRequests).to.equal('function'); }); - it('should return an object', () => { + it('should return an object', function () { const mockBidRequests = ['mockBid']; expect(typeof adapter.buildRequests(mockBidRequests)).to.equal('object') }); - it('should return a server request with a valid exchange url', () => { + it('should return a server request with a valid exchange url', function () { const mockBidRequests = ['mockBid']; expect(adapter.buildRequests(mockBidRequests).url).to.equal('https://targeting.unrulymedia.com/prebid') }); - it('should return a server request with method === POST', () => { + it('should return a server request with method === POST', function () { const mockBidRequests = ['mockBid']; expect(adapter.buildRequests(mockBidRequests).method).to.equal('POST'); }); @@ -113,7 +113,7 @@ describe('UnrulyAdapter', () => { contentType: 'application/json' }); }); - it('should return a server request with valid payload', () => { + it('should return a server request with valid payload', function () { const mockBidRequests = ['mockBid']; const mockBidderRequest = {bidderCode: 'mockBidder'}; expect(adapter.buildRequests(mockBidRequests, mockBidderRequest).data) @@ -121,18 +121,18 @@ describe('UnrulyAdapter', () => { }) }); - describe('interpretResponse', () => { - it('should be a function', () => { + describe('interpretResponse', function () { + it('should be a function', function () { expect(typeof adapter.interpretResponse).to.equal('function'); }); - it('should return empty array when serverResponse is undefined', () => { + it('should return empty array when serverResponse is undefined', function () { expect(adapter.interpretResponse()).to.deep.equal([]); }); - it('should return empty array when serverResponse has no bids', () => { + it('should return empty array when serverResponse has no bids', function () { const mockServerResponse = { body: { bids: [] } }; expect(adapter.interpretResponse(mockServerResponse)).to.deep.equal([]) }); - it('should return array of bids when receive a successful response from server', () => { + it('should return array of bids when receive a successful response from server', function () { const mockExchangeBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); const mockServerResponse = createExchangeResponse(mockExchangeBid); expect(adapter.interpretResponse(mockServerResponse)).to.deep.equal([ @@ -151,7 +151,7 @@ describe('UnrulyAdapter', () => { ]) }); - it('should initialize and set the renderer', () => { + it('should initialize and set the renderer', function () { expect(Renderer.install).not.to.have.been.called; expect(fakeRenderer.setRender).not.to.have.been.called; @@ -172,7 +172,7 @@ describe('UnrulyAdapter', () => { sinon.assert.calledWithExactly(fakeRenderer.setRender, sinon.match.func) }); - it('bid is placed on the bid queue when render is called', () => { + it('bid is placed on the bid queue when render is called', function () { const exchangeBid = createOutStreamExchangeBid({ adUnitCode: 'video', vastUrl: 'value: vastUrl' }); const exchangeResponse = createExchangeResponse(exchangeBid); @@ -192,7 +192,7 @@ describe('UnrulyAdapter', () => { expect(sentRendererConfig.adUnitCode).to.equal('video') }) - it('should ensure that renderer is placed in Prebid supply mode', () => { + it('should ensure that renderer is placed in Prebid supply mode', function () { const mockExchangeBid = createOutStreamExchangeBid({adUnitCode: 'video1', bidId: 'mockBidId'}); const mockServerResponse = createExchangeResponse(mockExchangeBid); diff --git a/test/spec/modules/uolBidAdapter_spec.js b/test/spec/modules/uolBidAdapter_spec.js new file mode 100644 index 00000000000..1733afc91f9 --- /dev/null +++ b/test/spec/modules/uolBidAdapter_spec.js @@ -0,0 +1,313 @@ +import { expect } from 'chai'; +import { spec } from 'modules/uolBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; + +const ENDPOINT = 'https://prebid.adilligo.com/v1/prebid.json'; + +describe('UOL Bid Adapter', function () { + const adapter = newBidder(spec); + + describe('isBidRequestValid', function () { + let bid = { + 'bidder': 'uol', + 'params': { + 'placementId': '19571273' + }, + 'adUnitCode': '/uol/unit/code', + 'sizes': [[300, 250], [970, 250]], + 'bidId': '3ddb6ed2d73b45', + 'bidderRequestId': 'd2b12f9d2bad975b7', + 'auctionId': 'eb511c63-df7e-4240-9b65-2f8ae50303e4', + }; + + it('should return true for valid params', function () { + let clonedBid = Object.assign({}, bid); + expect(spec.isBidRequestValid(clonedBid)).to.equal(true); + + delete clonedBid.params; + clonedBid.params = { + 'placementId': '19571277', + 'test': 'true' + } + expect(spec.isBidRequestValid(clonedBid)).to.equal(true); + + delete clonedBid.params; + clonedBid.params = { + 'placementId': '19571278', + 'test': 'true', + 'cpmFactor': 2 + } + expect(spec.isBidRequestValid(clonedBid)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + let clonedBid = Object.assign({}, bid); + delete clonedBid.params; + expect(spec.isBidRequestValid(clonedBid)).to.equal(false); + }); + + it('should return false when params are invalid', function () { + let clonedBid = Object.assign({}, bid); + delete clonedBid.params; + clonedBid.params = { + 'placementId': 0 + } + expect(spec.isBidRequestValid(clonedBid)).to.equal(false); + + delete clonedBid.params; + clonedBid.params = { + 'placementId': '19571281', + 'cpmFactor': 2 + } + expect(spec.isBidRequestValid(clonedBid)).to.equal(false); + + delete clonedBid.params; + clonedBid.params = { + 'placementId': '19571282', + 'cpmFactor': 'two' + } + expect(spec.isBidRequestValid(clonedBid)).to.equal(false); + }); + + it('should return false when cpmFactor is passed and test flag isn\'t active', function () { + let clonedBid = Object.assign({}, bid); + delete clonedBid.params; + clonedBid.params = { + 'placementId': '19571283', + 'test': false, + 'cpmFactor': 2 + }; + expect(spec.isBidRequestValid(clonedBid)).to.equal(false); + }); + + it('should not allow empty size', function () { + let clonedBid = Object.assign({}, bid); + delete clonedBid.sizes; + expect(spec.isBidRequestValid(clonedBid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let queryPermission; + let cleanup = function() { + navigator.permissions.query = queryPermission; + }; + let grantTriangulation = function() { + queryPermission = navigator.permissions.query; + navigator.permissions.query = function(data) { + return new Promise((resolve, reject) => { + resolve({state: 'granted'}); + }); + } + }; + let denyTriangulation = function() { + queryPermission = navigator.permissions.query; + navigator.permissions.query = function(data) { + return new Promise((resolve, reject) => { + resolve({state: 'prompt'}); + }); + } + }; + let removeQuerySupport = function() { + queryPermission = navigator.permissions.query; + navigator.permissions.query = undefined; + } + + let bidRequests = [ + { + 'bidder': 'uol', + 'params': { + 'placementId': '19571273' + }, + 'adUnitCode': '/uol/unit/code', + 'sizes': [[300, 250]], + 'bidId': '3ddb6ed2d73b45', + 'bidderRequestId': 'd2b12f9d2bad975b7', + 'auctionId': 'eb511c63-df7e-4240-9b65-2f8ae50303e4', + }, { + 'bidder': 'uol', + 'params': { + 'placementId': '19571274' + }, + 'adUnitCode': '/uol/unit/code2', + 'sizes': [[300, 600], [970, 250]], + 'bidId': '3a3ea8e80a2dc5', + 'bidderRequestId': 'd2b12f9d2bad975b7', + 'auctionId': 'eb511c63-df7e-4240-9b65-2f8ae50303e4', + } + ]; + + let bidderRequest = { + 'auctionId': 'eb511c63-df7e-4240-9b65-2f8ae50303e4', + 'auctionStart': 1530133180799, + 'bidderCode': 'uol', + 'bidderRequestId': 'd2b12f9d2bad975b7', + 'bids': bidRequests, + 'doneCbCallCount': 1, + 'start': 1530133180801, + 'timeout': 3000 + }; + + describe('buildRequest basic params', function () { + const requestObject = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(requestObject.data); + + it('should send bid requests to expected endpoint via POST method', function () { + expect(requestObject.url).to.equal(ENDPOINT); + expect(requestObject.method).to.equal('POST'); + }); + + it('should contain referrer URL', function () { + expect(payload.referrerURL).to.exist.and.to.match(/^http(s)?:\/\/.+$/) + }); + + it('should contain an array of requests with length equivalent to bid count', function () { + expect(payload.requests).to.have.length(bidRequests.length); + }); + it('should return propper ad size if at least one entry is provided', function () { + expect(payload.requests[0].sizes).to.deep.equal(bidRequests[0].sizes); + }); + }); + + if (navigator.permissions && navigator.permissions.query && navigator.geolocation) { + describe('buildRequest geolocation param', function () { // shall only be tested if browser engine supports geolocation and permissions API. + let geolocation = { lat: 4, long: 3, timestamp: 123121451 }; + + it('should contain user coordinates if (i) DNT is off; (ii) browser supports implementation; (iii) localStorage contains geolocation history', function () { + localStorage.setItem('uolLocationTracker', JSON.stringify(geolocation)); + grantTriangulation(); + const requestObject = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(requestObject.data); + expect(payload.geolocation).to.exist.and.not.be.empty; + cleanup(); + }) + + it('should not contain user coordinates if localStorage is empty', function () { + localStorage.removeItem('uolLocationTracker'); + denyTriangulation(); + const requestObject = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(requestObject.data); + expect(payload.geolocation).to.not.exist; + cleanup(); + }) + + it('should not contain user coordinates if browser doesnt support permission query', function () { + localStorage.setItem('uolLocationTracker', JSON.stringify(geolocation)); + removeQuerySupport(); + const requestObject = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(requestObject.data); + expect(payload.geolocation).to.not.exist; + cleanup(); + }) + }) + } + describe('buildRequest test params', function () { + it('should return test and cpmFactor params if defined', function () { + let clonedBid = JSON.parse(JSON.stringify(bidRequests)); + delete clonedBid[0].params; + clonedBid.splice(1, 1); + clonedBid[0].params = { + 'placementId': '19571277', + 'test': true + } + let requestObject = spec.buildRequests(clonedBid, bidderRequest); + let payload = JSON.parse(requestObject.data); + expect(payload.requests[0].customParams.test).to.exist.and.equal(true); + expect(payload.requests[0].customParams.cpmFactor).to.be.an('undefined'); + + delete clonedBid[0].params; + clonedBid[0].params = { + 'placementId': '19571278', + 'test': true, + 'cpmFactor': 2 + } + requestObject = spec.buildRequests(clonedBid, bidderRequest); + payload = JSON.parse(requestObject.data); + expect(payload.requests[0].customParams.test).to.exist.and.equal(true); + expect(payload.requests[0].customParams.cpmFactor).to.exist.and.equal(2); + }); + }) + }); + + describe('interpretResponse', function () { + let serverResponse = { + 'body': { + 'bidderRequestId': '2a21a2fc993ef9', + 'ads': [{ + 'currency': 'BRL', + 'creativeId': '12334', + 'cpm': 1.9, + 'ttl': 300, + 'netRevenue': false, + 'ad': '', + 'width': 300, + 'height': 250, + 'bidId': '26df49c6447b82', + 'mediaType': 'banner' + }, { + 'currency': 'BRL', + 'creativeId': '12335', + 'cpm': 1.99, + 'ttl': 300, + 'netRevenue': false, + 'ad': '', + 'width': 300, + 'height': 600, + 'bidId': '26df49c6447b82', + 'mediaType': 'banner' + }] + }, + 'headers': {} + }; + let bidRequest = {}; + + it('should return the correct bid response structure', function () { + let expectedResponse = [ + { + 'requestId': '2a21a2fc993ef9', + 'cpm': 1.9, + 'width': 300, + 'height': 250, + 'creativeId': '12335', + 'currency': 'BRL', + 'dealId': null, + 'mediaType': 'banner', + 'netRevenue': false, + 'ttl': 300, + 'ad': '' + } + ]; + let result = spec.interpretResponse(serverResponse, {bidRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('should corretly return an empty array of bidResponses if no ads were received', function () { + let emptyResponse = Object.assign({}, serverResponse); + emptyResponse.body.ads = []; + let result = spec.interpretResponse(emptyResponse, {bidRequest}); + expect(result.length).to.equal(0); + }); + }); + + describe('getUserSyncs', function () { + let syncOptions = { iframeEnabled: true }; + let serverResponses = [{ body: { trackingPixel: 'https://www.uol.com.br' } }, { body: { trackingPixel: 'http://www.dynad.net/' } }]; + + it('should return the two sync params for iframeEnabled bids with a trackingPixel response', function () { + expect(spec.getUserSyncs(syncOptions, serverResponses)).to.have.length(2); + }) + + it('should not return any sync params if iframe is disabled or no trackingPixel is received', function () { + let cloneOptions = Object.assign({}, syncOptions); + delete cloneOptions.iframeEnabled; + expect(spec.getUserSyncs(cloneOptions, serverResponses)).to.have.length(0); + + let cloneResponses = Object.assign({}, serverResponses); + delete cloneResponses[0].body.trackingPixel; + delete cloneResponses[1].body.trackingPixel; + expect(spec.getUserSyncs(syncOptions, cloneResponses)).to.have.length(0); + + expect(spec.getUserSyncs(cloneOptions, cloneResponses)).to.have.length(0); + }) + }); +}); diff --git a/test/spec/modules/vertamediaBidAdapter_spec.js b/test/spec/modules/vertamediaBidAdapter_spec.js index 271f1f2d04a..fefa8e446ed 100644 --- a/test/spec/modules/vertamediaBidAdapter_spec.js +++ b/test/spec/modules/vertamediaBidAdapter_spec.js @@ -96,45 +96,45 @@ const displayEqResponse = [{ cpm: 0.9 }]; -describe('vertamediaBidAdapter', () => { +describe('vertamediaBidAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(VIDEO_REQUEST)).to.equal(12345); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, VIDEO_REQUEST); delete bid.params; expect(spec.isBidRequestValid(bid)).to.equal(undefined); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let videoBidRequests = [VIDEO_REQUEST]; let dispalyBidRequests = [DISPLAY_REQUEST]; const displayRequest = spec.buildRequests(dispalyBidRequests, {}); const videoRequest = spec.buildRequests(videoBidRequests, {}); - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { expect(videoRequest.method).to.equal('GET'); expect(displayRequest.method).to.equal('GET'); }); - it('sends bid request to correct ENDPOINT', () => { + it('sends bid request to correct ENDPOINT', function () { expect(videoRequest.url).to.equal(ENDPOINT); expect(displayRequest.url).to.equal(ENDPOINT); }); - it('sends correct video bid parameters', () => { + it('sends correct video bid parameters', function () { const bid = Object.assign({}, videoRequest.data); delete bid.domain; @@ -148,7 +148,7 @@ describe('vertamediaBidAdapter', () => { expect(bid).to.deep.equal(eq); }); - it('sends correct display bid parameters', () => { + it('sends correct display bid parameters', function () { const bid = Object.assign({}, displayRequest.data); delete bid.domain; @@ -163,18 +163,18 @@ describe('vertamediaBidAdapter', () => { }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let serverResponse; let bidderRequest; let eqResponse; - afterEach(() => { + afterEach(function () { serverResponse = null; bidderRequest = null; eqResponse = null; }); - it('should get correct video bid response', () => { + it('should get correct video bid response', function () { serverResponse = SERVER_VIDEO_RESPONSE; bidderRequest = videoBidderRequest; eqResponse = videoEqResponse; @@ -182,7 +182,7 @@ describe('vertamediaBidAdapter', () => { bidServerResponseCheck(); }); - it('should get correct display bid response', () => { + it('should get correct display bid response', function () { serverResponse = SERVER_DISPLAY_RESPONSE; bidderRequest = displayBidderRequest; eqResponse = displayEqResponse; @@ -203,13 +203,13 @@ describe('vertamediaBidAdapter', () => { expect(noBidResult.length).to.equal(0); } - it('handles video nobid responses', () => { + it('handles video nobid responses', function () { bidderRequest = videoBidderRequest; nobidServerResponseCheck(); }); - it('handles display nobid responses', () => { + it('handles display nobid responses', function () { bidderRequest = displayBidderRequest; nobidServerResponseCheck(); diff --git a/test/spec/modules/vertozBidAdapter_spec.js b/test/spec/modules/vertozBidAdapter_spec.js index a84fc4847f5..1eb85b6b566 100644 --- a/test/spec/modules/vertozBidAdapter_spec.js +++ b/test/spec/modules/vertozBidAdapter_spec.js @@ -4,16 +4,16 @@ import { newBidder } from 'src/adapters/bidderFactory'; const BASE_URI = '//hb.vrtzads.com/vzhbidder/bid?'; -describe('VertozAdapter', () => { +describe('VertozAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'vertoz', 'params': { @@ -26,11 +26,11 @@ describe('VertozAdapter', () => { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -40,7 +40,7 @@ describe('VertozAdapter', () => { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'vertoz', @@ -55,14 +55,14 @@ describe('VertozAdapter', () => { } ]; - it('sends bid request to ENDPOINT via POST', () => { + it('sends bid request to ENDPOINT via POST', function () { const request = spec.buildRequests(bidRequests)[0]; expect(request.url).to.equal(BASE_URI); expect(request.method).to.equal('POST'); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { 'vzhPlacementId': 'VZ-HB-B784382V6C6G3C', 'bid': '76021e56-adaf-4114-b68d-ccacd1b3e551_1', @@ -75,7 +75,7 @@ describe('VertozAdapter', () => { 'statusText': 'Vertoz:Success' }; - it('should get correct bid response', () => { + it('should get correct bid response', function () { let expectedResponse = [ { 'requestId': '44b3fcfd24aa93', @@ -97,7 +97,7 @@ describe('VertozAdapter', () => { expect(result[0].cpm).to.not.equal(null); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let response = { 'vzhPlacementId': 'VZ-HB-I617046VBGE3EH', 'slotBidId': 'f00412ac86b79', diff --git a/test/spec/modules/viBidAdapter_spec.js b/test/spec/modules/viBidAdapter_spec.js index e8b0fbcc4b2..2468da0cfaf 100644 --- a/test/spec/modules/viBidAdapter_spec.js +++ b/test/spec/modules/viBidAdapter_spec.js @@ -7,7 +7,7 @@ const ENDPOINT = `//pb.vi-serve.com/prebid/bid`; describe('viBidAdapter', function() { newBidder(spec); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'vi', 'params': { @@ -27,17 +27,17 @@ describe('viBidAdapter', function() { 'transactionId': '474da635-9cf0-4188-a3d9-58961be8f905' }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when pubId not passed', () => { + it('should return false when pubId not passed', function () { bid.params.pubId = undefined; expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [{ 'bidder': 'vi', 'params': { @@ -59,16 +59,16 @@ describe('viBidAdapter', function() { const request = spec.buildRequests(bidRequests); - it('POST bid request to vi', () => { + it('POST bid request to vi', function () { expect(request.method).to.equal('POST'); }); - it('check endpoint URL', () => { + it('check endpoint URL', function () { expect(request.url).to.equal(ENDPOINT) }); }); - describe('buildRequests can handle size in 1-dim array', () => { + describe('buildRequests can handle size in 1-dim array', function () { let bidRequests = [{ 'bidder': 'vi', 'params': { @@ -88,16 +88,16 @@ describe('viBidAdapter', function() { const request = spec.buildRequests(bidRequests); - it('POST bid request to vi', () => { + it('POST bid request to vi', function () { expect(request.method).to.equal('POST'); }); - it('check endpoint URL', () => { + it('check endpoint URL', function () { expect(request.url).to.equal(ENDPOINT) }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let response = { body: [{ 'id': '29b891ad542377', @@ -109,7 +109,7 @@ describe('viBidAdapter', function() { }] }; - it('should get the correct bid response', () => { + it('should get the correct bid response', function () { let expectedResponse = [{ 'requestId': '29b891ad542377', 'cpm': 0.1, @@ -128,7 +128,7 @@ describe('viBidAdapter', function() { expect(Object.keys(result[0])).to.deep.equal(Object.keys(expectedResponse[0])); }); - it('handles empty bid response', () => { + it('handles empty bid response', function () { let response = { body: [] }; diff --git a/test/spec/modules/vidazooBidAdapter_spec.js b/test/spec/modules/vidazooBidAdapter_spec.js index d88e5a718ed..d9c08ad924c 100644 --- a/test/spec/modules/vidazooBidAdapter_spec.js +++ b/test/spec/modules/vidazooBidAdapter_spec.js @@ -1,6 +1,7 @@ import {expect} from 'chai'; import {spec as adapter, URL} from 'modules/vidazooBidAdapter'; import * as utils from 'src/utils'; + const BID = { 'bidId': '2d52001cabd527', 'params': { @@ -19,6 +20,12 @@ const BID = { 'requestId': 'b0777d85-d061-450e-9bc7-260dd54bbb7a' }; +const BIDDER_REQUEST = { + 'gdprConsent': { + 'consentString': 'consent_string' + } +}; + const SERVER_RESPONSE = { body: { 'ad': '', @@ -47,31 +54,31 @@ const SYNC_OPTIONS = { 'pixelEnabled': true }; -describe('VidazooBidAdapter', () => { - describe('validtae spec', () => { - it('exists and is a function', () => { +describe('VidazooBidAdapter', function () { + describe('validtae spec', function () { + it('exists and is a function', function () { expect(adapter.isBidRequestValid).to.exist.and.to.be.a('function'); }); - it('exists and is a function', () => { + it('exists and is a function', function () { expect(adapter.buildRequests).to.exist.and.to.be.a('function'); }); - it('exists and is a function', () => { + it('exists and is a function', function () { expect(adapter.interpretResponse).to.exist.and.to.be.a('function'); }); - it('exists and is a function', () => { + it('exists and is a function', function () { expect(adapter.getUserSyncs).to.exist.and.to.be.a('function'); }); - it('exists and is a string', () => { + it('exists and is a string', function () { expect(adapter.code).to.exist.and.to.be.a('string'); }); }); - describe('validate bid requests', () => { - it('should require cId', () => { + describe('validate bid requests', function () { + it('should require cId', function () { const isValid = adapter.isBidRequestValid({ params: { pId: 'pid' @@ -80,7 +87,7 @@ describe('VidazooBidAdapter', () => { expect(isValid).to.be.false; }); - it('should require pId', () => { + it('should require pId', function () { const isValid = adapter.isBidRequestValid({ params: { cId: 'cid' @@ -89,7 +96,7 @@ describe('VidazooBidAdapter', () => { expect(isValid).to.be.false; }); - it('should validate correctly', () => { + it('should validate correctly', function () { const isValid = adapter.isBidRequestValid({ params: { cId: 'cid', @@ -100,21 +107,22 @@ describe('VidazooBidAdapter', () => { }); }); - describe('build requests', () => { + describe('build requests', function () { let sandbox; - before(() => { + before(function () { sandbox = sinon.sandbox.create(); sandbox.stub(utils, 'getTopWindowUrl').returns('http://www.greatsite.com'); sandbox.stub(Date, 'now').returns(1000); }); - it('should build request for each size', () => { - const requests = adapter.buildRequests([BID]); + it('should build request for each size', function () { + const requests = adapter.buildRequests([BID], BIDDER_REQUEST); expect(requests).to.have.length(2); expect(requests[0]).to.deep.equal({ method: 'GET', url: `${URL}/prebid/59db6b3b4ffaa70004f45cdc`, data: { + consent: 'consent_string', width: '300', height: '250', url: 'http://www.greatsite.com', @@ -130,6 +138,7 @@ describe('VidazooBidAdapter', () => { method: 'GET', url: `${URL}/prebid/59db6b3b4ffaa70004f45cdc`, data: { + consent: 'consent_string', width: '300', height: '600', url: 'http://www.greatsite.com', @@ -143,28 +152,28 @@ describe('VidazooBidAdapter', () => { }); }); - after(() => { + after(function () { sandbox.restore(); }); }); - describe('interpret response', () => { - it('should return empty array when there is no response', () => { + describe('interpret response', function () { + it('should return empty array when there is no response', function () { const responses = adapter.interpretResponse(null); expect(responses).to.be.empty; }); - it('should return empty array when there is no ad', () => { + it('should return empty array when there is no ad', function () { const responses = adapter.interpretResponse({price: 1, ad: ''}); expect(responses).to.be.empty; }); - it('should return empty array when there is no price', () => { + it('should return empty array when there is no price', function () { const responses = adapter.interpretResponse({price: null, ad: 'great ad'}); expect(responses).to.be.empty; }); - it('should return an array of interpreted responses', () => { + it('should return an array of interpreted responses', function () { const responses = adapter.interpretResponse(SERVER_RESPONSE, REQUEST); expect(responses).to.have.length(1); expect(responses[0]).to.deep.equal({ @@ -180,7 +189,7 @@ describe('VidazooBidAdapter', () => { }); }); - it('should take default TTL', () => { + it('should take default TTL', function () { const serverResponse = utils.deepClone(SERVER_RESPONSE); delete serverResponse.body.exp; const responses = adapter.interpretResponse(serverResponse, REQUEST); diff --git a/test/spec/modules/visxBidAdapter_spec.js b/test/spec/modules/visxBidAdapter_spec.js index 20b056adf6d..bf8d4cc7d13 100755 --- a/test/spec/modules/visxBidAdapter_spec.js +++ b/test/spec/modules/visxBidAdapter_spec.js @@ -6,13 +6,13 @@ import { newBidder } from 'src/adapters/bidderFactory'; describe('VisxAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'visx', 'params': { @@ -25,11 +25,11 @@ describe('VisxAdapter', function () { 'auctionId': '1d1a030790a475', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { let bid = Object.assign({}, bid); delete bid.params; bid.params = { @@ -39,7 +39,7 @@ describe('VisxAdapter', function () { }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'visx', @@ -76,7 +76,7 @@ describe('VisxAdapter', function () { } ]; - it('should attach valid params to the tag', () => { + it('should attach valid params to the tag', function () { const request = spec.buildRequests([bidRequests[0]]); const payload = request.data; expect(payload).to.be.an('object'); @@ -87,7 +87,7 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('cur', 'EUR'); }); - it('auids must not be duplicated', () => { + it('auids must not be duplicated', function () { const request = spec.buildRequests(bidRequests); const payload = request.data; expect(payload).to.be.an('object'); @@ -98,7 +98,7 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('cur', 'EUR'); }); - it('pt parameter must be "gross" if params.priceType === "gross"', () => { + it('pt parameter must be "gross" if params.priceType === "gross"', function () { bidRequests[1].params.priceType = 'gross'; const request = spec.buildRequests(bidRequests); const payload = request.data; @@ -111,7 +111,7 @@ describe('VisxAdapter', function () { delete bidRequests[1].params.priceType; }); - it('pt parameter must be "net" or "gross"', () => { + it('pt parameter must be "net" or "gross"', function () { bidRequests[1].params.priceType = 'some'; const request = spec.buildRequests(bidRequests); const payload = request.data; @@ -123,7 +123,7 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('cur', 'EUR'); delete bidRequests[1].params.priceType; }); - it('should add currency from currency.bidderCurrencyDefault', () => { + it('should add currency from currency.bidderCurrencyDefault', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'currency.bidderCurrencyDefault.visx' ? 'JPY' : 'USD'); const request = spec.buildRequests(bidRequests); @@ -136,7 +136,7 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('cur', 'JPY'); getConfigStub.restore(); }); - it('should add currency from currency.adServerCurrency', () => { + it('should add currency from currency.adServerCurrency', function () { const getConfigStub = sinon.stub(config, 'getConfig').callsFake( arg => arg === 'currency.bidderCurrencyDefault.visx' ? '' : 'USD'); const request = spec.buildRequests(bidRequests); @@ -149,9 +149,32 @@ describe('VisxAdapter', function () { expect(payload).to.have.property('cur', 'USD'); getConfigStub.restore(); }); + it('if gdprConsent is present payload must have gdpr params', function () { + const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: true}}); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('gdpr_consent', 'AAA'); + expect(payload).to.have.property('gdpr_applies', 1); + }); + + it('if gdprApplies is false gdpr_applies must be 0', function () { + const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA', gdprApplies: false}}); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('gdpr_consent', 'AAA'); + expect(payload).to.have.property('gdpr_applies', 0); + }); + + it('if gdprApplies is undefined gdpr_applies must be 1', function () { + const request = spec.buildRequests(bidRequests, {gdprConsent: {consentString: 'AAA'}}); + const payload = request.data; + expect(payload).to.be.an('object'); + expect(payload).to.have.property('gdpr_consent', 'AAA'); + expect(payload).to.have.property('gdpr_applies', 1); + }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { const responses = [ {'bid': [{'price': 1.15, 'adm': '
test content 1
', 'auid': 903535, 'h': 250, 'w': 300}], 'seat': '1'}, {'bid': [{'price': 0.5, 'adm': '
test content 2
', 'auid': 903536, 'h': 90, 'w': 728}], 'seat': '1'}, @@ -162,7 +185,7 @@ describe('VisxAdapter', function () { {'seat': '1'}, ]; - it('should get correct bid response', () => { + it('should get correct bid response', function () { const bidRequests = [ { 'bidder': 'visx', @@ -196,7 +219,7 @@ describe('VisxAdapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should get correct multi bid response', () => { + it('should get correct multi bid response', function () { const bidRequests = [ { 'bidder': 'visx', @@ -276,7 +299,7 @@ describe('VisxAdapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should return right currency', () => { + it('should return right currency', function () { const bidRequests = [ { 'bidder': 'visx', @@ -312,7 +335,7 @@ describe('VisxAdapter', function () { getConfigStub.restore(); }); - it('handles wrong and nobid responses', () => { + it('handles wrong and nobid responses', function () { const bidRequests = [ { 'bidder': 'visx', diff --git a/test/spec/modules/vubleAnalyticsAdapter_spec.js b/test/spec/modules/vubleAnalyticsAdapter_spec.js index 896f6e4ee87..fe84c0a6b04 100644 --- a/test/spec/modules/vubleAnalyticsAdapter_spec.js +++ b/test/spec/modules/vubleAnalyticsAdapter_spec.js @@ -6,21 +6,21 @@ let constants = require('src/constants.json'); describe('Vuble Prebid Analytic', function () { let xhr; - before(() => { + before(function () { xhr = sinon.useFakeXMLHttpRequest(); }); - after(() => { + after(function () { vubleAnalytics.disableAnalytics(); xhr.restore(); }); describe('enableAnalytics', function () { - beforeEach(() => { + beforeEach(function () { sinon.spy(vubleAnalytics, 'track'); sinon.stub(events, 'getEvents').returns([]); }); - afterEach(() => { + afterEach(function () { vubleAnalytics.track.restore(); events.getEvents.restore(); }); diff --git a/test/spec/modules/vubleBidAdapter_spec.js b/test/spec/modules/vubleBidAdapter_spec.js index 6d266ca465e..8996c1b4957 100644 --- a/test/spec/modules/vubleBidAdapter_spec.js +++ b/test/spec/modules/vubleBidAdapter_spec.js @@ -4,23 +4,23 @@ import {expect} from 'chai'; import {spec as adapter} from 'modules/vubleBidAdapter'; import * as utils from 'src/utils'; -describe('VubleAdapter', () => { - describe('Check methods existance', () => { - it('exists and is a function', () => { +describe('VubleAdapter', function () { + describe('Check methods existance', function () { + it('exists and is a function', function () { expect(adapter.isBidRequestValid).to.exist.and.to.be.a('function'); }); - it('exists and is a function', () => { + it('exists and is a function', function () { expect(adapter.buildRequests).to.exist.and.to.be.a('function'); }); - it('exists and is a function', () => { + it('exists and is a function', function () { expect(adapter.interpretResponse).to.exist.and.to.be.a('function'); }); - it('exists and is a function', () => { + it('exists and is a function', function () { expect(adapter.getUserSyncs).to.exist.and.to.be.a('function'); }); }); - describe('Check method isBidRequestValid return', () => { + describe('Check method isBidRequestValid return', function () { let bid = { bidder: 'vuble', params: { @@ -37,11 +37,11 @@ describe('VubleAdapter', () => { }, }; - it('should be true', () => { + it('should be true', function () { expect(adapter.isBidRequestValid(bid)).to.be.true; }); - it('should be false because the sizes are missing or in the wrong format', () => { + it('should be false because the sizes are missing or in the wrong format', function () { let wrongBid = utils.deepClone(bid); wrongBid.sizes = '640360'; expect(adapter.isBidRequestValid(wrongBid)).to.be.false; @@ -51,7 +51,7 @@ describe('VubleAdapter', () => { expect(adapter.isBidRequestValid(wrongBid)).to.be.false; }); - it('should be false because the mediaType is missing or wrong', () => { + it('should be false because the mediaType is missing or wrong', function () { let wrongBid = utils.deepClone(bid); wrongBid.mediaTypes = {}; expect(adapter.isBidRequestValid(wrongBid)).to.be.false; @@ -61,7 +61,7 @@ describe('VubleAdapter', () => { expect(adapter.isBidRequestValid(wrongBid)).to.be.false; }); - it('should be false because the env is missing or wrong', () => { + it('should be false because the env is missing or wrong', function () { let wrongBid = utils.deepClone(bid); wrongBid.params.env = 'us'; expect(adapter.isBidRequestValid(wrongBid)).to.be.false; @@ -71,22 +71,22 @@ describe('VubleAdapter', () => { expect(adapter.isBidRequestValid(wrongBid)).to.be.false; }); - it('should be false because params.pubId is missing', () => { + it('should be false because params.pubId is missing', function () { let wrongBid = utils.deepClone(bid); delete wrongBid.params.pubId; expect(adapter.isBidRequestValid(wrongBid)).to.be.false; }); - it('should be false because params.zoneId is missing', () => { + it('should be false because params.zoneId is missing', function () { let wrongBid = utils.deepClone(bid); delete wrongBid.params.zoneId; expect(adapter.isBidRequestValid(wrongBid)).to.be.false; }); }); - describe('Check buildRequests method', () => { + describe('Check buildRequests method', function () { let sandbox; - before(() => { + before(function () { sandbox = sinon.sandbox.create(); sandbox.stub(utils, 'getTopWindowUrl').returns('http://www.vuble.tv/'); }); @@ -161,17 +161,17 @@ describe('VubleAdapter', () => { } }; - it('must return the right formatted requests', () => { + it('must return the right formatted requests', function () { let rs = adapter.buildRequests([bid1, bid2]); expect(adapter.buildRequests([bid1, bid2])).to.deep.equal([request1, request2]); }); - after(() => { + after(function () { sandbox.restore(); }); }); - describe('Check interpretResponse method return', () => { + describe('Check interpretResponse method return', function () { // Server's response let response = { body: { @@ -213,11 +213,11 @@ describe('VubleAdapter', () => { mediaType: 'video' }; - it('should equal to the expected formatted result', () => { + it('should equal to the expected formatted result', function () { expect(adapter.interpretResponse(response, bid)).to.deep.equal([result]); }); - it('should be empty because the status is missing or wrong', () => { + it('should be empty because the status is missing or wrong', function () { let wrongResponse = utils.deepClone(response); wrongResponse.body.status = 'ko'; expect(adapter.interpretResponse(wrongResponse, bid)).to.be.empty; @@ -227,7 +227,7 @@ describe('VubleAdapter', () => { expect(adapter.interpretResponse(wrongResponse, bid)).to.be.empty; }); - it('should be empty because the body is missing or wrong', () => { + it('should be empty because the body is missing or wrong', function () { let wrongResponse = utils.deepClone(response); wrongResponse.body = [1, 2, 3]; expect(adapter.interpretResponse(wrongResponse, bid)).to.be.empty; @@ -237,7 +237,7 @@ describe('VubleAdapter', () => { expect(adapter.interpretResponse(wrongResponse, bid)).to.be.empty; }); - it('should equal to the expected formatted result', () => { + it('should equal to the expected formatted result', function () { response.body.renderer_url = 'vuble_renderer.js'; result.adUnitCode = 'code'; let formattedResponses = adapter.interpretResponse(response, bid); @@ -245,7 +245,7 @@ describe('VubleAdapter', () => { }); }); - describe('Check getUserSyncs method return', () => { + describe('Check getUserSyncs method return', function () { // Sync options let syncOptions = { iframeEnabled: false @@ -265,7 +265,7 @@ describe('VubleAdapter', () => { url: 'http://player.mediabong.net/csifr?1234' }; - it('should return an empty array', () => { + it('should return an empty array', function () { expect(adapter.getUserSyncs({}, [])).to.be.empty; expect(adapter.getUserSyncs({}, [])).to.be.empty; expect(adapter.getUserSyncs(syncOptions, [response])).to.be.empty; @@ -275,7 +275,7 @@ describe('VubleAdapter', () => { expect(adapter.getUserSyncs(syncOptions, [response])).to.be.empty; }); - it('should be equal to the expected result', () => { + it('should be equal to the expected result', function () { response.body.iframeSync = 'http://player.mediabong.net/csifr?1234'; expect(adapter.getUserSyncs(syncOptions, [response])).to.deep.equal([result]); }) diff --git a/test/spec/modules/weboramaBidAdapter_spec.js b/test/spec/modules/weboramaBidAdapter_spec.js new file mode 100644 index 00000000000..d0b119825a6 --- /dev/null +++ b/test/spec/modules/weboramaBidAdapter_spec.js @@ -0,0 +1,118 @@ +import {expect} from 'chai'; +import {spec} from '../../../modules/weboramaBidAdapter'; + +describe('WeboramaAdapter', function () { + let bid = { + bidId: '2dd581a2b6281d', + bidder: 'weborama', + bidderRequestId: '145e1d6a7837c9', + params: { + placementId: 123, + traffic: 'banner' + }, + placementCode: 'placement_0', + auctionId: '74f78609-a92d-4cf1-869f-1b244bbfb5d2', + sizes: [[300, 250]], + transactionId: '3bb2f6da-87a6-4029-aeb0-bfe951372e62' + }; + + describe('isBidRequestValid', function () { + it('Should return true when placementId can be cast to a number', function () { + expect(spec.isBidRequestValid(bid)).to.be.true; + }); + it('Should return false when placementId is not a number', function () { + bid.params.placementId = 'aaa'; + expect(spec.isBidRequestValid(bid)).to.be.false; + }); + }); + + describe('buildRequests', function () { + let serverRequest = spec.buildRequests([bid]); + it('Creates a ServerRequest object with method, URL and data', function () { + expect(serverRequest).to.exist; + expect(serverRequest.method).to.exist; + expect(serverRequest.url).to.exist; + expect(serverRequest.data).to.exist; + }); + it('Returns POST method', function () { + expect(serverRequest.method).to.equal('POST'); + }); + it('Returns valid URL', function () { + expect(serverRequest.url).to.equal('//supply.nl.weborama.fr/?c=o&m=multi'); + }); + it('Returns valid data if array of bids is valid', function () { + let data = serverRequest.data; + expect(data).to.be.an('object'); + expect(data).to.have.all.keys('deviceWidth', 'deviceHeight', 'secure', 'host', 'page', 'placements'); + expect(data.deviceWidth).to.be.a('number'); + expect(data.deviceHeight).to.be.a('number'); + expect(data.secure).to.be.within(0, 1); + expect(data.host).to.be.a('string'); + expect(data.page).to.be.a('string'); + let placements = data['placements']; + for (let i = 0; i < placements.length; i++) { + let placement = placements[i]; + expect(placement).to.have.all.keys('placementId', 'bidId', 'traffic', 'sizes'); + expect(placement.placementId).to.be.a('number'); + expect(placement.bidId).to.be.a('string'); + expect(placement.traffic).to.be.a('string'); + expect(placement.sizes).to.be.an('array'); + } + }); + it('Returns empty data if no valid requests are passed', function () { + serverRequest = spec.buildRequests([]); + let data = serverRequest.data; + expect(data.placements).to.be.an('array').that.is.empty; + }); + }); + describe('interpretResponse', function () { + let resObject = { + body: [ { + requestId: '123', + mediaType: 'banner', + cpm: 0.3, + width: 320, + height: 50, + ad: '

Hello ad

', + ttl: 1000, + creativeId: '123asd', + netRevenue: true, + currency: 'USD' + } ] + }; + let serverResponses = spec.interpretResponse(resObject); + it('Returns an array of valid server responses if response object is valid', function () { + expect(serverResponses).to.be.an('array').that.is.not.empty; + for (let i = 0; i < serverResponses.length; i++) { + let dataItem = serverResponses[i]; + expect(dataItem).to.have.all.keys('requestId', 'cpm', 'width', 'height', 'ad', 'ttl', 'creativeId', + 'netRevenue', 'currency', 'mediaType'); + expect(dataItem.requestId).to.be.a('string'); + expect(dataItem.cpm).to.be.a('number'); + expect(dataItem.width).to.be.a('number'); + expect(dataItem.height).to.be.a('number'); + expect(dataItem.ad).to.be.a('string'); + expect(dataItem.ttl).to.be.a('number'); + expect(dataItem.creativeId).to.be.a('string'); + expect(dataItem.netRevenue).to.be.a('boolean'); + expect(dataItem.currency).to.be.a('string'); + expect(dataItem.mediaType).to.be.a('string'); + } + it('Returns an empty array if invalid response is passed', function () { + serverResponses = spec.interpretResponse('invalid_response'); + expect(serverResponses).to.be.an('array').that.is.empty; + }); + }); + }); + + describe('getUserSyncs', function () { + let userSync = spec.getUserSyncs(); + it('Returns valid URL and `', function () { + expect(userSync).to.be.an('array').with.lengthOf(1); + expect(userSync[0].type).to.exist; + expect(userSync[0].url).to.exist; + expect(userSync[0].type).to.be.equal('image'); + expect(userSync[0].url).to.be.equal('//supply.nl.weborama.fr/?c=o&m=cookie'); + }); + }); +}); diff --git a/test/spec/modules/widespaceBidAdapter_spec.js b/test/spec/modules/widespaceBidAdapter_spec.js index 81d2528465e..dc0d547d47a 100644 --- a/test/spec/modules/widespaceBidAdapter_spec.js +++ b/test/spec/modules/widespaceBidAdapter_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import { spec } from 'modules/widespaceBidAdapter'; import includes from 'core-js/library/fn/array/includes'; -describe('+widespaceAdatperTest', () => { +describe('+widespaceAdatperTest', function () { // Dummy bid request const bidRequest = [{ 'adUnitCode': 'div-gpt-ad-1460505748561-0', @@ -110,8 +110,8 @@ describe('+widespaceAdatperTest', () => { navigator.connection.type = 'wifi'; } - describe('+bidRequestValidity', () => { - it('bidRequest with sid and currency params', () => { + describe('+bidRequestValidity', function () { + it('bidRequest with sid and currency params', function () { expect(spec.isBidRequestValid({ bidder: 'widespace', params: { @@ -121,7 +121,7 @@ describe('+widespaceAdatperTest', () => { })).to.equal(true); }); - it('-bidRequest with missing sid', () => { + it('-bidRequest with missing sid', function () { expect(spec.isBidRequestValid({ bidder: 'widespace', params: { @@ -130,7 +130,7 @@ describe('+widespaceAdatperTest', () => { })).to.equal(false); }); - it('-bidRequest with missing currency', () => { + it('-bidRequest with missing currency', function () { expect(spec.isBidRequestValid({ bidder: 'widespace', params: { @@ -140,37 +140,37 @@ describe('+widespaceAdatperTest', () => { }); }); - describe('+bidRequest', () => { + describe('+bidRequest', function () { const request = spec.buildRequests(bidRequest, bidderRequest); const UrlRegExp = /^((ftp|http|https):)?\/\/[^ "]+$/; - it('-bidRequest method is POST', () => { + it('-bidRequest method is POST', function () { expect(request[0].method).to.equal('POST'); }); - it('-bidRequest url is valid', () => { + it('-bidRequest url is valid', function () { expect(UrlRegExp.test(request[0].url)).to.equal(true); }); - it('-bidRequest data exist', () => { + it('-bidRequest data exist', function () { expect(request[0].data).to.exists; }); - it('-bidRequest data is form data', () => { + it('-bidRequest data is form data', function () { expect(typeof request[0].data).to.equal('string'); }); - it('-bidRequest options have header type', () => { + it('-bidRequest options have header type', function () { expect(request[0].options.contentType).to.exists; }); - it('-cookie test for wsCustomData ', () => { + it('-cookie test for wsCustomData ', function () { expect(request[0].data.indexOf('hb.cd') > -1).to.equal(true); }); }); - describe('+interpretResponse', () => { - it('-required params available in response', () => { + describe('+interpretResponse', function () { + it('-required params available in response', function () { const result = spec.interpretResponse(bidResponse, bidRequest); let requiredKeys = [ 'requestId', @@ -201,19 +201,19 @@ describe('+widespaceAdatperTest', () => { }); }); - it('-empty result if noad responded', () => { + it('-empty result if noad responded', function () { const noAdResult = spec.interpretResponse(bidResponseNoAd, bidRequest); expect(noAdResult.length).to.equal(0); }); - it('-empty response should not breake anything in adapter', () => { + it('-empty response should not breake anything in adapter', function () { const noResponse = spec.interpretResponse({}, bidRequest); expect(noResponse.length).to.equal(0); }); }); - describe('+getUserSyncs', () => { - it('-always return an array', () => { + describe('+getUserSyncs', function () { + it('-always return an array', function () { const userSync_test1 = spec.getUserSyncs({}, [bidResponse]); expect(Array.isArray(userSync_test1)).to.equal(true); diff --git a/test/spec/modules/xendizBidAdapter_spec.js b/test/spec/modules/xendizBidAdapter_spec.js index 66b9dc62b88..4d1aa3c935f 100644 --- a/test/spec/modules/xendizBidAdapter_spec.js +++ b/test/spec/modules/xendizBidAdapter_spec.js @@ -34,39 +34,39 @@ const bidResponse = { const noBidResponse = { body: { id: '1d1a030790a475', bids: [] } }; -describe('xendizBidAdapter', () => { +describe('xendizBidAdapter', function () { const adapter = newBidder(spec); - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); }); - describe('isBidRequestValid', () => { - it('should return false', () => { + describe('isBidRequestValid', function () { + it('should return false', function () { let bid = Object.assign({}, bidRequest); bid.params = {}; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return true', () => { + it('should return true', function () { expect(spec.isBidRequestValid(bidRequest)).to.equal(true); }); }); - describe('buildRequests', () => { - it('should format valid url', () => { + describe('buildRequests', function () { + it('should format valid url', function () { const request = spec.buildRequests([bidRequest]); expect(request.url).to.equal(VALID_ENDPOINT); }); - it('should format valid url', () => { + it('should format valid url', function () { const request = spec.buildRequests([bidRequest]); expect(request.url).to.equal(VALID_ENDPOINT); }); - it('should format valid request body', () => { + it('should format valid request body', function () { const request = spec.buildRequests([bidRequest]); const payload = JSON.parse(request.data); expect(payload.id).to.exist; @@ -74,7 +74,7 @@ describe('xendizBidAdapter', () => { expect(payload.device).to.exist; }); - it('should attach valid device info', () => { + it('should attach valid device info', function () { const request = spec.buildRequests([bidRequest]); const payload = JSON.parse(request.data); expect(payload.device).to.deep.equal([ @@ -84,7 +84,7 @@ describe('xendizBidAdapter', () => { ]); }); - it('should transform sizes', () => { + it('should transform sizes', function () { const request = spec.buildRequests([bidRequest]); const payload = JSON.parse(request.data); const item = payload.items[0]; @@ -92,8 +92,8 @@ describe('xendizBidAdapter', () => { }); }); - describe('interpretResponse', () => { - it('should get correct bid response', () => { + describe('interpretResponse', function () { + it('should get correct bid response', function () { const result = spec.interpretResponse(bidResponse); const validResponse = [{ requestId: '30b31c1838de1e', @@ -111,7 +111,7 @@ describe('xendizBidAdapter', () => { expect(result).to.deep.equal(validResponse); }); - it('handles nobid responses', () => { + it('handles nobid responses', function () { let result = spec.interpretResponse(noBidResponse); expect(result.length).to.equal(0); }); diff --git a/test/spec/modules/xhbBidAdapter_spec.js b/test/spec/modules/xhbBidAdapter_spec.js new file mode 100644 index 00000000000..e48d3011ed2 --- /dev/null +++ b/test/spec/modules/xhbBidAdapter_spec.js @@ -0,0 +1,495 @@ +import { expect } from 'chai'; +import { spec } from 'modules/xhbBidAdapter'; +import { newBidder } from 'src/adapters/bidderFactory'; +import { deepClone } from 'src/utils'; + +const ENDPOINT = '//ib.adnxs.com/ut/v3/prebid'; + +describe('xhbAdapter', function () { + 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 () { + let bid = { + 'bidder': 'xhb', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + }; + + it('should return true when required params found', function () { + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return true when required params found', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'member': '1234', + 'invCode': 'ABCD' + }; + + expect(spec.isBidRequestValid(bid)).to.equal(true); + }); + + it('should return false when required params are not passed', function () { + let bid = Object.assign({}, bid); + delete bid.params; + bid.params = { + 'placementId': 0 + }; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', function () { + let bidRequests = [ + { + 'bidder': 'xhb', + 'params': { + 'placementId': '10433394' + }, + 'adUnitCode': 'adunit-code', + 'sizes': [[300, 250], [300, 600]], + 'bidId': '30b31c1838de1e', + 'bidderRequestId': '22edbae2733bf6', + 'auctionId': '1d1a030790a475', + } + ]; + + it('should parse out private sizes', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + privateSizes: [300, 250] + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].private_sizes).to.exist; + expect(payload.tags[0].private_sizes).to.deep.equal([{width: 300, height: 250}]); + }); + + it('should add source and verison to the tag', function () { + const request = spec.buildRequests(bidRequests); + const payload = JSON.parse(request.data); + expect(payload.sdk).to.exist; + expect(payload.sdk).to.deep.equal({ + source: 'pbjs', + version: '$prebid.version$' + }); + }); + + it('should populate the ad_types array on all requests', function () { + ['banner', 'video', 'native'].forEach(type => { + const bidRequest = Object.assign({}, bidRequests[0]); + bidRequest.mediaTypes = {}; + bidRequest.mediaTypes[type] = {}; + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].ad_types).to.deep.equal([type]); + }); + }); + + it('should populate the ad_types array on outstream requests', function () { + const bidRequest = Object.assign({}, bidRequests[0]); + bidRequest.mediaTypes = {}; + bidRequest.mediaTypes.video = {context: 'outstream'}; + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].ad_types).to.deep.equal(['video']); + }); + + it('sends bid request to ENDPOINT via POST', function () { + const request = spec.buildRequests(bidRequests); + expect(request.url).to.equal(ENDPOINT); + expect(request.method).to.equal('POST'); + }); + + it('should attach valid video params to the tag', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + video: { + id: 123, + minduration: 100, + foobar: 'invalid' + } + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + expect(payload.tags[0].video).to.deep.equal({ + id: 123, + minduration: 100 + }); + }); + + it('should attach valid user params to the tag', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + user: { + external_uid: '123', + foobar: 'invalid' + } + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.user).to.exist; + expect(payload.user).to.deep.equal({ + external_uid: '123', + }); + }); + + it('should attach native params to the request', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + title: {required: true}, + body: {required: true}, + image: {required: true, sizes: [{ width: 100, height: 100 }]}, + cta: {required: false}, + sponsoredBy: {required: true} + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ + title: {required: true}, + description: {required: true}, + main_image: {required: true, sizes: [{ width: 100, height: 100 }]}, + ctatext: {required: false}, + sponsored_by: {required: true} + }); + }); + + it('sets minimum native asset params when not provided on adunit', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + image: {required: true}, + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ + main_image: {required: true, sizes: [{}]}, + }); + }); + + it('does not overwrite native ad unit params with mimimum params', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + mediaType: 'native', + nativeParams: { + image: { + aspect_ratios: [{ + min_width: 100, + ratio_width: 2, + ratio_height: 3, + }] + } + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].native.layouts[0]).to.deep.equal({ + main_image: { + required: true, + aspect_ratios: [{ + min_width: 100, + ratio_width: 2, + ratio_height: 3, + }] + }, + }); + }); + + it('should convert keyword params to proper form and attaches to request', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + keywords: { + single: 'val', + singleArr: ['val'], + singleArrNum: [5], + multiValMixed: ['value1', 2, 'value3'], + singleValNum: 123, + badValue: {'foo': 'bar'} // should be dropped + } + } + } + ); + + 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'] + }]); + }); + + it('should add payment rules to the request', function () { + let bidRequest = Object.assign({}, + bidRequests[0], + { + params: { + placementId: '10433394', + usePaymentRule: true + } + } + ); + + const request = spec.buildRequests([bidRequest]); + const payload = JSON.parse(request.data); + + expect(payload.tags[0].use_pmt_rule).to.equal(true); + }); + + it('should add gdpr consent information to the request', function () { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + let bidderRequest = { + 'bidderCode': 'xhb', + 'auctionId': '1d1a030790a475', + 'bidderRequestId': '22edbae2733bf6', + 'timeout': 3000, + 'gdprConsent': { + consentString: consentString, + gdprApplies: true + } + }; + bidderRequest.bids = bidRequests; + + const request = spec.buildRequests(bidRequests, bidderRequest); + const payload = JSON.parse(request.data); + + expect(payload.gdpr_consent).to.exist; + expect(payload.gdpr_consent.consent_string).to.exist.and.to.equal(consentString); + expect(payload.gdpr_consent.consent_required).to.exist.and.to.be.true; + }); + }); + + describe('interpretResponse', function () { + let response = { + 'version': '3.0.0', + 'tags': [ + { + 'uuid': '3db3773286ee59', + 'tag_id': 10433394, + 'auction_id': '4534722592064951574', + 'nobid': false, + 'no_ad_url': 'http://lax1-ib.adnxs.com/no-ad', + 'timeout_ms': 10000, + 'ad_profile_id': 27079, + 'ads': [ + { + 'content_source': 'rtb', + 'ad_type': 'banner', + 'buyer_member_id': 958, + 'creative_id': 29681110, + 'media_type_id': 1, + 'media_subtype_id': 1, + 'cpm': 0.5, + 'cpm_publisher_currency': 0.5, + 'publisher_currency_code': '$', + 'client_initiated_ad_counting': true, + 'rtb': { + 'banner': { + 'content': '', + 'width': 300, + 'height': 250 + }, + 'trackers': [ + { + 'impression_urls': [ + 'http://lax1-ib.adnxs.com/impression' + ], + 'video_events': {} + } + ] + } + } + ] + } + ] + }; + + it('should get correct bid response', function () { + let expectedResponse = [ + { + 'requestId': '3db3773286ee59', + 'cpm': 0.5, + 'creativeId': 29681110, + 'dealId': undefined, + 'width': 300, + 'height': 250, + 'ad': '', + 'mediaType': 'banner', + 'currency': 'USD', + 'ttl': 300, + 'netRevenue': true, + 'appnexus': { + 'buyerMemberId': 958 + } + } + ]; + let bidderRequest; + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0])); + }); + + it('handles nobid responses', function () { + let response = { + 'version': '0.0.1', + 'tags': [{ + 'uuid': '84ab500420319d', + 'tag_id': 5976557, + 'auction_id': '297492697822162468', + 'nobid': true + }] + }; + let bidderRequest; + + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(result.length).to.equal(0); + }); + + it('handles non-banner media responses', function () { + let response = { + 'tags': [{ + 'uuid': '84ab500420319d', + 'ads': [{ + 'ad_type': 'video', + 'cpm': 0.500000, + 'notify_url': 'imptracker.com', + 'rtb': { + 'video': { + 'content': '' + } + } + }] + }] + }; + let bidderRequest; + + let result = spec.interpretResponse({ body: response }, {bidderRequest}); + expect(result[0]).to.have.property('vastUrl'); + expect(result[0]).to.have.property('vastImpUrl'); + expect(result[0]).to.have.property('mediaType', 'video'); + }); + + it('handles native responses', function () { + let response1 = deepClone(response); + response1.tags[0].ads[0].ad_type = 'native'; + response1.tags[0].ads[0].rtb.native = { + 'title': 'Native Creative', + 'desc': 'Cool description great stuff', + 'ctatext': 'Do it', + 'sponsored': 'AppNexus', + 'icon': { + 'width': 0, + 'height': 0, + 'url': 'http://cdn.adnxs.com/icon.png' + }, + 'main_img': { + 'width': 2352, + 'height': 1516, + 'url': 'http://cdn.adnxs.com/img.png' + }, + 'link': { + 'url': 'https://www.appnexus.com', + 'fallback_url': '', + 'click_trackers': ['http://nym1-ib.adnxs.com/click'] + }, + 'impression_trackers': ['http://example.com'], + }; + let bidderRequest; + + let result = spec.interpretResponse({ body: response1 }, {bidderRequest}); + expect(result[0].native.title).to.equal('Native Creative'); + expect(result[0].native.body).to.equal('Cool description great stuff'); + expect(result[0].native.cta).to.equal('Do it'); + expect(result[0].native.image.url).to.equal('http://cdn.adnxs.com/img.png'); + }); + + it('supports configuring outstream renderers', function () { + const outstreamResponse = deepClone(response); + outstreamResponse.tags[0].ads[0].rtb.video = {}; + outstreamResponse.tags[0].ads[0].renderer_url = 'renderer.js'; + + const bidderRequest = { + bids: [{ + renderer: { + options: { + adText: 'configured' + } + } + }] + }; + + const result = spec.interpretResponse({ body: outstreamResponse }, {bidderRequest}); + expect(result[0].renderer.config).to.deep.equal( + bidderRequest.bids[0].renderer.options + ); + }); + }); +}); diff --git a/test/spec/modules/yieldNexusBidAdapter_spec.js b/test/spec/modules/yieldNexusBidAdapter_spec.js new file mode 100644 index 00000000000..b966d890e7a --- /dev/null +++ b/test/spec/modules/yieldNexusBidAdapter_spec.js @@ -0,0 +1,310 @@ +import { expect } from 'chai'; +import { spec } from 'modules/yieldNexusBidAdapter'; +import * as utils from 'src/utils'; + +const spid = '123'; + +describe('YieldNexusAdapter', () => { + describe('isBidRequestValid', () => { + it('should validate supply', () => { + expect(spec.isBidRequestValid({ params: {} })).to.equal(false); + expect(spec.isBidRequestValid({ params: { spid: 123 } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { spid: '123' } })).to.equal(true); + }); + it('should validate bid floor', () => { + expect(spec.isBidRequestValid({ params: { spid: '123' } })).to.equal(true); // bidfloor has a default + expect(spec.isBidRequestValid({ params: { spid: '123', bidfloor: '123' } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { spid: '123', bidfloor: 0.1 } })).to.equal(true); + }); + it('should validate adpos', () => { + expect(spec.isBidRequestValid({ params: { spid: '123' } })).to.equal(true); // adpos has a default + expect(spec.isBidRequestValid({ params: { spid: '123', adpos: '123' } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { spid: '123', adpos: 0.1 } })).to.equal(true); + }); + it('should validate instl', () => { + expect(spec.isBidRequestValid({ params: { spid: '123' } })).to.equal(true); // adpos has a default + expect(spec.isBidRequestValid({ params: { spid: '123', instl: '123' } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { spid: '123', instl: -1 } })).to.equal(false); + expect(spec.isBidRequestValid({ params: { spid: '123', instl: 0 } })).to.equal(true); + expect(spec.isBidRequestValid({ params: { spid: '123', instl: 1 } })).to.equal(true); + expect(spec.isBidRequestValid({ params: { spid: '123', instl: 2 } })).to.equal(false); + }); + }); + describe('buildRequests', () => { + const bidRequest = { + 'adUnitCode': 'adunit-code', + 'auctionId': 'fdkhjg3s7ahjja', + 'mediaTypes': { + banner: {} + }, + 'params': { spid }, + 'sizes': [ [ 300, 250 ], [ 300, 600 ] ] + }; + + it('returns an array', () => { + let response; + + response = spec.buildRequests([]); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(0); + + response = spec.buildRequests([ bidRequest ]); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(1); + + const adUnit1 = Object.assign({}, utils.deepClone(bidRequest), { auctionId: '1', adUnitCode: 'a' }); + const adUnit2 = Object.assign({}, utils.deepClone(bidRequest), { auctionId: '1', adUnitCode: 'b' }); + response = spec.buildRequests([adUnit1, adUnit2]); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(2); + }); + + it('uses yieldnexus dns', () => { + const response = spec.buildRequests([ bidRequest ])[ 0 ]; + expect(response.method).to.equal('POST'); + expect(response.url).to.match(new RegExp(`^https://ssp\\.ynxs\\.io/r/${spid}/bidr\\?bidder=prebid&rformat=open_rtb&reqformat=rtb_json$`, 'g')); + expect(response.data.id).to.equal(bidRequest.auctionId); + }); + + it('builds request correctly', () => { + let stub = sinon.stub(utils, 'getTopWindowUrl').returns('http://www.test.com/page.html'); + + let response; + response = spec.buildRequests([ bidRequest ])[ 0 ]; + expect(response.data.site.domain).to.equal('www.test.com'); + expect(response.data.site.page).to.equal('http://www.test.com/page.html'); + expect(response.data.site.ref).to.equal(''); + expect(response.data.imp.length).to.equal(1); + expect(response.data.imp[ 0 ].id).to.equal(bidRequest.transactionId); + 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); + expect(response.data.imp[ 0 ].bidfloorcur).to.equal('USD'); + + const bidRequestWithInstlEquals1 = utils.deepClone(bidRequest); + bidRequestWithInstlEquals1.params.instl = 1; + response = spec.buildRequests([ bidRequestWithInstlEquals1 ])[ 0 ]; + expect(response.data.imp[ 0 ].instl).to.equal(bidRequestWithInstlEquals1.params.instl); + + const bidRequestWithInstlEquals0 = utils.deepClone(bidRequest); + bidRequestWithInstlEquals0.params.instl = 1; + response = spec.buildRequests([ bidRequestWithInstlEquals0 ])[ 0 ]; + expect(response.data.imp[ 0 ].instl).to.equal(bidRequestWithInstlEquals0.params.instl); + + const bidRequestWithBidfloorEquals1 = utils.deepClone(bidRequest); + bidRequestWithBidfloorEquals1.params.bidfloor = 1; + response = spec.buildRequests([ bidRequestWithBidfloorEquals1 ])[ 0 ]; + expect(response.data.imp[ 0 ].bidfloor).to.equal(bidRequestWithBidfloorEquals1.params.bidfloor); + + stub.restore(); + }); + + it('builds request banner object correctly', () => { + let response; + + const bidRequestWithBanner = utils.deepClone(bidRequest); + bidRequestWithBanner.mediaTypes = { + banner: { + sizes: [ [ 300, 250 ], [ 120, 600 ] ] + } + }; + + response = spec.buildRequests([ bidRequestWithBanner ])[ 0 ]; + expect(response.data.imp[ 0 ].banner.w).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[ 0 ][ 0 ]); + expect(response.data.imp[ 0 ].banner.h).to.equal(bidRequestWithBanner.mediaTypes.banner.sizes[ 0 ][ 1 ]); + expect(response.data.imp[ 0 ].banner.pos).to.equal(0); + expect(response.data.imp[ 0 ].banner.topframe).to.equal(0); + + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithBanner); + bidRequestWithPosEquals1.params.pos = 1; + response = spec.buildRequests([ bidRequestWithPosEquals1 ])[ 0 ]; + expect(response.data.imp[ 0 ].banner.pos).to.equal(bidRequestWithPosEquals1.params.pos); + }); + + it('builds request video object correctly', () => { + let response; + + const bidRequestWithVideo = utils.deepClone(bidRequest); + bidRequestWithVideo.mediaTypes = { + video: { + sizes: [ [ 300, 250 ], [ 120, 600 ] ] + } + }; + + response = spec.buildRequests([ bidRequestWithVideo ])[ 0 ]; + expect(response.data.imp[ 0 ].video.w).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[ 0 ][ 0 ]); + expect(response.data.imp[ 0 ].video.h).to.equal(bidRequestWithVideo.mediaTypes.video.sizes[ 0 ][ 1 ]); + expect(response.data.imp[ 0 ].video.pos).to.equal(0); + expect(response.data.imp[ 0 ].video.topframe).to.equal(0); + + const bidRequestWithPosEquals1 = utils.deepClone(bidRequestWithVideo); + bidRequestWithPosEquals1.params.pos = 1; + response = spec.buildRequests([ bidRequestWithPosEquals1 ])[ 0 ]; + expect(response.data.imp[ 0 ].video.pos).to.equal(bidRequestWithPosEquals1.params.pos); + }); + }); + describe('interpretResponse', () => { + const bannerBidRequest = { + 'adUnitCode': 'adunit-code', + 'auctionId': 'fdkhjg3s7ahjja', + 'mediaTypes': { + banner: {} + }, + 'params': { + 'spid': spid + }, + 'sizes': [ [ 300, 250 ], [ 300, 600 ] ], + 'bidId': '111' + }; + const videoBidRequest = { + 'adUnitCode': 'adunit-code', + 'auctionId': 'fdkhjg3s7ahjja', + 'mediaTypes': { + video: {} + }, + 'params': { + 'spid': spid + }, + 'sizes': [ [ 300, 250 ], [ 300, 600 ] ], + 'bidId': '111' + }; + const rtbResponse = { + 'id': 'imp_5b05b9fde4b09084267a556f', + 'bidid': 'imp_5b05b9fde4b09084267a556f', + 'cur': 'USD', + 'ext': { + 'utrk': [ + { 'type': 'iframe', 'url': '//ssp.ynxs.io/user/sync/1' }, + { 'type': 'image', 'url': '//ssp.ynxs.io/user/sync/2' } + ] + }, + 'seatbid': [ + { + 'seat': 'testSeatBidA', + 'bid': [ + { + 'id': '0', + 'impid': '1', + 'price': 2.016, + 'adm': '', + 'adomain': [ 'nike.com' ], + 'h': 600, + 'w': 120, + 'ext': { + 'vast_url': 'http://vast.tag.com', + 'utrk': [ + { 'type': 'iframe', 'url': '//pix.usersync.io/user-sync' } + ] + } + } + ] + }, + { + 'seat': 'testSeatBidB', + 'bid': [ + { + 'id': '1', + 'impid': '1', + 'price': 3, + 'adid': '542jlhdfd2112jnjf3x', + 'adm': '', + 'adomain': [ 'adidas.com' ], + 'h': 250, + 'w': 300, + 'ext': { + 'utrk': [ + { 'type': 'image', 'url': '//pix.usersync.io/user-sync' } + ] + } + } + ] + } + ] + }; + it('fails gracefully on empty response body', () => { + let response; + + response = spec.interpretResponse(undefined, { bidRequest: bannerBidRequest }); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(0); + + response = spec.interpretResponse({}, { bidRequest: bannerBidRequest }); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(0); + }); + it('collects banner bids', () => { + const response = spec.interpretResponse({ body: rtbResponse }, { bidRequest: bannerBidRequest }); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(2); + + const ad0 = response[ 0 ], ad1 = response[ 1 ]; + expect(ad0.requestId).to.equal(bannerBidRequest.bidId); + expect(ad0.cpm).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].price); + expect(ad0.width).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].w); + expect(ad0.height).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].h); + expect(ad0.ttl).to.equal(15 * 60); + expect(ad0.creativeId).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].crid); + expect(ad0.netRevenue).to.equal(true); + expect(ad0.currency).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); + expect(ad0.ad).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].adm); + expect(ad0.vastXml).to.be.an('undefined'); + + expect(ad1.requestId).to.equal(bannerBidRequest.bidId); + expect(ad1.cpm).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].price); + expect(ad1.width).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].w); + expect(ad1.height).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].h); + expect(ad1.ttl).to.equal(15 * 60); + expect(ad1.creativeId).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].crid); + expect(ad1.netRevenue).to.equal(true); + expect(ad1.currency).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); + expect(ad1.ad).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); + expect(ad1.vastXml).to.be.an('undefined'); + + // expect(ad1.ad).to.be.an('undefined'); + // expect(ad1.vastXml).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); + }); + it('collects video bids', () => { + const response = spec.interpretResponse({ body: rtbResponse }, { bidRequest: videoBidRequest }); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(2); + + const ad0 = response[ 0 ], ad1 = response[ 1 ]; + expect(ad0.requestId).to.equal(videoBidRequest.bidId); + expect(ad0.cpm).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].price); + expect(ad0.width).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].w); + expect(ad0.height).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].h); + expect(ad0.ttl).to.equal(15 * 60); + expect(ad0.creativeId).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].crid); + expect(ad0.netRevenue).to.equal(true); + expect(ad0.currency).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); + expect(ad0.ad).to.be.an('undefined'); + expect(ad0.vastXml).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].adm); + expect(ad0.vastUrl).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].ext.vast_url); + + expect(ad1.requestId).to.equal(videoBidRequest.bidId); + expect(ad1.cpm).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].price); + expect(ad1.width).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].w); + expect(ad1.height).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].h); + expect(ad1.ttl).to.equal(15 * 60); + expect(ad1.creativeId).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].crid); + expect(ad1.netRevenue).to.equal(true); + expect(ad1.currency).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].cur || rtbResponse.cur || 'USD'); + expect(ad1.ad).to.be.an('undefined'); + expect(ad1.vastXml).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].adm); + expect(ad1.vastUrl).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.vast_url); + }); + it('applies user-syncs', () => { + const response = spec.getUserSyncs({}, [ { body: rtbResponse } ]); + expect(Array.isArray(response)).to.equal(true); + expect(response.length).to.equal(4); + expect(response[ 0 ].type).to.equal(rtbResponse.ext.utrk[ 0 ].type); + expect(response[ 0 ].url).to.equal(rtbResponse.ext.utrk[ 0 ].url + '?gc=missing'); + expect(response[ 1 ].type).to.equal(rtbResponse.ext.utrk[ 1 ].type); + expect(response[ 1 ].url).to.equal(rtbResponse.ext.utrk[ 1 ].url + '?gc=missing'); + expect(response[ 2 ].type).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].ext.utrk[ 0 ].type); + expect(response[ 2 ].url).to.equal(rtbResponse.seatbid[ 0 ].bid[ 0 ].ext.utrk[ 0 ].url + '?gc=missing'); + expect(response[ 3 ].type).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.utrk[ 0 ].type); + expect(response[ 3 ].url).to.equal(rtbResponse.seatbid[ 1 ].bid[ 0 ].ext.utrk[ 0 ].url + '?gc=missing'); + }); + }); +}); diff --git a/test/spec/modules/yieldbotBidAdapter_spec.js b/test/spec/modules/yieldbotBidAdapter_spec.js index 206645acd95..2977e4ef30d 100644 --- a/test/spec/modules/yieldbotBidAdapter_spec.js +++ b/test/spec/modules/yieldbotBidAdapter_spec.js @@ -1323,4 +1323,51 @@ describe('Yieldbot Adapter Unit Tests', function() { done(); }); }); + + describe('Adapter Request Timestamps', function() { + let sandbox; + beforeEach(function() { + sandbox = sinon.sandbox.create(); + sandbox.stub(Date, 'now').callsFake(() => { + return new Date(); + }); + }); + + afterEach(function() { + sandbox.restore(); + }); + + it('should have overridden Date.now() function', function() { + expect(Date.now().getTime()).to.match(/^[0-9]+/); + }); + + it('should be milliseconds past epoch query param values', function() { + const request = YieldbotAdapter.buildRequests(FIXTURE_BID_REQUESTS)[0]; + expect(request.data).to.not.equal(undefined); + + const timestampParams = [ + 'cts_ns', + 'cts_js', + 'cts_ini' + ]; + + timestampParams.forEach((item) => { + expect(!isNaN(request.data[item])).to.equal(true); + expect(request.data[item] > 0).to.equal(true); + expect(request.data[item]).to.match(/^[0-9]+/); + }); + }); + + it('should use (new Date()).getTime() for timestamps in ad markup', function() { + FIXTURE_SERVER_RESPONSE.body.url_prefix = 'http://close.edge.adserver.com/'; + const responses = YieldbotAdapter.interpretResponse( + FIXTURE_SERVER_RESPONSE, + FIXTURE_BID_REQUEST + ); + + expect(responses[0].ad).to.match(/cts_rend_.*='\+\(new Date\(\)\)\.getTime\(\)/); + expect(responses[0].ad).to.match(/cts_ad='\+\(new Date\(\)\)\.getTime\(\)/); + expect(responses[0].ad).to.match(/cts_imp='\+\(new Date\(\)\)\.getTime\(\)/); + }); + }); }); diff --git a/test/spec/modules/yieldlabBidAdapter_spec.js b/test/spec/modules/yieldlabBidAdapter_spec.js index 1a5ca59d3a2..0e97910bbb7 100644 --- a/test/spec/modules/yieldlabBidAdapter_spec.js +++ b/test/spec/modules/yieldlabBidAdapter_spec.js @@ -7,7 +7,11 @@ const REQUEST = { 'params': { 'adslotId': '1111', 'supplyId': '2222', - 'adSize': '728x90' + 'adSize': '728x90', + 'targeting': { + 'key1': 'value1', + 'key2': 'value2' + } }, 'bidderRequestId': '143346cf0f1731', 'auctionId': '2e41f65424c87c', @@ -25,17 +29,17 @@ const RESPONSE = { pid: 2222 } -describe('yieldlabBidAdapter', () => { +describe('yieldlabBidAdapter', function () { const adapter = newBidder(spec) - describe('inherited functions', () => { - it('exists and is a function', () => { + describe('inherited functions', function () { + it('exists and is a function', function () { expect(adapter.callBids).to.exist.and.to.be.a('function') }) }) - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { + describe('isBidRequestValid', function () { + it('should return true when required params found', function () { const request = { 'params': { 'adslotId': '1111', @@ -46,35 +50,51 @@ describe('yieldlabBidAdapter', () => { expect(spec.isBidRequestValid(request)).to.equal(true) }) - it('should return false when required params are not passed', () => { + it('should return false when required params are not passed', function () { expect(spec.isBidRequestValid({})).to.equal(false) }) }) - describe('buildRequests', () => { + describe('buildRequests', function () { const bidRequests = [REQUEST] const request = spec.buildRequests(bidRequests) - it('sends bid request to ENDPOINT via GET', () => { + it('sends bid request to ENDPOINT via GET', function () { expect(request.method).to.equal('GET') }) - it('returns a list of valid requests', () => { + it('returns a list of valid requests', function () { expect(request.validBidRequests).to.eql([REQUEST]) }) + + it('passes targeting to bid request', function () { + expect(request.url).to.include('t=key1%3Dvalue1%26key2%3Dvalue2') + }) + + const gdprRequest = spec.buildRequests(bidRequests, { + gdprConsent: { + consentString: 'BN5lERiOMYEdiAKAWXEND1AAAAE6DABACMA', + gdprApplies: true + } + }) + + it('passes gdpr flag and consent if present', function () { + expect(gdprRequest.url).to.include('consent=BN5lERiOMYEdiAKAWXEND1AAAAE6DABACMA') + expect(gdprRequest.url).to.include('gdpr=true') + }) }) - describe('interpretResponse', () => { + describe('interpretResponse', function () { const validRequests = { validBidRequests: [REQUEST] } - it('handles nobid responses', () => { + it('handles nobid responses', function () { expect(spec.interpretResponse({body: {}}, {validBidRequests: []}).length).to.equal(0) expect(spec.interpretResponse({body: []}, {validBidRequests: []}).length).to.equal(0) }) - it('should get correct bid response', () => { + it('should get correct bid response', function () { const result = spec.interpretResponse({body: [RESPONSE]}, validRequests) expect(result[0].requestId).to.equal('2d925f27f5079f') @@ -90,7 +110,7 @@ describe('yieldlabBidAdapter', () => { expect(result[0].ad).to.include('
', - creativeId: '9874652394875' + creative_id: '9874652394875' }], header: 'header?' }; }) - it('should correctly reorder the server response', () => { + it('should correctly reorder the server response', function () { const newResponse = spec.interpretResponse(serverResponse); expect(newResponse.length).to.be.equal(1); expect(newResponse[0]).to.deep.equal({ @@ -126,7 +126,7 @@ describe('YieldmoAdapter', () => { }); }); - it('should not add responses if the cpm is 0 or null', () => { + it('should not add responses if the cpm is 0 or null', function () { serverResponse.body[0].cpm = 0; let response = spec.interpretResponse(serverResponse); expect(response).to.deep.equal([]); @@ -137,14 +137,14 @@ describe('YieldmoAdapter', () => { }); }); - describe('getUserSync', () => { + describe('getUserSync', function () { const SYNC_ENDPOINT = 'https://static.yieldmo.com/blank.min.html?orig='; let options = { iframeEnabled: true, pixelEnabled: true }; - it('should return a tracker with type and url as parameters', () => { + it('should return a tracker with type and url as parameters', function () { if (/iPhone|iPad|iPod/i.test(window.navigator.userAgent)) { expect(spec.getUserSync(options)).to.deep.equal([{ type: 'iframe', diff --git a/test/spec/modules/yieldoneBidAdapter_spec.js b/test/spec/modules/yieldoneBidAdapter_spec.js index e763257f097..b717ef52709 100644 --- a/test/spec/modules/yieldoneBidAdapter_spec.js +++ b/test/spec/modules/yieldoneBidAdapter_spec.js @@ -7,7 +7,7 @@ const ENDPOINT = '//y.one.impact-ad.jp/h_bid'; describe('yieldoneBidAdapter', function() { const adapter = newBidder(spec); - describe('isBidRequestValid', () => { + describe('isBidRequestValid', function () { let bid = { 'bidder': 'yieldone', 'params': { @@ -22,23 +22,23 @@ describe('yieldoneBidAdapter', function() { 'auctionId': '61466567-d482-4a16-96f0-fe5f25ffbdf1', }; - it('should return true when required params found', () => { + it('should return true when required params found', function () { expect(spec.isBidRequestValid(bid)).to.equal(true); }); - it('should return false when placementId not passed correctly', () => { + it('should return false when placementId not passed correctly', function () { bid.params.placementId = ''; expect(spec.isBidRequestValid(bid)).to.equal(false); }); - it('should return false when require params are not passed', () => { + it('should return false when require params are not passed', function () { let bid = Object.assign({}, bid); bid.params = {}; expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); - describe('buildRequests', () => { + describe('buildRequests', function () { let bidRequests = [ { 'bidder': 'yieldone', @@ -70,18 +70,18 @@ describe('yieldoneBidAdapter', function() { const request = spec.buildRequests(bidRequests); - it('sends bid request to our endpoint via GET', () => { + it('sends bid request to our endpoint via GET', function () { expect(request[0].method).to.equal('GET'); expect(request[1].method).to.equal('GET'); }); - it('attaches source and version to endpoint URL as query params', () => { + it('attaches source and version to endpoint URL as query params', function () { expect(request[0].url).to.equal(ENDPOINT); expect(request[1].url).to.equal(ENDPOINT); }); }); - describe('interpretResponse', () => { + describe('interpretResponse', function () { let bidRequest = [ { 'method': 'GET', @@ -111,7 +111,7 @@ describe('yieldoneBidAdapter', function() { } }; - it('should get the correct bid response', () => { + it('should get the correct bid response', function () { let expectedResponse = [{ 'requestId': '23beaa6af6cdde', 'cpm': 53.6616, @@ -129,7 +129,7 @@ describe('yieldoneBidAdapter', function() { expect(Object.keys(result)).to.deep.equal(Object.keys(expectedResponse)); }); - it('handles empty bid response', () => { + it('handles empty bid response', function () { let response = { body: { 'uid': '2c0b634db95a01', @@ -144,4 +144,20 @@ describe('yieldoneBidAdapter', function() { expect(result.length).to.equal(0); }); }); + + describe('getUserSyncs', function () { + const userSyncUrl = '//y.one.impact-ad.jp/push_sync'; + + it('handles empty sync options', function () { + expect(spec.getUserSyncs({})).to.be.empty; + }); + + it('should return a sync url if iframe syncs are enabled', function () { + expect(spec.getUserSyncs({ + 'iframeEnabled': true + })).to.deep.equal([{ + type: 'iframe', url: userSyncUrl + }]); + }); + }); }); diff --git a/test/spec/modules/yuktamediaAnalyticsAdaptor_spec.js b/test/spec/modules/yuktamediaAnalyticsAdaptor_spec.js index 29d23d66bd2..2239abcb33f 100644 --- a/test/spec/modules/yuktamediaAnalyticsAdaptor_spec.js +++ b/test/spec/modules/yuktamediaAnalyticsAdaptor_spec.js @@ -4,23 +4,23 @@ let adaptermanager = require('src/adaptermanager'); let events = require('src/events'); let constants = require('src/constants.json'); -describe('YuktaMedia analytics adapter', () => { +describe('YuktaMedia analytics adapter', function () { let xhr; let requests; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = request => requests.push(request); sinon.stub(events, 'getEvents').returns([]); }); - afterEach(() => { + afterEach(function () { xhr.restore(); events.getEvents.restore(); }); - describe('track', () => { + describe('track', function () { let initOptions = { pubId: '1', pubKey: 'ZXlKaGJHY2lPaUpJVXpJMU5pSjkuT==' @@ -31,18 +31,18 @@ describe('YuktaMedia analytics adapter', () => { adapter: yuktamediaAnalyticsAdapter }); - beforeEach(() => { + beforeEach(function () { adaptermanager.enableAnalytics({ provider: 'yuktamedia', options: initOptions }); }); - afterEach(() => { + afterEach(function () { yuktamediaAnalyticsAdapter.disableAnalytics(); }); - it('builds and sends auction data', () => { + it('builds and sends auction data', function () { let auctionTimestamp = 1496510254313; let bidRequest = { 'bidderCode': 'appnexus', diff --git a/test/spec/modules/zedoBidAdapter_spec.js b/test/spec/modules/zedoBidAdapter_spec.js new file mode 100644 index 00000000000..85209edd4c3 --- /dev/null +++ b/test/spec/modules/zedoBidAdapter_spec.js @@ -0,0 +1,268 @@ +import { expect } from 'chai'; +import { spec } from 'modules/zedoBidAdapter'; + +describe('The ZEDO bidding adapter', function () { + describe('isBidRequestValid', function () { + it('should return false when given an invalid bid', function () { + const bid = { + bidder: 'zedo', + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(false); + }); + + it('should return true when given a channelcode bid', function () { + const bid = { + bidder: 'zedo', + params: { + channelCode: 20000000, + dimId: 9 + }, + }; + const isValid = spec.isBidRequestValid(bid); + expect(isValid).to.equal(true); + }); + }); + + describe('buildRequests', function () { + const bidderRequest = { + timeout: 3000, + }; + + it('should properly build a channelCode request for dim Id with type not defined', function () { + const bidRequests = [ + { + bidder: 'zedo', + adUnitCode: 'p12345', + transactionId: '12345667', + sizes: [[300, 200]], + params: { + channelCode: 20000000, + dimId: 10 + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.url).to.match(/^\/\/z2.zedo.com\/asw\/fmh.json/); + expect(request.method).to.equal('GET'); + const zedoRequest = request.data; + expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"width":300,"height":200,"dimension":10,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"display"}]}]}'); + }); + + it('should properly build a channelCode request for video with type defined', function () { + const bidRequests = [ + { + bidder: 'zedo', + adUnitCode: 'p12345', + transactionId: '12345667', + sizes: [640, 480], + mediaTypes: { + video: { + context: 'instream', + }, + }, + params: { + channelCode: 20000000, + dimId: 85 + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.url).to.match(/^\/\/z2.zedo.com\/asw\/fmh.json/); + expect(request.method).to.equal('GET'); + const zedoRequest = request.data; + expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"width":640,"height":480,"dimension":85,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"Inarticle"}]}]}'); + }); + + describe('buildGDPRRequests', function () { + let consentString = 'BOJ8RZsOJ8RZsABAB8AAAAAZ+A=='; + const bidderRequest = { + timeout: 3000, + gdprConsent: { + 'consentString': consentString, + 'gdprApplies': true + } + }; + + it('should properly build request with gdpr consent', function () { + const bidRequests = [ + { + bidder: 'zedo', + adUnitCode: 'p12345', + transactionId: '12345667', + sizes: [[300, 200]], + params: { + channelCode: 20000000, + dimId: 10 + }, + }, + ]; + const request = spec.buildRequests(bidRequests, bidderRequest); + expect(request.method).to.equal('GET'); + const zedoRequest = request.data; + expect(zedoRequest).to.equal('g={"placements":[{"network":20,"channel":0,"width":300,"height":200,"dimension":10,"version":"$prebid.version$","keyword":"","transactionId":"12345667","renderers":[{"name":"display"}]}],"gdpr":1,"gdpr_consent":"BOJ8RZsOJ8RZsABAB8AAAAAZ+A=="}'); + }); + }); + }); + describe('interpretResponse', function () { + it('should return an empty array when there is bid response', function () { + const response = {}; + const request = { bidRequests: [] }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(0); + }); + + it('should properly parse a bid response with no valid creative', function () { + const response = { + body: { + ad: [ + { + 'slotId': 'ad1d762', + 'network': '2000', + 'creatives': [ + { + 'adId': '12345', + 'height': '600', + 'width': '160', + 'isFoc': true, + 'creativeDetails': { + 'type': 'StdBanner', + 'adContent': { + 'focImage': { + 'url': 'https://c13.zedo.com/OzoDB/0/0/0/blank.gif', + 'target': '_blank', + } + } + }, + 'cpm': '0' + } + ] + } + ] + } + }; + const request = { + bidRequests: [{ + bidder: 'zedo', + adUnitCode: 'p12345', + bidId: 'test-bidId', + params: { + channelCode: 2000000, + dimId: 9 + } + }] + }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(0); + }); + + it('should properly parse a bid response with valid display creative', function () { + const response = { + body: { + ad: [ + { + 'slotId': 'ad1d762', + 'network': '2000', + 'creatives': [ + { + 'adId': '12345', + 'height': '600', + 'width': '160', + 'isFoc': true, + 'creativeDetails': { + 'type': 'StdBanner', + 'adContent': '' + }, + 'cpm': '1200000' + } + ] + } + ] + } + }; + const request = { + bidRequests: [{ + bidder: 'zedo', + adUnitCode: 'test-requestId', + bidId: 'test-bidId', + params: { + channelCode: 2000000, + dimId: 9 + }, + }] + }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(1); + expect(bids[0].requestId).to.equal('ad1d762'); + expect(bids[0].cpm).to.equal(0.72); + expect(bids[0].width).to.equal('160'); + expect(bids[0].height).to.equal('600'); + }); + + it('should properly parse a bid response with valid video creative', function () { + const response = { + body: { + ad: [ + { + 'slotId': 'ad1d762', + 'network': '2000', + 'creatives': [ + { + 'adId': '12345', + 'height': '480', + 'width': '640', + 'isFoc': true, + 'creativeDetails': { + 'type': 'VAST', + 'adContent': '' + }, + 'cpm': '1200000' + } + ] + } + ] + } + }; + const request = { + bidRequests: [{ + bidder: 'zedo', + adUnitCode: 'test-requestId', + bidId: 'test-bidId', + params: { + channelCode: 2000000, + dimId: 85 + }, + }] + }; + const bids = spec.interpretResponse(response, request); + expect(bids).to.have.lengthOf(1); + expect(bids[0].requestId).to.equal('ad1d762'); + expect(bids[0].cpm).to.equal(0.78); + expect(bids[0].width).to.equal('640'); + expect(bids[0].height).to.equal('480'); + expect(bids[0].vastXml).to.not.equal(''); + expect(bids[0].ad).to.be.an('undefined'); + }); + }); + + describe('user sync', function () { + it('should register the iframe sync url', function () { + let syncs = spec.getUserSyncs({ + iframeEnabled: true + }); + expect(syncs).to.not.be.an('undefined'); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0].type).to.equal('iframe'); + }); + + it('should pass gdpr params', function () { + let syncs = spec.getUserSyncs({ iframeEnabled: true }, {}, { + gdprApplies: false, consentString: 'test' + }); + expect(syncs).to.not.be.an('undefined'); + expect(syncs).to.have.lengthOf(1); + expect(syncs[0].type).to.equal('iframe'); + expect(syncs[0].url).to.contains('gdpr=0'); + }); + }); +}); diff --git a/test/spec/native_spec.js b/test/spec/native_spec.js index 653f858576f..dc70592877e 100644 --- a/test/spec/native_spec.js +++ b/test/spec/native_spec.js @@ -15,42 +15,42 @@ const bid = { } }; -describe('native.js', () => { +describe('native.js', function () { let triggerPixelStub; let insertHtmlIntoIframeStub; - beforeEach(() => { + beforeEach(function () { triggerPixelStub = sinon.stub(utils, 'triggerPixel'); insertHtmlIntoIframeStub = sinon.stub(utils, 'insertHtmlIntoIframe'); }); - afterEach(() => { + afterEach(function () { utils.triggerPixel.restore(); utils.insertHtmlIntoIframe.restore(); }); - it('gets native targeting keys', () => { + it('gets native targeting keys', function () { const targeting = getNativeTargeting(bid); expect(targeting.hb_native_title).to.equal(bid.native.title); expect(targeting.hb_native_body).to.equal(bid.native.body); expect(targeting.hb_native_linkurl).to.equal(bid.native.clickUrl); }); - it('fires impression trackers', () => { + it('fires impression trackers', function () { fireNativeTrackers({}, bid); sinon.assert.calledOnce(triggerPixelStub); sinon.assert.calledWith(triggerPixelStub, bid.native.impressionTrackers[0]); sinon.assert.calledWith(insertHtmlIntoIframeStub, bid.native.javascriptTrackers); }); - it('fires click trackers', () => { + it('fires click trackers', function () { fireNativeTrackers({ action: 'click' }, bid); sinon.assert.calledOnce(triggerPixelStub); sinon.assert.calledWith(triggerPixelStub, bid.native.clickTrackers[0]); }); }); -describe('validate native', () => { +describe('validate native', function () { let bidReq = [{ bids: [{ bidderCode: 'test_bidder', @@ -149,11 +149,11 @@ describe('validate native', () => { } }; - beforeEach(() => {}); + beforeEach(function () {}); - afterEach(() => {}); + afterEach(function () {}); - it('should reject bid if no image sizes are defined', () => { + it('should reject bid if no image sizes are defined', function () { let result = nativeBidIsValid(validBid, bidReq); expect(result).to.be.true; result = nativeBidIsValid(noIconDimBid, bidReq); diff --git a/test/spec/refererDetection_spec.js b/test/spec/refererDetection_spec.js new file mode 100644 index 00000000000..956ba794546 --- /dev/null +++ b/test/spec/refererDetection_spec.js @@ -0,0 +1,80 @@ +import { detectReferer } from 'src/refererDetection'; +import { expect } from 'chai'; + +var mocks = { + createFakeWindow: function (referrer, href) { + return { + document: { + referrer: referrer + }, + location: { + href: href, + // TODO: add ancestorOrigins to increase test coverage + }, + parent: null, + top: null + }; + } +} + +describe('referer detection', () => { + it('should return referer details in nested friendly iframes', function() { + // Fake window object to test friendly iframes + // - Main page http://example.com/page.html + // - - Iframe1 http://example.com/iframe1.html + // - - - Iframe2 http://example.com/iframe2.html + let mockIframe2WinObject = mocks.createFakeWindow('http://example.com/iframe1.html', 'http://example.com/iframe2.html'); + let mockIframe1WinObject = mocks.createFakeWindow('http://example.com/page.html', 'http://example.com/iframe1.html'); + let mainWinObject = mocks.createFakeWindow('http://example.com/page.html', 'http://example.com/page.html'); + mockIframe2WinObject.parent = mockIframe1WinObject; + mockIframe2WinObject.top = mainWinObject; + mockIframe1WinObject.parent = mainWinObject; + mockIframe1WinObject.top = mainWinObject; + mainWinObject.top = mainWinObject; + + const getRefererInfo = detectReferer(mockIframe2WinObject); + let result = getRefererInfo(); + let expectedResult = { + referer: 'http://example.com/page.html', + reachedTop: true, + numIframes: 2, + stack: [ + 'http://example.com/page.html', + 'http://example.com/iframe1.html', + 'http://example.com/iframe2.html' + ] + }; + expect(result).to.deep.equal(expectedResult); + }); + + it('should return referer details in nested cross domain iframes', function() { + // Fake window object to test cross domain iframes. + // - Main page http://example.com/page.html + // - - Iframe1 http://aaa.com/iframe1.html + // - - - Iframe2 http://bbb.com/iframe2.html + let mockIframe2WinObject = mocks.createFakeWindow('http://aaa.com/iframe1.html', 'http://bbb.com/iframe2.html'); + // Sinon cannot throw exception when accessing a propery so passing null to create cross domain + // environment for refererDetection module + let mockIframe1WinObject = mocks.createFakeWindow(null, null); + let mainWinObject = mocks.createFakeWindow(null, null); + mockIframe2WinObject.parent = mockIframe1WinObject; + mockIframe2WinObject.top = mainWinObject; + mockIframe1WinObject.parent = mainWinObject; + mockIframe1WinObject.top = mainWinObject; + mainWinObject.top = mainWinObject; + + const getRefererInfo = detectReferer(mockIframe2WinObject); + let result = getRefererInfo(); + let expectedResult = { + referer: 'http://aaa.com/iframe1.html', + reachedTop: false, + numIframes: 2, + stack: [ + null, + 'http://aaa.com/iframe1.html', + 'http://bbb.com/iframe2.html' + ] + }; + expect(result).to.deep.equal(expectedResult); + }); +}); diff --git a/test/spec/renderer_spec.js b/test/spec/renderer_spec.js index a511a1b214c..7f95af1a257 100644 --- a/test/spec/renderer_spec.js +++ b/test/spec/renderer_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import { Renderer } from 'src/Renderer'; const adloader = require('../../src/adloader'); -describe('Renderer: A renderer installed on a bid response', () => { +describe('Renderer: A renderer installed on a bid response', function () { let testRenderer1; let testRenderer2; let spyRenderFn; @@ -10,7 +10,7 @@ describe('Renderer: A renderer installed on a bid response', () => { let loadScriptStub; - beforeEach(() => { + beforeEach(function () { loadScriptStub = sinon.stub(adloader, 'loadScript').callsFake((...args) => { args[1](); }); @@ -30,33 +30,33 @@ describe('Renderer: A renderer installed on a bid response', () => { spyEventHandler = sinon.spy(); }); - afterEach(() => { + afterEach(function () { loadScriptStub.restore(); }); - it('is an instance of Renderer', () => { + it('is an instance of Renderer', function () { expect(testRenderer1 instanceof Renderer).to.equal(true); }); - it('has expected properties ', () => { + it('has expected properties ', function () { expect(testRenderer1.url).to.equal('https://httpbin.org/post'); expect(testRenderer1.config).to.deep.equal({ test: 'config1' }); expect(testRenderer1.id).to.equal(1); }); - it('returns config from getConfig method', () => { + it('returns config from getConfig method', function () { expect(testRenderer1.getConfig()).to.deep.equal({ test: 'config1' }); expect(testRenderer2.getConfig()).to.deep.equal({ test: 'config2' }); }); - it('sets a render function with setRender method', () => { + it('sets a render function with setRender method', function () { testRenderer1.setRender(spyRenderFn); expect(typeof testRenderer1.render).to.equal('function'); testRenderer1.render(); expect(spyRenderFn.called).to.equal(true); }); - it('sets event handlers with setEventHandlers method and handles events with installed handlers', () => { + it('sets event handlers with setEventHandlers method and handles events with installed handlers', function () { testRenderer1.setEventHandlers({ testEvent: spyEventHandler }); @@ -69,7 +69,7 @@ describe('Renderer: A renderer installed on a bid response', () => { expect(spyEventHandler.called).to.equal(true); }); - it('pushes commands to queue if renderer is not loaded', () => { + it('pushes commands to queue if renderer is not loaded', function () { testRenderer1.loaded = false; testRenderer1.push(spyRenderFn); expect(testRenderer1.cmd.length).to.equal(1); @@ -78,7 +78,7 @@ describe('Renderer: A renderer installed on a bid response', () => { testRenderer1.cmd = []; }); - it('fires commands immediately if the renderer is loaded', () => { + it('fires commands immediately if the renderer is loaded', function () { const func = sinon.spy(); testRenderer1.loaded = true; @@ -89,7 +89,7 @@ describe('Renderer: A renderer installed on a bid response', () => { sinon.assert.calledOnce(func); }); - it('processes queue by calling each function in queue', () => { + it('processes queue by calling each function in queue', function () { testRenderer1.loaded = false; const func1 = sinon.spy(); const func2 = sinon.spy(); diff --git a/test/spec/sizeMapping_spec.js b/test/spec/sizeMapping_spec.js index 74b86a8c5aa..15213958296 100644 --- a/test/spec/sizeMapping_spec.js +++ b/test/spec/sizeMapping_spec.js @@ -5,7 +5,7 @@ import includes from 'core-js/library/fn/array/includes'; let utils = require('src/utils'); let deepClone = utils.deepClone; -describe('sizeMapping', () => { +describe('sizeMapping', function () { var testSizes = [[970, 90], [728, 90], [300, 250], [300, 100], [80, 80]]; var sizeConfig = [{ @@ -49,7 +49,7 @@ describe('sizeMapping', () => { let sandbox, matchMediaOverride; - beforeEach(() => { + beforeEach(function () { setSizeConfig(sizeConfig); sandbox = sinon.sandbox.create(); @@ -64,14 +64,14 @@ describe('sizeMapping', () => { }); }); - afterEach(() => { + afterEach(function () { setSizeConfig([]); sandbox.restore(); }); - describe('when handling sizes', () => { - it('should log a warning when mediaQuery property missing from sizeConfig', () => { + describe('when handling sizes', function () { + it('should log a warning when mediaQuery property missing from sizeConfig', function () { let errorConfig = deepClone(sizeConfig); delete errorConfig[0].mediaQuery; @@ -82,7 +82,7 @@ describe('sizeMapping', () => { expect(utils.logWarn.firstCall.args[0]).to.match(/missing.+?mediaQuery/); }); - it('when one mediaQuery block matches, it should filter the adUnit.sizes passed in', () => { + 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, sizeConfig); @@ -93,7 +93,7 @@ describe('sizeMapping', () => { }) }); - it('when multiple mediaQuery block matches, it should filter a union of the matched sizesSupported', () => { + 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)' @@ -106,7 +106,7 @@ describe('sizeMapping', () => { }) }); - it('if no mediaQueries match, it should allow all sizes specified', () => { + it('if no mediaQueries match, it should allow all sizes specified', function () { matchMediaOverride = () => ({matches: false}); let status = resolveStatus(undefined, testSizes, sizeConfig); @@ -116,7 +116,7 @@ describe('sizeMapping', () => { }) }); - it('if a mediaQuery matches and has sizesSupported: [], it should filter all sizes', () => { + 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, sizeConfig); @@ -126,7 +126,7 @@ describe('sizeMapping', () => { }) }); - it('if a mediaQuery matches and no sizesSupported specified, it should not effect adUnit.sizes', () => { + it('if a mediaQuery matches and no sizesSupported specified, it should not effect adUnit.sizes', function () { matchMediaOverride = (str) => str === '(min-width: 1200px)' ? {matches: true} : {matches: false}; let status = resolveStatus(undefined, testSizes, sizeConfigWithLabels); @@ -137,8 +137,8 @@ describe('sizeMapping', () => { }); }); - describe('when handling labels', () => { - it('should activate/deactivate adUnits/bidders based on sizeConfig.labels', () => { + 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({ @@ -160,7 +160,7 @@ describe('sizeMapping', () => { }); }); - it('should active/deactivate adUnits/bidders based on requestBids labels', () => { + it('should active/deactivate adUnits/bidders based on requestBids labels', function () { let activeLabels = ['us-visitor', 'desktop', 'smart']; let status = resolveStatus({ diff --git a/test/spec/unit/adServerManager_spec.js b/test/spec/unit/adServerManager_spec.js index 72a3b61ce41..928050ee93c 100644 --- a/test/spec/unit/adServerManager_spec.js +++ b/test/spec/unit/adServerManager_spec.js @@ -4,12 +4,12 @@ import { registerVideoSupport } from 'src/adServerManager'; const prebid = getGlobal(); -describe('The ad server manager', () => { - beforeEach(() => { +describe('The ad server manager', function () { + beforeEach(function () { delete prebid.adServers; }); - it('should register video support to the proper place on the API', () => { + it('should register video support to the proper place on the API', function () { function videoSupport() { } registerVideoSupport('dfp', { buildVideoUrl: videoSupport }); @@ -18,7 +18,7 @@ describe('The ad server manager', () => { expect(prebid.adServers.dfp).to.have.property('buildVideoUrl', videoSupport); }); - it('should keep the first function when we try to add a second', () => { + it('should keep the first function when we try to add a second', function () { function videoSupport() { } registerVideoSupport('dfp', { buildVideoUrl: videoSupport }); registerVideoSupport('dfp', { buildVideoUrl: function noop() { } }); diff --git a/test/spec/unit/adUnits_spec.js b/test/spec/unit/adUnits_spec.js new file mode 100644 index 00000000000..ff77315ba4a --- /dev/null +++ b/test/spec/unit/adUnits_spec.js @@ -0,0 +1,23 @@ +import { expect } from 'chai'; +import { adunitCounter } from 'src/adUnits'; + +describe('Adunit Counter', function () { + const ADUNIT_ID_1 = 'test1'; + const ADUNIT_ID_2 = 'test2'; + + it('increments and checks counter of adunit 1', function () { + adunitCounter.incrementCounter(ADUNIT_ID_1); + expect(adunitCounter.getCounter(ADUNIT_ID_1)).to.be.equal(1); + }); + it('checks counter of adunit 2', function () { + expect(adunitCounter.getCounter(ADUNIT_ID_2)).to.be.equal(0); + }); + it('increments and checks counter of adunit 1', function () { + adunitCounter.incrementCounter(ADUNIT_ID_1); + expect(adunitCounter.getCounter(ADUNIT_ID_1)).to.be.equal(2); + }); + it('increments and checks counter of adunit 2', function () { + adunitCounter.incrementCounter(ADUNIT_ID_2); + expect(adunitCounter.getCounter(ADUNIT_ID_2)).to.be.equal(1); + }); +}); diff --git a/test/spec/unit/core/adapterManager_spec.js b/test/spec/unit/core/adapterManager_spec.js index 8b1c164a804..644f10de794 100644 --- a/test/spec/unit/core/adapterManager_spec.js +++ b/test/spec/unit/core/adapterManager_spec.js @@ -19,7 +19,8 @@ const CONFIG = { timeout: 1000, maxBids: 1, adapter: 'prebidServer', - bidders: ['appnexus'] + bidders: ['appnexus'], + accountId: 'abc' }; var prebidServerAdapterMock = { bidder: 'prebidServer', @@ -40,12 +41,12 @@ var rubiconAdapterMock = { }; let loadScriptStub; -describe('adapterManager tests', () => { +describe('adapterManager tests', function () { let orgAppnexusAdapter; let orgAdequantAdapter; let orgPrebidServerAdapter; let orgRubiconAdapter; - before(() => { + before(function () { orgAppnexusAdapter = AdapterManager.bidderRegistry['appnexus']; orgAdequantAdapter = AdapterManager.bidderRegistry['adequant']; orgPrebidServerAdapter = AdapterManager.bidderRegistry['prebidServer']; @@ -55,7 +56,7 @@ describe('adapterManager tests', () => { }); }); - after(() => { + after(function () { AdapterManager.bidderRegistry['appnexus'] = orgAppnexusAdapter; AdapterManager.bidderRegistry['adequant'] = orgAdequantAdapter; AdapterManager.bidderRegistry['prebidServer'] = orgPrebidServerAdapter; @@ -64,23 +65,23 @@ describe('adapterManager tests', () => { config.setConfig({s2sConfig: { enabled: false }}); }); - describe('callBids', () => { - before(() => { + describe('callBids', function () { + before(function () { config.setConfig({s2sConfig: { enabled: false }}); }); - beforeEach(() => { + beforeEach(function () { sinon.stub(utils, 'logError'); appnexusAdapterMock.callBids.reset(); AdapterManager.bidderRegistry['appnexus'] = appnexusAdapterMock; }); - afterEach(() => { + afterEach(function () { utils.logError.restore(); delete AdapterManager.bidderRegistry['appnexus']; }); - it('should log an error if a bidder is used that does not exist', () => { + it('should log an error if a bidder is used that does not exist', function () { const adUnits = [{ code: 'adUnit-code', sizes: [[728, 90]], @@ -91,11 +92,12 @@ describe('adapterManager tests', () => { }]; let bidRequests = AdapterManager.makeBidRequests(adUnits, 1111, 2222, 1000); - AdapterManager.callBids(adUnits, bidRequests, () => {}, () => {}); + expect(bidRequests.length).to.equal(1); + expect(bidRequests[0].bidderCode).to.equal('appnexus'); sinon.assert.called(utils.logError); }); - it('should emit BID_REQUESTED event', () => { + it('should emit BID_REQUESTED event', function () { // function to count BID_REQUESTED events let cnt = 0; let count = () => cnt++; @@ -138,19 +140,20 @@ describe('adapterManager tests', () => { }); }); - describe('S2S tests', () => { - beforeEach(() => { + describe('S2S tests', function () { + beforeEach(function () { config.setConfig({s2sConfig: CONFIG}); AdapterManager.bidderRegistry['prebidServer'] = prebidServerAdapterMock; prebidServerAdapterMock.callBids.reset(); }); - it('invokes callBids on the S2S adapter', () => { + it('invokes callBids on the S2S adapter', function () { let bidRequests = [{ 'bidderCode': 'appnexus', 'auctionId': '1863e370099523', 'bidderRequestId': '2946b569352ef2', 'tid': '34566b569352ef2', + 'timeout': 1000, 'src': 's2s', 'adUnitsS2SCopy': [ { @@ -172,7 +175,7 @@ describe('adapterManager tests', () => { 'placementId': '543221', 'test': 'me' }, - 'placementCode': '/19968336/header-bid-tag1', + 'adUnitCode': '/19968336/header-bid-tag1', 'sizes': [ [ 728, @@ -188,7 +191,7 @@ describe('adapterManager tests', () => { 'auctionId': '1ff753bd4ae5cb', 'startTime': 1463510220995, 'status': 1, - 'bid_id': '378a8914450b334' + 'bid_id': '68136e1c47023d' } ] }, @@ -210,7 +213,7 @@ describe('adapterManager tests', () => { 'params': { 'placementId': '5324321' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -225,7 +228,7 @@ describe('adapterManager tests', () => { 'bidderRequestId': '55e24a66bed717', 'auctionId': '1ff753bd4ae5cb', 'startTime': 1463510220996, - 'bid_id': '387d9d9c32ca47c' + 'bid_id': '7e5d6af25ed188' } ] } @@ -292,7 +295,7 @@ describe('adapterManager tests', () => { }); // Enable this test when prebidServer adapter is made 1.0 compliant - it('invokes callBids with only s2s bids', () => { + it('invokes callBids with only s2s bids', function () { const adUnits = getAdUnits(); // adUnit without appnexus bidder adUnits.push({ @@ -315,6 +318,7 @@ describe('adapterManager tests', () => { 'bidderRequestId': '2946b569352ef2', 'tid': '34566b569352ef2', 'src': 's2s', + 'timeout': 1000, 'adUnitsS2SCopy': [ { 'code': '/19968336/header-bid-tag1', @@ -335,7 +339,7 @@ describe('adapterManager tests', () => { 'placementId': '543221', 'test': 'me' }, - 'placementCode': '/19968336/header-bid-tag1', + 'adUnitCode': '/19968336/header-bid-tag1', 'sizes': [ [ 728, @@ -373,7 +377,7 @@ describe('adapterManager tests', () => { 'params': { 'placementId': '5324321' }, - 'placementCode': '/19968336/header-bid-tag-0', + 'adUnitCode': '/19968336/header-bid-tag-0', 'sizes': [ [ 300, @@ -444,6 +448,7 @@ describe('adapterManager tests', () => { ], 'start': 1462918897460 }]; + AdapterManager.callBids( adUnits, bidRequests, @@ -455,21 +460,21 @@ describe('adapterManager tests', () => { sinon.assert.calledOnce(prebidServerAdapterMock.callBids); }); - describe('BID_REQUESTED event', () => { + describe('BID_REQUESTED event', function () { // function to count BID_REQUESTED events let cnt, count = () => cnt++; - beforeEach(() => { + beforeEach(function () { prebidServerAdapterMock.callBids.reset(); cnt = 0; events.on(CONSTANTS.EVENTS.BID_REQUESTED, count); }); - afterEach(() => { + afterEach(function () { events.off(CONSTANTS.EVENTS.BID_REQUESTED, count); }); - it('should fire for s2s requests', () => { + it('should fire for s2s requests', function () { let adUnits = utils.deepClone(getAdUnits()).map(adUnit => { adUnit.bids = adUnit.bids.filter(bid => includes(['appnexus'], bid.bidder)); return adUnit; @@ -480,7 +485,7 @@ describe('adapterManager tests', () => { sinon.assert.calledOnce(prebidServerAdapterMock.callBids); }); - it('should fire for simultaneous s2s and client requests', () => { + it('should fire for simultaneous s2s and client requests', function () { AdapterManager.bidderRegistry['adequant'] = adequantAdapterMock; let adUnits = utils.deepClone(getAdUnits()).map(adUnit => { adUnit.bids = adUnit.bids.filter(bid => includes(['adequant', 'appnexus'], bid.bidder)); @@ -497,7 +502,7 @@ describe('adapterManager tests', () => { }); }); // end s2s tests - describe('s2sTesting', () => { + describe('s2sTesting', function () { let doneStub = sinon.stub(); let ajaxStub = sinon.stub(); @@ -538,7 +543,7 @@ describe('adapterManager tests', () => { }); let stubGetSourceBidderMap; - beforeEach(() => { + beforeEach(function () { config.setConfig({s2sConfig: TESTING_CONFIG}); AdapterManager.bidderRegistry['prebidServer'] = prebidServerAdapterMock; AdapterManager.bidderRegistry['adequant'] = adequantAdapterMock; @@ -553,12 +558,12 @@ describe('adapterManager tests', () => { rubiconAdapterMock.callBids.reset(); }); - afterEach(() => { + afterEach(function () { config.setConfig({s2sConfig: {}}); s2sTesting.getSourceBidderMap.restore(); }); - it('calls server adapter if no sources defined', () => { + it('calls server adapter if no sources defined', function () { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: [], [s2sTesting.SERVER]: []}); callBids(); @@ -572,7 +577,7 @@ describe('adapterManager tests', () => { sinon.assert.notCalled(adequantAdapterMock.callBids); }); - it('calls client adapter if one client source defined', () => { + it('calls client adapter if one client source defined', function () { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus'], [s2sTesting.SERVER]: []}); callBids(); @@ -586,7 +591,7 @@ describe('adapterManager tests', () => { sinon.assert.notCalled(adequantAdapterMock.callBids); }); - it('calls client adapters if client sources defined', () => { + it('calls client adapters if client sources defined', function () { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); callBids(); @@ -600,7 +605,7 @@ describe('adapterManager tests', () => { checkClientCalled(adequantAdapterMock, 2); }); - it('calls client adapters if client sources defined', () => { + it('calls client adapters if client sources defined', function () { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); callBids(); @@ -614,7 +619,7 @@ describe('adapterManager tests', () => { checkClientCalled(adequantAdapterMock, 2); }); - it('does not call server adapter for bidders that go to client', () => { + it('does not call server adapter for bidders that go to client', function () { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); var adUnits = getTestAdUnits(); adUnits[0].bids[0].finalSource = s2sTesting.CLIENT; @@ -633,7 +638,7 @@ describe('adapterManager tests', () => { checkClientCalled(adequantAdapterMock, 2); }); - it('does not call client adapters for bidders that go to server', () => { + it('does not call client adapters for bidders that go to server', function () { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); var adUnits = getTestAdUnits(); adUnits[0].bids[0].finalSource = s2sTesting.SERVER; @@ -652,7 +657,7 @@ describe('adapterManager tests', () => { sinon.assert.notCalled(adequantAdapterMock.callBids); }); - it('calls client and server adapters for bidders that go to both', () => { + it('calls client and server adapters for bidders that go to both', function () { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); var adUnits = getTestAdUnits(); adUnits[0].bids[0].finalSource = s2sTesting.BOTH; @@ -671,7 +676,7 @@ describe('adapterManager tests', () => { checkClientCalled(adequantAdapterMock, 2); }); - it('makes mixed client/server adapter calls for mixed bidder sources', () => { + it('makes mixed client/server adapter calls for mixed bidder sources', function () { stubGetSourceBidderMap.returns({[s2sTesting.CLIENT]: ['appnexus', 'adequant'], [s2sTesting.SERVER]: []}); var adUnits = getTestAdUnits(); adUnits[0].bids[0].finalSource = s2sTesting.CLIENT; @@ -697,7 +702,7 @@ describe('adapterManager tests', () => { describe('using bidderFactory', function() { let spec; - beforeEach(() => { + beforeEach(function () { spec = { code: CODE, isBidRequestValid: () => {}, @@ -716,28 +721,58 @@ describe('adapterManager tests', () => { expect(AdapterManager.videoAdapters).to.include(alias); }); }); + + describe('special case for s2s-only bidders', function () { + beforeEach(function () { + sinon.stub(utils, 'logError'); + }); + + afterEach(function () { + config.resetConfig(); + utils.logError.restore(); + }); + + it('should allow an alias if alias is part of s2sConfig.bidders', function () { + let testS2sConfig = utils.deepClone(CONFIG); + testS2sConfig.bidders = ['s2sAlias']; + config.setConfig({s2sConfig: testS2sConfig}); + + AdapterManager.aliasBidAdapter('s2sBidder', 's2sAlias'); + expect(AdapterManager.aliasRegistry).to.have.property('s2sAlias'); + }); + + it('should throw an error if alias + bidder are unknown and not part of s2sConfig.bidders', function () { + let testS2sConfig = utils.deepClone(CONFIG); + testS2sConfig.bidders = ['s2sAlias']; + config.setConfig({s2sConfig: testS2sConfig}); + + AdapterManager.aliasBidAdapter('s2sBidder1', 's2sAlias1'); + sinon.assert.calledOnce(utils.logError); + expect(AdapterManager.aliasRegistry).to.not.have.property('s2sAlias1'); + }); + }); }); - describe('makeBidRequests', () => { + describe('makeBidRequests', function () { let adUnits; - beforeEach(() => { + beforeEach(function () { adUnits = utils.deepClone(getAdUnits()).map(adUnit => { adUnit.bids = adUnit.bids.filter(bid => includes(['appnexus', 'rubicon'], bid.bidder)); return adUnit; }) }); - describe('setBidderSequence', () => { - beforeEach(() => { + describe('setBidderSequence', function () { + beforeEach(function () { sinon.spy(utils, 'shuffle'); }); - afterEach(() => { + afterEach(function () { config.resetConfig(); utils.shuffle.restore(); }); - it('setting to `random` uses shuffled order of adUnits', () => { + it('setting to `random` uses shuffled order of adUnits', function () { config.setConfig({ bidderSequence: 'random' }); let bidRequests = AdapterManager.makeBidRequests( adUnits, @@ -750,17 +785,18 @@ describe('adapterManager tests', () => { }); }); - describe('sizeMapping', () => { - beforeEach(() => { + describe('sizeMapping', function () { + beforeEach(function () { sinon.stub(window, 'matchMedia').callsFake(() => ({matches: true})); }); - afterEach(() => { + afterEach(function () { matchMedia.restore(); + config.resetConfig(); setSizeConfig([]); }); - it('should not filter bids w/ no labels', () => { + it('should not filter bids w/ no labels', function () { let bidRequests = AdapterManager.makeBidRequests( adUnits, Date.now(), @@ -780,7 +816,7 @@ describe('adapterManager tests', () => { expect(appnexusBidRequests.bids[1].sizes).to.deep.equal(find(adUnits, adUnit => adUnit.code === appnexusBidRequests.bids[1].adUnitCode).sizes); }); - it('should filter sizes using size config', () => { + it('should filter sizes using size config', function () { let validSizes = [ [728, 90], [300, 250] @@ -832,7 +868,7 @@ describe('adapterManager tests', () => { expect(bidRequests.length).to.equal(0); }); - it('should filter adUnits/bidders based on applied labels', () => { + it('should filter adUnits/bidders based on applied labels', function () { adUnits[0].labelAll = ['visitor-uk', 'mobile']; adUnits[1].labelAny = ['visitor-uk', 'desktop']; adUnits[1].bids[0].labelAny = ['mobile']; @@ -852,10 +888,37 @@ describe('adapterManager tests', () => { expect(bidRequests[0].bids.length).to.equal(1); expect(bidRequests[0].bids[0].adUnitCode).to.equal(adUnits[1].code); }); + + it('should filter adUnits/bidders based on applid labels for s2s requests', function () { + adUnits[0].labelAll = ['visitor-uk', 'mobile']; + adUnits[1].labelAny = ['visitor-uk', 'desktop']; + adUnits[1].bids[0].labelAny = ['mobile']; + adUnits[1].bids[1].labelAll = ['desktop']; + + let TESTING_CONFIG = utils.deepClone(CONFIG); + TESTING_CONFIG.bidders = ['appnexus', 'rubicon']; + config.setConfig({ s2sConfig: TESTING_CONFIG }); + + let bidRequests = AdapterManager.makeBidRequests( + adUnits, + Date.now(), + utils.getUniqueIdentifierStr(), + function callback() {}, + ['visitor-uk', 'desktop'] + ); + + expect(bidRequests.length).to.equal(1); + expect(bidRequests[0].adUnitsS2SCopy.length).to.equal(1); + expect(bidRequests[0].adUnitsS2SCopy[0].bids.length).to.equal(1); + expect(bidRequests[0].adUnitsS2SCopy[0].bids[0].bidder).to.equal('rubicon'); + expect(bidRequests[0].adUnitsS2SCopy[0].bids[0].adUnitCode).to.equal(adUnits[1].code); + expect(bidRequests[0].adUnitsS2SCopy[0].bids[0].bid_id).to.equal(bidRequests[0].bids[0].bid_id); + expect(bidRequests[0].adUnitsS2SCopy[0].labelAny).to.deep.equal(['visitor-uk', 'desktop']); + }); }); - describe('gdpr consent module', () => { - it('inserts gdprConsent object to bidRequest only when module was enabled', () => { + describe('gdpr consent module', function () { + it('inserts gdprConsent object to bidRequest only when module was enabled', function () { AdapterManager.gdprDataHandler.setConsentData({ consentString: 'abc123def456', consentRequired: true @@ -885,17 +948,17 @@ describe('adapterManager tests', () => { }); }); - describe('isValidBidRequest', () => { - describe('positive tests for validating bid request', () => { - beforeEach(() => { + describe('isValidBidRequest', function () { + describe('positive tests for validating bid request', function () { + beforeEach(function () { sinon.stub(utils, 'logInfo'); }); - afterEach(() => { + afterEach(function () { utils.logInfo.restore(); }); - it('should maintain adUnit structure and adUnits.sizes is replaced', () => { + it('should maintain adUnit structure and adUnits.sizes is replaced', function () { let fullAdUnit = [{ sizes: [[300, 250], [300, 600]], mediaTypes: { @@ -979,18 +1042,32 @@ describe('adapterManager tests', () => { expect(result[0].mediaTypes.video).to.exist; sinon.assert.calledOnce(utils.logInfo); }); + + it('should normalize adUnit.sizes and adUnit.mediaTypes.banner.sizes', function () { + let fullAdUnit = [{ + sizes: [300, 250], + mediaTypes: { + banner: { + sizes: [300, 250] + } + } + }]; + let result = checkBidRequestSizes(fullAdUnit); + expect(result[0].sizes).to.deep.equal([[300, 250]]); + expect(result[0].mediaTypes.banner.sizes).to.deep.equal([[300, 250]]); + }); }); - describe('negative tests for validating bid requests', () => { - beforeEach(() => { + describe('negative tests for validating bid requests', function () { + beforeEach(function () { sinon.stub(utils, 'logError'); }); - afterEach(() => { + afterEach(function () { utils.logError.restore(); }); - it('should throw error message and delete an object/property', () => { + it('should throw error message and delete an object/property', function () { let badBanner = [{ sizes: [[300, 250], [300, 600]], mediaTypes: { diff --git a/test/spec/unit/core/bidderFactory_spec.js b/test/spec/unit/core/bidderFactory_spec.js index ca2a9afc103..6cc4a0b172c 100644 --- a/test/spec/unit/core/bidderFactory_spec.js +++ b/test/spec/unit/core/bidderFactory_spec.js @@ -29,13 +29,13 @@ const MOCK_BIDS_REQUEST = { ] } -describe('bidders created by newBidder', () => { +describe('bidders created by newBidder', function () { let spec; let bidder; let addBidResponseStub; let doneStub; - beforeEach(() => { + beforeEach(function () { spec = { code: CODE, isBidRequestValid: sinon.stub(), @@ -48,20 +48,20 @@ describe('bidders created by newBidder', () => { doneStub = sinon.stub(); }); - describe('when the ajax response is irrelevant', () => { + describe('when the ajax response is irrelevant', function () { let ajaxStub; - beforeEach(() => { + beforeEach(function () { ajaxStub = sinon.stub(ajax, 'ajax'); addBidResponseStub.reset(); doneStub.reset(); }); - afterEach(() => { + afterEach(function () { ajaxStub.restore(); }); - it('should handle bad bid requests gracefully', () => { + it('should handle bad bid requests gracefully', function () { const bidder = newBidder(spec); spec.getUserSyncs.returns([]); @@ -75,7 +75,7 @@ describe('bidders created by newBidder', () => { expect(spec.interpretResponse.called).to.equal(false); }); - it('should call buildRequests(bidRequest) the params are valid', () => { + it('should call buildRequests(bidRequest) the params are valid', function () { const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); @@ -89,7 +89,7 @@ describe('bidders created by newBidder', () => { expect(spec.buildRequests.firstCall.args[0]).to.deep.equal(MOCK_BIDS_REQUEST.bids); }); - it('should not call buildRequests the params are invalid', () => { + it('should not call buildRequests the params are invalid', function () { const bidder = newBidder(spec); spec.isBidRequestValid.returns(false); @@ -102,7 +102,7 @@ describe('bidders created by newBidder', () => { expect(spec.buildRequests.called).to.equal(false); }); - it('should filter out invalid bids before calling buildRequests', () => { + it('should filter out invalid bids before calling buildRequests', function () { const bidder = newBidder(spec); spec.isBidRequestValid.onFirstCall().returns(true); @@ -117,7 +117,7 @@ describe('bidders created by newBidder', () => { expect(spec.buildRequests.firstCall.args[0]).to.deep.equal([MOCK_BIDS_REQUEST.bids[0]]); }); - it('should make no server requests if the spec doesn\'t return any', () => { + it('should make no server requests if the spec doesn\'t return any', function () { const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); @@ -128,7 +128,7 @@ describe('bidders created by newBidder', () => { expect(ajaxStub.called).to.equal(false); }); - it('should make the appropriate POST request', () => { + it('should make the appropriate POST request', function () { const bidder = newBidder(spec); const url = 'test.url.com'; const data = { arg: 2 }; @@ -151,7 +151,7 @@ describe('bidders created by newBidder', () => { }); }); - it('should make the appropriate POST request when options are passed', () => { + it('should make the appropriate POST request when options are passed', function () { const bidder = newBidder(spec); const url = 'test.url.com'; const data = { arg: 2 }; @@ -176,7 +176,7 @@ describe('bidders created by newBidder', () => { }); }); - it('should make the appropriate GET request', () => { + it('should make the appropriate GET request', function () { const bidder = newBidder(spec); const url = 'test.url.com'; const data = { arg: 2 }; @@ -198,7 +198,7 @@ describe('bidders created by newBidder', () => { }); }); - it('should make the appropriate GET request when options are passed', () => { + it('should make the appropriate GET request when options are passed', function () { const bidder = newBidder(spec); const url = 'test.url.com'; const data = { arg: 2 }; @@ -222,7 +222,7 @@ describe('bidders created by newBidder', () => { }); }); - it('should make multiple calls if the spec returns them', () => { + it('should make multiple calls if the spec returns them', function () { const bidder = newBidder(spec); const url = 'test.url.com'; const data = { arg: 2 }; @@ -245,7 +245,7 @@ describe('bidders created by newBidder', () => { expect(ajaxStub.calledTwice).to.equal(true); }); - it('should not add bids for each placement code if no requests are given', () => { + it('should not add bids for each placement code if no requests are given', function () { const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); @@ -259,12 +259,12 @@ describe('bidders created by newBidder', () => { }); }); - describe('when the ajax call succeeds', () => { + describe('when the ajax call succeeds', function () { let ajaxStub; let userSyncStub; let logErrorSpy; - beforeEach(() => { + beforeEach(function () { ajaxStub = sinon.stub(ajax, 'ajax').callsFake(function(url, callbacks) { const fakeResponse = sinon.stub(); fakeResponse.returns('headerContent'); @@ -276,13 +276,13 @@ describe('bidders created by newBidder', () => { logErrorSpy = sinon.spy(utils, 'logError'); }); - afterEach(() => { + afterEach(function () { ajaxStub.restore(); userSyncStub.restore(); utils.logError.restore(); }); - it('should call spec.interpretResponse() with the response content', () => { + it('should call spec.interpretResponse() with the response content', function () { const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); @@ -307,7 +307,7 @@ describe('bidders created by newBidder', () => { expect(doneStub.calledOnce).to.equal(true); }); - it('should call spec.interpretResponse() once for each request made', () => { + it('should call spec.interpretResponse() once for each request made', function () { const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); @@ -331,7 +331,7 @@ describe('bidders created by newBidder', () => { expect(doneStub.calledOnce).to.equal(true); }); - it('should only add bids for valid adUnit code into the auction, even if the bidder doesn\'t bid on all of them', () => { + it('should only add bids for valid adUnit code into the auction, even if the bidder doesn\'t bid on all of them', function () { const bidder = newBidder(spec); const bid = { @@ -364,7 +364,7 @@ describe('bidders created by newBidder', () => { expect(logErrorSpy.callCount).to.equal(0); }); - it('should call spec.getUserSyncs() with the response', () => { + it('should call spec.getUserSyncs() with the response', function () { const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); @@ -384,7 +384,7 @@ describe('bidders created by newBidder', () => { expect(spec.getUserSyncs.firstCall.args[1][0].headers.get).to.be.a('function'); }); - it('should register usersync pixels', () => { + it('should register usersync pixels', function () { const bidder = newBidder(spec); spec.isBidRequestValid.returns(false); @@ -402,7 +402,7 @@ describe('bidders created by newBidder', () => { expect(userSyncStub.firstCall.args[2]).to.equal('usersync.com'); }); - it('should logError when required bid response params are missing', () => { + it('should logError when required bid response params are missing', function () { const bidder = newBidder(spec); const bid = { @@ -427,12 +427,42 @@ describe('bidders created by newBidder', () => { expect(logErrorSpy.calledOnce).to.equal(true); }); + + it('should logError when required bid response params are undefined', function () { + const bidder = newBidder(spec); + + const bid = { + 'ad': 'creative', + 'cpm': '1.99', + 'width': 300, + 'height': 250, + 'requestId': '1', + 'creativeId': 'some-id', + 'currency': undefined, + 'netRevenue': true, + 'ttl': 360 + }; + + spec.isBidRequestValid.returns(true); + spec.buildRequests.returns({ + method: 'POST', + url: 'test.url.com', + data: {} + }); + spec.getUserSyncs.returns([]); + + spec.interpretResponse.returns(bid); + + bidder.callBids(MOCK_BIDS_REQUEST, addBidResponseStub, doneStub, ajaxStub); + + expect(logErrorSpy.calledOnce).to.equal(true); + }); }); - describe('when the ajax call fails', () => { + describe('when the ajax call fails', function () { let ajaxStub; - beforeEach(() => { + beforeEach(function () { ajaxStub = sinon.stub(ajax, 'ajax').callsFake(function(url, callbacks) { callbacks.error('ajax call failed.'); }); @@ -440,11 +470,11 @@ describe('bidders created by newBidder', () => { doneStub.reset(); }); - afterEach(() => { + afterEach(function () { ajaxStub.restore(); }); - it('should not spec.interpretResponse()', () => { + it('should not spec.interpretResponse()', function () { const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); @@ -461,7 +491,7 @@ describe('bidders created by newBidder', () => { expect(doneStub.calledOnce).to.equal(true); }); - it('should not add bids for each adunit code into the auction', () => { + it('should not add bids for each adunit code into the auction', function () { const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); @@ -479,7 +509,7 @@ describe('bidders created by newBidder', () => { expect(doneStub.calledOnce).to.equal(true); }); - it('should call spec.getUserSyncs() with no responses', () => { + it('should call spec.getUserSyncs() with no responses', function () { const bidder = newBidder(spec); spec.isBidRequestValid.returns(true); @@ -499,16 +529,16 @@ describe('bidders created by newBidder', () => { }); }); -describe('registerBidder', () => { +describe('registerBidder', function () { let registerBidAdapterStub; let aliasBidAdapterStub; - beforeEach(() => { + beforeEach(function () { registerBidAdapterStub = sinon.stub(adaptermanager, 'registerBidAdapter'); aliasBidAdapterStub = sinon.stub(adaptermanager, 'aliasBidAdapter'); }); - afterEach(() => { + afterEach(function () { registerBidAdapterStub.restore(); aliasBidAdapterStub.restore(); }); @@ -522,7 +552,7 @@ describe('registerBidder', () => { }; } - it('should register a bidder with the adapterManager', () => { + it('should register a bidder with the adapterManager', function () { registerBidder(newEmptySpec()); expect(registerBidAdapterStub.calledOnce).to.equal(true); expect(registerBidAdapterStub.firstCall.args[0]).to.have.property('callBids'); @@ -532,14 +562,14 @@ describe('registerBidder', () => { expect(registerBidAdapterStub.firstCall.args[2]).to.be.undefined; }); - it('should register a bidder with the appropriate mediaTypes', () => { + it('should register a bidder with the appropriate mediaTypes', function () { const thisSpec = Object.assign(newEmptySpec(), { supportedMediaTypes: ['video'] }); registerBidder(thisSpec); expect(registerBidAdapterStub.calledOnce).to.equal(true); expect(registerBidAdapterStub.firstCall.args[2]).to.deep.equal({supportedMediaTypes: ['video']}); }); - it('should register bidders with the appropriate aliases', () => { + it('should register bidders with the appropriate aliases', function () { const thisSpec = Object.assign(newEmptySpec(), { aliases: ['foo', 'bar'] }); registerBidder(thisSpec); @@ -556,7 +586,7 @@ describe('registerBidder', () => { }); }) -describe('validate bid response: ', () => { +describe('validate bid response: ', function () { let spec; let bidder; let addBidResponseStub; @@ -576,7 +606,7 @@ describe('validate bid response: ', () => { 'ttl': 360 }]; - beforeEach(() => { + beforeEach(function () { spec = { code: CODE, isBidRequestValid: sinon.stub(), @@ -601,12 +631,12 @@ describe('validate bid response: ', () => { logErrorSpy = sinon.spy(utils, 'logError'); }); - afterEach(() => { + afterEach(function () { ajaxStub.restore(); logErrorSpy.restore(); }); - it('should add native bids that do have required assets', () => { + it('should add native bids that do have required assets', function () { let bidRequest = { bids: [{ bidId: 1, @@ -643,7 +673,7 @@ describe('validate bid response: ', () => { expect(logErrorSpy.callCount).to.equal(0); }); - it('should not add native bids that do not have required assets', () => { + it('should not add native bids that do not have required assets', function () { let bidRequest = { bids: [{ bidId: 1, @@ -679,7 +709,7 @@ describe('validate bid response: ', () => { expect(logErrorSpy.callCount).to.equal(1); }); - it('should add bid when renderer is present on outstream bids', () => { + it('should add bid when renderer is present on outstream bids', function () { let bidRequest = { bids: [{ bidId: 1, @@ -713,7 +743,7 @@ describe('validate bid response: ', () => { expect(logErrorSpy.callCount).to.equal(0); }); - it('should add banner bids that have no width or height but single adunit size', () => { + it('should add banner bids that have no width or height but single adunit size', function () { let bidRequest = { bids: [{ bidder: CODE, diff --git a/test/spec/unit/core/targeting_spec.js b/test/spec/unit/core/targeting_spec.js index 048e19a6177..a72992e099d 100644 --- a/test/spec/unit/core/targeting_spec.js +++ b/test/spec/unit/core/targeting_spec.js @@ -30,6 +30,7 @@ const bid1 = { 'hb_bidder': 'rubicon', 'hb_adid': '148018fe5e', 'hb_pb': '0.53', + 'hb_deal': '1234', 'foobar': '300x250' }, 'netRevenue': true, @@ -97,13 +98,13 @@ const bid3 = { 'ttl': 300 }; -describe('targeting tests', () => { - describe('getAllTargeting', () => { +describe('targeting tests', function () { + describe('getAllTargeting', function () { let amBidsReceivedStub; let amGetAdUnitsStub; let bidExpiryStub; - beforeEach(() => { + beforeEach(function () { $$PREBID_GLOBAL$$._sendAllBids = false; amBidsReceivedStub = sinon.stub(auctionManager, 'getBidsReceived').callsFake(function() { return [bid1, bid2, bid3]; @@ -111,23 +112,35 @@ describe('targeting tests', () => { amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnitCodes').callsFake(function() { return ['/123456/header-bid-tag-0']; }); - bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired').returns(true); + bidExpiryStub = sinon.stub(targetingModule, 'isBidNotExpired').returns(true); }); - afterEach(() => { + afterEach(function () { auctionManager.getBidsReceived.restore(); auctionManager.getAdUnitCodes.restore(); - targetingModule.isBidExpired.restore(); + targetingModule.isBidNotExpired.restore(); }); - it('selects the top bid when _sendAllBids true', () => { + describe('when hb_deal is present in bid.adserverTargeting', function () { + it('returns targeting with both hb_deal and hb_deal_{bidder_code}', function () { + const targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + + // We should add both keys rather than one or the other + expect(targeting['/123456/header-bid-tag-0']).to.contain.keys('hb_deal', `hb_deal_${bid1.bidderCode}`); + + // We should assign both keys the same value + expect(targeting['/123456/header-bid-tag-0']['hb_deal']).to.deep.equal(targeting['/123456/header-bid-tag-0'][`hb_deal_${bid1.bidderCode}`]); + }); + }); + + it('selects the top bid when _sendAllBids true', function () { config.setConfig({ enableSendAllBids: true }); let targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); // we should only get the targeting data for the one requested adunit expect(Object.keys(targeting).length).to.equal(1); - let sendAllBidCpm = Object.keys(targeting['/123456/header-bid-tag-0']).filter(key => key.indexOf('hb_pb_') != -1) + let sendAllBidCpm = Object.keys(targeting['/123456/header-bid-tag-0']).filter(key => key.indexOf('hb_pb_') != -1); // we shouldn't get more than 1 key for hb_pb_${bidder} expect(sendAllBidCpm.length).to.equal(1); @@ -136,21 +149,51 @@ describe('targeting tests', () => { }); }); // end getAllTargeting tests - describe('Targeting in concurrent auctions', () => { - describe('check getOldestBid', () => { + describe('getAllTargeting without bids return empty object', function () { + let amBidsReceivedStub; + let amGetAdUnitsStub; + let bidExpiryStub; + + beforeEach(function () { + $$PREBID_GLOBAL$$._sendAllBids = false; + amBidsReceivedStub = sinon.stub(auctionManager, 'getBidsReceived').callsFake(function() { + return []; + }); + amGetAdUnitsStub = sinon.stub(auctionManager, 'getAdUnitCodes').callsFake(function() { + return ['/123456/header-bid-tag-0']; + }); + bidExpiryStub = sinon.stub(targetingModule, 'isBidNotExpired').returns(true); + }); + + afterEach(function () { + auctionManager.getBidsReceived.restore(); + auctionManager.getAdUnitCodes.restore(); + targetingModule.isBidNotExpired.restore(); + }); + + it('returns targetingSet correctly', function () { + let targeting = targetingInstance.getAllTargeting(['/123456/header-bid-tag-0']); + + // we should only get the targeting data for the one requested adunit to at least exist even though it has no keys to set + expect(Object.keys(targeting).length).to.equal(1); + }); + }); // end getAllTargeting without bids return empty object + + describe('Targeting in concurrent auctions', function () { + describe('check getOldestBid', function () { let bidExpiryStub; let auctionManagerStub; - beforeEach(() => { - bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired').returns(true); + beforeEach(function () { + bidExpiryStub = sinon.stub(targetingModule, 'isBidNotExpired').returns(true); auctionManagerStub = sinon.stub(auctionManager, 'getBidsReceived'); }); - afterEach(() => { + afterEach(function () { bidExpiryStub.restore(); auctionManagerStub.restore(); }); - it('should use bids from pool to get Winning Bid', () => { + it('should use bids from pool to get Winning Bid', function () { let bidsReceived = [ createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1'}), createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2'}), @@ -166,7 +209,7 @@ describe('targeting tests', () => { expect(bids[1].adId).to.equal('adid-2'); }); - it('should not use rendered bid to get winning bid', () => { + it('should not use rendered bid to get winning bid', function () { let bidsReceived = [ createBidReceived({bidder: 'appnexus', cpm: 8, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', status: 'rendered'}), createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2'}), @@ -183,7 +226,7 @@ describe('targeting tests', () => { expect(bids[1].adId).to.equal('adid-3'); }); - it('should use highest cpm bid from bid pool to get winning bid', () => { + it('should use highest cpm bid from bid pool to get winning bid', function () { // Pool is having 4 bids from 2 auctions. There are 2 bids from rubicon, #2 which is highest cpm bid will be selected to take part in auction. let bidsReceived = [ createBidReceived({bidder: 'appnexus', cpm: 8, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1'}), @@ -201,19 +244,19 @@ describe('targeting tests', () => { }); }); - describe('check bidExpiry', () => { + describe('check bidExpiry', function () { let auctionManagerStub; let timestampStub; - beforeEach(() => { + beforeEach(function () { auctionManagerStub = sinon.stub(auctionManager, 'getBidsReceived'); timestampStub = sinon.stub(utils, 'timestamp'); }); - afterEach(() => { + afterEach(function () { auctionManagerStub.restore(); timestampStub.restore(); }); - it('should not include expired bids in the auction', () => { + it('should not include expired bids in the auction', function () { timestampStub.returns(200000); // Pool is having 4 bids from 2 auctions. All the bids are expired and only bid #3 is passing the bidExpiry check. let bidsReceived = [ diff --git a/test/spec/unit/pbjs_api_spec.js b/test/spec/unit/pbjs_api_spec.js index ca4e5e7e5f9..41e40100011 100644 --- a/test/spec/unit/pbjs_api_spec.js +++ b/test/spec/unit/pbjs_api_spec.js @@ -9,7 +9,7 @@ import { createBidReceived } from 'test/fixtures/fixtures'; import { auctionManager, newAuctionManager } from 'src/auctionManager'; -import { targeting, newTargeting } from 'src/targeting'; +import { targeting, newTargeting, RENDERED } from 'src/targeting'; import { config as configObj } from 'src/config'; import * as ajaxLib from 'src/ajax'; import * as auctionModule from 'src/auction'; @@ -149,17 +149,17 @@ window.apntag = { describe('Unit: Prebid Module', function () { let bidExpiryStub; - before(() => { - bidExpiryStub = sinon.stub(targetingModule, 'isBidExpired').callsFake(() => true); + before(function () { + bidExpiryStub = sinon.stub(targetingModule, 'isBidNotExpired').callsFake(() => true); }); after(function() { $$PREBID_GLOBAL$$.adUnits = []; - targetingModule.isBidExpired.restore(); + targetingModule.isBidNotExpired.restore(); }); describe('getAdserverTargetingForAdUnitCodeStr', function () { - beforeEach(() => { + beforeEach(function () { resetAuction(); }); @@ -192,23 +192,23 @@ describe('Unit: Prebid Module', function () { }); describe('getAdServerTargeting', function () { - beforeEach(() => { + beforeEach(function () { resetAuction(); }); - afterEach(() => { + afterEach(function () { resetAuction(); }); it('should return current targeting data for slots', function () { $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); - const targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); - const expected = getAdServerTargeting(); + const targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); + const expected = getAdServerTargeting(['/19968336/header-bid-tag-0, /19968336/header-bid-tag1']); assert.deepEqual(targeting, expected, 'targeting ok'); }); - it('should return correct targeting with default settings', () => { - var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); + it('should return correct targeting with default settings', function () { + var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); var expected = { '/19968336/header-bid-tag-0': { foobar: '0x0,300x250,300x600', @@ -228,14 +228,14 @@ describe('Unit: Prebid Module', function () { assert.deepEqual(targeting, expected); }); - it('should return correct targeting with bid landscape targeting on', () => { + it('should return correct targeting with bid landscape targeting on', function () { $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); - var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); - var expected = getAdServerTargeting(); + var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); + var expected = getAdServerTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); assert.deepEqual(targeting, expected); }); - it("should include a losing bid's custom ad targeting key", () => { + it("should include a losing bid's custom ad targeting key", function () { // Let's make sure we're getting the expected losing bid. assert.equal(auction.getBidsReceived()[0]['bidderCode'], 'triplelift'); assert.equal(auction.getBidsReceived()[0]['cpm'], 0.112256); @@ -248,7 +248,7 @@ describe('Unit: Prebid Module', function () { auction.getBidsReceived = function() { return _bidsReceived }; - var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); + var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); // Ensure targeting for both ad placements includes the custom key. assert.equal( @@ -276,7 +276,7 @@ describe('Unit: Prebid Module', function () { assert.deepEqual(targeting, expected); }); - it('should not overwrite winning bids custom keys targeting key', () => { + it('should not overwrite winning bids custom keys targeting key', function () { resetAuction(); // mimic a bidderSetting.standard key here for each bid and alwaysUseBid true for every bid let _bidsReceived = getBidResponses(); @@ -312,7 +312,7 @@ describe('Unit: Prebid Module', function () { } }; - var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); + var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); var expected = { '/19968336/header-bid-tag-0': { @@ -337,7 +337,7 @@ describe('Unit: Prebid Module', function () { $$PREBID_GLOBAL$$.bidderSettings = {}; }); - it('should not send standard targeting keys when the bid has `sendStandardTargeting` set to `false`', () => { + it('should not send standard targeting keys when the bid has `sendStandardTargeting` set to `false`', function () { let _bidsReceived = getBidResponses(); _bidsReceived.forEach(bid => { bid.adserverTargeting.custom_ad_id = bid.adId; @@ -346,7 +346,7 @@ describe('Unit: Prebid Module', function () { auction.getBidsReceived = function() { return _bidsReceived }; - var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(); + var targeting = $$PREBID_GLOBAL$$.getAdserverTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); var expected = { '/19968336/header-bid-tag-0': { @@ -411,7 +411,7 @@ describe('Unit: Prebid Module', function () { }] }; - before(() => { + before(function () { $$PREBID_GLOBAL$$.bidderSettings = {}; currentPriceBucket = configObj.getConfig('priceGranularity'); configObj.setConfig({ priceGranularity: customConfigObject }); @@ -447,12 +447,12 @@ describe('Unit: Prebid Module', function () { )); }); - after(() => { + after(function () { configObj.setConfig({ priceGranularity: currentPriceBucket }); adaptermanager.makeBidRequests.restore(); }) - beforeEach(() => { + beforeEach(function () { let auctionManagerInstance = newAuctionManager(); targeting = newTargeting(auctionManagerInstance); let adUnits = [{ @@ -476,32 +476,32 @@ describe('Unit: Prebid Module', function () { }); }); - afterEach(() => { + afterEach(function () { ajaxStub.restore(); }); - it('should get correct hb_pb when using bid.cpm is between 0 to 5', () => { + it('should get correct hb_pb when using bid.cpm is between 0 to 5', function () { RESPONSE.tags[0].ads[0].cpm = 2.1234; auction.callBids(cbTimeout); let bidTargeting = targeting.getAllTargeting(); expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('2.12'); }); - it('should get correct hb_pb when using bid.cpm is between 5 to 8', () => { + it('should get correct hb_pb when using bid.cpm is between 5 to 8', function () { RESPONSE.tags[0].ads[0].cpm = 6.78; auction.callBids(cbTimeout); let bidTargeting = targeting.getAllTargeting(); expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('6.75'); }); - it('should get correct hb_pb when using bid.cpm is between 8 to 20', () => { + it('should get correct hb_pb when using bid.cpm is between 8 to 20', function () { RESPONSE.tags[0].ads[0].cpm = 19.5234; auction.callBids(cbTimeout); let bidTargeting = targeting.getAllTargeting(); expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('19.50'); }); - it('should get correct hb_pb when using bid.cpm is between 20 to 25', () => { + it('should get correct hb_pb when using bid.cpm is between 20 to 25', function () { RESPONSE.tags[0].ads[0].cpm = 21.5234; auction.callBids(cbTimeout); let bidTargeting = targeting.getAllTargeting(); @@ -678,7 +678,7 @@ describe('Unit: Prebid Module', function () { }); }; - before(() => { + before(function () { currentPriceBucket = configObj.getConfig('priceGranularity'); sinon.stub(adaptermanager, 'makeBidRequests').callsFake(() => ([{ 'bidderCode': 'appnexus', @@ -711,16 +711,16 @@ describe('Unit: Prebid Module', function () { }])); }); - after(() => { + after(function () { configObj.setConfig({ priceGranularity: currentPriceBucket }); adaptermanager.makeBidRequests.restore(); }) - afterEach(() => { + afterEach(function () { ajaxStub.restore(); }); - it('should get correct hb_pb with cpm between 0 - 5', () => { + it('should get correct hb_pb with cpm between 0 - 5', function () { initTestConfig({ adUnits: [createAdUnit('div-gpt-ad-1460505748561-0')], adUnitCodes: ['div-gpt-ad-1460505748561-0'] @@ -734,7 +734,7 @@ describe('Unit: Prebid Module', function () { expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('3.25'); }); - it('should get correct hb_pb with cpm between 21 - 100', () => { + it('should get correct hb_pb with cpm between 21 - 100', function () { initTestConfig({ adUnits: [createAdUnit('div-gpt-ad-1460505748561-0')], adUnitCodes: ['div-gpt-ad-1460505748561-0'] @@ -748,7 +748,7 @@ describe('Unit: Prebid Module', function () { expect(bidTargeting['div-gpt-ad-1460505748561-0']['hb_pb']).to.equal('43.00'); }); - it('should only apply price granularity if bid media type matches', () => { + it('should only apply price granularity if bid media type matches', function () { initTestConfig({ adUnits: [ createAdUnit('div-gpt-ad-1460505748561-0', 'video') ], adUnitCodes: ['div-gpt-ad-1460505748561-0'] @@ -770,7 +770,7 @@ describe('Unit: Prebid Module', function () { assert.deepEqual(result, compare, 'expected bid responses are returned'); }); - it('should return bid responses for most recent requestId only', () => { + it('should return bid responses for most recent requestId only', function () { const responses = $$PREBID_GLOBAL$$.getBidResponses(); assert.equal(responses[Object.keys(responses)[0]].bids.length, 4); }); @@ -789,12 +789,12 @@ describe('Unit: Prebid Module', function () { describe('setTargetingForGPTAsync', function () { let logErrorSpy; - beforeEach(() => { + beforeEach(function () { logErrorSpy = sinon.spy(utils, 'logError'); resetAuction(); }); - afterEach(() => { + afterEach(function () { utils.logError.restore(); resetAuction(); }); @@ -1024,7 +1024,7 @@ describe('Unit: Prebid Module', function () { assert.ok(spyLogError.calledWith(error), 'expected error was logged'); }); - it('should log an error when not in an iFrame', () => { + it('should log an error when not in an iFrame', function () { pushBidResponseToAuction({ ad: "" }); @@ -1034,7 +1034,7 @@ describe('Unit: Prebid Module', function () { assert.ok(spyLogError.calledWith(error), 'expected error was logged'); }); - it('should not render videos', () => { + it('should not render videos', function () { pushBidResponseToAuction({ mediatype: 'video' }); @@ -1070,7 +1070,7 @@ describe('Unit: Prebid Module', function () { assert.deepEqual($$PREBID_GLOBAL$$.getAllWinningBids()[0], adResponse); }); - it('fires billing url if present on s2s bid', () => { + it('fires billing url if present on s2s bid', function () { const burl = 'http://www.example.com/burl'; pushBidResponseToAuction({ ad: '
ad
', @@ -1085,12 +1085,13 @@ describe('Unit: Prebid Module', function () { }); }); - describe('requestBids', () => { + describe('requestBids', function () { let logMessageSpy; let makeRequestsStub; let xhr; let adUnits; let clock; + let bidsBackHandlerStub = sinon.stub(); const BIDDER_CODE = 'sampleBidder'; let bids = [{ @@ -1127,7 +1128,7 @@ describe('Unit: Prebid Module', function () { 'start': 1000 }]; - beforeEach(() => { + beforeEach(function () { logMessageSpy = sinon.spy(utils, 'logMessage'); makeRequestsStub = sinon.stub(adaptermanager, 'makeBidRequests'); makeRequestsStub.returns(bidRequests); @@ -1140,12 +1141,17 @@ describe('Unit: Prebid Module', function () { ] }]; let adUnitCodes = ['adUnit-code']; - let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: 2000}); + let auction = auctionModule.newAuction({ + adUnits, + adUnitCodes, + callback: bidsBackHandlerStub, + cbTimeout: 2000 + }); let createAuctionStub = sinon.stub(auctionModule, 'newAuction'); createAuctionStub.returns(auction); }); - afterEach(() => { + afterEach(function () { clock.restore(); adaptermanager.makeBidRequests.restore(); auctionModule.newAuction.restore(); @@ -1153,7 +1159,7 @@ describe('Unit: Prebid Module', function () { xhr.restore(); }); - it('should execute callback after timeout', () => { + it('should execute callback after timeout', function () { let spec = { code: BIDDER_CODE, isBidRequestValid: sinon.stub(), @@ -1169,7 +1175,7 @@ describe('Unit: Prebid Module', function () { clock = sinon.useFakeTimers(); let requestObj = { - bidsBackHandler: function bidsBackHandlerCallback() {}, + bidsBackHandler: null, // does not need to be defined because of newAuction mock in beforeEach timeout: 2000, adUnits: adUnits }; @@ -1181,20 +1187,25 @@ describe('Unit: Prebid Module', function () { clock.tick(1); assert.ok(logMessageSpy.calledWith(sinon.match(re)), 'executeCallback called'); + + expect(bidsBackHandlerStub.getCall(0).args[1]).to.equal(true, + 'bidsBackHandler should be called with timedOut=true'); }); }) - describe('requestBids', () => { + describe('requestBids', function () { let xhr; let requests; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = request => requests.push(request); }); - afterEach(() => xhr.restore()); + afterEach(function () { + xhr.restore(); + }); var adUnitsBackup; var auctionManagerStub; let logMessageSpy @@ -1208,23 +1219,26 @@ describe('Unit: Prebid Module', function () { }; registerBidder(spec); - describe('part 1', () => { - beforeEach(() => { + describe('part 1', function () { + let auctionArgs; + + beforeEach(function () { adUnitsBackup = auction.getAdUnits auctionManagerStub = sinon.stub(auctionManager, 'createAuction').callsFake(function() { + auctionArgs = arguments[0]; return auction; }); logMessageSpy = sinon.spy(utils, 'logMessage'); }); - afterEach(() => { + afterEach(function () { auction.getAdUnits = adUnitsBackup; auctionManager.createAuction.restore(); utils.logMessage.restore(); resetAuction(); }); - it('should log message when adUnits not configured', () => { + it('should log message when adUnits not configured', function () { $$PREBID_GLOBAL$$.adUnits = []; try { $$PREBID_GLOBAL$$.requestBids({}); @@ -1234,7 +1248,27 @@ describe('Unit: Prebid Module', function () { assert.ok(logMessageSpy.calledWith('No adUnits configured. No bids requested.'), 'expected message was logged'); }); - it('should execute callback immediately if adUnits is empty', () => { + it('should attach transactionIds to ads (or pass through transactionId if it already exists)', function () { + $$PREBID_GLOBAL$$.requestBids({ + adUnits: [ + { + code: 'test1', + transactionId: 'd0676a3c-ff32-45a5-af65-8175a8e7ddca', + bids: [] + }, { + code: 'test2', + bids: [] + } + ] + }); + + expect(auctionArgs.adUnits[0]).to.have.property('transactionId') + .and.to.equal('d0676a3c-ff32-45a5-af65-8175a8e7ddca'); + expect(auctionArgs.adUnits[1]).to.have.property('transactionId') + .and.to.match(/[a-f0-9\-]{36}/i); + }); + + it('should execute callback immediately if adUnits is empty', function () { var bidsBackHandler = function bidsBackHandlerCallback() {}; var spyExecuteCallback = sinon.spy(bidsBackHandler); @@ -1247,7 +1281,7 @@ describe('Unit: Prebid Module', function () { ' empty'); }); - it('should not propagate exceptions from bidsBackHandler', () => { + it('should not propagate exceptions from bidsBackHandler', function () { $$PREBID_GLOBAL$$.adUnits = []; var requestObj = { @@ -1263,12 +1297,12 @@ describe('Unit: Prebid Module', function () { }); }); - describe('multiformat requests', () => { + describe('multiformat requests', function () { let spyCallBids; let createAuctionStub; let adUnits; - beforeEach(() => { + beforeEach(function () { adUnits = [{ code: 'adUnit-code', mediaTypes: { @@ -1282,18 +1316,19 @@ describe('Unit: Prebid Module', function () { ] }]; adUnitCodes = ['adUnit-code']; + configObj.setConfig({maxRequestsPerOrigin: Number.MAX_SAFE_INTEGER || 99999999}); let auction = auctionModule.newAuction({adUnits, adUnitCodes, callback: function() {}, cbTimeout: timeout}); spyCallBids = sinon.spy(adaptermanager, 'callBids'); createAuctionStub = sinon.stub(auctionModule, 'newAuction'); createAuctionStub.returns(auction); }) - afterEach(() => { + afterEach(function () { auctionModule.newAuction.restore(); adaptermanager.callBids.restore(); }); - it('bidders that support one of the declared formats are allowed to participate', () => { + it('bidders that support one of the declared formats are allowed to participate', function () { $$PREBID_GLOBAL$$.requestBids({adUnits}); sinon.assert.calledOnce(adaptermanager.callBids); @@ -1304,7 +1339,7 @@ describe('Unit: Prebid Module', function () { expect(biddersCalled.length).to.equal(2); }); - it('bidders that do not support one of the declared formats are dropped', () => { + it('bidders that do not support one of the declared formats are dropped', function () { delete adUnits[0].mediaTypes.banner; $$PREBID_GLOBAL$$.requestBids({adUnits}); @@ -1318,12 +1353,12 @@ describe('Unit: Prebid Module', function () { }); }); - describe('part 2', () => { + describe('part 2', function () { let spyCallBids; let createAuctionStub; let adUnits; - before(() => { + before(function () { adUnits = [{ code: 'adUnit-code', sizes: [[300, 250], [300, 600]], @@ -1354,24 +1389,24 @@ describe('Unit: Prebid Module', function () { createAuctionStub.returns(auction); }); - after(() => { + after(function () { auctionModule.newAuction.restore(); }); - beforeEach(() => { + beforeEach(function () { spyCallBids = sinon.spy(adaptermanager, 'callBids'); }) - afterEach(() => { + afterEach(function () { adaptermanager.callBids.restore(); }) - it('should callBids if a native adUnit has all native bidders', () => { + it('should callBids if a native adUnit has all native bidders', function () { $$PREBID_GLOBAL$$.requestBids({adUnits}); sinon.assert.calledOnce(adaptermanager.callBids); }); - it('should call callBids function on adaptermanager', () => { + it('should call callBids function on adaptermanager', function () { let adUnits = [{ code: 'adUnit-code', sizes: [[300, 250], [300, 600]], @@ -1383,7 +1418,7 @@ describe('Unit: Prebid Module', function () { assert.ok(spyCallBids.called, 'called adaptermanager.callBids'); }); - it('splits native type to individual native assets', () => { + it('splits native type to individual native assets', function () { let adUnits = [{ code: 'adUnit-code', nativeParams: {type: 'image'}, @@ -1407,7 +1442,7 @@ describe('Unit: Prebid Module', function () { }); }); - describe('part-3', () => { + describe('part-3', function () { let auctionManagerInstance = newAuctionManager(); let auctionManagerStub; let adUnits1 = getAdUnits().filter((adUnit) => { @@ -1467,7 +1502,7 @@ describe('Unit: Prebid Module', function () { adaptermanager.callBids.restore(); }); - it('should not queue bid requests when a previous bid request is in process', () => { + it('should not queue bid requests when a previous bid request is in process', function () { var requestObj1 = { bidsBackHandler: function bidsBackHandlerCallback() {}, timeout: 2000, @@ -1488,7 +1523,7 @@ describe('Unit: Prebid Module', function () { assert.ok(spyCallBids.calledTwice, 'When two requests for bids are made both should be' + ' callBids immediately'); - let result = targeting.getAllTargeting(); // $$PREBID_GLOBAL$$.getAdserverTargeting(); + let result = targeting.getAllTargeting(['/19968336/header-bid-tag-0', '/19968336/header-bid-tag1']); // $$PREBID_GLOBAL$$.getAdserverTargeting(); let expected = { '/19968336/header-bid-tag-0': { 'foobar': '0x0,300x250,300x600', @@ -1510,8 +1545,8 @@ describe('Unit: Prebid Module', function () { }); }); - describe('onEvent', () => { - it('should log an error when handler is not a function', () => { + describe('onEvent', function () { + it('should log an error when handler is not a function', function () { var spyLogError = sinon.spy(utils, 'logError'); var event = 'testEvent'; $$PREBID_GLOBAL$$.onEvent(event); @@ -1520,7 +1555,7 @@ describe('Unit: Prebid Module', function () { utils.logError.restore(); }); - it('should log an error when id provided is not valid for event', () => { + it('should log an error when id provided is not valid for event', function () { var spyLogError = sinon.spy(utils, 'logError'); var event = 'bidWon'; $$PREBID_GLOBAL$$.onEvent(event, Function, 'testId'); @@ -1529,7 +1564,7 @@ describe('Unit: Prebid Module', function () { utils.logError.restore(); }); - it('should call events.on with valid parameters', () => { + it('should call events.on with valid parameters', function () { var spyEventsOn = sinon.spy(events, 'on'); $$PREBID_GLOBAL$$.onEvent('bidWon', Function); assert.ok(spyEventsOn.calledWith('bidWon', Function)); @@ -1537,15 +1572,15 @@ describe('Unit: Prebid Module', function () { }); }); - describe('offEvent', () => { - it('should return when id provided is not valid for event', () => { + describe('offEvent', function () { + it('should return when id provided is not valid for event', function () { var spyEventsOff = sinon.spy(events, 'off'); $$PREBID_GLOBAL$$.offEvent('bidWon', Function, 'testId'); assert.ok(spyEventsOff.notCalled); events.off.restore(); }); - it('should call events.off with valid parameters', () => { + it('should call events.off with valid parameters', function () { var spyEventsOff = sinon.spy(events, 'off'); $$PREBID_GLOBAL$$.offEvent('bidWon', Function); assert.ok(spyEventsOff.calledWith('bidWon', Function)); @@ -1553,8 +1588,8 @@ describe('Unit: Prebid Module', function () { }); }); - describe('emit', () => { - it('should be able to emit event without arguments', () => { + describe('emit', function () { + it('should be able to emit event without arguments', function () { var spyEventsEmit = sinon.spy(events, 'emit'); events.emit(CONSTANTS.EVENTS.AUCTION_END); assert.ok(spyEventsEmit.calledWith('auctionEnd')); @@ -1562,15 +1597,15 @@ describe('Unit: Prebid Module', function () { }); }); - describe('registerBidAdapter', () => { - it('should register bidAdaptor with adaptermanager', () => { + describe('registerBidAdapter', function () { + it('should register bidAdaptor with adaptermanager', function () { var registerBidAdapterSpy = sinon.spy(adaptermanager, 'registerBidAdapter'); $$PREBID_GLOBAL$$.registerBidAdapter(Function, 'biddercode'); assert.ok(registerBidAdapterSpy.called, 'called adaptermanager.registerBidAdapter'); adaptermanager.registerBidAdapter.restore(); }); - it('should catch thrown errors', () => { + it('should catch thrown errors', function () { var spyLogError = sinon.spy(utils, 'logError'); var errorObject = { message: 'bidderAdaptor error' }; var bidderAdaptor = sinon.stub().throws(errorObject); @@ -1583,8 +1618,8 @@ describe('Unit: Prebid Module', function () { }); }); - describe('createBid', () => { - it('should return a bid object', () => { + describe('createBid', function () { + it('should return a bid object', function () { const statusCode = 1; const bid = $$PREBID_GLOBAL$$.createBid(statusCode); assert.isObject(bid, 'bid is an object'); @@ -1596,8 +1631,8 @@ describe('Unit: Prebid Module', function () { }); }); - describe('loadScript', () => { - it('should call adloader.loadScript', () => { + describe('loadScript', function () { + it('should call adloader.loadScript', function () { const loadScriptSpy = sinon.spy(adloader, 'loadScript'); const tagSrc = ''; const callback = Function; @@ -1609,8 +1644,8 @@ describe('Unit: Prebid Module', function () { }); }); - describe('aliasBidder', () => { - it('should call adaptermanager.aliasBidder', () => { + describe('aliasBidder', function () { + it('should call adaptermanager.aliasBidder', function () { const aliasBidAdapterSpy = sinon.spy(adaptermanager, 'aliasBidAdapter'); const bidderCode = 'testcode'; const alias = 'testalias'; @@ -1620,7 +1655,7 @@ describe('Unit: Prebid Module', function () { adaptermanager.aliasBidAdapter.restore(); }); - it('should log error when not passed correct arguments', () => { + it('should log error when not passed correct arguments', function () { const logErrorSpy = sinon.spy(utils, 'logError'); const error = 'bidderCode and alias must be passed as arguments'; @@ -1630,8 +1665,8 @@ describe('Unit: Prebid Module', function () { }); }); - describe('setPriceGranularity', () => { - it('should log error when not passed granularity', () => { + describe('setPriceGranularity', function () { + it('should log error when not passed granularity', function () { const logErrorSpy = sinon.spy(utils, 'logError'); const error = 'Prebid Error: no value passed to `setPriceGranularity()`'; @@ -1640,7 +1675,7 @@ describe('Unit: Prebid Module', function () { utils.logError.restore(); }); - it('should log error when not passed a valid config object', () => { + it('should log error when not passed a valid config object', function () { const logErrorSpy = sinon.spy(utils, 'logError'); const error = 'Invalid custom price value passed to `setPriceGranularity()`'; const badConfig = { @@ -1663,7 +1698,7 @@ describe('Unit: Prebid Module', function () { utils.logError.restore(); }); - it('should set customPriceBucket with custom config buckets', () => { + it('should set customPriceBucket with custom config buckets', function () { let customPriceBucket = configObj.getConfig('customPriceBucket'); const goodConfig = { 'buckets': [{ @@ -1682,21 +1717,21 @@ describe('Unit: Prebid Module', function () { }); }); - describe('emit event', () => { + describe('emit event', function () { let auctionManagerStub; - beforeEach(() => { + beforeEach(function () { auctionManagerStub = sinon.stub(auctionManager, 'createAuction').callsFake(function() { return auction; }); }); - afterEach(() => { + afterEach(function () { auctionManager.createAuction.restore(); }); }); - describe('removeAdUnit', () => { - it('should remove given adUnit in adUnits array', () => { + describe('removeAdUnit', function () { + it('should remove given adUnit in adUnits array', function () { const adUnit1 = { code: 'adUnit1', bids: [{ @@ -1724,16 +1759,16 @@ describe('Unit: Prebid Module', function () { }); }); - describe('getDealTargeting', () => { - beforeEach(() => { + describe('getDealTargeting', function () { + beforeEach(function () { resetAuction(); }); - afterEach(() => { + afterEach(function () { resetAuction(); }); - it('should truncate deal keys', () => { + it('should truncate deal keys', function () { $$PREBID_GLOBAL$$._bidsReceived = [ { 'bidderCode': 'appnexusDummyName', @@ -1783,18 +1818,18 @@ describe('Unit: Prebid Module', function () { // expect(highestCpmBids[1]).to.deep.equal(auctionManager.getBidsReceived()[2]); // }); - it('returns an array containing the highest bid object for the given adUnitCode', () => { + it('returns an array containing the highest bid object for the given adUnitCode', function () { const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/19968336/header-bid-tag-0'); expect(highestCpmBids.length).to.equal(1); expect(highestCpmBids[0]).to.deep.equal(auctionManager.getBidsReceived()[1]); }); - it('returns an empty array when the given adUnit is not found', () => { + it('returns an empty array when the given adUnit is not found', function () { const highestCpmBids = $$PREBID_GLOBAL$$.getHighestCpmBids('/stallone'); expect(highestCpmBids.length).to.equal(0); }); - it('returns an empty array when the given adUnit has no bids', () => { + it('returns an empty array when the given adUnit has no bids', function () { let _bidsReceived = getBidResponses()[0]; _bidsReceived.cpm = 0; auction.getBidsReceived = function() { return _bidsReceived }; @@ -1805,11 +1840,79 @@ describe('Unit: Prebid Module', function () { }); }); - describe('setTargetingForAst', () => { + describe('markWinningBidAsUsed', function () { + it('marks the bid object as used for the given adUnitCode/adId combination', function () { + // make sure the auction has "state" and does not reload the fixtures + const adUnitCode = '/19968336/header-bid-tag-0'; + const bidsReceived = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode); + auction.getBidsReceived = function() { return bidsReceived.bids }; + + // mark the bid and verify the state has changed to RENDERED + const winningBid = targeting.getWinningBids(adUnitCode)[0]; + $$PREBID_GLOBAL$$.markWinningBidAsUsed({ adUnitCode, adId: winningBid.adId }); + const markedBid = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode) + .bids + .find(bid => bid.adId === winningBid.adId); + + expect(markedBid.status).to.equal(RENDERED); + resetAuction(); + }); + + it('try and mark the bid object, but fail because we supplied the wrong adId', function () { + const adUnitCode = '/19968336/header-bid-tag-0'; + const bidsReceived = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode); + auction.getBidsReceived = function() { return bidsReceived.bids }; + + const winningBid = targeting.getWinningBids(adUnitCode)[0]; + $$PREBID_GLOBAL$$.markWinningBidAsUsed({ adUnitCode, adId: 'miss' }); + const markedBid = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode) + .bids + .find(bid => bid.adId === winningBid.adId); + + expect(markedBid.status).to.not.equal(RENDERED); + resetAuction(); + }); + + it('marks the winning bid object as used for the given adUnitCode', function () { + // make sure the auction has "state" and does not reload the fixtures + const adUnitCode = '/19968336/header-bid-tag-0'; + const bidsReceived = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode); + auction.getBidsReceived = function() { return bidsReceived.bids }; + + // mark the bid and verify the state has changed to RENDERED + const winningBid = targeting.getWinningBids(adUnitCode)[0]; + $$PREBID_GLOBAL$$.markWinningBidAsUsed({ adUnitCode }); + const markedBid = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode) + .bids + .find(bid => bid.adId === winningBid.adId); + + expect(markedBid.status).to.equal(RENDERED); + resetAuction(); + }); + + it('marks a bid object as used for the given adId', function () { + // make sure the auction has "state" and does not reload the fixtures + const adUnitCode = '/19968336/header-bid-tag-0'; + const bidsReceived = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode); + auction.getBidsReceived = function() { return bidsReceived.bids }; + + // mark the bid and verify the state has changed to RENDERED + const winningBid = targeting.getWinningBids(adUnitCode)[0]; + $$PREBID_GLOBAL$$.markWinningBidAsUsed({ adId: winningBid.adId }); + const markedBid = $$PREBID_GLOBAL$$.getBidResponsesForAdUnitCode(adUnitCode) + .bids + .find(bid => bid.adId === winningBid.adId); + + expect(markedBid.status).to.equal(RENDERED); + resetAuction(); + }); + }); + + describe('setTargetingForAst', function () { let targeting; let auctionManagerInstance; - beforeEach(() => { + beforeEach(function () { resetAuction(); auctionManagerInstance = newAuctionManager(); sinon.stub(auctionManagerInstance, 'getBidsReceived').callsFake(function() { @@ -1824,13 +1927,13 @@ describe('Unit: Prebid Module', function () { targeting = newTargeting(auctionManagerInstance); }); - afterEach(() => { + afterEach(function () { auctionManagerInstance.getBidsReceived.restore(); auctionManagerInstance.getAdUnitCodes.restore(); resetAuction(); }); - it('should set targeting for appnexus apntag object', () => { + it('should set targeting for appnexus apntag object', function () { const bids = auctionManagerInstance.getBidsReceived(); const adUnitCode = '/19968336/header-bid-tag-0'; @@ -1849,7 +1952,7 @@ describe('Unit: Prebid Module', function () { expect(newAdserverTargeting).to.deep.equal(window.apntag.tags[adUnitCode].keywords); }); - it('should not find hb_adid key in lowercase for all bidders', () => { + it('should not find hb_adid key in lowercase for all bidders', function () { const adUnitCode = '/19968336/header-bid-tag-0'; $$PREBID_GLOBAL$$.setConfig({ enableSendAllBids: true }); targeting.setTargetingForAst(); @@ -1892,17 +1995,17 @@ describe('Unit: Prebid Module', function () { }); }); - describe('getAllPrebidWinningBids', () => { + describe('getAllPrebidWinningBids', function () { let auctionManagerStub; - beforeEach(() => { + beforeEach(function () { auctionManagerStub = sinon.stub(auctionManager, 'getBidsReceived'); }); - afterEach(() => { + afterEach(function () { auctionManagerStub.restore(); }); - it('should return prebid auction winning bids', () => { + it('should return prebid auction winning bids', function () { let bidsReceived = [ createBidReceived({bidder: 'appnexus', cpm: 7, auctionId: 1, responseTimestamp: 100, adUnitCode: 'code-0', adId: 'adid-1', status: 'targetingSet'}), createBidReceived({bidder: 'rubicon', cpm: 6, auctionId: 1, responseTimestamp: 101, adUnitCode: 'code-1', adId: 'adid-2'}), diff --git a/test/spec/url_spec.js b/test/spec/url_spec.js index cfa1b0c80b4..90047273043 100644 --- a/test/spec/url_spec.js +++ b/test/spec/url_spec.js @@ -1,31 +1,31 @@ import {format, parse} from '../../src/url'; import { expect } from 'chai'; -describe('helpers.url', () => { - describe('parse()', () => { +describe('helpers.url', function () { + describe('parse()', function () { let parsed; - beforeEach(() => { + beforeEach(function () { parsed = parse('http://example.com:3000/pathname/?search=test&foo=bar&bar=foo%26foo%3Dxxx#hash'); }); - it('extracts the protocol', () => { + it('extracts the protocol', function () { expect(parsed).to.have.property('protocol', 'http'); }); - it('extracts the hostname', () => { + it('extracts the hostname', function () { expect(parsed).to.have.property('hostname', 'example.com'); }); - it('extracts the port', () => { + it('extracts the port', function () { expect(parsed).to.have.property('port', 3000); }); - it('extracts the pathname', () => { + it('extracts the pathname', function () { expect(parsed).to.have.property('pathname', '/pathname/'); }); - it('extracts the search query', () => { + it('extracts the search query', function () { expect(parsed).to.have.property('search'); expect(parsed.search).to.eql({ foo: 'xxx', @@ -34,23 +34,23 @@ describe('helpers.url', () => { }); }); - it('extracts the hash', () => { + it('extracts the hash', function () { expect(parsed).to.have.property('hash', 'hash'); }); - it('extracts the host', () => { + it('extracts the host', function () { expect(parsed).to.have.property('host', 'example.com:3000'); }); }); - describe('parse(url, {noDecodeWholeURL: true})', () => { + describe('parse(url, {noDecodeWholeURL: true})', function () { let parsed; - beforeEach(() => { + beforeEach(function () { parsed = parse('http://example.com:3000/pathname/?search=test&foo=bar&bar=foo%26foo%3Dxxx#hash', {noDecodeWholeURL: true}); }); - it('extracts the search query', () => { + it('extracts the search query', function () { expect(parsed).to.have.property('search'); expect(parsed.search).to.eql({ foo: 'bar', @@ -60,8 +60,8 @@ describe('helpers.url', () => { }); }); - describe('format()', () => { - it('formats an object in to a URL', () => { + describe('format()', function () { + it('formats an object in to a URL', function () { expect(format({ protocol: 'http', hostname: 'example.com', @@ -72,21 +72,21 @@ describe('helpers.url', () => { })).to.equal('http://example.com:3000/pathname/?foo=bar&search=test&bar=foo%26foo%3Dxxx#hash'); }); - it('will use defaults for missing properties', () => { + it('will use defaults for missing properties', function () { expect(format({ hostname: 'example.com' })).to.equal('http://example.com'); }); }); - describe('parse(url, {decodeSearchAsString: true})', () => { + describe('parse(url, {decodeSearchAsString: true})', function () { let parsed; - beforeEach(() => { + beforeEach(function () { parsed = parse('http://example.com:3000/pathname/?search=test&foo=bar&bar=foo%26foo%3Dxxx#hash', {decodeSearchAsString: true}); }); - it('extracts the search query', () => { + it('extracts the search query', function () { expect(parsed).to.have.property('search'); expect(parsed.search).to.equal('?search=test&foo=bar&bar=foo&foo=xxx'); }); diff --git a/test/spec/userSync_spec.js b/test/spec/userSync_spec.js index 9a72629c71a..7040256ccd6 100644 --- a/test/spec/userSync_spec.js +++ b/test/spec/userSync_spec.js @@ -4,7 +4,7 @@ import { config } from 'src/config'; const utils = require('../../src/utils'); let { newUserSync } = require('../../src/userSync'); -describe('user sync', () => { +describe('user sync', function () { let triggerPixelStub; let logWarnStub; let timeoutStub; @@ -25,15 +25,15 @@ describe('user sync', () => { }) } let clock; - before(() => { + before(function () { clock = sinon.useFakeTimers(); }); - after(() => { + after(function () { clock.restore(); }); - beforeEach(() => { + beforeEach(function () { triggerPixelStub = sinon.stub(utils, 'triggerPixel'); logWarnStub = sinon.stub(utils, 'logWarn'); shuffleStub = sinon.stub(utils, 'shuffle').callsFake((array) => array.reverse()); @@ -41,7 +41,7 @@ describe('user sync', () => { insertUserSyncIframeStub = sinon.stub(utils, 'insertUserSyncIframe'); }); - afterEach(() => { + afterEach(function () { triggerPixelStub.restore(); logWarnStub.restore(); shuffleStub.restore(); @@ -49,7 +49,7 @@ describe('user sync', () => { insertUserSyncIframeStub.restore(); }); - it('should register and fire a pixel URL', () => { + it('should register and fire a pixel URL', function () { const userSync = newTestUserSync(); userSync.registerSync('image', 'testBidder', 'http://example.com'); userSync.syncUsers(); @@ -57,13 +57,13 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com'); }); - it('should clear queue after sync', () => { + it('should clear queue after sync', function () { const userSync = newTestUserSync(); userSync.syncUsers(); expect(triggerPixelStub.callCount).to.equal(0); }); - it('should delay firing a pixel by the expected amount', () => { + it('should delay firing a pixel by the expected amount', function () { const userSync = newTestUserSync(); userSync.registerSync('image', 'testBidder', 'http://example.com'); // This implicitly tests cookie and browser support @@ -72,7 +72,7 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(0)).to.not.be.null; }); - it('should register and fires multiple pixel URLs', () => { + it('should register and fires multiple pixel URLs', function () { const userSync = newTestUserSync(); userSync.registerSync('image', 'testBidder', 'http://example.com/1'); userSync.registerSync('image', 'testBidder', 'http://example.com/2'); @@ -84,21 +84,21 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(2)).to.be.null; }); - it('should not register pixel URL since it is not supported', () => { + it('should not register pixel URL since it is not supported', function () { const userSync = newTestUserSync({pixelEnabled: false}); userSync.registerSync('image', 'testBidder', 'http://example.com'); userSync.syncUsers(); expect(triggerPixelStub.getCall(0)).to.be.null; }); - it('should register and load an iframe', () => { + it('should register and load an iframe', function () { const userSync = newTestUserSync({iframeEnabled: true}); userSync.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); userSync.syncUsers(); expect(insertUserSyncIframeStub.getCall(0).args[0]).to.equal('http://example.com/iframe'); }); - it('should only trigger syncs once per page', () => { + it('should only trigger syncs once per page', function () { const userSync = newTestUserSync({pixelEnabled: true}); userSync.registerSync('image', 'testBidder', 'http://example.com/1'); userSync.syncUsers(); @@ -109,20 +109,20 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(1)).to.be.null; }); - it('should not fire syncs if cookies are not supported', () => { + it('should not fire syncs if cookies are not supported', function () { const userSync = newTestUserSync({pixelEnabled: true}, true); userSync.registerSync('image', 'testBidder', 'http://example.com'); userSync.syncUsers(); expect(triggerPixelStub.getCall(0)).to.be.null; }); - it('should prevent registering invalid type', () => { + it('should prevent registering invalid type', function () { const userSync = newTestUserSync(); userSync.registerSync('invalid', 'testBidder', 'http://example.com'); expect(logWarnStub.getCall(0).args[0]).to.exist; }); - it('should expose the syncUsers method for the publisher to manually trigger syncs', () => { + it('should expose the syncUsers method for the publisher to manually trigger syncs', function () { // triggerUserSyncs should do nothing by default let userSync = newTestUserSync(); let syncUsersSpy = sinon.spy(userSync, 'syncUsers'); @@ -135,7 +135,7 @@ describe('user sync', () => { expect(syncUsersSpy.called).to.be.true; }); - it('should limit the sync per bidder', () => { + it('should limit the sync per bidder', function () { const userSync = newTestUserSync({syncsPerBidder: 2}); userSync.registerSync('image', 'testBidder', 'http://example.com/1'); userSync.registerSync('image', 'testBidder', 'http://example.com/2'); @@ -148,7 +148,7 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(2)).to.be.null; }); - it('should balance out bidder requests', () => { + it('should balance out bidder requests', function () { const userSync = newTestUserSync(); userSync.registerSync('image', 'atestBidder', 'http://example.com/1'); userSync.registerSync('image', 'atestBidder', 'http://example.com/3'); @@ -164,7 +164,7 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(3)).to.be.null; }); - it('should disable user sync', () => { + it('should disable user sync', function () { const userSync = newTestUserSync({syncEnabled: false}); userSync.registerSync('pixel', 'testBidder', 'http://example.com'); expect(logWarnStub.getCall(0).args[0]).to.exist; @@ -172,7 +172,7 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(0)).to.be.null; }); - it('should only sync enabled bidders', () => { + it('should only sync enabled bidders', function () { const userSync = newTestUserSync({enabledBidders: ['testBidderA']}); userSync.registerSync('image', 'testBidderA', 'http://example.com/1'); userSync.registerSync('image', 'testBidderB', 'http://example.com/2'); @@ -182,7 +182,7 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(1)).to.be.null; }); - it('should register config set after instantiation', () => { + it('should register config set after instantiation', function () { // start with userSync off const userSync = newTestUserSync({syncEnabled: false}); // turn it on with setConfig() @@ -192,4 +192,153 @@ describe('user sync', () => { expect(triggerPixelStub.getCall(0)).to.not.be.null; expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com'); }); + + it('should register both image and iframe pixels with filterSettings.all config', function () { + const userSync = newTestUserSync({ + filterSettings: { + all: { + bidders: ['atestBidder', 'testBidder'], + filter: 'include' + }, + } + }); + userSync.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync.syncUsers(); + expect(triggerPixelStub.getCall(0)).to.not.be.null; + expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com/1'); + expect(insertUserSyncIframeStub.getCall(0)).to.not.be.null; + expect(insertUserSyncIframeStub.getCall(0).args[0]).to.equal('http://example.com/iframe'); + }); + + it('should register iframe and not register image pixels based on filterSettings config', function () { + const userSync = newTestUserSync({ + filterSettings: { + image: { + bidders: '*', + filter: 'exclude' + }, + iframe: { + bidders: ['testBidder'] + } + } + }); + userSync.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync.syncUsers(); + expect(triggerPixelStub.getCall(0)).to.be.null; + expect(insertUserSyncIframeStub.getCall(0)).to.not.be.null; + expect(insertUserSyncIframeStub.getCall(0).args[0]).to.equal('http://example.com/iframe'); + }); + + it('should throw a warning and default to basic resgistration rules when filterSettings config is invalid', function () { + // invalid config - passed invalid filter option + const userSync1 = newTestUserSync({ + filterSettings: { + iframe: { + bidders: ['testBidder'], + filter: 'includes' + } + } + }); + userSync1.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync1.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync1.syncUsers(); + expect(logWarnStub.getCall(0).args[0]).to.exist; + expect(triggerPixelStub.getCall(0)).to.not.be.null; + expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com/1'); + expect(insertUserSyncIframeStub.getCall(0)).to.be.null; + + // invalid config - bidders is not an array of strings + const userSync2 = newTestUserSync({ + filterSettings: { + iframe: { + bidders: ['testBidder', 0], + filter: 'include' + } + } + }); + userSync2.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync2.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync2.syncUsers(); + expect(logWarnStub.getCall(1).args[0]).to.exist; + expect(triggerPixelStub.getCall(1)).to.not.be.null; + expect(triggerPixelStub.getCall(1).args[0]).to.exist.and.to.equal('http://example.com/1'); + expect(insertUserSyncIframeStub.getCall(0)).to.be.null; + + // invalid config - bidders list includes wildcard + const userSync3 = newTestUserSync({ + filterSettings: { + iframe: { + bidders: ['testBidder', '*'], + filter: 'include' + } + } + }); + userSync3.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync3.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync3.syncUsers(); + expect(logWarnStub.getCall(2).args[0]).to.exist; + expect(triggerPixelStub.getCall(2)).to.not.be.null; + expect(triggerPixelStub.getCall(2).args[0]).to.exist.and.to.equal('http://example.com/1'); + expect(insertUserSyncIframeStub.getCall(0)).to.be.null; + + // invalid config - incorrect wildcard + const userSync4 = newTestUserSync({ + filterSettings: { + iframe: { + bidders: '***', + filter: 'include' + } + } + }); + userSync4.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync4.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync4.syncUsers(); + expect(logWarnStub.getCall(3).args[0]).to.exist; + expect(triggerPixelStub.getCall(3)).to.not.be.null; + expect(triggerPixelStub.getCall(3).args[0]).to.exist.and.to.equal('http://example.com/1'); + expect(insertUserSyncIframeStub.getCall(0)).to.be.null; + + // invalid config - missing bidders field + const userSync5 = newTestUserSync({ + filterSettings: { + iframe: { + filter: 'include' + } + } + }); + userSync5.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync5.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync5.syncUsers(); + expect(logWarnStub.getCall(4).args[0]).to.exist; + expect(triggerPixelStub.getCall(4)).to.not.be.null; + expect(triggerPixelStub.getCall(4).args[0]).to.exist.and.to.equal('http://example.com/1'); + expect(insertUserSyncIframeStub.getCall(0)).to.be.null; + }); + + it('should overwrite logic of deprecated fields when filterSettings is defined', function () { + const userSync = newTestUserSync({ + pixelsEnabled: false, + iframeEnabled: true, + enabledBidders: ['ctestBidder'], + filterSettings: { + image: { + bidders: '*', + filter: 'include' + }, + iframe: { + bidders: ['testBidder'], + filter: 'exclude' + } + } + }); + userSync.registerSync('image', 'atestBidder', 'http://example.com/1'); + userSync.registerSync('iframe', 'testBidder', 'http://example.com/iframe'); + userSync.syncUsers(); + expect(logWarnStub.getCall(0).args[0]).to.exist; + expect(triggerPixelStub.getCall(0)).to.not.be.null; + expect(triggerPixelStub.getCall(0).args[0]).to.exist.and.to.equal('http://example.com/1'); + expect(insertUserSyncIframeStub.getCall(0)).to.be.null; + }); }); diff --git a/test/spec/utils_spec.js b/test/spec/utils_spec.js index 454d6ed4136..7891eff5f33 100755 --- a/test/spec/utils_spec.js +++ b/test/spec/utils_spec.js @@ -639,8 +639,8 @@ describe('Utils', function () { }); }); - describe('getDefinedParams', () => { - it('builds an object consisting of defined params', () => { + describe('getDefinedParams', function () { + it('builds an object consisting of defined params', function () { const adUnit = { mediaType: 'video', comeWithMe: 'ifuwant2live', @@ -658,8 +658,8 @@ describe('Utils', function () { }); }); - describe('deepClone', () => { - it('deep copies objects', () => { + describe('deepClone', function () { + it('deep copies objects', function () { const adUnit = [{ code: 'swan', mediaTypes: {video: {context: 'outstream'}}, @@ -679,7 +679,7 @@ describe('Utils', function () { }); }); - describe('getUserConfiguredParams', () => { + describe('getUserConfiguredParams', function () { const adUnits = [{ code: 'adUnit1', bids: [{ @@ -692,7 +692,7 @@ describe('Utils', function () { }] }]; - it('should return params configured', () => { + it('should return params configured', function () { const output = utils.getUserConfiguredParams(adUnits, 'adUnit1', 'bidder1'); const expected = [{ key1: 'value1' @@ -700,37 +700,37 @@ describe('Utils', function () { assert.deepEqual(output, expected); }); - it('should return array containting empty object, if bidder present and no params are configured', () => { + it('should return array containting empty object, if bidder present and no params are configured', function () { const output = utils.getUserConfiguredParams(adUnits, 'adUnit1', 'bidder2'); const expected = [{}]; assert.deepEqual(output, expected); }); - it('should return empty array, if bidder is not present', () => { + it('should return empty array, if bidder is not present', function () { const output = utils.getUserConfiguredParams(adUnits, 'adUnit1', 'bidder3'); const expected = []; assert.deepEqual(output, expected); }); - it('should return empty array, if adUnit is not present', () => { + it('should return empty array, if adUnit is not present', function () { const output = utils.getUserConfiguredParams(adUnits, 'adUnit2', 'bidder3'); const expected = []; assert.deepEqual(output, expected); }); }); - describe('getTopWindowLocation', () => { + describe('getTopWindowLocation', function () { let sandbox; - beforeEach(() => { + beforeEach(function () { sandbox = sinon.sandbox.create(); }); - afterEach(() => { + afterEach(function () { sandbox.restore(); }); - it('returns window.location if not in iFrame', () => { + it('returns window.location if not in iFrame', function () { sandbox.stub(utils, 'getWindowLocation').returns({ href: 'https://www.google.com/', ancestorOrigins: {}, @@ -762,7 +762,7 @@ describe('Utils', function () { expect(topWindowLocation.host).to.equal('www.google.com'); }); - it('returns parsed dom string from ancestorOrigins if in iFrame & ancestorOrigins is populated', () => { + it('returns parsed dom string from ancestorOrigins if in iFrame & ancestorOrigins is populated', function () { sandbox.stub(utils, 'getWindowSelf').returns( { self: 'is not same as top' } ); @@ -783,7 +783,7 @@ describe('Utils', function () { expect(topWindowLocation.host).to.be.oneOf(['www.google.com', 'www.google.com:443']); }); - it('returns parsed referrer string if in iFrame but no ancestorOrigins', () => { + it('returns parsed referrer string if in iFrame but no ancestorOrigins', function () { sandbox.stub(utils, 'getWindowSelf').returns( { self: 'is not same as top' } ); @@ -806,8 +806,8 @@ describe('Utils', function () { }); }); - describe('convertCamelToUnderscore', () => { - it('returns converted string value using underscore syntax instead of camelCase', () => { + describe('convertCamelToUnderscore', function () { + it('returns converted string value using underscore syntax instead of camelCase', function () { let var1 = 'placementIdTest'; let test1 = utils.convertCamelToUnderscore(var1); expect(test1).to.equal('placement_id_test'); @@ -818,18 +818,18 @@ describe('Utils', function () { }); }); - describe('getAdUnitSizes', () => { - it('returns an empty response when adUnits is undefined', () => { + describe('getAdUnitSizes', function () { + it('returns an empty response when adUnits is undefined', function () { let sizes = utils.getAdUnitSizes(); expect(sizes).to.be.undefined; }); - it('returns an empty array when invalid data is present in adUnit object', () => { + it('returns an empty array when invalid data is present in adUnit object', function () { let sizes = utils.getAdUnitSizes({ sizes: 300 }); expect(sizes).to.deep.equal([]); }); - it('retuns an array of arrays when reading from adUnit.sizes', () => { + it('retuns an array of arrays when reading from adUnit.sizes', function () { let sizes = utils.getAdUnitSizes({ sizes: [300, 250] }); expect(sizes).to.deep.equal([[300, 250]]); @@ -837,7 +837,7 @@ describe('Utils', function () { expect(sizes).to.deep.equal([[300, 250], [300, 600]]); }); - it('returns an array of arrays when reading from adUnit.mediaTypes.banner.sizes', () => { + it('returns an array of arrays when reading from adUnit.mediaTypes.banner.sizes', function () { let sizes = utils.getAdUnitSizes({ mediaTypes: { banner: { sizes: [300, 250] } } }); expect(sizes).to.deep.equal([[300, 250]]); diff --git a/test/spec/videoCache_spec.js b/test/spec/videoCache_spec.js index b853da708fc..c9052fbbf9d 100644 --- a/test/spec/videoCache_spec.js +++ b/test/spec/videoCache_spec.js @@ -5,7 +5,7 @@ import { config } from 'src/config'; const should = chai.should(); -describe('The video cache', () => { +describe('The video cache', function () { function assertError(callbackSpy) { callbackSpy.calledOnce.should.equal(true); callbackSpy.firstCall.args[0].should.be.an('error'); @@ -16,19 +16,21 @@ describe('The video cache', () => { should.not.exist(callbackSpy.firstCall.args[0]); } - describe('when the cache server is unreachable', () => { + describe('when the cache server is unreachable', function () { let xhr; let requests; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = (request) => requests.push(request); }); - afterEach(() => xhr.restore()); + afterEach(function () { + xhr.restore(); + }); - it('should execute the callback with an error when store() is called', () => { + it('should execute the callback with an error when store() is called', function () { const callback = sinon.spy(); store([ { vastUrl: 'my-mock-url.com' } ], callback); @@ -41,11 +43,11 @@ describe('The video cache', () => { }); }); - describe('when the cache server is available', () => { + describe('when the cache server is available', function () { let xhr; let requests; - beforeEach(() => { + beforeEach(function () { xhr = sinon.useFakeXMLHttpRequest(); requests = []; xhr.onCreate = (request) => requests.push(request); @@ -56,12 +58,12 @@ describe('The video cache', () => { }) }); - afterEach(() => { + afterEach(function () { xhr.restore(); config.resetConfig(); }); - it('should execute the callback with a successful result when store() is called', () => { + it('should execute the callback with a successful result when store() is called', function () { const uuid = 'c488b101-af3e-4a99-b538-00423e5a3371'; const callback = fakeServerCall( { vastUrl: 'my-mock-url.com' }, @@ -71,7 +73,7 @@ describe('The video cache', () => { callback.firstCall.args[1].should.deep.equal([{ uuid: uuid }]); }); - it('should execute the callback with an error if the cache server response has no responses property', () => { + it('should execute the callback with an error if the cache server response has no responses property', function () { const callback = fakeServerCall( { vastUrl: 'my-mock-url.com' }, '{"broken":[{"uuid":"c488b101-af3e-4a99-b538-00423e5a3371"}]}'); @@ -79,7 +81,7 @@ describe('The video cache', () => { callback.firstCall.args[1].should.deep.equal([]); }); - it('should execute the callback with an error if the cache server responds with malformed JSON', () => { + it('should execute the callback with an error if the cache server responds with malformed JSON', function () { const callback = fakeServerCall( { vastUrl: 'my-mock-url.com' }, 'Not JSON here'); @@ -87,7 +89,7 @@ describe('The video cache', () => { callback.firstCall.args[1].should.deep.equal([]); }); - it('should make the expected request when store() is called on an ad with a vastUrl', () => { + it('should make the expected request when store() is called on an ad with a vastUrl', function () { const expectedValue = ` @@ -101,7 +103,7 @@ describe('The video cache', () => { assertRequestMade({ vastUrl: 'my-mock-url.com' }, expectedValue) }); - it('should make the expected request when store() is called on an ad with a vastUrl and a vastImpUrl', () => { + it('should make the expected request when store() is called on an ad with a vastUrl and a vastImpUrl', function () { const expectedValue = ` @@ -115,7 +117,7 @@ describe('The video cache', () => { assertRequestMade({ vastUrl: 'my-mock-url.com', vastImpUrl: 'imptracker.com' }, expectedValue) }); - it('should make the expected request when store() is called on an ad with vastXml', () => { + it('should make the expected request when store() is called on an ad with vastXml', function () { const vastXml = ''; assertRequestMade({ vastXml: vastXml }, vastXml); }); @@ -150,8 +152,8 @@ describe('The video cache', () => { }); }); -describe('The getCache function', () => { - beforeEach(() => { +describe('The getCache function', function () { + beforeEach(function () { config.setConfig({ cache: { url: 'https://prebid.adnxs.com/pbc/v1/cache' @@ -159,11 +161,11 @@ describe('The getCache function', () => { }) }); - afterEach(() => { + afterEach(function () { config.resetConfig(); }); - it('should return the expected URL', () => { + it('should return the expected URL', function () { const uuid = 'c488b101-af3e-4a99-b538-00423e5a3371'; const url = getCacheUrl(uuid); url.should.equal(`https://prebid.adnxs.com/pbc/v1/cache?uuid=${uuid}`); diff --git a/test/spec/video_spec.js b/test/spec/video_spec.js index 06cd653f444..3d6ed04ffae 100644 --- a/test/spec/video_spec.js +++ b/test/spec/video_spec.js @@ -1,7 +1,7 @@ import { isValidVideoBid } from 'src/video'; -describe('video.js', () => { - it('validates valid instream bids', () => { +describe('video.js', function () { + it('validates valid instream bids', function () { const bid = { adId: '123abc', vastUrl: 'http://www.example.com/vastUrl' @@ -19,7 +19,7 @@ describe('video.js', () => { expect(valid).to.equal(true); }); - it('catches invalid instream bids', () => { + it('catches invalid instream bids', function () { const bid = { adId: '123abc' }; @@ -36,7 +36,7 @@ describe('video.js', () => { expect(valid).to.equal(false); }); - it('catches invalid bids when prebid-cache is disabled', () => { + it('catches invalid bids when prebid-cache is disabled', function () { const bidRequests = [{ bids: [{ bidder: 'vastOnlyVideoBidder', @@ -49,7 +49,7 @@ describe('video.js', () => { expect(valid).to.equal(false); }); - it('validates valid outstream bids', () => { + it('validates valid outstream bids', function () { const bid = { adId: '123abc', renderer: { @@ -70,7 +70,7 @@ describe('video.js', () => { expect(valid).to.equal(true); }); - it('catches invalid outstream bids', () => { + it('catches invalid outstream bids', function () { const bid = { adId: '123abc' }; diff --git a/webpack.conf.js b/webpack.conf.js index 4b53aabef22..1048cb94386 100644 --- a/webpack.conf.js +++ b/webpack.conf.js @@ -19,7 +19,7 @@ module.exports = { ], }, output: { - jsonpFunction: prebid.globalVarName+"Chunk" + jsonpFunction: prebid.globalVarName + "Chunk" }, module: { rules: [ @@ -88,7 +88,7 @@ module.exports = { name: 'prebid', filename: 'prebid-core.js', minChunks: function(module, count) { - return !(count < 2 || neverBundle.includes(path.basename(module.resource))) + return !(count < 2 || neverBundle.indexOf(path.basename(module.resource)) !== -1) } }) ]