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

Add tutorial infrastructure. #725

Merged
merged 3 commits into from
Aug 3, 2017
Merged
Show file tree
Hide file tree
Changes from all 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
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