mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Merge pull request #451 from subtleGradient/subtlegradient/browser-testing
Browser testing.
This commit is contained in:
+1
-1
@@ -22,4 +22,4 @@ docs/js/live_editor.js
|
||||
docs/js/examples
|
||||
docs/downloads
|
||||
examples/shared/*.js
|
||||
|
||||
test/the-files-to-test.generated.js
|
||||
|
||||
@@ -13,3 +13,5 @@ env:
|
||||
- secure: qPvsJ46XzGrdIuPA70b55xQNGF8jcK7N1LN5CCQYYocXLa+fBrl+fTE77QvehOPhqwJXcj6kOxI+sY0KrVwV7gmq2XY2HZGWUSCxTN0SZlNIzqPA80Y7G/yOjA4PUt8LKgP+8tptyhTAY56qf+hgW8BoLiKOdztYF2p+3zXOLuA=
|
||||
# SECRET_TOKEN
|
||||
- secure: dkpPW+VnoqC/okhRdV90m36NcyBFhcwEKL3bNFExAwi0dXnFao8RoFlvnwiPlA23h2faROkMIetXlti6Aju08BgUFV+f9aL6vLyU7gUent4Nd3413zf2fwDtXIWIETg6uLnOpSykGKgCAT/hY3Q2oPLqOoY0OxfgnbqwxkxljrE=
|
||||
- secure: eHMg4yQWJ+5zFxNcjVwpdpcbZCQMaSByqJy0wwQ2XOOMItdCvSfO/fa+mYoVND/9Orsi5kvXC9tx4sYHyth5hLrvO+bghYjiayrbxYYrxso6G/aU8Pttc7s/qk3I4zadLlua1kGy2TauByxS6nt9nUDe0FDaJKA9k1QXVlpq5Ac=
|
||||
- secure: v65jUPPNBvJg1xhj4cY7wMKinCESUseHsW1d2gp68SluFHHyjWZOvXYXZdABqB/1uNmQxjbUkwkdSNAOn5k7ppjRcRnlAH2uu1xDqXrGp6cW4MfNPchrAe+FcUMtse/3THGJj8SZ9IQWIl+BHv4XASQ7FwqCR8cwlOfhsqdfch8=
|
||||
|
||||
+19
-10
@@ -4,7 +4,8 @@ var exec = require('child_process').exec;
|
||||
var jsxTask = require('./grunt/tasks/jsx');
|
||||
var browserifyTask = require('./grunt/tasks/browserify');
|
||||
var populistTask = require('./grunt/tasks/populist');
|
||||
var phantomTask = require('./grunt/tasks/phantom');
|
||||
var webdriverPhantomJSTask = require('./grunt/tasks/webdriver-phantomjs');
|
||||
var webdriverJasmineTasks = require('./grunt/tasks/webdriver-jasmine');
|
||||
var npmTask = require('./grunt/tasks/npm');
|
||||
var releaseTasks = require('./grunt/tasks/release');
|
||||
|
||||
@@ -16,7 +17,8 @@ module.exports = function(grunt) {
|
||||
jsx: require('./grunt/config/jsx/jsx'),
|
||||
browserify: require('./grunt/config/browserify'),
|
||||
populist: require('./grunt/config/populist'),
|
||||
phantom: require('./grunt/config/phantom'),
|
||||
connect: require('./grunt/config/server')(grunt),
|
||||
"webdriver-jasmine": require('./grunt/config/webdriver-jasmine.js'),
|
||||
npm: require('./grunt/config/npm'),
|
||||
clean: ['./build', './*.gem', './docs/_site', './examples/shared/*.js'],
|
||||
jshint: require('./grunt/config/jshint'),
|
||||
@@ -25,11 +27,12 @@ module.exports = function(grunt) {
|
||||
|
||||
grunt.config.set('compress', require('./grunt/config/compress'));
|
||||
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
grunt.loadNpmTasks('grunt-compare-size');
|
||||
grunt.loadNpmTasks('grunt-contrib-compress');
|
||||
Object.keys(grunt.file.readJSON('package.json').devDependencies)
|
||||
.filter(function(npmTaskName){ return npmTaskName.indexOf('grunt-') === 0;})
|
||||
.forEach(function(npmTaskName){
|
||||
grunt.loadNpmTasks(npmTaskName);
|
||||
})
|
||||
;
|
||||
|
||||
// Alias 'jshint' to 'lint' to better match the workflow we know
|
||||
grunt.registerTask('lint', ['jshint']);
|
||||
@@ -42,7 +45,7 @@ module.exports = function(grunt) {
|
||||
|
||||
grunt.registerMultiTask('populist', populistTask);
|
||||
|
||||
grunt.registerMultiTask('phantom', phantomTask);
|
||||
grunt.registerMultiTask('webdriver-jasmine', webdriverJasmineTasks);
|
||||
|
||||
grunt.registerMultiTask('npm', npmTask);
|
||||
|
||||
@@ -70,11 +73,17 @@ module.exports = function(grunt) {
|
||||
'jsx:jasmine',
|
||||
'jsx:test',
|
||||
'version-check',
|
||||
'populist:jasmine',
|
||||
'populist:test'
|
||||
]);
|
||||
|
||||
grunt.registerTask('test', ['build:test', 'build:basic', 'phantom:run']);
|
||||
grunt.registerTask('webdriver-phantomjs', webdriverPhantomJSTask);
|
||||
|
||||
grunt.registerTask('test:webdriver:phantomjs', [
|
||||
'connect',
|
||||
'webdriver-phantomjs',
|
||||
'webdriver-jasmine:local'
|
||||
]);
|
||||
grunt.registerTask('test', ['build:test', 'build:basic', 'test:webdriver:phantomjs']);
|
||||
grunt.registerTask('npm:test', ['build', 'npm:pack']);
|
||||
|
||||
// Optimized build task that does all of our builds. The subtasks will be run
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
var grunt = require("grunt");
|
||||
|
||||
exports.run = {
|
||||
port: 8080,
|
||||
harness: "test/phantom-harness.js",
|
||||
// Run `grunt test --debug` to enable in-browser testing.
|
||||
debug: !!grunt.option("debug"),
|
||||
tests: [
|
||||
"**/__tests__/*-test.js"
|
||||
]
|
||||
};
|
||||
@@ -0,0 +1,47 @@
|
||||
var pxlgif = Buffer('R0lGODlhAQABAIAAAP///wAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==', 'base64');
|
||||
|
||||
module.exports = function(grunt){
|
||||
|
||||
function printMiddleware(req, res, next) {
|
||||
if (req._parsedUrl.pathname != '/print') return next();
|
||||
if (req.query.message.indexOf('ok') === 0){
|
||||
grunt.log.ok(req.query.message);
|
||||
} else if (req.query.message.indexOf('not ok') === 0){
|
||||
grunt.log.error(req.query.message);
|
||||
} else {
|
||||
grunt[req.query.type || 'log'].writeln('[%s][%s]', req.headers['user-agent'], Date.now(), req.query.message);
|
||||
}
|
||||
res.end(pxlgif);
|
||||
}
|
||||
function testResultLoggerMiddleware(req, res, next) {
|
||||
if (!(req.body && req.body.data)) return next();
|
||||
grunt.log.writeln('[%s][%s]', req.headers['user-agent'], Date.now(), req.body.data);
|
||||
res.end('Got it, thanks!');
|
||||
}
|
||||
|
||||
return {
|
||||
server: {
|
||||
options: {
|
||||
base: '.',
|
||||
hostname: '*',
|
||||
port: 9999,
|
||||
middleware: function(connect, options) {
|
||||
connect.logger.token('user-agent', function(req, res){ return req.headers['user-agent']; });
|
||||
connect.logger.token('timestamp', function(req, res){ return Date.now(); });
|
||||
|
||||
return [
|
||||
connect.query(),
|
||||
printMiddleware,
|
||||
|
||||
connect.logger({format:'[:user-agent][:timestamp] :method :url', stream:grunt.verbose}),
|
||||
connect.bodyParser(),
|
||||
testResultLoggerMiddleware,
|
||||
|
||||
connect.static(options.base),
|
||||
connect.directory(options.base)
|
||||
];
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
var grunt = require('grunt');
|
||||
|
||||
|
||||
exports.local = {
|
||||
webdriver: {
|
||||
remote: { protocol: 'http:', hostname: '127.0.0.1', port: 9515, path: '/' }
|
||||
},
|
||||
url: "http://127.0.0.1:9999/test/index.html",
|
||||
onComplete: function(report){
|
||||
var browser = this;
|
||||
if (!report.passed){
|
||||
grunt.fatal("tests failed");
|
||||
}
|
||||
},
|
||||
onError: function(error){
|
||||
grunt.fatal(error);
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
var assert = require("assert");
|
||||
var grunt = require("grunt");
|
||||
var spawn = grunt.util.spawn;
|
||||
var semver = require("semver");
|
||||
var MIN_VERSION = "1.9.0";
|
||||
var phantomjs = require("phantomjs").path;
|
||||
|
||||
function checkVersion(error, result, code) {
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
assert.strictEqual(code, 0);
|
||||
|
||||
var version = result.stdout;
|
||||
|
||||
assert.ok(
|
||||
semver.valid(version),
|
||||
"Invalid PhantomJS version: " + version
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
semver.gte(version, MIN_VERSION),
|
||||
"PhantomJS v" + version + " too old; need to install " +
|
||||
"v" + MIN_VERSION + " or higher."
|
||||
);
|
||||
}
|
||||
|
||||
function run(config, done) {
|
||||
var args = [
|
||||
config.harness,
|
||||
"--port", config.port
|
||||
];
|
||||
|
||||
if (config.debug) {
|
||||
args.push("--debug");
|
||||
}
|
||||
|
||||
args.push("--tests");
|
||||
grunt.file.expand({
|
||||
nonull: true,
|
||||
cwd: "src"
|
||||
}, config.tests || []).forEach(function(file) {
|
||||
args.push(file.replace(/\.js$/i, ""));
|
||||
});
|
||||
|
||||
var child = spawn({
|
||||
cmd: phantomjs,
|
||||
args: args
|
||||
}, done);
|
||||
|
||||
child.stdout.pipe(process.stdout);
|
||||
child.stderr.pipe(process.stderr);
|
||||
}
|
||||
|
||||
module.exports = function() {
|
||||
var config = this.data;
|
||||
var done = this.async();
|
||||
|
||||
spawn({
|
||||
cmd: phantomjs,
|
||||
args: ["--version"]
|
||||
}, function(error, result, code) {
|
||||
checkVersion(error, result, code);
|
||||
run(config, done);
|
||||
});
|
||||
};
|
||||
+12
-1
@@ -1,11 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
var grunt = require('grunt');
|
||||
var fs = require('fs')
|
||||
|
||||
module.exports = function() {
|
||||
var config = this.data;
|
||||
var done = this.async();
|
||||
|
||||
var theFilesToTestScript = fs.createWriteStream(__dirname + '/../../test/the-files-to-test.generated.js');
|
||||
theFilesToTestScript.write('// Generated by ');
|
||||
theFilesToTestScript.write(JSON.stringify(__filename.split(/(?=grunt)/)[1]));
|
||||
theFilesToTestScript.write(' at ');
|
||||
theFilesToTestScript.write(JSON.stringify(new Date()));
|
||||
theFilesToTestScript.write('\n\n');
|
||||
|
||||
// create the bundle we'll work with
|
||||
var args = config.args;
|
||||
|
||||
@@ -15,7 +23,9 @@ module.exports = function() {
|
||||
nonull: true, // Keep IDs that don't expand to anything.
|
||||
cwd: config.rootDirectory
|
||||
}, requires).forEach(function(name) {
|
||||
args.push(name.replace(/\.js$/i, ""));
|
||||
name = name.replace(/\.js$/i, "");
|
||||
args.push(name);
|
||||
theFilesToTestScript.write('harness.enableTest(' + JSON.stringify(name) + ');\n');
|
||||
});
|
||||
|
||||
require("populist").buildP({
|
||||
@@ -23,6 +33,7 @@ module.exports = function() {
|
||||
args: args
|
||||
}).then(function(output) {
|
||||
grunt.file.write(config.outfile, output);
|
||||
theFilesToTestScript.end();
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
var grunt = require("grunt");
|
||||
var wd = require('wd');
|
||||
|
||||
module.exports = function(){
|
||||
var config = this.data;
|
||||
var taskSucceeded = this.async();
|
||||
grunt.verbose.write('webdriver remote', JSON.stringify(config.webdriver.remote));
|
||||
var browser = wd.promiseChainRemote(config.webdriver.remote);
|
||||
|
||||
browser.on('status', function(info) {
|
||||
grunt.verbose.writeln(info);
|
||||
});
|
||||
|
||||
browser.on('command', function(meth, path, data) {
|
||||
grunt.verbose.writeln(' > ' + meth, path, data || '');
|
||||
});
|
||||
|
||||
browser
|
||||
.init(config.browser || {})
|
||||
.get(config.url)
|
||||
.then(function(){return browser;})
|
||||
.then(getJSReport)
|
||||
.then(config.onComplete && config.onComplete.bind(browser), config.onError && config.onError.bind(browser))
|
||||
.fail(grunt.verbose.writeln.bind(grunt.verbose))
|
||||
.fin(function(){
|
||||
if (grunt.option('webdriver-keep-open')) return;
|
||||
grunt.verbose.writeln('Closing the browser window. To keep it open, pass the --webdriver-keep-open flag to grunt.');
|
||||
return browser.quit();
|
||||
})
|
||||
.done(
|
||||
taskSucceeded.bind(null,true),
|
||||
taskSucceeded.bind(null,false)
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
function getJSReport(browser){
|
||||
return browser
|
||||
.waitForCondition("typeof window.jasmine != 'undefined'", 500)
|
||||
.waitForCondition("typeof window.jasmine.getJSReport != 'undefined'", 10e3)
|
||||
.waitForCondition("window.testImageURL.running <= 0", 5e3)
|
||||
.eval("jasmine.getJSReport()")
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
var grunt = require('grunt');
|
||||
|
||||
module.exports = function(){
|
||||
var onReadyCallback = this.async();
|
||||
|
||||
var phantomjs = require("phantomjs").path;
|
||||
var child_process = require('child_process');
|
||||
var config = this.data || {};
|
||||
|
||||
var args = ["--webdriver=" + (config.port || 9515)];
|
||||
grunt.verbose.writeln('phantomjs START path:%s args:%s', phantomjs, args);
|
||||
|
||||
var child = child_process.spawn(phantomjs, args);
|
||||
process.on('exit', function() {
|
||||
child.kill();
|
||||
});
|
||||
|
||||
child.on('error', function(error) {
|
||||
grunt.verbose.writeln('phantomjs ERROR');
|
||||
grunt.fatal(error);
|
||||
});
|
||||
child.on('exit', function(code) {
|
||||
grunt.verbose.writeln('phantomjs END');
|
||||
if (code) grunt.fatal('phantomjs FAIL');
|
||||
});
|
||||
|
||||
function verboseWrite(chunk) {
|
||||
if (onReadyCallback && chunk.toString().indexOf('running on port') != -1) {
|
||||
grunt.verbose.writeln('phantomjs STARTED');
|
||||
onReadyCallback();
|
||||
onReadyCallback = null;
|
||||
}
|
||||
grunt.verbose.write(chunk);
|
||||
}
|
||||
child.stdout.on('data', verboseWrite);
|
||||
child.stderr.on('data', verboseWrite);
|
||||
}
|
||||
+6
-2
@@ -48,7 +48,7 @@
|
||||
"grunt-contrib-copy": "~0.4.1",
|
||||
"grunt-contrib-jshint": "~0.6.0",
|
||||
"optimist": "~0.6.0",
|
||||
"phantomjs": "~1.9.1-4",
|
||||
"phantomjs": "~1.9",
|
||||
"recast": "~0.4.16",
|
||||
"semver": "~2.1.0",
|
||||
"uglify-js": "~2.4.0",
|
||||
@@ -56,7 +56,11 @@
|
||||
"grunt-compare-size": "~0.4.0",
|
||||
"gzip-js": "~0.3.2",
|
||||
"tmp": "~0.0.18",
|
||||
"grunt-contrib-compress": "~0.5.1"
|
||||
"grunt-contrib-compress": "~0.5.1",
|
||||
"jasmine-tapreporter": "~0.2.2",
|
||||
"grunt-contrib-connect": "~0.5.0",
|
||||
"es5-shim": "~2.1.0",
|
||||
"wd": "~0.2.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
"use strict";
|
||||
|
||||
describe('ReactWebWorker', function() {
|
||||
it('can run React in a web worker', function() {
|
||||
;(typeof Worker == 'undefined' ? xit : it)('can run React in a web worker', function() {
|
||||
var done = false;
|
||||
var error;
|
||||
|
||||
var worker = new Worker('/worker.js');
|
||||
var worker = new Worker(window.ReactWebWorker_URL || '/src/test/worker.js?_=' + Date.now().toString(36));
|
||||
worker.addEventListener('message', function(e) {
|
||||
var data = JSON.parse(e.data);
|
||||
if (data.type == 'error') {
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ var global = {};
|
||||
importScripts("phantomjs-shims.js");
|
||||
|
||||
try {
|
||||
importScripts("react.js");
|
||||
importScripts("../../build/react.js");
|
||||
} catch (e) {
|
||||
postMessage(JSON.stringify({
|
||||
type: 'error',
|
||||
|
||||
+36
-21
@@ -1,23 +1,38 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="jasmine.css" />
|
||||
<script src="jasmine.js"></script>
|
||||
<script src="react-test.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
ENABLE_TESTS_HERE
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<body>
|
||||
<script>
|
||||
;(function(){
|
||||
|
||||
(function(env) {
|
||||
// Clean up any nodes the previous test might have added.
|
||||
env.afterEach(function() {
|
||||
harness.removeNextSiblings(document.body);
|
||||
harness.removeNextSiblings(document.getElementById("HTMLReporter"));
|
||||
});
|
||||
var urls = [
|
||||
'../vendor/jasmine/jasmine.js',
|
||||
'../vendor/jasmine/jasmine-support.js',
|
||||
'../vendor/jasmine/jasmine-html.js',
|
||||
'../node_modules/jasmine-tapreporter/src/tapreporter.js',
|
||||
'../vendor/jasmine-jsreporter/jasmine-jsreporter.js',
|
||||
|
||||
env.execute();
|
||||
})(jasmine.getEnv());
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
'lib/testImageURL.browser.js',
|
||||
'lib/reportTestResults.browser.js',
|
||||
|
||||
'../build/react.js',
|
||||
'../build/react-test.js',
|
||||
'the-files-to-test.generated.js',
|
||||
'lib/jasmine-execute.js'
|
||||
];
|
||||
|
||||
if (typeof Function.prototype.bind == 'undefined') {
|
||||
urls.unshift('../node_modules/es5-shim/es5-sham.js');
|
||||
urls.unshift('../node_modules/es5-shim/es5-shim.js');
|
||||
}
|
||||
|
||||
var cacheBust = '?_=' + Date.now().toString(36);
|
||||
|
||||
for (var urls_index = -1, urls_length = urls.length; ++urls_index < urls_length;) {
|
||||
document.write('<script src="' + urls[urls_index] + cacheBust + '"><\/script>');
|
||||
}
|
||||
|
||||
var base = location.protocol + '//' + location.hostname + ':' + location.port + location.pathname.replace(/^\/?/,'/').split('/').reverse().slice(1).reverse().join('/');
|
||||
window.ReactWebWorker_URL = base + '/../src/test/worker.js' + cacheBust;
|
||||
|
||||
}());
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
document.write('<style> @import "../vendor/jasmine/jasmine.css?_=' + (+new Date).toString(36) + '"; </style>');
|
||||
|
||||
;(function(env){
|
||||
env.addReporter(new jasmine.HtmlReporter);
|
||||
// Clean up any nodes the previous test might have added.
|
||||
env.afterEach(function() {
|
||||
harness.removeNextSiblings(document.body);
|
||||
harness.removeNextSiblings(document.getElementById("HTMLReporter"));
|
||||
});
|
||||
|
||||
window.onload = function(){
|
||||
env.execute();
|
||||
}
|
||||
})(jasmine.getEnv());
|
||||
@@ -0,0 +1,76 @@
|
||||
console._error = console.error;
|
||||
console._warn = console.warn;
|
||||
console._log = console.log;
|
||||
|
||||
console.log = window.print = function(message){
|
||||
console._log(message);
|
||||
testImageURL('/print?type=log&message=' + encodeURIComponent(message) + '&_=' + Date.now().toString(36));
|
||||
};
|
||||
|
||||
console.error = function(message){
|
||||
console._error(message);
|
||||
testImageURL('/print?type=error&message=' + encodeURIComponent(message) + '&_=' + Date.now().toString(36));
|
||||
};
|
||||
|
||||
console.warn = function(message){
|
||||
console._warn(message);
|
||||
testImageURL('/print?type=warn&message=' + encodeURIComponent(message) + '&_=' + Date.now().toString(36));
|
||||
};
|
||||
|
||||
;(function(env){
|
||||
|
||||
env.addReporter(new jasmine.JSReporter());
|
||||
env.addReporter(new TAPReporter(window.print));
|
||||
|
||||
function report(){
|
||||
if (typeof jasmine.getJSReport != 'function') return setTimeout(report, 100);
|
||||
postDataToURL(JSON.stringify(jasmine.getJSReport()), '/reportTestResults', function(error, event){
|
||||
if (error) return console.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
var oldCallback = env.currentRunner().finishCallback;
|
||||
env.currentRunner().finishCallback = function(){
|
||||
if (oldCallback) oldCallback.apply(this, arguments);
|
||||
report();
|
||||
};
|
||||
|
||||
function postDataToURL(data, url, callback){
|
||||
var id = '$' + (+new Date()).toString(36);
|
||||
|
||||
var postReportingTarget = document.createElement('iframe');
|
||||
postReportingTarget.id = postReportingTarget.name = 'postReportingTarget' + id;
|
||||
|
||||
var postReportingForm = document.createElement('form');
|
||||
postReportingForm.method = 'POST';
|
||||
postReportingForm.action = url;
|
||||
postReportingForm.target = postReportingTarget.name;
|
||||
|
||||
var postReportingData = document.createElement('input');
|
||||
postReportingData.type = 'hidden';
|
||||
postReportingData.name = 'data';
|
||||
postReportingData.value = data || '{"error":"unknown error in postReportingData"}';
|
||||
|
||||
postReportingForm.appendChild(postReportingData);
|
||||
postReportingForm.appendChild(postReportingTarget);
|
||||
postReportingForm.style.cssText = "visibility:hidden; position:absolute; bottom:100%; right:100%";
|
||||
|
||||
function done(error, event){
|
||||
postReportingForm.parentNode.removeChild(postReportingForm);
|
||||
callback(error, event);
|
||||
}
|
||||
|
||||
postReportingTarget.onerror = function(error){
|
||||
done(error);
|
||||
}
|
||||
postReportingTarget.onload = function(event){
|
||||
done(null, event);
|
||||
}
|
||||
document.body.appendChild(postReportingForm);
|
||||
setTimeout(function(){
|
||||
postReportingForm.submit();
|
||||
},0);
|
||||
}
|
||||
|
||||
}(window.jasmine.getEnv()));
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
testImageURL._recycle = function(img){
|
||||
console.log('_recycle', img);
|
||||
try {
|
||||
img.src = '';
|
||||
img.onload = img.onerror = null;
|
||||
} catch(e){}
|
||||
testImageURL._recycleBin.push(img);
|
||||
}
|
||||
testImageURL.getImage = function(callback){
|
||||
// if (!testImageURL._recycleBin) testImageURL._recycleBin = [new Image(),new Image(),new Image(),new Image()];
|
||||
// function get(){
|
||||
// if (testImageURL._recycleBin.length === 0) return setTimeout(get, 100);
|
||||
// callback(testImageURL._recycleBin.shift(), testImageURL._recycle);
|
||||
// }
|
||||
// get();
|
||||
callback(new Image(), function recycle(){});
|
||||
}
|
||||
|
||||
testImageURL.defaultCallback = function(error, event){}
|
||||
|
||||
function testImageURL(url, timeout, callback){
|
||||
if (typeof timeout == 'function'){
|
||||
callback = timeout;
|
||||
timeout = testImageURL.timeout;
|
||||
}
|
||||
if (typeof callback != 'function') callback = testImageURL.defaultCallback;
|
||||
|
||||
testImageURL.getImage(function(img, done){
|
||||
function callbackWrapper(error, event){
|
||||
callbackWrapper = testImageURL.noop;
|
||||
testImageURL.running = (testImageURL.running || 0) - 1;
|
||||
clearTimeout(timer);
|
||||
done(img);
|
||||
img = url = timeout = null;
|
||||
callback(error, event);
|
||||
error = event = callback = null;
|
||||
}
|
||||
|
||||
var timer = setTimeout(function(){callbackWrapper(Error('timeout'));}, timeout);
|
||||
|
||||
try {
|
||||
img.onload = function(event){ callbackWrapper(null, event || window.event); };
|
||||
img.onerror = function(error){ callbackWrapper(error); };
|
||||
img.src = url;
|
||||
testImageURL.running = (testImageURL.running || 0) + 1;
|
||||
|
||||
if (img.complete === true
|
||||
|| img.readyState == 4
|
||||
|| img.width > 0
|
||||
|| img.height > 0
|
||||
|| img.readyState == 'complete'
|
||||
) callbackWrapper(null, null);
|
||||
}
|
||||
catch(error){
|
||||
callbackWrapper(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
testImageURL.noop = function(){};
|
||||
|
||||
testImageURL.timeout = 5000;
|
||||
@@ -1,137 +0,0 @@
|
||||
var slice = Array.prototype.slice;
|
||||
var argv = slice.call(require("system").args);
|
||||
|
||||
// Hard to believe PhantomJS has no equivalent of Node's "path" module.
|
||||
var fs = require("fs");
|
||||
var splat = [fs.workingDirectory, argv[0]]
|
||||
.join(fs.separator)
|
||||
.split(fs.separator);
|
||||
|
||||
var harness = splat.pop();
|
||||
if (harness !== "phantom-harness.js") {
|
||||
console.error("wrong harness: " + harness);
|
||||
phantom.exit(-1);
|
||||
}
|
||||
|
||||
var cwd = splat.join(fs.separator);
|
||||
fs.changeWorkingDirectory(cwd);
|
||||
|
||||
// Hard to believe PhantomJS has no option parsing module.
|
||||
var port = 8080;
|
||||
var debug = false;
|
||||
var tests = [];
|
||||
var rest = [];
|
||||
while (argv.length > 0) {
|
||||
var arg = argv.pop();
|
||||
if (arg === "--port") {
|
||||
port = +rest.pop();
|
||||
} else if (arg === "--debug") {
|
||||
debug = true;
|
||||
} else if (arg === "--tests") {
|
||||
while (rest.length > 0)
|
||||
tests.push(rest.pop());
|
||||
}
|
||||
rest.push(arg);
|
||||
}
|
||||
|
||||
// Dynamically enable the individual tests.
|
||||
var indexHtml = fs.read("index.html").replace(
|
||||
/^(\s*)ENABLE_TESTS_HERE/m,
|
||||
function(placeholder, leadingSpace) {
|
||||
return leadingSpace + tests.map(function(testID) {
|
||||
return "harness.enableTest(" + JSON.stringify(testID) + ");";
|
||||
}).join("\n" + leadingSpace);
|
||||
}
|
||||
);
|
||||
|
||||
var server = require("webserver").create();
|
||||
server.listen(port, function(req, res) {
|
||||
var file = req.url.replace(/^\/+/, "");
|
||||
var content;
|
||||
|
||||
switch (file) {
|
||||
case "jasmine.js":
|
||||
case "react.js":
|
||||
case "react-test.js":
|
||||
file = "../build/" + file;
|
||||
break;
|
||||
|
||||
case "phantomjs-shims.js":
|
||||
case "worker.js":
|
||||
file = "../src/test/" + file;
|
||||
break;
|
||||
|
||||
case "jasmine.css":
|
||||
file = "../vendor/jasmine/" + file;
|
||||
break;
|
||||
|
||||
case "":
|
||||
default:
|
||||
file = "index.html";
|
||||
content = indexHtml; // Prevents calling fs.read again.
|
||||
break;
|
||||
}
|
||||
|
||||
if (/\.css$/i.test(file)) {
|
||||
res.setHeader("Content-Type", "text/css");
|
||||
} else if (/\.js/i.test(file)) {
|
||||
res.setHeader("Content-Type", "text/javascript");
|
||||
} else {
|
||||
res.setHeader("Content-Type", "text/html");
|
||||
}
|
||||
|
||||
res.statusCode = 200;
|
||||
res.write(content || fs.read(file));
|
||||
res.close();
|
||||
});
|
||||
|
||||
var url = "http://localhost:" + port;
|
||||
var green = "\033[32m";
|
||||
var cyan = "\033[36m";
|
||||
var reset = "\033[0m";
|
||||
|
||||
if (debug) {
|
||||
console.log(green);
|
||||
console.log("PhantomJS received the " + cyan + "--debug" + green + " option.");
|
||||
console.log("Load " + cyan + url + green + " in your browser to execute " +
|
||||
"the test suite.");
|
||||
console.log("Type " + cyan + "control-C" + green + " to terminate the " +
|
||||
"PhantomJS process.");
|
||||
console.log(reset);
|
||||
|
||||
// Leave PhantomJS running until killed with control-C...
|
||||
|
||||
} else {
|
||||
var page = require("webpage").create();
|
||||
var timeoutSecs = 60;
|
||||
|
||||
page.onCallback = function(data) {
|
||||
switch (data.type) {
|
||||
case "console":
|
||||
console[data.method].apply(console, data.args);
|
||||
break;
|
||||
|
||||
case "exit":
|
||||
// PhantomJS crashes sometimes unless we call phantom.exit in its own
|
||||
// event loop tick.
|
||||
setTimeout(function() {
|
||||
phantom.exit(data.code);
|
||||
}, 10);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
page.open(url, function(status) {
|
||||
if (status !== "success") {
|
||||
console.error("failed to open " + url);
|
||||
phantom.exit(-1);
|
||||
}
|
||||
|
||||
setTimeout(function() {
|
||||
console.error(
|
||||
"PhantomJS tests timed out after " +
|
||||
timeoutSecs + " seconds.");
|
||||
phantom.exit(-1);
|
||||
}, timeoutSecs * 1e3);
|
||||
});
|
||||
}
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
This file is part of the Jasmine JSReporter project from Ivan De Marino.
|
||||
|
||||
Copyright (C) 2011 Ivan De Marino (aka detro, aka detronizator), http://blog.ivandemarino.me, ivan.de.marino@gmail.com
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL IVAN DE MARINO BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
(function () {
|
||||
// Ensure that Jasmine library is loaded first
|
||||
if (typeof jasmine === "undefined") {
|
||||
throw new Error("[Jasmine JSReporter] 'Jasmine' library not found");
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate elapsed time, in Seconds.
|
||||
* @param startMs Start time in Milliseconds
|
||||
* @param finishMs Finish time in Milliseconds
|
||||
* @return Elapsed time in Seconds */
|
||||
function elapsedSec (startMs, finishMs) {
|
||||
return (finishMs - startMs) / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Round an amount to the given number of Digits.
|
||||
* If no number of digits is given, than '2' is assumed.
|
||||
* @param amount Amount to round
|
||||
* @param numOfDecDigits Number of Digits to round to. Default value is '2'.
|
||||
* @return Rounded amount */
|
||||
function round (amount, numOfDecDigits) {
|
||||
numOfDecDigits = numOfDecDigits || 2;
|
||||
return Math.round(amount * Math.pow(10, numOfDecDigits)) / Math.pow(10, numOfDecDigits);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect information about a Suite, recursively, and return a JSON result.
|
||||
* @param suite The Jasmine Suite to get data from
|
||||
*/
|
||||
function getSuiteData (suite) {
|
||||
var suiteData = {
|
||||
description : suite.description,
|
||||
durationSec : 0,
|
||||
specs: [],
|
||||
suites: [],
|
||||
passed: true
|
||||
},
|
||||
specs = suite.specs(),
|
||||
suites = suite.suites(),
|
||||
i, ilen;
|
||||
|
||||
// Loop over all the Suite's Specs
|
||||
for (i = 0, ilen = specs.length; i < ilen; ++i) {
|
||||
suiteData.specs[i] = {
|
||||
description : specs[i].description,
|
||||
durationSec : specs[i].durationSec,
|
||||
passed : specs[i].results().passedCount === specs[i].results().totalCount,
|
||||
skipped : specs[i].results().skipped,
|
||||
passedCount : specs[i].results().passedCount,
|
||||
failedCount : specs[i].results().failedCount,
|
||||
totalCount : specs[i].results().totalCount
|
||||
};
|
||||
suiteData.passed = !suiteData.specs[i].passed ? false : suiteData.passed;
|
||||
suiteData.durationSec += suiteData.specs[i].durationSec;
|
||||
}
|
||||
|
||||
// Loop over all the Suite's sub-Suites
|
||||
for (i = 0, ilen = suites.length; i < ilen; ++i) {
|
||||
suiteData.suites[i] = getSuiteData(suites[i]); //< recursive population
|
||||
suiteData.passed = !suiteData.suites[i].passed ? false : suiteData.passed;
|
||||
suiteData.durationSec += suiteData.suites[i].durationSec;
|
||||
}
|
||||
|
||||
// Rounding duration numbers to 3 decimal digits
|
||||
suiteData.durationSec = round(suiteData.durationSec, 4);
|
||||
|
||||
return suiteData;
|
||||
}
|
||||
|
||||
var JSReporter = function () {
|
||||
};
|
||||
|
||||
JSReporter.prototype = {
|
||||
reportRunnerStarting: function (runner) {
|
||||
// Nothing to do
|
||||
},
|
||||
|
||||
reportSpecStarting: function (spec) {
|
||||
// Start timing this spec
|
||||
spec.startedAt = new Date();
|
||||
},
|
||||
|
||||
reportSpecResults: function (spec) {
|
||||
// Finish timing this spec and calculate duration/delta (in sec)
|
||||
spec.finishedAt = new Date();
|
||||
spec.durationSec = elapsedSec(spec.startedAt.getTime(), spec.finishedAt.getTime());
|
||||
},
|
||||
|
||||
reportSuiteResults: function (suite) {
|
||||
// Nothing to do
|
||||
},
|
||||
|
||||
reportRunnerResults: function (runner) {
|
||||
var suites = runner.suites(),
|
||||
i, ilen;
|
||||
|
||||
// Attach results to the "jasmine" object to make those results easy to scrap/find
|
||||
jasmine.runnerResults = {
|
||||
suites: [],
|
||||
durationSec : 0,
|
||||
passed : true
|
||||
};
|
||||
|
||||
// Loop over all the Suites
|
||||
for (i = 0, ilen = suites.length; i < ilen; ++i) {
|
||||
if (suites[i].parentSuite === null) {
|
||||
jasmine.runnerResults.suites[i] = getSuiteData(suites[i]);
|
||||
// If 1 suite fails, the whole runner fails
|
||||
jasmine.runnerResults.passed = !jasmine.runnerResults.suites[i].passed ? false : jasmine.runnerResults.passed;
|
||||
// Add up all the durations
|
||||
jasmine.runnerResults.durationSec += jasmine.runnerResults.suites[i].durationSec;
|
||||
}
|
||||
}
|
||||
|
||||
// Decorate the 'jasmine' object with getters
|
||||
jasmine.getJSReport = function () {
|
||||
if (jasmine.runnerResults) {
|
||||
return jasmine.runnerResults;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
jasmine.getJSReportAsString = function () {
|
||||
return JSON.stringify(jasmine.getJSReport());
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// export public
|
||||
jasmine.JSReporter = JSReporter;
|
||||
})();
|
||||
|
||||
Vendored
-2
@@ -1,5 +1,3 @@
|
||||
var jasmine = require("./jasmine");
|
||||
|
||||
jasmine.HtmlReporterHelpers = {};
|
||||
|
||||
jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) {
|
||||
|
||||
Vendored
+3
-3
@@ -1,4 +1,4 @@
|
||||
var jasmine = require("./jasmine");
|
||||
if (typeof jasmine == 'undefined') jasmine = require("./jasmine");
|
||||
var spec = false; // TODO
|
||||
|
||||
// Add some matcher for mock functions
|
||||
@@ -120,8 +120,8 @@ if (typeof WeakMap !== "undefined") {
|
||||
mismatchValues.push("arrays were not the same length");
|
||||
}
|
||||
|
||||
_comparedObjects.delete(a);
|
||||
_comparedObjects.delete(b);
|
||||
_comparedObjects["delete"](a);
|
||||
_comparedObjects["delete"](b);
|
||||
return (mismatchKeys.length == 0 && mismatchValues.length == 0);
|
||||
};
|
||||
}
|
||||
|
||||
Vendored
+21
-18
@@ -1,10 +1,12 @@
|
||||
var isCommonJS = typeof window == "undefined" && typeof exports == "object";
|
||||
|
||||
/**
|
||||
* Top level namespace for Jasmine, a lightweight JavaScript BDD/spec/testing framework.
|
||||
*
|
||||
* @namespace
|
||||
*/
|
||||
var jasmine = {};
|
||||
exports = module.exports = jasmine;
|
||||
if (isCommonJS) exports.jasmine = jasmine;
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
@@ -478,7 +480,7 @@ jasmine.log = function() {
|
||||
var spyOn = function(obj, methodName) {
|
||||
return jasmine.getEnv().currentSpec.spyOn(obj, methodName);
|
||||
};
|
||||
exports.spyOn = spyOn;
|
||||
if (isCommonJS) exports.spyOn = spyOn;
|
||||
|
||||
/**
|
||||
* Creates a Jasmine spec that will be added to the current suite.
|
||||
@@ -496,7 +498,7 @@ exports.spyOn = spyOn;
|
||||
var it = function(desc, func) {
|
||||
return jasmine.getEnv().it(desc, func);
|
||||
};
|
||||
exports.it = it;
|
||||
if (isCommonJS) exports.it = it;
|
||||
|
||||
/**
|
||||
* Creates a <em>disabled</em> Jasmine spec.
|
||||
@@ -509,7 +511,7 @@ exports.it = it;
|
||||
var xit = function(desc, func) {
|
||||
return jasmine.getEnv().xit(desc, func);
|
||||
};
|
||||
exports.xit = xit;
|
||||
if (isCommonJS) exports.xit = xit;
|
||||
|
||||
/**
|
||||
* Starts a chain for a Jasmine expectation.
|
||||
@@ -523,7 +525,7 @@ exports.xit = xit;
|
||||
var expect = function(actual) {
|
||||
return jasmine.getEnv().currentSpec.expect(actual);
|
||||
};
|
||||
exports.expect = expect;
|
||||
if (isCommonJS) exports.expect = expect;
|
||||
|
||||
/**
|
||||
* Defines part of a jasmine spec. Used in cominbination with waits or waitsFor in asynchrnous specs.
|
||||
@@ -533,7 +535,7 @@ exports.expect = expect;
|
||||
var runs = function(func) {
|
||||
jasmine.getEnv().currentSpec.runs(func);
|
||||
};
|
||||
exports.runs = runs;
|
||||
if (isCommonJS) exports.runs = runs;
|
||||
|
||||
/**
|
||||
* Waits a fixed time period before moving to the next block.
|
||||
@@ -544,7 +546,7 @@ exports.runs = runs;
|
||||
var waits = function(timeout) {
|
||||
jasmine.getEnv().currentSpec.waits(timeout);
|
||||
};
|
||||
exports.waits = waits;
|
||||
if (isCommonJS) exports.waits = waits;
|
||||
|
||||
/**
|
||||
* Waits for the latchFunction to return true before proceeding to the next block.
|
||||
@@ -556,7 +558,7 @@ exports.waits = waits;
|
||||
var waitsFor = function(latchFunction, optional_timeoutMessage, optional_timeout) {
|
||||
jasmine.getEnv().currentSpec.waitsFor.apply(jasmine.getEnv().currentSpec, arguments);
|
||||
};
|
||||
exports.waitsFor = waitsFor;
|
||||
if (isCommonJS) exports.waitsFor = waitsFor;
|
||||
|
||||
/**
|
||||
* A function that is called before each spec in a suite.
|
||||
@@ -568,7 +570,7 @@ exports.waitsFor = waitsFor;
|
||||
var beforeEach = function(beforeEachFunction) {
|
||||
jasmine.getEnv().beforeEach(beforeEachFunction);
|
||||
};
|
||||
exports.beforeEach = beforeEach;
|
||||
if (isCommonJS) exports.beforeEach = beforeEach;
|
||||
|
||||
/**
|
||||
* A function that is called after each spec in a suite.
|
||||
@@ -580,7 +582,7 @@ exports.beforeEach = beforeEach;
|
||||
var afterEach = function(afterEachFunction) {
|
||||
jasmine.getEnv().afterEach(afterEachFunction);
|
||||
};
|
||||
exports.afterEach = afterEach;
|
||||
if (isCommonJS) exports.afterEach = afterEach;
|
||||
|
||||
/**
|
||||
* Defines a suite of specifications.
|
||||
@@ -600,7 +602,7 @@ exports.afterEach = afterEach;
|
||||
var describe = function(description, specDefinitions) {
|
||||
return jasmine.getEnv().describe(description, specDefinitions);
|
||||
};
|
||||
exports.describe = describe;
|
||||
if (isCommonJS) exports.describe = describe;
|
||||
|
||||
/**
|
||||
* Disables a suite of specifications. Used to disable some suites in a file, or files, temporarily during development.
|
||||
@@ -611,7 +613,7 @@ exports.describe = describe;
|
||||
var xdescribe = function(description, specDefinitions) {
|
||||
return jasmine.getEnv().xdescribe(description, specDefinitions);
|
||||
};
|
||||
exports.xdescribe = xdescribe;
|
||||
if (isCommonJS) exports.xdescribe = xdescribe;
|
||||
|
||||
|
||||
// Provide the XMLHttpRequest class for IE 5.x-6.x:
|
||||
@@ -871,10 +873,11 @@ jasmine.Env.prototype.it = function(description, func) {
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.xit = function(desc, func) {
|
||||
var spec = this.it(desc, func);
|
||||
spec.results_.skipped = true;
|
||||
spec.runs = function() {};
|
||||
return spec;
|
||||
return {
|
||||
id: this.nextSpecId(),
|
||||
runs: function() {
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
jasmine.Env.prototype.compareRegExps_ = function(a, b, mismatchKeys, mismatchValues) {
|
||||
@@ -2592,6 +2595,6 @@ jasmine.WaitsForBlock.prototype.execute = function(onComplete) {
|
||||
jasmine.version_= {
|
||||
"major": 1,
|
||||
"minor": 3,
|
||||
"build": 1,
|
||||
"revision": 1354556913
|
||||
"build": 0,
|
||||
"revision": 1354052693
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user