text: 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" and "url"', 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();
  
        // passing "url" 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.throwException();
  
        // passing "size" and "url" in config object
        expect(function() {
          source = new Zoomify({
            url: '',
            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({
            url: '',
            size: [47, 11]
          });
        }).to.not.throwException();
      });
  
      it('accepts "tierSizeCalculation" option "default"', function() {
        expect(function() {
          new Zoomify({
            url: '',
            size: [47, 11],
            tierSizeCalculation: 'default'
          });
        }).to.not.throwException();
      });
  
      it('accepts "tierSizeCalculation" option "truncated"', function() {
        expect(function() {
          new Zoomify({
            url: '',
            size: [47, 11],
            tierSizeCalculation: 'truncated'
          });
        }).to.not.throwException();
      });
  
      it('throws on unexpected "tierSizeCalculation" ', function() {
        // passing unknown string will throw
        expect(function() {
          new Zoomify({
            url: '',
            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();
      });
  
    });
  
  });
  