From fef5d259b7712ca6749707d99e9fe61cd56060c8 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Fri, 9 Feb 2018 18:08:46 -0500 Subject: [PATCH 1/4] allow promise to url for CesiumTerrainProvider, createTileMapServiceImageryProvider and Cesium3DTileset --- Source/Core/CesiumTerrainProvider.js | 29 +++++----- Source/Scene/Cesium3DTileset.js | 53 +++++++++++-------- .../createTileMapServiceImageryProvider.js | 27 ++++++---- Specs/Core/CesiumTerrainProviderSpec.js | 11 ++++ Specs/Scene/Cesium3DTilesetSpec.js | 17 ++++++ ...createTileMapServiceImageryProviderSpec.js | 11 ++++ 6 files changed, 101 insertions(+), 47 deletions(-) diff --git a/Source/Core/CesiumTerrainProvider.js b/Source/Core/CesiumTerrainProvider.js index 613c0b95e708..821db7dee08e 100644 --- a/Source/Core/CesiumTerrainProvider.js +++ b/Source/Core/CesiumTerrainProvider.js @@ -68,7 +68,7 @@ define([ * @constructor * * @param {Object} options Object with the following properties: - * @param {Resource|String} options.url The URL of the Cesium terrain server. + * @param {Resource|String|Promise|Promise} options.url The URL of the Cesium terrain server. * @param {Boolean} [options.requestVertexNormals=false] Flag that indicates if the client should request additional lighting information from the server, in the form of per vertex normals if available. * @param {Boolean} [options.requestWaterMask=false] Flag that indicates if the client should request per tile water masks from the server, if available. * @param {Ellipsoid} [options.ellipsoid] The ellipsoid. If not specified, the WGS84 ellipsoid is used. @@ -112,11 +112,6 @@ define([ deprecationWarning('CesiumTerrainProvider.proxy', 'The options.proxy parameter has been deprecated. Specify options.url as a Resource instance and set the proxy property there.'); } - var resource = Resource.createIfNeeded(options.url, { - proxy: options.proxy - }); - resource.appendForwardSlash(); - this._tilingScheme = new GeographicTilingScheme({ numberOfLevelZeroTilesX : 2, numberOfLevelZeroTilesY : 1, @@ -159,17 +154,27 @@ define([ this._ready = false; this._readyPromise = when.defer(); - var lastResource = resource; - var metadataResource = lastResource.getDerivedResource({ - url: 'layer.json' - }); - var that = this; + var lastResource; + var metadataResource; var metadataError; var layers = this._layers = []; var attribution = ''; var overallAvailability = []; + when(options.url) + .then(function(url) { + var resource = Resource.createIfNeeded(url, { + proxy: options.proxy + }); + resource.appendForwardSlash(); + lastResource = resource; + metadataResource = lastResource.getDerivedResource({ + url: 'layer.json' + }); + + requestMetadata(); + }); function parseMetadataSuccess(data) { var message; @@ -346,8 +351,6 @@ define([ var metadata = metadataResource.fetchJson(); when(metadata, metadataSuccess, metadataFailure); } - - requestMetadata(); } /** diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 81ee88ae968b..200e480cc7f1 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -94,7 +94,7 @@ define([ * @constructor * * @param {Object} options Object with the following properties: - * @param {Resource|String} options.url The url to a tileset.json file or to a directory containing a tileset.json file. + * @param {Resource|String|Promise|Promise} options.url The url to a tileset.json file or to a directory containing a tileset.json file. * @param {Boolean} [options.show=true] Determines if the tileset will be shown. * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] A 4x4 transformation matrix that transforms the tileset's root tile. * @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the tileset casts or receives shadows from each light source. @@ -165,26 +165,9 @@ define([ Check.defined('options.url', options.url); //>>includeEnd('debug'); - var resource = Resource.createIfNeeded(options.url); - - var tilesetResource = resource; - var basePath; - - if (resource.extension === 'json') { - basePath = resource.getBaseUri(true); - } else if (resource.isDataUri) { - basePath = ''; - } else { - resource.appendForwardSlash(); - tilesetResource = resource.getDerivedResource({ - url: 'tileset.json' - }); - basePath = resource.url; - } - - this._url = resource.url; - this._tilesetUrl = tilesetResource.url; - this._basePath = basePath; + this._url = undefined; + this._tilesetUrl = undefined; + this._basePath = undefined; this._root = undefined; this._asset = undefined; // Metadata for the entire tileset this._properties = undefined; // Metadata for per-model/point/etc properties @@ -699,9 +682,33 @@ define([ this._brokenUrlWorkaround = false; var that = this; + var tilesetResource; + when(options.url) + .then(function(url) { + var basePath; + var resource = Resource.createIfNeeded(url); + + tilesetResource = resource; + + if (resource.extension === 'json') { + basePath = resource.getBaseUri(true); + } else if (resource.isDataUri) { + basePath = ''; + } else { + resource.appendForwardSlash(); + tilesetResource = resource.getDerivedResource({ + url: 'tileset.json' + }); + basePath = resource.url; + } - // We don't know the distance of the tileset until tileset.json is loaded, so use the default distance for now - Cesium3DTileset.loadJson(tilesetResource) + that._url = resource.url; + that._tilesetUrl = tilesetResource.url; + that._basePath = basePath; + + // We don't know the distance of the tileset until tileset.json is loaded, so use the default distance for now + return Cesium3DTileset.loadJson(tilesetResource); + }) .then(function(tilesetJson) { return detectBrokenUrlWorkaround(that, tilesetResource, tilesetJson); }) diff --git a/Source/Scene/createTileMapServiceImageryProvider.js b/Source/Scene/createTileMapServiceImageryProvider.js index cf1667f0211a..f53b88a0c654 100644 --- a/Source/Scene/createTileMapServiceImageryProvider.js +++ b/Source/Scene/createTileMapServiceImageryProvider.js @@ -37,7 +37,7 @@ define([ * @exports createTileMapServiceImageryProvider * * @param {Object} [options] Object with the following properties: - * @param {Resource|String} [options.url='.'] Path to image tiles on server. + * @param {Resource|String|Promise|Promise} [options.url='.'] Path to image tiles on server. * @param {String} [options.fileExtension='png'] The file extension for images on the server. * @param {Credit|String} [options.credit=''] A credit for the data source, which is displayed on the canvas. * @param {Number} [options.minimumLevel=0] The minimum level-of-detail supported by the imagery provider. Take care when specifying @@ -95,19 +95,25 @@ define([ deprecationWarning('createTileMapServiceImageryProvider.proxy', 'The options.proxy parameter has been deprecated. Specify options.url as a Resource instance and set the proxy property there.'); } - var resource = Resource.createIfNeeded(options.url, { - proxy : options.proxy - }); - resource.appendForwardSlash(); - - var xmlResource = resource.getDerivedResource({ - url: 'tilemapresource.xml' - }); - var deferred = when.defer(); var imageryProvider = new UrlTemplateImageryProvider(deferred.promise); var metadataError; + var resource; + var xmlResource; + when(options.url) + .then(function(url) { + resource = Resource.createIfNeeded(url, { + proxy : options.proxy + }); + resource.appendForwardSlash(); + + xmlResource = resource.getDerivedResource({ + url: 'tilemapresource.xml' + }); + + requestMetadata(); + }); function metadataSuccess(xml) { var tileFormatRegex = /tileformat/i; @@ -282,7 +288,6 @@ define([ xmlResource.fetchXML().then(metadataSuccess).otherwise(metadataFailure); } - requestMetadata(); return imageryProvider; } diff --git a/Specs/Core/CesiumTerrainProviderSpec.js b/Specs/Core/CesiumTerrainProviderSpec.js index 9a1e8935f272..2e1b41050aaa 100644 --- a/Specs/Core/CesiumTerrainProviderSpec.js +++ b/Specs/Core/CesiumTerrainProviderSpec.js @@ -139,6 +139,17 @@ defineSuite([ }); }); + it('resolves readyPromise when url promise is used', function() { + var provider = new CesiumTerrainProvider({ + url : when.resolve('made/up/url') + }); + + return provider.readyPromise.then(function (result) { + expect(result).toBe(true); + expect(provider.ready).toBe(true); + }); + }); + it('resolves readyPromise with Resource', function() { var resource = new Resource({ url : 'made/up/url' diff --git a/Specs/Scene/Cesium3DTilesetSpec.js b/Specs/Scene/Cesium3DTilesetSpec.js index c3e2a7fce4d1..7c9160d52220 100644 --- a/Specs/Scene/Cesium3DTilesetSpec.js +++ b/Specs/Scene/Cesium3DTilesetSpec.js @@ -255,6 +255,23 @@ defineSuite([ }); }); + it('Constructor works with promise to resource', function() { + var resource = new Resource({ + url: 'Data/Cesium3DTiles/Tilesets/TilesetOfTilesets' + }); + + // setup tileset with invalid url (overridden loadJson should replace invalid url with correct url) + var tileset = new Cesium3DTileset({ + url : when.resolve(resource) + }); + + return tileset.readyPromise.then(function() { + expect(tileset.ready).toEqual(true); + }).otherwise(function(error) { + fail('should not fail'); + }); + }); + it('Constructor works with directory resource', function() { var resource = new Resource({ url: 'Data/Cesium3DTiles/Tilesets/TilesetOfTilesets' diff --git a/Specs/Scene/createTileMapServiceImageryProviderSpec.js b/Specs/Scene/createTileMapServiceImageryProviderSpec.js index c9db47dc9ce0..00bd98e96449 100644 --- a/Specs/Scene/createTileMapServiceImageryProviderSpec.js +++ b/Specs/Scene/createTileMapServiceImageryProviderSpec.js @@ -71,6 +71,17 @@ defineSuite([ }); }); + it('resolves readyPromise when promise url is used', function() { + var provider = createTileMapServiceImageryProvider({ + url : when.resolve('made/up/tms/server/') + }); + + return provider.readyPromise.then(function(result) { + expect(result).toBe(true); + expect(provider.ready).toBe(true); + }); + }); + it('resolves readyPromise with Resource', function() { var resource = new Resource({ url: 'made/up/tms/server/' From 3067a77fe26783f6fc10cc3f76068e954bd39617 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Mon, 12 Feb 2018 13:56:43 -0500 Subject: [PATCH 2/4] handle rejection --- Source/Core/CesiumTerrainProvider.js | 11 +- .../createTileMapServiceImageryProvider.js | 3 + Specs/Core/CesiumTerrainProviderSpec.js | 16 +++ ...createTileMapServiceImageryProviderSpec.js | 115 ++++++++++-------- 4 files changed, 91 insertions(+), 54 deletions(-) diff --git a/Source/Core/CesiumTerrainProvider.js b/Source/Core/CesiumTerrainProvider.js index 821db7dee08e..1865bc5a00cc 100644 --- a/Source/Core/CesiumTerrainProvider.js +++ b/Source/Core/CesiumTerrainProvider.js @@ -151,8 +151,9 @@ define([ this._availability = undefined; + var deferred = when.defer(); this._ready = false; - this._readyPromise = when.defer(); + this._readyPromise = deferred; var that = this; var lastResource; @@ -174,6 +175,9 @@ define([ }); requestMetadata(); + }) + .otherwise(function() { + deferred.reject(new RuntimeError('An error occurred while loading options.url')); }); function parseMetadataSuccess(data) { @@ -348,8 +352,9 @@ define([ } function requestMetadata() { - var metadata = metadataResource.fetchJson(); - when(metadata, metadataSuccess, metadataFailure); + when(metadataResource.fetchJson()) + .then(metadataSuccess) + .otherwise(metadataFailure); } } diff --git a/Source/Scene/createTileMapServiceImageryProvider.js b/Source/Scene/createTileMapServiceImageryProvider.js index f53b88a0c654..09fbde3a3153 100644 --- a/Source/Scene/createTileMapServiceImageryProvider.js +++ b/Source/Scene/createTileMapServiceImageryProvider.js @@ -113,6 +113,9 @@ define([ }); requestMetadata(); + }) + .otherwise(function() { + deferred.reject(new RuntimeError('An error occurred while loading options.url')); }); function metadataSuccess(xml) { diff --git a/Specs/Core/CesiumTerrainProviderSpec.js b/Specs/Core/CesiumTerrainProviderSpec.js index 2e1b41050aaa..a770b257e671 100644 --- a/Specs/Core/CesiumTerrainProviderSpec.js +++ b/Specs/Core/CesiumTerrainProviderSpec.js @@ -11,6 +11,7 @@ defineSuite([ 'Core/Request', 'Core/RequestScheduler', 'Core/Resource', + 'Core/RuntimeError', 'Core/TerrainProvider', 'Specs/pollToPromise', 'ThirdParty/when' @@ -27,6 +28,7 @@ defineSuite([ Request, RequestScheduler, Resource, + RuntimeError, TerrainProvider, pollToPromise, when) { @@ -165,6 +167,20 @@ defineSuite([ }); }); + it('rejects readyPromise when url rejects', function() { + var provider = new CesiumTerrainProvider({ + url: when.reject() + }); + return provider.readyPromise + .then(function() { + fail('should not resolve'); + }) + .otherwise(function(result) { + expect(result).toBeInstanceOf(RuntimeError); + expect(provider.ready).toBe(false); + }); + }); + it('uses geographic tiling scheme by default', function() { returnHeightmapTileJson(); diff --git a/Specs/Scene/createTileMapServiceImageryProviderSpec.js b/Specs/Scene/createTileMapServiceImageryProviderSpec.js index 00bd98e96449..89bcaa165954 100644 --- a/Specs/Scene/createTileMapServiceImageryProviderSpec.js +++ b/Specs/Scene/createTileMapServiceImageryProviderSpec.js @@ -1,47 +1,47 @@ defineSuite([ - 'Scene/createTileMapServiceImageryProvider', - 'Core/Cartesian2', - 'Core/Cartographic', - 'Core/DefaultProxy', - 'Core/GeographicProjection', - 'Core/GeographicTilingScheme', - 'Core/getAbsoluteUri', - 'Core/loadImage', - 'Core/loadWithXhr', - 'Core/Math', - 'Core/Rectangle', - 'Core/RequestScheduler', - 'Core/Resource', - 'Core/WebMercatorProjection', - 'Core/WebMercatorTilingScheme', - 'Scene/Imagery', - 'Scene/ImageryLayer', - 'Scene/ImageryState', - 'Scene/UrlTemplateImageryProvider', - 'Specs/pollToPromise', - 'ThirdParty/when' - ], function( - createTileMapServiceImageryProvider, - Cartesian2, - Cartographic, - DefaultProxy, - GeographicProjection, - GeographicTilingScheme, - getAbsoluteUri, - loadImage, - loadWithXhr, - CesiumMath, - Rectangle, - RequestScheduler, - Resource, - WebMercatorProjection, - WebMercatorTilingScheme, - Imagery, - ImageryLayer, - ImageryState, - UrlTemplateImageryProvider, - pollToPromise, - when) { + 'Scene/createTileMapServiceImageryProvider', + 'Core/Cartesian2', + 'Core/Cartographic', + 'Core/DefaultProxy', + 'Core/GeographicProjection', + 'Core/GeographicTilingScheme', + 'Core/getAbsoluteUri', + 'Core/loadImage', + 'Core/loadWithXhr', + 'Core/Math', + 'Core/Rectangle', + 'Core/RequestScheduler', + 'Core/Resource', + 'Core/WebMercatorProjection', + 'Core/WebMercatorTilingScheme', + 'Scene/Imagery', + 'Scene/ImageryLayer', + 'Scene/ImageryState', + 'Scene/UrlTemplateImageryProvider', + 'Specs/pollToPromise', + 'ThirdParty/when' +], function( + createTileMapServiceImageryProvider, + Cartesian2, + Cartographic, + DefaultProxy, + GeographicProjection, + GeographicTilingScheme, + getAbsoluteUri, + loadImage, + loadWithXhr, + CesiumMath, + Rectangle, + RequestScheduler, + Resource, + WebMercatorProjection, + WebMercatorTilingScheme, + Imagery, + ImageryLayer, + ImageryState, + UrlTemplateImageryProvider, + pollToPromise, + when) { 'use strict'; beforeEach(function() { @@ -55,7 +55,7 @@ defineSuite([ it('return a UrlTemplateImageryProvider', function() { var provider = createTileMapServiceImageryProvider({ - url: 'made/up/tms/server/' + url : 'made/up/tms/server/' }); expect(provider).toBeInstanceOf(UrlTemplateImageryProvider); }); @@ -84,7 +84,7 @@ defineSuite([ it('resolves readyPromise with Resource', function() { var resource = new Resource({ - url: 'made/up/tms/server/' + url : 'made/up/tms/server/' }); var provider = createTileMapServiceImageryProvider({ @@ -97,6 +97,18 @@ defineSuite([ }); }); + it('rejects readyPromise if options.url rejects', function() { + var provider = createTileMapServiceImageryProvider({ + url : when.reject() + }); + return provider.readyPromise.then(function() { + fail('should not resolve'); + }).otherwise(function(result) { + expect(result).toBeInstanceOf(RuntimeError); + expect(provider.ready).toBe(false); + }); + }); + it('rejects readyPromise on error', function() { loadWithXhr.load = function(url, responseType, method, data, headers, deferred, overrideMimeType) { // We can't resolve the promise immediately, because then the error would be raised @@ -127,7 +139,7 @@ defineSuite([ return provider.readyPromise.then(function() { fail('should not resolve'); - }).otherwise(function (e) { + }).otherwise(function(e) { expect(provider.ready).toBe(false); expect(e.message).toContain('unsupported profile'); }); @@ -162,7 +174,7 @@ defineSuite([ return provider.readyPromise.then(function() { fail('should not resolve'); - }).otherwise(function (e) { + }).otherwise(function(e) { expect(provider.ready).toBe(false); expect(e.message).toContain('expected tilesets or bbox attributes'); }); @@ -172,6 +184,7 @@ defineSuite([ function createWithoutUrl() { return createTileMapServiceImageryProvider({}); } + expect(createWithoutUrl).toThrowDeveloperError(); }); @@ -287,9 +300,9 @@ defineSuite([ url : 'made/up/tms/server' }); return pollToPromise(function() { - return provider.ready; + return provider.ready; }).then(function() { - expect(provider.credit).toBeUndefined(); + expect(provider.credit).toBeUndefined(); }); }); @@ -299,9 +312,9 @@ defineSuite([ credit : 'Thanks to our awesome made up source of this imagery!' }); return pollToPromise(function() { - return providerWithCredit.ready; + return providerWithCredit.ready; }).then(function() { - expect(providerWithCredit.credit).toBeDefined(); + expect(providerWithCredit.credit).toBeDefined(); }); }); From 5c56ec555e3465faafe185000c536ec15784a139 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Mon, 12 Feb 2018 14:02:14 -0500 Subject: [PATCH 3/4] cleanup --- Specs/Scene/createTileMapServiceImageryProviderSpec.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Specs/Scene/createTileMapServiceImageryProviderSpec.js b/Specs/Scene/createTileMapServiceImageryProviderSpec.js index 89bcaa165954..2a4471888e48 100644 --- a/Specs/Scene/createTileMapServiceImageryProviderSpec.js +++ b/Specs/Scene/createTileMapServiceImageryProviderSpec.js @@ -12,6 +12,7 @@ defineSuite([ 'Core/Rectangle', 'Core/RequestScheduler', 'Core/Resource', + 'Core/RuntimeError', 'Core/WebMercatorProjection', 'Core/WebMercatorTilingScheme', 'Scene/Imagery', @@ -34,6 +35,7 @@ defineSuite([ Rectangle, RequestScheduler, Resource, + RuntimeError, WebMercatorProjection, WebMercatorTilingScheme, Imagery, From 64d50a80ba50aac41981a923c13f8a9ddb505ca7 Mon Sep 17 00:00:00 2001 From: hpinkos Date: Tue, 13 Feb 2018 11:41:31 -0500 Subject: [PATCH 4/4] cleanup --- CHANGES.md | 3 +++ Source/Core/CesiumTerrainProvider.js | 4 ++-- Source/Scene/createTileMapServiceImageryProvider.js | 4 ++-- Specs/Core/CesiumTerrainProviderSpec.js | 7 +++---- Specs/Scene/createTileMapServiceImageryProviderSpec.js | 7 +++---- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0dcfd8ed5311..d59d5919eaa8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,9 @@ Change Log ### 1.43 - 2018-03-01 +##### Additions :tada: +* Added support for a promise to a resource for `CesiumTerrainProvider`, `createTileMapServiceImageryProvider` and `Cesium3DTileset` [#6204](https://github.com/AnalyticalGraphicsInc/cesium/pull/6204) + ##### Fixes :wrench: * Fixed bug where AxisAlignedBoundingBox did not copy over center value when cloning an undefined result. [#6183](https://github.com/AnalyticalGraphicsInc/cesium/pull/6183) diff --git a/Source/Core/CesiumTerrainProvider.js b/Source/Core/CesiumTerrainProvider.js index 1865bc5a00cc..3be6b183b4b2 100644 --- a/Source/Core/CesiumTerrainProvider.js +++ b/Source/Core/CesiumTerrainProvider.js @@ -176,8 +176,8 @@ define([ requestMetadata(); }) - .otherwise(function() { - deferred.reject(new RuntimeError('An error occurred while loading options.url')); + .otherwise(function(e) { + deferred.reject(e); }); function parseMetadataSuccess(data) { diff --git a/Source/Scene/createTileMapServiceImageryProvider.js b/Source/Scene/createTileMapServiceImageryProvider.js index 09fbde3a3153..8034a0b6a871 100644 --- a/Source/Scene/createTileMapServiceImageryProvider.js +++ b/Source/Scene/createTileMapServiceImageryProvider.js @@ -114,8 +114,8 @@ define([ requestMetadata(); }) - .otherwise(function() { - deferred.reject(new RuntimeError('An error occurred while loading options.url')); + .otherwise(function(e) { + deferred.reject(e); }); function metadataSuccess(xml) { diff --git a/Specs/Core/CesiumTerrainProviderSpec.js b/Specs/Core/CesiumTerrainProviderSpec.js index a770b257e671..3fd9b5aee1fa 100644 --- a/Specs/Core/CesiumTerrainProviderSpec.js +++ b/Specs/Core/CesiumTerrainProviderSpec.js @@ -11,7 +11,6 @@ defineSuite([ 'Core/Request', 'Core/RequestScheduler', 'Core/Resource', - 'Core/RuntimeError', 'Core/TerrainProvider', 'Specs/pollToPromise', 'ThirdParty/when' @@ -28,7 +27,6 @@ defineSuite([ Request, RequestScheduler, Resource, - RuntimeError, TerrainProvider, pollToPromise, when) { @@ -168,15 +166,16 @@ defineSuite([ }); it('rejects readyPromise when url rejects', function() { + var error = new Error(); var provider = new CesiumTerrainProvider({ - url: when.reject() + url: when.reject(error) }); return provider.readyPromise .then(function() { fail('should not resolve'); }) .otherwise(function(result) { - expect(result).toBeInstanceOf(RuntimeError); + expect(result).toBe(error); expect(provider.ready).toBe(false); }); }); diff --git a/Specs/Scene/createTileMapServiceImageryProviderSpec.js b/Specs/Scene/createTileMapServiceImageryProviderSpec.js index 2a4471888e48..85fd375219d5 100644 --- a/Specs/Scene/createTileMapServiceImageryProviderSpec.js +++ b/Specs/Scene/createTileMapServiceImageryProviderSpec.js @@ -12,7 +12,6 @@ defineSuite([ 'Core/Rectangle', 'Core/RequestScheduler', 'Core/Resource', - 'Core/RuntimeError', 'Core/WebMercatorProjection', 'Core/WebMercatorTilingScheme', 'Scene/Imagery', @@ -35,7 +34,6 @@ defineSuite([ Rectangle, RequestScheduler, Resource, - RuntimeError, WebMercatorProjection, WebMercatorTilingScheme, Imagery, @@ -100,13 +98,14 @@ defineSuite([ }); it('rejects readyPromise if options.url rejects', function() { + var error = new Error(); var provider = createTileMapServiceImageryProvider({ - url : when.reject() + url : when.reject(error) }); return provider.readyPromise.then(function() { fail('should not resolve'); }).otherwise(function(result) { - expect(result).toBeInstanceOf(RuntimeError); + expect(result).toBe(error); expect(provider.ready).toBe(false); }); });