import { GeographicTilingScheme } from "../../Source/Cesium.js"; import { Rectangle } from "../../Source/Cesium.js"; import { Request } from "../../Source/Cesium.js"; import { RequestScheduler } from "../../Source/Cesium.js"; import { Resource } from "../../Source/Cesium.js"; import { WebMercatorTilingScheme } from "../../Source/Cesium.js"; import { GoogleEarthEnterpriseMapsProvider } from "../../Source/Cesium.js"; import { Imagery } from "../../Source/Cesium.js"; import { ImageryLayer } from "../../Source/Cesium.js"; import { ImageryProvider } from "../../Source/Cesium.js"; import { ImageryState } from "../../Source/Cesium.js"; import pollToPromise from "../pollToPromise.js"; describe("Scene/GoogleEarthEnterpriseMapsProvider", function () { var supportsImageBitmapOptions; beforeAll(function () { // This suite spies on requests. Resource.supportsImageBitmapOptions needs to make a request to a data URI. // We run it here to avoid interfering with the tests. return Resource.supportsImageBitmapOptions().then(function (result) { supportsImageBitmapOptions = result; }); }); afterEach(function () { Resource._Implementations.createImage = Resource._DefaultImplementations.createImage; Resource._Implementations.loadWithXhr = Resource._DefaultImplementations.loadWithXhr; }); it("conforms to ImageryProvider interface", function () { expect(GoogleEarthEnterpriseMapsProvider).toConformToInterface( ImageryProvider ); }); it("constructor throws when url is not specified", function () { function constructWithoutServer() { return new GoogleEarthEnterpriseMapsProvider({ channel: 1234, }); } expect(constructWithoutServer).toThrowDeveloperError(); }); it("constructor throws when channel is not specified", function () { function constructWithoutChannel() { return new GoogleEarthEnterpriseMapsProvider({ url: "http://invalid.localhost", }); } expect(constructWithoutChannel).toThrowDeveloperError(); }); it("resolves readyPromise", function () { var path = ""; var url = "http://example.invalid"; var channel = 1234; Resource._Implementations.loadWithXhr = function ( url, responseType, method, data, headers, deferred, overrideMimeType ) { Resource._DefaultImplementations.loadWithXhr( "Data/GoogleEarthEnterpriseMapsProvider/good.json", responseType, method, data, headers, deferred ); }; var provider = new GoogleEarthEnterpriseMapsProvider({ url: url, channel: channel, path: path, }); return provider.readyPromise.then(function (result) { expect(result).toBe(true); expect(provider.ready).toBe(true); }); }); it("resolves readyPromise with Resource", function () { var path = ""; var url = "http://example.invalid"; var channel = 1234; Resource._Implementations.loadWithXhr = function ( url, responseType, method, data, headers, deferred, overrideMimeType ) { Resource._DefaultImplementations.loadWithXhr( "Data/GoogleEarthEnterpriseMapsProvider/good.json", responseType, method, data, headers, deferred ); }; var resource = new Resource({ url: url, }); var provider = new GoogleEarthEnterpriseMapsProvider({ url: resource, channel: channel, path: path, }); return provider.readyPromise.then(function (result) { expect(result).toBe(true); expect(provider.ready).toBe(true); }); }); it("rejects readyPromise on error", function () { var url = "http://invalid.localhost"; var provider = new GoogleEarthEnterpriseMapsProvider({ url: url, channel: 1234, }); return provider.readyPromise .then(function () { fail("should not resolve"); }) .otherwise(function (e) { expect(provider.ready).toBe(false); expect(e.message).toContain(url); }); }); it("returns valid value for hasAlphaChannel", function () { var path = ""; var url = "http://example.invalid"; var channel = 1234; Resource._Implementations.loadWithXhr = function ( url, responseType, method, data, headers, deferred, overrideMimeType ) { Resource._DefaultImplementations.loadWithXhr( "Data/GoogleEarthEnterpriseMapsProvider/good.json", responseType, method, data, headers, deferred ); }; var provider = new GoogleEarthEnterpriseMapsProvider({ url: url, channel: channel, path: path, }); return pollToPromise(function () { return provider.ready; }).then(function () { expect(typeof provider.hasAlphaChannel).toBe("boolean"); }); }); it("can provide a root tile", function () { var path = ""; var url = "http://example.invalid"; var channel = 1234; var version = 1; Resource._Implementations.loadWithXhr = function ( url, responseType, method, data, headers, deferred, overrideMimeType ) { Resource._DefaultImplementations.loadWithXhr( "Data/GoogleEarthEnterpriseMapsProvider/good.json", responseType, method, data, headers, deferred ); }; var provider = new GoogleEarthEnterpriseMapsProvider({ url: url, channel: channel, path: path, }); expect(provider.url).toEqual(url); expect(provider.path).toEqual(path); expect(provider.channel).toEqual(channel); return pollToPromise(function () { return provider.ready; }).then(function () { expect(provider.tileWidth).toEqual(256); expect(provider.tileHeight).toEqual(256); expect(provider.maximumLevel).toBeUndefined(); expect(provider.minimumLevel).toEqual(0); expect(provider.version).toEqual(version); expect(provider.tilingScheme).toBeInstanceOf(WebMercatorTilingScheme); expect(provider.tileDiscardPolicy).toBeUndefined(); expect(provider.rectangle).toEqual( new WebMercatorTilingScheme().rectangle ); expect(provider.credit).toBeInstanceOf(Object); Resource._Implementations.createImage = function ( request, crossOrigin, deferred ) { var url = request.url; if (/^blob:/.test(url) || supportsImageBitmapOptions) { // If ImageBitmap is supported, we expect a loadWithXhr request to fetch it as a blob. Resource._DefaultImplementations.createImage( request, crossOrigin, deferred, true, true ); } else { expect(url).toEqual( "http://example.invalid/query?request=ImageryMaps&channel=1234&version=1&x=0&y=0&z=1" ); // Just return any old image. Resource._DefaultImplementations.createImage( new Request({ url: "Data/Images/Red16x16.png" }), crossOrigin, deferred ); } }; Resource._Implementations.loadWithXhr = function ( url, responseType, method, data, headers, deferred, overrideMimeType ) { expect(url).toEqual( "http://example.invalid/query?request=ImageryMaps&channel=1234&version=1&x=0&y=0&z=1" ); // Just return any old image. Resource._DefaultImplementations.loadWithXhr( "Data/Images/Red16x16.png", responseType, method, data, headers, deferred ); }; return provider.requestImage(0, 0, 0).then(function (image) { expect(image).toBeImageOrImageBitmap(); }); }); }); it("handles malformed JSON data returned by the server", function () { var path = "/default_map"; var url = "http://example.invalid"; var version = 1; var channel = 1234; Resource._Implementations.loadWithXhr = function ( url, responseType, method, data, headers, deferred, overrideMimeType ) { return deferred.resolve( "{\n" + "isAuthenticated: true,\n" + "layers: [\n" + " {\n" + ' icon: "icons/773_l.png",\n' + " id: 1234,\n" + " initialState: true,\n" + ' label: "Imagery",\n' + ' lookAt: "none",\n' + ' requestType: "ImageryMaps",\n' + " version: 1\n" + " },{\n" + ' icon: "icons/773_l.png",\n' + " id: 1007,\n" + " initialState: true,\n" + ' label: "Labels",\n' + ' lookAt: "none",\n' + ' requestType: "VectorMapsRaster",\n' + " version: 8\n" + " }\n" + "],\n" + 'serverUrl: "https://example.invalid",\n' + "useGoogleLayers: false\n" + "}" ); }; var provider = new GoogleEarthEnterpriseMapsProvider({ url: url, channel: channel, }); expect(provider.url).toEqual(url); expect(provider.path).toEqual(path); expect(provider.version).toEqual(version); expect(provider.channel).toEqual(channel); return pollToPromise(function () { return provider.ready; }); }); it("raises error on invalid url", function () { var url = "http://invalid.localhost"; var provider = new GoogleEarthEnterpriseMapsProvider({ url: url, channel: 1234, }); var errorEventRaised = false; provider.errorEvent.addEventListener(function (error) { expect(error.message.indexOf(url) >= 0).toEqual(true); errorEventRaised = true; }); return pollToPromise(function () { return provider.ready || errorEventRaised; }).then(function () { expect(provider.ready).toEqual(false); expect(errorEventRaised).toEqual(true); }); }); it("raises error event when image cannot be loaded", function () { Resource._Implementations.loadWithXhr = function ( url, responseType, method, data, headers, deferred, overrideMimeType ) { Resource._DefaultImplementations.loadWithXhr( "Data/GoogleEarthEnterpriseMapsProvider/good.json", responseType, method, data, headers, deferred ); }; var provider = new GoogleEarthEnterpriseMapsProvider({ url: "example.invalid", channel: 1234, }); var layer = new ImageryLayer(provider); var tries = 0; provider.errorEvent.addEventListener(function (error) { expect(error.timesRetried).toEqual(tries); ++tries; if (tries < 3) { error.retry = true; } setTimeout(function () { RequestScheduler.update(); }, 1); }); Resource._Implementations.createImage = function ( request, crossOrigin, deferred ) { var url = request.url; if (/^blob:/.test(url) || supportsImageBitmapOptions) { // If ImageBitmap is supported, we expect a loadWithXhr request to fetch it as a blob. Resource._DefaultImplementations.createImage( request, crossOrigin, deferred, true, true ); } else if (tries === 2) { // Succeed after 2 tries Resource._DefaultImplementations.createImage( new Request({ url: "Data/Images/Red16x16.png" }), crossOrigin, deferred ); } else { // fail setTimeout(function () { deferred.reject(); }, 1); } }; Resource._Implementations.loadWithXhr = function ( url, responseType, method, data, headers, deferred, overrideMimeType ) { if (tries === 2) { // Succeed after 2 tries Resource._DefaultImplementations.loadWithXhr( "Data/Images/Red16x16.png", responseType, method, data, headers, deferred ); } else { // fail setTimeout(function () { deferred.reject(); }, 1); } }; return pollToPromise(function () { return provider.ready; }).then(function () { var imagery = new Imagery(layer, 0, 0, 0); imagery.addReference(); layer._requestImagery(imagery); RequestScheduler.update(); return pollToPromise(function () { return imagery.state === ImageryState.RECEIVED; }).then(function () { expect(imagery.image).toBeImageOrImageBitmap(); expect(tries).toEqual(2); imagery.releaseReference(); }); }); }); it("defaults to WebMercatorTilingScheme when no projection specified", function () { Resource._Implementations.loadWithXhr = function ( url, responseType, method, data, headers, deferred, overrideMimeType ) { return deferred.resolve( JSON.stringify({ isAuthenticated: true, layers: [ { icon: "icons/773_l.png", id: 1234, initialState: true, label: "Imagery", requestType: "ImageryMaps", version: 1, }, ], serverUrl: "https://example.invalid", useGoogleLayers: false, }) ); }; var provider = new GoogleEarthEnterpriseMapsProvider({ url: "http://example.invalid", channel: 1234, }); return pollToPromise(function () { return provider.ready; }).then(function () { expect(provider.tilingScheme).toBeInstanceOf(WebMercatorTilingScheme); expect(provider.rectangle).toEqual( new WebMercatorTilingScheme().rectangle ); }); }); it("Projection is WebMercatorTilingScheme when server projection is mercator", function () { Resource._Implementations.loadWithXhr = function ( url, responseType, method, data, headers, deferred, overrideMimeType ) { return deferred.resolve( JSON.stringify({ isAuthenticated: true, layers: [ { icon: "icons/773_l.png", id: 1234, initialState: true, label: "Imagery", requestType: "ImageryMaps", version: 1, }, ], projection: "mercator", serverUrl: "https://example.invalid", useGoogleLayers: false, }) ); }; var provider = new GoogleEarthEnterpriseMapsProvider({ url: "http://example.invalid", channel: 1234, }); return pollToPromise(function () { return provider.ready; }).then(function () { expect(provider.tilingScheme).toBeInstanceOf(WebMercatorTilingScheme); expect(provider.rectangle).toEqual( new WebMercatorTilingScheme().rectangle ); }); }); it("Projection is GeographicTilingScheme when server projection is flat", function () { Resource._Implementations.loadWithXhr = function ( url, responseType, method, data, headers, deferred, overrideMimeType ) { return deferred.resolve( JSON.stringify({ isAuthenticated: true, layers: [ { icon: "icons/773_l.png", id: 1234, initialState: true, label: "Imagery", requestType: "ImageryMaps", version: 1, }, ], projection: "flat", serverUrl: "https://example.invalid", useGoogleLayers: false, }) ); }; var provider = new GoogleEarthEnterpriseMapsProvider({ url: "http://example.invalid", channel: 1234, }); return pollToPromise(function () { return provider.ready; }).then(function () { expect(provider.tilingScheme).toBeInstanceOf(GeographicTilingScheme); expect(provider.rectangle).toEqual( new Rectangle(-Math.PI, -Math.PI, Math.PI, Math.PI) ); }); }); it("raises error when channel cannot be found", function () { Resource._Implementations.loadWithXhr = function ( url, responseType, method, data, headers, deferred, overrideMimeType ) { Resource._DefaultImplementations.loadWithXhr( "Data/GoogleEarthEnterpriseMapsProvider/bad_channel.json", responseType, method, data, headers, deferred ); }; var provider = new GoogleEarthEnterpriseMapsProvider({ url: "http://invalid.localhost", channel: 1235, }); var errorEventRaised = false; provider.errorEvent.addEventListener(function (error) { expect( error.message.indexOf("Could not find layer with channel") >= 0 ).toEqual(true); errorEventRaised = true; }); return pollToPromise(function () { return provider.ready || errorEventRaised; }).then(function () { expect(provider.ready).toEqual(false); expect(errorEventRaised).toEqual(true); }); }); it("raises error when channel version cannot be found", function () { Resource._Implementations.loadWithXhr = function ( url, responseType, method, data, headers, deferred, overrideMimeType ) { Resource._DefaultImplementations.loadWithXhr( "Data/GoogleEarthEnterpriseMapsProvider/bad_version.json", responseType, method, data, headers, deferred ); }; var provider = new GoogleEarthEnterpriseMapsProvider({ url: "http://invalid.localhost", channel: 1234, }); var errorEventRaised = false; provider.errorEvent.addEventListener(function (error) { expect( error.message.indexOf("Could not find a version in channel") >= 0 ).toEqual(true); errorEventRaised = true; }); return pollToPromise(function () { return provider.ready || errorEventRaised; }).then(function () { expect(provider.ready).toEqual(false); expect(errorEventRaised).toEqual(true); }); }); it("raises error when unsupported projection is specified", function () { Resource._Implementations.loadWithXhr = function ( url, responseType, method, data, headers, deferred, overrideMimeType ) { Resource._DefaultImplementations.loadWithXhr( "Data/GoogleEarthEnterpriseMapsProvider/bad_projection.json", responseType, method, data, headers, deferred ); }; var provider = new GoogleEarthEnterpriseMapsProvider({ url: "http://invalid.localhost", channel: 1234, }); var errorEventRaised = false; provider.errorEvent.addEventListener(function (error) { expect(error.message.indexOf("Unsupported projection") >= 0).toEqual( true ); errorEventRaised = true; }); return pollToPromise(function () { return provider.ready || errorEventRaised; }).then(function () { expect(provider.ready).toEqual(false); expect(errorEventRaised).toEqual(true); }); }); });