UNPKG

videojs-contrib-ads

Version:

A framework that provides common functionality needed by video advertisement libraries working with video.js.

260 lines (214 loc) 6.57 kB
import '../example/app.js'; // Old integration tests that were disabled years ago and are out of date. // To try to fix them, start by renaming to videojs.ads.events.test.js so they run again. (function(){ /** * Events which are explicitly ignored by player listeners in tests. * * @type {Array} */ var filteredEvents = [ 'contenttimeupdate', 'contentprogress', 'contentwaiting', 'contentsuspend', 'adtimeupdate', 'adprogress', 'adwaiting', 'adsuspend', 'timeupdate', 'progress', 'waiting', 'suspend' ]; /** * All player events that are listened to in the testing process. * * @type {Array} */ var relevantEvents = (function (events) { return _.union( events, events.map(function(event) { return 'ad' + event; }), events.map(function(event) { return 'content' + event; }), [ // events emitted by ad plugin 'adtimeout', 'contentended', 'contentupdate', 'contentplayback', // events emitted by third party ad implementors 'adsready', 'adscanceled', 'adstart', // startLinearAdMode() 'adend' // endLinearAdMode() ]).filter(function(event) { return filteredEvents.indexOf(event) === -1; }); }(videojs.getTech('Html5').Events)); /** * Attaches a listener to track occurrences of `relevantEvents` on a player * in a testing context. * * @param {Object} env * A QUnit testing context. Expects `player` and `events` properties. * @return {Object} * The `player` object in `env`. */ var attachPlayerListeners = function(env) { return env.player.on(relevantEvents, function(event) { env.events.push(event.type); }); }; /** * Asserts that elements in the first array occur in the same order as * in the second array. It's okay to have duplicates or intermediate * elements in the first array that don't occur in the second. An * assertion will fail if all of the elements in the second array are * not present in the first. * * @param {Object} assert * @param {Array} actual * @param {Array} expected */ var occurInOrder = function(assert, actual, expected) { var i, j; for (i = j = 0; i < actual.length; i++) { if (actual[i] !== expected[j]) { continue; } assert.strictEqual( actual[i], expected[j], 'matched "' + expected[j] + '" to event number ' + i ); j++; } assert.strictEqual( j, expected.length, expected.length !== j ? 'missing ' + expected.slice(j).join(', ') : 'all expected events occurred' ); }; /** * Counts the number of elements in an array that are strictly equal to the * specified element. * * @param {Array} array * @param {Mixed} element * @return {Number} */ var count = function(array, element) { var i = array.length, result = 0; while (i--) { if (array[i] === element) { result++; } } return result; }; QUnit.module('Ad Events Tranformation', { beforeEach: function() { var vjsOptions = { inactivityTimeout: 0 }; var video = document.createElement('video'); this.events = []; video.className = 'video-js vjs-default-skin'; video.width = '640'; video.height = '272'; video.setAttribute('controls', ''); // add video element behavior to phantom's non-functioning version if (/phantom/i.test(window.navigator.userAgent)) { video.removeAttribute = function(attr) { this[attr] = ''; }; video.load = function() {}; video.play = function() {}; } document.getElementById('qunit-fixture').appendChild(video); if (QUnit.config.flash) { vjsOptions.techOrder = ['flash']; } this.player = videojs(video, vjsOptions); // load a video this.player.src({ // get the absolute URL to the video so that snapshot restores aren't // seen as content updates src: (function() { var a = document.createElement('a'); a.href = '../example/sintel-low.mp4'; return a.href; })(), type: 'video/mp4' }); }, afterEach: function(){ this.player.dispose(); } }); QUnit.test('linear ads should not affect regular video playback events', function(assert) { var done = assert.async(); this.player.exampleAds({ midrollPoint: 2 }); attachPlayerListeners(this).on('ended', videojs.bind(this, function() { assert.ok(this.events.length > 0, 'fired video events'); // ad events should occur in a sensible order occurInOrder(assert, this.events, [ 'adstart', 'adend', // play a preroll 'contentplayback', 'adstart', 'adend', // play a midroll 'contentplayback', 'adstart', 'contentended', 'adend', // play a postroll 'contentplayback', 'ended' // end the video ]); // content related events should occur in a sensible order occurInOrder(assert, this.events, [ 'play', // start the video 'playing', // content begins playing 'ended' // end the video ]); occurInOrder(assert, this.events, [ 'loadstart', 'playing' ]); assert.strictEqual(count(this.events, 'adsready'), 1, 'fired adsready exactly once'); assert.strictEqual(count(this.events, 'loadstart'), 1, 'fired loadstart exactly once'); assert.strictEqual(count(this.events, 'ended'), 1, 'fired ended exactly once'); assert.ok(this.player.ended(), 'the video is still ended'); done(); })); this.player.ready(this.player.play); }); QUnit.test('regular video playback is not affected', function(assert) { var done = assert.async(); // disable ads this.player.exampleAds({ adServerUrl: 'empty-inventory.json' }); attachPlayerListeners(this).on('ended', videojs.bind(this, function() { assert.ok(this.events.length > 0, 'fired video events'); occurInOrder(assert, this.events, [ 'play', // start the video 'ended' // end the video ]); occurInOrder(assert, this.events, [ 'loadstart', 'playing' ]); assert.strictEqual(count(this.events, 'adstart'), 0, 'did not fire adstart'); assert.strictEqual(count(this.events, 'adend'), 0, 'did not fire adend'); assert.strictEqual(count(this.events, 'loadstart'), 1, 'fired loadstart exactly once'); assert.strictEqual(count(this.events, 'ended'), 1, 'fired ended exactly once'); assert.ok(this.player.ended(), 'the video is still ended'); done(); })); this.player.ready(this.player.play); }); }());