Skip to content

Commit

Permalink
Merge pull request #725 from OpenGeoscience/tutorial
Browse files Browse the repository at this point in the history
Add tutorial infrastructure.
  • Loading branch information
manthey authored Aug 3, 2017
2 parents efec8cb + 9ffad58 commit f302872
Show file tree
Hide file tree
Showing 29 changed files with 1,060 additions and 16 deletions.
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ built/
bower_components/
dist/
.eslintcache
tutorials/
18 changes: 18 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ if(PHANTOMJS_TESTS)
set_property(TEST "phantomjs" APPEND PROPERTY DEPENDS "notes-reset")
set_property(TEST "notes-report" APPEND PROPERTY DEPENDS "phantomjs")
set_property(TEST "total-coverage" APPEND PROPERTY DEPENDS "phantomjs")

add_test(
NAME "tutorials"
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
COMMAND npm run tutorialsci
)
set_property(TEST "tutorials" APPEND PROPERTY DEPENDS "build_tutorials")
set_property(TEST "total-coverage" APPEND PROPERTY DEPENDS "tutorials")
endif()

add_custom_target(
Expand All @@ -98,6 +106,16 @@ 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")

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

if(FFHEADLESS_TESTS)
find_program(NPM_EXECUTABLE npm)
add_test(
Expand Down
2 changes: 1 addition & 1 deletion examples/tiles/index.pug
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ block append mainContent
datalist#url-list
option(value="http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", credit="© OpenStreetMap contributors") OSM
option(value="../../data/tilefancy.png", credit="") Fancy Test Tile
option(value="http://tile.stamen.com/toner-lite/{z}/{x}/{y}.png", credit='Map tiles by <a href="http://stamen.com"<Stamen Design</a<, under <a href="http://creativecommons.org/licenses/by/3.0"<CC BY 3.0</a<. Data by <a href="http://openstreetmap.org"<OpenStreetMap</a<, under <a href="http://www.openstreetmap.org/copyright"<ODbL</a<.') Toner Lite
option(value="http://tile.stamen.com/toner-lite/{z}/{x}/{y}.png", credit='Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>.') Toner Lite
.form-group(title="The subdomains used to fetch tiles. This can be a comma-separated list or a string of single-letter subdomains.")
label(for="layer-subdomains") URL Subdomains
input#layer-subdomains.layerparam(param-name="subdomains", placeholder="abc")
Expand Down
8 changes: 6 additions & 2 deletions karma-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,12 +214,16 @@ module.exports = function (config) {
{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}
{pattern: 'dist/examples/**/*', included: false},
{pattern: 'dist/tutorials/**/*', included: false},
{pattern: 'dist/built/**/*', included: false}
],
proxies: {
'/testdata/': '/base/tests/data/',
'/data/': '/base/dist/data/',
'/examples/': '/base/dist/examples/'
'/examples/': '/base/dist/examples/',
'/tutorials/': '/base/dist/tutorials/',
'/built/': '/base/dist/built/'
},
browsers: [
'PhantomJS'
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"jsdoc": "^3.4",
"jsdoc-autoprivate": "0.0.1",
"json-loader": "^0.5.4",
"jstransformer-markdown-it": "^2.0.0",
"karma": "^0.13.22",
"karma-coverage": "^1.0.0",
"karma-firefox-launcher": "^1.0.0",
Expand Down Expand Up @@ -85,13 +86,15 @@
"scripts": {
"build": "webpack --config webpack.config.js && webpack --config external.config.js",
"build-examples": "webpack --config webpack-examples.config.js",
"build-tutorials": "webpack --config webpack-tutorials.config.js",
"lint": "eslint --cache .",
"puglint": "pug-lint src examples",
"test": "GEOJS_TEST_CASE=tests/test-unit.js karma start karma-cov.conf.js --single-run --browsers PhantomJS",
"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",
"tutorialsci": "GEOJS_TEST_CASE=tests/tutorials.js karma start karma-cov.conf.js --single-run --browsers PhantomJS",
"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": "codecov",
Expand Down
4 changes: 2 additions & 2 deletions src/fetchQueue.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ module.exports = (function () {
return defer;
}
}
var wait = new $.Deferred();
var process = new $.Deferred();
var wait = $.Deferred();
var process = $.Deferred();
wait.then(function () {
$.when(callback.call(defer)).always(process.resolve);
}, process.resolve);
Expand Down
11 changes: 6 additions & 5 deletions src/imageTile.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@ module.exports = (function () {
spec.size = spec.size || {x: 256, y: 256};
this._image = null;

// Cache the coordinate scaling
this._cors = spec.crossDomain || 'anonymous';
this._cors = (spec.crossDomain || spec.crossDomain === null) ? spec.crossDomain : 'anonymous';

// Call superclass constructor
tile.call(this, spec);
Expand All @@ -62,17 +61,19 @@ module.exports = (function () {

/**
* Initiate the image request.
*
* @returns {this} The current tile class instance.
*/
this.fetch = function () {
var defer;
if (!this._image) {
this._image = new Image(this.size.x, this.size.y);
// Only set the crossOrigin parameter if this is going across origins.
if (this._url.indexOf(':') >= 0 &&
if (this._cors && this._url.indexOf(':') >= 0 &&
this._url.indexOf('/') === this._url.indexOf(':') + 1) {
this._image.crossOrigin = this._cors;
}
defer = new $.Deferred();
defer = $.Deferred();
this._image.onload = defer.resolve;
this._image.onerror = defer.reject;
this._image.src = this._url;
Expand All @@ -93,7 +94,7 @@ module.exports = (function () {
* @returns {this} chainable
*/
this.fadeIn = function (duration) {
var promise = this.fetch(), defer = new $.Deferred();
var promise = this.fetch(), defer = $.Deferred();
$(this._image).css('display', 'none');
promise.then(function () {
$(this._image).fadeIn(duration, function () {
Expand Down
5 changes: 3 additions & 2 deletions src/osmLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module.exports = (function () {
var quadFeature = require('./quadFeature');

/**
* Create a new instance of osmLayer
* Create a new instance of osmLayer.
*
* @class geo.osmLayer
* @extends geo.featureLayer
Expand Down Expand Up @@ -56,7 +56,8 @@ module.exports = (function () {
scale: this._options.tileScale,
url: this._options.url.call(
this, urlParams.x, urlParams.y, urlParams.level || 0,
this._options.subdomains)
this._options.subdomains),
crossDomain: this._options.crossDomain
});
}.bind(this);
};
Expand Down
2 changes: 1 addition & 1 deletion src/pixelmapFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ var pixelmapFeature = function (arg) {
m_srcImage = src;
this._computePixelmap();
} else if (src) {
var defer = new $.Deferred(), prev_onload, prev_onerror;
var defer = $.Deferred(), prev_onload, prev_onerror;
if (src instanceof Image) {
/* we have an unloaded image. Hook to the load and error callbacks
* so that when it is loaded we can use it. */
Expand Down
2 changes: 1 addition & 1 deletion src/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ transform.defs = proj4.defs;
*/
transform.lookup = function (projection) {
var $ = require('jquery');
var code, defer = new $.Deferred(), parts;
var code, defer = $.Deferred(), parts;

if (proj4.defs.hasOwnProperty(projection)) {
return defer.resolve(proj4.defs[projection]);
Expand Down
4 changes: 2 additions & 2 deletions tests/cases/tileLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -641,8 +641,8 @@ describe('geo.tileLayer', function () {
});
it('prefetch', function (done) {
var l = geo.tileLayer({map: map(), url: function () { return '/testdata/white.jpg'; }}),
d1 = new $.Deferred(),
d2 = new $.Deferred();
d1 = $.Deferred(),
d2 = $.Deferred();

// replace the standard getTiles method to return our pseudo-tiles
l._getTiles = function (level, bounds) {
Expand Down
94 changes: 94 additions & 0 deletions tests/tutorials.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/* Find all tutorials. */
var tutorials = require.context('../tutorials', true, /\/tutorial.json$/);

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

var $ = require('jquery');

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

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

/* Test each tutorial */
tutorials.keys().forEach(function (tutorialPath) {
var tutorialName = tutorialPath.split('/')[1];
describe('Test ' + tutorialName, function () {
/* Load the tutorial in the test iframe */
beforeEach(function (done) {
$('#map').one('load', done);
$('#map').attr('src', '/tutorials/' + tutorialName + '/index.html');
});
it('Run tutorial tests', function (done) {
var base$, tests;

base$ = $('iframe#map')[0].contentWindow.jQuery;
/* Find all codeblock_tests. We chain them together and end on the it
* function's done callback, so reverse them so that they run in the
* order written. */
tests = base$(base$('.codeblock_test').get().reverse());
tests.each(function (testIdx) {
var test = base$(this),
codeblock = test.prevAll('.codeblock').eq(0),
target = base$('#' + codeblock.attr('target')),
testDefer = $.Deferred();
testDefer.then(done);
done = function () {
/* When the codeblock's target has runm handle the results */
var onCodeLoaded = function () {
var targetWindow = target[0].contentWindow,
tut$ = targetWindow.$,
deferreds = [];
/* Evaluate and wait for each idle function and promises. */
test.data('idlefuncs').forEach(function (idleFunc) {
var defer = tut$.Deferred();
deferreds.push(defer);
var idle = targetWindow.eval(idleFunc);
if (!tut$.isFunction(idle)) {
idle = idle.done;
}
idle(function () {
defer.resolve();
});
});
/* When all idle functions have resolved, evaluate each test in
* the test list. */
tut$.when.apply(tut$, deferreds).fail(function () {
throw new Error('Idle functions were rejected');
}).then(function () {
test.data('tests').forEach(function (testExp) {
var result = targetWindow.eval(testExp);
/* If the result isn't truthy, make sure our expect has a
* description telling which test block and specific test
* failed. */
expect(result).toBeTruthy(test.data('description') + ' -> ' + testExp);
});
testDefer.resolve();
});
};
/* If we have already run the specific codeblock, don't run it
* again. If not, click run and wait for the results. On the
* first test (which will be the last added), always force the code
* block to run, as it ensures that we catch the load event. */
if (codeblock.is(base$('.codeblock.active:last')) && testIdx !== tests.length - 1) {
onCodeLoaded();
} else {
target.one('load', onCodeLoaded);
if (testIdx !== tests.length - 1) {
codeblock.find('.codeblock_run').click();
} else {
var evt = base$.Event('click');
evt.shiftKey = true;
codeblock.find('.codeblock_run').trigger(evt);
}
}
};
});
/* Call the first step in the chained tests */
done();
}, 15000);
});
});
});
8 changes: 8 additions & 0 deletions tutorials/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"globals": {
"d3": true,
"geo": true,
"$": true,
"CodeMirror": true
}
}
73 changes: 73 additions & 0 deletions tutorials/basic/index.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
extends ../common/index.pug

block mainTutorial
:markdown-it
# Tutorial - Simple Map
We need a little bit of html to import the geojs library and to create a div to show our map:

+codeblock('html', 1).
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="../../built/geo.min.js"></script>
<script type="text/javascript" src="../../built/geo.ext.min.js"></script>
</head>
<body>
<div id="map"></div>
</body>
</html>

:markdown-it
The second script, ``geo.ext.min.js``, is optional. It adds support
for svg elements and touch interaction.

Some CSS will make our map fill the page:

+codeblock('css', 2).
html,body,#map{
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}

:markdown-it
And some javascript to ask for a map and place the default map tiles on it:

+codeblock('javascript', 3, undefined, true).
var map = geo.map({
node: "#map"
});
map.createLayer('osm');
+codeblock_test('map has one layer',
'map.layers().length === 1')
+codeblock_test('first layer is an osmLayer',
'map.layers()[0] instanceof geo.osmLayer')
+codeblock_test('zoom is 4',
'map.zoom() === 4')

:markdown-it
Move the map to Kensington Gardens, London and zoom in.

+codeblock('javascript', 4).
map.center({x: -0.1704, y: 51.5047}).zoom(14);
+codeblock_test('zoom is 14',
'map.zoom() === 14'
)

:markdown-it
We could have started the map at this location by adding the center and
zoom parameters to the initial ``map()`` call:

+codeblock('javascript', 5, 2, false, 'Step 3-B').
var map = geo.map({
node: "#map",
center: {x: -0.1704, y: 51.5047},
zoom: 14
});
map.createLayer('osm');
+codeblock_test('map has one osm layer and zoom is 14', [
'map.layers().length === 1',
'map.layers()[0] instanceof geo.osmLayer',
'map.zoom() === 14'
])
11 changes: 11 additions & 0 deletions tutorials/basic/tutorial.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"title": "Simple Map",
"hideNavbar": true,
"level": 0,
"order": 0,
"tutorialCss": [],
"tutorialJs": [],
"about": {
"text": "Make a simple map. Includes HTML, CSS, and Javascript."
}
}
Loading

0 comments on commit f302872

Please sign in to comment.