1
0
mirror of https://github.com/videojs/video.js.git synced 2025-03-17 21:18:27 +02:00

Merge branch 'feature/test-buildout'

This commit is contained in:
Steve Heffernan 2012-12-10 18:54:48 -08:00
commit 60a70f94b2
59 changed files with 480 additions and 357 deletions

4
.gitignore vendored
View File

@ -2,4 +2,6 @@
dist/*
dev.html
projects
.zenflow-log
.zenflow-log
node_modules

16
.jshintrc Normal file
View File

@ -0,0 +1,16 @@
{
"validthis": true,
"browser" : true,
"debug" : true,
"boss" : true,
"expr" : true,
"eqnull" : true,
"quotmark" : "double",
"sub" : true,
"trailing" : true,
"undef" : true,
"predef" : [ // Extra globals.
"_V_",
"VideoJS"
]
}

3
.travis.yml Normal file
View File

@ -0,0 +1,3 @@
language: node_js
node_js:
- 0.8

View File

@ -1,3 +1,4 @@
* Added automated test suite and support for Travis CI.
* Updated docs to use Github markdown
* Allow disabling of default components
* Duration is now setable (need ed for HLS m3u8 files)

10
Makefile Normal file
View File

@ -0,0 +1,10 @@
# Using makefile temporarily to run tests on Travis CI
test:
# jshint src/*.js --config .jshintrc
node test/server.js &
phantomjs test/phantom.js "http://localhost:3000/test/unit.html"
kill -9 `cat test/pid.txt`
rm test/pid.txt
.PHONY: test

View File

@ -1,51 +0,0 @@
#! /bin/csh
# Combines Source Files. In terminal, sh build.sh
# It will put a new video.js file under dist/
# Create dist directory if it doesn't already exist
mkdir -p dist
# FILES=../src/*
# for f in $FILES
# do
# echo "Processing $f file..."
# # take action on each file. $f store current file name
# cat $f
# done
cat src/_begin.js > dist/video.js
cat src/core.js >> dist/video.js
cat src/lib.js >> dist/video.js
cat src/json.js >> dist/video.js
cat src/events.js >> dist/video.js
cat src/component.js >> dist/video.js
cat src/player.js >> dist/video.js
cat src/tech.js >> dist/video.js
cat src/controls.js >> dist/video.js
cat src/tracks.js >> dist/video.js
# h5swf temporarily requires swfobject
# cat flash/swfobject.js >> dist/video.js
cat tech/html5/html5.js >> dist/video.js
cat tech/flash/flash.js >> dist/video.js
cat src/setup.js >> dist/video.js
cat src/_end.js >> dist/video.js
# Copy Files
cp design/video-js.css dist/video-js.css
cp design/video-js.png dist/video-js.png
cp flash/video-js.swf dist/video-js.swf
cp build/release-files/README.md dist/README.md
cp build/release-files/demo.html dist/demo.html
cp LGPLv3-LICENSE.txt dist/LGPLv3-LICENSE.txt
java -jar build/lib/yuicompressor-2.4.7.jar dist/video.js -o dist/video.min.js
java -jar build/lib/yuicompressor-2.4.7.jar dist/video-js.css -o dist/video-js.min.css

View File

@ -1,8 +0,0 @@
Tracking/Polling CurrentTime Manually
-------------------------------------
- Necessary for most flash players and browsers that don't trigger timeupdate events.
- In VJS 1-2, we always tracked time because timeupdate was rare.
- Now most browsers support it well. There is a delay bug in the current Chrome.
http://code.google.com/p/chromium/issues/detail?id=92251
Andrew from Chrome told me it would be fix in an upcoming release.
Going to rely on browsers timeupdates when available now.

View File

@ -1,13 +0,0 @@
1
00:00:00,000 --> 00:00:07,200
[Background Music Playing]
2
00:00:16,000 --> 00:00:17,200
Welcome to this week's episode
3
00:00:17,400 --> 00:00:19,000
of explore California

18
package.json Normal file
View File

@ -0,0 +1,18 @@
{
"name": "Video.js"
, "description": "An HTML5 and Flash video player with a common API and skin for both."
, "version": "3.2.3"
, "keywords": ["html5", "flash", "video", "player"]
, "homepage": "http://videojs.com"
, "author": "Steve Heffernan"
, "scripts": { "test": "make test" }
, "repository": {
"type": "git"
, "url": "https://github.com/zencoder/video-js.git"
}
, "devDependencies": {
, "jshint": "0.6.1"
, "connect": "2.1.3"
, "phantomjs": "1.7.0"
}
}

View File

@ -1 +0,0 @@
var vjsSourceList = [];

File diff suppressed because one or more lines are too long

42
test/integration.html Normal file
View File

@ -0,0 +1,42 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Video.js Test Suite</title>
<!-- QUnit -->
<link rel="stylesheet" href="vendor/qunit/qunit/qunit.css" />
<script src="vendor/qunit/qunit/qunit.js"></script>
<!-- Video.js CSS -->
<link rel="stylesheet" href="../design/video-js.css" type="text/css">
<!-- Video.js JavaScript -->
<script src='../src/core.js'></script>
<script src='../src/lib.js'></script>
<script src='../src/component.js'></script>
<script src='../src/controls.js'></script>
<script src='../src/events.js'></script>
<script src='../src/json.js'></script>
<script src='../src/player.js'></script>
<script src='../src/tech.js'></script>
<script src='../src/tracks.js'></script>
<script src='../tech/html5/html5.js'></script>
<script src='../tech/flash/flash.js'></script>
<script src='../src/setup.js'></script>
<!-- Integration Tests -->
<script src="integration/test.js"></script>
</head>
<body>
<div>
<h1 id="qunit-header">Bootstrap Plugin Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
</div>
</body>
</html>

View File

@ -43,7 +43,7 @@ function createVideoTag(id){
function playerSetup(){
_V_.el("player_box").appendChild(createVideoTag())
_V_.el("qunit-fixture").appendChild(createVideoTag())
var vid = document.getElementById("vid1");
this.player = _V_(vid);
@ -137,107 +137,107 @@ test("Paused", 2, function() {
this.player.play();
});
test("currentTime()", 1, function() {
stop();
// test("currentTime()", 1, function() {
// stop();
// Try for 3 time updates, sometimes it updates at 0 seconds.
// var tries = 0;
// // Try for 3 time updates, sometimes it updates at 0 seconds.
// // var tries = 0;
// Can't rely on just time update because it's faked for Flash.
this.player.one("loadeddata", _V_.proxy(this, function(){
// // Can't rely on just time update because it's faked for Flash.
// this.player.one("loadeddata", _V_.proxy(this, function(){
this.player.addEvent("timeupdate", _V_.proxy(this, function(){
// this.player.addEvent("timeupdate", _V_.proxy(this, function(){
if (this.player.currentTime() > 0) {
ok(true, "Time is greater than 0.");
start();
} else {
// tries++;
}
// if (this.player.currentTime() > 0) {
// ok(true, "Time is greater than 0.");
// start();
// } else {
// // tries++;
// }
// if (tries >= 3) {
// start();
// }
}));
// // if (tries >= 3) {
// // start();
// // }
// }));
}));
// }));
this.player.play();
});
// this.player.play();
// });
test("currentTime(seconds)", 2, function() {
stop();
// test("currentTime(seconds)", 2, function() {
// stop();
// var afterPlayback = _V_.proxy(this, function(){
// this.player.currentTime(this.player.duration() / 2);
//
// this.player.addEvent("timeupdate", _V_.proxy(this, function(){
// ok(this.player.currentTime() > 0, "Time is greater than 0.");
//
// this.player.pause();
//
// this.player.addEvent("timeupdate", _V_.proxy(this, function(){
// ok(this.player.currentTime() == 0, "Time is 0.");
// start();
// }));
//
// this.player.currentTime(0);
// }));
// });
// // var afterPlayback = _V_.proxy(this, function(){
// // this.player.currentTime(this.player.duration() / 2);
// //
// // this.player.addEvent("timeupdate", _V_.proxy(this, function(){
// // ok(this.player.currentTime() > 0, "Time is greater than 0.");
// //
// // this.player.pause();
// //
// // this.player.addEvent("timeupdate", _V_.proxy(this, function(){
// // ok(this.player.currentTime() == 0, "Time is 0.");
// // start();
// // }));
// //
// // this.player.currentTime(0);
// // }));
// // });
// Wait for Source to be ready.
this.player.one("loadeddata", _V_.proxy(this, function(){
// // Wait for Source to be ready.
// this.player.one("loadeddata", _V_.proxy(this, function(){
_V_.log("loadeddata", this.player);
this.player.currentTime(this.player.duration() - 1);
// _V_.log("loadeddata", this.player);
// this.player.currentTime(this.player.duration() - 1);
}));
// }));
this.player.one("seeked", _V_.proxy(this, function(){
// this.player.one("seeked", _V_.proxy(this, function(){
_V_.log("seeked", this.player.currentTime())
ok(this.player.currentTime() > 1, "Time is greater than 1.");
// _V_.log("seeked", this.player.currentTime())
// ok(this.player.currentTime() > 1, "Time is greater than 1.");
this.player.one("seeked", _V_.proxy(this, function(){
// this.player.one("seeked", _V_.proxy(this, function(){
_V_.log("seeked2", this.player.currentTime())
// _V_.log("seeked2", this.player.currentTime())
ok(this.player.currentTime() <= 1, "Time is less than 1.");
start();
// ok(this.player.currentTime() <= 1, "Time is less than 1.");
// start();
}));
// }));
this.player.currentTime(0);
// this.player.currentTime(0);
}));
// }));
this.player.play();
// this.player.play();
// this.player.one("timeupdate", _V_.proxy(this, function(){
//
// this.player.currentTime(this.player.duration() / 2);
//
// this.player.one("timeupdate", _V_.proxy(this, function(){
// ok(this.player.currentTime() > 0, "Time is greater than 0.");
//
// this.player.pause();
// this.player.currentTime(0);
//
// this.player.one("timeupdate", _V_.proxy(this, function(){
//
// ok(this.player.currentTime() == 0, "Time is 0.");
// start();
//
// }));
//
// }));
//
//
// }));
// // this.player.one("timeupdate", _V_.proxy(this, function(){
// //
// // this.player.currentTime(this.player.duration() / 2);
// //
// // this.player.one("timeupdate", _V_.proxy(this, function(){
// // ok(this.player.currentTime() > 0, "Time is greater than 0.");
// //
// // this.player.pause();
// // this.player.currentTime(0);
// //
// // this.player.one("timeupdate", _V_.proxy(this, function(){
// //
// // ok(this.player.currentTime() == 0, "Time is 0.");
// // start();
// //
// // }));
// //
// // }));
// //
// //
// // }));
});
// });
/* Events
================================================================================ */

