mirror of
https://github.com/zebrajr/react.git
synced 2025-12-06 00:20:04 +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
|
src/shared/vendor
|
||||||
# This should be enabled but that folder has too much in it that doesn't belong
|
# This should be enabled but that folder has too much in it that doesn't belong
|
||||||
src/test
|
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/*
|
# But not in docs/_js/examples/*
|
||||||
docs/_js/*.js
|
docs/_js/*.js
|
||||||
docs/js/
|
docs/js/
|
||||||
|
|
|
||||||
11
.travis.yml
11
.travis.yml
|
|
@ -66,12 +66,10 @@ script:
|
||||||
fi
|
fi
|
||||||
env:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
- TEST_TYPE=test
|
|
||||||
- TEST_TYPE=build
|
- TEST_TYPE=build
|
||||||
- TEST_TYPE=jest
|
- TEST_TYPE=jest
|
||||||
- TEST_TYPE=lint
|
- TEST_TYPE=lint
|
||||||
- TEST_TYPE=build_website
|
- TEST_TYPE=build_website
|
||||||
- TEST_TYPE=test:webdriver:saucelabs:modern
|
|
||||||
global:
|
global:
|
||||||
# SERVER
|
# SERVER
|
||||||
- secure: qPvsJ46XzGrdIuPA70b55xQNGF8jcK7N1LN5CCQYYocXLa+fBrl+fTE77QvehOPhqwJXcj6kOxI+sY0KrVwV7gmq2XY2HZGWUSCxTN0SZlNIzqPA80Y7G/yOjA4PUt8LKgP+8tptyhTAY56qf+hgW8BoLiKOdztYF2p+3zXOLuA=
|
- secure: qPvsJ46XzGrdIuPA70b55xQNGF8jcK7N1LN5CCQYYocXLa+fBrl+fTE77QvehOPhqwJXcj6kOxI+sY0KrVwV7gmq2XY2HZGWUSCxTN0SZlNIzqPA80Y7G/yOjA4PUt8LKgP+8tptyhTAY56qf+hgW8BoLiKOdztYF2p+3zXOLuA=
|
||||||
|
|
@ -81,15 +79,6 @@ env:
|
||||||
- secure: EHCyCSKMwKlLHNtcj9nmkRzmiiPE3aDGlPcnEyrDJeRI0SeN/iCXHXfFivR0vFq3vr+9naMBczAR2AEidtps5KbJrKqdZnjPFRbmfVtzWr/LlvVCub3u13Pub6TdKIVBTny1PuZ5X8GvdxMNVig89jGjvzhhWuQRaz3VhJnTra4=
|
- secure: EHCyCSKMwKlLHNtcj9nmkRzmiiPE3aDGlPcnEyrDJeRI0SeN/iCXHXfFivR0vFq3vr+9naMBczAR2AEidtps5KbJrKqdZnjPFRbmfVtzWr/LlvVCub3u13Pub6TdKIVBTny1PuZ5X8GvdxMNVig89jGjvzhhWuQRaz3VhJnTra4=
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
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:
|
notifications:
|
||||||
irc:
|
irc:
|
||||||
use_notice: true
|
use_notice: true
|
||||||
|
|
|
||||||
106
Gruntfile.js
106
Gruntfile.js
|
|
@ -6,9 +6,6 @@ module.exports = function(grunt) {
|
||||||
pkg: grunt.file.readJSON('package.json'),
|
pkg: grunt.file.readJSON('package.json'),
|
||||||
jsx: require('./grunt/config/jsx'),
|
jsx: require('./grunt/config/jsx'),
|
||||||
browserify: require('./grunt/config/browserify'),
|
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'),
|
npm: require('./grunt/config/npm'),
|
||||||
clean: [
|
clean: [
|
||||||
'./build',
|
'./build',
|
||||||
|
|
@ -39,11 +36,6 @@ module.exports = function(grunt) {
|
||||||
|
|
||||||
grunt.registerTask('lint', ['eslint']);
|
grunt.registerTask('lint', ['eslint']);
|
||||||
|
|
||||||
grunt.registerTask(
|
|
||||||
'download-previous-version',
|
|
||||||
require('./grunt/tasks/download-previous-version.js')
|
|
||||||
);
|
|
||||||
|
|
||||||
grunt.registerTask('delete-build-modules', function() {
|
grunt.registerTask('delete-build-modules', function() {
|
||||||
if (grunt.file.exists('build/modules')) {
|
if (grunt.file.exists('build/modules')) {
|
||||||
grunt.file.delete('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.
|
// Our own browserify-based tasks to build a single JS file build.
|
||||||
grunt.registerMultiTask('browserify', require('./grunt/tasks/browserify'));
|
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'));
|
grunt.registerMultiTask('npm', require('./grunt/tasks/npm'));
|
||||||
|
|
||||||
var npmReactTasks = require('./grunt/tasks/npm-react');
|
var npmReactTasks = require('./grunt/tasks/npm-react');
|
||||||
|
|
@ -107,17 +93,6 @@ module.exports = function(grunt) {
|
||||||
'jsx:normal',
|
'jsx:normal',
|
||||||
'browserify:addonsMin',
|
'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', [
|
grunt.registerTask('build:npm-react', [
|
||||||
'version-check',
|
'version-check',
|
||||||
'jsx:normal',
|
'jsx:normal',
|
||||||
|
|
@ -128,89 +103,10 @@ module.exports = function(grunt) {
|
||||||
'gem-react-source:release',
|
'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.registerTask('fasttest', function() {
|
||||||
grunt.task.run('test');
|
grunt.task.run('test');
|
||||||
});
|
});
|
||||||
grunt.registerTask('test', function() {
|
grunt.registerTask('test', ['jest']);
|
||||||
if (grunt.option('debug')) {
|
|
||||||
grunt.task.run('build:test', 'connect:server:keepalive');
|
|
||||||
} else {
|
|
||||||
grunt.task.run('build:test', 'test:webdriver:phantomjs');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
grunt.registerTask('npm:test', ['build', 'npm:pack']);
|
grunt.registerTask('npm:test', ['build', 'npm:pack']);
|
||||||
|
|
||||||
// Optimized build task that does all of our builds. The subtasks will be run
|
// Optimized build task that does all of our builds. The subtasks will be run
|
||||||
|
|
|
||||||
|
|
@ -43,22 +43,5 @@ require("commoner").version(
|
||||||
}).code;
|
}).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;
|
return source;
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -121,25 +121,10 @@ var addonsMin = {
|
||||||
after: [/*derequire,*/ minify, bannerify],
|
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 = {
|
module.exports = {
|
||||||
basic: basic,
|
basic: basic,
|
||||||
min: min,
|
min: min,
|
||||||
transformer: transformer,
|
transformer: transformer,
|
||||||
addons: addons,
|
addons: addons,
|
||||||
addonsMin: addonsMin,
|
addonsMin: addonsMin,
|
||||||
withCodeCoverageLogging: withCodeCoverageLogging,
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var assign = require('../../src/shared/stubs/Object.assign');
|
|
||||||
var grunt = require('grunt');
|
var grunt = require('grunt');
|
||||||
|
|
||||||
var rootIDs = [
|
var rootIDs = [
|
||||||
|
|
@ -21,23 +20,6 @@ var normal = {
|
||||||
outputDir: 'build/modules',
|
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 = {
|
module.exports = {
|
||||||
normal: normal,
|
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",
|
"browserify": "^9.0.3",
|
||||||
"bundle-collapser": "^1.1.1",
|
"bundle-collapser": "^1.1.1",
|
||||||
"coffee-script": "^1.8.0",
|
"coffee-script": "^1.8.0",
|
||||||
"coverify": "^1.3.3",
|
|
||||||
"derequire": "^2.0.0",
|
"derequire": "^2.0.0",
|
||||||
"envify": "^3.0.0",
|
"envify": "^3.0.0",
|
||||||
"es5-shim": "^4.0.0",
|
|
||||||
"eslint": "^0.22.1",
|
"eslint": "^0.22.1",
|
||||||
"eslint-plugin-react": "^2.5.0",
|
"eslint-plugin-react": "^2.5.0",
|
||||||
"eslint-plugin-react-internal": "file:eslint-rules",
|
"eslint-plugin-react-internal": "file:eslint-rules",
|
||||||
|
|
@ -48,22 +46,16 @@
|
||||||
"grunt-compare-size": "^0.4.0",
|
"grunt-compare-size": "^0.4.0",
|
||||||
"grunt-contrib-clean": "^0.6.0",
|
"grunt-contrib-clean": "^0.6.0",
|
||||||
"grunt-contrib-compress": "^0.13.0",
|
"grunt-contrib-compress": "^0.13.0",
|
||||||
"grunt-contrib-connect": "~0.6.0",
|
|
||||||
"grunt-jest": "^0.1.3",
|
"grunt-jest": "^0.1.3",
|
||||||
"gzip-js": "~0.3.2",
|
"gzip-js": "~0.3.2",
|
||||||
"jasmine-tapreporter": "~0.2.2",
|
|
||||||
"jest-cli": "^0.4.13",
|
"jest-cli": "^0.4.13",
|
||||||
"object-assign": "^3.0.0",
|
"object-assign": "^3.0.0",
|
||||||
"optimist": "^0.6.1",
|
"optimist": "^0.6.1",
|
||||||
"phantomjs": "^1.9.17",
|
|
||||||
"platform": "^1.1.0",
|
"platform": "^1.1.0",
|
||||||
"populist": "~0.1.6",
|
|
||||||
"sauce-tunnel": "~1.1.0",
|
|
||||||
"tmp": "~0.0.18",
|
"tmp": "~0.0.18",
|
||||||
"typescript": "^1.4.0",
|
"typescript": "^1.4.0",
|
||||||
"uglify-js": "^2.4.23",
|
"uglify-js": "^2.4.23",
|
||||||
"uglifyify": "^3.0.1",
|
"uglifyify": "^3.0.1"
|
||||||
"wd": "~0.2.6"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"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