Skip to content

Commit

Permalink
Merge pull request #658 from OpenGeoscience/test-examples
Browse files Browse the repository at this point in the history
Test examples
  • Loading branch information
manthey authored Jan 10, 2017
2 parents 42417cd + f85f792 commit 60b1b2b
Show file tree
Hide file tree
Showing 22 changed files with 336 additions and 107 deletions.
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/``
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 docs/provisioning.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ convenience in configuring CMake options) ::
sudo apt-get install --yes \
cmake \
firefox \
imagemagick \
git \
libjpeg8-dev \
libpango1.0-dev \
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;
}
4 changes: 4 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,9 @@ $(function () {
lineFeature.draw();
var text = 'Shown: ' + segments;
$('#lines-shown').text(text).attr('title', text);
map.onIdle(function () {
$('#map').addClass('ready');
});
}

/**
Expand Down
165 changes: 109 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,84 @@ 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
},
resolve: webpack_config.resolve,
plugins: webpack_config.exposed_plugins
}
/**
* Express style middleware to handle REST requests for OSM tiles on the test
* server.
*/
var osmtiles_middleware = function (config) {
return function (request, response, next) {
var match = request.url.match(/.*http:\/\/[a-c]\.tile.openstreetmap.org\/([0-9]+\/[0-9]+\/[0-9]+.png)$/);
/* Serve tiles if they have been proxied */
if (match && request.method === 'GET') {
var imagePath = 'dist/data/tiles/' + match[1];
var img = new Buffer(fs.readFileSync(imagePath));
response.setHeader('Content-Type', 'image/png');
response.setHeader('Content-Length', img.length);
response.setHeader('Access-Control-Allow-Origin', '*');
response.writeHead(200);
return response.end(img);
}
next();
};
};

module.exports.preprocessors[test_case] = ['webpack', 'sourcemap'];
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/'
},
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',
'osmtiles'
],
plugins: [
{'middleware:notes': ['factory', notes_middleware]},
{'middleware:osmtiles': ['factory', osmtiles_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'];
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
914356846f8c541a813bb7e53efc6c57
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/586d1ff18d777f05f44a5c75/download
2 changes: 1 addition & 1 deletion testing/test-data/tiles.tgz.md5
Original file line number Diff line number Diff line change
@@ -1 +1 @@
73d3e6e8800e5d82d5f668413379373a
910b4894cc906dc3762dc9e314fd4025
Loading

0 comments on commit 60b1b2b

Please sign in to comment.