ares-ide
Version:
A browser-based code editor and UI designer for Enyo 2 projects
739 lines (593 loc) • 26 kB
text/coffeescript
describe 'Dropbox.Xhr', ->
beforeEach ->
@node_js = module? and module?.exports? and require?
@oauth = new Dropbox.Oauth testKeys
describe 'with a GET', ->
beforeEach ->
@xhr = new Dropbox.Xhr 'GET', 'https://request.url'
it 'initializes correctly', ->
expect(@xhr.isGet).to.equal true
expect(@xhr.method).to.equal 'GET'
expect(@xhr.url).to.equal 'https://request.url'
expect(@xhr.preflight).to.equal false
describe '#setHeader', ->
beforeEach ->
@xhr.setHeader 'Range', 'bytes=0-1000'
it 'adds a HTTP header header', ->
expect(@xhr.headers).to.have.property 'Range'
expect(@xhr.headers['Range']).to.equal 'bytes=0-1000'
it 'does not work twice for the same header', ->
expect(=> @xhr.setHeader('Range', 'bytes=0-1000')).to.throw Error
it 'flags the Xhr as needing preflight', ->
expect(@xhr.preflight).to.equal true
it 'rejects Content-Type', ->
expect(=> @xhr.setHeader('Content-Type', 'text/plain')).to.throw Error
describe '#setParams', ->
beforeEach ->
@xhr.setParams 'param 1': true, 'answer': 42
it 'does not flag the XHR as needing preflight', ->
expect(@xhr.preflight).to.equal false
it 'does not work twice', ->
expect(=> @xhr.setParams 'answer': 43).to.throw Error
describe '#paramsToUrl', ->
beforeEach ->
@xhr.paramsToUrl()
it 'changes the url', ->
expect(@xhr.url).to.
equal 'https://request.url?answer=42¶m%201=true'
it 'sets params to null', ->
expect(@xhr.params).to.equal null
describe '#paramsToBody', ->
it 'throws an error', ->
expect(=> @xhr.paramsToBody()).to.throw Error
describe '#addOauthParams', ->
beforeEach ->
@xhr.addOauthParams @oauth
it 'keeps existing params', ->
expect(@xhr.params).to.have.property 'answer'
expect(@xhr.params.answer).to.equal 42
it 'adds an oauth_signature param', ->
expect(@xhr.params).to.have.property 'oauth_signature'
it 'does not add an Authorization header', ->
expect(@xhr.headers).not.to.have.property 'Authorization'
it 'does not work twice', ->
expect(=> @xhr.addOauthParams()).to.throw Error
describe '#addOauthHeader', ->
beforeEach ->
@xhr.addOauthHeader @oauth
it 'keeps existing params', ->
expect(@xhr.params).to.have.property 'answer'
expect(@xhr.params.answer).to.equal 42
it 'does not add an oauth_signature param', ->
expect(@xhr.params).not.to.have.property 'oauth_signature'
it 'adds an Authorization header', ->
expect(@xhr.headers).to.have.property 'Authorization'
describe '#addOauthParams without params', ->
beforeEach ->
@xhr.addOauthParams @oauth
it 'adds an oauth_signature param', ->
expect(@xhr.params).to.have.property 'oauth_signature'
describe '#addOauthHeader without params', ->
beforeEach ->
@xhr.addOauthHeader @oauth
it 'adds an Authorization header', ->
expect(@xhr.headers).to.have.property 'Authorization'
describe '#signWithOauth', ->
describe 'for a request that does not need preflight', ->
beforeEach ->
@xhr.signWithOauth @oauth
if Dropbox.Xhr.doesPreflight
it 'uses addOauthParams', ->
expect(@xhr.params).to.have.property 'oauth_signature'
else
it 'uses addOauthHeader in node.js', ->
expect(@xhr.headers).to.have.property 'Authorization'
describe 'for a request that needs preflight', ->
beforeEach ->
@xhr.setHeader 'Range', 'bytes=0-1000'
@xhr.signWithOauth @oauth
if Dropbox.Xhr.ieXdr # IE's XDR doesn't do HTTP headers.
it 'uses addOauthParams in IE', ->
expect(@xhr.params).to.have.property 'oauth_signature'
else
it 'uses addOauthHeader', ->
expect(@xhr.headers).to.have.property 'Authorization'
describe 'with cacheFriendly: true', ->
describe 'for a request that does not need preflight', ->
beforeEach ->
@xhr.signWithOauth @oauth, true
if Dropbox.Xhr.ieXdr
it 'uses addOauthParams in IE', ->
expect(@xhr.params).to.have.property 'oauth_signature'
else
it 'uses addOauthHeader', ->
expect(@xhr.headers).to.have.property 'Authorization'
describe 'for a request that needs preflight', ->
beforeEach ->
@xhr.setHeader 'Range', 'bytes=0-1000'
@xhr.signWithOauth @oauth, true
if Dropbox.Xhr.ieXdr # IE's XDR doesn't do HTTP headers.
it 'uses addOauthParams in IE', ->
expect(@xhr.params).to.have.property 'oauth_signature'
else
it 'uses addOauthHeader', ->
expect(@xhr.headers).to.have.property 'Authorization'
describe '#setFileField', ->
it 'throws an error', ->
expect(=> @xhr.setFileField('file', 'filename.bin', '<p>File Data</p>',
'text/html')).to.throw Error
describe '#setBody', ->
it 'throws an error', ->
expect(=> @xhr.setBody('body data')).to.throw Error
it 'does not flag the XHR as needing preflight', ->
expect(@xhr.preflight).to.equal false
describe '#setResponseType', ->
beforeEach ->
@xhr.setResponseType 'b'
it 'changes responseType', ->
expect(@xhr.responseType).to.equal 'b'
it 'does not flag the XHR as needing preflight', ->
expect(@xhr.preflight).to.equal false
describe '#prepare with params', ->
beforeEach ->
@xhr.setParams answer: 42
@xhr.prepare()
it 'creates the native xhr', ->
expect(typeof @xhr.xhr).to.equal 'object'
it 'opens the native xhr', ->
return if Dropbox.Xhr.ieXdr # IE's XDR doesn't do readyState.
expect(@xhr.xhr.readyState).to.equal 1
it 'pushes the params in the url', ->
expect(@xhr.url).to.equal 'https://request.url?answer=42'
describe 'with a POST', ->
beforeEach ->
@xhr = new Dropbox.Xhr 'POST', 'https://request.url'
it 'initializes correctly', ->
expect(@xhr.isGet).to.equal false
expect(@xhr.method).to.equal 'POST'
expect(@xhr.url).to.equal 'https://request.url'
expect(@xhr.preflight).to.equal false
describe '#setHeader', ->
beforeEach ->
@xhr.setHeader 'Range', 'bytes=0-1000'
it 'adds a HTTP header header', ->
expect(@xhr.headers).to.have.property 'Range'
expect(@xhr.headers['Range']).to.equal 'bytes=0-1000'
it 'does not work twice for the same header', ->
expect(=> @xhr.setHeader('Range', 'bytes=0-1000')).to.throw Error
it 'flags the Xhr as needing preflight', ->
expect(@xhr.preflight).to.equal true
it 'rejects Content-Type', ->
expect(=> @xhr.setHeader('Content-Type', 'text/plain')).to.throw Error
describe '#setParams', ->
beforeEach ->
@xhr.setParams 'param 1': true, 'answer': 42
it 'does not work twice', ->
expect(=> @xhr.setParams 'answer': 43).to.throw Error
it 'does not flag the XHR as needing preflight', ->
expect(@xhr.preflight).to.equal false
describe '#paramsToUrl', ->
beforeEach ->
@xhr.paramsToUrl()
it 'changes the url', ->
expect(@xhr.url).to.
equal 'https://request.url?answer=42¶m%201=true'
it 'sets params to null', ->
expect(@xhr.params).to.equal null
it 'does not set the body', ->
expect(@xhr.body).to.equal null
describe '#paramsToBody', ->
beforeEach ->
@xhr.paramsToBody()
it 'url-encodes the params', ->
expect(@xhr.body).to.equal 'answer=42¶m%201=true'
it 'sets the Content-Type header', ->
expect(@xhr.headers).to.have.property 'Content-Type'
expect(@xhr.headers['Content-Type']).to.
equal 'application/x-www-form-urlencoded'
it 'does not change the url', ->
expect(@xhr.url).to.equal 'https://request.url'
it 'does not work twice', ->
@xhr.setParams answer: 43
expect(=> @xhr.paramsToBody()).to.throw Error
describe '#addOauthParams', ->
beforeEach ->
@xhr.addOauthParams @oauth
it 'keeps existing params', ->
expect(@xhr.params).to.have.property 'answer'
expect(@xhr.params.answer).to.equal 42
it 'adds an oauth_signature param', ->
expect(@xhr.params).to.have.property 'oauth_signature'
it 'does not add an Authorization header', ->
expect(@xhr.headers).not.to.have.property 'Authorization'
it 'does not work twice', ->
expect(=> @xhr.addOauthParams()).to.throw Error
describe '#addOauthHeader', ->
beforeEach ->
@xhr.addOauthHeader @oauth
it 'keeps existing params', ->
expect(@xhr.params).to.have.property 'answer'
expect(@xhr.params.answer).to.equal 42
it 'does not add an oauth_signature param', ->
expect(@xhr.params).not.to.have.property 'oauth_signature'
it 'adds an Authorization header', ->
expect(@xhr.headers).to.have.property 'Authorization'
describe '#addOauthParams without params', ->
beforeEach ->
@xhr.addOauthParams @oauth
it 'adds an oauth_signature param', ->
expect(@xhr.params).to.have.property 'oauth_signature'
describe '#addOauthHeader without params', ->
beforeEach ->
@xhr.addOauthHeader @oauth
it 'adds an Authorization header', ->
expect(@xhr.headers).to.have.property 'Authorization'
describe '#signWithOauth', ->
describe 'for a request that does not need preflight', ->
beforeEach ->
@xhr.signWithOauth @oauth
if Dropbox.Xhr.doesPreflight
it 'uses addOauthParams', ->
expect(@xhr.params).to.have.property 'oauth_signature'
else
it 'uses addOauthHeader in node.js', ->
expect(@xhr.headers).to.have.property 'Authorization'
describe 'for a request that needs preflight', ->
beforeEach ->
@xhr.setHeader 'Range', 'bytes=0-1000'
@xhr.signWithOauth @oauth
if Dropbox.Xhr.ieXdr # IE's XDR doesn't do HTTP headers.
it 'uses addOauthParams in IE', ->
expect(@xhr.params).to.have.property 'oauth_signature'
else
it 'uses addOauthHeader', ->
expect(@xhr.headers).to.have.property 'Authorization'
describe 'with cacheFriendly: true', ->
describe 'for a request that does not need preflight', ->
beforeEach ->
@xhr.signWithOauth @oauth, true
if Dropbox.Xhr.doesPreflight
it 'uses addOauthParams', ->
expect(@xhr.params).to.have.property 'oauth_signature'
else
it 'uses addOauthHeader in node.js', ->
expect(@xhr.headers).to.have.property 'Authorization'
describe 'for a request that needs preflight', ->
beforeEach ->
@xhr.setHeader 'Range', 'bytes=0-1000'
@xhr.signWithOauth @oauth, true
if Dropbox.Xhr.ieXdr # IE's XDR doesn't do HTTP headers.
it 'uses addOauthParams in IE', ->
expect(@xhr.params).to.have.property 'oauth_signature'
else
it 'uses addOauthHeader', ->
expect(@xhr.headers).to.have.property 'Authorization'
describe '#setFileField with a String', ->
beforeEach ->
@nonceStub = sinon.stub @xhr, 'multipartBoundary'
@nonceStub.returns 'multipart----boundary'
@xhr.setFileField 'file', 'filename.bin', '<p>File Data</p>',
'text/html'
afterEach ->
@nonceStub.restore()
it 'sets the Content-Type header', ->
expect(@xhr.headers).to.have.property 'Content-Type'
expect(@xhr.headers['Content-Type']).to.
equal 'multipart/form-data; boundary=multipart----boundary'
it 'sets the body', ->
expect(@xhr.body).to.equal("""--multipart----boundary\r
Content-Disposition: form-data; name="file"; filename="filename.bin"\r
Content-Type: text/html\r
Content-Transfer-Encoding: binary\r
\r
<p>File Data</p>\r
--multipart----boundary--\r\n
""")
it 'does not work twice', ->
expect(=> @xhr.setFileField('file', 'filename.bin', '<p>File Data</p>',
'text/html')).to.throw Error
it 'does not flag the XHR as needing preflight', ->
expect(@xhr.preflight).to.equal false
describe '#setBody with a string', ->
beforeEach ->
@xhr.setBody 'body data'
it 'sets the request body', ->
expect(@xhr.body).to.equal 'body data'
it 'does not work twice', ->
expect(=> @xhr.setBody('body data')).to.throw Error
it 'does not flag the XHR as needing preflight', ->
expect(@xhr.preflight).to.equal false
describe '#setBody with FormData', ->
beforeEach ->
if FormData?
formData = new FormData()
formData.append 'name', 'value'
@xhr.setBody formData
it 'does not flag the XHR as needing preflight', ->
return unless FormData?
expect(@xhr.preflight).to.equal false
describe '#setBody with Blob', ->
beforeEach ->
if Blob?
try
blob = new Blob ["abcdef"], type: 'image/png'
catch blobError
builder = new WebKitBlobBuilder
builder.append "abcdef"
blob = builder.getBlob 'image/png'
@xhr.setBody blob
it 'flags the XHR as needing preflight', ->
return unless Blob?
expect(@xhr.preflight).to.equal true
it 'sets the Content-Type header', ->
return unless Blob?
expect(@xhr.headers).to.have.property 'Content-Type'
expect(@xhr.headers['Content-Type']).to.
equal 'application/octet-stream'
describe '#setBody with ArrayBuffer', ->
beforeEach ->
if ArrayBuffer?
buffer = new ArrayBuffer 5
@xhr.setBody buffer
it 'flags the XHR as needing preflight', ->
return unless ArrayBuffer?
expect(@xhr.preflight).to.equal true
it 'sets the Content-Type header', ->
return unless ArrayBuffer?
expect(@xhr.headers).to.have.property 'Content-Type'
expect(@xhr.headers['Content-Type']).to.
equal 'application/octet-stream'
describe '#setBody with ArrayBufferView', ->
beforeEach ->
if Uint8Array?
view = new Uint8Array 5
@xhr.setBody view
it 'flags the XHR as needing preflight', ->
return unless Uint8Array?
expect(@xhr.preflight).to.equal true
it 'sets the Content-Type header', ->
return unless Uint8Array?
expect(@xhr.headers).to.have.property 'Content-Type'
expect(@xhr.headers['Content-Type']).to.
equal 'application/octet-stream'
describe '#setBody with node.js Buffer', ->
beforeEach ->
if Buffer?
@xhr.setBody new Buffer(5)
it 'flags the XHR as needing preflight', ->
return unless Buffer?
expect(@xhr.preflight).to.equal true
it 'sets the Content-Type header', ->
return unless Buffer?
expect(@xhr.headers).to.have.property 'Content-Type'
expect(@xhr.headers['Content-Type']).to.
equal 'application/octet-stream'
describe '#setResponseType', ->
beforeEach ->
@xhr.setResponseType 'b'
it 'changes responseType', ->
expect(@xhr.responseType).to.equal 'b'
it 'does not flag the XHR as needing preflight', ->
expect(@xhr.preflight).to.equal false
describe '#prepare with params', ->
beforeEach ->
@xhr.setParams answer: 42
@xhr.prepare()
it 'creates the native xhr', ->
expect(typeof @xhr.xhr).to.equal 'object'
it 'opens the native xhr', ->
return if Dropbox.Xhr.ieXdr # IE's XDR doesn't do readyState.
expect(@xhr.xhr.readyState).to.equal 1
if Dropbox.Xhr.ieXdr
it 'keeps the params in the URL in IE', ->
expect(@xhr.url).to.equal 'https://request.url?answer=42'
expect(@xhr.body).to.equal null
else
it 'pushes the params in the body', ->
expect(@xhr.body).to.equal 'answer=42'
describe 'with a PUT', ->
beforeEach ->
@xhr = new Dropbox.Xhr 'PUT', 'https://request.url'
it 'initializes correctly', ->
expect(@xhr.isGet).to.equal false
expect(@xhr.method).to.equal 'PUT'
expect(@xhr.url).to.equal 'https://request.url'
expect(@xhr.preflight).to.equal true
describe '#send', ->
it 'reports errors correctly', (done) ->
@url = 'https://api.dropbox.com/1/oauth/request_token'
@xhr = new Dropbox.Xhr 'POST', @url
@xhr.prepare().send (error, data) =>
expect(data).to.equal undefined
expect(error).to.be.instanceOf Dropbox.ApiError
expect(error).to.have.property 'url'
expect(error.url).to.equal @url
expect(error).to.have.property 'method'
expect(error.method).to.equal 'POST'
unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do HTTP status codes.
expect(error).to.have.property 'status'
expect(error.status).to.equal Dropbox.ApiError.INVALID_TOKEN
expect(error).to.have.property 'responseText'
expect(error.responseText).to.be.a 'string'
unless Dropbox.Xhr.ieXdr # IE's XDR hides the HTTP body on error.
expect(error).to.have.property 'response'
expect(error.response).to.be.an 'object'
expect(error.toString()).to.match /^Dropbox API error/
expect(error.toString()).to.contain 'POST'
expect(error.toString()).to.contain @url
done()
it 'reports errors correctly when onError is set', (done) ->
@url = 'https://api.dropbox.com/1/oauth/request_token'
@xhr = new Dropbox.Xhr 'POST', @url
listenerError = null
xhrCallbackCalled = false
@xhr.onError = (error, callback) ->
expect(listenerError).to.equal null
expect(xhrCallbackCalled).to.equal false
listenerError = error
callback error
@xhr.prepare().send (error, data) =>
xhrCallbackCalled = true
expect(data).to.equal undefined
expect(error).to.be.instanceOf Dropbox.ApiError
expect(error).to.have.property 'url'
expect(error.url).to.equal @url
expect(error).to.have.property 'method'
expect(error.method).to.equal 'POST'
expect(listenerError).to.equal error
done()
it 'reports network errors correctly', (done) ->
@url = 'https://broken.to.causeanetworkerror.com/1/oauth/request_token'
@xhr = new Dropbox.Xhr 'POST', @url
@xhr.prepare().send (error, data) =>
expect(data).to.equal undefined
expect(error).to.be.instanceOf Dropbox.ApiError
expect(error).to.have.property 'url'
expect(error.url).to.equal @url
expect(error).to.have.property 'method'
expect(error.method).to.equal 'POST'
expect(error).to.have.property 'responseText'
expect(error.responseText).to.equal '(no response)'
unless Dropbox.Xhr.ieXdr # IE's XDR doesn't do HTTP status codes.
expect(error).to.have.property 'status'
expect(error.status).to.equal Dropbox.ApiError.NETWORK_ERROR
done()
it 'processes data correctly', (done) ->
xhr = new Dropbox.Xhr 'POST',
'https://api.dropbox.com/1/oauth/request_token',
xhr.addOauthParams @oauth
xhr.prepare().send (error, data) ->
expect(error).to.not.be.ok
expect(data).to.have.property 'oauth_token'
expect(data).to.have.property 'oauth_token_secret'
done()
it 'processes data correctly when using setCallback', (done) ->
xhr = new Dropbox.Xhr 'POST',
'https://api.dropbox.com/1/oauth/request_token',
xhr.addOauthParams @oauth
xhr.setCallback (error, data) ->
expect(error).to.not.be.ok
expect(data).to.have.property 'oauth_token'
expect(data).to.have.property 'oauth_token_secret'
done()
xhr.prepare().send()
it 'processes data and headers correctly', (done) ->
xhr = new Dropbox.Xhr 'POST',
'https://api.dropbox.com/1/oauth/request_token',
xhr.addOauthParams @oauth
xhr.reportResponseHeaders()
xhr.prepare().send (error, data, metadata, headers) ->
expect(error).to.not.be.ok
expect(data).to.have.property 'oauth_token'
expect(data).to.have.property 'oauth_token_secret'
expect(headers).to.have.property 'content-type'
expect(headers['content-type']).to.
equal 'application/x-www-form-urlencoded'
done()
it 'sends Authorize headers correctly', (done) ->
return done() if Dropbox.Xhr.ieXdr # IE's XDR doesn't set headers.
xhr = new Dropbox.Xhr 'POST',
'https://api.dropbox.com/1/oauth/request_token',
xhr.addOauthHeader @oauth
xhr.prepare().send (error, data) ->
expect(error).to.equal null
expect(data).to.have.property 'oauth_token'
expect(data).to.have.property 'oauth_token_secret'
done()
describe 'with a binary response', ->
beforeEach ->
testImageServerOn()
@xhr = new Dropbox.Xhr 'GET', testImageUrl
afterEach ->
testImageServerOff()
describe 'with responseType b', ->
beforeEach ->
@xhr.setResponseType 'b'
it 'retrieves a string where each character is a byte', (done) ->
@xhr.prepare().send (error, data) ->
expect(error).to.not.be.ok
expect(data).to.be.a 'string'
bytes = (data.charCodeAt i for i in [0...data.length])
expect(bytes).to.deep.equal testImageBytes
done()
describe 'with responseType arraybuffer', ->
beforeEach ->
@xhr.setResponseType 'arraybuffer'
it 'retrieves a well-formed ArrayBuffer', (done) ->
# Skip this test on node.js and IE 9 and below
return done() unless ArrayBuffer?
@xhr.prepare().send (error, buffer) ->
expect(error).to.not.be.ok
expect(buffer).to.be.instanceOf ArrayBuffer
view = new Uint8Array buffer
bytes = (view[i] for i in [0...buffer.byteLength])
expect(bytes).to.deep.equal testImageBytes
done()
describe 'with responseType blob', ->
beforeEach ->
@xhr.setResponseType 'blob'
it 'retrieves a well-formed Blob', (done) ->
# Skip this test on node.js and IE 9 and below
return done() unless Blob?
@xhr.prepare().send (error, blob) ->
expect(error).to.not.be.ok
expect(blob).to.be.instanceOf Blob
onBufferAvailable = (buffer) ->
view = new Uint8Array buffer
bytes = (view[i] for i in [0...buffer.byteLength])
expect(bytes).to.deep.equal testImageBytes
done()
if typeof FileReaderSync isnt 'undefined'
# Firefox WebWorkers don't have FileReader.
reader = new FileReaderSync
buffer = reader.readAsArrayBuffer blob
onBufferAvailable buffer
else
reader = new FileReader
reader.onloadend = ->
return unless reader.readyState == FileReader.DONE
onBufferAvailable reader.result
reader.readAsArrayBuffer blob
describe 'with responseType buffer', ->
beforeEach ->
if Buffer?
@xhr.setResponseType 'buffer'
it 'retrieves a well-formed Buffer on node.js', (done) ->
return done() unless Buffer?
@xhr.prepare().send (error, buffer) ->
expect(error).to.not.be.ok
expect(buffer).to.be.instanceOf Buffer
bytes = (buffer.readUInt8(i) for i in [0...buffer.length])
expect(bytes).to.deep.equal testImageBytes
done()
describe '#urlEncode', ->
it 'iterates properly', ->
expect(Dropbox.Xhr.urlEncode({foo: 'bar', baz: 5})).to.
equal 'baz=5&foo=bar'
it 'percent-encodes properly', ->
expect(Dropbox.Xhr.urlEncode({'a +x()': "*b'"})).to.
equal 'a%20%2Bx%28%29=%2Ab%27'
describe '#urlDecode', ->
it 'iterates properly', ->
decoded = Dropbox.Xhr.urlDecode('baz=5&foo=bar')
expect(decoded['baz']).to.equal '5'
expect(decoded['foo']).to.equal 'bar'
it 'percent-decodes properly', ->
decoded = Dropbox.Xhr.urlDecode('a%20%2Bx%28%29=%2Ab%27')
expect(decoded['a +x()']).to.equal "*b'"
describe '#parseResponseHeaders', ->
it 'parses one header correctly', ->
headers = "Content-Type: 35225"
decoded = Dropbox.Xhr.parseResponseHeaders headers
expect(decoded).to.deep.equal 'content-type': '35225'
it 'parses multiple headers correctly', ->
headers =
"""
Content-Type: 35225
s : t
diffic ULT: Random: value: with: colons
"""
decoded = Dropbox.Xhr.parseResponseHeaders headers
expect(decoded).to.deep.equal(
'content-type': '35225', 's': 't',
'diffic ult': 'Random: value: with: colons')