You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
701 lines
16 KiB
701 lines
16 KiB
define([ |
|
'intern!object', |
|
'intern/chai!assert', |
|
'../../../request/xhr', |
|
'../../../errors/RequestTimeoutError', |
|
'../../../errors/CancelError', |
|
'dojo/promise/all', |
|
'dojo/query', |
|
'require', |
|
'../../../has' |
|
], function(registerSuite, assert, xhr, RequestTimeoutError, CancelError, all, query, require, has){ |
|
var global = this; |
|
var hasFormData = 'FormData' in this && typeof FormData === 'function'; |
|
var hasResponseType = typeof XMLHttpRequest !== 'undefined' && |
|
typeof new XMLHttpRequest().responseType !== 'undefined'; |
|
var formData; |
|
|
|
function hasFile(){ |
|
if (typeof File !== 'undefined') { |
|
try { |
|
new File(); |
|
} catch (e) { |
|
// File is not a constructor. |
|
} |
|
} |
|
return false; |
|
} |
|
|
|
registerSuite({ |
|
name: 'dojo/request/xhr', |
|
'.get': function(){ |
|
var promise = xhr.get('/__services/request/xhr', { |
|
preventCache: true, |
|
handleAs: 'json' |
|
}); |
|
|
|
assert.isFunction(promise.then); |
|
assert.isFunction(promise.cancel); |
|
assert.isObject(promise.response); |
|
assert.isFunction(promise.response.then); |
|
assert.isFunction(promise.response.cancel); |
|
|
|
return promise.response.then(function(response){ |
|
assert.strictEqual(response.data.method, 'GET'); |
|
assert.strictEqual(response.xhr.readyState, 4); |
|
return response; |
|
}); |
|
}, |
|
|
|
'.get 404': function(){ |
|
var def = this.async(), |
|
promise = xhr.get(require.toUrl('./xhr_blarg.html'), { |
|
preventCache: true |
|
}); |
|
|
|
promise.response.then( |
|
def.reject, |
|
def.callback(function(error){ |
|
assert.strictEqual(error.response.status, 404); |
|
}) |
|
); |
|
}, |
|
|
|
'.get json with truthy value': function(){ |
|
var def = this.async(), |
|
promise = xhr.get(require.toUrl('./support/truthy.json'), { |
|
preventCache: true, |
|
handleAs: 'json' |
|
}); |
|
|
|
promise.then( |
|
def.callback(function(response){ |
|
assert.strictEqual(response, true); |
|
}) |
|
); |
|
}, |
|
'.get json with falsy value': function(){ |
|
var def = this.async(), |
|
promise = xhr.get(require.toUrl('./support/falsy.json'), { |
|
preventCache: true, |
|
handleAs: 'json' |
|
}); |
|
|
|
promise.then( |
|
def.callback(function(response){ |
|
assert.strictEqual(response, false); |
|
}) |
|
); |
|
}, |
|
|
|
'.get with progress': function(){ |
|
var def = this.async(), |
|
promise = xhr.get(require.toUrl('./support/truthy.json'), { |
|
handleAs: 'json', |
|
preventCache: true |
|
}); |
|
promise.then(def.callback( |
|
function(){ |
|
}), function(error){ |
|
assert.isTrue(false, error); |
|
}, def.callback(function(event){ |
|
assert.strictEqual(event.transferType, 'download'); |
|
})); |
|
return def.promise; |
|
}, |
|
|
|
'.get with query': function(){ |
|
var def = this.async(), |
|
promise = xhr.get('/__services/request/xhr?color=blue', { |
|
query: { |
|
foo: ['bar', 'baz'], |
|
thud: 'thonk', |
|
xyzzy: 3 |
|
}, |
|
handleAs: 'json' |
|
}); |
|
|
|
promise.response.then(def.callback(function(response){ |
|
assert.strictEqual(response.data.method, 'GET'); |
|
var query = response.data.query; |
|
assert.ok(query.color && query.foo && query.foo.length && query.thud && query.xyzzy); |
|
assert.strictEqual(query.color, 'blue'); |
|
assert.strictEqual(query.foo.length, 2); |
|
assert.strictEqual(query.thud, 'thonk'); |
|
assert.strictEqual(query.xyzzy, '3'); |
|
assert.strictEqual(response.url, '/__services/request/xhr?color=blue&foo=bar&foo=baz&thud=thonk&xyzzy=3'); |
|
})); |
|
}, |
|
|
|
'.post': function(){ |
|
var def = this.async(), |
|
promise = xhr.post('/__services/request/xhr', { |
|
data: {color: 'blue'}, |
|
handleAs: 'json' |
|
}); |
|
|
|
promise.response.then( |
|
def.callback(function(response){ |
|
assert.strictEqual(response.data.method, 'POST'); |
|
var payload = response.data.payload; |
|
|
|
assert.ok(payload && payload.color); |
|
assert.strictEqual(payload.color, 'blue'); |
|
}), |
|
def.reject |
|
); |
|
}, |
|
'.post ArrayBuffer': function(){ |
|
if (has('native-arraybuffer')) { |
|
var def = this.async(), |
|
str = 'foo', |
|
arrbuff = new ArrayBuffer(str.length), |
|
i8array = new Uint8Array(arrbuff); |
|
|
|
for (var i = 0; i < str.length; i++) { |
|
i8array[i] = str.charCodeAt(i); |
|
} |
|
var promise = xhr.post('/__services/request/xhr', { |
|
data: arrbuff, |
|
handleAs: 'json', |
|
headers: { |
|
'Content-Type': 'text/plain' |
|
} |
|
}); |
|
|
|
promise.response.then( |
|
def.callback(function(response){ |
|
assert.strictEqual(response.data.method, 'POST'); |
|
var payload = response.data.payload; |
|
|
|
assert.deepEqual(payload, {'foo': ''}); |
|
}), |
|
def.reject |
|
); |
|
} else { |
|
this.skip('ArrayBuffer not available'); |
|
} |
|
}, |
|
'.post Blob': function(){ |
|
if (has('native-blob')) { |
|
var def = this.async(), |
|
str = 'foo', |
|
blob = new Blob([str], {type: 'text/plain'}); |
|
|
|
var promise = xhr.post('/__services/request/xhr', { |
|
data: blob, |
|
handleAs: 'json', |
|
headers: { |
|
'Content-Type': 'text/plain' |
|
} |
|
}); |
|
|
|
promise.response.then( |
|
def.callback(function(response){ |
|
assert.strictEqual(response.data.method, 'POST'); |
|
var payload = response.data.payload; |
|
|
|
assert.deepEqual(payload, {'foo': ''}); |
|
}), |
|
def.reject |
|
); |
|
} else { |
|
this.skip('Blob not available'); |
|
} |
|
}, |
|
'.post File': function(){ |
|
if (hasFile()) { |
|
var def = this.async(), |
|
str = 'foo', |
|
file = new File([str], 'bar.txt', {type: 'text/plain'}); |
|
|
|
var promise = xhr.post('/__services/request/xhr', { |
|
data: file, |
|
handleAs: 'json', |
|
headers: { |
|
'Content-Type': 'text/plain' |
|
} |
|
}); |
|
|
|
promise.response.then( |
|
def.callback(function(response){ |
|
assert.strictEqual(response.data.method, 'POST'); |
|
var payload = response.data.payload; |
|
|
|
assert.deepEqual(payload, {'foo': ''}); |
|
}), |
|
def.reject |
|
); |
|
} else { |
|
this.skip('File or File constructor not available'); |
|
} |
|
}, |
|
'.post File with upload progress': function(){ |
|
if (hasFile()) { |
|
var def = this.async(), |
|
str = 'foo', |
|
file = new File([str], 'bar.txt', {type: 'text/plain'}); |
|
|
|
var promise = xhr.post('/__services/request/xhr', { |
|
data: file, |
|
handleAs: 'json', |
|
uploadProgress: true, |
|
query: { |
|
simulateProgress: true |
|
}, |
|
headers: { |
|
'Content-Type': 'text/plain' |
|
} |
|
}); |
|
|
|
promise.then(null, def.reject, def.callback(function(progressEvent){ |
|
assert.isDefined(progressEvent.xhr); |
|
assert.deepEqual(progressEvent.transferType, 'upload'); |
|
})); |
|
} else { |
|
this.skip('File or File constructor not available'); |
|
} |
|
}, |
|
'.post with query': function(){ |
|
var def = this.async(), |
|
promise = xhr.post('/__services/request/xhr', { |
|
query: { |
|
foo: ['bar', 'baz'], |
|
thud: 'thonk', |
|
xyzzy: 3 |
|
}, |
|
data: {color: 'blue'}, |
|
handleAs: 'json' |
|
}); |
|
|
|
promise.then( |
|
def.callback(function(data){ |
|
assert.strictEqual(data.method, 'POST'); |
|
var query = data.query, |
|
payload = data.payload; |
|
|
|
assert.ok(query); |
|
assert.deepEqual(query.foo, ['bar', 'baz']); |
|
assert.strictEqual(query.thud, 'thonk'); |
|
assert.strictEqual(query.xyzzy, '3'); |
|
|
|
assert.ok(payload); |
|
assert.strictEqual(payload.color, 'blue'); |
|
}), |
|
def.reject |
|
); |
|
}, |
|
|
|
'.post string payload': function(){ |
|
var def = this.async(), |
|
promise = xhr.post('/__services/request/xhr', { |
|
data: 'foo=bar&color=blue&height=average', |
|
handleAs: 'json' |
|
}); |
|
|
|
promise.then( |
|
def.callback(function(data){ |
|
assert.strictEqual(data.method, 'POST'); |
|
|
|
var payload = data.payload; |
|
|
|
assert.ok(payload); |
|
assert.strictEqual(payload.foo, 'bar'); |
|
assert.strictEqual(payload.color, 'blue'); |
|
assert.strictEqual(payload.height, 'average'); |
|
}), |
|
def.reject |
|
); |
|
}, |
|
|
|
'.put': function(){ |
|
var def = this.async(), |
|
promise = xhr.put('/__services/request/xhr', { |
|
query: {foo: 'bar'}, |
|
data: {color: 'blue'}, |
|
handleAs: 'json' |
|
}); |
|
|
|
promise.then( |
|
def.callback(function(data){ |
|
assert.strictEqual(data.method, 'PUT'); |
|
|
|
assert.ok(data.payload); |
|
assert.strictEqual(data.payload.color, 'blue'); |
|
|
|
assert.ok(data.query); |
|
assert.strictEqual(data.query.foo, 'bar'); |
|
}), |
|
def.reject |
|
); |
|
}, |
|
|
|
'.del': function(){ |
|
var def = this.async(), |
|
promise = xhr.del('/__services/request/xhr', { |
|
query: {foo: 'bar'}, |
|
handleAs: 'json' |
|
}); |
|
|
|
promise.then( |
|
def.callback(function(data){ |
|
assert.strictEqual(data.method, 'DELETE'); |
|
assert.strictEqual(data.query.foo, 'bar'); |
|
}), |
|
def.reject |
|
); |
|
}, |
|
|
|
'timeout': function(){ |
|
var def = this.async(), |
|
promise = xhr.get('/__services/request/xhr', { |
|
query: { |
|
delay: '3000' |
|
}, |
|
timeout: 1000 |
|
}); |
|
|
|
promise.then( |
|
def.reject, |
|
def.callback(function(error){ |
|
assert.instanceOf(error, RequestTimeoutError); |
|
}) |
|
); |
|
}, |
|
|
|
cancel: function(){ |
|
var def = this.async(), |
|
promise = xhr.get('/__services/request/xhr', { |
|
query: { |
|
delay: '3000' |
|
} |
|
}); |
|
|
|
promise.then( |
|
def.reject, |
|
def.callback(function(error){ |
|
assert.instanceOf(error, CancelError); |
|
}) |
|
); |
|
promise.cancel(); |
|
}, |
|
|
|
sync: function(){ |
|
var called = false; |
|
|
|
xhr.get('/__services/request/xhr', { |
|
sync: true |
|
}).then(function(){ |
|
called = true; |
|
}); |
|
|
|
assert.ok(called); |
|
}, |
|
|
|
'cross-domain fails': function(){ |
|
var def = this.async(); |
|
|
|
xhr.get('http://dojotoolkit.org').response.then( |
|
def.reject, |
|
function(){ |
|
def.resolve(true); |
|
} |
|
); |
|
}, |
|
|
|
'has Content-Type with data': function(){ |
|
var def = this.async(); |
|
|
|
xhr.post('/__services/request/xhr', { |
|
data: 'testing', |
|
handleAs: 'json' |
|
}).then( |
|
def.callback(function(response){ |
|
assert.equal(response.headers['content-type'], 'application/x-www-form-urlencoded'); |
|
}), |
|
def.reject |
|
); |
|
}, |
|
|
|
'no Content-Type with no data': function(){ |
|
var def = this.async(); |
|
|
|
xhr.get('/__services/request/xhr', { |
|
handleAs: 'json' |
|
}).then( |
|
def.callback(function(response){ |
|
assert.isUndefined(response.headers['content-type']); |
|
}), |
|
def.reject |
|
); |
|
}, |
|
|
|
headers: function(){ |
|
var def = this.async(); |
|
|
|
xhr.get('/__services/request/xhr').response.then( |
|
def.callback(function(response){ |
|
assert.notEqual(response.getHeader('Content-Type'), null); |
|
}), |
|
def.reject |
|
); |
|
}, |
|
|
|
'custom Content-Type': function(){ |
|
var def = this.async(), |
|
expectedContentType = 'application/x-test-xhr'; |
|
|
|
function post(headers){ |
|
return xhr.post('/__services/request/xhr', { |
|
query: { |
|
'header-test': 'true' |
|
}, |
|
headers: headers, |
|
data: 'testing', |
|
handleAs: 'json' |
|
}); |
|
} |
|
|
|
all({ |
|
lowercase: post({ |
|
'content-type': expectedContentType |
|
}), |
|
uppercase: post({ |
|
'CONTENT-TYPE': expectedContentType |
|
}) |
|
}).then( |
|
def.callback(function(results){ |
|
assert.match( |
|
results.lowercase.headers['content-type'], |
|
/^application\/x-test-xhr(?:;.*)?$/ |
|
); |
|
assert.match( |
|
results.uppercase.headers['content-type'], |
|
/^application\/x-test-xhr(?:;.*)?$/ |
|
); |
|
}), |
|
def.reject |
|
); |
|
}, |
|
|
|
'queryable xml': function(){ |
|
var def = this.async(); |
|
|
|
xhr.get('/__services/request/xhr/xml', { |
|
handleAs: 'xml' |
|
}).then( |
|
def.callback(function(xmlDoc){ |
|
var results = query('bar', xmlDoc); |
|
|
|
assert.strictEqual(results.length, 2); |
|
}), |
|
def.reject |
|
); |
|
}, |
|
|
|
'strip fragment': function(){ |
|
var def = this.async(), |
|
promise = xhr.get('/__services/request/xhr?color=blue#some-hash', { |
|
handleAs: 'json' |
|
}); |
|
|
|
promise.response.then(def.callback(function(response){ |
|
assert.strictEqual(response.data.method, 'GET'); |
|
assert.strictEqual(response.data.url, '/__services/request/xhr?color=blue'); |
|
})); |
|
}, |
|
|
|
'form data': { |
|
setup: function(){ |
|
if (!hasFormData) { |
|
return; |
|
} |
|
|
|
formData = new FormData(); |
|
formData.append('foo', 'bar'); |
|
formData.append('baz', 'blah'); |
|
}, |
|
|
|
post: function(){ |
|
if (!hasFormData) { |
|
this.skip('No FormData to test'); |
|
} |
|
|
|
var def = this.async(); |
|
|
|
xhr.post('/__services/request/xhr/multipart', { |
|
data: formData, |
|
handleAs: 'json' |
|
}).then( |
|
def.callback(function(data){ |
|
assert.deepEqual(data, {foo: 'bar', baz: 'blah'}); |
|
}), |
|
def.reject |
|
); |
|
}, |
|
|
|
teardown: function(){ |
|
formData = null; |
|
} |
|
}, |
|
|
|
'response type': { |
|
'Blob': function(){ |
|
if (!hasResponseType) { |
|
this.skip('No responseType to test'); |
|
} |
|
|
|
return xhr.get('/__services/request/xhr/responseTypeGif', { |
|
handleAs: 'blob' |
|
}).then(function(response){ |
|
assert.strictEqual(response.constructor, Blob); |
|
}); |
|
}, |
|
|
|
'Blob POST': function(){ |
|
if (!hasResponseType) { |
|
this.skip('No responseType to test'); |
|
} |
|
|
|
return xhr.post('/__services/request/xhr/responseTypeGif', { |
|
handleAs: 'blob' |
|
}).then(function(response){ |
|
assert.strictEqual(response.constructor, Blob); |
|
}); |
|
}, |
|
|
|
'ArrayBuffer': function(){ |
|
if (has('native-arraybuffer') && hasResponseType) { |
|
return xhr.get('/__services/request/xhr/responseTypeGif', { |
|
handleAs: 'arraybuffer' |
|
}).then(function(response){ |
|
assert.strictEqual(response.constructor, ArrayBuffer); |
|
}); |
|
} else { |
|
this.skip('No responseType to test'); |
|
} |
|
}, |
|
|
|
'ArrayBuffer POST': function(){ |
|
if (has('native-arraybuffer') && hasResponseType) { |
|
return xhr.post('/__services/request/xhr/responseTypeGif', { |
|
handleAs: 'arraybuffer' |
|
}).then(function(response){ |
|
assert.strictEqual(response.constructor, ArrayBuffer); |
|
}); |
|
} else { |
|
this.skip('No responseType to test'); |
|
} |
|
}, |
|
|
|
'document': function(){ |
|
if (!hasResponseType) { |
|
this.skip('No responseType to test'); |
|
} |
|
|
|
return xhr.get('/__services/request/xhr/responseTypeDoc', { |
|
handleAs: 'document' |
|
}).then(function(response){ |
|
assert.strictEqual(response.constructor, document.constructor); |
|
}); |
|
}, |
|
|
|
'document POST': function(){ |
|
if (!hasResponseType) { |
|
this.skip('No responseType to test'); |
|
} |
|
|
|
return xhr.post('/__services/request/xhr/responseTypeDoc', { |
|
handleAs: 'document' |
|
}).then(function(response){ |
|
assert.strictEqual(response.constructor, document.constructor); |
|
}); |
|
} |
|
}, |
|
|
|
'Web Workers': { |
|
'from blob': function(){ |
|
if (!('URL' in global)) { |
|
this.skip('URL is not supported'); |
|
} |
|
|
|
if (!('Worker' in global)) { |
|
this.skip('Worker is not supported'); |
|
} |
|
|
|
if (!('Blob' in global)) { |
|
this.skip('Blob is not supported'); |
|
} |
|
|
|
if (!URL.createObjectURL) { |
|
this.skip('URL.createObjectURL is not supported'); |
|
} |
|
|
|
var dfd = this.async(); |
|
var baseUrl = location.origin + '/' + require.toUrl('testing'); |
|
var testUrl = location.origin + '/' + require.toUrl('./support/truthy.json'); |
|
|
|
var workerFunction = function(){ |
|
self.addEventListener('message', function(event){ |
|
if (event.data.baseUrl) { |
|
testXhr(event.data.baseUrl, event.data.testUrl); |
|
} |
|
}); |
|
|
|
dojoConfig = {async: true}; |
|
|
|
function testXhr(baseUrl, testUrl){ |
|
var xhr = new XMLHttpRequest(); |
|
|
|
dojoConfig.baseUrl = baseUrl; |
|
|
|
xhr.onreadystatechange = function(){ |
|
if (xhr.readyState === 4 && xhr.status === 200) { |
|
var blob = new Blob([xhr.response], {type: 'application/javascript'}); |
|
var blobURL = URL.createObjectURL(blob); |
|
|
|
importScripts(blobURL); |
|
|
|
require([ |
|
'dojo/request/xhr' |
|
], function(xhr){ |
|
xhr.get(testUrl).then(function(response){ |
|
if (response === 'true') { |
|
self.postMessage('success'); |
|
} else { |
|
throw new Error(response); |
|
} |
|
}, function(error){ |
|
throw error; |
|
}); |
|
}); |
|
} |
|
}; |
|
xhr.open('GET', baseUrl + '/dojo.js', true); |
|
xhr.send(); |
|
} |
|
}; |
|
|
|
var blob = new Blob(['(' + workerFunction.toString() + ')()'], {type: 'application/javascript'}); |
|
var worker = new Worker(URL.createObjectURL(blob)); |
|
|
|
worker.addEventListener('error', function(error){ |
|
dfd.reject(error); |
|
}); |
|
|
|
worker.addEventListener('message', function(message){ |
|
if (message.data === 'success') { |
|
dfd.resolve(); |
|
} else { |
|
dfd.reject(message); |
|
} |
|
}); |
|
|
|
worker.postMessage({ |
|
baseUrl: baseUrl, |
|
testUrl: testUrl |
|
}); |
|
} |
|
} |
|
}); |
|
});
|
|
|