import {DEFAULT_TILE_SIZE} from '../../../../src/ol/tilegrid/common.js'; import {listen} from '../../../../src/ol/events.js'; import Projection from '../../../../src/ol/proj/Projection.js'; import Zoomify, {CustomTile} from '../../../../src/ol/source/Zoomify.js'; import TileGrid from '../../../../src/ol/tilegrid/TileGrid.js'; describe('ol.source.Zoomify', function() { const w = 1024; const h = 512; const size = [w, h]; const zoomifyUrl = 'spec/ol/source/images/zoomify/{TileGroup}/{z}-{x}-{y}.jpg'; const iipUrl = 'spec/ol/source/images/zoomify?JTL={z},{tileIndex}'; const proj = new Projection({ code: 'ZOOMIFY', units: 'pixels', extent: [0, 0, w, h] }); function getZoomifySource() { return new Zoomify({ url: zoomifyUrl, size: size }); } function getZoomifySourceWithExtentInFirstQuadrant() { return new Zoomify({ url: zoomifyUrl, size: size, extent: [0, 0, size[0], size[1]] }); } function getIIPSource() { return new Zoomify({ url: iipUrl, size: size }); } function getZoomifySourceWith1024pxTiles() { return new Zoomify({ url: zoomifyUrl, size: size, tileSize: 1024 }); } describe('constructor', function() { it('requires config "size"', function() { let source; // undefined config object expect(function() { source = new Zoomify(); }).to.throwException(); // empty object as config object expect(function() { source = new Zoomify({}); }).to.throwException(); // not passing "size" in config object expect(function() { source = new Zoomify({ url: 'some-url' }); }).to.throwException(); // passing "size" in config object expect(function() { source = new Zoomify({ size: [47, 11] }); }).to.not.throwException(); // we got a source expect(source).to.be.a(Zoomify); // also test our helper methods from above expect(function() { source = getZoomifySource(); }).to.not.throwException(); expect(function() { source = getIIPSource(); }).to.not.throwException(); // we got a source expect(source).to.be.a(Zoomify); }); it('does not need "tierSizeCalculation" option', function() { expect(function() { new Zoomify({ size: [47, 11] }); }).to.not.throwException(); }); it('accepts "tierSizeCalculation" option "default"', function() { expect(function() { new Zoomify({ size: [47, 11], tierSizeCalculation: 'default' }); }).to.not.throwException(); }); it('accepts "tierSizeCalculation" option "truncated"', function() { expect(function() { new Zoomify({ size: [47, 11], tierSizeCalculation: 'truncated' }); }).to.not.throwException(); }); it('throws on unexpected "tierSizeCalculation" ', function() { // passing unknown string will throw expect(function() { new Zoomify({ size: [47, 11], tierSizeCalculation: 'ace-of-spades' }); }).to.throwException(); }); it('creates a tileGrid for both protocols', function() { const sources = [getZoomifySource(), getIIPSource()]; for (let i = 0; i < sources.length; i++) { const tileGrid = sources[i].getTileGrid(); expect(tileGrid).to.be.a(TileGrid); } }); }); describe('generated tileGrid', function() { it('has expected extent', function() { const sources = [getZoomifySource(), getIIPSource()]; for (let i = 0; i < sources.length; i++) { const tileGrid = sources[i].getTileGrid(); const expectedExtent = [0, -h, w, 0]; expect(tileGrid.getExtent()).to.eql(expectedExtent); } }); it('has expected origin', function() { const sources = [getZoomifySource(), getIIPSource()]; for (let i = 0; i < sources.length; i++) { const tileGrid = sources[i].getTileGrid(); const expectedOrigin = [0, 0]; expect(tileGrid.getOrigin()).to.eql(expectedOrigin); } }); it('has expected resolutions', function() { const sources = [getZoomifySource(), getIIPSource()]; for (let i = 0; i < sources.length; i++) { const tileGrid = sources[i].getTileGrid(); const expectedResolutions = [4, 2, 1]; expect(tileGrid.getResolutions()).to.eql(expectedResolutions); } }); it('has expected tileSize', function() { const sources = [getZoomifySource(), getZoomifySourceWith1024pxTiles()]; const expectedTileSizes = [DEFAULT_TILE_SIZE, 1024]; for (let i = 0; i < sources.length; i++) { const tileGrid = sources[i].getTileGrid(); expect(tileGrid.getTileSize()).to.eql(expectedTileSizes[i]); } }); it('has expected extent', function() { const sources = [getZoomifySource(), getZoomifySourceWithExtentInFirstQuadrant()]; const expectedExtents = [ [0, -size[1], size[0], 0], [0, 0, size[0], size[1]] ]; for (let i = 0; i < sources.length; i++) { const tileGrid = sources[i].getTileGrid(); expect(tileGrid.getExtent()).to.eql(expectedExtents[i]); } }); it('has expected origin', function() { const sources = [getZoomifySource(), getZoomifySourceWithExtentInFirstQuadrant()]; const expectedOrigins = [ [0, 0], [0, size[1]] ]; for (let i = 0; i < sources.length; i++) { const tileGrid = sources[i].getTileGrid(); expect(tileGrid.getOrigin()).to.eql(expectedOrigins[i]); } }); }); describe('tierSizeCalculation configuration', function() { it('influences resolutions', function() { // not configured at all const source = new Zoomify({ url: zoomifyUrl, size: [513, 256] }); const tileGrid = source.getTileGrid(); // explicitly set as 'default' const sourceDefault = new Zoomify({ url: zoomifyUrl, size: [513, 256], tierSizeCalculation: 'default' }); const tileGridDefault = sourceDefault.getTileGrid(); // explicitly set to 'truncated' const sourceTruncated = new Zoomify({ url: zoomifyUrl, size: [513, 256], tierSizeCalculation: 'truncated' }); const tileGridTruncated = sourceTruncated.getTileGrid(); expect(tileGrid.getResolutions()).to.eql([4, 2, 1]); expect(tileGridDefault.getResolutions()).to.eql([4, 2, 1]); expect(tileGridTruncated.getResolutions()).to.eql([2, 1]); }); }); describe('generated tileUrlFunction for zoomify protocol', function() { it('creates an expected tileUrlFunction with zoomify template', function() { const source = getZoomifySource(); const tileUrlFunction = source.getTileUrlFunction(); // zoomlevel 0 expect(tileUrlFunction([0, 0, 0])).to.eql('spec/ol/source/images/zoomify/TileGroup0/0-0-0.jpg'); // zoomlevel 1 expect(tileUrlFunction([1, 0, 0])).to.eql('spec/ol/source/images/zoomify/TileGroup0/1-0-0.jpg'); expect(tileUrlFunction([1, 1, 0])).to.eql('spec/ol/source/images/zoomify/TileGroup0/1-1-0.jpg'); expect(tileUrlFunction([1, 0, 1])).to.eql('spec/ol/source/images/zoomify/TileGroup0/1-0-1.jpg'); expect(tileUrlFunction([1, 1, 1])).to.eql('spec/ol/source/images/zoomify/TileGroup0/1-1-1.jpg'); }); it('creates an expected tileUrlFunction with IIP template', function() { const source = getIIPSource(); const tileUrlFunction = source.getTileUrlFunction(); // zoomlevel 0 expect(tileUrlFunction([0, 0, 0])).to.eql('spec/ol/source/images/zoomify?JTL=0,0'); // zoomlevel 1 expect(tileUrlFunction([1, 0, 0])).to.eql('spec/ol/source/images/zoomify?JTL=1,0'); expect(tileUrlFunction([1, 1, 0])).to.eql('spec/ol/source/images/zoomify?JTL=1,1'); expect(tileUrlFunction([1, 0, 1])).to.eql('spec/ol/source/images/zoomify?JTL=1,2'); expect(tileUrlFunction([1, 1, 1])).to.eql('spec/ol/source/images/zoomify?JTL=1,3'); }); it('creates an expected tileUrlFunction without template', function() { const source = new Zoomify({ url: 'spec/ol/source/images/zoomify/', size: size }); const tileUrlFunction = source.getTileUrlFunction(); // zoomlevel 0 expect(tileUrlFunction([0, 0, 0])).to.eql('spec/ol/source/images/zoomify/TileGroup0/0-0-0.jpg'); // zoomlevel 1 expect(tileUrlFunction([1, 0, 0])).to.eql('spec/ol/source/images/zoomify/TileGroup0/1-0-0.jpg'); expect(tileUrlFunction([1, 1, 0])).to.eql('spec/ol/source/images/zoomify/TileGroup0/1-1-0.jpg'); expect(tileUrlFunction([1, 0, 1])).to.eql('spec/ol/source/images/zoomify/TileGroup0/1-0-1.jpg'); expect(tileUrlFunction([1, 1, 1])).to.eql('spec/ol/source/images/zoomify/TileGroup0/1-1-1.jpg'); }); it('returns undefined if no tileCoord passed', function() { const source = getZoomifySource(); const tileUrlFunction = source.getTileUrlFunction(); expect(tileUrlFunction()).to.be(undefined); }); }); describe('uses a custom tileClass', function() { it('returns expected tileClass instances via "getTile"', function() { const source = getZoomifySource(); const tile = source.getTile(0, 0, 0, 1, proj); expect(tile).to.be.a(CustomTile); }); it('"tile.getImage" returns and caches an unloaded image', function() { const source = getZoomifySource(); const tile = source.getTile(0, 0, 0, 1, proj); const img = tile.getImage(); const tile2 = source.getTile(0, 0, 0, 1, proj); const img2 = tile2.getImage(); expect(img).to.be.a(HTMLImageElement); expect(img).to.be(img2); }); it('"tile.getImage" returns and caches a loaded canvas', function(done) { const source = getZoomifySource(); const tile = source.getTile(0, 0, 0, 1, proj); listen(tile, 'change', function() { if (tile.getState() == 2) { // LOADED const img = tile.getImage(); expect(img).to.be.a(HTMLCanvasElement); const tile2 = source.getTile(0, 0, 0, 1, proj); expect(tile2.getState()).to.be(2); // LOADED const img2 = tile2.getImage(); expect(img).to.be(img2); done(); } }); tile.load(); }); }); });