diff --git a/examples/mapbox-vector-tiles-simple.css b/examples/mapbox-vector-tiles-simple.css
new file mode 100644
index 0000000000..33e90f7301
--- /dev/null
+++ b/examples/mapbox-vector-tiles-simple.css
@@ -0,0 +1,3 @@
+.map {
+ background: #f8f4f0;
+}
diff --git a/examples/mapbox-vector-tiles-simple.html b/examples/mapbox-vector-tiles-simple.html
new file mode 100644
index 0000000000..36da8db103
--- /dev/null
+++ b/examples/mapbox-vector-tiles-simple.html
@@ -0,0 +1,15 @@
+---
+template: example.html
+title: Simple Mapbox vector tiles example
+shortdesc: Example of a simple Mapbox vector tiles map.
+docs: >
+ A simple vector tiles map. **Note**: Make sure to get your own Mapbox API key when using this example. No map will be visible when the API key has expired.
+tags: "simple, mapbox, vector, tiles"
+resources:
+ - resources/mapbox-streets-v6-style.js
+---
+
diff --git a/examples/mapbox-vector-tiles-simple.js b/examples/mapbox-vector-tiles-simple.js
new file mode 100644
index 0000000000..3d68525c4d
--- /dev/null
+++ b/examples/mapbox-vector-tiles-simple.js
@@ -0,0 +1,44 @@
+goog.require('ol.Attribution');
+goog.require('ol.Map');
+goog.require('ol.View');
+goog.require('ol.format.MVT');
+goog.require('ol.layer.VectorTile');
+goog.require('ol.source.VectorTile');
+goog.require('ol.style.Fill');
+goog.require('ol.style.Icon');
+goog.require('ol.style.Stroke');
+goog.require('ol.style.Style');
+goog.require('ol.style.Text');
+
+
+// Mapbox access token - request your own at http://mapbox.com
+var accessToken =
+ 'pk.eyJ1IjoiYWhvY2V2YXIiLCJhIjoiRk1kMWZaSSJ9.E5BkluenyWQMsBLsuByrmg';
+
+var map = new ol.Map({
+ layers: [
+ new ol.layer.VectorTile({
+ source: new ol.source.VectorTile({
+ attributions: [new ol.Attribution({
+ html: '© Mapbox ' +
+ '© ' +
+ 'OpenStreetMap contributors'
+ })],
+ format: new ol.format.MVT(),
+ tileGrid: ol.tilegrid.createXYZ({maxZoom: 22}),
+ tilePixelRatio: 16,
+ url: 'http://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/' +
+ '{z}/{x}/{y}.vector.pbf?access_token=' + accessToken
+ }),
+ style: createMapboxStreetsV6Style()
+ })
+ ],
+ target: 'map',
+ view: new ol.View({
+ center: [0, 0],
+ zoom: 2
+ })
+});
+
+// ol.style.Fill, ol.style.Icon, ol.style.Stroke, ol.style.Style and
+// ol.style.Text are required for createMapboxStreetsV6Style()
diff --git a/examples/mapbox-vector-tiles.html b/examples/mapbox-vector-tiles.html
index ec0744b5f7..c7cb0b45d3 100644
--- a/examples/mapbox-vector-tiles.html
+++ b/examples/mapbox-vector-tiles.html
@@ -3,7 +3,7 @@ template: example.html
title: Mapbox vector tiles example
shortdesc: Example of a Mapbox vector tiles map.
docs: >
- A simple vector tiles map.
+ A vector tiles map which reuses the same tiles for subsequent zoom levels to save bandwith on mobile devices. **Note**: Make sure to get your own Mapbox API key when using this example. No map will be visible when the API key has expired.
tags: "simple, mapbox, vector, tiles"
resources:
- resources/mapbox-streets-v6-style.js
diff --git a/examples/mapbox-vector-tiles.js b/examples/mapbox-vector-tiles.js
index ad1a5d8816..4506437370 100644
--- a/examples/mapbox-vector-tiles.js
+++ b/examples/mapbox-vector-tiles.js
@@ -13,21 +13,36 @@ goog.require('ol.style.Text');
goog.require('ol.tilegrid.TileGrid');
-// Mapbox access token - request your own at http://mabobox.com
+// Mapbox access token - request your own at http://mapbox.com
var accessToken =
'pk.eyJ1IjoiYWhvY2V2YXIiLCJhIjoiRk1kMWZaSSJ9.E5BkluenyWQMsBLsuByrmg';
-// For how many zoom levels do we want to use the same vector tile?
+// For how many zoom levels do we want to use the same vector tiles?
+// 1 means "use tiles from all zoom levels". 2 means "use the same tiles for 2
+// subsequent zoom levels".
var reuseZoomLevels = 2;
-// Offset from web mercator zoom level 0
-var zOffset = 1;
+// Offset of loaded tiles from web mercator zoom level 0.
+// 0 means "At map zoom level 0, use tiles from zoom level 0". 1 means "At map
+// zoom level 0, use tiles from zoom level 1".
+var zoomOffset = 1;
+
+// Calculation of tile urls
var resolutions = [];
-for (var z = zOffset / reuseZoomLevels; z <= 22 / reuseZoomLevels; ++z) {
+for (var z = zoomOffset / reuseZoomLevels; z <= 22 / reuseZoomLevels; ++z) {
resolutions.push(156543.03392804097 / Math.pow(2, z * reuseZoomLevels));
}
+function tileUrlFunction(tileCoord) {
+ return ('http://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/' +
+ '{z}/{x}/{y}.vector.pbf?access_token=' + accessToken)
+ .replace('{z}', String(tileCoord[0] * reuseZoomLevels + zoomOffset))
+ .replace('{x}', String(tileCoord[1]))
+ .replace('{y}', String(-tileCoord[2] - 1))
+ .replace('{a-d}', 'abcd'.substr(
+ ((tileCoord[1] << tileCoord[0]) + tileCoord[2]) % 4, 1));
+}
-var map = new ol.Map({
+var map = new ol.Map({
layers: [
new ol.layer.VectorTile({
preload: Infinity,
@@ -37,22 +52,13 @@ var map = new ol.Map({
'© ' +
'OpenStreetMap contributors'
})],
- rightHandedPolygons: true,
format: new ol.format.MVT(),
tileGrid: new ol.tilegrid.TileGrid({
extent: ol.proj.get('EPSG:3857').getExtent(),
resolutions: resolutions
}),
tilePixelRatio: 16,
- tileUrlFunction: function(tileCoord) {
- return ('http://{a-d}.tiles.mapbox.com/v4/mapbox.mapbox-streets-v6/' +
- '{z}/{x}/{y}.vector.pbf?access_token=' + accessToken)
- .replace('{z}', String(tileCoord[0] * reuseZoomLevels + zOffset))
- .replace('{x}', String(tileCoord[1]))
- .replace('{y}', String(-tileCoord[2] - 1))
- .replace('{a-d}', 'abcd'.substr(
- ((tileCoord[1] << tileCoord[0]) + tileCoord[2]) % 4, 1));
- }
+ tileUrlFunction: tileUrlFunction
}),
style: createMapboxStreetsV6Style()
})
@@ -64,3 +70,6 @@ var map = new ol.Map({
zoom: 3
})
});
+
+// ol.style.Fill, ol.style.Icon, ol.style.Stroke, ol.style.Style and
+// ol.style.Text are required for createMapboxStreetsV6Style()
diff --git a/src/ol/layer/vectortilelayer.js b/src/ol/layer/vectortilelayer.js
index a3330d414f..31797e1170 100644
--- a/src/ol/layer/vectortilelayer.js
+++ b/src/ol/layer/vectortilelayer.js
@@ -16,7 +16,7 @@ ol.layer.VectorTileProperty = {
/**
* @classdesc
- * Vector tile data that is rendered client-side.
+ * Layer for vector tile data that is rendered client-side.
* Note that any property set in the options is set as a {@link ol.Object}
* property on the layer object; for example, setting `title: 'My Title'` in the
* options means that `title` is observable, and has get/set accessors.
diff --git a/src/ol/render/renderfeature.js b/src/ol/render/renderfeature.js
index 21bc706cd9..4a147fed7d 100644
--- a/src/ol/render/renderfeature.js
+++ b/src/ol/render/renderfeature.js
@@ -10,7 +10,7 @@ goog.require('ol.geom.GeometryType');
/**
* Lightweight, read-only, {@link ol.Feature} and {@link ol.geom.Geometry} like
- * structure, optimized for rendering and styling. Geometry acces through the
+ * structure, optimized for rendering and styling. Geometry access through the
* API is limited to getting the type and extent of the geometry.
*
* @constructor
diff --git a/src/ol/source/vectorsource.js b/src/ol/source/vectorsource.js
index d36696c86f..cb708c0891 100644
--- a/src/ol/source/vectorsource.js
+++ b/src/ol/source/vectorsource.js
@@ -66,7 +66,9 @@ ol.source.VectorEventType = {
/**
* @classdesc
- * Provides a source of features for vector layers.
+ * Provides a source of features for vector layers. Vector features provided
+ * by this source are suitable for editing. See {@link ol.source.VectorTile} for
+ * vector data that is optimized for rendering.
*
* @constructor
* @extends {ol.source.Source}
diff --git a/src/ol/source/vectortilesource.js b/src/ol/source/vectortilesource.js
index 4b264bcbff..4e8e2b4476 100644
--- a/src/ol/source/vectortilesource.js
+++ b/src/ol/source/vectortilesource.js
@@ -12,7 +12,13 @@ goog.require('ol.source.UrlTile');
/**
* @classdesc
- * Base class for sources providing images divided into a tile grid.
+ * Class for layer sources providing vector data divided into a tile grid, to be
+ * used with {@link ol.layer.VectorTile}. Although this source receives tiles
+ * with vector features from the server, it is not meant for feature editing.
+ * Features are optimized for rendering, their geometries are clipped at or near
+ * tile boundaries and simplified for a view resolution. See
+ * {@link ol.source.Vector} for vector sources that are suitable for feature
+ * editing.
*
* @constructor
* @fires ol.source.TileEvent
diff --git a/test/spec/ol/layer/vectortilelayer.test.js b/test/spec/ol/layer/vectortilelayer.test.js
new file mode 100644
index 0000000000..4ced5c282e
--- /dev/null
+++ b/test/spec/ol/layer/vectortilelayer.test.js
@@ -0,0 +1,37 @@
+goog.provide('ol.test.layer.VectorTile');
+
+describe('ol.layer.VectorTile', function() {
+
+ describe('constructor (defaults)', function() {
+
+ var layer;
+
+ beforeEach(function() {
+ layer = new ol.layer.VectorTile({
+ source: new ol.source.VectorTile({})
+ });
+ });
+
+ afterEach(function() {
+ goog.dispose(layer);
+ });
+
+ it('creates an instance', function() {
+ expect(layer).to.be.a(ol.layer.VectorTile);
+ });
+
+ it('provides default preload', function() {
+ expect(layer.getPreload()).to.be(0);
+ });
+
+ it('provides default useInterimTilesOnError', function() {
+ expect(layer.getUseInterimTilesOnError()).to.be(true);
+ });
+
+ });
+
+});
+
+goog.require('goog.dispose');
+goog.require('ol.layer.VectorTile');
+goog.require('ol.source.VectorTile');
diff --git a/test/spec/ol/render/renderfeature.test.js b/test/spec/ol/render/renderfeature.test.js
new file mode 100644
index 0000000000..622cfaddc4
--- /dev/null
+++ b/test/spec/ol/render/renderfeature.test.js
@@ -0,0 +1,90 @@
+goog.provide('ol.test.render.Feature');
+
+describe('ol.render.Feature', function() {
+
+ var renderFeature;
+ var type = 'Point';
+ var flatCoordinates = [0, 0];
+ var ends = null;
+ var properties = {foo: 'bar'};
+
+ describe('Constructor', function() {
+ it('creates an instance', function() {
+ renderFeature =
+ new ol.render.Feature(type, flatCoordinates, ends, properties);
+ expect(renderFeature).to.be.a(ol.render.Feature);
+ });
+ });
+
+ describe('#get()', function() {
+ it('returns a single property', function() {
+ expect(renderFeature.get('foo')).to.be('bar');
+ });
+ });
+
+ describe('#getEnds()', function() {
+ it('returns the ends it was created with', function() {
+ expect(renderFeature.getEnds()).to.equal(ends);
+ });
+ });
+
+ describe('#getExtent()', function() {
+ it('returns the correct extent for a point', function() {
+ expect(renderFeature.getExtent()).to.eql([0, 0, 0, 0]);
+ });
+ it('caches the extent', function() {
+ expect(renderFeature.getExtent()).to.equal(renderFeature.extent_);
+ });
+ it('returns the correct extent for a linestring', function() {
+ var feature =
+ new ol.render.Feature('LineString', [-1, -2, 2, 1], null, {});
+ expect(feature.getExtent()).to.eql([-1, -2, 2, 1]);
+ });
+ });
+
+ describe('#getFlatCoordinates()', function() {
+ it('returns the flat coordinates it was created with', function() {
+ expect(renderFeature.getFlatCoordinates()).to.equal(flatCoordinates);
+ });
+ });
+
+ describe('#getGeometry()', function() {
+ it('returns itself as geometry', function() {
+ expect(renderFeature.getGeometry()).to.equal(renderFeature);
+ });
+ });
+
+ describe('#getProperties()', function() {
+ it('returns the properties it was created with', function() {
+ expect(renderFeature.getProperties()).to.equal(properties);
+ });
+ });
+
+ describe('#getSimplifiedGeometry()', function() {
+ it('returns itself as simplified geometry', function() {
+ expect(renderFeature.getSimplifiedGeometry()).to.equal(renderFeature);
+ });
+ });
+
+ describe('#getStride()', function() {
+ it('returns 2', function() {
+ expect(renderFeature.getStride()).to.be(2);
+ });
+ });
+
+ describe('#getStyleFunction()', function() {
+ it('returns undefined', function() {
+ expect(renderFeature.getStyleFunction()).to.be(undefined);
+ });
+ });
+
+ describe('#getType()', function() {
+ it('returns the type it was created with', function() {
+ expect(renderFeature.getType()).to.equal(type);
+ });
+ });
+
+});
+
+
+goog.require('ol.render.Feature');
diff --git a/test/spec/ol/renderer/canvas/canvasvectortilelayerrenderer.test.js b/test/spec/ol/renderer/canvas/canvasvectortilelayerrenderer.test.js
new file mode 100644
index 0000000000..da228a61c0
--- /dev/null
+++ b/test/spec/ol/renderer/canvas/canvasvectortilelayerrenderer.test.js
@@ -0,0 +1,128 @@
+goog.provide('ol.test.renderer.canvas.VectorTileLayer');
+
+describe('ol.renderer.canvas.VectorTileLayer', function() {
+
+ describe('constructor', function() {
+
+ it('creates a new instance', function() {
+ var layer = new ol.layer.VectorTile({
+ source: new ol.source.VectorTile({})
+ });
+ var renderer = new ol.renderer.canvas.VectorTileLayer(layer);
+ expect(renderer).to.be.a(ol.renderer.canvas.VectorTileLayer);
+ });
+
+ it('gives precedence to feature styles over layer styles', function() {
+ var target = document.createElement('div');
+ target.style.width = '256px';
+ target.style.height = '256px';
+ document.body.appendChild(target);
+ var map = new ol.Map({
+ view: new ol.View({
+ center: [0, 0],
+ zoom: 0
+ }),
+ target: target
+ });
+ var layerStyle = [new ol.style.Style({
+ text: new ol.style.Text({
+ text: 'layer'
+ })
+ })];
+ var featureStyle = [new ol.style.Style({
+ text: new ol.style.Text({
+ text: 'feature'
+ })
+ })];
+ var feature1 = new ol.Feature(new ol.geom.Point([0, 0]));
+ var feature2 = new ol.Feature(new ol.geom.Point([0, 0]));
+ feature2.setStyle(featureStyle);
+ var TileClass = function() {
+ ol.VectorTile.apply(this, arguments);
+ this.setState('loaded');
+ this.setFeatures([feature1, feature2]);
+ this.setProjection(ol.proj.get('EPSG:3857'));
+ };
+ ol.inherits(TileClass, ol.VectorTile);
+ var source = new ol.source.VectorTile({
+ format: new ol.format.MVT(),
+ tileClass: TileClass,
+ tileGrid: ol.tilegrid.createXYZ()
+ });
+ var layer = new ol.layer.VectorTile({
+ source: source,
+ style: layerStyle
+ });
+ map.addLayer(layer);
+ var spy = sinon.spy(map.getRenderer().getLayerRenderer(layer),
+ 'renderFeature');
+ map.renderSync();
+ expect(spy.getCall(0).args[2]).to.be(layerStyle);
+ expect(spy.getCall(1).args[2]).to.be(featureStyle);
+ document.body.removeChild(target);
+ });
+
+ });
+
+ describe('#forEachFeatureAtCoordinate', function() {
+ var layer, renderer, replayGroup;
+ var TileClass = function() {
+ ol.VectorTile.apply(this, arguments);
+ this.setState('loaded');
+ this.setProjection(ol.proj.get('EPSG:3857'));
+ this.replayState_.replayGroup = replayGroup;
+ };
+ ol.inherits(TileClass, ol.VectorTile);
+
+ beforeEach(function() {
+ replayGroup = {};
+ layer = new ol.layer.VectorTile({
+ source: new ol.source.VectorTile({
+ tileClass: TileClass,
+ tileGrid: ol.tilegrid.createXYZ()
+ })
+ });
+ renderer = new ol.renderer.canvas.VectorTileLayer(layer);
+ replayGroup.forEachFeatureAtCoordinate = function(coordinate,
+ resolution, rotation, skippedFeaturesUids, callback) {
+ var feature = new ol.Feature();
+ callback(feature);
+ callback(feature);
+ };
+ });
+
+ it('calls callback once per feature with a layer as 2nd arg', function() {
+ var spy = sinon.spy();
+ var coordinate = [0, 0];
+ var frameState = {
+ layerStates: {},
+ skippedFeatureUids: {},
+ viewState: {
+ resolution: 1,
+ rotation: 0
+ }
+ };
+ frameState.layerStates[goog.getUid(layer)] = {};
+ renderer.renderedTiles_ = [new TileClass([0, 0, -1])];
+ renderer.forEachFeatureAtCoordinate(
+ coordinate, frameState, spy, undefined);
+ expect(spy.callCount).to.be(1);
+ expect(spy.getCall(0).args[1]).to.equal(layer);
+ });
+ });
+
+});
+
+
+goog.require('ol.Feature');
+goog.require('ol.Map');
+goog.require('ol.VectorTile');
+goog.require('ol.View');
+goog.require('ol.format.MVT');
+goog.require('ol.geom.Point');
+goog.require('ol.layer.VectorTile');
+goog.require('ol.proj');
+goog.require('ol.renderer.canvas.VectorTileLayer');
+goog.require('ol.source.VectorTile');
+goog.require('ol.style.Style');
+goog.require('ol.style.Text');
diff --git a/test/spec/ol/source/urltilesource.test.js b/test/spec/ol/source/urltilesource.test.js
new file mode 100644
index 0000000000..8273b5956a
--- /dev/null
+++ b/test/spec/ol/source/urltilesource.test.js
@@ -0,0 +1,162 @@
+goog.provide('ol.test.source.UrlTile');
+
+
+describe('ol.source.UrlTile', function() {
+
+ describe('tileUrlFunction', function() {
+
+ var tileSource, tileGrid;
+
+ beforeEach(function() {
+ tileSource = new ol.source.UrlTile({
+ projection: 'EPSG:3857',
+ tileGrid: ol.tilegrid.createXYZ({maxZoom: 6}),
+ url: '{z}/{x}/{y}',
+ wrapX: true
+ });
+ tileGrid = tileSource.getTileGrid();
+ });
+
+ it('returns the expected URL', function() {
+
+ var coordinate = [829330.2064098881, 5933916.615134273];
+ var tileUrl;
+
+ tileUrl = tileSource.tileUrlFunction(
+ tileGrid.getTileCoordForCoordAndZ(coordinate, 0));
+ expect(tileUrl).to.eql('0/0/0');
+
+ tileUrl = tileSource.tileUrlFunction(
+ tileGrid.getTileCoordForCoordAndZ(coordinate, 1));
+ expect(tileUrl).to.eql('1/1/0');
+
+ tileUrl = tileSource.tileUrlFunction(
+ tileGrid.getTileCoordForCoordAndZ(coordinate, 2));
+ expect(tileUrl).to.eql('2/2/1');
+
+ tileUrl = tileSource.tileUrlFunction(
+ tileGrid.getTileCoordForCoordAndZ(coordinate, 3));
+ expect(tileUrl).to.eql('3/4/2');
+
+ tileUrl = tileSource.tileUrlFunction(
+ tileGrid.getTileCoordForCoordAndZ(coordinate, 4));
+ expect(tileUrl).to.eql('4/8/5');
+
+ tileUrl = tileSource.tileUrlFunction(
+ tileGrid.getTileCoordForCoordAndZ(coordinate, 5));
+ expect(tileUrl).to.eql('5/16/11');
+
+ tileUrl = tileSource.tileUrlFunction(
+ tileGrid.getTileCoordForCoordAndZ(coordinate, 6));
+ expect(tileUrl).to.eql('6/33/22');
+
+ });
+
+ describe('wrap x', function() {
+
+ it('returns the expected URL', function() {
+ var projection = tileSource.getProjection();
+ var tileUrl = tileSource.tileUrlFunction(
+ tileSource.getTileCoordForTileUrlFunction(
+ [6, -31, -23], projection));
+ expect(tileUrl).to.eql('6/33/22');
+
+ tileUrl = tileSource.tileUrlFunction(
+ tileSource.getTileCoordForTileUrlFunction(
+ [6, 33, -23], projection));
+ expect(tileUrl).to.eql('6/33/22');
+
+ tileUrl = tileSource.tileUrlFunction(
+ tileSource.getTileCoordForTileUrlFunction(
+ [6, 97, -23], projection));
+ expect(tileUrl).to.eql('6/33/22');
+ });
+
+ });
+
+ describe('crop y', function() {
+
+ it('returns the expected URL', function() {
+ var projection = tileSource.getProjection();
+ var tileUrl = tileSource.tileUrlFunction(
+ tileSource.getTileCoordForTileUrlFunction(
+ [6, 33, 0], projection));
+ expect(tileUrl).to.be(undefined);
+
+ tileUrl = tileSource.tileUrlFunction(
+ tileSource.getTileCoordForTileUrlFunction(
+ [6, 33, -23], projection));
+ expect(tileUrl).to.eql('6/33/22');
+
+ tileUrl = tileSource.tileUrlFunction(
+ tileSource.getTileCoordForTileUrlFunction(
+ [6, 33, -65], projection));
+ expect(tileUrl).to.be(undefined);
+ });
+
+ });
+
+ });
+
+ describe('#getUrls', function() {
+
+ var sourceOptions;
+ var source;
+ var url = 'http://geo.nls.uk/maps/towns/glasgow1857/{z}/{x}/{-y}.png';
+
+ beforeEach(function() {
+ sourceOptions = {
+ tileGrid: ol.tilegrid.createXYZ({
+ extent: ol.proj.get('EPSG:4326').getExtent()
+ })
+ };
+ });
+
+ describe('using a "url" option', function() {
+ beforeEach(function() {
+ sourceOptions.url = url;
+ source = new ol.source.UrlTile(sourceOptions);
+ });
+
+ it('returns the XYZ URL', function() {
+ var urls = source.getUrls();
+ expect(urls).to.be.eql([url]);
+ });
+
+ });
+
+ describe('using a "urls" option', function() {
+ beforeEach(function() {
+ sourceOptions.urls = ['some_xyz_url1', 'some_xyz_url2'];
+ source = new ol.source.UrlTile(sourceOptions);
+ });
+
+ it('returns the XYZ URLs', function() {
+ var urls = source.getUrls();
+ expect(urls).to.be.eql(['some_xyz_url1', 'some_xyz_url2']);
+ });
+
+ });
+
+ describe('using a "tileUrlFunction"', function() {
+ beforeEach(function() {
+ sourceOptions.tileUrlFunction = function() {
+ return 'some_xyz_url';
+ };
+ source = new ol.source.UrlTile(sourceOptions);
+ });
+
+ it('returns null', function() {
+ var urls = source.getUrls();
+ expect(urls).to.be(null);
+ });
+
+ });
+
+ });
+
+});
+
+goog.require('ol.TileCoord');
+goog.require('ol.proj');
+goog.require('ol.source.UrlTile');
diff --git a/test/spec/ol/source/vectortilesource.test.js b/test/spec/ol/source/vectortilesource.test.js
new file mode 100644
index 0000000000..441c4f382d
--- /dev/null
+++ b/test/spec/ol/source/vectortilesource.test.js
@@ -0,0 +1,43 @@
+goog.provide('ol.test.source.VectorTile');
+
+
+describe('ol.source.VectorTile', function() {
+
+ var format = new ol.format.MVT();
+ var source = new ol.source.VectorTile({
+ format: format,
+ tileGrid: ol.tilegrid.createXYZ(),
+ url: '{z}/{x}/{y}.pbf'
+ });
+ var tile;
+
+ describe('constructor', function() {
+ it('sets the format on the instance', function() {
+ expect(source.format_).to.equal(format);
+ });
+ it('uses ol.VectorTile as default tileClass', function() {
+ expect(source.tileClass).to.equal(ol.VectorTile);
+ });
+ });
+
+ describe('#getTile()', function() {
+ it('creates a tile with the correct tile class', function() {
+ tile = source.getTile(0, 0, 0, 1, ol.proj.get('EPSG:3857'));
+ expect(tile).to.be.a(ol.VectorTile);
+ });
+ it('sets the correct tileCoord on the created tile', function() {
+ expect(tile.getTileCoord()).to.eql([0, 0, 0]);
+ });
+ it('fetches tile from cache when requested again', function() {
+ expect(source.getTile(0, 0, 0, 1, ol.proj.get('EPSG:3857')))
+ .to.equal(tile);
+ });
+ });
+
+});
+
+
+goog.require('ol.VectorTile');
+goog.require('ol.format.MVT');
+goog.require('ol.proj');
+goog.require('ol.source.VectorTile');