63
test/phantom.js Normal file
View File

@ -0,0 +1,63 @@
// Simple phantom.js integration script
// Adapted from Modernizr & Bootstrap
function waitFor(testFx, onReady, timeOutMillis) {
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 5001 //< Default Max Timout is 5s
, start = new Date().getTime()
, condition = false
, interval = setInterval(function () {
if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) {
// If not time-out yet and condition not yet fulfilled
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()) //< defensive code
} else {
if (!condition) {
// If condition still not fulfilled (timeout but condition is 'false')
console.log("'waitFor()' timeout")
phantom.exit(1)
} else {
// Condition fulfilled (timeout and/or condition is 'true')
typeof(onReady) === "string" ? eval(onReady) : onReady() //< Do what it's supposed to do once the condition is fulfilled
clearInterval(interval) //< Stop this interval
}
}
}, 100) //< repeat check every 100ms
}
if (phantom.args.length === 0 || phantom.args.length > 2) {
console.log('Usage: phantom.js URL')
phantom.exit()
}
var page = new WebPage()
// Route "console.log()" calls from within the Page context to the main Phantom context (i.e. current "this")
page.onConsoleMessage = function(msg) {
console.log(msg)
};
page.open(phantom.args[0], function(status){
if (status !== "success") {
console.log("Unable to access network")
phantom.exit()
} else {
waitFor(function(){
return page.evaluate(function(){
var el = document.getElementById('qunit-testresult')
if (el && el.innerText.match('completed')) {
return true
}
return false
})
}, function(){
var failedNum = page.evaluate(function(){
var el = document.getElementById('qunit-testresult')
try {
return el.getElementsByClassName('failed')[0].innerHTML
} catch (e) { }
return 10000
});
phantom.exit((parseInt(failedNum, 10) > 0) ? 1 : 0)
})
}
})

