DSDSWeb/static/js/Cesium-1.53/Specs/Core/ResourceSpec.js

2112 lines
84 KiB
JavaScript
Raw Normal View History

2024-07-11 18:02:47 +08:00
defineSuite([
'Core/Resource',
'Core/defaultValue',
'Core/DefaultProxy',
'Core/queryToObject',
'Core/Request',
'Core/RequestErrorEvent',
'Core/RequestScheduler',
'ThirdParty/Uri',
'ThirdParty/when'
], function(
Resource,
defaultValue,
DefaultProxy,
queryToObject,
Request,
RequestErrorEvent,
RequestScheduler,
Uri,
when) {
'use strict';
it('Constructor sets correct properties', function() {
var proxy = new DefaultProxy('/proxy/');
var request = new Request();
function retryFunc() {
}
var resource = new Resource({
url: 'http://test.com/tileset',
queryParameters: {
key1: 'value1',
key2: 'value2'
},
templateValues: {
key3: 'value3',
key4: 'value4'
},
headers: {
Accept: 'application/test-type'
},
proxy: proxy,
retryCallback: retryFunc,
retryAttempts: 4,
request: request
});
expect(resource.getUrlComponent(false, false)).toEqual('http://test.com/tileset');
expect(resource.getUrlComponent(true, false)).toEqual('http://test.com/tileset?key1=value1&key2=value2');
expect(resource.getUrlComponent(false, true)).toEqual(proxy.getURL('http://test.com/tileset'));
expect(resource.getUrlComponent(true, true)).toEqual(proxy.getURL('http://test.com/tileset?key1=value1&key2=value2'));
expect(resource.url).toEqual(proxy.getURL('http://test.com/tileset?key1=value1&key2=value2'));
expect(resource.queryParameters).toEqual({
key1: 'value1',
key2: 'value2'
});
expect(resource.templateValues).toEqual({
key3: 'value3',
key4: 'value4'
});
expect(resource.headers).toEqual({
Accept: 'application/test-type'
});
expect(resource.proxy).toBe(proxy);
expect(resource.retryCallback).toBe(retryFunc);
expect(resource.retryAttempts).toEqual(4);
expect(resource._retryCount).toEqual(0);
expect(resource.request).toBe(request);
});
it('Constructor sets correct properties', function() {
var url = 'http://invalid.domain.com/tileset';
var resource = new Resource(url);
expect(resource.url).toEqual(url);
expect(resource.queryParameters).toEqual({});
expect(resource.templateValues).toEqual({});
expect(resource.headers).toEqual({});
expect(resource.proxy).toBeUndefined();
expect(resource.retryCallback).toBeUndefined();
expect(resource.retryAttempts).toEqual(0);
expect(resource.request).toBeDefined();
});
it('_makeRequest returns undefined if the request is throttled', function() {
var oldMaximumRequests = RequestScheduler.maximumRequests;
RequestScheduler.maximumRequests = 0;
var resource = new Resource({
url: 'http://example.invalid/testuri',
request: new Request({
throttle: true
})
});
var promise = resource._makeRequest({ method: 'GET' });
expect(promise).toBeUndefined();
RequestScheduler.maximumRequests = oldMaximumRequests;
});
it('appendForwardSlash appends a /', function() {
var resource = new Resource({
url: 'http://test.com/tileset'
});
expect(resource.url).toEqual('http://test.com/tileset');
resource.appendForwardSlash();
expect(resource.url).toEqual('http://test.com/tileset/');
});
it('Setting a url with a query string sets queryParameters correctly', function() {
var resource = new Resource({
url: 'http://test.com/tileset?foo=bar&baz=foo'
});
expect(resource.getUrlComponent()).toEqual('http://test.com/tileset');
expect(resource.getUrlComponent(true)).toEqual('http://test.com/tileset?foo=bar&baz=foo');
expect(resource.queryParameters).toEqual({
foo: 'bar',
baz: 'foo'
});
});
it('createIfNeeded returns undefined, if parameter is undefined', function() {
expect(Resource.createIfNeeded()).toBeUndefined();
});
it('createIfNeeded returns Resource, if parameter is a Resource', function() {
var resource = new Resource({
url: 'http://test.com/tileset'
});
expect(Resource.createIfNeeded(resource)).toEqual(resource);
});
it('createIfNeeded returns Resource, if parameter is a String', function() {
var resource = Resource.createIfNeeded('http://test.com/tileset');
expect(resource.url).toEqual('http://test.com/tileset');
});
it('multiple values for query parameters are allowed', function() {
var resource = new Resource('http://test.com/tileset/endpoint?a=1&a=2&b=3&a=4');
expect(resource.queryParameters.a).toEqual(['1', '2', '4']);
expect(resource.queryParameters.b).toEqual('3');
expect(resource.url).toEqual('http://test.com/tileset/endpoint?a=1&a=2&a=4&b=3');
});
it('multiple values for query parameters works with getDerivedResource without preserverQueryParameters', function() {
var resource = new Resource('http://test.com/tileset/endpoint?a=1&a=2&b=3&a=4');
expect(resource.queryParameters.a).toEqual(['1', '2', '4']);
expect(resource.queryParameters.b).toEqual('3');
expect(resource.url).toEqual('http://test.com/tileset/endpoint?a=1&a=2&a=4&b=3');
var derived = resource.getDerivedResource({
url: 'other_endpoint?a=5&b=6&a=7'
});
expect(derived.queryParameters.a).toEqual(['5', '7']);
expect(derived.queryParameters.b).toEqual('6');
expect(derived.url).toEqual('http://test.com/tileset/other_endpoint?a=5&a=7&b=6');
});
it('multiple values for query parameters works with getDerivedResource with preserveQueryParameters', function() {
var resource = new Resource('http://test.com/tileset/endpoint?a=1&a=2&b=3&a=4');
expect(resource.queryParameters.a).toEqual(['1', '2', '4']);
expect(resource.queryParameters.b).toEqual('3');
expect(resource.url).toEqual('http://test.com/tileset/endpoint?a=1&a=2&a=4&b=3');
var derived = resource.getDerivedResource({
url: 'other_endpoint?a=5&b=6&a=7',
preserveQueryParameters: true
});
expect(derived.queryParameters.a).toEqual(['5', '7', '1', '2', '4']);
expect(derived.queryParameters.b).toEqual(['6', '3']);
expect(derived.url).toEqual('http://test.com/tileset/other_endpoint?a=5&a=7&a=1&a=2&a=4&b=6&b=3');
});
it('templateValues are respected', function() {
var resource = new Resource({
url: 'http://test.com/tileset/{foo}/{bar}',
templateValues: {
foo: 'test1',
bar: 'test2'
}
});
expect(resource.url).toEqual('http://test.com/tileset/test1/test2');
});
it('getDerivedResource sets correct properties', function() {
var proxy = new DefaultProxy('/proxy/');
var request = new Request();
function retryFunc() {
}
var parent = new Resource({
url: 'http://test.com/tileset?key=value',
queryParameters: {
foo: 'bar'
},
templateValues: {
key5: 'value5',
key6: 'value6'
}
});
parent.appendForwardSlash();
var resource = parent.getDerivedResource({
url: 'tileset.json',
queryParameters: {
key1: 'value1',
key2: 'value2'
},
templateValues: {
key3: 'value3',
key4: 'value4'
},
headers: {
Accept: 'application/test-type'
},
proxy: proxy,
retryCallback: retryFunc,
retryAttempts: 4,
request: request
});
expect(resource.getUrlComponent(false, false)).toEqual('http://test.com/tileset/tileset.json');
expect(resource.getUrlComponent(true, false)).toEqual('http://test.com/tileset/tileset.json?key1=value1&key2=value2&key=value&foo=bar');
expect(resource.getUrlComponent(false, true)).toEqual(proxy.getURL('http://test.com/tileset/tileset.json'));
expect(resource.getUrlComponent(true, true)).toEqual(proxy.getURL('http://test.com/tileset/tileset.json?key1=value1&key2=value2&key=value&foo=bar'));
expect(resource.url).toEqual(proxy.getURL('http://test.com/tileset/tileset.json?key1=value1&key2=value2&key=value&foo=bar'));
expect(resource.queryParameters).toEqual({
foo: 'bar',
key: 'value',
key1: 'value1',
key2: 'value2'
});
expect(resource.templateValues).toEqual({
key5: 'value5',
key6: 'value6',
key3: 'value3',
key4: 'value4'
});
expect(resource.headers).toEqual({
Accept: 'application/test-type'
});
expect(resource.proxy).toBe(proxy);
expect(resource.retryCallback).toBe(retryFunc);
expect(resource.retryAttempts).toEqual(4);
expect(resource._retryCount).toEqual(0);
expect(resource.request).toBe(request);
});
it('getDerivedResource works with directory parent resource', function() {
var parent = new Resource({
url: 'http://test.com/tileset/'
});
expect(parent.url).toEqual('http://test.com/tileset/');
var resource = parent.getDerivedResource({
url: 'tileset.json'
});
expect(resource.url).toEqual('http://test.com/tileset/tileset.json');
});
it('getDerivedResource works with file parent resource', function() {
var parent = new Resource({
url: 'http://test.com/tileset/tileset.json'
});
expect(parent.url).toEqual('http://test.com/tileset/tileset.json');
var resource = parent.getDerivedResource({
url: '0/0/0.b3dm'
});
expect(resource.url).toEqual('http://test.com/tileset/0/0/0.b3dm');
});
it('getDerivedResource works with only template values', function() {
var parent = new Resource({
url: 'http://test.com/terrain/{z}/{x}/{y}.terrain'
});
expect(parent.url).toEqual('http://test.com/terrain/{z}/{x}/{y}.terrain');
var resource = parent.getDerivedResource({
templateValues: {
x: 1,
y: 2,
z: 0
}
});
expect(resource.url).toEqual('http://test.com/terrain/0/1/2.terrain');
});
it('getDerivedResource works with only query parameters', function() {
var parent = new Resource({
url: 'http://test.com/terrain'
});
expect(parent.url).toEqual('http://test.com/terrain');
var resource = parent.getDerivedResource({
queryParameters: {
x: 1,
y: 2,
z: 0
}
});
expect(resource.url).toEqual('http://test.com/terrain?x=1&y=2&z=0');
});
it('setQueryParameters with useAsDefault set to true', function() {
var resource = new Resource({
url: 'http://test.com/terrain',
queryParameters: {
x: 1,
y: 2
}
});
expect(resource.queryParameters).toEqual({
x: 1,
y: 2
});
resource.setQueryParameters({
x: 3,
y: 4,
z: 0
}, true);
expect(resource.queryParameters).toEqual({
x: 1,
y: 2,
z: 0
});
});
it('setQueryParameters with useAsDefault set to false', function() {
var resource = new Resource({
url: 'http://test.com/terrain',
queryParameters: {
x: 1,
y: 2
}
});
expect(resource.queryParameters).toEqual({
x: 1,
y: 2
});
resource.setQueryParameters({
x: 3,
y: 4,
z: 0
}, false);
expect(resource.queryParameters).toEqual({
x: 3,
y: 4,
z: 0
});
});
it('appendQueryParameters works with non-arrays', function() {
var resource = new Resource({
url: 'http://test.com/terrain',
queryParameters: {
x: 1,
y: 2
}
});
expect(resource.queryParameters).toEqual({
x: 1,
y: 2
});
resource.appendQueryParameters({
x: 3,
y: 4,
z: 0
});
expect(resource.queryParameters).toEqual({
x: [3, 1],
y: [4, 2],
z: 0
});
});
it('appendQueryParameters works with arrays/non-arrays', function() {
var resource = new Resource({
url: 'http://test.com/terrain',
queryParameters: {
x: [1, 2],
y: 2,
z: [-1, -2]
}
});
expect(resource.queryParameters).toEqual({
x: [1, 2],
y: 2,
z: [-1, -2]
});
resource.appendQueryParameters({
x: 3,
y: [4, 5],
z: [-3, -4]
});
expect(resource.queryParameters).toEqual({
x: [3, 1, 2],
y: [4, 5, 2],
z: [-3, -4, -1, -2]
});
});
it('setTemplateValues with useAsDefault set to true', function() {
var resource = new Resource({
url: 'http://test.com/terrain/{z}/{x}/{y}.terrain',
templateValues: {
x: 1,
y: 2,
map: 'my map'
}
});
expect(resource.templateValues).toEqual({
x: 1,
y: 2,
map: 'my map'
});
resource.setTemplateValues({
x: 3,
y: 4,
z: 0,
style: 'my style'
}, true);
expect(resource.templateValues).toEqual({
x: 1,
y: 2,
map: 'my map',
z: 0,
style: 'my style'
});
});
it('setTemplateValues with useAsDefault set to false', function() {
var resource = new Resource({
url: 'http://test.com/terrain/{z}/{x}/{y}.terrain',
templateValues: {
x: 1,
y: 2,
map: 'my map'
}
});
expect(resource.templateValues).toEqual({
x: 1,
y: 2,
map: 'my map'
});
resource.setTemplateValues({
x: 3,
y: 4,
z: 0,
style: 'my style'
}, false);
expect(resource.templateValues).toEqual({
x: 3,
y: 4,
map: 'my map',
z: 0,
style: 'my style'
});
});
it('retryOnFail doesn\'t exceed retryAttempts', function() {
var cb = jasmine.createSpy('retry').and.returnValue(true);
var resource = new Resource({
url: 'http://test.com/terrain',
retryCallback: cb,
retryAttempts: 3
});
var promises = [];
for (var i=0;i<6;++i) {
promises.push(resource.retryOnError());
}
when.all(promises)
.then(function(result) {
expect(result).toEqual([true, true, true, false, false, false]);
expect(cb.calls.count()).toEqual(3);
expect(resource._retryCount).toEqual(3);
});
});
it('retryOnFail returns value from callback', function() {
var result = true;
var cb = jasmine.createSpy('retry').and.callFake(function() {
result = !result;
return result;
});
var resource = new Resource({
url: 'http://test.com/terrain',
retryCallback: cb,
retryAttempts: 4
});
var promises = [];
for (var i=0;i<6;++i) {
promises.push(resource.retryOnError());
}
when.all(promises)
.then(function(result) {
expect(result).toEqual([false, true, false, true, false, false]);
expect(cb.calls.count()).toEqual(4);
expect(resource._retryCount).toEqual(4);
});
});
it('isDataUri returns correct values', function() {
var dataResource = new Resource({
url: 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3'
});
expect(dataResource.isDataUri).toBe(true);
var resource = new Resource({
url: 'http://invalid.uri/tileset'
});
expect(resource.isDataUri).toBe(false);
});
it('isBlobUri returns correct values', function() {
var dataResource = new Resource({
url: 'blob:d3958f5c-0777-0845-9dcf-2cb28783acaf'
});
expect(dataResource.isBlobUri).toBe(true);
var resource = new Resource({
url: 'http://invalid.uri/tileset'
});
expect(resource.isBlobUri).toBe(false);
});
it('post calls with correct method', function() {
var expectedUrl = 'http://test.com/endpoint';
var expectedResponseType = 'json';
var expectedData = {
stuff: 'myStuff'
};
var expectedHeaders = {
'X-My-Header': 'My-Value'
};
var expectedResult = {
status: 'success'
};
var expectedMimeType = 'application/test-data';
var resource = new Resource({
url: expectedUrl,
headers: expectedHeaders
});
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
expect(url).toEqual(expectedUrl);
expect(responseType).toEqual(expectedResponseType);
expect(method).toEqual('POST');
expect(data).toEqual(expectedData);
expect(headers['X-My-Header']).toEqual('My-Value');
expect(headers['X-My-Other-Header']).toEqual('My-Other-Value');
expect(overrideMimeType).toBe(expectedMimeType);
deferred.resolve(expectedResult);
});
return resource.post(expectedData, {
responseType: expectedResponseType,
headers: {
'X-My-Other-Header': 'My-Other-Value'
},
overrideMimeType: expectedMimeType
})
.then(function(result) {
expect(result).toEqual(expectedResult);
});
});
it('static post calls with correct method', function() {
var expectedUrl = 'http://test.com/endpoint';
var expectedResponseType = 'json';
var expectedData = {
stuff: 'myStuff'
};
var expectedHeaders = {
'X-My-Header': 'My-Value'
};
var expectedResult = {
status: 'success'
};
var expectedMimeType = 'application/test-data';
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
expect(url).toEqual(expectedUrl);
expect(responseType).toEqual(expectedResponseType);
expect(method).toEqual('POST');
expect(data).toEqual(expectedData);
expect(headers).toEqual(expectedHeaders);
expect(overrideMimeType).toBe(expectedMimeType);
deferred.resolve(expectedResult);
});
return Resource.post({
url: expectedUrl,
data: expectedData,
responseType: expectedResponseType,
headers: expectedHeaders,
overrideMimeType: expectedMimeType
})
.then(function(result) {
expect(result).toEqual(expectedResult);
});
});
it('put calls with correct method', function() {
var expectedUrl = 'http://test.com/endpoint';
var expectedResponseType = 'json';
var expectedData = {
stuff: 'myStuff'
};
var expectedHeaders = {
'X-My-Header': 'My-Value'
};
var expectedResult = {
status: 'success'
};
var expectedMimeType = 'application/test-data';
var resource = new Resource({
url: expectedUrl,
headers: expectedHeaders
});
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
expect(url).toEqual(expectedUrl);
expect(responseType).toEqual(expectedResponseType);
expect(method).toEqual('PUT');
expect(data).toEqual(expectedData);
expect(headers['X-My-Header']).toEqual('My-Value');
expect(headers['X-My-Other-Header']).toEqual('My-Other-Value');
expect(overrideMimeType).toBe(expectedMimeType);
deferred.resolve(expectedResult);
});
return resource.put(expectedData, {
responseType: expectedResponseType,
headers: {
'X-My-Other-Header': 'My-Other-Value'
},
overrideMimeType: expectedMimeType
})
.then(function(result) {
expect(result).toEqual(expectedResult);
});
});
it('static put calls with correct method', function() {
var expectedUrl = 'http://test.com/endpoint';
var expectedResponseType = 'json';
var expectedData = {
stuff: 'myStuff'
};
var expectedHeaders = {
'X-My-Header': 'My-Value'
};
var expectedResult = {
status: 'success'
};
var expectedMimeType = 'application/test-data';
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
expect(url).toEqual(expectedUrl);
expect(responseType).toEqual(expectedResponseType);
expect(method).toEqual('PUT');
expect(data).toEqual(expectedData);
expect(headers).toEqual(expectedHeaders);
expect(overrideMimeType).toBe(expectedMimeType);
deferred.resolve(expectedResult);
});
return Resource.put({
url: expectedUrl,
data: expectedData,
responseType: expectedResponseType,
headers: expectedHeaders,
overrideMimeType: expectedMimeType
})
.then(function(result) {
expect(result).toEqual(expectedResult);
});
});
it('patch calls with correct method', function() {
var expectedUrl = 'http://test.com/endpoint';
var expectedResponseType = 'json';
var expectedData = {
stuff: 'myStuff'
};
var expectedHeaders = {
'X-My-Header': 'My-Value'
};
var expectedResult = {
status: 'success'
};
var expectedMimeType = 'application/test-data';
var resource = new Resource({
url: expectedUrl,
headers: expectedHeaders
});
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
expect(url).toEqual(expectedUrl);
expect(responseType).toEqual(expectedResponseType);
expect(method).toEqual('PATCH');
expect(data).toEqual(expectedData);
expect(headers['X-My-Header']).toEqual('My-Value');
expect(headers['X-My-Other-Header']).toEqual('My-Other-Value');
expect(overrideMimeType).toBe(expectedMimeType);
deferred.resolve(expectedResult);
});
return resource.patch(expectedData, {
responseType: expectedResponseType,
headers: {
'X-My-Other-Header': 'My-Other-Value'
},
overrideMimeType: expectedMimeType
})
.then(function(result) {
expect(result).toEqual(expectedResult);
});
});
it('static patch calls with correct method', function() {
var expectedUrl = 'http://test.com/endpoint';
var expectedResponseType = 'json';
var expectedData = {
stuff: 'myStuff'
};
var expectedHeaders = {
'X-My-Header': 'My-Value'
};
var expectedResult = {
status: 'success'
};
var expectedMimeType = 'application/test-data';
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
expect(url).toEqual(expectedUrl);
expect(responseType).toEqual(expectedResponseType);
expect(method).toEqual('PATCH');
expect(data).toEqual(expectedData);
expect(headers).toEqual(expectedHeaders);
expect(overrideMimeType).toBe(expectedMimeType);
deferred.resolve(expectedResult);
});
return Resource.patch({
url: expectedUrl,
data: expectedData,
responseType: expectedResponseType,
headers: expectedHeaders,
overrideMimeType: expectedMimeType
})
.then(function(result) {
expect(result).toEqual(expectedResult);
});
});
it('static fetchArrayBuffer calls correct method', function() {
var url = 'http://test.com/data';
var expectedResult = when.resolve();
spyOn(Resource.prototype, 'fetchArrayBuffer').and.returnValue(expectedResult);
var result = Resource.fetchArrayBuffer(url);
expect(result).toBe(expectedResult);
return Resource.fetchArrayBuffer(url)
.then(function() {
expect(Resource.prototype.fetchArrayBuffer).toHaveBeenCalled();
});
});
it('fetchArrayBuffer calls fetch with expected parameters', function() {
var url = 'http://test.com/data';
var expectedResult = when.resolve();
spyOn(Resource.prototype, 'fetch').and.returnValue(expectedResult);
var result = Resource.fetchArrayBuffer(url);
expect(result).toBe(expectedResult);
return result
.then(function() {
expect(Resource.prototype.fetch).toHaveBeenCalledWith({ responseType: 'arraybuffer' });
});
});
it('static fetchBlob calls correct method', function() {
var url = 'http://test.com/data';
spyOn(Resource.prototype, 'fetchBlob').and.returnValue(when.resolve());
return Resource.fetchBlob(url)
.then(function() {
expect(Resource.prototype.fetchBlob).toHaveBeenCalled();
});
});
it('fetchBlob calls fetch with expected parameters', function() {
var url = 'http://test.com/data';
var expectedResult = when.resolve();
spyOn(Resource.prototype, 'fetch').and.returnValue(expectedResult);
var result = Resource.fetchBlob(url);
expect(result).toBe(expectedResult);
return result
.then(function() {
expect(Resource.prototype.fetch).toHaveBeenCalledWith({ responseType: 'blob' });
});
});
it('fetchArrayBuffer calls fetch with expected parameters', function() {
var url = 'http://test.com/data';
var expectedResult = when.resolve();
spyOn(Resource.prototype, 'fetch').and.returnValue(expectedResult);
var result = Resource.fetchArrayBuffer(url);
expect(result).toBe(expectedResult);
return result
.then(function() {
expect(Resource.prototype.fetch).toHaveBeenCalledWith({ responseType: 'arraybuffer' });
});
});
it('static fetchImage calls correct method', function() {
var url = 'http://test.com/data';
spyOn(Resource.prototype, 'fetchImage').and.returnValue(when.resolve());
return Resource.fetchImage(url)
.then(function() {
expect(Resource.prototype.fetchImage).toHaveBeenCalled();
});
});
it('static fetchText calls correct method', function() {
var url = 'http://test.com/data';
spyOn(Resource.prototype, 'fetchText').and.returnValue(when.resolve());
return Resource.fetchText(url)
.then(function() {
expect(Resource.prototype.fetchText).toHaveBeenCalled();
});
});
it('fetchText calls fetch with expected parameters', function() {
var url = 'http://test.com/data';
var expectedResult = when.resolve();
spyOn(Resource.prototype, 'fetch').and.returnValue(expectedResult);
var result = Resource.fetchText(url);
expect(result).toBe(expectedResult);
return result
.then(function() {
expect(Resource.prototype.fetch).toHaveBeenCalledWith({ responseType: 'text' });
});
});
it('static fetchJson calls correct method', function() {
var url = 'http://test.com/data';
spyOn(Resource.prototype, 'fetchJson').and.returnValue(when.resolve());
return Resource.fetchJson(url)
.then(function() {
expect(Resource.prototype.fetchJson).toHaveBeenCalled();
});
});
it('fetchJson calls fetch with expected parameters and parses result', function() {
var expectedResult = { x: 123 };
spyOn(Resource.prototype, 'fetch').and.returnValue(when.resolve(JSON.stringify(expectedResult)));
return Resource.fetchJson('url')
.then(function(result) {
expect(result).toEqual(expectedResult);
expect(Resource.prototype.fetch).toHaveBeenCalledWith({
responseType: 'text',
headers: {
Accept: 'application/json,*/*;q=0.01'
}
});
});
});
it('static fetchXML calls correct method', function() {
var url = 'http://test.com/data';
spyOn(Resource.prototype, 'fetchXML').and.returnValue(when.resolve());
return Resource.fetchXML(url)
.then(function() {
expect(Resource.prototype.fetchXML).toHaveBeenCalled();
});
});
it('fetchXML calls fetch with expected parameters', function() {
var url = 'http://test.com/data';
var expectedResult = when.resolve();
spyOn(Resource.prototype, 'fetch').and.returnValue(expectedResult);
var result = Resource.fetchXML(url);
expect(result).toBe(expectedResult);
return result
.then(function() {
expect(Resource.prototype.fetch).toHaveBeenCalledWith({
responseType: 'document',
overrideMimeType: 'text/xml'
});
});
});
it('static fetchJsonp calls correct method', function() {
var url = 'http://test.com/data';
spyOn(Resource.prototype, 'fetchJsonp').and.returnValue(when.resolve());
return Resource.fetchJsonp(url)
.then(function() {
expect(Resource.prototype.fetchJsonp).toHaveBeenCalled();
});
});
it('static fetch calls correct method', function() {
var url = 'http://test.com/data';
spyOn(Resource.prototype, 'fetch').and.returnValue(when.resolve());
return Resource.fetch(url)
.then(function() {
expect(Resource.prototype.fetch).toHaveBeenCalled();
});
});
it('fetch calls correct method', function() {
var expectedUrl = 'http://test.com/endpoint';
var expectedResult = {
status: 'success'
};
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
expect(url).toEqual(expectedUrl);
expect(method).toEqual('GET');
deferred.resolve(expectedResult);
});
var resource = new Resource({url: expectedUrl});
return resource.fetch()
.then(function(result) {
expect(result).toEqual(expectedResult);
});
});
it('static delete calls correct method', function() {
var url = 'http://test.com/data';
spyOn(Resource.prototype, 'delete').and.returnValue(when.resolve());
return Resource.delete(url)
.then(function() {
expect(Resource.prototype.delete).toHaveBeenCalled();
});
});
it('delete calls correct method', function() {
var expectedUrl = 'http://test.com/endpoint';
var expectedResult = {
status: 'success'
};
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
expect(url).toEqual(expectedUrl);
expect(method).toEqual('DELETE');
deferred.resolve(expectedResult);
});
var resource = new Resource({url: expectedUrl});
return resource.delete()
.then(function(result) {
expect(result).toEqual(expectedResult);
});
});
it('static head calls correct method', function() {
var url = 'http://test.com/data';
spyOn(Resource.prototype, 'head').and.returnValue(when.resolve({}));
return Resource.head(url)
.then(function() {
expect(Resource.prototype.head).toHaveBeenCalled();
});
});
it('head calls correct method', function() {
var expectedUrl = 'http://test.com/endpoint';
var expectedResult = {
'accept-ranges': 'bytes',
'access-control-allow-headers' : 'Origin, X-Requested-With, Content-Type, Accept',
'access-control-allow-origin' : '*',
'cache-control': 'public, max-age=0',
'connection' : 'keep-alive',
'content-length' : '883',
'content-type' : 'image/png',
'date' : 'Tue, 13 Feb 2018 03:38:55 GMT',
'etag' : 'W/"373-15e34d146a1"',
'vary' : 'Accept-Encoding',
'x-powered-vy' : 'Express'
};
var headerString = '';
for (var key in expectedResult) {
if (expectedResult.hasOwnProperty(key)) {
headerString += key + ': ' + expectedResult[key] + '\r\n';
}
}
var fakeXHR = {
status: 200,
send : function() {
this.onload();
},
open : function() {},
getAllResponseHeaders : function() {
return headerString;
}
};
spyOn(window, 'XMLHttpRequest').and.returnValue(fakeXHR);
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
expect(url).toEqual(expectedUrl);
expect(method).toEqual('HEAD');
Resource._DefaultImplementations.loadWithXhr(url, responseType, method, data, headers, deferred, overrideMimeType);
});
var resource = new Resource({url: expectedUrl});
return resource.head()
.then(function(result) {
expect(result.date).toEqual(expectedResult.date);
expect(result['last-modified']).toEqual(expectedResult['last-modified']);
expect(result['x-powered-by']).toEqual(expectedResult['x-powered-by']);
expect(result.etag).toEqual(expectedResult.etag);
expect(result['content-type']).toEqual(expectedResult['content-type']);
expect(result['access-control-allow-origin']).toEqual(expectedResult['access-control-allow-origin']);
expect(result['cache-control']).toEqual(expectedResult['cache-control']);
expect(result['accept-ranges']).toEqual(expectedResult['accept-ranges']);
expect(result['access-control-allow-headers']).toEqual(expectedResult['access-control-allow-headers']);
expect(result['content-length']).toEqual(expectedResult['content-length']);
});
});
it('static options calls correct method', function() {
var url = 'http://test.com/data';
spyOn(Resource.prototype, 'options').and.returnValue(when.resolve({}));
return Resource.options(url)
.then(function() {
expect(Resource.prototype.options).toHaveBeenCalled();
});
});
it('options calls correct method', function() {
var expectedUrl = 'http://test.com/endpoint';
var expectedResult = {
'access-control-allow-headers' : 'Origin, X-Requested-With, Content-Type, Accept',
'access-control-allow-methods' : 'GET, PUT, POST, DELETE, OPTIONS',
'access-control-allow-origin' : '*',
'connection' : 'keep-alive',
'content-length' : '2',
'content-type' : 'text/plain; charset=utf-8',
'date' : 'Tue, 13 Feb 2018 03:38:55 GMT',
'etag' : 'W/"2-nOO9QiTIwXgNtWtBJezz8kv3SLc"',
'vary' : 'Accept-Encoding',
'x-powered-vy' : 'Express'
};
var headerString = '';
for (var key in expectedResult) {
if (expectedResult.hasOwnProperty(key)) {
headerString += key + ': ' + expectedResult[key] + '\r\n';
}
}
var fakeXHR = {
status: 200,
send : function() {
this.onload();
},
open : function() {},
getAllResponseHeaders : function() {
return headerString;
}
};
spyOn(window, 'XMLHttpRequest').and.returnValue(fakeXHR);
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
expect(url).toEqual(expectedUrl);
expect(method).toEqual('OPTIONS');
Resource._DefaultImplementations.loadWithXhr(url, responseType, method, data, headers, deferred, overrideMimeType);
});
var resource = new Resource({url: expectedUrl});
return resource.options()
.then(function(result) {
expect(result.date).toEqual(expectedResult.date);
expect(result['x-powered-by']).toEqual(expectedResult['x-powered-by']);
expect(result.etag).toEqual(expectedResult.etag);
expect(result['content-type']).toEqual(expectedResult['content-type']);
expect(result['access-control-allow-origin']).toEqual(expectedResult['access-control-allow-origin']);
expect(result['access-control-allow-methods']).toEqual(expectedResult['access-control-allow-methods']);
expect(result['access-control-allow-headers']).toEqual(expectedResult['access-control-allow-headers']);
expect(result['content-length']).toEqual(expectedResult['content-length']);
});
});
describe('fetchImage', function() {
var dataUri = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVQIW2Nk+M/wHwAEBgIA5agATwAAAABJRU5ErkJggg==';
it('can load an image', function() {
return Resource.fetchImage('./Data/Images/Green.png').then(function(loadedImage) {
expect(loadedImage.width).toEqual(1);
expect(loadedImage.height).toEqual(1);
});
});
it('can load an image preferring blob', function() {
return Resource.fetchImage('./Data/Images/Green.png', true).then(function(loadedImage) {
expect(loadedImage.width).toEqual(1);
expect(loadedImage.height).toEqual(1);
});
});
it('can load an image from a data URI', function() {
return Resource.fetchImage(dataUri).then(function(loadedImage) {
expect(loadedImage.width).toEqual(1);
expect(loadedImage.height).toEqual(1);
});
});
it('sets the crossOrigin property for cross-origin images', function() {
var fakeImage = {};
var imageConstructorSpy = spyOn(window, 'Image').and.returnValue(fakeImage);
Resource.fetchImage('http://example.invalid/someImage.png');
expect(imageConstructorSpy).toHaveBeenCalled();
expect(fakeImage.crossOrigin).toEqual('');
});
it('does not set the crossOrigin property for non-cross-origin images', function() {
var fakeImage = {};
var imageConstructorSpy = spyOn(window, 'Image').and.returnValue(fakeImage);
Resource.fetchImage('./someImage.png');
expect(imageConstructorSpy).toHaveBeenCalled();
expect(fakeImage.crossOrigin).toBeUndefined();
});
it('does not set the crossOrigin property for data URIs', function() {
var fakeImage = {};
var imageConstructorSpy = spyOn(window, 'Image').and.returnValue(fakeImage);
Resource.fetchImage(dataUri);
expect(imageConstructorSpy).toHaveBeenCalled();
expect(fakeImage.crossOrigin).toBeUndefined();
});
it('resolves the promise when the image loads', function() {
var fakeImage = {};
spyOn(window, 'Image').and.returnValue(fakeImage);
var success = false;
var failure = false;
var loadedImage;
when(Resource.fetchImage(dataUri), function(image) {
success = true;
loadedImage = image;
}, function() {
failure = true;
});
// neither callback has fired yet
expect(success).toEqual(false);
expect(failure).toEqual(false);
fakeImage.onload();
expect(success).toEqual(true);
expect(failure).toEqual(false);
expect(loadedImage).toBe(fakeImage);
});
it('rejects the promise when the image errors', function() {
var fakeImage = {};
spyOn(window, 'Image').and.returnValue(fakeImage);
var success = false;
var failure = false;
var loadedImage;
when(Resource.fetchImage(dataUri), function(image) {
success = true;
loadedImage = image;
}, function() {
failure = true;
});
// neither callback has fired yet
expect(success).toEqual(false);
expect(failure).toEqual(false);
fakeImage.onerror();
expect(success).toEqual(false);
expect(failure).toEqual(true);
expect(loadedImage).toBeUndefined();
});
it('Calls loadWithXhr with blob response type if headers is set', function() {
var expectedUrl = 'http://example.invalid/testuri.png';
var expectedHeaders = {
'X-my-header': 'my-value'
};
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
expect(url).toEqual(expectedUrl);
expect(headers).toEqual(expectedHeaders);
expect(responseType).toEqual('blob');
var binary = atob(dataUri.split(',')[1]);
var array = [];
for (var i = 0; i < binary.length; i++) {
array.push(binary.charCodeAt(i));
}
deferred.resolve(new Blob([new Uint8Array(array)], { type: 'image/png' }));
});
var testResource = new Resource({
url: expectedUrl,
headers: expectedHeaders
});
var promise = testResource.fetchImage();
expect(promise).toBeDefined();
return promise
.then(function(image) {
expect(image).toBeDefined();
});
});
it('Doesn\'t call loadWithXhr with blob response type if headers is set but is a data URI', function() {
spyOn(Resource._Implementations, 'loadWithXhr').and.callFake(function(url, responseType, method, data, headers, deferred, overrideMimeType) {
deferred.reject('this shouldn\'t happen');
});
spyOn(Resource._Implementations, 'createImage').and.callFake(function(url, crossOrigin, deferred) {
expect(url).toEqual(dataUri);
}).and.callThrough();
var testResource = new Resource({
url: dataUri,
headers: {
'X-my-header': 'my-value'
}
});
var promise = testResource.fetchImage();
expect(promise).toBeDefined();
return promise
.then(function(image) {
expect(image).toBeDefined();
});
});
describe('retries when Resource has the callback set', function() {
it('rejects after too many retries', function() {
var fakeImage = {};
spyOn(window, 'Image').and.returnValue(fakeImage);
var cb = jasmine.createSpy('retry').and.returnValue(true);
var resource = new Resource({
url: 'http://example.invalid/image.png',
retryCallback: cb,
retryAttempts: 1
});
var promise = resource.fetchImage();
expect(promise).toBeDefined();
var success = false;
var failure = false;
promise.then(function() {
success = true;
}).otherwise(function() {
failure = true;
});
expect(success).toBe(false);
expect(failure).toBe(false);
fakeImage.onerror('some error'); // This should retry
expect(success).toBe(false);
expect(failure).toBe(false);
expect(cb.calls.count()).toEqual(1);
var receivedResource = cb.calls.argsFor(0)[0];
expect(receivedResource.url).toEqual(resource.url);
expect(receivedResource._retryCount).toEqual(1);
expect(cb.calls.argsFor(0)[1]).toEqual('some error');
fakeImage.onerror(); // This fails because we only retry once
expect(success).toBe(false);
expect(failure).toBe(true);
});
it('rejects after callback returns false', function() {
var fakeImage = {};
spyOn(window, 'Image').and.returnValue(fakeImage);
var cb = jasmine.createSpy('retry').and.returnValue(false);
var resource = new Resource({
url: 'http://example.invalid/image.png',
retryCallback: cb,
retryAttempts: 2
});
var promise = resource.fetchImage();
expect(promise).toBeDefined();
var success = false;
var failure = false;
promise.then(function(value) {
success = true;
}).otherwise(function(error) {
failure = true;
});
expect(success).toBe(false);
expect(failure).toBe(false);
fakeImage.onerror('some error'); // This fails because the callback returns false
expect(success).toBe(false);
expect(failure).toBe(true);
expect(cb.calls.count()).toEqual(1);
var receivedResource = cb.calls.argsFor(0)[0];
expect(receivedResource.url).toEqual(resource.url);
expect(receivedResource._retryCount).toEqual(1);
expect(cb.calls.argsFor(0)[1]).toEqual('some error');
});
it('resolves after retry', function() {
var fakeImage = {};
spyOn(window, 'Image').and.returnValue(fakeImage);
var cb = jasmine.createSpy('retry').and.returnValue(true);
var resource = new Resource({
url: 'http://example.invalid/image.png',
retryCallback: cb,
retryAttempts: 1
});
var promise = resource.fetchImage();
expect(promise).toBeDefined();
var success = false;
var failure = false;
promise.then(function(value) {
success = true;
}).otherwise(function(error) {
failure = true;
});
expect(success).toBe(false);
expect(failure).toBe(false);
fakeImage.onerror('some error'); // This should retry
expect(success).toBe(false);
expect(failure).toBe(false);
expect(cb.calls.count()).toEqual(1);
var receivedResource = cb.calls.argsFor(0)[0];
expect(receivedResource.url).toEqual(resource.url);
expect(receivedResource._retryCount).toEqual(1);
expect(cb.calls.argsFor(0)[1]).toEqual('some error');
fakeImage.onload();
expect(success).toBe(true);
expect(failure).toBe(false);
});
});
});
describe('loadWithXhr', function(){
var loadWithXhr = function(options) {
var resource = new Resource(options);
return resource._makeRequest({
responseType: options.responseType,
overrideMimeType: options.overrideMimeType,
method: defaultValue(options.method, 'GET'),
data: options.data
});
};
describe('data URI loading', function() {
it('can load URI escaped text with default response type', function() {
return loadWithXhr({
url : 'data:,Hello%2C%20World!'
}).then(function(result) {
expect(result).toEqual('Hello, World!');
});
});
it('can load URI escaped text with responseType=text', function() {
return loadWithXhr({
url : 'data:,Hello%2C%20World!',
responseType : 'text'
}).then(function(result) {
expect(result).toEqual('Hello, World!');
});
});
it('can load Base64 encoded text with default response type', function() {
return loadWithXhr({
url : 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ=='
}).then(function(result) {
expect(result).toEqual('Hello, World!');
});
});
it('can load Base64 encoded text with responseType=text', function() {
return loadWithXhr({
url : 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==',
responseType : 'text'
}).then(function(result) {
expect(result).toEqual('Hello, World!');
});
});
it('can load Base64 & URI encoded text with default responseType', function() {
return loadWithXhr({
url : 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D'
}).then(function(result) {
expect(result).toEqual('Hello, World!');
});
});
it('can load Base64 & URI encoded text with responseType=text', function() {
return loadWithXhr({
url : 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D',
responseType : 'text'
}).then(function(result) {
expect(result).toEqual('Hello, World!');
});
});
it('can load URI escaped HTML as text with default responseType', function() {
return loadWithXhr({
url : 'data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E'
}).then(function(result) {
expect(result).toEqual('<h1>Hello, World!</h1>');
});
});
it('can load URI escaped HTML as text with responseType=text', function() {
return loadWithXhr({
url : 'data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E',
responseType : 'text'
}).then(function(result) {
expect(result).toEqual('<h1>Hello, World!</h1>');
});
});
it('can load URI escaped text as JSON', function() {
return loadWithXhr({
url : 'data:application/json,%7B%22key%22%3A%22value%22%7D',
responseType : 'json'
}).then(function(result) {
expect(result.key).toEqual('value');
});
});
it('can load Base64 encoded text as JSON', function() {
return loadWithXhr({
url : 'data:application/json;base64,eyJrZXkiOiJ2YWx1ZSJ9',
responseType : 'json'
}).then(function(result) {
expect(result.key).toEqual('value');
});
});
it('can load URI escaped HTML as document', function() {
return loadWithXhr({
url : 'data:text/html,%3Ch1%3EHello%2C%20World!%3C%2Fh1%3E',
responseType : 'document'
}).then(function(result) {
expect(result.querySelector('h1')).not.toBeNull();
});
});
var tile = 'data:;base64,rZ+P95jW+j0AAABAplRYwQAAAAAAAAAAFwEcw/RY1UUqDN/so3WJQETWnpq/aabA19EOeYzEh8D+6WPqtldYQYlaPeMGcRRAO+KDbxWIcsMAAAAAAAAAANsAAAD+N/03/mf/UQDq/f/+T/8foDBgL/8TACwAWP8H/xf/H/8b/yMAGP8r/wv/H/8P/w8ACP8PAEj/F/8TADwAIAAg/w8AMAAg/wcAGP8v/xf/J4gPIBOnIv8P/wf/FwAo/xfkM+MXACwACAAAAAgAGAAA/w//B/8P/wf/D/8XmgmZGf8XAAgAEBYZFQkAGAAQABj/DwAQAAgAEAAA/w8ACP8P/w8AIP8v2QD9DScR/w8AGAAQABAACAAQABwABAAIAAAAAAAI/xf/HwAQ/y8ADP8j/wf/D/8HRAlDEQAAABAAIP8fADAAFP8P/xP/H/8H5wf4Ag8TAAAABAAEAAD/D/8HAAAAAAAANhLKBf8HABAAIAAA/y95GHoIAAD/D/8DAAz/BwAAAAD/DwAAAAAAAAAAABD/Gz4Vwhb/G/8XAKz9t/4XAAj/D/0P/g8AAP0PAAAAAP4P/Q8AAAAAAAD+//8TABT/PwBA/y8AGP8n/w8AKAAYABAAAAAAAAAAAP8PABD/DwAQAAD/DwAIAAgAAP8PABD9//4P/Q/+H/8P/Q/+EwAYAAz/H/8PABj9H/43ABAACP1PAADWBdUF/gMADv0R/g8AEP8LdwCHBwAI/wsACP8HAAAACAAMAAQACP8DAAwACP8P/wcAIP8PABAACAAE/xsAAP8HABj/H/8HABT/CwAQABAAAL4WFwSlAv8PABAAAAAIAAh0A4wEAAD/B/8P/w8AAAAQAAgAEAAQ/wcAAAAI9wQHCwAAABAAAAgI+Af/BwAA/wcAEAAA/xf/BwAYAAAAGAAAAAD/DwAQuw/4AMQO/w8AGAAAAAAAEP8HAAT/E/8HABAAIFESUgoACP8D/wsAFP8T/w//D/8H1hvVA/8PACAADAAEAAgABAAQ/xMACP8HYREzDGkK/w8AHP8j/w8AAAAY/w8AMP8P5hoaHf8PACD/BwAQAAQ5HjoS/yf/HwAU/xv/B/8P/w8AEP8PACAAEAAgAAj/G7ItTh7/CwAIAAQACP8f/w//D/8P/w//DwAQ/w//DwAAAEAAEAAQABAAEP8TAAT/B/8H/wcACP8HABj/JwAIAAD/D/8P/w//D/8PAAD/DwAA/w8AAP8PAAD/D/8H/wcAQAAA/w8AAAAA/w8ABAAAABT/JwAIAAD/BwAYABD/D/83ABBwbM1nul3BXggB7QCqADoARH8JagIPNQkNGk5YCQunTVhLcUvMAAsBWAAbAKkArQCgAckA0AAXABwAGwCCAL4AHgqlCgIWfxVhAGAA3wByAKTgYdIxDm8AIwAxAIYAQwAYqNmncha+DYckCgDaADcAiwCuAs4GFAUvBlcI0vb59iAAYQAHAHbgr986A34DMgGBCbIAOABKAH4AlwDMABUB4QC4AdkBDm0OV83CDQCdAPsAPgAuAdwA6AAzAD4W3QmLC+Rs3WzvANwAgQPOCxEAuwomAFUAXoP9gygAKiIvEVYKWQUlFJsAWgQUBrYPnGdRNw9MQgAVAGAAlAA4AHMAkgAXASYApJgDkeZO+VX8BVQRkxb8w2vEpQB0AEcAHgCOAIAAWwCgAFMACQApAE0AKAA5AHTgz99zAD4AtABVAK4ApwCfAD8ApgAeAGMAagBYAD8AwwBMACAAEwBkAAgBLQCKZhlmQgA+AJxXuxLVRE8ATQCAAfIkBxvDA6kIEQA5AAIAPgA1ACwAEAAcADIAFwCSALkAIgGlAZwAnADrAJkAKQAJAMYAcwAaAG0ADwAFALcBuACSAQAAAAAAAAAAAwAAAAMAAwAAAAMABAACAAAABgAAAAAABQAIAAEAAgAIAAAABwABAAkABwAAAAAAAAADAAoACAABAAoAAgAEAAoACAAAAAAACgAAAAQAAQALAAIAAQAAAAUAAQAAAAYABgABAAgAAAAJAAAAAQAKAAMACgACAAkACwAJAAAACgADAAEAAQAOAAwAAAAPAAIADwABAAAAAQAAABEAEAARAAEAFAAQAAAAAQARAAIAAgADAAAAAwABAAAABAABAAMAAAAGAAcABgABAAAABAAHAAAAAQAIAAIAAAAKAAsACgABAAQACwANAAEAAAAOAA0AAQACAA4AAAAAAA8AEQACAA8ADwABAAMAEgACABEAEgATAAAAAQADABMAFAAAAAIAAQAVABYAFgAXAAEAAgABAAAAAgAAAAIAAQADABkABAACAAAAAQAHAAUABwABAAAABwAIAAEACQAHAAAAAAAJAAAACgAAAAQAAgALAAUACwADAAEAAAAPAA4AAQAOAAUADwABABIAAgAAAAIAEwACAAEABgADAAIAEwAAABMAFAACAAEAAgAAAAAAAgAEAAYAAwAEAAEACAACAAYACAAHAAAACQAAAAQAAgABAAoAAAAKAAAACwAOAAAABQAMAAMAAgAMAAEADwAQAAAAAgAQAAEAAAACABIAEgAUAAEAAAADAAIAAAAEAAIABAABAAUABQABAAYAAAAIAAcABwACAAEACAAAAAAAAwACAAoAAQAMAAoAAAAMAA0AAQANAAIAAAANAAAAAAASAA8AAwABAA8ADwAEAAIAEQASAAEAAAASAAAAEwACABUAAwABABMAAAAEAAYAAQACAAQAAAAAAAgACAABAAMABwACAAgAAgAHAAAAAQAIAAoACgAAAAIADAABAAsADQABAAwADQAOAAAAAgAOAAAAAQAPAAAAAwABABAAEgAAABIABAASAAEAEwAAAAIAFQABABQAAQAAAAMAAwAAAAcABAACAAEAAQAFAAcABQAAAAAABwAAAAkAAQAIAAIAAwAIAAAAAQAJAAUAAgAAAAsACwABAAAADAABAA4ADwAOAAEAAAASABAAAgABABAAAQARABIAAAASAAIAEgABAAAAFQATAAEAAAAEAAAABgAHAAUAAQAFAAcABQACAAQABwAAAAIACAAKAAEACgAAAAIAAQALAAAAAQAMAA0ADgABAA0AAAACAA8AAQAPAAAADQABABAAEQASAA0AEgABAA0AAQASAAAAAgABAAAAAQAEAAMAAAAFAAAAAAAHAAMAAQAIAAcAAgAHAAQACAAAAAoAAQAJAAAACgADAAEACwAAAA0ADAADAAAAAQACAA0ADwAOAAIAAgAQAA8AAgAAABEAEwARAAAAAQASAAIAAQAAABUAFAAVAAEAAQAAABUAFQABACkAAgAAAAAAAgAEAAUAAwAEAAAAAQAFAAIABwAAAAcABwABAAQAAAAAAAoAAwAKAAEACgAMAAIAAAANAAwADQABAAMAAAACAA0ADQAQAAEAAAAAAAQABgAEAAEAAwACAAQAAQAFAAYABQAAAAAABwADAAIABwAAAAoAAQAIAAIAAAAOAAsACwACAAEADQAOAAEAAAAAAA8ADwABAA4AAgAPAAAAAQAQAAQAAAATABAAEAADAAEAPAA7ABMAAQA8ABMAPAABAAAAAQACAAAAAwAFAAEABQAGAAAAAAAHAAIAAwAHAAEACAAAAAAACAACAAoAAQAEAAoACAAMAAAAAQADAAkADAANAAkADgABAA0ADwAAAA8AAgAPAAAAAQAQAAIAAAASAAAAEwAUAAEABAATAAIAFAAVAAEAAQAVAAAAAwACAAEAAQAAAAQAAQAGAAQAAAAHAAAACAACAAcAAQAIAAMAAAAKAAgACAADAAEADAAKAAEADAAAAAwAAgAAAA4AAgAOAAEAAAARAA4ADgADAAEAAAAAABMAAwACABMAEwABABIAAAAVABMAAQATAAIAAgAAAAAABAABAAMABQACAAQABgAIAAUAAAADAAYABgAJAAEAAAACAAoACQABAAoAAAAKAAAAAwALAAAAAQAMAAMAAgAMAA4ADgAQAAIAAAADABEAEQAQAAEAAAAAABIAFAACABIAAwASAAEAFAAVAAIAAgAAAAIAAwAWAAAAAA
it('can load Base64 encoded data as arraybuffer', function() {
return loadWithXhr({
url : tile,
responseType : 'arraybuffer'
}).then(function(result) {
expect(result.byteLength).toEqual(3914);
});
});
var image = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEISURBVEhLvVXBDYQwDOuojHKj8LhBbpTbpBCEkZsmIVTXq1RVQGrHiWlLmTTqPiZBlyLgy/KSZQ5JSHDQ/mCYCsC8106kDU0AdwRnvYZArWRcAl0dcYJq1hWCb3hBrumbDAVMwAC82WoRvgMnVMDBnB0nYZFTbE6BBvdUGqVqCbjBIk3PyFFR/NU7EKzru+qZsau3ryPwwCRLKYOzutZuCL6fUmWeJGzNzL/RxAMrUmASSCkkAayk2IxPlwhAAYGpsiHQjbLccfdOY5gKkCXAMi7SscAwbQpAnKyctWyUZ6z8ja3OGMepwD8asz+9FnSvbhU8uVOHFIwQsI3/p0CfhuqCSQuxLqsN6mu8SS+N42MAAAAASUVORK5CYII=';
it('can load Base64 encoded data as blob', function() {
return loadWithXhr({
url : image,
responseType : 'blob'
}).then(function(result) {
expect(result.type).toEqual('image/png');
/*global URL*/
var blobUrl = URL.createObjectURL(result);
return Resource.fetchImage(blobUrl).then(function(image) {
expect(image.width).toEqual(24);
expect(image.height).toEqual(24);
});
});
});
xit('can support 2xx HTTP status (other than 200)', function() {
return loadWithXhr({
method : 'POST',
url : 'http://jsonplaceholder.typicode.com/posts',
data : {
title : 'foo',
body : 'bar',
userId : 1
}
}).then(function(result) {
expect(JSON.parse(result).id).toEqual(101);
});
});
});
describe('URL loading using XHR', function() {
describe('returns a promise that rejects when the request', function() {
it('results in an HTTP status code greater than or equal to 300', function() {
return loadWithXhr({
url : 'http://example.invalid'
}).then(function() {
fail('expected promise to reject');
}).otherwise(function(err) {
expect(err instanceof RequestErrorEvent).toBe(true);
});
});
it('loads an invalid JSON string response with a json responseType', function() {
return loadWithXhr({
url : 'Data/htmlString.txt',
responseType : 'json'
}).then(function() {
fail('expected promise to reject');
}).otherwise(function(err) {
expect(err).toBeDefined();
expect(err instanceof Error).toBe(true);
});
});
});
describe('returns a promise that resolves when the request loads', function() {
it('a non-null response with default responseType', function() {
return loadWithXhr({
url : 'Data/Models/Box/ReadMe.txt'
}).then(function(result) {
expect(result).toBe('CesiumBoxTest-NoTechnique.gltf is a modified glTF that has techniques, shaders & programs removed.');
});
});
it('a non-null response with a browser-supported responseType', function() {
return loadWithXhr({
url : 'Data/Models/Box/ReadMe.txt',
responseType : 'text'
}).then(function(result) {
expect(result).toBe('CesiumBoxTest-NoTechnique.gltf is a modified glTF that has techniques, shaders & programs removed.');
});
});
it('a valid JSON string response as JSON with a json responseType', function() {
return loadWithXhr({
url : 'Data/jsonString.txt',
responseType : 'json'
}).then(function(result) {
expect(result).toEqual(jasmine.objectContaining({hello : 'world'}));
});
});
});
});
describe('URL loading using mocked XHR', function() {
var fakeXHR;
beforeEach(function() {
fakeXHR = jasmine.createSpyObj('XMLHttpRequest', ['send', 'open', 'setRequestHeader', 'abort', 'getAllResponseHeaders']);
fakeXHR.simulateError = function() {
fakeXHR.response = '';
if (typeof fakeXHR.onerror === 'function') {
fakeXHR.onerror();
}
};
fakeXHR.simulateHttpResponse = function(statusCode, response) {
fakeXHR.status = statusCode;
fakeXHR.response = response;
if (typeof fakeXHR.onload === 'function') {
fakeXHR.onload();
}
};
fakeXHR.simulateResponseXMLLoad = function(responseXML) {
fakeXHR.status = 200;
fakeXHR.responseXML = responseXML;
if (typeof fakeXHR.onload === 'function') {
fakeXHR.onload();
}
};
fakeXHR.simulateResponseTextLoad = function(responseText) {
fakeXHR.simulateHttpResponse(200, responseText);
};
spyOn(window, 'XMLHttpRequest').and.returnValue(fakeXHR);
});
describe('returns a promise that rejects when the request', function() {
it('errors', function() {
var promise = loadWithXhr({
url : 'http://example.invalid'
});
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(function(value) {
resolvedValue = value;
}).otherwise(function (error) {
rejectedError = error;
});
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
fakeXHR.simulateError();
expect(resolvedValue).toBeUndefined();
expect(rejectedError instanceof RequestErrorEvent).toBe(true);
});
it('results in an HTTP status code less than 200', function() {
var promise = loadWithXhr({
url : 'http://example.invalid'
});
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(function(value) {
resolvedValue = value;
}).otherwise(function (error) {
rejectedError = error;
});
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
fakeXHR.simulateHttpResponse(199);
expect(resolvedValue).toBeUndefined();
expect(rejectedError instanceof RequestErrorEvent).toBe(true);
});
it('resolves undefined for status code 204', function() {
var promise = loadWithXhr({
url : 'http://example.invalid'
});
expect(promise).toBeDefined();
var resolved = false;
var resolvedValue;
var rejectedError;
promise.then(function(value) {
resolved = true;
resolvedValue = value;
}).otherwise(function (error) {
rejectedError = error;
});
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
fakeXHR.simulateHttpResponse(204);
expect(resolved).toBe(true);
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
});
});
describe('returns a promise that resolves when the request loads', function() {
it('a null response with a \'\' responseType and non-null responseXML with child nodes', function() {
var promise = loadWithXhr({
url : 'http://example.invalid',
responseType : ''
});
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(function(value) {
resolvedValue = value;
}).otherwise(function (error) {
rejectedError = error;
});
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
var responseXML = {
hasChildNodes : jasmine.createSpy('hasChildNodes').and.returnValue(true)
};
fakeXHR.simulateResponseXMLLoad(responseXML);
expect(resolvedValue).toEqual(responseXML);
expect(rejectedError).toBeUndefined();
});
it('a null response with a document responseType and non-null responseXML with child nodes', function() {
var promise = loadWithXhr({
url : 'http://example.invalid',
responseType : 'document'
});
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(function(value) {
resolvedValue = value;
}).otherwise(function (error) {
rejectedError = error;
});
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
var responseXML = {
hasChildNodes : jasmine.createSpy('hasChildNodes').and.returnValue(true)
};
fakeXHR.simulateResponseXMLLoad(responseXML);
expect(resolvedValue).toEqual(responseXML);
expect(rejectedError).toBeUndefined();
});
it('a null response with a \'\' responseType and non-null responseText', function() {
var promise = loadWithXhr({
url : 'http://example.invalid',
responseType : ''
});
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(function(value) {
resolvedValue = value;
}).otherwise(function (error) {
rejectedError = error;
});
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
var responseText = 'hello world';
fakeXHR.simulateResponseTextLoad(responseText);
expect(resolvedValue).toEqual(responseText);
expect(rejectedError).toBeUndefined();
});
it('a null response with a text responseType and non-null responseText', function() {
var promise = loadWithXhr({
url : 'http://example.invalid',
responseType : 'text'
});
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(function(value) {
resolvedValue = value;
}).otherwise(function (error) {
rejectedError = error;
});
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
var responseText = 'hello world';
fakeXHR.simulateResponseTextLoad(responseText);
expect(resolvedValue).toEqual(responseText);
expect(rejectedError).toBeUndefined();
});
});
describe('retries when Resource has the callback set', function() {
it('rejects after too many retries', function() {
var cb = jasmine.createSpy('retry').and.returnValue(true);
var resource = new Resource({
url : 'http://example.invalid',
retryCallback: cb,
retryAttempts: 1
});
var promise = loadWithXhr(resource);
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(function(value) {
resolvedValue = value;
}).otherwise(function (error) {
rejectedError = error;
});
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
fakeXHR.simulateError(); // This should retry
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
expect(cb.calls.count()).toEqual(1);
var receivedResource = cb.calls.argsFor(0)[0];
expect(receivedResource.url).toEqual(resource.url);
expect(receivedResource._retryCount).toEqual(1);
expect(cb.calls.argsFor(0)[1] instanceof RequestErrorEvent).toBe(true);
fakeXHR.simulateError(); // This fails because we only retry once
expect(resolvedValue).toBeUndefined();
expect(rejectedError instanceof RequestErrorEvent).toBe(true);
});
it('rejects after callback returns false', function() {
var cb = jasmine.createSpy('retry').and.returnValue(false);
var resource = new Resource({
url : 'http://example.invalid',
retryCallback: cb,
retryAttempts: 2
});
var promise = loadWithXhr(resource);
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(function(value) {
resolvedValue = value;
}).otherwise(function (error) {
rejectedError = error;
});
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
fakeXHR.simulateError(); // This fails because the callback returns false
expect(resolvedValue).toBeUndefined();
expect(rejectedError instanceof RequestErrorEvent).toBe(true);
expect(cb.calls.count()).toEqual(1);
var receivedResource = cb.calls.argsFor(0)[0];
expect(receivedResource.url).toEqual(resource.url);
expect(receivedResource._retryCount).toEqual(1);
expect(cb.calls.argsFor(0)[1] instanceof RequestErrorEvent).toBe(true);
});
it('resolves after retry', function() {
var cb = jasmine.createSpy('retry').and.returnValue(true);
var resource = new Resource({
url : 'http://example.invalid',
retryCallback: cb,
retryAttempts: 1
});
var promise = loadWithXhr(resource);
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(function(value) {
resolvedValue = value;
}).otherwise(function (error) {
rejectedError = error;
});
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
fakeXHR.simulateError(); // This should retry
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
expect(cb.calls.count()).toEqual(1);
var receivedResource = cb.calls.argsFor(0)[0];
expect(receivedResource.url).toEqual(resource.url);
expect(receivedResource._retryCount).toEqual(1);
expect(cb.calls.argsFor(0)[1] instanceof RequestErrorEvent).toBe(true);
fakeXHR.simulateHttpResponse(200, 'OK');
expect(resolvedValue).toBeDefined();
expect(rejectedError).toBeUndefined();
});
});
});
});
describe('fetchJsonp', function() {
it('returns a promise that resolves when the request loads', function() {
var testUrl = 'http://example.invalid/testuri';
spyOn(Resource._Implementations, 'loadAndExecuteScript').and.callFake(function(url, name, deffered) {
expect(url).toContain(testUrl);
expect(name).toContain('loadJsonp');
expect(deffered).toBeDefined();
});
Resource.fetchJsonp(testUrl);
});
it('returns a promise that rejects when the request errors', function() {
var testUrl = 'http://example.invalid/testuri';
return Resource.fetchJsonp(testUrl).otherwise(function(error) {
expect(error).toBeDefined();
});
});
it('Uses callback name specified in options', function() {
var testUrl = 'test';
var options = {
callbackParameterName: 'testCallback'
};
spyOn(Resource._Implementations, 'loadAndExecuteScript').and.callFake(function(url, functionName, deferred) {
expect(url).toContain('callback=loadJsonp');
});
Resource.fetchJsonp(testUrl, options);
});
describe('retries when Resource has the callback set', function() {
it('rejects after too many retries', function() {
//var cb = jasmine.createSpy('retry').and.returnValue(true);
var cb = jasmine.createSpy('retry').and.callFake(function(resource, error) {
return true;
});
var lastDeferred;
spyOn(Resource._Implementations, 'loadAndExecuteScript').and.callFake(function(url, functionName, deferred) {
lastDeferred = deferred;
});
var resource = new Resource({
url: 'http://example.invalid',
retryCallback: cb,
retryAttempts: 1
});
var promise = resource.fetchJsonp();
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(function(value) {
resolvedValue = value;
}).otherwise(function(error) {
rejectedError = error;
});
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
lastDeferred.reject('some error'); // This should retry
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
expect(cb.calls.count()).toEqual(1);
var receivedResource = cb.calls.argsFor(0)[0];
expect(receivedResource.url).toEqual(resource.url);
expect(receivedResource._retryCount).toEqual(1);
expect(cb.calls.argsFor(0)[1]).toEqual('some error');
lastDeferred.reject('another error'); // This fails because we only retry once
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toEqual('another error');
});
it('rejects after callback returns false', function() {
var cb = jasmine.createSpy('retry').and.returnValue(false);
var lastDeferred;
spyOn(Resource._Implementations, 'loadAndExecuteScript').and.callFake(function(url, functionName, deferred) {
lastDeferred = deferred;
});
var resource = new Resource({
url: 'http://example.invalid',
retryCallback: cb,
retryAttempts: 2
});
var promise = resource.fetchJsonp();
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(function(value) {
resolvedValue = value;
}).otherwise(function(error) {
rejectedError = error;
});
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
lastDeferred.reject('some error'); // This fails because the callback returns false
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toEqual('some error');
expect(cb.calls.count()).toEqual(1);
var receivedResource = cb.calls.argsFor(0)[0];
expect(receivedResource.url).toEqual(resource.url);
expect(receivedResource._retryCount).toEqual(1);
expect(cb.calls.argsFor(0)[1]).toEqual('some error');
});
it('resolves after retry', function() {
var cb = jasmine.createSpy('retry').and.returnValue(true);
var lastDeferred;
var lastUrl;
spyOn(Resource._Implementations, 'loadAndExecuteScript').and.callFake(function(url, functionName, deferred) {
lastUrl = url;
lastDeferred = deferred;
});
var resource = new Resource({
url: 'http://example.invalid',
retryCallback: cb,
retryAttempts: 1
});
var promise = resource.fetchJsonp();
expect(promise).toBeDefined();
var resolvedValue;
var rejectedError;
promise.then(function(value) {
resolvedValue = value;
}).otherwise(function(error) {
rejectedError = error;
});
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
lastDeferred.reject('some error'); // This should retry
expect(resolvedValue).toBeUndefined();
expect(rejectedError).toBeUndefined();
expect(cb.calls.count()).toEqual(1);
var receivedResource = cb.calls.argsFor(0)[0];
expect(receivedResource.url).toEqual(resource.url);
expect(receivedResource._retryCount).toEqual(1);
expect(cb.calls.argsFor(0)[1]).toEqual('some error');
var uri = new Uri(lastUrl);
var query = queryToObject(uri.query);
window[query.callback]('something good');
expect(resolvedValue).toEqual('something good');
expect(rejectedError).toBeUndefined();
});
});
});
});