Permalink
Browse files

Add coverage for all events triggered by UI.js

Cleanup karma settings
JW8-1623
  • Loading branch information...
robwalch committed Jul 6, 2018
1 parent 3771c1e commit 777a569045db871e1b0298a3cd19ac31412efe05
@@ -149,7 +149,7 @@ module.exports = function(grunt) {
browsers: ['Safari']
},
browserstack: {
browsers: ['chrome', 'firefox', 'edge', 'ie11_windows']
browsers: ['chrome', 'firefox', 'edge', 'ie11']
},
browserstack_chrome: {
browsers: ['chrome']
@@ -161,7 +161,13 @@ module.exports = function(grunt) {
browsers: ['edge']
},
browserstack_ie11: {
browsers: ['ie11_windows']
browsers: ['ie11']
},
browserstack_iphone: {
browsers: ['iphone']
},
browserstack_android: {
browsers: ['android']
}
},
@@ -76,9 +76,28 @@ module.exports = function(config) {
'mocha',
'coverage-istanbul'
];
let browsers = [
'ChromeHeadless',
'Chrome',
'Safari',
'Firefox',
'edge',
'ie11',
'iphone',
'android'
];
if (isJenkins) {
testReporters.push('junit');
process.env.CHROME_BIN = puppeteer.executablePath();
browsers = [
'ChromeHeadless',
'chrome',
'firefox',
'edge',
'ie11',
'iphone',
'android'
];
}
const packageInfo = JSON.parse(require('fs').readFileSync('package.json', 'utf8'));
@@ -98,23 +117,18 @@ module.exports = function(config) {
// LOG_DEBUG (useful for writing karma server network status messages to stdio)
logLevel: config.LOG_INFO,
browsers: [
'ChromeHeadless',
'Chrome',
// 'Safari', // experiencing issues with safari-launcher@1.0.0 and Safari 9.1.1
'Firefox'
],
browsers,
customLaunchers: require('./test/karma/browserstack-launchers'),
browserStack: {
username: env.BS_USERNAME,
accessKey: env.BS_AUTHKEY,
username: env.BS_USERNAME || env.BROWSERSTACK_USERNAME,
accessKey: env.BS_AUTHKEY || env.BROWSERSTACK_ACCESS_KEY,
name: 'Unit Tests',
project: 'jwplayer',
build: '' + (env.JOB_NAME || 'local') + ' ' +
(env.BUILD_NUMBER || env.USER) + ' ' +
(env.GIT_BRANCH || '') + ' ' + packageInfo.version,
build: env.BROWSERSTACK_BUILD || ('' + (env.JOB_NAME || 'local') + ' ' +
(env.BUILD_NUMBER || env.USER || env.GITHUB_USER) + ' ' +
(env.GIT_BRANCH || 'jwplayer') + ' ' + packageInfo.version),
timeout: 300 // 5 minutes
},
@@ -3,11 +3,15 @@ import { DRAG, DRAG_START, DRAG_END, CLICK, DOUBLE_CLICK, MOVE, OUT, TAP, DOUBLE
import Events from 'utils/backbone.events';
import { now } from 'utils/date';
const TouchEvent = window.TouchEvent;
const PointerEvent = window.PointerEvent;
const _supportsPointerEvents = ('PointerEvent' in window) && !OS.android;
const _supportsTouchEvents = ('ontouchstart' in window); // TODO: Use createEvent() try catch test
const _useMouseEvents = !_supportsPointerEvents && !(_supportsTouchEvents && OS.mobile);
const noop = function() {};
const KeyboardEvent = window.KeyboardEvent || noop;
const MouseEvent = window.MouseEvent || noop;
const PointerEvent = window.PointerEvent || noop;
const TouchEvent = window.TouchEvent || noop;
const TOUCH_SUPPORT = ('ontouchstart' in window);
const USE_POINTER_EVENTS = ('PointerEvent' in window) && !OS.android;
const USE_MOUSE_EVENTS = !USE_POINTER_EVENTS && !(TOUCH_SUPPORT && OS.mobile);
const _isOSXFirefox = Browser.firefox && OS.mac;
let unique = 0;
@@ -17,6 +21,7 @@ let unique = 0;
// Research: listener total is 154 with 3IkpdgrX-rcY6EcsD setup
// 36 UI instances listen with 'interactStartHandler'
// 11 buttons with preventDefault
// TODO: unit tests
// TODO: Only add event listeners when on('event') requires it
// TODO: remove need for `useHover`, `useFocus`*, `useMove` and `enableDoubleTap`
@@ -51,7 +56,7 @@ const UI = function (elem, options) {
// If its not mobile, add mouse listener. Add touch listeners so touch devices that aren't Android or iOS
// (windows phones) still get listeners just in case they want to use them.
if (_supportsPointerEvents) {
if (USE_POINTER_EVENTS) {
elem.addEventListener('pointerdown', interactStartHandler, listenerOptions);
if (options.useHover) {
elem.addEventListener('pointerover', overHandler);
@@ -61,7 +66,7 @@ const UI = function (elem, options) {
elem.addEventListener('pointermove', moveHandler);
}
} else {
if (_useMouseEvents) {
if (USE_MOUSE_EVENTS) {
elem.addEventListener('mousedown', interactStartHandler, listenerOptions);
if (options.useHover) {
elem.addEventListener('mouseover', overHandler);
@@ -122,7 +127,7 @@ const UI = function (elem, options) {
}
function interactStartHandler(evt) {
_touchListenerTarget = evt.target;
const target = evt.target;
_startX = getCoord(evt, 'X');
_startY = getCoord(evt, 'Y');
@@ -137,7 +142,7 @@ const UI = function (elem, options) {
setEventListener(elem, 'pointercancel', interactEndHandler);
// Listen for mouseup after mouse pointer down because pointerup doesn't fire on swf objects
if (evt.pointerType === 'mouse' && _touchListenerTarget.nodeName === 'OBJECT') {
if (evt.pointerType === 'mouse' && target.nodeName === 'OBJECT') {
setEventListener(document, 'mouseup', interactEndDelegate);
} else {
setEventListener(elem, 'pointerup', interactEndHandler);
@@ -152,6 +157,7 @@ const UI = function (elem, options) {
setEventListener(document, 'mouseup', interactEndDelegate);
}
} else if (evt.type === 'touchstart') {
_touchListenerTarget = target;
longPressTimeout = setTimeout(() => {
if (_touchListenerTarget) {
_touchListenerTarget.removeEventListener('touchmove', interactDragHandler);
@@ -253,8 +259,6 @@ const UI = function (elem, options) {
this.trigger(type, evt);
};
this.triggerEvent = triggerEvent;
this.destroy = function() {
this.off();
elem.removeEventListener('touchstart', interactStartHandler);
@@ -268,7 +272,7 @@ const UI = function (elem, options) {
_touchListenerTarget = null;
}
if (_supportsPointerEvents) {
if (USE_POINTER_EVENTS) {
if (options.preventScrolling) {
elem.releasePointerCapture(_pointerId);
}
@@ -391,16 +395,16 @@ export default UI;
// Expose what the source of the event is so that we can ensure it's handled correctly.
// This returns only 'touch' or 'mouse'. 'pen' will be treated as a mouse.
export function getPointerType(evt) {
if ((_supportsTouchEvents && evt instanceof TouchEvent) ||
(_supportsPointerEvents && evt instanceof PointerEvent && evt.pointerType === 'touch')) {
if ((TOUCH_SUPPORT && evt instanceof TouchEvent) ||
(USE_POINTER_EVENTS && evt instanceof PointerEvent && evt.pointerType === 'touch')) {
return 'touch';
}
return 'mouse';
}
function getCoord(e, c) {
return /touch/.test(e.type) ? (e.originalEvent || e).changedTouches[0]['page' + c] : e['page' + c];
return /^touch/.test(e.type) ? (e.originalEvent || e).changedTouches[0]['page' + c] : e['page' + c];
}
function isRightClick(evt) {
@@ -2,18 +2,18 @@ module.exports = {
firefox: {
base: 'BrowserStack',
browser: 'firefox',
os: 'OS X',
os_version: 'Yosemite'
os: 'Windows',
os_version: '10'
},
chrome: {
base: 'BrowserStack',
browser: 'chrome',
os: 'OS X',
os_version: 'Yosemite'
os: 'Windows',
os_version: '10'
},
ie11_windows: {
ie11: {
base: 'BrowserStack',
browser: 'ie',
browser_version: '11.0',
@@ -26,5 +26,23 @@ module.exports = {
browser: 'edge',
os: 'Windows',
os_version: '10'
},
iphone: {
base: 'BrowserStack',
device: 'iPhone 7',
device_browser: 'safari',
os: 'iOS',
os_version: '10.0',
real_mobile: true
},
android: {
base: 'BrowserStack',
device: 'Samsung Galaxy S8',
device_browser: 'chrome',
os: 'android',
os_version: '7.0',
real_mobile: true
}
};
@@ -2,7 +2,7 @@ import { ajax } from 'utils/ajax';
import * as errors from 'api/errors';
describe('utils.ajax', function() {
this.timeout(5000);
this.timeout(8000);
function validateXHR(xhr) {
expect(xhr).to.be.instanceOf(window.XMLHttpRequest);
@@ -1,5 +1,4 @@
import _ from 'test/underscore';
import $ from 'jquery';
import jwplayer from 'jwplayer';
function testInstanceOfApi(api) {
@@ -11,8 +10,13 @@ function testInstanceOfApi(api) {
describe('jwplayer function', function() {
beforeEach(function() {
// remove fixture
$('body').append('<div id="test-container"><div id="player"></div></div>');
// add fixture
const fixture = document.createElement('div');
fixture.id = 'test-container';
const playerContainer = document.createElement('div');
playerContainer.id = 'player';
fixture.appendChild(playerContainer);
document.body.appendChild(fixture);
});
afterEach(function() {
@@ -24,7 +28,8 @@ describe('jwplayer function', function() {
}
}
// remove fixture
$('#test-container').remove();
const fixture = document.querySelector('#test-container');
document.body.removeChild(fixture);
});
it('is defined', function() {
@@ -60,12 +65,12 @@ describe('jwplayer function', function() {
});
it('returns a new api instance when given an element with an id', function() {
const element = $('#player')[0];
const element = document.querySelector('#player');
testInstanceOfApi(jwplayer(element));
});
it('returns a new api instance when given an element with no id not in the DOM', function() {
const element = $('<div></div>')[0];
const element = document.createElement('div');
const x = testInstanceOfApi(jwplayer(element));
// FIXME: this only works with one player whose id is empty ""
@@ -74,10 +79,10 @@ describe('jwplayer function', function() {
});
it('returns the same api instance for matching queries', function() {
const element = $('#player')[0];
const element = document.querySelector('#player');
const x = jwplayer('player');
const y = jwplayer($('<div></div>')[0]);
const y = jwplayer(document.createElement('div'));
const uniquePlayers = _.uniq([
x,
@@ -418,15 +418,16 @@ describe('ProgramController', function () {
it('fires itemReady for background loaded items', function() {
sandbox.spy(model, 'trigger');
const changeMediaElement = model.get('backgroundLoading') ? 1 : 0;
return programController.setActiveItem(0)
.then(function () {
expect(model.trigger).to.have.callCount(6);
expect(model.trigger).to.have.callCount(5 + changeMediaElement);
expect(model.trigger.lastCall).to.have.been.calledWith('change:itemReady', model, true);
programController.backgroundLoad(mp4Item);
})
.then(() => programController.setActiveItem(1))
.then(function () {
expect(model.trigger).to.have.callCount(13);
expect(model.trigger).to.have.callCount(11 + changeMediaElement * 2);
expect(model.trigger.lastCall).to.have.been.calledWith('change:itemReady', model, true);
});
});
Oops, something went wrong.

0 comments on commit 777a569

Please sign in to comment.