14
test/server.js Normal file
View File

@ -0,0 +1,14 @@
/*
* Simple connect server for phantom.js
* Adapted from Modernizr & Bootstrap
*/
var connect = require('connect')
, http = require('http')
, fs = require('fs')
, app = connect()
.use(connect.static(__dirname + '/../'));
http.createServer(app).listen(3000);
fs.writeFileSync(__dirname + '/pid.txt', process.pid, 'utf-8')

View File

@ -1,52 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>QUnit Test Suite</title>
<link rel="stylesheet" href="../design/video-js.css" type="text/css">
<!--[if IE]>
<script src="https://getfirebug.com/firebug-lite.js" type="text/javascript" charset="utf-8"></script>
<![endif]-->
<!-- Video.js Source Files -->
<script src='../src/core.js'></script>
<script src='../src/lib.js'></script>
<script src='../src/component.js'></script>
<script src='../src/controls.js'></script>
<script src='../src/events.js'></script>
<script src='../src/json.js'></script>
<script src='../src/player.js'></script>
<script src='../src/tech.js'></script>
<script src='../src/tracks.js'></script>
<script src='../tech/html5/html5.js'></script>
<script src='../tech/flash/flash.js'></script>
<script src='../src/setup.js'></script>
<!-- END Video.js Source Files -->
<script type="text/javascript" charset="utf-8">
// Easy access to test Flash over HTML5. Add ?flash to URL
if (window.location.href.indexOf("?flash") !== -1) {
_V_.options.techOrder = ["flash"]
}
</script>
<link rel="stylesheet" href="qunit/qunit/qunit.css" type="text/css" media="screen">
<script type="text/javascript" src="qunit/qunit/qunit.js"></script>
<script type="text/javascript" src="test.js"></script>
</head>
<body>
<h1 id="qunit-header">QUnit Test Suite</h1>
<h2 id="qunit-banner"></h2>
<div id="qunit-testrunner-toolbar"></div>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture">test markup</div>
<div id="player_box"></div>
</body>
</html>

