Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test examples #658

Merged
merged 5 commits into from
Jan 10, 2017
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,13 @@ cache:
- "$HOME/cache"

before_install:
# Start xvfb with a specific resolution and pixel depth
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -ac -screen 0 1280x1024x24"
- CACHE="${HOME}/cache" CMAKE_VERSION=3.5.0 CMAKE_SHORT_VERSION=3.5 source ./scripts/install_cmake.sh
- npm prune

before_script:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start

script:
- npm run build
Expand Down
26 changes: 25 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,16 @@ add_custom_target(
)
add_test(NAME get_data_files COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target data_files)

add_custom_command(OUTPUT "${GEOJS_DEPLOY_DIR}/examples/bundle.js"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMAND npm run build-examples
COMMENT "Build examples"
VERBATIM
)
add_custom_target(examples DEPENDS "${GEOJS_DEPLOY_DIR}/examples/bundle.js")
add_test(NAME build_examples COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target examples)
set_property(TEST "build_examples" APPEND PROPERTY DEPENDS "get_data_files")

if(FFHEADLESS_TESTS)
find_program(NPM_EXECUTABLE npm)
add_test(
Expand All @@ -111,6 +121,16 @@ if(FFHEADLESS_TESTS)
set_property(TEST "total-coverage" APPEND PROPERTY DEPENDS "ffheadless")
set_property(TEST "ffheadless" APPEND PROPERTY DEPENDS "get_data_files")

add_test(
NAME "examplesheadless"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMAND npm run examplesci
)
set_property(TEST "examplesheadless" APPEND PROPERTY ENVIRONMENT "CTEST_IMAGE_PATH=${CMAKE_CURRENT_BINARY_DIR}/images")
set_property(TEST "examplesheadless" APPEND PROPERTY ENVIRONMENT "TEST_SAVE_IMAGE=${TEST_SAVE_IMAGE}")
set_property(TEST "total-coverage" APPEND PROPERTY DEPENDS "examplesheadless")
set_property(TEST "examplesheadless" APPEND PROPERTY DEPENDS "build_examples")

configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/testing/test-runners/baseline_images.py"
"${CMAKE_CURRENT_BINARY_DIR}/test/baseline_images.py"
Expand All @@ -124,8 +144,12 @@ add_custom_command(OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/base-images.tgz"
COMMAND "${CMAKE_COMMAND}" --build ${CMAKE_BINARY_DIR} --target data_files
# Run the ffheadless test, asking to save all images
COMMAND TEST_SAVE_IMAGE=all npm run ffci
# Build examples to make sure that they are available.
COMMAND npm run build-examples
# Run the examplesheadless test, asking to save all images
COMMAND TEST_SAVE_IMAGE=all npm run examplesci
# Make a tarball of all of the images
COMMAND tar -zcvf "${CMAKE_CURRENT_BINARY_DIR}/base-images.tgz" --exclude=*-test.png --exclude=*-diff.png --exclude=*-base.png -C "${CMAKE_CURRENT_BINARY_DIR}/images" .
COMMAND tar -zcvf "${CMAKE_CURRENT_BINARY_DIR}/base-images.tgz" --exclude=*-test.png --exclude=*-diff.png --exclude=*-base.png --exclude=*-screen.png -C "${CMAKE_CURRENT_BINARY_DIR}/images" .
COMMENT "Create baseline images, then tar them into a single file"
VERBATIM
)
Expand Down
6 changes: 6 additions & 0 deletions docs/developers.rst
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ test command or set this parameter in CMake.
build correctly. Try running ``ccmake /path/to/geojs`` for a full
list of configuration options.

Examples should be tested by creating an entry in the ``tests/example-cases/``
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

directory. To run these tests in a normal browser, run
``npm run start`` and browse to `<http://localhost:9876/debug.html?test=all>`_.
Since the browser's direct screen output is used, the browser must be running
on the same machine as the ``npm run start`` command.

Selenium testing
----------------

Expand Down
1 change: 1 addition & 0 deletions examples/common/css/examples.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ html, body {
#map {
width: 100%;
height: calc(100% - 60px);
overflow: hidden;
}
2 changes: 2 additions & 0 deletions examples/lines/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ $(function () {
* the line.
*/
function show_lines(rawdata) {
$('#map').removeClass('ready');
if (!rawdata) {
return;
}
Expand All @@ -143,6 +144,7 @@ $(function () {
lineFeature.draw();
var text = 'Shown: ' + segments;
$('#lines-shown').text(text).attr('title', text);
$('#map').addClass('ready');
}

/**
Expand Down
143 changes: 87 additions & 56 deletions karma-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,29 @@ function saveImage(name, image, always) {
}
}

/* Use ImageMagick's import tool to get a portion of the screen. The caller is
* responsible for identifying the useful portion of the screen.
*
* @param {string} name: base name for the image.
* @param {number} left: left screen coordinate
* @param {number} top: top screen coordinate
* @param {number} width: width in pixels of area to fetch.
* @param {number} height: height in pixels of area to fetch.
* @returns: a base64-encoded image.
*/
function getScreenImage(name, left, top, width, height) {
var child_process = require('child_process');
var dest = path.resolve(image_path, name + '-screen.png');
child_process.execSync(
'import -window root ' +
'-crop ' + width + 'x' + height + (left >= 0 ? '+' : '') + left +
(top >= 0 ? '+' : '') + top + ' +repage ' +
'\'' + dest.replace(/'/g, "'\\''") + '\'');
var xvfbImage = new Buffer(fs.readFileSync(dest)).toString('base64');
xvfbImage = 'data:image/png;base64,' + xvfbImage;
return xvfbImage;
}

/* Compare an image to a base image. If it violates a threshold, save the
* image and a diff between it and the base image. Returns the resemble
* results.
Expand All @@ -64,17 +87,6 @@ function saveImage(name, image, always) {
* @param {function} callback: a function to call when complete.
*/
function compareImage(name, image, threshold, callback) {
/* Note, we could read the xvfb frame buffer using imageMagick, which would
* get the entire browser display, including it's window border, tabs, search
* bar, and non-canvas elements. It might be worth install a kiosk extension
* to FireFox (or use Chrome in Kiosk mode), and exclude the portions of the
* window that are used for Karma information.
var child_process = require('child_process');
var dest = path.resolve(image_path, name + '-xvfb.png');
child_process.execSync('import -window root \'' + dest.replace(/'/g, "'\\''") + '\'');
var xvfbImage = new Buffer(fs.readFileSync(dest)).toString('base64');
xvfbImage = 'data:image/png;base64,' + xvfbImage;
*/
var resemble = require('node-resemble');
var src = path.resolve('dist/data/base-images', name + '.png');
if (!fs.existsSync(src)) {
Expand Down Expand Up @@ -138,7 +150,13 @@ var notes_middleware = function (config) {
if (request.method === 'PUT') {
return getRawBody(request).then(function (body) {
var name = query.name;
var image = '' + body;
var image;
if (query.screen === 'true') {
image = getScreenImage(name, query.left, query.top,
query.width, query.height);
} else {
image = '' + body;
}
saveImage(name, image);
if (query.compare === 'true') {
compareImage(name, image, query.threshold, function (results) {
Expand All @@ -165,49 +183,62 @@ var notes_middleware = function (config) {
};
};

module.exports = {
autoWatch: false,
files: [
test_case,
{pattern: 'tests/data/**/*', included: false},
{pattern: 'tests/cases/**/*.js', included: false, served: false, watched: true},
{pattern: 'tests/gl-cases/**/*.js', included: false, served: false, watched: true},
{pattern: 'dist/data/**/*', included: false},
{pattern: 'dist/examples/**/*', included: false}
],
proxies: {
'/testdata/': '/base/tests/data/',
'/data/': '/base/dist/data/',
'/examples/': '/base/dist/examples/'
},
browsers: [
'PhantomJS'
],
browserNoActivityTimeout: 30000,
reporters: [
'progress',
'kjhtml'
],
middleware: [
'notes'
],
plugins: [
{'middleware:notes': ['factory', notes_middleware]},
'karma-*'
],
preprocessors: {},
frameworks: [
'jasmine', 'sinon'
],
webpack: {
cache: true,
devtool: 'inline-source-map',
module: {
loaders: webpack_config.module.loaders
module.exports = function (config) {
var newConfig = {
autoWatch: false,
files: [
test_case,
{pattern: 'tests/data/**/*', included: false},
{pattern: 'tests/cases/**/*.js', included: false, served: false, watched: true},
{pattern: 'tests/gl-cases/**/*.js', included: false, served: false, watched: true},
{pattern: 'tests/example-cases/**/*.js', included: false, served: false, watched: true},
{pattern: 'dist/data/**/*', included: false},
{pattern: 'dist/examples/**/*', included: false}
],
proxies: {
'/testdata/': '/base/tests/data/',
'/data/': '/base/dist/data/',
'/examples/': '/base/dist/examples/'
},
resolve: webpack_config.resolve,
plugins: webpack_config.exposed_plugins
}
};
browsers: [
'PhantomJS'
],
customLaunchers: {
FirefoxWithProxy: {
base: 'Firefox',
prefs: {
'network.proxy.type': 2,
'network.proxy.autoconfig_url': config.protocol + '//' + config.hostname + ':' + config.port + '/testdata/proxy-for-tests.pac'
}
}
},
browserNoActivityTimeout: 30000,
reporters: [
'progress',
'kjhtml'
],
middleware: [
'notes'
],
plugins: [
{'middleware:notes': ['factory', notes_middleware]},
'karma-*'
],
preprocessors: {},
frameworks: [
'jasmine', 'sinon'
],
webpack: {
cache: true,
devtool: 'inline-source-map',
module: {
loaders: webpack_config.module.loaders
},
resolve: webpack_config.resolve,
plugins: webpack_config.exposed_plugins
}
};
newConfig.preprocessors[test_case] = ['webpack', 'sourcemap'];

module.exports.preprocessors[test_case] = ['webpack', 'sourcemap'];
return newConfig;
};
39 changes: 20 additions & 19 deletions karma-cov.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// with coverage support.

var path = require('path');
var karma_config = require('./karma-base');

/**
* Return URL friendly browser string
Expand All @@ -11,24 +10,26 @@ function browser(b) {
return b.toLowerCase().split(/[ /-]/)[0];
}

karma_config.reporters = ['progress', 'coverage'];
karma_config.coverageReporter = {
reporters: [
{type: 'html', dir: 'dist/coverage/', subdir: browser},
{type: 'cobertura', dir: 'dist/cobertura/', file: 'coverage.xml', subdir: browser},
{type: 'json', dir: 'dist/coverage/json/', subdir: browser},
{type: 'lcovonly', dir: 'lcov', subdir: browser},
{type: 'text'}
]
};
karma_config.webpack.module.preLoaders = [
{
test: /\.js$/,
include: path.resolve('src/'),
loader: 'istanbul-instrumenter'
}
];

module.exports = function (config) {
var karma_config = require('./karma-base')(config);

karma_config.reporters = ['progress', 'coverage'];
karma_config.coverageReporter = {
reporters: [
{type: 'html', dir: 'dist/coverage/', subdir: browser},
{type: 'cobertura', dir: 'dist/cobertura/', file: 'coverage.xml', subdir: browser},
{type: 'json', dir: 'dist/coverage/json/', subdir: browser},
{type: 'lcovonly', dir: 'lcov', subdir: browser},
{type: 'text'}
]
};
karma_config.webpack.module.preLoaders = [
{
test: /\.js$/,
include: path.resolve('src/'),
loader: 'istanbul-instrumenter'
}
];

config.set(karma_config);
};
4 changes: 1 addition & 3 deletions karma.conf.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
var karma_config = require('./karma-base');

module.exports = function (config) {
config.set(karma_config);
config.set(require('./karma-base')(config));
};
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"express": "^4.13.4",
"file-loader": "^0.8.5",
"forever": "^0.15.2",
"fs-extra": "^1.0.0",
"gl-mat3": "^1.0.0",
"gl-mat4": "^1.1.4",
"gl-vec2": "^1.0.0",
Expand All @@ -61,7 +62,6 @@
"karma-sourcemap-loader": "^0.3.7",
"karma-webpack": "^1.7.0",
"mousetrap": "^1.6.0",
"node-fs-extra": "^0.8.1",
"node-resemble": "^1.1.3",
"phantomjs-prebuilt": "^2.1.5",
"proj4": "^2.3.14",
Expand All @@ -82,7 +82,9 @@
"start": "karma start karma.conf.js",
"ci": "GEOJS_TEST_CASE=tests/test-unit.js karma start karma-cov.conf.js --single-run --browsers PhantomJS",
"ffci": "GEOJS_TEST_CASE=tests/test-gl.js karma start karma-cov.conf.js --single-run --browsers Firefox",
"examplesci": "GEOJS_TEST_CASE=tests/test-examples.js karma start karma-cov.conf.js --single-run --browsers FirefoxWithProxy",
"test-webgl": "GEOJS_TEST_CASE=tests/test-gl.js xvfb-run -s '-ac -screen 0 1280x1024x24' karma start karma-cov.conf.js --single-run --browsers Firefox",
"test-examples": "GEOJS_TEST_CASE=tests/test-examples.js xvfb-run -s '-ac -screen 0 1280x1024x24' karma start karma-cov.conf.js --single-run --browsers FirefoxWithProxy",
"codecov": "cat lcov/*/lcov.info | codecov",
"combine-coverage": "istanbul-combine -d dist/cobertura -r cobertura 'dist/coverage/json/**/coverage-final.json'",
"examples": "webpack-dev-server --config webpack-examples.config.js --host ${HOST-127.0.0.1} --port ${PORT-8082} --content-base dist/",
Expand Down
2 changes: 1 addition & 1 deletion testing/test-data/base-images.tgz.md5
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5fc9100434a75382b93dc86db6a8c62e
2f4ea11110deac8f5de053c49d09ce1e
2 changes: 1 addition & 1 deletion testing/test-data/base-images.tgz.url
Original file line number Diff line number Diff line change
@@ -1 +1 @@
https://data.kitware.com/api/v1/file/5858590d8d777f1e3428d5b0/download
https://data.kitware.com/api/v1/file/586bfea38d777f05f44a5c6f/download
21 changes: 17 additions & 4 deletions tests/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,21 @@
* Entry point for all tests.
*/

var query = require('./test-utils').getQuery();

/* By default, general and gl tests are run. Set the 'test' query parameter to
* 'all' to run all tests, or use a specific test group name.
*/
var tests;
tests = require.context('./cases', true, /.*\.js$/);
tests.keys().forEach(tests);
tests = require.context('./gl-cases', true, /.*\.js$/);
tests.keys().forEach(tests);
if (query.test === 'all' || query.test === 'general' || query.test === undefined) {
tests = require.context('./cases', true, /.*\.js$/);
tests.keys().forEach(tests);
}
if (query.test === 'all' || query.test === 'gl' || query.test === undefined) {
tests = require.context('./gl-cases', true, /.*\.js$/);
tests.keys().forEach(tests);
}
if (query.test === 'all' || query.test === 'examples') {
tests = require.context('./example-cases', true, /.*\.js$/);
tests.keys().forEach(tests);
}
7 changes: 7 additions & 0 deletions tests/data/proxy-for-tests.pac
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
function FindProxyForURL(url, host) {
// Don't serve certain remote addresses
if (dnsDomainIs(host, "fonts.googleapis.com")) {
return "PROXY http://192.0.2.0";
}
return "DIRECT";
}
Loading