mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 12:20:20 +01:00
Remove in-browser unit testing
Rely on jest for now until we get a better and less hacky solution to running tests in the browser, probably a totally different test suite with different behavior/goals.
This commit is contained in:
parent
44ed6010d3
commit
5da408297f
|
|
@ -2,11 +2,6 @@
|
|||
src/shared/vendor
|
||||
# This should be enabled but that folder has too much in it that doesn't belong
|
||||
src/test
|
||||
test/the-files-to-test.generated.js
|
||||
# This is synced with a different file internally, don't want to lint it yet
|
||||
vendor/fbtransform/syntax.js
|
||||
vendor/jasmine/
|
||||
vendor/jasmine-jsreporter/
|
||||
# But not in docs/_js/examples/*
|
||||
docs/_js/*.js
|
||||
docs/js/
|
||||
|
|
|
|||
11
.travis.yml
11
.travis.yml
|
|
@ -66,12 +66,10 @@ script:
|
|||
fi
|
||||
env:
|
||||
matrix:
|
||||
- TEST_TYPE=test
|
||||
- TEST_TYPE=build
|
||||
- TEST_TYPE=jest
|
||||
- TEST_TYPE=lint
|
||||
- TEST_TYPE=build_website
|
||||
- TEST_TYPE=test:webdriver:saucelabs:modern
|
||||
global:
|
||||
# SERVER
|
||||
- secure: qPvsJ46XzGrdIuPA70b55xQNGF8jcK7N1LN5CCQYYocXLa+fBrl+fTE77QvehOPhqwJXcj6kOxI+sY0KrVwV7gmq2XY2HZGWUSCxTN0SZlNIzqPA80Y7G/yOjA4PUt8LKgP+8tptyhTAY56qf+hgW8BoLiKOdztYF2p+3zXOLuA=
|
||||
|
|
@ -81,15 +79,6 @@ env:
|
|||
- secure: EHCyCSKMwKlLHNtcj9nmkRzmiiPE3aDGlPcnEyrDJeRI0SeN/iCXHXfFivR0vFq3vr+9naMBczAR2AEidtps5KbJrKqdZnjPFRbmfVtzWr/LlvVCub3u13Pub6TdKIVBTny1PuZ5X8GvdxMNVig89jGjvzhhWuQRaz3VhJnTra4=
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- env: TEST_TYPE=test:coverage
|
||||
- env: TEST_TYPE=test:webdriver:saucelabs:modern
|
||||
- env: TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=ie11
|
||||
- env: TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=ie10
|
||||
- env: TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=ie9
|
||||
- env: TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=ie8
|
||||
- env: TEST_TYPE=test:webdriver:saucelabs:ios
|
||||
- env: TEST_TYPE=test:webdriver:saucelabs BROWSER_NAME=safari
|
||||
notifications:
|
||||
irc:
|
||||
use_notice: true
|
||||
|
|
|
|||
106
Gruntfile.js
106
Gruntfile.js
|
|
@ -6,9 +6,6 @@ module.exports = function(grunt) {
|
|||
pkg: grunt.file.readJSON('package.json'),
|
||||
jsx: require('./grunt/config/jsx'),
|
||||
browserify: require('./grunt/config/browserify'),
|
||||
populist: require('./grunt/config/populist')(grunt),
|
||||
connect: require('./grunt/config/server')(grunt),
|
||||
'webdriver-jasmine': require('./grunt/config/webdriver-jasmine'),
|
||||
npm: require('./grunt/config/npm'),
|
||||
clean: [
|
||||
'./build',
|
||||
|
|
@ -39,11 +36,6 @@ module.exports = function(grunt) {
|
|||
|
||||
grunt.registerTask('lint', ['eslint']);
|
||||
|
||||
grunt.registerTask(
|
||||
'download-previous-version',
|
||||
require('./grunt/tasks/download-previous-version.js')
|
||||
);
|
||||
|
||||
grunt.registerTask('delete-build-modules', function() {
|
||||
if (grunt.file.exists('build/modules')) {
|
||||
grunt.file.delete('build/modules');
|
||||
|
|
@ -56,12 +48,6 @@ module.exports = function(grunt) {
|
|||
// Our own browserify-based tasks to build a single JS file build.
|
||||
grunt.registerMultiTask('browserify', require('./grunt/tasks/browserify'));
|
||||
|
||||
grunt.registerMultiTask('populist', require('./grunt/tasks/populist'));
|
||||
|
||||
grunt.registerTask('sauce-tunnel', require('./grunt/tasks/sauce-tunnel'));
|
||||
|
||||
grunt.registerMultiTask('webdriver-jasmine', require('./grunt/tasks/webdriver-jasmine'));
|
||||
|
||||
grunt.registerMultiTask('npm', require('./grunt/tasks/npm'));
|
||||
|
||||
var npmReactTasks = require('./grunt/tasks/npm-react');
|
||||
|
|
@ -107,17 +93,6 @@ module.exports = function(grunt) {
|
|||
'jsx:normal',
|
||||
'browserify:addonsMin',
|
||||
]);
|
||||
grunt.registerTask('build:withCodeCoverageLogging', [
|
||||
'jsx:normal',
|
||||
'version-check',
|
||||
'browserify:withCodeCoverageLogging',
|
||||
]);
|
||||
grunt.registerTask('build:test', [
|
||||
'delete-build-modules',
|
||||
'jsx:test',
|
||||
'version-check',
|
||||
'populist:test',
|
||||
]);
|
||||
grunt.registerTask('build:npm-react', [
|
||||
'version-check',
|
||||
'jsx:normal',
|
||||
|
|
@ -128,89 +103,10 @@ module.exports = function(grunt) {
|
|||
'gem-react-source:release',
|
||||
]);
|
||||
|
||||
grunt.registerTask('webdriver-phantomjs', require('./grunt/tasks/webdriver-phantomjs'));
|
||||
|
||||
grunt.registerTask('coverage:parse', require('./grunt/tasks/coverage-parse'));
|
||||
|
||||
grunt.registerTask('test:webdriver:phantomjs', [
|
||||
'connect',
|
||||
'webdriver-phantomjs',
|
||||
'webdriver-jasmine:local',
|
||||
]);
|
||||
|
||||
grunt.registerTask('test:full', [
|
||||
'build:test',
|
||||
'build:basic',
|
||||
|
||||
'connect',
|
||||
'webdriver-phantomjs',
|
||||
'webdriver-jasmine:local',
|
||||
|
||||
'sauce-tunnel',
|
||||
'webdriver-jasmine:saucelabs_android',
|
||||
'webdriver-jasmine:saucelabs_firefox',
|
||||
'webdriver-jasmine:saucelabs_chrome',
|
||||
]);
|
||||
|
||||
grunt.registerTask('test:webdriver:saucelabs', [
|
||||
'build:test',
|
||||
'build:basic',
|
||||
|
||||
'connect',
|
||||
'sauce-tunnel',
|
||||
'webdriver-jasmine:saucelabs_' + (process.env.BROWSER_NAME || 'ie8'),
|
||||
]);
|
||||
|
||||
grunt.registerTask('test:webdriver:saucelabs:modern', [
|
||||
'build:test',
|
||||
'build:basic',
|
||||
|
||||
'connect',
|
||||
'sauce-tunnel',
|
||||
'webdriver-jasmine:saucelabs_android',
|
||||
'webdriver-jasmine:saucelabs_firefox',
|
||||
'webdriver-jasmine:saucelabs_chrome',
|
||||
'webdriver-jasmine:saucelabs_ie11',
|
||||
]);
|
||||
|
||||
grunt.registerTask('test:webdriver:saucelabs:ie', [
|
||||
'build:test',
|
||||
'build:basic',
|
||||
|
||||
'connect',
|
||||
'sauce-tunnel',
|
||||
'webdriver-jasmine:saucelabs_ie8',
|
||||
'webdriver-jasmine:saucelabs_ie9',
|
||||
'webdriver-jasmine:saucelabs_ie10',
|
||||
'webdriver-jasmine:saucelabs_ie11',
|
||||
]);
|
||||
|
||||
grunt.registerTask('test:webdriver:saucelabs:ios', [
|
||||
'build:test',
|
||||
'build:basic',
|
||||
|
||||
'connect',
|
||||
'sauce-tunnel',
|
||||
'webdriver-jasmine:saucelabs_ios6_1',
|
||||
'webdriver-jasmine:saucelabs_ios5_1',
|
||||
'webdriver-jasmine:saucelabs_ios4',
|
||||
]);
|
||||
|
||||
grunt.registerTask('test:coverage', [
|
||||
'build:withCodeCoverageLogging',
|
||||
'test:webdriver:phantomjs',
|
||||
'coverage:parse',
|
||||
]);
|
||||
grunt.registerTask('fasttest', function() {
|
||||
grunt.task.run('test');
|
||||
});
|
||||
grunt.registerTask('test', function() {
|
||||
if (grunt.option('debug')) {
|
||||
grunt.task.run('build:test', 'connect:server:keepalive');
|
||||
} else {
|
||||
grunt.task.run('build:test', 'test:webdriver:phantomjs');
|
||||
}
|
||||
});
|
||||
grunt.registerTask('test', ['jest']);
|
||||
grunt.registerTask('npm:test', ['build', 'npm:pack']);
|
||||
|
||||
// Optimized build task that does all of our builds. The subtasks will be run
|
||||
|
|
|
|||
|
|
@ -43,22 +43,5 @@ require("commoner").version(
|
|||
}).code;
|
||||
}
|
||||
|
||||
if (context.config.mocking) {
|
||||
// Make sure there is exactly one newline at the end of the module.
|
||||
source = source.replace(/\s+$/m, "\n");
|
||||
|
||||
return context.getProvidedP().then(function(idToPath) {
|
||||
if (id !== "mock-modules" &&
|
||||
id !== "mocks" &&
|
||||
id !== "test/all" &&
|
||||
idToPath.hasOwnProperty("mock-modules")) {
|
||||
return source + '\nrequire("mock-modules").register(' +
|
||||
JSON.stringify(id) + ', module);\n';
|
||||
}
|
||||
|
||||
return source;
|
||||
});
|
||||
}
|
||||
|
||||
return source;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -121,25 +121,10 @@ var addonsMin = {
|
|||
after: [/*derequire,*/ minify, bannerify],
|
||||
};
|
||||
|
||||
var withCodeCoverageLogging = {
|
||||
entries: [
|
||||
'./build/modules/React.js',
|
||||
],
|
||||
outfile: './build/react.js',
|
||||
debug: true,
|
||||
standalone: 'React',
|
||||
transforms: [
|
||||
envify({NODE_ENV: process.env.NODE_ENV || 'development'}),
|
||||
require('coverify'),
|
||||
],
|
||||
plugins: [collapser],
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
basic: basic,
|
||||
min: min,
|
||||
transformer: transformer,
|
||||
addons: addons,
|
||||
addonsMin: addonsMin,
|
||||
withCodeCoverageLogging: withCodeCoverageLogging,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
var assign = require('../../src/shared/stubs/Object.assign');
|
||||
var grunt = require('grunt');
|
||||
|
||||
var rootIDs = [
|
||||
|
|
@ -21,23 +20,6 @@ var normal = {
|
|||
outputDir: 'build/modules',
|
||||
};
|
||||
|
||||
|
||||
var test = {
|
||||
rootIDs: rootIDs.concat([
|
||||
'test/all.js',
|
||||
'**/__tests__/*.js',
|
||||
]),
|
||||
getConfig: function() {
|
||||
return assign({}, normal.getConfig(), {
|
||||
mocking: true,
|
||||
});
|
||||
},
|
||||
sourceDir: 'src',
|
||||
outputDir: 'build/modules',
|
||||
};
|
||||
|
||||
|
||||
module.exports = {
|
||||
normal: normal,
|
||||
test: test,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = function(grunt) {
|
||||
var jasmine = {
|
||||
rootDirectory: 'build/jasmine',
|
||||
// This syntax means to require and expose the 'jasmine' module
|
||||
// (build/jasmine/jasmine.js) as global.jasmine, and to require the
|
||||
// 'all' module (build/jasmine/all.js) but not expose it globally.
|
||||
args: ['jasmine:jasmine', 'all:'],
|
||||
outfile: './build/jasmine.js',
|
||||
};
|
||||
|
||||
var filterExpr = grunt.option('filter');
|
||||
|
||||
if (filterExpr) {
|
||||
filterExpr = '**/__tests__/' + filterExpr + '-test.js';
|
||||
} else {
|
||||
filterExpr = '**/__tests__/*-test.js';
|
||||
}
|
||||
|
||||
var test = {
|
||||
rootDirectory: 'build/modules',
|
||||
args: ['test/all:harness'],
|
||||
requires: [filterExpr],
|
||||
outfile: './build/react-test.js',
|
||||
};
|
||||
|
||||
return {
|
||||
jasmine: jasmine,
|
||||
test: test,
|
||||
};
|
||||
};
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
module.exports = function(grunt) {
|
||||
var coverageWriteStream;
|
||||
|
||||
grunt.task.registerTask('finalize-coverage-stream', function() {
|
||||
if (!coverageWriteStream) {
|
||||
return;
|
||||
}
|
||||
var done = this.async();
|
||||
coverageWriteStream.once('close', done);
|
||||
coverageWriteStream.end();
|
||||
coverageWriteStream = null;
|
||||
});
|
||||
|
||||
function consoleLoggerMiddleware(req, res, next) {
|
||||
if (!(req.method === 'POST' && req._parsedUrl.pathname.replace(/\//g, '') === 'console' && Array.isArray(req.body))) {
|
||||
return next();
|
||||
}
|
||||
res.write('<!doctype html><meta charset=utf-8>');
|
||||
res.end('Got it, thanks!');
|
||||
|
||||
req.body.forEach(function(log) {
|
||||
if (log.message.indexOf('not ok ') === 0) {
|
||||
log.type = 'error';
|
||||
} else if (log.message.indexOf('ok ') === 0) {
|
||||
log.type = 'ok';
|
||||
} else if (log.message.indexOf('COVER') === 0) {
|
||||
log.type = 'coverage';
|
||||
} else if (log.message.indexOf('DONE\t') === 0) {
|
||||
log.type = 'coverage done';
|
||||
}
|
||||
|
||||
if (log.type === 'error') {
|
||||
grunt.log.error(log.message);
|
||||
} else if (log.type === 'ok') {
|
||||
grunt.log.ok(log.message);
|
||||
} else if (log.type === 'log') {
|
||||
grunt.log.writeln(log.message);
|
||||
} else if (log.type === 'coverage') {
|
||||
if (!coverageWriteStream) {
|
||||
coverageWriteStream = fs.createWriteStream(path.join(__dirname, '/../../coverage.log'));
|
||||
}
|
||||
coverageWriteStream.write(log.message + '\n');
|
||||
} else if (log.type === 'coverage done') {
|
||||
grunt.task.run('finalize-coverage-stream');
|
||||
} else if (log.type === 'perf') {
|
||||
grunt.event.emit('perf results', log.message);
|
||||
} else {
|
||||
grunt.verbose.writeln(log);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function testResultLoggerMiddleware(req, res, next) {
|
||||
if (!(req.method === 'POST' && req._parsedUrl.pathname.indexOf('/reportTestResults') === 0)) {
|
||||
return next();
|
||||
}
|
||||
res.write('<!doctype html><meta charset=utf-8>');
|
||||
res.end('Got it, thanks!');
|
||||
|
||||
var logType = 'writeln';
|
||||
var message = req.body;
|
||||
|
||||
if (req.body.type && req.body.message) {
|
||||
if (req.body.type === 'error') {
|
||||
logType = 'error';
|
||||
} else if (req.body.message.indexOf('ok') === 0) {
|
||||
logType = 'ok';
|
||||
} else if (req.body.message.indexOf('not ok') === 0) {
|
||||
logType = 'error';
|
||||
}
|
||||
message = req.body.message;
|
||||
}
|
||||
if (typeof message !== 'string') {
|
||||
message = JSON.stringify(message, null, 2);
|
||||
}
|
||||
grunt.log[logType]('[%s][%s]', req.headers['user-agent'], Date.now(), message);
|
||||
}
|
||||
|
||||
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.json(),
|
||||
consoleLoggerMiddleware,
|
||||
testResultLoggerMiddleware,
|
||||
|
||||
connect.logger({format:'[:user-agent][:timestamp] :method :url', stream:grunt.verbose}),
|
||||
connect.static(options.base),
|
||||
connect.directory(options.base),
|
||||
];
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var grunt = require('grunt');
|
||||
|
||||
module.exports = function(props) {
|
||||
if (typeof props.url !== 'string') {
|
||||
throw TypeError('expected url string');
|
||||
}
|
||||
if ('isDoneTimeout' in props && typeof props.isDoneTimeout !== 'number') {
|
||||
throw TypeError('expected isDoneTimeout to be a number');
|
||||
}
|
||||
if ('onStart' in props && typeof props.onStart !== 'function') {
|
||||
throw TypeError('expected onStart to be a function');
|
||||
}
|
||||
if ('onComplete' in props && typeof props.onComplete !== 'function') {
|
||||
throw TypeError('expected onComplete to be a function');
|
||||
}
|
||||
if ('onError' in props && typeof props.onError !== 'function') {
|
||||
throw TypeError('expected onError to be a function');
|
||||
}
|
||||
|
||||
var exports = {};
|
||||
|
||||
exports.local = {
|
||||
webdriver: {
|
||||
remote: {protocol: 'http:', hostname: '127.0.0.1', port: 9515, path: '/'},
|
||||
},
|
||||
url: props.url,
|
||||
onStart: props.onStart,
|
||||
onComplete: props.onComplete,
|
||||
onError: props.onError,
|
||||
isDoneTimeout: props.isDoneTimeout,
|
||||
};
|
||||
|
||||
if (grunt.option('debug')) {
|
||||
exports.local.url += (exports.local.url.indexOf('?') === -1 ? '?' : '&') + 'debug=' + grunt.option('debug');
|
||||
}
|
||||
|
||||
exports.saucelabs = {
|
||||
webdriver: {
|
||||
remote: {
|
||||
/* https://github.com/admc/wd/blob/master/README.md#named-parameters */
|
||||
user: process.env.SAUCE_USERNAME || 'React',
|
||||
pwd: process.env.SAUCE_ACCESS_KEY || '339d32ca-d594-4570-a3c2-94c50a91919b',
|
||||
protocol: 'http:',
|
||||
hostname: 'ondemand.saucelabs.com',
|
||||
port: '80',
|
||||
path: '/wd/hub',
|
||||
},
|
||||
},
|
||||
desiredCapabilities: {
|
||||
'build': process.env.TRAVIS_BUILD_NUMBER || 'dev' + Date.now(),
|
||||
'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER || 'my awesome tunnel',
|
||||
'browserName': 'chrome',
|
||||
},
|
||||
url: exports.local.url,
|
||||
onStart: function(browser) {
|
||||
grunt.log.writeln('Starting WebDriver Test. Watch results here: http://saucelabs.com/tests/' + browser.sessionID);
|
||||
if (props.onStart) {
|
||||
return props.onStart(browser);
|
||||
}
|
||||
},
|
||||
onComplete: exports.local.onComplete,
|
||||
onError: exports.local.onError,
|
||||
isDoneTimeout: exports.local.isDoneTimeout,
|
||||
};
|
||||
|
||||
/*eslint-disable camelcase*/
|
||||
/* https://saucelabs.com/platforms */
|
||||
exports.saucelabs_ios =
|
||||
exports.saucelabs_ios7 = sauceItUp({browserName: 'iphone', version: '7', platform:'OS X 10.9'});
|
||||
exports.saucelabs_ios6_1 = sauceItUp({browserName: 'iphone', version: '6.1', platform:'OS X 10.8'});
|
||||
exports.saucelabs_ios6 = sauceItUp({browserName: 'iphone', version: '6', platform:'OS X 10.8'});
|
||||
exports.saucelabs_ios5_1 = sauceItUp({browserName: 'iphone', version: '5.1', platform:'OS X 10.8'});
|
||||
exports.saucelabs_ios5 = sauceItUp({browserName: 'iphone', version: '5', platform:'OS X 10.6'});
|
||||
exports.saucelabs_ios4 = sauceItUp({browserName: 'iphone', version: '4', platform:'OS X 10.6'});
|
||||
|
||||
exports.saucelabs_ipad =
|
||||
exports.saucelabs_ipad7 = sauceItUp({browserName: 'ipad', version: '7', platform:'OS X 10.9'});
|
||||
exports.saucelabs_ipad6_1 = sauceItUp({browserName: 'ipad', version: '6.1', platform:'OS X 10.8'});
|
||||
exports.saucelabs_ipad6 = sauceItUp({browserName: 'ipad', version: '6', platform:'OS X 10.8'});
|
||||
exports.saucelabs_ipad5_1 = sauceItUp({browserName: 'ipad', version: '5.1', platform:'OS X 10.8'});
|
||||
exports.saucelabs_ipad5 = sauceItUp({browserName: 'ipad', version: '5', platform:'OS X 10.6'});
|
||||
exports.saucelabs_ipad4 = sauceItUp({browserName: 'ipad', version: '4', platform:'OS X 10.6'});
|
||||
|
||||
exports.saucelabs_android = sauceItUp({browserName: 'android', version: '4.0', platform:'Linux'});
|
||||
exports.saucelabs_android_tablet = sauceItUp({browserName: 'android', version: '4.0', platform:'Linux', 'device-type':'tablet'});
|
||||
|
||||
exports.saucelabs_safari = sauceItUp({browserName: 'safari'});
|
||||
exports.saucelabs_chrome = sauceItUp({browserName: 'chrome'});
|
||||
exports.saucelabs_firefox = sauceItUp({browserName: 'firefox'});
|
||||
|
||||
exports.saucelabs_ie =
|
||||
exports.saucelabs_ie8 = sauceItUp({browserName: 'internet explorer', version: 8});
|
||||
exports.saucelabs_ie9 = sauceItUp({browserName: 'internet explorer', version: 9});
|
||||
exports.saucelabs_ie10 = sauceItUp({browserName: 'internet explorer', version: 10});
|
||||
exports.saucelabs_ie11 = sauceItUp({browserName: 'internet explorer', version: 11, platform:'Windows 8.1'});
|
||||
/*eslint-enable camelcase*/
|
||||
|
||||
function sauceItUp(desiredCapabilities) {
|
||||
desiredCapabilities.build = exports.saucelabs.desiredCapabilities.build;
|
||||
desiredCapabilities['tunnel-identifier'] = exports.saucelabs.desiredCapabilities['tunnel-identifier'];
|
||||
return {
|
||||
webdriver: exports.saucelabs.webdriver,
|
||||
url: exports.saucelabs.url,
|
||||
onStart: exports.saucelabs.onStart,
|
||||
onComplete: exports.saucelabs.onComplete,
|
||||
onError: exports.saucelabs.onError,
|
||||
isDoneTimeout: exports.saucelabs.isDoneTimeout,
|
||||
desiredCapabilities: desiredCapabilities,
|
||||
};
|
||||
}
|
||||
|
||||
return exports;
|
||||
};
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var grunt = require('grunt');
|
||||
|
||||
module.exports = require('./webdriver-all')({
|
||||
url: 'http://127.0.0.1:9999/test/index.html',
|
||||
onComplete: function(passed) {
|
||||
if (!passed) {
|
||||
grunt.fatal('tests failed');
|
||||
}
|
||||
},
|
||||
onError: function(error) {
|
||||
grunt.fatal(error);
|
||||
},
|
||||
});
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
'use strict';
|
||||
var grunt = require('grunt');
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
|
||||
module.exports = function() {
|
||||
var ROOT = path.join(__dirname, '/../..');
|
||||
var done = this.async();
|
||||
var uncoveredExpressionCount = 0;
|
||||
var uncoveredLineCount = 0;
|
||||
|
||||
fs.createReadStream(ROOT + '/coverage.log')
|
||||
.pipe(require('coverify/parse')(function(error, results) {
|
||||
if (error) {
|
||||
grunt.fatal(error);
|
||||
}
|
||||
|
||||
Object.keys(results)
|
||||
.sort(function(a, b) {
|
||||
return results[a].length - results[b].length;
|
||||
})
|
||||
.reverse()
|
||||
.forEach(function(concretePath) {
|
||||
if (results[concretePath].length === 0) {
|
||||
return;
|
||||
}
|
||||
var relativePath = concretePath.replace(ROOT, '');
|
||||
uncoveredExpressionCount += results[concretePath].length;
|
||||
grunt.log.error(results[concretePath].length + ' expressions not covered ' + relativePath);
|
||||
|
||||
results[concretePath].forEach(function(c) {
|
||||
uncoveredLineCount += c.code.split('\n').length;
|
||||
console.log('txmt://open?url=' + encodeURIComponent('file://' + concretePath) + '&line=' + (c.lineNum + 1) + '&column=' + (c.column[0] + 2));
|
||||
});
|
||||
console.log('');
|
||||
});
|
||||
|
||||
Object.keys(results).sort().forEach(function(concretePath) {
|
||||
if (results[concretePath].length > 0) {
|
||||
return;
|
||||
}
|
||||
var relativePath = concretePath.replace(ROOT, '');
|
||||
grunt.log.ok('100% coverage ' + relativePath);
|
||||
});
|
||||
|
||||
if (uncoveredExpressionCount > 0) {
|
||||
grunt.log.error(uncoveredExpressionCount + ' expressions not covered');
|
||||
}
|
||||
if (uncoveredLineCount > 0) {
|
||||
grunt.log.error(uncoveredLineCount + ' lines not covered');
|
||||
}
|
||||
done();
|
||||
}));
|
||||
};
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var grunt = require('grunt');
|
||||
var http = require('http');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
function get(url, targetFilePath, completedSuccessfully) {
|
||||
grunt.verbose.writeln('getting url \'' + url + '\'');
|
||||
http.get(url, function(response) {
|
||||
grunt.verbose.writeln('Received status code ' + response.statusCode + ' for \'' + url + '\'');
|
||||
|
||||
if (response.statusCode !== 200) {
|
||||
if (response.headers.location) {
|
||||
get(response.headers.location, targetFilePath);
|
||||
return;
|
||||
} else {
|
||||
grunt.fatal('Nothing else to do.');
|
||||
completedSuccessfully(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
grunt.verbose.writeln('Writing url to \'' + targetFilePath + '\'');
|
||||
response.pipe(fs.createWriteStream(targetFilePath))
|
||||
.on('close', function() {
|
||||
completedSuccessfully(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = function() {
|
||||
var completedSuccessfully = this.async();
|
||||
get(
|
||||
'http://react.zpao.com/builds/master/latest/react.min.js',
|
||||
path.join(__dirname, '/../../build/react-previous.min.js'),
|
||||
function(success) {
|
||||
if (!success) {
|
||||
return completedSuccessfully(success);
|
||||
}
|
||||
get(
|
||||
'http://react.zpao.com/builds/master/latest/JSXTransformer.js',
|
||||
path.join(__dirname, '/../../build/JSXTransformer-previous.js'),
|
||||
completedSuccessfully
|
||||
);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var grunt = require('grunt');
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
module.exports = function() {
|
||||
var config = this.data;
|
||||
var done = this.async();
|
||||
|
||||
var theFilesToTestScript = fs.createWriteStream(path.join(__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;
|
||||
|
||||
// Make sure the things that need to be exposed are.
|
||||
var requires = config.requires || [];
|
||||
grunt.file.expand({
|
||||
nonull: true, // Keep IDs that don't expand to anything.
|
||||
cwd: config.rootDirectory,
|
||||
}, requires).forEach(function(name) {
|
||||
name = name.replace(/\.js$/i, '');
|
||||
args.push(name);
|
||||
theFilesToTestScript.write('harness.enableTest(' + JSON.stringify(name) + ');\n');
|
||||
});
|
||||
|
||||
require('populist').buildP({
|
||||
rootDirectory: config.rootDirectory,
|
||||
args: args,
|
||||
}).then(function(output) {
|
||||
grunt.file.write(config.outfile, 'process = {env: {}};' + output);
|
||||
theFilesToTestScript.end();
|
||||
theFilesToTestScript.once('close', done);
|
||||
});
|
||||
};
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var grunt = require('grunt');
|
||||
var SauceTunnel = require('sauce-tunnel');
|
||||
|
||||
module.exports = function() {
|
||||
var task = this;
|
||||
var shouldStayAliveForever = task.flags.keepalive;
|
||||
|
||||
var SAUCE_ACCESS_KEY = process.env.SAUCE_ACCESS_KEY || '339d32ca-d594-4570-a3c2-94c50a91919b';
|
||||
if (!SAUCE_ACCESS_KEY) {
|
||||
grunt.fatal('Requires the environment variable SAUCE_ACCESS_KEY to be set');
|
||||
}
|
||||
|
||||
var SAUCE_USERNAME = process.env.SAUCE_USERNAME || 'React';
|
||||
if (!SAUCE_USERNAME) {
|
||||
grunt.fatal('Requires the environment variable SAUCE_USERNAME to be set');
|
||||
}
|
||||
|
||||
var IDENTIFIER = process.env.TRAVIS_JOB_NUMBER || 'my awesome tunnel';
|
||||
|
||||
var taskCompletedSuccessfully = task.async();
|
||||
|
||||
var stunnel = new SauceTunnel(SAUCE_USERNAME, SAUCE_ACCESS_KEY, IDENTIFIER, /*tunneled*/true, /*tunnelTimeout*/5);
|
||||
process.on('exit', stunnel.stop.bind(stunnel, function() {}));
|
||||
|
||||
stunnel.on('log:error', grunt.log.error.bind(grunt.log));
|
||||
stunnel.on('log:writeln', grunt.log.writeln.bind(grunt.log));
|
||||
|
||||
stunnel.on('verbose:ok', grunt.verbose.ok.bind(grunt.verbose));
|
||||
stunnel.on('verbose:error', grunt.verbose.error.bind(grunt.verbose));
|
||||
stunnel.on('verbose:debug', grunt.verbose.debug.bind(grunt.verbose));
|
||||
stunnel.on('verbose:writeln', grunt.verbose.writeln.bind(grunt.verbose));
|
||||
|
||||
stunnel.openTunnel(function(isOpen) {
|
||||
if (shouldStayAliveForever && isOpen) {
|
||||
grunt.verbose.writeln('Keeping the sauce-tunnel open forever because you used the keepalive flag `' + task.nameArgs + '`');
|
||||
return;
|
||||
}
|
||||
grunt.verbose.writeln('To keep the sauce-tunnel open forever, use the grunt task `' + task.nameArgs + ':keepalive`');
|
||||
taskCompletedSuccessfully(isOpen);
|
||||
});
|
||||
};
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/*eslint-disable consistent-return*/
|
||||
'use strict';
|
||||
|
||||
var grunt = require('grunt');
|
||||
var wd = require('wd');
|
||||
|
||||
module.exports = function task(getJSReport) {
|
||||
var config = this.data;
|
||||
var taskSucceeded = this.async();
|
||||
getJSReport = getJSReport.bind(this, config, wd);
|
||||
|
||||
var desiredCapabilities = {};
|
||||
if (config.desiredCapabilities) {
|
||||
Object.keys(config.desiredCapabilities).forEach(function(key) {
|
||||
if (config.desiredCapabilities[key] === undefined) {
|
||||
return;
|
||||
}
|
||||
desiredCapabilities[key] = config.desiredCapabilities[key];
|
||||
});
|
||||
}
|
||||
grunt.verbose.writeln('desiredCapabilities', JSON.stringify(desiredCapabilities));
|
||||
|
||||
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 || '');
|
||||
});
|
||||
|
||||
var results = null;
|
||||
|
||||
// browser._debugPromise();
|
||||
browser
|
||||
.init(desiredCapabilities)
|
||||
.then(config.onStart && config.onStart.bind(config, browser))
|
||||
.get(config.url)
|
||||
.then(function() {
|
||||
return browser;
|
||||
})
|
||||
.then(getJSReport)
|
||||
.then(function(data) {
|
||||
results = data;
|
||||
})
|
||||
.fail(function(error) {
|
||||
grunt.log.error(error);
|
||||
return browser
|
||||
.eval('document.documentElement.innerText || document.documentElement.textContent')
|
||||
.then(grunt.verbose.writeln.bind(grunt.verbose))
|
||||
.then(function() {
|
||||
throw error;
|
||||
});
|
||||
})
|
||||
.finally(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(
|
||||
function() {
|
||||
if (config.onComplete) {
|
||||
config.onComplete(results);
|
||||
}
|
||||
taskSucceeded(true);
|
||||
},
|
||||
function(error) {
|
||||
if (config.onError) {
|
||||
config.onError(error);
|
||||
}
|
||||
taskSucceeded(false);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
module.exports = function() {
|
||||
return require('./webdriver-all').call(this, function(config, wd, browser) {
|
||||
return browser
|
||||
.waitFor(wd.asserters.jsCondition('typeof window.jasmine != \'undefined\''), 5e3, 50)
|
||||
.fail(function(error) {
|
||||
throw Error('The test page didn\'t load properly. ' + error);
|
||||
})
|
||||
.waitFor(wd.asserters.jsCondition('typeof window.jasmine.getJSReport != \'undefined\''), 60e3, 100)
|
||||
.waitFor(wd.asserters.jsCondition('window.postDataToURL.running <= 0'), 30e3, 500)
|
||||
.eval('jasmine.getJSReport().passed');
|
||||
});
|
||||
};
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var grunt = require('grunt');
|
||||
|
||||
module.exports = function() {
|
||||
var onReadyCallback = this.async();
|
||||
|
||||
var phantomjs = require('phantomjs').path;
|
||||
var childProcess = 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 = childProcess.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);
|
||||
};
|
||||
10
package.json
10
package.json
|
|
@ -35,10 +35,8 @@
|
|||
"browserify": "^9.0.3",
|
||||
"bundle-collapser": "^1.1.1",
|
||||
"coffee-script": "^1.8.0",
|
||||
"coverify": "^1.3.3",
|
||||
"derequire": "^2.0.0",
|
||||
"envify": "^3.0.0",
|
||||
"es5-shim": "^4.0.0",
|
||||
"eslint": "^0.22.1",
|
||||
"eslint-plugin-react": "^2.5.0",
|
||||
"eslint-plugin-react-internal": "file:eslint-rules",
|
||||
|
|
@ -48,22 +46,16 @@
|
|||
"grunt-compare-size": "^0.4.0",
|
||||
"grunt-contrib-clean": "^0.6.0",
|
||||
"grunt-contrib-compress": "^0.13.0",
|
||||
"grunt-contrib-connect": "~0.6.0",
|
||||
"grunt-jest": "^0.1.3",
|
||||
"gzip-js": "~0.3.2",
|
||||
"jasmine-tapreporter": "~0.2.2",
|
||||
"jest-cli": "^0.4.13",
|
||||
"object-assign": "^3.0.0",
|
||||
"optimist": "^0.6.1",
|
||||
"phantomjs": "^1.9.17",
|
||||
"platform": "^1.1.0",
|
||||
"populist": "~0.1.6",
|
||||
"sauce-tunnel": "~1.1.0",
|
||||
"tmp": "~0.0.18",
|
||||
"typescript": "^1.4.0",
|
||||
"uglify-js": "^2.4.23",
|
||||
"uglifyify": "^3.0.1",
|
||||
"wd": "~0.2.6"
|
||||
"uglifyify": "^3.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
// This file exists both to give a single entry point for all the utility
|
||||
// modules in src/test and to specify an ordering on those modules, since
|
||||
// some still have implicit dependencies on others.
|
||||
|
||||
require("./phantomjs-shims");
|
||||
require("ReactTestUtils");
|
||||
require("reactComponentExpect");
|
||||
require("mocks");
|
||||
require("mock-modules");
|
||||
require("./mock-timers");
|
||||
|
||||
exports.enableTest = function(testID) {
|
||||
describe(testID, function() {
|
||||
beforeEach(function() {
|
||||
require("mock-modules").setMockMap(mockMap);
|
||||
});
|
||||
|
||||
require("mock-modules").clearMockMap();
|
||||
require("../" + testID);
|
||||
var mockMap = require("mock-modules").getMockMap();
|
||||
});
|
||||
};
|
||||
|
||||
exports.removeNextSiblings = function(node) {
|
||||
var parent = node && node.parentNode;
|
||||
if (parent) {
|
||||
while (node.nextSibling) {
|
||||
parent.removeChild(node.nextSibling);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2015, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule mock-modules
|
||||
*/
|
||||
|
||||
var mocks = require("mocks");
|
||||
var exportsRegistry = {};
|
||||
var hasOwn = exportsRegistry.hasOwnProperty;
|
||||
var explicitMockMap = {};
|
||||
|
||||
function getMock(exports) {
|
||||
try {
|
||||
return mocks.generateFromMetadata(mocks.getMetadata(exports));
|
||||
} catch (err) {
|
||||
console.warn(err);
|
||||
return exports;
|
||||
}
|
||||
}
|
||||
|
||||
// This function should be called at the bottom of any module that might
|
||||
// need to be mocked, after the final value of module.exports is known.
|
||||
exports.register = function(id, module) {
|
||||
exportsRegistry[id] = {
|
||||
module: module,
|
||||
actual: module.exports,
|
||||
mocked: null // Filled in lazily later.
|
||||
};
|
||||
|
||||
// If doMock or doNotMock was called earlier, before the module was
|
||||
// registered, then the choice should have been recorded in
|
||||
// explicitMockMap. Now that the module is registered, we can finally
|
||||
// fulfill the request.
|
||||
if (hasOwn.call(explicitMockMap, id)) {
|
||||
if (explicitMockMap[id]) {
|
||||
doMock(id);
|
||||
} else {
|
||||
doNotMock(id);
|
||||
}
|
||||
}
|
||||
|
||||
return exports;
|
||||
};
|
||||
|
||||
function resetEntry(id) {
|
||||
if (hasOwn.call(exportsRegistry, id)) {
|
||||
delete exportsRegistry[id].module.exports;
|
||||
delete exportsRegistry[id];
|
||||
}
|
||||
}
|
||||
|
||||
exports.dumpCache = function() {
|
||||
require("mocks").clear();
|
||||
|
||||
// Deleting module.exports will cause the module to be lazily
|
||||
// reevaluated the next time it is required.
|
||||
for (var id in exportsRegistry) {
|
||||
resetEntry(id);
|
||||
}
|
||||
|
||||
return exports;
|
||||
};
|
||||
|
||||
exports.getMockMap = function() {
|
||||
return explicitMockMap;
|
||||
};
|
||||
|
||||
exports.clearMockMap = function() {
|
||||
explicitMockMap = {};
|
||||
};
|
||||
|
||||
exports.setMockMap = function(mockMap) {
|
||||
exports.dumpCache();
|
||||
exports.clearMockMap();
|
||||
for (var id in mockMap) {
|
||||
if (mockMap[id]) {
|
||||
doMock(id);
|
||||
} else {
|
||||
doNotMock(id);
|
||||
}
|
||||
}
|
||||
|
||||
return exports;
|
||||
};
|
||||
|
||||
// Call this function to ensure that require(id) returns the actual
|
||||
// exports object created by the module.
|
||||
function doNotMock(id) {
|
||||
explicitMockMap[id] = false;
|
||||
|
||||
var entry = exportsRegistry[id];
|
||||
if (entry && entry.module && entry.actual) {
|
||||
entry.module.exports = entry.actual;
|
||||
}
|
||||
|
||||
return exports;
|
||||
}
|
||||
|
||||
// Call this function to ensure that require(id) returns a mock exports
|
||||
// object based on the actual exports object created by the module.
|
||||
function doMock(id) {
|
||||
explicitMockMap[id] = true;
|
||||
|
||||
var entry = exportsRegistry[id];
|
||||
if (entry && entry.module && entry.actual) {
|
||||
// Because mocking can be expensive, create the mock exports object on
|
||||
// demand, the first time doMock is called.
|
||||
entry.mocked || (entry.mocked = getMock(entry.actual));
|
||||
entry.module.exports = entry.mocked;
|
||||
}
|
||||
|
||||
return exports;
|
||||
}
|
||||
|
||||
var global = Function("return this")();
|
||||
require('test/mock-timers').installMockTimers(global);
|
||||
|
||||
// Exported names are different for backwards compatibility.
|
||||
exports.dontMock = doNotMock;
|
||||
exports.mock = doMock;
|
||||
|
|
@ -1,219 +0,0 @@
|
|||
var mocks = require('mocks');
|
||||
|
||||
var timers = {};
|
||||
// Keep a fake timestamp
|
||||
// move on the time when runTimersToTime() is called
|
||||
var now = 0;
|
||||
|
||||
// add a timer of type either 'timeout' or 'interval'
|
||||
function _setTimer(type, callback, delay) {
|
||||
var token = null;
|
||||
do {
|
||||
token = Math.floor(Math.random() * 4294967296) + 1;
|
||||
} while (timers[token]);
|
||||
timers[token] = {
|
||||
type: type,
|
||||
callback: callback,
|
||||
// Add some random msecs to the delay to mimic code execution time.
|
||||
time: now + delay + Math.floor(Math.random() * 5),
|
||||
interval: (type == 'interval' ? delay : 0)
|
||||
};
|
||||
return token;
|
||||
}
|
||||
|
||||
// clear a timer of type either 'timeout' or 'interval'
|
||||
function _clearTimer(type, token) {
|
||||
if (timers[token] && timers[token].type == type) {
|
||||
delete timers[token];
|
||||
}
|
||||
}
|
||||
|
||||
function _setTimeout(callback, delay) {
|
||||
return _setTimer('timeout', callback, delay);
|
||||
}
|
||||
|
||||
function _setInterval(callback, delay) {
|
||||
return _setTimer('interval', callback, delay);
|
||||
}
|
||||
|
||||
function _clearTimeout(token) {
|
||||
_clearTimer('timeout', token);
|
||||
}
|
||||
|
||||
function _clearInterval(token) {
|
||||
_clearTimer('interval', token);
|
||||
}
|
||||
|
||||
// Run timer of given token
|
||||
function _runTimer(token) {
|
||||
// Skip non-existing token
|
||||
if (timers[token]) {
|
||||
if (timers[token].type == 'timeout') {
|
||||
// for 'timeout', run callback and delete the timer
|
||||
var callback = timers[token].callback;
|
||||
delete timers[token];
|
||||
callback();
|
||||
} else if (timers[token].type == 'interval') {
|
||||
// for 'interval', run callback and set the next invoke time
|
||||
// Add some random msecs to the delay to mimic code execution time.
|
||||
timers[token].time =
|
||||
now + timers[token].interval + Math.floor(Math.random() * 5);
|
||||
timers[token].callback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function _runTimersOnce() {
|
||||
// Invoke all timers once regardsless of the delay
|
||||
for (var token in timers) {
|
||||
_runTimer(token);
|
||||
}
|
||||
}
|
||||
|
||||
function _runTimersToTime(delay) {
|
||||
var toRunToken = _getNextTimerToken();
|
||||
if (!toRunToken) {
|
||||
return;
|
||||
}
|
||||
|
||||
var minTime = timers[toRunToken].time;
|
||||
if (now + delay < minTime) {
|
||||
// Termination when there's no more timers to invoke
|
||||
now += delay;
|
||||
} else {
|
||||
// Recursively invoke the next to-run timer
|
||||
delay -= (minTime - now);
|
||||
now = minTime;
|
||||
_runTimer(toRunToken);
|
||||
_runTimersToTime(delay);
|
||||
}
|
||||
}
|
||||
|
||||
function _runTimersRepeatedly() {
|
||||
// Only run a generous 1000 timers and then bail, since we may have entered
|
||||
// a loop if we have more than that.
|
||||
var max_timers = 1000;
|
||||
|
||||
var token;
|
||||
for (var ii = 0; ii < max_timers; ii++) {
|
||||
token = _getNextTimerToken();
|
||||
|
||||
if (!token) {
|
||||
break;
|
||||
}
|
||||
|
||||
_runTimer(token);
|
||||
}
|
||||
|
||||
if (ii === max_timers) {
|
||||
throw new Error("More timers still exist after " + max_timers + " timers!");
|
||||
}
|
||||
}
|
||||
|
||||
function _clearTimers() {
|
||||
for (var token in timers) {
|
||||
delete timers[token];
|
||||
}
|
||||
}
|
||||
|
||||
function _getNextTimerToken() {
|
||||
var nextTimerToken = null;
|
||||
var minTime = 31536000000; // One year
|
||||
// Find the next to invoke timer
|
||||
for (var token in timers) {
|
||||
if (timers[token].time < minTime) {
|
||||
nextTimerToken = token;
|
||||
minTime = timers[token].time;
|
||||
}
|
||||
}
|
||||
return nextTimerToken;
|
||||
}
|
||||
|
||||
var mockTimers = {
|
||||
setTimeout: _setTimeout,
|
||||
clearTimeout: _clearTimeout,
|
||||
setInterval: _setInterval,
|
||||
clearInterval: _clearInterval,
|
||||
|
||||
/**
|
||||
* Copyright 2013-2015, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* Iteratively run callbacks in time order during the time from now to
|
||||
* now + delay.
|
||||
* If one callback register another timer which should be run during now to
|
||||
* now + delay, the new timer will also be run in the right order.
|
||||
*
|
||||
* @param delay
|
||||
*/
|
||||
runTimersToTime: _runTimersToTime,
|
||||
|
||||
/**
|
||||
* Run all registered timer once. Newly registered timers will not be run.
|
||||
*/
|
||||
runTimersOnce: _runTimersOnce,
|
||||
|
||||
/**
|
||||
* Iteratively run callbacks until there are no timers left to call. Will
|
||||
* stop after a maximum number of iterations to avoid infinite loop.
|
||||
*
|
||||
* @param maximum iterations (optional)
|
||||
*/
|
||||
runTimersRepeatedly: _runTimersRepeatedly,
|
||||
|
||||
/**
|
||||
* Clear all timers
|
||||
*/
|
||||
clearTimers: _clearTimers,
|
||||
|
||||
/**
|
||||
* Get the number of remaining timers
|
||||
*/
|
||||
getTimersCount: function() {
|
||||
return Object.keys(timers).length;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.installMockTimers = function(window) {
|
||||
window._originalTimeouts = {
|
||||
setTimeout: window.setTimeout,
|
||||
clearTimeout: window.clearTimeout,
|
||||
setInterval: window.setInterval,
|
||||
clearInterval: window.clearInterval
|
||||
};
|
||||
window.setTimeout =
|
||||
mocks.getMockFunction().mockImplementation(mockTimers.setTimeout);
|
||||
window.clearTimeout =
|
||||
mocks.getMockFunction().mockImplementation(mockTimers.clearTimeout);
|
||||
window.setInterval =
|
||||
mocks.getMockFunction().mockImplementation(mockTimers.setInterval);
|
||||
window.clearInterval =
|
||||
mocks.getMockFunction().mockImplementation(mockTimers.clearInterval);
|
||||
window.mockRunTimersOnce =
|
||||
mocks.getMockFunction().mockImplementation(mockTimers.runTimersOnce);
|
||||
window.mockRunTimersToTime =
|
||||
mocks.getMockFunction().mockImplementation(mockTimers.runTimersToTime);
|
||||
window.mockRunTimersRepeatedly =
|
||||
mocks.getMockFunction().mockImplementation(mockTimers.runTimersRepeatedly);
|
||||
window.mockClearTimers =
|
||||
mocks.getMockFunction().mockImplementation(mockTimers.clearTimers);
|
||||
window.mockGetTimersCount =
|
||||
mocks.getMockFunction().mockImplementation(mockTimers.getTimersCount);
|
||||
};
|
||||
|
||||
module.exports.uninstallMockTimers = function(window) {
|
||||
window.setTimeout = window._originalTimeouts.setTimeout;
|
||||
window.clearTimeout = window._originalTimeouts.clearTimeout;
|
||||
window.setInterval = window._originalTimeouts.setInterval;
|
||||
window.clearInterval = window._originalTimeouts.clearInterval;
|
||||
window._originalTimeouts = undefined;
|
||||
window.mockRunTimersOnce = undefined;
|
||||
window.mockRunTimersToTime = undefined;
|
||||
window.mockRunTimersRepeatedly = undefined;
|
||||
window.mockClearTimers = undefined;
|
||||
window.mockGetTimersCount = undefined;
|
||||
};
|
||||
|
|
@ -1,425 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2015, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* @providesModule mocks
|
||||
*/
|
||||
|
||||
function isA(typeName, value) {
|
||||
return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
|
||||
}
|
||||
|
||||
function getType(ref) {
|
||||
if (isA('RegExp', ref)) {
|
||||
return 'regexp';
|
||||
}
|
||||
|
||||
if (isA('Array', ref)) {
|
||||
return 'array';
|
||||
}
|
||||
|
||||
if (isA('Function', ref)) {
|
||||
return 'function';
|
||||
}
|
||||
|
||||
if (isA('Object', ref)) {
|
||||
return 'object';
|
||||
}
|
||||
|
||||
// consider number and string fields to be constants that we want to
|
||||
// pick up as they are
|
||||
if (isA('Number', ref) || isA('String', ref)) {
|
||||
return 'constant';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function makeComponent(metadata) {
|
||||
switch (metadata.type) {
|
||||
case 'object':
|
||||
return {};
|
||||
|
||||
case 'array':
|
||||
return [];
|
||||
|
||||
case 'regexp':
|
||||
return new RegExp();
|
||||
|
||||
case 'constant':
|
||||
return metadata.value;
|
||||
|
||||
case 'function':
|
||||
var defaultReturnValue;
|
||||
var specificReturnValues = [];
|
||||
var mockImpl;
|
||||
var isReturnValueLastSet = false;
|
||||
var calls = [];
|
||||
var instances = [];
|
||||
var prototype =
|
||||
(metadata.members && metadata.members.prototype &&
|
||||
metadata.members.prototype.members) || {};
|
||||
|
||||
var f = function() {
|
||||
global.dirtyMocks.push(f);
|
||||
|
||||
instances.push(this);
|
||||
calls.push(Array.prototype.slice.call(arguments));
|
||||
if (this instanceof f) {
|
||||
// This is probably being called as a constructor
|
||||
for (var slot in prototype) {
|
||||
// Copy prototype methods to the instance to make
|
||||
// it easier to interact with mock instance call and
|
||||
// return values
|
||||
if (prototype[slot].type == 'function') {
|
||||
var protoImpl = this[slot];
|
||||
this[slot] = generateFromMetadata(prototype[slot]);
|
||||
this[slot]._protoImpl = protoImpl;
|
||||
}
|
||||
}
|
||||
|
||||
// Run the mock constructor implementation
|
||||
mockImpl && mockImpl.apply(this, arguments);
|
||||
return;
|
||||
}
|
||||
|
||||
var returnValue;
|
||||
// If return value is last set, either specific or default, i.e.
|
||||
// mockReturnValueOnce()/mockReturnValue() is called and no
|
||||
// mockImplementation() is called after that.
|
||||
// use the set return value.
|
||||
if (isReturnValueLastSet) {
|
||||
returnValue = specificReturnValues.shift();
|
||||
if (returnValue === undefined) {
|
||||
returnValue = defaultReturnValue;
|
||||
}
|
||||
}
|
||||
|
||||
// If mockImplementation() is last set, or specific return values
|
||||
// are used up, use the mock implementation.
|
||||
if (mockImpl && returnValue === undefined) {
|
||||
return mockImpl.apply(this, arguments);
|
||||
}
|
||||
|
||||
// Otherwise use prototype implementation
|
||||
if (returnValue === undefined && f._protoImpl) {
|
||||
return f._protoImpl.apply(this, arguments);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
};
|
||||
|
||||
f._isMockFunction = true;
|
||||
|
||||
f.mock = {
|
||||
calls: calls,
|
||||
instances: instances
|
||||
};
|
||||
|
||||
f.mockClear = function() {
|
||||
calls.length = 0;
|
||||
instances.length = 0;
|
||||
};
|
||||
|
||||
f.mockReturnValueOnce = function(value) {
|
||||
// next function call will return this value or default return value
|
||||
isReturnValueLastSet = true;
|
||||
specificReturnValues.push(value);
|
||||
return f;
|
||||
};
|
||||
|
||||
f.mockReturnValue = function(value) {
|
||||
// next function call will return specified return value or this one
|
||||
isReturnValueLastSet = true;
|
||||
defaultReturnValue = value;
|
||||
return f;
|
||||
};
|
||||
|
||||
f.mockImplementation = function(fn) {
|
||||
// next function call will use mock implementation return value
|
||||
isReturnValueLastSet = false;
|
||||
mockImpl = fn;
|
||||
return f;
|
||||
};
|
||||
|
||||
f.mockReturnThis = function() {
|
||||
return f.mockImplementation(function() {
|
||||
return this;
|
||||
});
|
||||
};
|
||||
|
||||
f._getMockImplementation = function() {
|
||||
return mockImpl;
|
||||
};
|
||||
|
||||
if (metadata.mockImpl) {
|
||||
f.mockImplementation(metadata.mockImpl);
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
throw new Error('Unrecognized type ' + metadata.type);
|
||||
}
|
||||
|
||||
function generateFromMetadata(_metadata) {
|
||||
var callbacks = [];
|
||||
var refs = {};
|
||||
|
||||
function generateMock(metadata) {
|
||||
var mock = makeComponent(metadata);
|
||||
if (metadata.ref_id != null) {
|
||||
refs[metadata.ref_id] = mock;
|
||||
}
|
||||
|
||||
function getRefCallback(slot, ref) {
|
||||
return function() {
|
||||
mock[slot] = refs[ref];
|
||||
};
|
||||
}
|
||||
|
||||
for (var slot in metadata.members) {
|
||||
var slotMetadata = metadata.members[slot];
|
||||
if (slotMetadata.ref != null) {
|
||||
callbacks.push(getRefCallback(slot, slotMetadata.ref));
|
||||
} else {
|
||||
mock[slot] = generateMock(slotMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
return mock;
|
||||
}
|
||||
|
||||
var mock = generateMock(_metadata);
|
||||
callbacks.forEach(function(setter) {
|
||||
setter();
|
||||
});
|
||||
|
||||
return mock;
|
||||
}
|
||||
|
||||
|
||||
function _getMetadata(component, _refs) {
|
||||
var refs = _refs || [];
|
||||
|
||||
// This is a potential performance drain, since the whole list is scanned
|
||||
// for every component
|
||||
var ref = refs.indexOf(component);
|
||||
if (ref > -1) {
|
||||
return {ref: ref};
|
||||
}
|
||||
|
||||
var type = getType(component);
|
||||
if (!type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var metadata = {type: type};
|
||||
if (type == 'constant') {
|
||||
metadata.value = component;
|
||||
return metadata;
|
||||
} else if (type == 'function') {
|
||||
if (component._isMockFunction) {
|
||||
metadata.mockImpl = component._getMockImplementation();
|
||||
}
|
||||
}
|
||||
|
||||
metadata.ref_id = refs.length;
|
||||
refs.push(component);
|
||||
|
||||
var members = null;
|
||||
|
||||
function addMember(slot, data) {
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
if (!members) {
|
||||
members = {};
|
||||
}
|
||||
members[slot] = data;
|
||||
}
|
||||
|
||||
// Leave arrays alone
|
||||
if (type != 'array') {
|
||||
for (var slot in component) {
|
||||
if (slot.charAt(0) == '_' ||
|
||||
(type == 'function' && component._isMockFunction &&
|
||||
slot.match(/^mock/))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (component.hasOwnProperty(slot) ||
|
||||
(type == 'object' && component[slot] != Object.prototype[slot])) {
|
||||
addMember(slot, _getMetadata(component[slot], refs));
|
||||
}
|
||||
}
|
||||
|
||||
// If component is native code function, prototype might be undefined
|
||||
if (type == 'function' && component.prototype) {
|
||||
var prototype = _getMetadata(component.prototype, refs);
|
||||
if (prototype && prototype.members) {
|
||||
addMember('prototype', prototype);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (members) {
|
||||
metadata.members = members;
|
||||
}
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
function removeUnusedRefs(metadata) {
|
||||
function visit(md, f) {
|
||||
f(md);
|
||||
if (md.members) {
|
||||
for (var slot in md.members) {
|
||||
visit(md.members[slot], f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var usedRefs = {};
|
||||
visit(metadata, function(md) {
|
||||
if (md.ref != null) {
|
||||
usedRefs[md.ref] = true;
|
||||
}
|
||||
});
|
||||
|
||||
visit(metadata, function(md) {
|
||||
if (!usedRefs[md.ref_id]) {
|
||||
delete md.ref_id;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var global = Function("return this")();
|
||||
global.dirtyMocks = global.dirtyMocks || [];
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Invokes the .mockClear method of all function mocks that have been
|
||||
* called since the last time clear was called.
|
||||
*/
|
||||
clear: function() {
|
||||
var old = global.dirtyMocks;
|
||||
global.dirtyMocks = [];
|
||||
old.forEach(function(mock) {
|
||||
mock.mockClear();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Generates a mock based on the given metadata. Mocks treat functions
|
||||
* specially, and all mock functions have additional members, described in the
|
||||
* documentation for getMockFunction in this module.
|
||||
*
|
||||
* One important note: function prototoypes are handled specially by this
|
||||
* mocking framework. For functions with prototypes, when called as a
|
||||
* constructor, the mock will install mocked function members on the instance.
|
||||
* This allows different instances of the same constructor to have different
|
||||
* values for its mocks member and its return values.
|
||||
*
|
||||
* @param metadata Metadata for the mock in the schema returned by the
|
||||
* getMetadata method of this module.
|
||||
*
|
||||
*/
|
||||
generateFromMetadata: generateFromMetadata,
|
||||
|
||||
/**
|
||||
* Inspects the argument and returns its schema in the following recursive
|
||||
* format:
|
||||
* {
|
||||
* type: ...
|
||||
* members : {}
|
||||
* }
|
||||
*
|
||||
* Where type is one of 'array', 'object', 'function', or 'ref', and members
|
||||
* is an optional dictionary where the keys are member names and the values
|
||||
* are metadata objects. Function prototypes are defined simply by defining
|
||||
* metadata for the member.prototype of the function. The type of a function
|
||||
* prototype should always be "object". For instance, a simple class might be
|
||||
* defined like this:
|
||||
*
|
||||
* {
|
||||
* type: 'function',
|
||||
* members: {
|
||||
* staticMethod: {type: 'function'},
|
||||
* prototype: {
|
||||
* type: 'object',
|
||||
* members: {
|
||||
* instanceMethod: {type: 'function'}
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Metadata may also contain references to other objects defined within the
|
||||
* same metadata object. The metadata for the referent must be marked with
|
||||
* 'ref_id' key and an arbitrary value. The referer must be marked with a
|
||||
* 'ref' key that has the same value as object with ref_id that it refers to.
|
||||
* For instance, this metadata blob:
|
||||
* {
|
||||
* type: 'object',
|
||||
* ref_id: 1,
|
||||
* members: {
|
||||
* self: {ref: 1}
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* defines an object with a slot named 'self' that refers back to the object.
|
||||
*
|
||||
* @param {*} component The component for which to retrieve metadata.
|
||||
*/
|
||||
getMetadata: function(component) {
|
||||
var metadata = _getMetadata(component);
|
||||
// to make it easier to work with mock metadata, only preserve references
|
||||
// that are actually used
|
||||
removeUnusedRefs(metadata);
|
||||
return metadata;
|
||||
},
|
||||
|
||||
/**
|
||||
* Generates a stand-alone function with members that help drive unit tests or
|
||||
* confirm expectations. Specifically, functions returned by this method have
|
||||
* the following members:
|
||||
*
|
||||
* .mock:
|
||||
* An object with two members, "calls", and "instances", which are both
|
||||
* lists. The items in the "calls" list are the arguments with which the
|
||||
* function was called. The "instances" list stores the value of 'this' for
|
||||
* each call to the function. This is useful for retrieving instances from a
|
||||
* constructor.
|
||||
*
|
||||
* .mockReturnValueOnce(value)
|
||||
* Pushes the given value onto a FIFO queue of return values for the
|
||||
* function.
|
||||
*
|
||||
* .mockReturnValue(value)
|
||||
* Sets the default return value for the function.
|
||||
*
|
||||
* .mockImplementation(function)
|
||||
* Sets a mock implementation for the function.
|
||||
*
|
||||
* .mockReturnThis()
|
||||
* Syntactic sugar for .mockImplementation(function() {return this;})
|
||||
*
|
||||
* In case both mockImplementation() and
|
||||
* mockReturnValueOnce()/mockReturnValue() are called. The priority of
|
||||
* which to use is based on what is the last call:
|
||||
* - if the last call is mockReturnValueOnce() or mockReturnValue(),
|
||||
* use the specific return specific return value or default return value.
|
||||
* If specific return values are used up or no default return value is set,
|
||||
* fall back to try mockImplementation();
|
||||
* - if the last call is mockImplementation(), run the given implementation
|
||||
* and return the result.
|
||||
*/
|
||||
getMockFunction: function() {
|
||||
return makeComponent({type: 'function'});
|
||||
}
|
||||
};
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
(function() {
|
||||
|
||||
var Ap = Array.prototype;
|
||||
var slice = Ap.slice;
|
||||
var Fp = Function.prototype;
|
||||
|
||||
if (!Fp.bind) {
|
||||
// PhantomJS doesn't support Function.prototype.bind natively, so
|
||||
// polyfill it whenever this module is required.
|
||||
Fp.bind = function(context) {
|
||||
var func = this;
|
||||
var args = slice.call(arguments, 1);
|
||||
|
||||
function bound() {
|
||||
var invokedAsConstructor = func.prototype && (this instanceof func);
|
||||
return func.apply(
|
||||
// Ignore the context parameter when invoking the bound function
|
||||
// as a constructor. Note that this includes not only constructor
|
||||
// invocations using the new keyword but also calls to base class
|
||||
// constructors such as BaseClass.call(this, ...) or super(...).
|
||||
!invokedAsConstructor && context || this,
|
||||
args.concat(slice.call(arguments))
|
||||
);
|
||||
}
|
||||
|
||||
// The bound function must share the .prototype of the unbound
|
||||
// function so that any object created by one constructor will count
|
||||
// as an instance of both constructors.
|
||||
bound.prototype = func.prototype;
|
||||
|
||||
return bound;
|
||||
};
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
globals:
|
||||
harness: true
|
||||
|
||||
rules:
|
||||
strict: false
|
||||
no-undef: false
|
||||
no-unused-vars: false
|
||||
block-scoped-var: false
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<body>
|
||||
<script>
|
||||
;(function(){
|
||||
|
||||
var urls = [
|
||||
'../src/shared/vendor/third_party/webcomponents.js',
|
||||
'../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',
|
||||
|
||||
'lib/postDataToURL.browser.js',
|
||||
'lib/reportTestResults.browser.js',
|
||||
'lib/jasmine-execute.js',
|
||||
|
||||
'../build/react.js',
|
||||
'../build/react-test.js',
|
||||
'the-files-to-test.generated.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 = '?_=' + (+new Date).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('/');
|
||||
|
||||
}());
|
||||
</script>
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
document.write('<style> @import \'../vendor/jasmine/jasmine.css?_=' + (+new Date()).toString(36) + '\'; </style>');
|
||||
|
||||
(function(env) {
|
||||
var htmlReporter = new jasmine.HtmlReporter();
|
||||
env.addReporter(htmlReporter);
|
||||
env.specFilter = function(spec) {
|
||||
return htmlReporter.specFilter(spec);
|
||||
};
|
||||
|
||||
// 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();
|
||||
};
|
||||
|
||||
var oldError = console.error;
|
||||
var newError = function() {
|
||||
oldError.apply(this, arguments);
|
||||
var spec = env.currentSpec;
|
||||
if (spec) {
|
||||
var expectationResult = new jasmine.ExpectationResult({
|
||||
passed: false,
|
||||
message:
|
||||
'Expected test not to warn. If the warning is expected, mock it ' +
|
||||
'out using spyOn(console, \'error\'); and test that the warning ' +
|
||||
'occurs.',
|
||||
});
|
||||
spec.addMatcherResult(expectationResult);
|
||||
}
|
||||
};
|
||||
console.error = newError;
|
||||
// Make sure console.error is set back at the end of each test, or else the
|
||||
// above logic won't work
|
||||
env.afterEach(function() {
|
||||
if (console.error !== newError && !console.error.isSpy) {
|
||||
var expectationResult = new jasmine.ExpectationResult({
|
||||
passed: false,
|
||||
message: 'Test did not tear down console.error mock properly.',
|
||||
});
|
||||
env.currentSpec.addMatcherResult(expectationResult);
|
||||
}
|
||||
});
|
||||
})(jasmine.getEnv());
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/*eslint-disable brace-style*/
|
||||
function createXMLHttpRequest() {
|
||||
try {
|
||||
return new XMLHttpRequest();
|
||||
}
|
||||
catch(e) {}
|
||||
try {
|
||||
return new ActiveXObject('Msxml2.XMLHTTP');
|
||||
}
|
||||
catch (e) {}
|
||||
try {
|
||||
return new ActiveXObject('Microsoft.XMLHTTP');
|
||||
}
|
||||
catch (e) {}
|
||||
}
|
||||
/*eslint-enable brace-style*/
|
||||
|
||||
function getURLSync(url) {
|
||||
var request = createXMLHttpRequest();
|
||||
request.open('GET', url, /*asynchronous?*/false);
|
||||
return request.responseText;
|
||||
}
|
||||
|
||||
function postDataToURL(data, url, callback) {
|
||||
if (!callback) {
|
||||
callback = postDataToURL.defaultCallback;
|
||||
}
|
||||
var request = createXMLHttpRequest();
|
||||
if (!request) {
|
||||
return callback(Error('XMLHttpRequest is unsupported'));
|
||||
}
|
||||
postDataToURL.running = (postDataToURL.running || 0) + 1;
|
||||
request.onreadystatechange = function() {
|
||||
if (request.readyState !== 4) {
|
||||
return;
|
||||
}
|
||||
request.onreadystatechange = null;
|
||||
postDataToURL.running = (postDataToURL.running || 0) - 1;
|
||||
callback(request.status === 200 ? null : request.status, request.responseText);
|
||||
};
|
||||
request.open('POST', url);
|
||||
request.setRequestHeader('Content-Type', 'application/json');
|
||||
request.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
postDataToURL.defaultCallback = function(error) {
|
||||
// console.log('postDataToURL.defaultCallback', arguments)
|
||||
};
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
var __DEBUG__ = location.search.substring(1).indexOf('debug') !== -1;
|
||||
|
||||
if (typeof console === 'undefined') {
|
||||
console = {
|
||||
log: function() {},
|
||||
warn: function() {},
|
||||
error: function() {},
|
||||
};
|
||||
}
|
||||
|
||||
var __consoleReport__ = [];
|
||||
|
||||
console._log = console.log;
|
||||
console.log = function(message) {
|
||||
console._log(message);
|
||||
if (__DEBUG__) {
|
||||
postDataToURL({type:'log', message:message}, '/reportTestResults');
|
||||
} else {
|
||||
__consoleReport__.push({type:'log', message:message});
|
||||
}
|
||||
};
|
||||
|
||||
console._error = console.error;
|
||||
console.error = function(message) {
|
||||
console._error(message);
|
||||
if (__DEBUG__) {
|
||||
postDataToURL({type:'error', message:message}, '/reportTestResults');
|
||||
} else {
|
||||
__consoleReport__.push({type:'error', message:message});
|
||||
}
|
||||
};
|
||||
|
||||
console._flush = function() {
|
||||
postDataToURL(__consoleReport__, '/console');
|
||||
__consoleReport__.length = 0;
|
||||
};
|
||||
|
||||
(function(env) {
|
||||
env.addReporter(new jasmine.JSReporter());
|
||||
env.addReporter(new TAPReporter(console.log.bind(console)));
|
||||
|
||||
function report() {
|
||||
if (typeof jasmine.getJSReport !== 'function') {
|
||||
return setTimeout(report, 100);
|
||||
}
|
||||
if (!__DEBUG__) {
|
||||
console.log('DONE\t' + navigator.userAgent);
|
||||
console._flush();
|
||||
}
|
||||
}
|
||||
|
||||
var oldCallback = env.currentRunner().finishCallback;
|
||||
env.currentRunner().finishCallback = function() {
|
||||
if (oldCallback) {
|
||||
oldCallback.apply(this, arguments);
|
||||
}
|
||||
report();
|
||||
};
|
||||
|
||||
}(window.jasmine.getEnv()));
|
||||
162
vendor/jasmine-jsreporter/jasmine-jsreporter.js
vendored
162
vendor/jasmine-jsreporter/jasmine-jsreporter.js
vendored
|
|
@ -1,162 +0,0 @@
|
|||
/*
|
||||
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();
|
||||
// If the spec was skipped, reportSpecStarting is never called and spec.startedAt is undefined
|
||||
spec.durationSec = spec.startedAt ? elapsedSec(spec.startedAt.getTime(), spec.finishedAt.getTime()) : 0;
|
||||
},
|
||||
|
||||
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;
|
||||
})();
|
||||
|
||||
168
vendor/jasmine/HtmlReporter.js
vendored
168
vendor/jasmine/HtmlReporter.js
vendored
|
|
@ -1,168 +0,0 @@
|
|||
var jasmine = require("./jasmine");
|
||||
|
||||
exports.HtmlReporter =
|
||||
jasmine.HtmlReporter = function(_doc) {
|
||||
var self = this;
|
||||
var doc = _doc || window.document;
|
||||
|
||||
var reporterView;
|
||||
|
||||
var dom = {};
|
||||
|
||||
// Jasmine Reporter Public Interface
|
||||
self.logRunningSpecs = false;
|
||||
|
||||
self.reportRunnerStarting = function(runner) {
|
||||
var specs = runner.specs() || [];
|
||||
|
||||
if (specs.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
createReporterDom(runner.env.versionString());
|
||||
doc.body.appendChild(dom.reporter);
|
||||
setExceptionHandling();
|
||||
|
||||
reporterView = new jasmine.HtmlReporter.ReporterView(dom);
|
||||
reporterView.addSpecs(specs, self.specFilter);
|
||||
};
|
||||
|
||||
self.reportRunnerResults = function(runner) {
|
||||
reporterView && reporterView.complete();
|
||||
};
|
||||
|
||||
self.reportSuiteResults = function(suite) {
|
||||
reporterView.suiteComplete(suite);
|
||||
};
|
||||
|
||||
self.reportSpecStarting = function(spec) {
|
||||
if (self.logRunningSpecs) {
|
||||
self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
|
||||
}
|
||||
};
|
||||
|
||||
self.reportSpecResults = function(spec) {
|
||||
reporterView.specComplete(spec);
|
||||
};
|
||||
|
||||
self.log = function() {
|
||||
var console = jasmine.getGlobal().console;
|
||||
if (console && console.log) {
|
||||
if (console.log.apply) {
|
||||
console.log.apply(console, arguments);
|
||||
} else {
|
||||
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.specFilter = function(spec) {
|
||||
if (!focusedSpecName()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return spec.getFullName().indexOf(focusedSpecName()) === 0;
|
||||
};
|
||||
|
||||
return self;
|
||||
|
||||
function focusedSpecName() {
|
||||
var specName;
|
||||
|
||||
(function memoizeFocusedSpec() {
|
||||
if (specName) {
|
||||
return;
|
||||
}
|
||||
|
||||
var paramMap = [];
|
||||
var params = jasmine.HtmlReporter.parameters(doc);
|
||||
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var p = params[i].split('=');
|
||||
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
|
||||
}
|
||||
|
||||
specName = paramMap.spec;
|
||||
})();
|
||||
|
||||
return specName;
|
||||
}
|
||||
|
||||
function createReporterDom(version) {
|
||||
dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' },
|
||||
dom.banner = self.createDom('div', { className: 'banner' },
|
||||
self.createDom('span', { className: 'title' }, "Jasmine "),
|
||||
self.createDom('span', { className: 'version' }, version)),
|
||||
|
||||
dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
|
||||
dom.alert = self.createDom('div', {className: 'alert'},
|
||||
self.createDom('span', { className: 'exceptions' },
|
||||
self.createDom('label', { className: 'label', 'for': 'no_try_catch' }, 'No try/catch'),
|
||||
self.createDom('input', { id: 'no_try_catch', type: 'checkbox' }))),
|
||||
dom.results = self.createDom('div', {className: 'results'},
|
||||
dom.summary = self.createDom('div', { className: 'summary' }),
|
||||
dom.details = self.createDom('div', { id: 'details' }))
|
||||
);
|
||||
}
|
||||
|
||||
function noTryCatch() {
|
||||
return window.location.search.match(/catch=false/);
|
||||
}
|
||||
|
||||
function searchWithCatch() {
|
||||
var params = jasmine.HtmlReporter.parameters(window.document);
|
||||
var removed = false;
|
||||
var i = 0;
|
||||
|
||||
while (!removed && i < params.length) {
|
||||
if (params[i].match(/catch=/)) {
|
||||
params.splice(i, 1);
|
||||
removed = true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (jasmine.CATCH_EXCEPTIONS) {
|
||||
params.push("catch=false");
|
||||
}
|
||||
|
||||
return params.join("&");
|
||||
}
|
||||
|
||||
function setExceptionHandling() {
|
||||
var chxCatch = document.getElementById('no_try_catch');
|
||||
|
||||
if (noTryCatch()) {
|
||||
chxCatch.setAttribute('checked', true);
|
||||
jasmine.CATCH_EXCEPTIONS = false;
|
||||
}
|
||||
chxCatch.onclick = function() {
|
||||
window.location.search = searchWithCatch();
|
||||
};
|
||||
}
|
||||
};
|
||||
jasmine.HtmlReporter.parameters = function(doc) {
|
||||
var paramStr = doc.location.search.substring(1);
|
||||
var params = [];
|
||||
|
||||
if (paramStr.length > 0) {
|
||||
params = paramStr.split('&');
|
||||
}
|
||||
return params;
|
||||
}
|
||||
jasmine.HtmlReporter.sectionLink = function(sectionName) {
|
||||
var link = '?';
|
||||
var params = [];
|
||||
|
||||
if (sectionName) {
|
||||
params.push('spec=' + encodeURIComponent(sectionName));
|
||||
}
|
||||
if (!jasmine.CATCH_EXCEPTIONS) {
|
||||
params.push("catch=false");
|
||||
}
|
||||
if (params.length > 0) {
|
||||
link += params.join("&");
|
||||
}
|
||||
|
||||
return link;
|
||||
};
|
||||
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);
|
||||
128
vendor/jasmine/PrintReporter.js
vendored
128
vendor/jasmine/PrintReporter.js
vendored
|
|
@ -1,128 +0,0 @@
|
|||
var jasmine = require("./jasmine");
|
||||
var diff = require('./diff');
|
||||
|
||||
var red = '\u001b[1;41m';
|
||||
var reset = '\u001b[0m';
|
||||
|
||||
function highlightDifferences(a, b) {
|
||||
var changes = diff.diffChars(a, b);
|
||||
|
||||
var ret = {a: '', b: ''};
|
||||
var change;
|
||||
for (var i = 0, il = changes.length; i < il; i++) {
|
||||
change = changes[i];
|
||||
if (change.added) {
|
||||
ret.b += red + change.value + reset;
|
||||
} else if (change.removed) {
|
||||
ret.a += red + change.value + reset;
|
||||
} else {
|
||||
ret.a += change.value;
|
||||
ret.b += change.value;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function PrintReporter(name, root_directory) {
|
||||
this.skipCount = 0;
|
||||
this.failCount = 0;
|
||||
this.expectCount = 0;
|
||||
this.specCount = 0;
|
||||
this.name = name;
|
||||
this.rootDirectory = root_directory;
|
||||
}
|
||||
exports.PrintReporter =
|
||||
jasmine.PrintReporter = PrintReporter;
|
||||
|
||||
PrintReporter.prototype = new jasmine.Reporter();
|
||||
// Set verbose=true on the test instance to enable additional logging
|
||||
PrintReporter.prototype.verbose = false;
|
||||
PrintReporter.prototype._didSpecName = false;
|
||||
|
||||
PrintReporter.prototype.reportSpecStarting = function(spec) {
|
||||
this._didSpecName = false;
|
||||
this._spec = spec;
|
||||
};
|
||||
|
||||
PrintReporter.prototype.reportRunnerResults = function(runner) {
|
||||
// Don't print out the spec name at the end
|
||||
this._didSpecName = true;
|
||||
|
||||
this.log([
|
||||
this.specCount + " spec",
|
||||
this.expectCount + " expect",
|
||||
this.skipCount + " skip",
|
||||
this.failCount + " fail"
|
||||
].join(" "));
|
||||
|
||||
require("./phantom").exit(this.failCount);
|
||||
};
|
||||
|
||||
|
||||
PrintReporter.prototype.reportSuiteResults = function(suite) {
|
||||
var results = suite.results();
|
||||
if (this.verbose) {
|
||||
this.log('Suite "' + suite.description + '": ' +
|
||||
results.passedCount + '/' + results.totalCount + ' passed.');
|
||||
}
|
||||
|
||||
// If suite is nested, only count the root suite
|
||||
if (!suite.parentSuite) {
|
||||
this.failCount += results.totalCount - results.passedCount;
|
||||
this.expectCount += results.totalCount;
|
||||
}
|
||||
};
|
||||
|
||||
PrintReporter.prototype.reportSpecResults = function(spec) {
|
||||
if (this.verbose) {
|
||||
this.log('it... ' +
|
||||
spec.description + ': ' + (spec.results().passed() ? 'pass' : 'fail'));
|
||||
}
|
||||
|
||||
var self = this;
|
||||
var results = spec.results();
|
||||
|
||||
this.specCount += 1;
|
||||
|
||||
if (results.skipped)
|
||||
this.skipCount += 1;
|
||||
|
||||
results.getItems().forEach(function(result) {
|
||||
if (result.type == 'log') {
|
||||
self.log(result.toString());
|
||||
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
||||
var ppActual = jasmine.pp(result.actual);
|
||||
var ppExpected = jasmine.pp(result.expected);
|
||||
|
||||
var colorDiff = highlightDifferences(ppActual, ppExpected);
|
||||
|
||||
var message = result.message;
|
||||
message = message.replace(ppActual, colorDiff.a);
|
||||
message = message.replace(ppExpected, colorDiff.b);
|
||||
|
||||
self.log(message);
|
||||
if (result.trace.stack) {
|
||||
self.log();
|
||||
result.trace.stack.split('\n').forEach(function(stackFrame) {
|
||||
if (stackFrame.indexOf('/jasmine/lib/jasmine-core') > -1) {
|
||||
return;
|
||||
}
|
||||
if (this.rootDirectory) {
|
||||
stackFrame = stackFrame.replace(this.rootDirectory + '/', '');
|
||||
}
|
||||
self.log(' ' + stackFrame);
|
||||
}.bind(this));
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
PrintReporter.prototype.log = function(str) {
|
||||
if (!this._didSpecName) {
|
||||
console.log('');
|
||||
console.log(
|
||||
this._spec.suite.description + ': it ' + this._spec.description);
|
||||
this._didSpecName = true;
|
||||
}
|
||||
console.log(str || '');
|
||||
};
|
||||
166
vendor/jasmine/ReporterView.js
vendored
166
vendor/jasmine/ReporterView.js
vendored
|
|
@ -1,166 +0,0 @@
|
|||
var jasmine = require("jasmine");
|
||||
|
||||
jasmine.HtmlReporter.ReporterView = function(dom) {
|
||||
this.startedAt = new Date();
|
||||
this.runningSpecCount = 0;
|
||||
this.completeSpecCount = 0;
|
||||
this.passedCount = 0;
|
||||
this.failedCount = 0;
|
||||
this.skippedCount = 0;
|
||||
|
||||
this.createResultsMenu = function() {
|
||||
this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'},
|
||||
this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'),
|
||||
' | ',
|
||||
this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing'));
|
||||
|
||||
this.summaryMenuItem.onclick = function() {
|
||||
dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, '');
|
||||
};
|
||||
|
||||
this.detailsMenuItem.onclick = function() {
|
||||
showDetails();
|
||||
};
|
||||
};
|
||||
|
||||
this.addSpecs = function(specs, specFilter) {
|
||||
this.totalSpecCount = specs.length;
|
||||
|
||||
this.views = {
|
||||
specs: {},
|
||||
suites: {}
|
||||
};
|
||||
|
||||
for (var i = 0; i < specs.length; i++) {
|
||||
var spec = specs[i];
|
||||
this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views);
|
||||
if (specFilter(spec)) {
|
||||
this.runningSpecCount++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.specComplete = function(spec) {
|
||||
this.completeSpecCount++;
|
||||
|
||||
if (isUndefined(this.views.specs[spec.id])) {
|
||||
this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom);
|
||||
}
|
||||
|
||||
var specView = this.views.specs[spec.id];
|
||||
|
||||
switch (specView.status()) {
|
||||
case 'passed':
|
||||
this.passedCount++;
|
||||
break;
|
||||
|
||||
case 'failed':
|
||||
this.failedCount++;
|
||||
break;
|
||||
|
||||
case 'skipped':
|
||||
this.skippedCount++;
|
||||
break;
|
||||
}
|
||||
|
||||
specView.refresh();
|
||||
this.refresh();
|
||||
};
|
||||
|
||||
this.suiteComplete = function(suite) {
|
||||
var suiteView = this.views.suites[suite.id];
|
||||
if (isUndefined(suiteView)) {
|
||||
return;
|
||||
}
|
||||
suiteView.refresh();
|
||||
};
|
||||
|
||||
this.refresh = function() {
|
||||
|
||||
if (isUndefined(this.resultsMenu)) {
|
||||
this.createResultsMenu();
|
||||
}
|
||||
|
||||
// currently running UI
|
||||
if (isUndefined(this.runningAlert)) {
|
||||
this.runningAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "runningAlert bar" });
|
||||
dom.alert.appendChild(this.runningAlert);
|
||||
}
|
||||
this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount);
|
||||
|
||||
// skipped specs UI
|
||||
if (isUndefined(this.skippedAlert)) {
|
||||
this.skippedAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "skippedAlert bar" });
|
||||
}
|
||||
|
||||
this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
|
||||
|
||||
if (this.skippedCount === 1 && isDefined(dom.alert)) {
|
||||
dom.alert.appendChild(this.skippedAlert);
|
||||
}
|
||||
|
||||
// passing specs UI
|
||||
if (isUndefined(this.passedAlert)) {
|
||||
this.passedAlert = this.createDom('span', { href: jasmine.HtmlReporter.sectionLink(), className: "passingAlert bar" });
|
||||
}
|
||||
this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount);
|
||||
|
||||
// failing specs UI
|
||||
if (isUndefined(this.failedAlert)) {
|
||||
this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"});
|
||||
}
|
||||
this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount);
|
||||
|
||||
if (this.failedCount === 1 && isDefined(dom.alert)) {
|
||||
dom.alert.appendChild(this.failedAlert);
|
||||
dom.alert.appendChild(this.resultsMenu);
|
||||
}
|
||||
|
||||
// summary info
|
||||
this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount);
|
||||
this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing";
|
||||
};
|
||||
|
||||
this.complete = function() {
|
||||
dom.alert.removeChild(this.runningAlert);
|
||||
|
||||
this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
|
||||
|
||||
if (this.failedCount === 0) {
|
||||
dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount)));
|
||||
} else {
|
||||
showDetails();
|
||||
}
|
||||
|
||||
dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"));
|
||||
};
|
||||
|
||||
return this;
|
||||
|
||||
function showDetails() {
|
||||
if (dom.reporter.className.search(/showDetails/) === -1) {
|
||||
dom.reporter.className += " showDetails";
|
||||
}
|
||||
}
|
||||
|
||||
function isUndefined(obj) {
|
||||
return typeof obj === 'undefined';
|
||||
}
|
||||
|
||||
function isDefined(obj) {
|
||||
return !isUndefined(obj);
|
||||
}
|
||||
|
||||
function specPluralizedFor(count) {
|
||||
var str = count + " spec";
|
||||
if (count > 1) {
|
||||
str += "s"
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView);
|
||||
|
||||
|
||||
81
vendor/jasmine/SpecView.js
vendored
81
vendor/jasmine/SpecView.js
vendored
|
|
@ -1,81 +0,0 @@
|
|||
var jasmine = require("./jasmine");
|
||||
|
||||
jasmine.HtmlReporter.SpecView = function(spec, dom, views) {
|
||||
this.spec = spec;
|
||||
this.dom = dom;
|
||||
this.views = views;
|
||||
|
||||
this.symbol = this.createDom('li', { className: 'pending' });
|
||||
this.dom.symbolSummary.appendChild(this.symbol);
|
||||
|
||||
this.summary = this.createDom('div', { className: 'specSummary' },
|
||||
this.createDom('a', {
|
||||
className: 'description',
|
||||
href: jasmine.HtmlReporter.sectionLink(this.spec.getFullName()),
|
||||
title: this.spec.getFullName()
|
||||
}, this.spec.description)
|
||||
);
|
||||
|
||||
this.detail = this.createDom('div', { className: 'specDetail' },
|
||||
this.createDom('a', {
|
||||
className: 'description',
|
||||
href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
|
||||
title: this.spec.getFullName()
|
||||
}, this.spec.getFullName())
|
||||
);
|
||||
};
|
||||
|
||||
jasmine.HtmlReporter.SpecView.prototype.status = function() {
|
||||
return this.getSpecStatus(this.spec);
|
||||
};
|
||||
|
||||
jasmine.HtmlReporter.SpecView.prototype.refresh = function() {
|
||||
this.symbol.className = this.status();
|
||||
|
||||
switch (this.status()) {
|
||||
case 'skipped':
|
||||
break;
|
||||
|
||||
case 'passed':
|
||||
this.appendSummaryToSuiteDiv();
|
||||
break;
|
||||
|
||||
case 'failed':
|
||||
this.appendSummaryToSuiteDiv();
|
||||
this.appendFailureDetail();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() {
|
||||
this.summary.className += ' ' + this.status();
|
||||
this.appendToSummary(this.spec, this.summary);
|
||||
};
|
||||
|
||||
jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() {
|
||||
this.detail.className += ' ' + this.status();
|
||||
|
||||
var resultItems = this.spec.results().getItems();
|
||||
var messagesDiv = this.createDom('div', { className: 'messages' });
|
||||
|
||||
for (var i = 0; i < resultItems.length; i++) {
|
||||
var result = resultItems[i];
|
||||
|
||||
if (result.type == 'log') {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
|
||||
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
|
||||
|
||||
if (result.trace.stack) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (messagesDiv.childNodes.length > 0) {
|
||||
this.detail.appendChild(messagesDiv);
|
||||
this.dom.details.appendChild(this.detail);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);
|
||||
24
vendor/jasmine/SuiteView.js
vendored
24
vendor/jasmine/SuiteView.js
vendored
|
|
@ -1,24 +0,0 @@
|
|||
var jasmine = require("./jasmine");
|
||||
|
||||
jasmine.HtmlReporter.SuiteView = function(suite, dom, views) {
|
||||
this.suite = suite;
|
||||
this.dom = dom;
|
||||
this.views = views;
|
||||
|
||||
this.element = this.createDom('div', { className: 'suite' },
|
||||
this.createDom('a', { className: 'description', href: jasmine.HtmlReporter.sectionLink(this.suite.getFullName()) }, this.suite.description)
|
||||
);
|
||||
|
||||
this.appendToSummary(this.suite, this.element);
|
||||
};
|
||||
|
||||
jasmine.HtmlReporter.SuiteView.prototype.status = function() {
|
||||
return this.getSpecStatus(this.suite);
|
||||
};
|
||||
|
||||
jasmine.HtmlReporter.SuiteView.prototype.refresh = function() {
|
||||
this.element.className += " " + this.status();
|
||||
};
|
||||
|
||||
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView);
|
||||
|
||||
38
vendor/jasmine/all.js
vendored
38
vendor/jasmine/all.js
vendored
|
|
@ -1,38 +0,0 @@
|
|||
require("./phantom");
|
||||
require("./console");
|
||||
|
||||
// TODO Also bundle jasmine.css here.
|
||||
var jasmine = require("./jasmine");
|
||||
require("./jasmine-html");
|
||||
require("./jasmine-support");
|
||||
|
||||
require("./HtmlReporter");
|
||||
require("./PrintReporter");
|
||||
require("./ReporterView");
|
||||
require("./SpecView");
|
||||
require("./SuiteView");
|
||||
|
||||
var env = jasmine.getEnv();
|
||||
env.addReporter(new jasmine.HtmlReporter);
|
||||
env.addReporter(new jasmine.PrintReporter);
|
||||
|
||||
function exposeFrom(obj) {
|
||||
obj.spyOn = jasmine.spyOn;
|
||||
obj.it = jasmine.it;
|
||||
obj.xit = jasmine.xit;
|
||||
obj.expect = jasmine.expect;
|
||||
obj.runs = jasmine.runs;
|
||||
obj.waits = jasmine.waits;
|
||||
obj.waitsFor = jasmine.waitsFor;
|
||||
obj.beforeEach = jasmine.beforeEach;
|
||||
obj.afterEach = jasmine.afterEach;
|
||||
obj.describe = jasmine.describe;
|
||||
obj.xdescribe = jasmine.xdescribe;
|
||||
obj.jasmine = jasmine;
|
||||
return obj;
|
||||
}
|
||||
jasmine.exposeFrom = exposeFrom;
|
||||
var global = Function("return this")();
|
||||
exposeFrom(global);
|
||||
|
||||
module.exports = jasmine;
|
||||
85
vendor/jasmine/console.js
vendored
85
vendor/jasmine/console.js
vendored
|
|
@ -1,85 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2015, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* This module allows interception of console.* method calls, so that
|
||||
* listeners other than the native console object can consume logged
|
||||
* messages.
|
||||
*/
|
||||
|
||||
var global = Function("return this")();
|
||||
var Ap = Array.prototype;
|
||||
var slice = Ap.slice;
|
||||
|
||||
var nativeConsole;
|
||||
if ("console" in global) {
|
||||
var gc = global.console;
|
||||
try { delete global.console } catch (ignored) {}
|
||||
nativeConsole = global.console || gc;
|
||||
global.console = gc;
|
||||
}
|
||||
|
||||
// Provide a reliable console interface in all browsers.
|
||||
global.console = exports;
|
||||
|
||||
function makeLogger(method) {
|
||||
var logger = exports[method] = function() {
|
||||
var args = slice.call(arguments);
|
||||
listeners.forEach(function(listener) {
|
||||
listener(method, args, logger);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
makeLogger("info");
|
||||
makeLogger("log");
|
||||
makeLogger("debug");
|
||||
makeLogger("warn");
|
||||
makeLogger("error");
|
||||
makeLogger("dir");
|
||||
makeLogger("dirxml");
|
||||
makeLogger("trace");
|
||||
makeLogger("assert");
|
||||
makeLogger("count");
|
||||
makeLogger("markTimeline");
|
||||
makeLogger("profile");
|
||||
makeLogger("profileEnd");
|
||||
makeLogger("time");
|
||||
makeLogger("timeEnd");
|
||||
makeLogger("timeStamp");
|
||||
makeLogger("group");
|
||||
makeLogger("groupCollapsed");
|
||||
makeLogger("groupEnd");
|
||||
makeLogger("clear");
|
||||
|
||||
var listeners = [];
|
||||
function addListener(listener) {
|
||||
listeners.push(listener);
|
||||
}
|
||||
exports.addListener = addListener
|
||||
|
||||
function clean(arg) {
|
||||
if (typeof arg === "string") {
|
||||
// Remove any xterm-color escape sequences.
|
||||
// TODO Display colors in console if possible.
|
||||
arg = arg.replace(/\033\[\d+m/g, "");
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
|
||||
if (nativeConsole) {
|
||||
// If present, the native console object becomes a listener just like
|
||||
// any other.
|
||||
addListener(function(method, args) {
|
||||
var method = nativeConsole[method];
|
||||
if (method) {
|
||||
method.apply(nativeConsole, args.map(clean));
|
||||
} else {
|
||||
// Ignore this call.
|
||||
}
|
||||
});
|
||||
}
|
||||
349
vendor/jasmine/diff.js
vendored
349
vendor/jasmine/diff.js
vendored
|
|
@ -1,349 +0,0 @@
|
|||
/* See LICENSE file for terms of use */
|
||||
|
||||
/*
|
||||
* Text diff implementation.
|
||||
*
|
||||
* This library supports the following APIS:
|
||||
* JsDiff.diffChars: Character by character diff
|
||||
* JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace
|
||||
* JsDiff.diffLines: Line based diff
|
||||
*
|
||||
* JsDiff.diffCss: Diff targeted at CSS content
|
||||
*
|
||||
* These methods are based on the implementation proposed in
|
||||
* "An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
|
||||
* http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
|
||||
*/
|
||||
var JsDiff = (function() {
|
||||
function clonePath(path) {
|
||||
return { newPos: path.newPos, components: path.components.slice(0) };
|
||||
}
|
||||
function removeEmpty(array) {
|
||||
var ret = [];
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
if (array[i]) {
|
||||
ret.push(array[i]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
function escapeHTML(s) {
|
||||
var n = s;
|
||||
n = n.replace(/&/g, "&");
|
||||
n = n.replace(/</g, "<");
|
||||
n = n.replace(/>/g, ">");
|
||||
n = n.replace(/"/g, """);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
var fbDiff = function(ignoreWhitespace) {
|
||||
this.ignoreWhitespace = ignoreWhitespace;
|
||||
};
|
||||
fbDiff.prototype = {
|
||||
diff: function(oldString, newString) {
|
||||
// Handle the identity case (this is due to unrolling editLength == 0
|
||||
if (newString == oldString) {
|
||||
return [{ value: newString }];
|
||||
}
|
||||
if (!newString) {
|
||||
return [{ value: oldString, removed: true }];
|
||||
}
|
||||
if (!oldString) {
|
||||
return [{ value: newString, added: true }];
|
||||
}
|
||||
|
||||
newString = this.tokenize(newString);
|
||||
oldString = this.tokenize(oldString);
|
||||
|
||||
var newLen = newString.length, oldLen = oldString.length;
|
||||
var maxEditLength = newLen + oldLen;
|
||||
var bestPath = [{ newPos: -1, components: [] }];
|
||||
|
||||
// Seed editLength = 0
|
||||
var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
|
||||
if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) {
|
||||
return bestPath[0].components;
|
||||
}
|
||||
|
||||
for (var editLength = 1; editLength <= maxEditLength; editLength++) {
|
||||
for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) {
|
||||
var basePath;
|
||||
var addPath = bestPath[diagonalPath-1],
|
||||
removePath = bestPath[diagonalPath+1];
|
||||
oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
|
||||
if (addPath) {
|
||||
// No one else is going to attempt to use this value, clear it
|
||||
bestPath[diagonalPath-1] = undefined;
|
||||
}
|
||||
|
||||
var canAdd = addPath && addPath.newPos+1 < newLen;
|
||||
var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;
|
||||
if (!canAdd && !canRemove) {
|
||||
bestPath[diagonalPath] = undefined;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Select the diagonal that we want to branch from. We select the prior
|
||||
// path whose position in the new string is the farthest from the origin
|
||||
// and does not pass the bounds of the diff graph
|
||||
if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) {
|
||||
basePath = clonePath(removePath);
|
||||
this.pushComponent(basePath.components, oldString[oldPos], undefined, true);
|
||||
} else {
|
||||
basePath = clonePath(addPath);
|
||||
basePath.newPos++;
|
||||
this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined);
|
||||
}
|
||||
|
||||
var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath);
|
||||
|
||||
if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) {
|
||||
return basePath.components;
|
||||
} else {
|
||||
bestPath[diagonalPath] = basePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
pushComponent: function(components, value, added, removed) {
|
||||
var last = components[components.length-1];
|
||||
if (last && last.added === added && last.removed === removed) {
|
||||
// We need to clone here as the component clone operation is just
|
||||
// as shallow array clone
|
||||
components[components.length-1] =
|
||||
{value: this.join(last.value, value), added: added, removed: removed };
|
||||
} else {
|
||||
components.push({value: value, added: added, removed: removed });
|
||||
}
|
||||
},
|
||||
extractCommon: function(basePath, newString, oldString, diagonalPath) {
|
||||
var newLen = newString.length,
|
||||
oldLen = oldString.length,
|
||||
newPos = basePath.newPos,
|
||||
oldPos = newPos - diagonalPath;
|
||||
while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) {
|
||||
newPos++;
|
||||
oldPos++;
|
||||
|
||||
this.pushComponent(basePath.components, newString[newPos], undefined, undefined);
|
||||
}
|
||||
basePath.newPos = newPos;
|
||||
return oldPos;
|
||||
},
|
||||
|
||||
equals: function(left, right) {
|
||||
var reWhitespace = /\S/;
|
||||
if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) {
|
||||
return true;
|
||||
} else {
|
||||
return left == right;
|
||||
}
|
||||
},
|
||||
join: function(left, right) {
|
||||
return left + right;
|
||||
},
|
||||
tokenize: function(value) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
var CharDiff = new fbDiff();
|
||||
|
||||
var WordDiff = new fbDiff(true);
|
||||
WordDiff.tokenize = function(value) {
|
||||
return removeEmpty(value.split(/(\s+|\b)/));
|
||||
};
|
||||
|
||||
var CssDiff = new fbDiff(true);
|
||||
CssDiff.tokenize = function(value) {
|
||||
return removeEmpty(value.split(/([{}:;,]|\s+)/));
|
||||
};
|
||||
|
||||
var LineDiff = new fbDiff();
|
||||
LineDiff.tokenize = function(value) {
|
||||
return value.split(/^/m);
|
||||
};
|
||||
|
||||
return {
|
||||
diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); },
|
||||
diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); },
|
||||
diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); },
|
||||
|
||||
diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); },
|
||||
|
||||
createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) {
|
||||
var ret = [];
|
||||
|
||||
ret.push("Index: " + fileName);
|
||||
ret.push("===================================================================");
|
||||
ret.push("--- " + fileName + (typeof oldHeader === "undefined" ? "" : "\t" + oldHeader));
|
||||
ret.push("+++ " + fileName + (typeof newHeader === "undefined" ? "" : "\t" + newHeader));
|
||||
|
||||
var diff = LineDiff.diff(oldStr, newStr);
|
||||
if (!diff[diff.length-1].value) {
|
||||
diff.pop(); // Remove trailing newline add
|
||||
}
|
||||
diff.push({value: "", lines: []}); // Append an empty value to make cleanup easier
|
||||
|
||||
function contextLines(lines) {
|
||||
return lines.map(function(entry) { return ' ' + entry; });
|
||||
}
|
||||
function eofNL(curRange, i, current) {
|
||||
var last = diff[diff.length-2],
|
||||
isLast = i === diff.length-2,
|
||||
isLastOfType = i === diff.length-3 && (current.added !== last.added || current.removed !== last.removed);
|
||||
|
||||
// Figure out if this is the last line for the given file and missing NL
|
||||
if (!/\n$/.test(current.value) && (isLast || isLastOfType)) {
|
||||
curRange.push('\\ No newline at end of file');
|
||||
}
|
||||
}
|
||||
|
||||
var oldRangeStart = 0, newRangeStart = 0, curRange = [],
|
||||
oldLine = 1, newLine = 1;
|
||||
for (var i = 0; i < diff.length; i++) {
|
||||
var current = diff[i],
|
||||
lines = current.lines || current.value.replace(/\n$/, "").split("\n");
|
||||
current.lines = lines;
|
||||
|
||||
if (current.added || current.removed) {
|
||||
if (!oldRangeStart) {
|
||||
var prev = diff[i-1];
|
||||
oldRangeStart = oldLine;
|
||||
newRangeStart = newLine;
|
||||
|
||||
if (prev) {
|
||||
curRange = contextLines(prev.lines.slice(-4));
|
||||
oldRangeStart -= curRange.length;
|
||||
newRangeStart -= curRange.length;
|
||||
}
|
||||
}
|
||||
curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?"+":"-") + entry; }));
|
||||
eofNL(curRange, i, current);
|
||||
|
||||
if (current.added) {
|
||||
newLine += lines.length;
|
||||
} else {
|
||||
oldLine += lines.length;
|
||||
}
|
||||
} else {
|
||||
if (oldRangeStart) {
|
||||
// Close out any changes that have been output (or join overlapping)
|
||||
if (lines.length <= 8 && i < diff.length-2) {
|
||||
// Overlapping
|
||||
curRange.push.apply(curRange, contextLines(lines));
|
||||
} else {
|
||||
// end the range and output
|
||||
var contextSize = Math.min(lines.length, 4);
|
||||
ret.push(
|
||||
"@@ -" + oldRangeStart + "," + (oldLine-oldRangeStart+contextSize)
|
||||
+ " +" + newRangeStart + "," + (newLine-newRangeStart+contextSize)
|
||||
+ " @@");
|
||||
ret.push.apply(ret, curRange);
|
||||
ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));
|
||||
if (lines.length <= 4) {
|
||||
eofNL(ret, i, current);
|
||||
}
|
||||
|
||||
oldRangeStart = 0; newRangeStart = 0; curRange = [];
|
||||
}
|
||||
}
|
||||
oldLine += lines.length;
|
||||
newLine += lines.length;
|
||||
}
|
||||
}
|
||||
|
||||
return ret.join('\n') + '\n';
|
||||
},
|
||||
|
||||
applyPatch: function(oldStr, uniDiff) {
|
||||
var diffstr = uniDiff.split("\n");
|
||||
var diff = [];
|
||||
var remEOFNL = false,
|
||||
addEOFNL = false;
|
||||
|
||||
for (var i = (diffstr[0][0]=="I"?4:0); i < diffstr.length; i++) {
|
||||
if(diffstr[i][0] == "@") {
|
||||
var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
|
||||
diff.unshift({
|
||||
start:meh[3],
|
||||
oldlength:meh[2],
|
||||
oldlines:[],
|
||||
newlength:meh[4],
|
||||
newlines:[]
|
||||
});
|
||||
} else if(diffstr[i][0] == '+') {
|
||||
diff[0].newlines.push(diffstr[i].substr(1));
|
||||
} else if(diffstr[i][0] == '-') {
|
||||
diff[0].oldlines.push(diffstr[i].substr(1));
|
||||
} else if(diffstr[i][0] == ' ') {
|
||||
diff[0].newlines.push(diffstr[i].substr(1));
|
||||
diff[0].oldlines.push(diffstr[i].substr(1));
|
||||
} else if(diffstr[i][0] == '\\') {
|
||||
if (diffstr[i-1][0] == '+') {
|
||||
remEOFNL = true;
|
||||
} else if(diffstr[i-1][0] == '-') {
|
||||
addEOFNL = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var str = oldStr.split("\n");
|
||||
for (var i = diff.length - 1; i >= 0; i--) {
|
||||
var d = diff[i];
|
||||
for (var j = 0; j < d.oldlength; j++) {
|
||||
if(str[d.start-1+j] != d.oldlines[j]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines));
|
||||
}
|
||||
|
||||
if (remEOFNL) {
|
||||
while (!str[str.length-1]) {
|
||||
str.pop();
|
||||
}
|
||||
} else if (addEOFNL) {
|
||||
str.push('');
|
||||
}
|
||||
return str.join('\n');
|
||||
},
|
||||
|
||||
convertChangesToXML: function(changes){
|
||||
var ret = [];
|
||||
for ( var i = 0; i < changes.length; i++) {
|
||||
var change = changes[i];
|
||||
if (change.added) {
|
||||
ret.push("<ins>");
|
||||
} else if (change.removed) {
|
||||
ret.push("<del>");
|
||||
}
|
||||
|
||||
ret.push(escapeHTML(change.value));
|
||||
|
||||
if (change.added) {
|
||||
ret.push("</ins>");
|
||||
} else if (change.removed) {
|
||||
ret.push("</del>");
|
||||
}
|
||||
}
|
||||
return ret.join("");
|
||||
},
|
||||
|
||||
// See: http://code.google.com/p/google-diff-match-patch/wiki/API
|
||||
convertChangesToDMP: function(changes){
|
||||
var ret = [], change;
|
||||
for ( var i = 0; i < changes.length; i++) {
|
||||
change = changes[i];
|
||||
ret.push([(change.added ? 1 : change.removed ? -1 : 0), change.value]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
if (typeof module !== "undefined") {
|
||||
module.exports = JsDiff;
|
||||
}
|
||||
681
vendor/jasmine/jasmine-html.js
vendored
681
vendor/jasmine/jasmine-html.js
vendored
|
|
@ -1,681 +0,0 @@
|
|||
jasmine.HtmlReporterHelpers = {};
|
||||
|
||||
jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) {
|
||||
var el = document.createElement(type);
|
||||
|
||||
for (var i = 2; i < arguments.length; i++) {
|
||||
var child = arguments[i];
|
||||
|
||||
if (typeof child === 'string') {
|
||||
el.appendChild(document.createTextNode(child));
|
||||
} else {
|
||||
if (child) {
|
||||
el.appendChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var attr in attrs) {
|
||||
if (attr == "className") {
|
||||
el[attr] = attrs[attr];
|
||||
} else {
|
||||
el.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
jasmine.HtmlReporterHelpers.getSpecStatus = function(child) {
|
||||
var results = child.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.skipped) {
|
||||
status = 'skipped';
|
||||
}
|
||||
|
||||
return status;
|
||||
};
|
||||
|
||||
jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) {
|
||||
var parentDiv = this.dom.summary;
|
||||
var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite';
|
||||
var parent = child[parentSuite];
|
||||
|
||||
if (parent) {
|
||||
if (typeof this.views.suites[parent.id] == 'undefined') {
|
||||
this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views);
|
||||
}
|
||||
parentDiv = this.views.suites[parent.id].element;
|
||||
}
|
||||
|
||||
parentDiv.appendChild(childElement);
|
||||
};
|
||||
|
||||
|
||||
jasmine.HtmlReporterHelpers.addHelpers = function(ctor) {
|
||||
for(var fn in jasmine.HtmlReporterHelpers) {
|
||||
ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn];
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.HtmlReporter = function(_doc) {
|
||||
var self = this;
|
||||
var doc = _doc || window.document;
|
||||
|
||||
var reporterView;
|
||||
|
||||
var dom = {};
|
||||
|
||||
// Jasmine Reporter Public Interface
|
||||
self.logRunningSpecs = false;
|
||||
|
||||
self.reportRunnerStarting = function(runner) {
|
||||
var specs = runner.specs() || [];
|
||||
|
||||
if (specs.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
createReporterDom(runner.env.versionString());
|
||||
doc.body.appendChild(dom.reporter);
|
||||
setExceptionHandling();
|
||||
|
||||
reporterView = new jasmine.HtmlReporter.ReporterView(dom);
|
||||
reporterView.addSpecs(specs, self.specFilter);
|
||||
};
|
||||
|
||||
self.reportRunnerResults = function(runner) {
|
||||
reporterView && reporterView.complete();
|
||||
};
|
||||
|
||||
self.reportSuiteResults = function(suite) {
|
||||
reporterView.suiteComplete(suite);
|
||||
};
|
||||
|
||||
self.reportSpecStarting = function(spec) {
|
||||
if (self.logRunningSpecs) {
|
||||
self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
|
||||
}
|
||||
};
|
||||
|
||||
self.reportSpecResults = function(spec) {
|
||||
reporterView.specComplete(spec);
|
||||
};
|
||||
|
||||
self.log = function() {
|
||||
var console = jasmine.getGlobal().console;
|
||||
if (console && console.log) {
|
||||
if (console.log.apply) {
|
||||
console.log.apply(console, arguments);
|
||||
} else {
|
||||
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.specFilter = function(spec) {
|
||||
if (!focusedSpecName()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return spec.getFullName().indexOf(focusedSpecName()) === 0;
|
||||
};
|
||||
|
||||
return self;
|
||||
|
||||
function focusedSpecName() {
|
||||
var specName;
|
||||
|
||||
(function memoizeFocusedSpec() {
|
||||
if (specName) {
|
||||
return;
|
||||
}
|
||||
|
||||
var paramMap = [];
|
||||
var params = jasmine.HtmlReporter.parameters(doc);
|
||||
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var p = params[i].split('=');
|
||||
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
|
||||
}
|
||||
|
||||
specName = paramMap.spec;
|
||||
})();
|
||||
|
||||
return specName;
|
||||
}
|
||||
|
||||
function createReporterDom(version) {
|
||||
dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' },
|
||||
dom.banner = self.createDom('div', { className: 'banner' },
|
||||
self.createDom('span', { className: 'title' }, "Jasmine "),
|
||||
self.createDom('span', { className: 'version' }, version)),
|
||||
|
||||
dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
|
||||
dom.alert = self.createDom('div', {className: 'alert'},
|
||||
self.createDom('span', { className: 'exceptions' },
|
||||
self.createDom('label', { className: 'label', 'for': 'no_try_catch' }, 'No try/catch'),
|
||||
self.createDom('input', { id: 'no_try_catch', type: 'checkbox' }))),
|
||||
dom.results = self.createDom('div', {className: 'results'},
|
||||
dom.summary = self.createDom('div', { className: 'summary' }),
|
||||
dom.details = self.createDom('div', { id: 'details' }))
|
||||
);
|
||||
}
|
||||
|
||||
function noTryCatch() {
|
||||
return window.location.search.match(/catch=false/);
|
||||
}
|
||||
|
||||
function searchWithCatch() {
|
||||
var params = jasmine.HtmlReporter.parameters(window.document);
|
||||
var removed = false;
|
||||
var i = 0;
|
||||
|
||||
while (!removed && i < params.length) {
|
||||
if (params[i].match(/catch=/)) {
|
||||
params.splice(i, 1);
|
||||
removed = true;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if (jasmine.CATCH_EXCEPTIONS) {
|
||||
params.push("catch=false");
|
||||
}
|
||||
|
||||
return params.join("&");
|
||||
}
|
||||
|
||||
function setExceptionHandling() {
|
||||
var chxCatch = document.getElementById('no_try_catch');
|
||||
|
||||
if (noTryCatch()) {
|
||||
chxCatch.setAttribute('checked', true);
|
||||
jasmine.CATCH_EXCEPTIONS = false;
|
||||
}
|
||||
chxCatch.onclick = function() {
|
||||
window.location.search = searchWithCatch();
|
||||
};
|
||||
}
|
||||
};
|
||||
jasmine.HtmlReporter.parameters = function(doc) {
|
||||
var paramStr = doc.location.search.substring(1);
|
||||
var params = [];
|
||||
|
||||
if (paramStr.length > 0) {
|
||||
params = paramStr.split('&');
|
||||
}
|
||||
return params;
|
||||
}
|
||||
jasmine.HtmlReporter.sectionLink = function(sectionName) {
|
||||
var link = '?';
|
||||
var params = [];
|
||||
|
||||
if (sectionName) {
|
||||
params.push('spec=' + encodeURIComponent(sectionName));
|
||||
}
|
||||
if (!jasmine.CATCH_EXCEPTIONS) {
|
||||
params.push("catch=false");
|
||||
}
|
||||
if (params.length > 0) {
|
||||
link += params.join("&");
|
||||
}
|
||||
|
||||
return link;
|
||||
};
|
||||
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);
|
||||
jasmine.HtmlReporter.ReporterView = function(dom) {
|
||||
this.startedAt = new Date();
|
||||
this.runningSpecCount = 0;
|
||||
this.completeSpecCount = 0;
|
||||
this.passedCount = 0;
|
||||
this.failedCount = 0;
|
||||
this.skippedCount = 0;
|
||||
|
||||
this.createResultsMenu = function() {
|
||||
this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'},
|
||||
this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'),
|
||||
' | ',
|
||||
this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing'));
|
||||
|
||||
this.summaryMenuItem.onclick = function() {
|
||||
dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, '');
|
||||
};
|
||||
|
||||
this.detailsMenuItem.onclick = function() {
|
||||
showDetails();
|
||||
};
|
||||
};
|
||||
|
||||
this.addSpecs = function(specs, specFilter) {
|
||||
this.totalSpecCount = specs.length;
|
||||
|
||||
this.views = {
|
||||
specs: {},
|
||||
suites: {}
|
||||
};
|
||||
|
||||
for (var i = 0; i < specs.length; i++) {
|
||||
var spec = specs[i];
|
||||
this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views);
|
||||
if (specFilter(spec)) {
|
||||
this.runningSpecCount++;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.specComplete = function(spec) {
|
||||
this.completeSpecCount++;
|
||||
|
||||
if (isUndefined(this.views.specs[spec.id])) {
|
||||
this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom);
|
||||
}
|
||||
|
||||
var specView = this.views.specs[spec.id];
|
||||
|
||||
switch (specView.status()) {
|
||||
case 'passed':
|
||||
this.passedCount++;
|
||||
break;
|
||||
|
||||
case 'failed':
|
||||
this.failedCount++;
|
||||
break;
|
||||
|
||||
case 'skipped':
|
||||
this.skippedCount++;
|
||||
break;
|
||||
}
|
||||
|
||||
specView.refresh();
|
||||
this.refresh();
|
||||
};
|
||||
|
||||
this.suiteComplete = function(suite) {
|
||||
var suiteView = this.views.suites[suite.id];
|
||||
if (isUndefined(suiteView)) {
|
||||
return;
|
||||
}
|
||||
suiteView.refresh();
|
||||
};
|
||||
|
||||
this.refresh = function() {
|
||||
|
||||
if (isUndefined(this.resultsMenu)) {
|
||||
this.createResultsMenu();
|
||||
}
|
||||
|
||||
// currently running UI
|
||||
if (isUndefined(this.runningAlert)) {
|
||||
this.runningAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "runningAlert bar" });
|
||||
dom.alert.appendChild(this.runningAlert);
|
||||
}
|
||||
this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount);
|
||||
|
||||
// skipped specs UI
|
||||
if (isUndefined(this.skippedAlert)) {
|
||||
this.skippedAlert = this.createDom('a', { href: jasmine.HtmlReporter.sectionLink(), className: "skippedAlert bar" });
|
||||
}
|
||||
|
||||
this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
|
||||
|
||||
if (this.skippedCount === 1 && isDefined(dom.alert)) {
|
||||
dom.alert.appendChild(this.skippedAlert);
|
||||
}
|
||||
|
||||
// passing specs UI
|
||||
if (isUndefined(this.passedAlert)) {
|
||||
this.passedAlert = this.createDom('span', { href: jasmine.HtmlReporter.sectionLink(), className: "passingAlert bar" });
|
||||
}
|
||||
this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount);
|
||||
|
||||
// failing specs UI
|
||||
if (isUndefined(this.failedAlert)) {
|
||||
this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"});
|
||||
}
|
||||
this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount);
|
||||
|
||||
if (this.failedCount === 1 && isDefined(dom.alert)) {
|
||||
dom.alert.appendChild(this.failedAlert);
|
||||
dom.alert.appendChild(this.resultsMenu);
|
||||
}
|
||||
|
||||
// summary info
|
||||
this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount);
|
||||
this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing";
|
||||
};
|
||||
|
||||
this.complete = function() {
|
||||
dom.alert.removeChild(this.runningAlert);
|
||||
|
||||
this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
|
||||
|
||||
if (this.failedCount === 0) {
|
||||
dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount)));
|
||||
} else {
|
||||
showDetails();
|
||||
}
|
||||
|
||||
dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"));
|
||||
};
|
||||
|
||||
return this;
|
||||
|
||||
function showDetails() {
|
||||
if (dom.reporter.className.search(/showDetails/) === -1) {
|
||||
dom.reporter.className += " showDetails";
|
||||
}
|
||||
}
|
||||
|
||||
function isUndefined(obj) {
|
||||
return typeof obj === 'undefined';
|
||||
}
|
||||
|
||||
function isDefined(obj) {
|
||||
return !isUndefined(obj);
|
||||
}
|
||||
|
||||
function specPluralizedFor(count) {
|
||||
var str = count + " spec";
|
||||
if (count > 1) {
|
||||
str += "s"
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView);
|
||||
|
||||
|
||||
jasmine.HtmlReporter.SpecView = function(spec, dom, views) {
|
||||
this.spec = spec;
|
||||
this.dom = dom;
|
||||
this.views = views;
|
||||
|
||||
this.symbol = this.createDom('li', { className: 'pending' });
|
||||
this.dom.symbolSummary.appendChild(this.symbol);
|
||||
|
||||
this.summary = this.createDom('div', { className: 'specSummary' },
|
||||
this.createDom('a', {
|
||||
className: 'description',
|
||||
href: jasmine.HtmlReporter.sectionLink(this.spec.getFullName()),
|
||||
title: this.spec.getFullName()
|
||||
}, this.spec.description)
|
||||
);
|
||||
|
||||
this.detail = this.createDom('div', { className: 'specDetail' },
|
||||
this.createDom('a', {
|
||||
className: 'description',
|
||||
href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
|
||||
title: this.spec.getFullName()
|
||||
}, this.spec.getFullName())
|
||||
);
|
||||
};
|
||||
|
||||
jasmine.HtmlReporter.SpecView.prototype.status = function() {
|
||||
return this.getSpecStatus(this.spec);
|
||||
};
|
||||
|
||||
jasmine.HtmlReporter.SpecView.prototype.refresh = function() {
|
||||
this.symbol.className = this.status();
|
||||
|
||||
switch (this.status()) {
|
||||
case 'skipped':
|
||||
break;
|
||||
|
||||
case 'passed':
|
||||
this.appendSummaryToSuiteDiv();
|
||||
break;
|
||||
|
||||
case 'failed':
|
||||
this.appendSummaryToSuiteDiv();
|
||||
this.appendFailureDetail();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() {
|
||||
this.summary.className += ' ' + this.status();
|
||||
this.appendToSummary(this.spec, this.summary);
|
||||
};
|
||||
|
||||
jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() {
|
||||
this.detail.className += ' ' + this.status();
|
||||
|
||||
var resultItems = this.spec.results().getItems();
|
||||
var messagesDiv = this.createDom('div', { className: 'messages' });
|
||||
|
||||
for (var i = 0; i < resultItems.length; i++) {
|
||||
var result = resultItems[i];
|
||||
|
||||
if (result.type == 'log') {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
|
||||
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
|
||||
|
||||
if (result.trace.stack) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (messagesDiv.childNodes.length > 0) {
|
||||
this.detail.appendChild(messagesDiv);
|
||||
this.dom.details.appendChild(this.detail);
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) {
|
||||
this.suite = suite;
|
||||
this.dom = dom;
|
||||
this.views = views;
|
||||
|
||||
this.element = this.createDom('div', { className: 'suite' },
|
||||
this.createDom('a', { className: 'description', href: jasmine.HtmlReporter.sectionLink(this.suite.getFullName()) }, this.suite.description)
|
||||
);
|
||||
|
||||
this.appendToSummary(this.suite, this.element);
|
||||
};
|
||||
|
||||
jasmine.HtmlReporter.SuiteView.prototype.status = function() {
|
||||
return this.getSpecStatus(this.suite);
|
||||
};
|
||||
|
||||
jasmine.HtmlReporter.SuiteView.prototype.refresh = function() {
|
||||
this.element.className += " " + this.status();
|
||||
};
|
||||
|
||||
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView);
|
||||
|
||||
/* @deprecated Use jasmine.HtmlReporter instead
|
||||
*/
|
||||
jasmine.TrivialReporter = function(doc) {
|
||||
this.document = doc || document;
|
||||
this.suiteDivs = {};
|
||||
this.logRunningSpecs = false;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
|
||||
var el = document.createElement(type);
|
||||
|
||||
for (var i = 2; i < arguments.length; i++) {
|
||||
var child = arguments[i];
|
||||
|
||||
if (typeof child === 'string') {
|
||||
el.appendChild(document.createTextNode(child));
|
||||
} else {
|
||||
if (child) { el.appendChild(child); }
|
||||
}
|
||||
}
|
||||
|
||||
for (var attr in attrs) {
|
||||
if (attr == "className") {
|
||||
el[attr] = attrs[attr];
|
||||
} else {
|
||||
el.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
|
||||
var showPassed, showSkipped;
|
||||
|
||||
this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' },
|
||||
this.createDom('div', { className: 'banner' },
|
||||
this.createDom('div', { className: 'logo' },
|
||||
this.createDom('span', { className: 'title' }, "Jasmine"),
|
||||
this.createDom('span', { className: 'version' }, runner.env.versionString())),
|
||||
this.createDom('div', { className: 'options' },
|
||||
"Show ",
|
||||
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
|
||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
|
||||
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
|
||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
|
||||
)
|
||||
),
|
||||
|
||||
this.runnerDiv = this.createDom('div', { className: 'runner running' },
|
||||
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
|
||||
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
|
||||
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
|
||||
);
|
||||
|
||||
this.document.body.appendChild(this.outerDiv);
|
||||
|
||||
var suites = runner.suites();
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
var suite = suites[i];
|
||||
var suiteDiv = this.createDom('div', { className: 'suite' },
|
||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
|
||||
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
|
||||
this.suiteDivs[suite.id] = suiteDiv;
|
||||
var parentDiv = this.outerDiv;
|
||||
if (suite.parentSuite) {
|
||||
parentDiv = this.suiteDivs[suite.parentSuite.id];
|
||||
}
|
||||
parentDiv.appendChild(suiteDiv);
|
||||
}
|
||||
|
||||
this.startedAt = new Date();
|
||||
|
||||
var self = this;
|
||||
showPassed.onclick = function(evt) {
|
||||
if (showPassed.checked) {
|
||||
self.outerDiv.className += ' show-passed';
|
||||
} else {
|
||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
|
||||
}
|
||||
};
|
||||
|
||||
showSkipped.onclick = function(evt) {
|
||||
if (showSkipped.checked) {
|
||||
self.outerDiv.className += ' show-skipped';
|
||||
} else {
|
||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
|
||||
var results = runner.results();
|
||||
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
|
||||
this.runnerDiv.setAttribute("class", className);
|
||||
//do it twice for IE
|
||||
this.runnerDiv.setAttribute("className", className);
|
||||
var specs = runner.specs();
|
||||
var specCount = 0;
|
||||
for (var i = 0; i < specs.length; i++) {
|
||||
if (this.specFilter(specs[i])) {
|
||||
specCount++;
|
||||
}
|
||||
}
|
||||
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
|
||||
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
|
||||
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
|
||||
|
||||
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
|
||||
var results = suite.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.totalCount === 0) { // todo: change this to check results.skipped
|
||||
status = 'skipped';
|
||||
}
|
||||
this.suiteDivs[suite.id].className += " " + status;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
|
||||
if (this.logRunningSpecs) {
|
||||
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
|
||||
var results = spec.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.skipped) {
|
||||
status = 'skipped';
|
||||
}
|
||||
var specDiv = this.createDom('div', { className: 'spec ' + status },
|
||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
|
||||
this.createDom('a', {
|
||||
className: 'description',
|
||||
href: '?spec=' + encodeURIComponent(spec.getFullName()),
|
||||
title: spec.getFullName()
|
||||
}, spec.description));
|
||||
|
||||
|
||||
var resultItems = results.getItems();
|
||||
var messagesDiv = this.createDom('div', { className: 'messages' });
|
||||
for (var i = 0; i < resultItems.length; i++) {
|
||||
var result = resultItems[i];
|
||||
|
||||
if (result.type == 'log') {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
|
||||
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
|
||||
|
||||
if (result.trace.stack) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (messagesDiv.childNodes.length > 0) {
|
||||
specDiv.appendChild(messagesDiv);
|
||||
}
|
||||
|
||||
this.suiteDivs[spec.suite.id].appendChild(specDiv);
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.log = function() {
|
||||
var console = jasmine.getGlobal().console;
|
||||
if (console && console.log) {
|
||||
if (console.log.apply) {
|
||||
console.log.apply(console, arguments);
|
||||
} else {
|
||||
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.getLocation = function() {
|
||||
return this.document.location;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
|
||||
var paramMap = {};
|
||||
var params = this.getLocation().search.substring(1).split('&');
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var p = params[i].split('=');
|
||||
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
|
||||
}
|
||||
|
||||
if (!paramMap.spec) {
|
||||
return true;
|
||||
}
|
||||
return spec.getFullName().indexOf(paramMap.spec) === 0;
|
||||
};
|
||||
127
vendor/jasmine/jasmine-support.js
vendored
127
vendor/jasmine/jasmine-support.js
vendored
|
|
@ -1,127 +0,0 @@
|
|||
if (typeof jasmine == 'undefined') jasmine = require("./jasmine");
|
||||
var spec = false; // TODO
|
||||
|
||||
// Add some matcher for mock functions
|
||||
jasmine.getEnv().beforeEach(function() {
|
||||
this.addMatchers({
|
||||
toBeCalled: function() {
|
||||
if (this.actual.mock === undefined) {
|
||||
throw Error('toBeCalled() should be used on a mock function');
|
||||
}
|
||||
return this.actual.mock.calls.length !== 0;
|
||||
},
|
||||
|
||||
lastCalledWith: function() {
|
||||
if (this.actual.mock === undefined) {
|
||||
throw Error('lastCalledWith() should be used on a mock function');
|
||||
}
|
||||
var calls = this.actual.mock.calls;
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
return this.env.equals_(calls[calls.length - 1], args);
|
||||
},
|
||||
|
||||
toBeCalledWith: function() {
|
||||
if (this.actual.mock === undefined) {
|
||||
throw Error('toBeCalledWith() should be used on a mock function');
|
||||
}
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
return this.actual.mock.calls.some(function(call) {
|
||||
return this.env.equals_(call, args);
|
||||
}.bind(this));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
var _it = jasmine.Env.prototype.it;
|
||||
var _xit = jasmine.Env.prototype.xit;
|
||||
jasmine.Env.prototype.it = function(desc, func) {
|
||||
// If spec is provided, only run matching specs
|
||||
if (!spec || desc.match(new RegExp(spec, 'i'))) {
|
||||
return _it.call(this, desc, func);
|
||||
} else {
|
||||
return this.xit(desc, func);
|
||||
}
|
||||
};
|
||||
jasmine.Env.prototype.xit = function(desc, func) {
|
||||
if (typeof func == 'function') {
|
||||
var matches = func.toString().match(/.*\W?expect\(/g);
|
||||
if (matches) {
|
||||
this.reporter.subReporters_[0].skipCount += matches.length;
|
||||
this.reporter.subReporters_[0].totalCount += matches.length;
|
||||
}
|
||||
}
|
||||
return _xit.call(this, desc, func);
|
||||
}
|
||||
|
||||
// Mainline Jasmine sets __Jasmine_been_here_before__ on each object to detect
|
||||
// cycles, but that doesn't work on frozen objects so we use a WeakMap instead.
|
||||
// We can only do this if if WeakMap is available, but if WeakMap is
|
||||
// unavailable, then objects probably can't be frozen anyway.
|
||||
|
||||
if (typeof WeakMap !== "undefined") {
|
||||
var _comparedObjects = new WeakMap;
|
||||
|
||||
jasmine.Env.prototype.compareObjects_ =
|
||||
function(a, b, mismatchKeys, mismatchValues) {
|
||||
if (_comparedObjects.get(a) === b && _comparedObjects.get(b) === a) {
|
||||
return true;
|
||||
}
|
||||
var areArrays = jasmine.isArray_(a) && jasmine.isArray_(b);
|
||||
|
||||
_comparedObjects.set(a, b);
|
||||
_comparedObjects.set(b, a);
|
||||
|
||||
var hasKey = function(obj, keyName) {
|
||||
return obj != null && obj[keyName] !== jasmine.undefined;
|
||||
};
|
||||
|
||||
for (var property in b) {
|
||||
if (areArrays && typeof b[property] == 'function') {
|
||||
continue;
|
||||
}
|
||||
if (!hasKey(a, property) && hasKey(b, property)) {
|
||||
mismatchKeys.push(
|
||||
"expected has key '" + property + "', but missing from actual."
|
||||
);
|
||||
}
|
||||
}
|
||||
for (property in a) {
|
||||
if (areArrays && typeof a[property] == 'function') {
|
||||
continue;
|
||||
}
|
||||
if (!hasKey(b, property) && hasKey(a, property)) {
|
||||
mismatchKeys.push(
|
||||
"expected missing key '" + property + "', but present in actual."
|
||||
);
|
||||
}
|
||||
}
|
||||
for (property in b) {
|
||||
// The only different implementation from the original jasmine
|
||||
if (areArrays &&
|
||||
(typeof a[property] == 'function' ||
|
||||
typeof b[property] == 'function')) {
|
||||
continue;
|
||||
}
|
||||
if (!this.equals_(a[property], b[property], mismatchKeys, mismatchValues))
|
||||
{
|
||||
mismatchValues.push(
|
||||
"'" + property + "' was '" + (b[property] ?
|
||||
jasmine.util.htmlEscape(b[property].toString()) :
|
||||
b[property]) +
|
||||
"' in expected, but was '" + (a[property] ?
|
||||
jasmine.util.htmlEscape(a[property].toString()) :
|
||||
a[property]) + "' in actual."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (areArrays &&
|
||||
a.length != b.length) {
|
||||
mismatchValues.push("arrays were not the same length");
|
||||
}
|
||||
|
||||
_comparedObjects["delete"](a);
|
||||
_comparedObjects["delete"](b);
|
||||
return (mismatchKeys.length == 0 && mismatchValues.length == 0);
|
||||
};
|
||||
}
|
||||
82
vendor/jasmine/jasmine.css
vendored
82
vendor/jasmine/jasmine.css
vendored
|
|
@ -1,82 +0,0 @@
|
|||
body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
|
||||
|
||||
#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
|
||||
#HTMLReporter a { text-decoration: none; }
|
||||
#HTMLReporter a:hover { text-decoration: underline; }
|
||||
#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; }
|
||||
#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; }
|
||||
#HTMLReporter #jasmine_content { position: fixed; right: 100%; }
|
||||
#HTMLReporter .version { color: #aaaaaa; }
|
||||
#HTMLReporter .banner { margin-top: 14px; }
|
||||
#HTMLReporter .duration { color: #aaaaaa; float: right; }
|
||||
#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; }
|
||||
#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
|
||||
#HTMLReporter .symbolSummary li.passed { font-size: 14px; }
|
||||
#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; }
|
||||
#HTMLReporter .symbolSummary li.failed { line-height: 9px; }
|
||||
#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
|
||||
#HTMLReporter .symbolSummary li.skipped { font-size: 14px; }
|
||||
#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
|
||||
#HTMLReporter .symbolSummary li.pending { line-height: 11px; }
|
||||
#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
|
||||
#HTMLReporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
|
||||
#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
|
||||
#HTMLReporter .runningAlert { background-color: #666666; }
|
||||
#HTMLReporter .skippedAlert { background-color: #aaaaaa; }
|
||||
#HTMLReporter .skippedAlert:first-child { background-color: #333333; }
|
||||
#HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; }
|
||||
#HTMLReporter .passingAlert { background-color: #a6b779; }
|
||||
#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; }
|
||||
#HTMLReporter .failingAlert { background-color: #cf867e; }
|
||||
#HTMLReporter .failingAlert:first-child { background-color: #b03911; }
|
||||
#HTMLReporter .results { margin-top: 14px; }
|
||||
#HTMLReporter #details { display: none; }
|
||||
#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; }
|
||||
#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
|
||||
#HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
|
||||
#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
|
||||
#HTMLReporter.showDetails .summary { display: none; }
|
||||
#HTMLReporter.showDetails #details { display: block; }
|
||||
#HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
|
||||
#HTMLReporter .summary { margin-top: 14px; }
|
||||
#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; }
|
||||
#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; }
|
||||
#HTMLReporter .summary .specSummary.failed a { color: #b03911; }
|
||||
#HTMLReporter .description + .suite { margin-top: 0; }
|
||||
#HTMLReporter .suite { margin-top: 14px; }
|
||||
#HTMLReporter .suite a { color: #333333; }
|
||||
#HTMLReporter #details .specDetail { margin-bottom: 28px; }
|
||||
#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; }
|
||||
#HTMLReporter .resultMessage { padding-top: 14px; color: #333333; }
|
||||
#HTMLReporter .resultMessage span.result { display: block; }
|
||||
#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }
|
||||
|
||||
#TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ }
|
||||
#TrivialReporter a:visited, #TrivialReporter a { color: #303; }
|
||||
#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; }
|
||||
#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; }
|
||||
#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; }
|
||||
#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; }
|
||||
#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; }
|
||||
#TrivialReporter .runner.running { background-color: yellow; }
|
||||
#TrivialReporter .options { text-align: right; font-size: .8em; }
|
||||
#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; }
|
||||
#TrivialReporter .suite .suite { margin: 5px; }
|
||||
#TrivialReporter .suite.passed { background-color: #dfd; }
|
||||
#TrivialReporter .suite.failed { background-color: #fdd; }
|
||||
#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; }
|
||||
#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; }
|
||||
#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; }
|
||||
#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; }
|
||||
#TrivialReporter .spec.skipped { background-color: #bbb; }
|
||||
#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; }
|
||||
#TrivialReporter .passed { background-color: #cfc; display: none; }
|
||||
#TrivialReporter .failed { background-color: #fbb; }
|
||||
#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; }
|
||||
#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; }
|
||||
#TrivialReporter .resultMessage .mismatch { color: black; }
|
||||
#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; }
|
||||
#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; }
|
||||
#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; }
|
||||
#TrivialReporter #jasmine_content { position: fixed; right: 100%; }
|
||||
#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; }
|
||||
2600
vendor/jasmine/jasmine.js
vendored
2600
vendor/jasmine/jasmine.js
vendored
File diff suppressed because it is too large
Load Diff
37
vendor/jasmine/phantom.js
vendored
37
vendor/jasmine/phantom.js
vendored
|
|
@ -1,37 +0,0 @@
|
|||
/**
|
||||
* Copyright 2013-2015, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the BSD-style license found in the
|
||||
* LICENSE file in the root directory of this source tree. An additional grant
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*
|
||||
* This module provides a bridge from content-land to phantom-land via the
|
||||
* window.callPhantom interface.
|
||||
*/
|
||||
|
||||
var console = require("./console");
|
||||
var global = Function("return this")();
|
||||
|
||||
if (global.callPhantom) {
|
||||
// Phantom's onConsoleMessage support is lacking (only one argument
|
||||
// supported, and it must be a string), so we use callPhantom to
|
||||
// forward console messages instead.
|
||||
console.addListener(function(method, args) {
|
||||
global.callPhantom({
|
||||
type: "console",
|
||||
method: method,
|
||||
args: args
|
||||
});
|
||||
});
|
||||
|
||||
exports.exit = function(code) {
|
||||
global.callPhantom({
|
||||
type: "exit",
|
||||
code: code
|
||||
});
|
||||
};
|
||||
|
||||
} else {
|
||||
exports.exit = function() {};
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user