nebulab-dropbox
Version:
Client library for the Dropbox API
344 lines (293 loc) • 13.8 kB
text/coffeescript
describe 'Dropbox.Client', ->
beforeEach ->
= new Dropbox.Client
key: 'mock00key',
token: 'mock00token',
uid: 3141592,
server: 'https://api$.no-calls-in-fasttests.com'
describe 'with custom API server URLs', ->
it 'computes the other URLs correctly', ->
client = new Dropbox.Client
key: 'mock00key',
server: 'https://api$.sandbox.dropbox-proxy.com'
expect(client._serverRoot).to.equal(
'https://api$.sandbox.dropbox-proxy.com')
expect(client._apiServer).to.match(
/^https:\/\/api\d*\.sandbox\.dropbox-proxy\.com$/)
expect(client._authServer).to.equal(
'https://www.sandbox.dropbox-proxy.com')
expect(client._fileServer).to.equal(
'https://api-content.sandbox.dropbox-proxy.com')
expect(client._notifyServer).to.equal(
'https://api-notify.sandbox.dropbox-proxy.com')
expect(client._downloadServer).to.equal(
'https://dl.dropboxusercontent.com')
describe '#_normalizePath', ->
it "doesn't touch relative paths", ->
expect(._normalizePath('aa/b/cc/dd')).to.equal 'aa/b/cc/dd'
it 'removes the leading / from absolute paths', ->
expect(._normalizePath('/aaa/b/cc/dd')).to.equal 'aaa/b/cc/dd'
it 'removes multiple leading /s from absolute paths', ->
expect(._normalizePath('///aa/b/ccc/dd')).to.equal 'aa/b/ccc/dd'
describe '#_urlEncodePath', ->
it 'encodes each segment separately', ->
expect(._urlEncodePath('a b+c/d?e"f/g&h')).to.
equal "a%20b%2Bc/d%3Fe%22f/g%26h"
it 'normalizes paths', ->
expect(._urlEncodePath('///a b+c/g&h')).to.
equal "a%20b%2Bc/g%26h"
describe '#dropboxUid', ->
it 'matches the uid in the credentials', ->
expect(.dropboxUid()).to.equal 3141592
describe '#reset', ->
beforeEach ->
= []
.onAuthStepChange.addListener (client) =>
.push client.authStep
.reset()
it 'gets the client into the RESET state', ->
expect(.authStep).to.equal Dropbox.Client.RESET
it 'removes token and uid information', ->
credentials = .credentials()
expect(credentials).not.to.have.property 'token'
expect(credentials).not.to.have.property 'uid'
it 'triggers onAuthStepChange', ->
expect().to.deep.equal [Dropbox.Client.RESET]
it 'does not trigger onAuthStep if already reset', ->
.length = 0
.reset()
expect().to.deep.equal []
describe '#credentials', ->
it 'contains all the expected keys when DONE', ->
credentials = .credentials()
expect(credentials).to.have.property 'key'
expect(credentials).to.have.property 'token'
expect(credentials).to.have.property 'uid'
it 'contains all the expected keys when RESET', ->
.reset()
credentials = .credentials()
expect(credentials).to.have.property 'key'
describe 'for a client with raw keys', ->
beforeEach ->
.setCredentials(
key: 'dpf43f3p2l4k3l03', secret: 'kd94hf93k423kf44',
token: 'user-token', uid: '1234567')
it 'contains all the expected keys when DONE', ->
credentials = .credentials()
expect(credentials).to.have.property 'key'
expect(credentials).to.have.property 'secret'
expect(credentials).to.have.property 'token'
expect(credentials).to.have.property 'uid'
it 'contains all the expected keys when RESET', ->
.reset()
credentials = .credentials()
expect(credentials).to.have.property 'key'
expect(credentials).to.have.property 'secret'
describe 'for a client with custom servers', ->
beforeEach ->
= new Dropbox.Client(
key: 'mock00key',
server: 'https://api$.sandbox.dropbox-proxy.com',
downloadServer: 'https://dlserver.sandbox.dropbox-proxy.com')
it 'contains the custom servers', ->
credentials = .credentials()
expect(credentials).to.have.property 'server'
expect(credentials.server).to.equal(
'https://api$.sandbox.dropbox-proxy.com')
expect(credentials).to.have.property 'downloadServer'
expect(credentials.downloadServer).to.equal(
'https://dlserver.sandbox.dropbox-proxy.com')
describe '#setCredentials', ->
it 'gets the client into the RESET state', ->
.setCredentials key: 'app-key', secret: 'app-secret'
expect(.authStep).to.equal Dropbox.Client.RESET
credentials = .credentials()
expect(credentials.key).to.equal 'app-key'
expect(credentials.secret).to.equal 'app-secret'
it 'gets the client into the DONE state', ->
.setCredentials(
key: 'app-key', secret: 'app-secret', token: 'user-token',
uid: '3141592')
expect(.authStep).to.equal Dropbox.Client.DONE
credentials = .credentials()
expect(credentials.key).to.equal 'app-key'
expect(credentials.secret).to.equal 'app-secret'
expect(credentials.token).to.equal 'user-token'
expect(credentials.uid).to.equal '3141592'
beforeEach ->
= []
.onAuthStepChange.addListener (client) =>
.push client.authStep
it 'triggers onAuthStepChange when switching from DONE to RESET', ->
.setCredentials key: 'app-key', secret: 'app-secret'
expect().to.deep.equal [Dropbox.Client.RESET]
it 'does not trigger onAuthStepChange when not switching', ->
.setCredentials key: 'app-key', secret: 'app-secret'
.length = 0
.setCredentials key: 'app-key', secret: 'app-secret'
expect().to.deep.equal []
describe '#authenticate', ->
describe 'without an OAuth driver', ->
beforeEach ->
= Dropbox.AuthDriver.autoConfigure
=
authType: -> 'token'
url: -> 'http://stub.url/'
Dropbox.AuthDriver.autoConfigure = (client) =>
client.authDriver
afterEach ->
Dropbox.AuthDriver.autoConfigure =
it 'calls autoConfigure when no OAuth driver is supplied', (done) ->
.reset()
.authDriver null
.doAuthorize = (authUrl, stateParam, client) =>
expect(client).to.equal
done()
.authenticate null
it 'raises an exception when AuthDriver.autoConfigure fails in RESET', ->
.reset()
expect(.authStep).to.equal Dropbox.Client.RESET
.authDriver null
= null
expect(=> .authenticate null).to.
throw Error, /auto-configuration failed/i
it 'raises an exception when autoConfigure fails in AUTHORIZED', ->
.setCredentials(
key: 'app-key', secret: 'app-secret', oauthCode: 'auth-code')
expect(.authStep).to.equal Dropbox.Client.AUTHORIZED
.authDriver null
= null
expect(=> .authenticate null).to.
throw Error, /auto-configuration failed/i
it 'completes without an OAuth driver if already in DONE', (done) ->
.authDriver null
.authenticate (error, client) =>
expect(error).to.equal null
expect(client).to.equal
done()
it 'complains if called when the client is in ERROR', ->
.authDriver doAuthorize: ->
assert false, 'The OAuth driver should not be invoked'
.authStep = Dropbox.Client.ERROR
expect(=> .authenticate null).to.throw Error, /error.*reset/i
describe 'with interactive: false', ->
beforeEach ->
=
doAuthorize: ->
assert false, 'The OAuth driver should not be invoked'
url: ->
'https://localhost:8912/oauth_redirect'
.authDriver
it 'stops at RESET with interactive: false', (done) ->
.reset()
.authenticate interactive: false, (error, client) ->
expect(error).to.equal null
expect(client.authStep).to.equal Dropbox.Client.RESET
done()
it 'stops at PARAM_SET with interactive: false', (done) ->
.reset()
._oauth.setAuthStateParam 'state_should_not_be_used'
.authStep = ._oauth.step()
expect(.authStep).to.equal Dropbox.Client.PARAM_SET
.authenticate interactive: false, (error, client) ->
expect(error).to.equal null
expect(client.authStep).to.equal Dropbox.Client.PARAM_SET
done()
it 'proceeds from PARAM_LOADED with interactive: false', (done) ->
.reset()
credentials = .credentials()
credentials.oauthStateParam = 'state_should_not_be_used'
.setCredentials credentials
expect(.authStep).to.equal Dropbox.Client.PARAM_LOADED
.authenticate interactive: false, (error, client) ->
expect(error).to.equal null
expect(client.authStep).to.equal Dropbox.Client.PARAM_SET
done()
it 'calls resumeAuthorize from PARAM_LOADED when defined', (done) ->
.resumeAuthorize = (stateParam, client, callback) ->
expect(stateParam).to.equal 'state_should_not_be_used'
expect(client.authStep).to.equal Dropbox.Client.PARAM_LOADED
done()
.reset()
credentials = .credentials()
credentials.oauthStateParam = 'state_should_not_be_used'
.setCredentials credentials
expect(.authStep).to.equal Dropbox.Client.PARAM_LOADED
.authenticate (error, client) ->
expect('callback_should_not_be_called').to.equal false
done()
describe '#signOut', ->
describe 'without a token', ->
beforeEach ->
.reset()
it 'throws an exception', ->
expect(=> .signOut()).to.throw(Error, /client.*user.*token/i)
describe 'with mustInvalidate', ->
beforeEach ->
.reset()
.setCredentials token: 'fake-token'
= []
.authDriver onAuthStepChange: (client, callback) =>
.push client.authStep
callback()
= { status: 0 }
._dispatchXhr = (xhr, callback) =>
callback new Dropbox.ApiError(, 'POST', 'url')
describe 'unset', ->
it 'ignores API server errors', (done) ->
.signOff (error) =>
expect(error).to.equal null
expect().to.deep.equal(
[Dropbox.Client.SIGNED_OUT])
expect(.isAuthenticated()).to.equal false
done()
describe 'set to true', ->
it 'aborts on API server errors', (done) ->
.signOut mustInvalidate: true, (error) =>
expect(error).to.be.instanceOf Dropbox.ApiError
expect(error.status).to.equal 0
expect(.length).to.equal 0
expect(.isAuthenticated()).to.equal true
done()
it 'succeeds if the API server says the token is invalid', (done) ->
.status = Dropbox.ApiError.INVALID_TOKEN
.signOff mustInvalidate: true, (error) =>
expect(error).to.equal null
expect().to.deep.equal(
[Dropbox.Client.SIGNED_OUT])
expect(.isAuthenticated()).to.equal false
done()
describe '#constructor', ->
it 'works with an access token and no API key', ->
client = new Dropbox.Client token: '123'
expect(client.authStep).to.equal Dropbox.Client.DONE
it 'works with an API key', ->
client = new Dropbox.Client key: 'key'
expect(client.authStep).to.equal Dropbox.Client.RESET
it 'throws an exception if initialized without an API key or token', ->
expect(-> new Dropbox.Client({})).to.throw(Error, /no api key/i)
describe '#_chooseApiServer', ->
describe 'with only one API server', ->
beforeEach ->
= new Dropbox.Client(
key: 'mock00key',
server: 'https://api$.dropbox.com',
maxApiServer: 0)
it 'always returns that API server', ->
for i in [1..10]
expect(._chooseApiServer()).to.equal 'https://api.dropbox.com'
describe 'with 10 API servers', ->
beforeEach ->
= new Dropbox.Client(
key: 'mock00key',
server: 'https://api$.dropbox.com',
maxApiServer: 10)
= sinon.stub Math, 'random'
afterEach ->
.restore()
it 'can return the un-numbered server', ->
.returns 0.001
expect(._chooseApiServer()).to.equal 'https://api.dropbox.com'
it 'can return the 10th numbered server', ->
.returns 0.999
expect(._chooseApiServer()).to.equal 'https://api10.dropbox.com'