48
test/unit.html Normal file
View File

@ -0,0 +1,48 @@
<!DOCTYPE HTML>
<html>
<head>
<title>Video.js Test Suite</title>
<!-- QUnit -->
<link rel="stylesheet" href="vendor/qunit/qunit/qunit.css" />
<script src="vendor/qunit/qunit/qunit.js"></script>
<!-- phantomjs logging script-->
<script src="unit/phantom-logging.js"></script>
<!-- Video.js CSS -->
<link rel="stylesheet" href="../design/video-js.css" type="text/css">
<!-- Video.js JavaScript -->
<script src='../src/core.js'></script>
<script src='../src/lib.js'></script>
<script src='../src/component.js'></script>
<script src='../src/controls.js'></script>
<script src='../src/events.js'></script>
<script src='../src/json.js'></script>
<script src='../src/player.js'></script>
<script src='../src/tech.js'></script>
<script src='../src/tracks.js'></script>
<script src='../tech/html5/html5.js'></script>
<script src='../tech/flash/flash.js'></script>
<script src='../src/setup.js'></script>
<!-- Unit Tests -->
<script src="unit/component.js"></script>
<script src="unit/controls.js"></script>
<script src="unit/player.js"></script>
<script src="unit/lib.js"></script>
</head>
<body>
<div>
<h1 id="qunit-header">Bootstrap Plugin Test Suite</h1>
<h2 id="qunit-banner"></h2>
<h2 id="qunit-userAgent"></h2>
<ol id="qunit-tests"></ol>
<div id="qunit-fixture"></div>
</div>
</body>
</html>

67
test/unit/component.js Normal file
View File

@ -0,0 +1,67 @@
module("Component");
test('should create an element', function(){
var comp = new _V_.Component({}, {});
ok(comp.el.nodeName);
});
test('should init child coponents from options', function(){
var comp = new _V_.Component({}, {
components: {
'component': true
}
});
ok(comp.el.childNodes.length === 1);
});
test('should show and hide an element', function(){
var comp = new _V_.Component({}, {});
comp.hide();
ok(comp.el.style.display === 'none');
comp.show();
ok(comp.el.style.display === 'block');
});
test('should add and remove a CSS class', function(){
var comp = new _V_.Component({}, {});
comp.addClass('test-class');
ok(comp.el.className.indexOf('test-class') !== -1);
comp.removeClass('test-class');
ok(comp.el.className.indexOf('test-class') === -1);
});
test('should add and remove event listeners to element', function(){
var comp = new _V_.Component({}, {});
// No need to make this async because we're triggering events inline.
// We're going to trigger the event after removing the listener,
// So if we get extra asserts that's a problem.
expect(1);
var testListener = function(){
ok(true, 'fired event once');
};
comp.on('test-event', testListener);
comp.trigger('test-event');
comp.off('test-event', testListener);
comp.trigger('test-event');
});
test('should trigger a listener once using one()', function(){
var comp = new _V_.Component({}, {});
expect(1);
var testListener = function(){
ok(true, 'fired event once');
};
comp.one('test-event', testListener);
comp.trigger('test-event');
comp.trigger('test-event');
});

