Skip to content

Commit

Permalink
Merge pull request #866 from OpenGeoscience/example-tests
Browse files Browse the repository at this point in the history
Add more support for testing examples.
  • Loading branch information
manthey authored Jul 13, 2018
2 parents dca5c39 + 61e62ea commit d24f8b3
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 80 deletions.
21 changes: 10 additions & 11 deletions examples/common/index.pug
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,9 @@ html(lang="en")
// include the main bundle
script(type='text/javascript', src=bundle, charset='UTF-8')

// include example sources
block exampleHeader
// Include example specific files
each css in exampleCss
link(rel="stylesheet", href=css)
each src in exampleJs
if(typeof src === "string")
script(type="text/javascript", src=src)
else
script&attributes(src)

// Include example specific css
each css in exampleCss
link(rel="stylesheet", href=css)
body
if !hideNavbar
// Add a navbar
Expand Down Expand Up @@ -70,3 +62,10 @@ html(lang="en")
// Add the default main content element
block mainContent
#map

// Include example specific scripts
each src in exampleJs
if(typeof src === "string")
script(type="text/javascript", src=src)
else
script&attributes(src)
21 changes: 19 additions & 2 deletions examples/contour/example.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@
"title": "Contour plot",
"exampleJs": ["main.js"],
"about": {
"text": "This example shows how to add contour features to a map. Contours color a region based on an array of scalar values."
}
"text": "This example shows how to add contour features to a map. Contours color a region based on an array of scalar values. If stepped colors are used, these are called isobands."
},
"tests": [{
"description": "contour feature loads small dataset",
"query": "url=../../data/oahu.json",
"wait": ["example.ready"],
"tests": [
"example.contour instanceof geo.contourFeature",
"example.contour._createContours().value.length === 1953"
]
}, {
"description": "contour feature loads dense dataset",
"query": "url=../../data/oahu-dense.json",
"wait": ["example.ready"],
"tests": [
"example.contour instanceof geo.contourFeature",
"example.contour._createContours().value.length === 194770"
]
}]
}
23 changes: 17 additions & 6 deletions examples/contour/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ $(function () {

// Define a function we will use to generate contours.
function makeContour(data, layer) {
/* There are two example data sets. One has a position array which
* consists of objects each with x, y, z values. The other has a values
* array which just has our contour values. */
// There are two example data sets. One has a position array which
// consists of objects each with x, y, z values. The other has a values
// array which just has our contour values.
var contour = layer.createFeature('contour')
.data(data.position || data.values)
.style({
Expand Down Expand Up @@ -47,8 +47,8 @@ $(function () {
value: function (d) { return d > -9999 ? d : null; }
})
.contour({
/* The geometry can be specified using 0-point coordinates and deltas
* since it is a regular grid. */
// The geometry can be specified using 0-point coordinates and deltas
// since it is a regular grid.
x0: data.x0, y0: data.y0, dx: data.dx, dy: data.dy
});
}
Expand Down Expand Up @@ -107,7 +107,18 @@ $(function () {
success: function (data) {
var contour = makeContour(data, contourLayer);
contour.draw();
/* After 10 second, load a denser data set */

// Make some values available in the global context to aid exploration
// and automated tests.
window.example = {
ready: true,
map: map,
contourLayer: contourLayer,
contour: contour,
data: data
};

// After 10 second, load a denser data set
if (!query.url) {
window.setTimeout(function () {
$.ajax({
Expand Down
10 changes: 9 additions & 1 deletion examples/isoline/example.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,13 @@
"exampleJs": ["main.js"],
"about": {
"text": "This example shows how to add isolines to a map."
}
},
"tests": [{
"description": "isoline feature is loaded and has text",
"wait": ["example.ready"],
"tests": [
"example.iso instanceof geo.isolineFeature",
"example.isolineLayer.children()[2].features()[0] instanceof geo.textFeature"
]
}]
}
114 changes: 56 additions & 58 deletions examples/isoline/main.js
Original file line number Diff line number Diff line change
@@ -1,63 +1,61 @@
// Run after the DOM loads
$(function () {
'use strict';

// Create a map object with the OpenStreetMaps base layer.
var map = geo.map({
node: '#map',
center: {
x: -157.965,
y: 21.482
},
zoom: 11
});
// Create a map object with the OpenStreetMaps base layer.
var map = geo.map({
node: '#map',
center: {
x: -157.965,
y: 21.482
},
zoom: 11
});

// Add a faint osm layer
map.createLayer('osm', {opacity: 0.5});
// Add a faint osm layer
map.createLayer('osm', {opacity: 0.5});

// Create a feature layer that supports contours
var isolineLayer = map.createLayer('feature', {
features: ['isoline']
});
// Create a feature layer that supports contours
var isolineLayer = map.createLayer('feature', {
features: ['isoline']
});

// Load the data
$.get('../../data/oahu-dense.json').done(function (data) {
// Create an isoline feature
var iso = isolineLayer.createFeature('isoline', {
isoline: {
// Specify our grid data
gridWidth: data.gridWidth,
gridHeight: data.gridHeight,
x0: data.x0,
y0: data.y0,
dx: data.dx,
dy: data.dy,
// Don't plot any values less than zero
min: 0,
// Create a contour line every 50 meters
spacing: 50,
// Make every 4th line heavier and every 4*5 = 20th line heavier yet
levels: [4, 5]
},
style: {
// The data uses -9999 to represent no value; modify it to return null
// instead.
value: function (d) { return d > -9999 ? d : null; },
// level relates to the isoline importance, with 0 being the most
// common and, using the levels specified, a level of 1 being every
// fourth, and 2 every twentieth line. Color the lines differently
// depending on the level
strokeColor: function (v, vi, d) {
return ['grey', 'mediumblue', 'blue'][d.level];
}
// Load the data
$.get('../../data/oahu-dense.json').done(function (data) {
// Create an isoline feature
var iso = isolineLayer.createFeature('isoline', {
isoline: {
// Specify our grid data
gridWidth: data.gridWidth,
gridHeight: data.gridHeight,
x0: data.x0,
y0: data.y0,
dx: data.dx,
dy: data.dy,
// Don't plot any values less than zero
min: 0,
// Create a contour line every 50 meters
spacing: 50,
// Make every 4th line heavier and every 4*5 = 20th line heavier yet
levels: [4, 5]
},
style: {
// The data uses -9999 to represent no value; modify it to return null
// instead.
value: function (d) { return d > -9999 ? d : null; },
// level relates to the isoline importance, with 0 being the most
// common and, using the levels specified, a level of 1 being every
// fourth, and 2 every twentieth line. Color the lines differently
// depending on the level
strokeColor: function (v, vi, d) {
return ['grey', 'mediumblue', 'blue'][d.level];
}
}).data(data.values).draw();
// Make some values available in the global context so curious people can
// play with them.
window.example = {
map: map,
isolineLayer: isolineLayer,
iso: iso
};
});
}
}).data(data.values).draw();

// Make some values available in the global context to aid exploration and
// automated tests.
window.example = {
ready: true,
map: map,
isolineLayer: isolineLayer,
iso: iso
};

});
138 changes: 138 additions & 0 deletions tests/headed-cases/examples.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/* In each examples/<path>/example.json, if there is a top-level key called
* "tests", this will run a test on that example. This key is an array of
* tests, each of which is an object with the following optional values:
* Partial example:
* "tests": [{
* "description": "test name", // a description of the test
* "htmlvideo": false, // if true, the test browser must support
* // video, or the test is skipped.
* "idle": [ // a list of idle functions or deferreds
* "map.onIdle" // an example idle function that will be
* ], // passed a function to call when idle
* "wait": [ // a list of expressions that will block
* // until they don't throw errors and
* // evaluate to truthy
* "map.layers().length >= 1" // an example wait expression
* ],
* "tests": [ // a list of expressions that must evaluate
* // to truthy for the tests to pass.
* "map.layers()[0] instanceof geo.tileLayer" // an example of a test
* ]
* }]
*/

/* Find all examples. */
var examples = require.context('../../examples', true, /\/example.json$/);

describe('examples', function () {
'use strict';

var $ = require('jquery');

var imageTest = require('../image-test');

beforeEach(function () {
imageTest.prepareIframeTest();
});

/* Test each example */
examples.keys().forEach(function (examplePath) {
var example;
try {
example = $.ajax({url: '/examples/' + examplePath, dataType: 'json', async: false}).responseJSON;
} catch (err) {
return;
}
if (!example || !example.tests) {
return;
}
var exampleName = examplePath.split('/')[1];
example.tests.forEach(function (test, idx) {
describe('Test ' + exampleName, function () {
/* Load the example in the test iframe */
beforeEach(function (done) {
sinon.stub(console, 'warn', function () {});
$('#map').one('load', function () {
/* allow logging to percolate through to our test environment */
$('iframe#map')[0].contentWindow.console = console;
window.setTimeout(done, 1);
});
$('#map').attr('src', '/examples/' + exampleName + '/index.html' + (test.query ? '?' + test.query : ''));
}, 150000);
afterEach(function () {
console.warn.restore();
});
it(test.description || ('Test ' + idx), function (done) {
/* Never complain if there are no explicit expect statements */
expect().nothing();
/* If a test requires html video and the current browser doesn't
* support video, skip the test. */
if (test.htmlvideo && !$('iframe#map')[0].contentWindow.HTMLVideoElement) {
done();
return;
}
var exampleWindow = $('iframe#map')[0].contentWindow,
ex$ = exampleWindow.$,
deferreds = [];
/* Description of the current example and test. */
var desc = $('iframe#map')[0].contentWindow.document.title + (test.description ? ' - ' + test.description : '');
/* Evaluate and wait for each idle function and promises. */
(test.idle || []).forEach(function (idleFunc) {
var defer = ex$.Deferred();
deferreds.push(defer);
var idle = exampleWindow.eval(idleFunc);
if (!ex$.isFunction(idle)) {
idle = idle.then || idle.done;
}
idle(function () {
defer.resolve();
});
});
(test.wait || []).forEach(function (waitCondition) {
var defer = ex$.Deferred();
deferreds.push(defer);
var interval;
interval = exampleWindow.setInterval(function () {
var result;
try {
result = exampleWindow.eval(waitCondition);
} catch (err) { }
if (result) {
exampleWindow.clearInterval(interval);
defer.resolve();
}
}, 10);
});
/* When all idle functions and wait conditions have resolved,
* evaluate each test in the tests list. */
ex$.when.apply(ex$, deferreds).then(function () {
var subtestDeferreds = [];
(test.tests || []).forEach(function (testExp) {
/* The test expression can return a value or a promise. We
* use jQuery's when to generically get the results in a
* resolution function. A rejection is a failure. */
try {
var testResult = exampleWindow.eval(testExp);
} catch (err) {
fail(desc + ' -> raised an error: ' + err);
return;
}
var subtestDefer = ex$.when(testResult).then(function (result) {
/* If the result isn't truthy, make sure our expect has a
* description telling which test block and specific test
* failed. */
expect(result).toBeTruthy(desc + ' -> ' + testExp);
}, function () {
fail(desc + ' promise failed -> ' + testExp);
});
subtestDeferreds.push(subtestDefer);
});
ex$.when.apply(ex$, subtestDeferreds).then(done);
}, function () {
fail(desc + ' -> idle functions were rejected');
});
}, 150000);
});
});
});
});
2 changes: 1 addition & 1 deletion tests/tutorials.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ describe('tutorials', function () {
sinon.stub(console, 'warn', function () {});
$('#map').one('load', function () { window.setTimeout(done, 1); });
$('#map').attr('src', '/tutorials/' + tutorialName + '/index.html');
});
}, 150000);
afterEach(function () {
console.warn.restore();
});
Expand Down
2 changes: 1 addition & 1 deletion website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"hexo-renderer-marked": "^0.3.2",
"hexo-renderer-scss": "^1.0.3",
"hexo-renderer-stylus": "^0.3.1",
"hexo-server": "^0.2.0"
"hexo-server": "^0.3.1"
},
"devDependencies": {
"ejs-lint": "^0.3.0",
Expand Down

0 comments on commit d24f8b3

Please sign in to comment.