import ImageTile from '../../../../../src/ol/ImageTile.js'; import Projection from '../../../../../src/ol/proj/Projection.js'; import ReprojTile from '../../../../../src/ol/reproj/Tile.js'; import TileImage from '../../../../../src/ol/source/TileImage.js'; import TileState from '../../../../../src/ol/TileState.js'; import {WORLD_EXTENT} from '../../../../../src/ol/proj/epsg3857.js'; import { addCommon, clearAllProjections, get as getProjection, } from '../../../../../src/ol/proj.js'; import { createForProjection, createXYZ, } from '../../../../../src/ol/tilegrid.js'; import {createFromTemplate} from '../../../../../src/ol/tileurlfunction.js'; import {getKeyZXY} from '../../../../../src/ol/tilecoord.js'; import {listen} from '../../../../../src/ol/events.js'; import {register} from '../../../../../src/ol/proj/proj4.js'; describe('ol/source/TileImage', function () { function createSource(opt_proj, opt_tileGrid, opt_cacheSize) { const proj = opt_proj || 'EPSG:3857'; return new TileImage({ cacheSize: opt_cacheSize, projection: proj, tileGrid: opt_tileGrid || createForProjection(proj, undefined, [2, 2]), tileUrlFunction: createFromTemplate( 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=' ), }); } describe('#getInterpolate()', function () { it('is true by default', function () { const source = new TileImage({}); expect(source.getInterpolate()).to.be(true); }); it('is false if constructed with interpolate: false', function () { const source = new TileImage({interpolate: false}); expect(source.getInterpolate()).to.be(false); }); it('is false if constructed with imageSmoothing: false', function () { const source = new TileImage({imageSmoothing: false}); expect(source.getInterpolate()).to.be(false); }); }); describe('#getTileCacheForProjection', function () { it('uses the cacheSize for reprojected tile caches', function () { const source = createSource(undefined, undefined, 442); const tileCache = source.getTileCacheForProjection( getProjection('EPSG:4326') ); expect(tileCache.highWaterMark).to.be(442); expect(tileCache).to.not.equal( source.getTileCacheForProjection(source.getProjection()) ); }); }); describe('#setTileGridForProjection', function () { it('uses the tilegrid for given projection', function () { const source = createSource(); const tileGrid = createForProjection('EPSG:4326', 3, [10, 20]); source.setTileGridForProjection('EPSG:4326', tileGrid); const retrieved = source.getTileGridForProjection( getProjection('EPSG:4326') ); expect(retrieved).to.be(tileGrid); }); }); describe('#getTileInternal', function () { let source, tile; beforeEach(function () { source = createSource(); expect(source.getKey()).to.be(''); source.getTileInternal(0, 0, 0, 1, getProjection('EPSG:3857')); expect(source.tileCache.getCount()).to.be(1); tile = source.tileCache.get(getKeyZXY(0, 0, 0)); }); it('gets the tile from the cache', function () { const returnedTile = source.getTileInternal( 0, 0, 0, 1, getProjection('EPSG:3857') ); expect(returnedTile).to.be(tile); }); describe('change a dynamic param', function () { describe('tile is not loaded', function () { it('returns a tile with no interim tile', function () { source.getKey = function () { return 'key0'; }; const returnedTile = source.getTileInternal( 0, 0, 0, 1, getProjection('EPSG:3857') ); expect(returnedTile).not.to.be(tile); expect(returnedTile.key).to.be('key0'); expect(returnedTile.interimTile).to.be(null); }); }); describe('tile is loaded', function () { it('returns a tile with interim tile', function () { source.getKey = function () { return 'key0'; }; tile.state = 2; // LOADED const returnedTile = source.getTileInternal( 0, 0, 0, 1, getProjection('EPSG:3857') ); expect(returnedTile).not.to.be(tile); expect(returnedTile.key).to.be('key0'); expect(returnedTile.interimTile).to.be(tile); }); }); describe('tile is not loaded but interim tile is', function () { it('returns a tile with interim tile', function () { let dynamicParamsKey, returnedTile; source.getKey = function () { return dynamicParamsKey; }; dynamicParamsKey = 'key0'; tile.state = 2; // LOADED returnedTile = source.getTileInternal( 0, 0, 0, 1, getProjection('EPSG:3857') ); dynamicParamsKey = 'key1'; returnedTile = source.getTileInternal( 0, 0, 0, 1, getProjection('EPSG:3857') ); expect(returnedTile).not.to.be(tile); expect(returnedTile.key).to.be('key1'); expect(returnedTile.interimTile).to.be(tile); }); }); }); }); describe('#getTile', function () { it('does not do reprojection for identity', function () { const source3857 = createSource('EPSG:3857'); const tile3857 = source3857.getTile( 0, 0, 0, 1, getProjection('EPSG:3857') ); expect(tile3857).to.be.a(ImageTile); expect(tile3857).not.to.be.a(ReprojTile); const projXXX = new Projection({ code: 'XXX', units: 'degrees', }); const sourceXXX = createSource(projXXX); const tileXXX = sourceXXX.getTile(0, 0, 0, 1, projXXX); expect(tileXXX).to.be.a(ImageTile); expect(tileXXX).not.to.be.a(ReprojTile); }); beforeEach(function () { proj4.defs('4326_noextentnounits', '+proj=longlat +datum=WGS84 +no_defs'); register(proj4); }); afterEach(function () { delete proj4.defs['4326_noextentnounits']; clearAllProjections(); addCommon(); }); it('can handle source projection without extent and units', function (done) { const source = createSource( '4326_noextentnounits', createXYZ({ extent: [-180, -90, 180, 90], tileSize: [2, 2], }) ); const tile = source.getTile(0, 0, 0, 1, getProjection('EPSG:3857')); expect(tile).to.be.a(ReprojTile); listen(tile, 'change', function () { if (tile.getState() == 2) { // LOADED done(); } }); tile.load(); }); it('can handle target projection without extent and units', function (done) { const proj = getProjection('4326_noextentnounits'); const source = createSource(); source.setTileGridForProjection( proj, createXYZ({ extent: WORLD_EXTENT, tileSize: [2, 2], }) ); const tile = source.getTile(0, 0, 0, 1, proj); expect(tile).to.be.a(ReprojTile); listen(tile, 'change', function () { if (tile.getState() == 2) { // LOADED done(); } }); tile.load(); }); }); describe('tile load events', function () { let source; beforeEach(function () { source = new TileImage({ url: '{z}/{x}/{y}', }); }); it('dispatches tileloadstart and tileloadend events', function () { source.setTileLoadFunction(function (tile) { tile.setState(TileState.LOADED); }); const startSpy = sinon.spy(); source.on('tileloadstart', startSpy); const endSpy = sinon.spy(); source.on('tileloadend', endSpy); const tile = source.getTile(0, 0, 0, 1, getProjection('EPSG:3857')); tile.load(); expect(startSpy.callCount).to.be(1); expect(endSpy.callCount).to.be(1); }); it('works for loading-error-loading-loaded sequences', function (done) { source.setTileLoadFunction(function (tile) { tile.setState( tile.state == TileState.ERROR ? TileState.LOADED : TileState.ERROR ); }); const startSpy = sinon.spy(); source.on('tileloadstart', startSpy); const errorSpy = sinon.spy(); source.on('tileloaderror', function (e) { setTimeout(function () { e.tile.setState(TileState.LOADING); e.tile.setState(TileState.LOADED); }, 0); errorSpy(); }); source.on('tileloadend', function () { expect(startSpy.callCount).to.be(2); expect(errorSpy.callCount).to.be(1); done(); }); const tile = source.getTile(0, 0, 0, 1, getProjection('EPSG:3857')); tile.load(); }); }); });