1
test/unit/controls.js vendored Normal file
View File

@ -0,0 +1 @@
module("Controls");

1
test/unit/core.js Normal file
View File

@ -0,0 +1 @@
module("Core");

1
test/unit/events.js Normal file
View File

@ -0,0 +1 @@
module("Events");

69
test/unit/lib.js Normal file
View File

@ -0,0 +1,69 @@
module("Lib");
test('should merge two objects', function(){
var obj1 = { a:1, b:2 };
var obj2 = { b:3, c:4 };
_V_.merge(obj1, obj2);
deepEqual(obj1, {a:1,b:3,c:4} );
});
test('should create an element with attributes', function(){
var el = _V_.createElement('div', { className: 'test-class', 'data-test': 'asdf' })
ok(el.className === 'test-class');
ok(el.getAttribute('data-test') === 'asdf' );
});
test('should insert an element first', function(){
var el1 = document.createElement('div');
var el2 = document.createElement('div');
var el3 = document.createElement('div');
_V_.insertFirst(el2, el1);
ok(el1.childNodes[0] === el2);
_V_.insertFirst(el3, el1);
ok(el1.childNodes[0] === el3);
});
test('should add and remove a CSS class', function(){
var el = document.createElement('div');
_V_.addClass(el, 'test-class')
ok(el.className.indexOf('test-class') !== -1);
_V_.removeClass(el, 'test-class')
ok(el.className.indexOf('test-class') === -1);
});
test('should format the time', function(){
ok(_V_.formatTime(120) === "2:00");
ok(_V_.formatTime(18121) === "5:02:01");
});
test('should uppercase a word', function(){
ok(_V_.uc('asdf') === "Asdf");
});
test('should trim a string', function(){
ok(_V_.trim(' asdf ') === "asdf");
});
test('should round a number', function(){
ok(_V_.round(1.01) === 1);
ok(_V_.round(1.01, 1) === 1.0);
ok(_V_.round(1.01, 2) === 1.01);
ok(_V_.round(1.05, 1) === 1.1);
});
test('should test that an object is empty', function(){
ok(_V_.isEmpty({}) === true);
ok(_V_.isEmpty({ asdf: 'asdf' }) === false);
});
test('should create a fake timerange', function(){
var tr = _V_.createTimeRange(0, 100);
ok(tr.start() === 0);
ok(tr.end() === 100);
ok(tr.length === 1);
});

View File

@ -0,0 +1,21 @@
// Logging setup for phantom integration
// adapted from Modernizr & Bootstrap
QUnit.begin = function () {
console.log("Starting test suite")
console.log("================================================\n")
}
QUnit.moduleDone = function (opts) {
if (opts.failed === 0) {
console.log("\u2714 All tests passed in '" + opts.name + "' module")
} else {
console.log("\u2716 " + opts.failed + " tests failed in '" + opts.name + "' module")
}
}
QUnit.done = function (opts) {
console.log("\n================================================")
console.log("Tests completed in " + opts.runtime + " milliseconds")
console.log(opts.passed + " tests of " + opts.total + " passed, " + opts.failed + " failed.")
}

22
test/unit/player.js Normal file
View File

@ -0,0 +1,22 @@
module("Player", {
setup: function(){
var videoTag = document.createElement('video');
videoTag.id = 'example_1';
videoTag.className = 'video-js vjs-default-skin';
var fixture = document.getElementById('qunit-fixture');
fixture.appendChild(videoTag);
this.player = new _V_.Player(videoTag, {});
},
teardown: function(){
}
});
test('should create and embed a new player element', function(){
ok(this.player.el.nodeName === 'DIV');
ok(this.player.el.parentNode.id === 'qunit-fixture');
ok(this.player.el.className.indexOf('video-js vjs-default-skin') !== -1);
ok(this.player.el.id === 'example_1');
});

1
test/unit/setup.js Normal file
View File

@ -0,0 +1 @@
module("Setup");

1
test/unit/tech.js Normal file
View File

@ -0,0 +1 @@
module("Tech");

1
test/unit/tracks.js Normal file
View File

@ -0,0 +1 @@
module("Tracks");