PageRenderTime 126ms CodeModel.GetById 3ms app.highlight 112ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/client/storage/dropbox/test/src/client_test.coffee

https://bitbucket.org/coderaiser/cloudcmd
CoffeeScript | 1492 lines | 1294 code | 164 blank | 34 comment | 48 complexity | 56e31d39f4b077f7f3a890f03ad58074 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1buildClientTests = (clientKeys) ->
   2  # Creates the global client.
   3  setupClient = (test, done) ->
   4    # Should only be used for fixture teardown.
   5    test.__client = new Dropbox.Client clientKeys
   6    done()
   7
   8  # Creates the test directory.
   9  setupDirectory = (test, done) ->
  10    # True if running on node.js
  11    test.node_js = module? and module?.exports? and require?
  12
  13    # All test data should go here.
  14    test.testFolder = '/js tests.' + Math.random().toString(36)
  15    test.__client.mkdir test.testFolder, (error, stat) ->
  16      expect(error).to.equal null
  17      done()
  18
  19  # Creates the binary image file in the test directory.
  20  setupImageFile = (test, done) ->
  21    test.imageFile = "#{test.testFolder}/test-binary-image.png"
  22    test.imageFileData = testImageBytes
  23
  24    setupImageFileUsingArrayBuffer test, (success) ->
  25      if success
  26        return done()
  27      setupImageFileUsingBlob test, (success) ->
  28        if success
  29          return done()
  30        setupImageFileUsingString test, done
  31
  32  # Standard-compliant browsers write via XHR#send(ArrayBufferView).
  33  setupImageFileUsingArrayBuffer = (test, done) ->
  34    if Uint8Array? and (not test.node_js)
  35      testImageServerOn()
  36      xhr = new Dropbox.Xhr 'GET', testImageUrl
  37      xhr.setResponseType('arraybuffer').prepare().send (error, buffer) =>
  38        testImageServerOff()
  39        expect(error).to.equal null
  40        test.__client.writeFile test.imageFile, buffer, (error, stat) ->
  41          expect(error).to.equal null
  42          # Some browsers will send the '[object Uint8Array]' string instead of
  43          # the ArrayBufferView.
  44          if stat.size is buffer.byteLength
  45            test.imageFileTag = stat.versionTag
  46            done true
  47          else
  48            done false
  49    else
  50      done false
  51
  52  # Fallback to XHR#send(Blob).
  53  setupImageFileUsingBlob = (test, done) ->
  54    if Blob? and (not test.node_js)
  55      testImageServerOn()
  56      xhr = new Dropbox.Xhr 'GET', testImageUrl
  57      xhr.setResponseType('arraybuffer').prepare().send (error, buffer) =>
  58        testImageServerOff()
  59        expect(error).to.equal null
  60        blob = new Blob [buffer], type: 'image/png'
  61        test.__client.writeFile test.imageFile, blob, (error, stat) ->
  62          expect(error).to.equal null
  63          if stat.size is blob.size
  64            test.imageFileTag = stat.versionTag
  65            done true
  66          else
  67            done false
  68    else
  69      done false
  70
  71  # Last resort: send a string that will get crushed by encoding errors.
  72  setupImageFileUsingString = (test, done) ->
  73    test.__client.writeFile(test.imageFile, test.imageFileData,
  74        { binary: true },
  75        (error, stat) ->
  76          expect(error).to.equal null
  77          test.imageFileTag = stat.versionTag
  78          done()
  79        )
  80
  81  # Creates the plaintext file in the test directory.
  82  setupTextFile = (test, done) ->
  83    test.textFile = "#{test.testFolder}/test-file.txt"
  84    test.textFileData = "Plaintext test file #{Math.random().toString(36)}.\n"
  85    test.__client.writeFile(test.textFile, test.textFileData,
  86        (error, stat) ->
  87          expect(error).to.equal null
  88          test.textFileTag = stat.versionTag
  89          done()
  90        )
  91
  92  # Global (expensive) fixtures.
  93  before (done) ->
  94    @timeout 10 * 1000
  95    setupClient this, =>
  96      setupDirectory this, =>
  97        setupImageFile this, =>
  98          setupTextFile this, ->
  99            done()
 100
 101  # Teardown for global fixtures.
 102  after (done) ->
 103    @__client.remove @testFolder, (error, stat) =>
 104      @test.error(new Error(error)) if error
 105      done()
 106
 107  # Per-test (cheap) fixtures.
 108  beforeEach ->
 109    @client = new Dropbox.Client clientKeys
 110
 111  describe 'URLs for custom API server', ->
 112    it 'computes the other URLs correctly', ->
 113      client = new Dropbox.Client
 114        key: clientKeys.key,
 115        secret: clientKeys.secret,
 116        server: 'https://api.sandbox.dropbox-proxy.com'
 117
 118      expect(client.apiServer).to.equal(
 119        'https://api.sandbox.dropbox-proxy.com')
 120      expect(client.authServer).to.equal(
 121        'https://www.sandbox.dropbox-proxy.com')
 122      expect(client.fileServer).to.equal(
 123        'https://api-content.sandbox.dropbox-proxy.com')
 124
 125  describe '#normalizePath', ->
 126    it "doesn't touch relative paths", ->
 127      expect(@client.normalizePath('aa/b/cc/dd')).to.equal 'aa/b/cc/dd'
 128
 129    it 'removes the leading / from absolute paths', ->
 130      expect(@client.normalizePath('/aaa/b/cc/dd')).to.equal 'aaa/b/cc/dd'
 131
 132    it 'removes multiple leading /s from absolute paths', ->
 133      expect(@client.normalizePath('///aa/b/ccc/dd')).to.equal 'aa/b/ccc/dd'
 134
 135  describe '#urlEncodePath', ->
 136    it 'encodes each segment separately', ->
 137      expect(@client.urlEncodePath('a b+c/d?e"f/g&h')).to.
 138          equal "a%20b%2Bc/d%3Fe%22f/g%26h"
 139    it 'normalizes paths', ->
 140      expect(@client.urlEncodePath('///a b+c/g&h')).to.
 141          equal "a%20b%2Bc/g%26h"
 142
 143  describe '#dropboxUid', ->
 144    it 'matches the uid in the credentials', ->
 145      expect(@client.dropboxUid()).to.equal clientKeys.uid
 146
 147  describe '#getUserInfo', ->
 148    it 'returns reasonable information', (done) ->
 149      @client.getUserInfo (error, userInfo, rawUserInfo) ->
 150        expect(error).to.equal null
 151        expect(userInfo).to.be.instanceOf Dropbox.UserInfo
 152        expect(userInfo.uid).to.equal clientKeys.uid
 153        expect(rawUserInfo).not.to.be.instanceOf Dropbox.UserInfo
 154        expect(rawUserInfo).to.have.property 'uid'
 155        done()
 156
 157    describe 'with httpCache', ->
 158      beforeEach ->
 159        @xhr = null
 160        @client.onXhr.addListener (xhr) =>
 161          @xhr = xhr
 162
 163      it 'uses Authorization headers', (done) ->
 164        @client.getUserInfo httpCache: true, (error, userInfo, rawUserInfo) =>
 165          if Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers
 166            expect(@xhr.url).to.contain 'oauth_nonce'
 167          else
 168            expect(@xhr.headers).to.have.key 'Authorization'
 169
 170          expect(error).to.equal null
 171          expect(userInfo).to.be.instanceOf Dropbox.UserInfo
 172          expect(userInfo.uid).to.equal clientKeys.uid
 173          expect(rawUserInfo).not.to.be.instanceOf Dropbox.UserInfo
 174          expect(rawUserInfo).to.have.property 'uid'
 175          done()
 176
 177  describe '#mkdir', ->
 178    afterEach (done) ->
 179      return done() unless @newFolder
 180      @client.remove @newFolder, (error, stat) -> done()
 181
 182    it 'creates a folder in the test folder', (done) ->
 183      @newFolder = "#{@testFolder}/test'folder"
 184      @client.mkdir @newFolder, (error, stat) =>
 185        expect(error).to.equal null
 186        expect(stat).to.be.instanceOf Dropbox.Stat
 187        expect(stat.path).to.equal @newFolder
 188        expect(stat.isFolder).to.equal true
 189        @client.stat @newFolder, (error, stat) =>
 190          expect(error).to.equal null
 191          expect(stat.isFolder).to.equal true
 192          done()
 193
 194  describe '#readFile', ->
 195    it 'reads a text file', (done) ->
 196      @client.readFile @textFile, (error, data, stat) =>
 197        expect(error).to.equal null
 198        expect(data).to.equal @textFileData
 199        unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 200          expect(stat).to.be.instanceOf Dropbox.Stat
 201          expect(stat.path).to.equal @textFile
 202          expect(stat.isFile).to.equal true
 203        done()
 204
 205    it 'reads the beginning of a text file', (done) ->
 206      return done() if Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 207
 208      @client.readFile @textFile, start: 0, length: 10, (error, data, stat) =>
 209        expect(error).to.equal null
 210        expect(data).to.equal @textFileData.substring(0, 10)
 211        expect(stat).to.be.instanceOf Dropbox.Stat
 212        expect(stat.path).to.equal @textFile
 213        expect(stat.isFile).to.equal true
 214        done()
 215
 216    it 'reads the middle of a text file', (done) ->
 217      return done() if Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 218
 219      @client.readFile @textFile, start: 8, length: 10, (error, data, stat) =>
 220        expect(error).to.equal null
 221        expect(data).to.equal @textFileData.substring(8, 18)
 222        expect(stat).to.be.instanceOf Dropbox.Stat
 223        expect(stat.path).to.equal @textFile
 224        expect(stat.isFile).to.equal true
 225        done()
 226
 227    it 'reads the end of a text file via the start: option', (done) ->
 228      return done() if Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 229
 230      @client.readFile @textFile, start: 10, (error, data, stat) =>
 231        expect(error).to.equal null
 232        expect(data).to.equal @textFileData.substring(10)
 233        expect(stat).to.be.instanceOf Dropbox.Stat
 234        expect(stat.path).to.equal @textFile
 235        expect(stat.isFile).to.equal true
 236        done()
 237
 238    it 'reads the end of a text file via the length: option', (done) ->
 239      return done() if Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 240
 241      @client.readFile @textFile, length: 10, (error, data, stat) =>
 242        expect(error).to.equal null
 243        expect(data).to.
 244            equal @textFileData.substring(@textFileData.length - 10)
 245        expect(stat).to.be.instanceOf Dropbox.Stat
 246        expect(stat.path).to.equal @textFile
 247        expect(stat.isFile).to.equal true
 248        done()
 249
 250    it 'reads a binary file into a string', (done) ->
 251      @client.readFile @imageFile, binary: true, (error, data, stat) =>
 252        expect(error).to.equal null
 253        expect(data).to.equal @imageFileData
 254        unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 255          expect(stat).to.be.instanceOf Dropbox.Stat
 256          expect(stat.path).to.equal @imageFile
 257          expect(stat.isFile).to.equal true
 258        done()
 259
 260    it 'reads a binary file into a Blob', (done) ->
 261      return done() unless Blob?
 262      @client.readFile @imageFile, blob: true, (error, blob, stat) =>
 263        expect(error).to.equal null
 264        expect(blob).to.be.instanceOf Blob
 265        unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 266          expect(stat).to.be.instanceOf Dropbox.Stat
 267          expect(stat.path).to.equal @imageFile
 268          expect(stat.isFile).to.equal true
 269        reader = new FileReader
 270        reader.onloadend = =>
 271          return unless reader.readyState == FileReader.DONE
 272          buffer = reader.result
 273          view = new Uint8Array buffer
 274          length = buffer.byteLength
 275          bytes = (String.fromCharCode view[i] for i in [0...length]).
 276              join('')
 277          expect(bytes).to.equal @imageFileData
 278          done()
 279        reader.readAsArrayBuffer blob
 280
 281    it 'reads a binary file into an ArrayBuffer', (done) ->
 282      return done() unless ArrayBuffer?
 283      @client.readFile @imageFile, arrayBuffer: true, (error, buffer, stat) =>
 284        expect(error).to.equal null
 285        expect(buffer).to.be.instanceOf ArrayBuffer
 286        unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 287          expect(stat).to.be.instanceOf Dropbox.Stat
 288          expect(stat.path).to.equal @imageFile
 289          expect(stat.isFile).to.equal true
 290        view = new Uint8Array buffer
 291        length = buffer.byteLength
 292        bytes = (String.fromCharCode view[i] for i in [0...length]).
 293            join('')
 294        expect(bytes).to.equal @imageFileData
 295        done()
 296
 297    describe 'with an onXhr listener', ->
 298      beforeEach ->
 299        @listenerXhr = null
 300        @callbackCalled = false
 301
 302      it 'calls the listener with a Dropbox.Xhr argument', (done) ->
 303        @client.onXhr.addListener (xhr) =>
 304          expect(xhr).to.be.instanceOf Dropbox.Xhr
 305          @listenerXhr = xhr
 306          true
 307
 308        @client.readFile @textFile, (error, data, stat) =>
 309          expect(error).to.equal null
 310          expect(data).to.equal @textFileData
 311          done() if @listenerXhr
 312
 313      it 'calls the listener before firing the XHR', (done) ->
 314        @client.onXhr.addListener (xhr) =>
 315          unless Dropbox.Xhr.ieXdr  # IE's XHR doesn't have readyState
 316            expect(xhr.xhr.readyState).to.equal 1
 317          expect(@callbackCalled).to.equal false
 318          @listenerXhr = xhr
 319          true
 320
 321        @client.readFile @textFile, (error, data, stat) =>
 322          @callbackCalled = true
 323          expect(@listenerXhr).to.be.instanceOf Dropbox.Xhr
 324          expect(error).to.equal null
 325          expect(data).to.equal @textFileData
 326          done() if @listenerXhr
 327
 328      it 'does not send the XHR if the listener cancels the event', (done) ->
 329        @client.onXhr.addListener (xhr) =>
 330          expect(@callbackCalled).to.equal false
 331          @listenerXhr = xhr
 332          # NOTE: if the client calls send(), a DOM error will fail the test
 333          xhr.send()
 334          false
 335
 336        @client.readFile @textFile, (error, data, stat) =>
 337          @callbackCalled = true
 338          expect(@listenerXhr).to.be.instanceOf Dropbox.Xhr
 339          done() if @listenerXhr
 340
 341    describe 'with httpCache', ->
 342      beforeEach ->
 343        @xhr = null
 344        @client.onXhr.addListener (xhr) =>
 345          @xhr = xhr
 346
 347      it 'reads a text file using Authorization headers', (done) ->
 348        @client.readFile @textFile, httpCache: true, (error, data, stat) =>
 349          if Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers
 350            expect(@xhr.url).to.contain 'oauth_nonce'
 351          else
 352            expect(@xhr.headers).to.have.key 'Authorization'
 353
 354          expect(error).to.equal null
 355          expect(data).to.equal @textFileData
 356          unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 357            expect(stat).to.be.instanceOf Dropbox.Stat
 358            expect(stat.path).to.equal @textFile
 359            expect(stat.isFile).to.equal true
 360          done()
 361
 362  describe '#writeFile', ->
 363    afterEach (done) ->
 364      return done() unless @newFile
 365      @client.remove @newFile, (error, stat) -> done()
 366
 367    it 'writes a new text file', (done) ->
 368      @newFile = "#{@testFolder}/another text file.txt"
 369      @newFileData = "Another plaintext file #{Math.random().toString(36)}."
 370      @client.writeFile @newFile, @newFileData, (error, stat) =>
 371        expect(error).to.equal null
 372        expect(stat).to.be.instanceOf Dropbox.Stat
 373        expect(stat.path).to.equal @newFile
 374        expect(stat.isFile).to.equal true
 375        @client.readFile @newFile, (error, data, stat) =>
 376          expect(error).to.equal null
 377          expect(data).to.equal @newFileData
 378          unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 379            expect(stat).to.be.instanceOf Dropbox.Stat
 380            expect(stat.path).to.equal @newFile
 381            expect(stat.isFile).to.equal true
 382          done()
 383
 384    it 'writes a new empty file', (done) ->
 385      @newFile = "#{@testFolder}/another text file.txt"
 386      @newFileData = ''
 387      @client.writeFile @newFile, @newFileData, (error, stat) =>
 388        expect(error).to.equal null
 389        expect(stat).to.be.instanceOf Dropbox.Stat
 390        expect(stat.path).to.equal @newFile
 391        expect(stat.isFile).to.equal true
 392        @client.readFile @newFile, (error, data, stat) =>
 393          expect(error).to.equal null
 394          expect(data).to.equal @newFileData
 395          unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 396            expect(stat).to.be.instanceOf Dropbox.Stat
 397            expect(stat.path).to.equal @newFile
 398            expect(stat.isFile).to.equal true
 399          done()
 400
 401    it 'writes a Blob to a binary file', (done) ->
 402      return done() unless Blob? and ArrayBuffer?
 403      @newFile = "#{@testFolder}/test image from blob.png"
 404      newBuffer = new ArrayBuffer @imageFileData.length
 405      newBytes = new Uint8Array newBuffer
 406      for i in [0...@imageFileData.length]
 407        newBytes[i] = @imageFileData.charCodeAt i
 408      @newBlob = new Blob [newBytes], type: 'image/png'
 409      if @newBlob.size isnt newBuffer.byteLength
 410        @newBlob = new Blob [newBuffer], type: 'image/png'
 411      @client.writeFile @newFile, @newBlob, (error, stat) =>
 412        expect(error).to.equal null
 413        expect(stat).to.be.instanceOf Dropbox.Stat
 414        expect(stat.path).to.equal @newFile
 415        expect(stat.isFile).to.equal true
 416
 417        @client.readFile @newFile, arrayBuffer: true,
 418            (error, buffer, stat) =>
 419              expect(error).to.equal null
 420              expect(buffer).to.be.instanceOf ArrayBuffer
 421              expect(stat).to.be.instanceOf Dropbox.Stat
 422              expect(stat.path).to.equal @newFile
 423              expect(stat.isFile).to.equal true
 424              view = new Uint8Array buffer
 425              length = buffer.byteLength
 426              bytes = (String.fromCharCode view[i] for i in [0...length]).
 427                  join('')
 428              expect(bytes).to.equal @imageFileData
 429              done()
 430
 431    it 'writes a File to a binary file', (done) ->
 432      return done() unless File? and Blob? and ArrayBuffer?
 433      @newFile = "#{@testFolder}/test image from blob.png"
 434      newBuffer = new ArrayBuffer @imageFileData.length
 435      newBytes = new Uint8Array newBuffer
 436      for i in [0...@imageFileData.length]
 437        newBytes[i] = @imageFileData.charCodeAt i
 438      newBlob = new Blob [newBytes], type: 'image/png'
 439
 440      # Called when we have a File wrapping newBlob.
 441      actualTestCase = (file) =>
 442        @newFileObject = file
 443        @client.writeFile @newFile, @newFileObject, (error, stat) =>
 444          expect(error).to.equal null
 445          expect(stat).to.be.instanceOf Dropbox.Stat
 446          expect(stat.path).to.equal @newFile
 447          expect(stat.isFile).to.equal true
 448
 449          @client.readFile @newFile, arrayBuffer: true,
 450              (error, buffer, stat) =>
 451                expect(error).to.equal null
 452                expect(buffer).to.be.instanceOf ArrayBuffer
 453                expect(stat).to.be.instanceOf Dropbox.Stat
 454                expect(stat.path).to.equal @newFile
 455                expect(stat.isFile).to.equal true
 456                view = new Uint8Array buffer
 457                length = buffer.byteLength
 458                bytes = (String.fromCharCode view[i] for i in [0...length]).
 459                    join('')
 460                expect(bytes).to.equal @imageFileData
 461                done()
 462
 463      # TODO(pwnall): use lighter method of constructing a File, when available
 464      #               http://crbug.com/164933
 465      return done() if typeof webkitRequestFileSystem is 'undefined'
 466      webkitRequestFileSystem window.TEMPORARY, 1024 * 1024, (fileSystem) ->
 467        # NOTE: the File name is different from the uploaded file name, to
 468        #       catch bugs such as http://crbug.com/165095
 469        fileSystem.root.getFile 'test image file.png',
 470            create: true, exclusive: false, (fileEntry) ->
 471              fileEntry.createWriter (fileWriter) ->
 472                fileWriter.onwriteend = ->
 473                  fileEntry.file (file) ->
 474                    actualTestCase file
 475                fileWriter.write newBlob
 476
 477    it 'writes an ArrayBuffer to a binary file', (done) ->
 478      return done() unless ArrayBuffer?
 479      @newFile = "#{@testFolder}/test image from arraybuffer.png"
 480      @newBuffer = new ArrayBuffer @imageFileData.length
 481      newBytes = new Uint8Array @newBuffer
 482      for i in [0...@imageFileData.length]
 483        newBytes[i] = @imageFileData.charCodeAt i
 484      @client.writeFile @newFile, @newBuffer, (error, stat) =>
 485        expect(error).to.equal null
 486        expect(stat).to.be.instanceOf Dropbox.Stat
 487        expect(stat.path).to.equal @newFile
 488        expect(stat.isFile).to.equal true
 489
 490        @client.readFile @newFile, arrayBuffer: true,
 491            (error, buffer, stat) =>
 492              expect(error).to.equal null
 493              expect(buffer).to.be.instanceOf ArrayBuffer
 494              expect(stat).to.be.instanceOf Dropbox.Stat
 495              expect(stat.path).to.equal @newFile
 496              expect(stat.isFile).to.equal true
 497              view = new Uint8Array buffer
 498              length = buffer.byteLength
 499              bytes = (String.fromCharCode view[i] for i in [0...length]).
 500                  join('')
 501              expect(bytes).to.equal @imageFileData
 502              done()
 503
 504    it 'writes an ArrayBufferView to a binary file', (done) ->
 505      return done() unless ArrayBuffer?
 506      @newFile = "#{@testFolder}/test image from arraybufferview.png"
 507      @newBytes = new Uint8Array @imageFileData.length
 508      for i in [0...@imageFileData.length]
 509        @newBytes[i] = @imageFileData.charCodeAt i
 510      @client.writeFile @newFile, @newBytes, (error, stat) =>
 511        expect(error).to.equal null
 512        expect(stat).to.be.instanceOf Dropbox.Stat
 513        expect(stat.path).to.equal @newFile
 514        expect(stat.isFile).to.equal true
 515
 516        @client.readFile @newFile, arrayBuffer: true,
 517            (error, buffer, stat) =>
 518              expect(error).to.equal null
 519              expect(buffer).to.be.instanceOf ArrayBuffer
 520              expect(stat).to.be.instanceOf Dropbox.Stat
 521              expect(stat.path).to.equal @newFile
 522              expect(stat.isFile).to.equal true
 523              view = new Uint8Array buffer
 524              length = buffer.byteLength
 525              bytes = (String.fromCharCode view[i] for i in [0...length]).
 526                  join('')
 527              expect(bytes).to.equal @imageFileData
 528              done()
 529
 530  describe '#resumableUploadStep + #resumableUploadFinish', ->
 531    beforeEach ->
 532      if ArrayBuffer?  # IE9 and below doesn't have ArrayBuffer
 533        @length1 = Math.ceil @imageFileData.length / 3
 534        @length2 = @imageFileData.length - @length1
 535        @buffer1 = new ArrayBuffer @length1
 536
 537        @view1 = new Uint8Array @buffer1
 538        for i in [0...@length1]
 539          @view1[i] = @imageFileData.charCodeAt i
 540        @buffer2 = new ArrayBuffer @length2
 541        @view2 = new Uint8Array @buffer2
 542        for i in [0...@length2]
 543          @view2[i] = @imageFileData.charCodeAt @length1 + i
 544
 545        if Blob?  # node.js and IE9 and below don't have Blob
 546          @blob1 = new Blob [@view1], type: 'image/png'
 547          if @blob1.size isnt @buffer1.byteLength
 548            @blob1 = new Blob [@buffer1], type: 'image/png'
 549          @blob2 = new Blob [@view2], type: 'image/png'
 550          if @blob2.size isnt @buffer2.byteLength
 551            @blob2 = new Blob [@buffer2], type: 'image/png'
 552
 553    afterEach (done) ->
 554      @timeout 20 * 1000  # This sequence is slow on the current API server.
 555      return done() unless @newFile
 556      @client.remove @newFile, (error, stat) -> done()
 557
 558    it 'writes a text file in two stages', (done) ->
 559      @timeout 20 * 1000  # This sequence is slow on the current API server.
 560
 561      @newFile = "#{@testFolder}/test resumable upload.txt"
 562      line1 = "This is the first fragment\n"
 563      line2 = "This is the second fragment\n"
 564      @client.resumableUploadStep line1, null, (error, cursor1) =>
 565        expect(error).to.equal null
 566        expect(cursor1).to.be.instanceOf Dropbox.UploadCursor
 567        expect(cursor1.offset).to.equal line1.length
 568        @client.resumableUploadStep line2, cursor1, (error, cursor2) =>
 569          expect(error).to.equal null
 570          expect(cursor2).to.be.instanceOf Dropbox.UploadCursor
 571          expect(cursor2.offset).to.equal line1.length + line2.length
 572          expect(cursor2.tag).to.equal cursor1.tag
 573          @client.resumableUploadFinish @newFile, cursor2, (error, stat) =>
 574            expect(error).to.equal null
 575            expect(stat).to.be.instanceOf Dropbox.Stat
 576            expect(stat.path).to.equal @newFile
 577            expect(stat.isFile).to.equal true
 578            @client.readFile @newFile, (error, data, stat) =>
 579              expect(error).to.equal null
 580              expect(data).to.equal line1 + line2
 581              unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 582                expect(stat).to.be.instanceOf Dropbox.Stat
 583                expect(stat.path).to.equal @newFile
 584                expect(stat.isFile).to.equal true
 585              done()
 586
 587    it 'writes a binary file using two ArrayBuffers', (done) ->
 588      return done() unless @buffer1
 589      @timeout 20 * 1000  # This sequence is slow on the current API server.
 590
 591      @newFile = "#{@testFolder}/test resumable arraybuffer upload.png"
 592      @client.resumableUploadStep @buffer1, null, (error, cursor1) =>
 593        expect(error).to.equal null
 594        expect(cursor1).to.be.instanceOf Dropbox.UploadCursor
 595        expect(cursor1.offset).to.equal @length1
 596        @client.resumableUploadStep @buffer2, cursor1, (error, cursor2) =>
 597          expect(error).to.equal null
 598          expect(cursor2).to.be.instanceOf Dropbox.UploadCursor
 599          expect(cursor2.offset).to.equal @length1 + @length2
 600          expect(cursor2.tag).to.equal cursor1.tag
 601          @client.resumableUploadFinish @newFile, cursor2, (error, stat) =>
 602            expect(error).to.equal null
 603            expect(stat).to.be.instanceOf Dropbox.Stat
 604            expect(stat.path).to.equal @newFile
 605            expect(stat.isFile).to.equal true
 606            @client.readFile @newFile, arrayBuffer: true,
 607                (error, buffer, stat) =>
 608                  expect(error).to.equal null
 609                  expect(buffer).to.be.instanceOf ArrayBuffer
 610                  expect(stat).to.be.instanceOf Dropbox.Stat
 611                  expect(stat.path).to.equal @newFile
 612                  expect(stat.isFile).to.equal true
 613                  view = new Uint8Array buffer
 614                  length = buffer.byteLength
 615                  bytes = (String.fromCharCode view[i] for i in [0...length]).
 616                      join('')
 617                  expect(bytes).to.equal @imageFileData
 618                  done()
 619
 620    it 'writes a binary file using two ArrayBufferViews', (done) ->
 621      return done() unless @view1
 622      @timeout 20 * 1000  # This sequence is slow on the current API server.
 623
 624      @newFile = "#{@testFolder}/test resumable arraybuffer upload.png"
 625      @client.resumableUploadStep @buffer1, null, (error, cursor1) =>
 626        expect(error).to.equal null
 627        expect(cursor1).to.be.instanceOf Dropbox.UploadCursor
 628        expect(cursor1.offset).to.equal @length1
 629        @client.resumableUploadStep @buffer2, cursor1, (error, cursor2) =>
 630          expect(error).to.equal null
 631          expect(cursor2).to.be.instanceOf Dropbox.UploadCursor
 632          expect(cursor2.offset).to.equal @length1 + @length2
 633          expect(cursor2.tag).to.equal cursor1.tag
 634          @client.resumableUploadFinish @newFile, cursor2, (error, stat) =>
 635            expect(error).to.equal null
 636            expect(stat).to.be.instanceOf Dropbox.Stat
 637            expect(stat.path).to.equal @newFile
 638            expect(stat.isFile).to.equal true
 639            @client.readFile @newFile, arrayBuffer: true,
 640                (error, buffer, stat) =>
 641                  expect(error).to.equal null
 642                  expect(buffer).to.be.instanceOf ArrayBuffer
 643                  expect(stat).to.be.instanceOf Dropbox.Stat
 644                  expect(stat.path).to.equal @newFile
 645                  expect(stat.isFile).to.equal true
 646                  view = new Uint8Array buffer
 647                  length = buffer.byteLength
 648                  bytes = (String.fromCharCode view[i] for i in [0...length]).
 649                      join('')
 650                  expect(bytes).to.equal @imageFileData
 651                  done()
 652
 653
 654    it 'writes a binary file using two Blobs', (done) ->
 655      return done() unless @blob1
 656      @timeout 20 * 1000  # This sequence is slow on the current API server.
 657
 658      @newFile = "#{@testFolder}/test resumable blob upload.png"
 659      @client.resumableUploadStep @blob1, null, (error, cursor1) =>
 660        expect(error).to.equal null
 661        expect(cursor1).to.be.instanceOf Dropbox.UploadCursor
 662        expect(cursor1.offset).to.equal @length1
 663        @client.resumableUploadStep @blob2, cursor1, (error, cursor2) =>
 664          expect(error).to.equal null
 665          expect(cursor2).to.be.instanceOf Dropbox.UploadCursor
 666          expect(cursor2.offset).to.equal @length1 + @length2
 667          expect(cursor2.tag).to.equal cursor1.tag
 668          @client.resumableUploadFinish @newFile, cursor2, (error, stat) =>
 669            expect(error).to.equal null
 670            expect(stat).to.be.instanceOf Dropbox.Stat
 671            expect(stat.path).to.equal @newFile
 672            expect(stat.isFile).to.equal true
 673            @client.readFile @newFile, arrayBuffer: true,
 674                (error, buffer, stat) =>
 675                  expect(error).to.equal null
 676                  expect(buffer).to.be.instanceOf ArrayBuffer
 677                  expect(stat).to.be.instanceOf Dropbox.Stat
 678                  expect(stat.path).to.equal @newFile
 679                  expect(stat.isFile).to.equal true
 680                  view = new Uint8Array buffer
 681                  length = buffer.byteLength
 682                  bytes = (String.fromCharCode view[i] for i in [0...length]).
 683                      join('')
 684                  expect(bytes).to.equal @imageFileData
 685                  done()
 686
 687    it 'recovers from out-of-sync correctly', (done) ->
 688      # IE's XDR doesn't return anything on errors, so we can't do recovery.
 689      return done() if Dropbox.Xhr.ieXdr
 690      @timeout 20 * 1000  # This sequence is slow on the current API server.
 691
 692      @newFile = "#{@testFolder}/test resumable upload out of sync.txt"
 693      line1 = "This is the first fragment\n"
 694      line2 = "This is the second fragment\n"
 695      @client.resumableUploadStep line1, null, (error, cursor1) =>
 696        expect(error).to.equal null
 697        expect(cursor1).to.be.instanceOf Dropbox.UploadCursor
 698        expect(cursor1.offset).to.equal line1.length
 699        cursor1.offset += 10
 700        @client.resumableUploadStep line2, cursor1, (error, cursor2) =>
 701          expect(error).to.equal null
 702          expect(cursor2).to.be.instanceOf Dropbox.UploadCursor
 703          expect(cursor2.offset).to.equal line1.length
 704          expect(cursor2.tag).to.equal cursor1.tag
 705          @client.resumableUploadStep line2, cursor2, (error, cursor3) =>
 706            expect(error).to.equal null
 707            expect(cursor3).to.be.instanceOf Dropbox.UploadCursor
 708            expect(cursor3.offset).to.equal line1.length + line2.length
 709            expect(cursor3.tag).to.equal cursor1.tag
 710            @client.resumableUploadFinish @newFile, cursor3, (error, stat) =>
 711              expect(error).to.equal null
 712              expect(stat).to.be.instanceOf Dropbox.Stat
 713              expect(stat.path).to.equal @newFile
 714              expect(stat.isFile).to.equal true
 715              @client.readFile @newFile, (error, data, stat) =>
 716                expect(error).to.equal null
 717                expect(data).to.equal line1 + line2
 718                unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 719                  expect(stat).to.be.instanceOf Dropbox.Stat
 720                  expect(stat.path).to.equal @newFile
 721                  expect(stat.isFile).to.equal true
 722                done()
 723
 724    it 'reports errors correctly', (done) ->
 725      @newFile = "#{@testFolder}/test resumable upload error.txt"
 726      badCursor = new Dropbox.UploadCursor 'trollcursor'
 727      badCursor.offset = 42
 728      @client.resumableUploadStep @textFileData, badCursor, (error, cursor) =>
 729        expect(cursor).to.equal undefined
 730        expect(error).to.be.instanceOf Dropbox.ApiError
 731        unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do status codes.
 732          expect(error.status).to.equal 404
 733        done()
 734
 735  describe '#stat', ->
 736    it 'retrieves a Stat for a file', (done) ->
 737      @client.stat @textFile, (error, stat) =>
 738        expect(error).to.equal null
 739        expect(stat).to.be.instanceOf Dropbox.Stat
 740        expect(stat.path).to.equal @textFile
 741        expect(stat.isFile).to.equal true
 742        expect(stat.versionTag).to.equal @textFileTag
 743        expect(stat.size).to.equal @textFileData.length
 744        if clientKeys.sandbox
 745          expect(stat.inAppFolder).to.equal true
 746        else
 747          expect(stat.inAppFolder).to.equal false
 748        done()
 749
 750    it 'retrieves a Stat for a folder', (done) ->
 751      @client.stat @testFolder, (error, stat, entries) =>
 752        expect(error).to.equal null
 753        expect(stat).to.be.instanceOf Dropbox.Stat
 754        expect(stat.path).to.equal @testFolder
 755        expect(stat.isFolder).to.equal true
 756        expect(stat.size).to.equal 0
 757        if clientKeys.sandbox
 758          expect(stat.inAppFolder).to.equal true
 759        else
 760          expect(stat.inAppFolder).to.equal false
 761        expect(entries).to.equal undefined
 762        done()
 763
 764    it 'retrieves a Stat and entries for a folder', (done) ->
 765      @client.stat @testFolder, { readDir: true }, (error, stat, entries) =>
 766        expect(error).to.equal null
 767        expect(stat).to.be.instanceOf Dropbox.Stat
 768        expect(stat.path).to.equal @testFolder
 769        expect(stat.isFolder).to.equal true
 770        expect(entries).to.be.ok
 771        expect(entries).to.have.length 2
 772        expect(entries[0]).to.be.instanceOf Dropbox.Stat
 773        expect(entries[0].path).not.to.equal @testFolder
 774        expect(entries[0].path).to.have.string @testFolder
 775        done()
 776
 777    it 'fails cleanly for a non-existing path', (done) ->
 778      listenerError = null
 779      @client.onError.addListener (error) -> listenerError = error
 780
 781      @client.stat @testFolder + '/should_404.txt', (error, stat, entries) =>
 782        expect(stat).to.equal undefined
 783        expect(entries).to.equal.null
 784        expect(error).to.be.instanceOf Dropbox.ApiError
 785        expect(listenerError).to.equal error
 786        unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do status codes.
 787          expect(error).to.have.property 'status'
 788          expect(error.status).to.equal 404
 789        done()
 790
 791    describe 'with httpCache', ->
 792      beforeEach ->
 793        @xhr = null
 794        @client.onXhr.addListener (xhr) =>
 795          @xhr = xhr
 796
 797      it 'retrieves a Stat for a file using Authorization headers', (done) ->
 798        @client.stat @textFile, httpCache: true, (error, stat) =>
 799          if Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers
 800            expect(@xhr.url).to.contain 'oauth_nonce'
 801          else
 802            expect(@xhr.headers).to.have.key 'Authorization'
 803
 804          expect(error).to.equal null
 805          expect(stat).to.be.instanceOf Dropbox.Stat
 806          expect(stat.path).to.equal @textFile
 807          expect(stat.isFile).to.equal true
 808          expect(stat.versionTag).to.equal @textFileTag
 809          expect(stat.size).to.equal @textFileData.length
 810          if clientKeys.sandbox
 811            expect(stat.inAppFolder).to.equal true
 812          else
 813            expect(stat.inAppFolder).to.equal false
 814          done()
 815
 816  describe '#readdir', ->
 817    it 'retrieves a Stat and entries for a folder', (done) ->
 818      @client.readdir @testFolder, (error, entries, dir_stat, entry_stats) =>
 819        expect(error).to.equal null
 820        expect(entries).to.be.ok
 821        expect(entries).to.have.length 2
 822        expect(entries[0]).to.be.a 'string'
 823        expect(entries[0]).not.to.have.string '/'
 824        expect(entries[0]).to.match /^(test-binary-image.png)|(test-file.txt)$/
 825        expect(dir_stat).to.be.instanceOf Dropbox.Stat
 826        expect(dir_stat.path).to.equal @testFolder
 827        expect(dir_stat.isFolder).to.equal true
 828        expect(entry_stats).to.be.ok
 829        expect(entry_stats).to.have.length 2
 830        expect(entry_stats[0]).to.be.instanceOf Dropbox.Stat
 831        expect(entry_stats[0].path).not.to.equal @testFolder
 832        expect(entry_stats[0].path).to.have.string @testFolder
 833        done()
 834
 835    describe 'with httpCache', ->
 836      beforeEach ->
 837        @xhr = null
 838        @client.onXhr.addListener (xhr) =>
 839          @xhr = xhr
 840
 841      it 'retrieves a folder Stat and entries using Authorization', (done) ->
 842        @client.readdir @testFolder, httpCache: true,
 843            (error, entries, dir_stat, entry_stats) =>
 844              if Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers
 845                expect(@xhr.url).to.contain 'oauth_nonce'
 846              else
 847                expect(@xhr.headers).to.have.key 'Authorization'
 848
 849              expect(error).to.equal null
 850              expect(entries).to.be.ok
 851              expect(entries).to.have.length 2
 852              expect(entries[0]).to.be.a 'string'
 853              expect(entries[0]).not.to.have.string '/'
 854              expect(entries[0]).to.match(
 855                  /^(test-binary-image.png)|(test-file.txt)$/)
 856              expect(dir_stat).to.be.instanceOf Dropbox.Stat
 857              expect(dir_stat.path).to.equal @testFolder
 858              expect(dir_stat.isFolder).to.equal true
 859              expect(entry_stats).to.be.ok
 860              expect(entry_stats).to.have.length 2
 861              expect(entry_stats[0]).to.be.instanceOf Dropbox.Stat
 862              expect(entry_stats[0].path).not.to.equal @testFolder
 863              expect(entry_stats[0].path).to.have.string @testFolder
 864              done()
 865
 866  describe '#history', ->
 867    it 'gets a list of revisions', (done) ->
 868      @client.history @textFile, (error, versions) =>
 869        expect(error).to.equal null
 870        expect(versions).to.have.length 1
 871        expect(versions[0]).to.be.instanceOf Dropbox.Stat
 872        expect(versions[0].path).to.equal @textFile
 873        expect(versions[0].size).to.equal @textFileData.length
 874        expect(versions[0].versionTag).to.equal @textFileTag
 875        done()
 876
 877    it 'returns 40x if the limit is set to 0', (done) ->
 878      listenerError = null
 879      @client.onError.addListener (error) -> listenerError = error
 880
 881      @client.history @textFile, limit: 0, (error, versions) =>
 882        expect(error).to.be.instanceOf Dropbox.ApiError
 883        expect(listenerError).to.equal error
 884        unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do status codes.
 885          expect(error.status).to.be.within 400, 499
 886        expect(versions).not.to.be.ok
 887        done()
 888
 889    describe 'with httpCache', ->
 890      beforeEach ->
 891        @xhr = null
 892        @client.onXhr.addListener (xhr) =>
 893          @xhr = xhr
 894
 895      it 'gets a list of revisions using Authorization headers', (done) ->
 896        @client.history @textFile, httpCache: true, (error, versions) =>
 897          if Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers
 898            expect(@xhr.url).to.contain 'oauth_nonce'
 899          else
 900            expect(@xhr.headers).to.have.key 'Authorization'
 901
 902          expect(error).to.equal null
 903          expect(versions).to.have.length 1
 904          expect(versions[0]).to.be.instanceOf Dropbox.Stat
 905          expect(versions[0].path).to.equal @textFile
 906          expect(versions[0].size).to.equal @textFileData.length
 907          expect(versions[0].versionTag).to.equal @textFileTag
 908          done()
 909
 910  describe '#copy', ->
 911    afterEach (done) ->
 912      return done() unless @newFile
 913      @client.remove @newFile, (error, stat) -> done()
 914
 915    it 'copies a file given by path', (done) ->
 916      @timeout 12 * 1000  # This sequence is slow on the current API server.
 917
 918      @newFile = "#{@testFolder}/copy of test-file.txt"
 919      @client.copy @textFile, @newFile, (error, stat) =>
 920        expect(error).to.equal null
 921        expect(stat).to.be.instanceOf Dropbox.Stat
 922        expect(stat.path).to.equal @newFile
 923        @client.readFile @newFile, (error, data, stat) =>
 924          expect(error).to.equal null
 925          expect(data).to.equal @textFileData
 926          unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 927            expect(stat).to.be.instanceOf Dropbox.Stat
 928            expect(stat.path).to.equal @newFile
 929          @client.readFile @textFile, (error, data, stat) =>
 930            expect(error).to.equal null
 931            expect(data).to.equal @textFileData
 932            unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 933              expect(stat).to.be.instanceOf Dropbox.Stat
 934              expect(stat.path).to.equal @textFile
 935              expect(stat.versionTag).to.equal @textFileTag
 936            done()
 937
 938  describe '#makeCopyReference', ->
 939    afterEach (done) ->
 940      return done() unless @newFile
 941      @client.remove @newFile, (error, stat) -> done()
 942
 943    it 'creates a Dropbox.CopyReference that copies the file', (done) ->
 944      @timeout 12 * 1000  # This sequence is slow on the current API server.
 945      @newFile = "#{@testFolder}/ref copy of test-file.txt"
 946
 947      @client.makeCopyReference @textFile, (error, copyRef) =>
 948        expect(error).to.equal null
 949        expect(copyRef).to.be.instanceOf Dropbox.CopyReference
 950        @client.copy copyRef, @newFile, (error, stat) =>
 951          expect(error).to.equal null
 952          expect(stat).to.be.instanceOf Dropbox.Stat
 953          expect(stat.path).to.equal @newFile
 954          expect(stat.isFile).to.equal true
 955          @client.readFile @newFile, (error, data, stat) =>
 956            expect(error).to.equal null
 957            expect(data).to.equal @textFileData
 958            unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 959              expect(stat).to.be.instanceOf Dropbox.Stat
 960              expect(stat.path).to.equal @newFile
 961            done()
 962
 963  describe '#move', ->
 964    beforeEach (done) ->
 965      @timeout 10 * 1000  # This sequence is slow on the current API server.
 966      @moveFrom = "#{@testFolder}/move source of test-file.txt"
 967      @client.copy @textFile, @moveFrom, (error, stat) ->
 968        expect(error).to.equal null
 969        done()
 970
 971    afterEach (done) ->
 972      @client.remove @moveFrom, (error, stat) =>
 973        return done() unless @moveTo
 974        @client.remove @moveTo, (error, stat) -> done()
 975
 976    it 'moves a file', (done) ->
 977      @timeout 15 * 1000  # This sequence is slow on the current API server.
 978      @moveTo = "#{@testFolder}/moved test-file.txt"
 979      @client.move @moveFrom, @moveTo, (error, stat) =>
 980        expect(error).to.equal null
 981        expect(stat).to.be.instanceOf Dropbox.Stat
 982        expect(stat.path).to.equal @moveTo
 983        expect(stat.isFile).to.equal true
 984        @client.readFile @moveTo, (error, data, stat) =>
 985          expect(error).to.equal null
 986          expect(data).to.equal @textFileData
 987          unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 988            expect(stat).to.be.instanceOf Dropbox.Stat
 989            expect(stat.path).to.equal @moveTo
 990          @client.readFile @moveFrom, (error, data, stat) ->
 991            expect(error).to.be.ok
 992            unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do status codes.
 993              expect(error).to.have.property 'status'
 994              expect(error.status).to.equal 404
 995            expect(data).to.equal undefined
 996            unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
 997              expect(stat).to.equal undefined
 998            done()
 999
1000  describe '#remove', ->
1001    beforeEach (done) ->
1002      @newFolder = "#{@testFolder}/folder delete test"
1003      @client.mkdir @newFolder, (error, stat) =>
1004        expect(error).to.equal null
1005        done()
1006
1007    afterEach (done) ->
1008      return done() unless @newFolder
1009      @client.remove @newFolder, (error, stat) -> done()
1010
1011    it 'deletes a folder', (done) ->
1012      @client.remove @newFolder, (error, stat) =>
1013        expect(error).to.equal null
1014        expect(stat).to.be.instanceOf Dropbox.Stat
1015        expect(stat.path).to.equal @newFolder
1016        @client.stat @newFolder, { removed: true }, (error, stat) =>
1017          expect(error).to.equal null
1018          expect(stat).to.be.instanceOf Dropbox.Stat
1019          expect(stat.isRemoved).to.equal true
1020          done()
1021
1022    it 'deletes a folder when called as unlink', (done) ->
1023      @client.unlink @newFolder, (error, stat) =>
1024        expect(error).to.equal null
1025        expect(stat).to.be.instanceOf Dropbox.Stat
1026        expect(stat.path).to.equal @newFolder
1027        @client.stat @newFolder, { removed: true }, (error, stat) =>
1028          expect(error).to.equal null
1029          expect(stat).to.be.instanceOf Dropbox.Stat
1030          expect(stat.isRemoved).to.equal true
1031          done()
1032
1033  describe '#revertFile', ->
1034    describe 'on a removed file', ->
1035      beforeEach (done) ->
1036        @timeout 12 * 1000  # This sequence seems to be quite slow.
1037
1038        @newFile = "#{@testFolder}/file revert test.txt"
1039        @client.copy @textFile, @newFile, (error, stat) =>
1040          expect(error).to.equal null
1041          expect(stat).to.be.instanceOf Dropbox.Stat
1042          expect(stat.path).to.equal @newFile
1043          @versionTag = stat.versionTag
1044          @client.remove @newFile, (error, stat) =>
1045            expect(error).to.equal null
1046            expect(stat).to.be.instanceOf Dropbox.Stat
1047            expect(stat.path).to.equal @newFile
1048            done()
1049
1050      afterEach (done) ->
1051        return done() unless @newFile
1052        @client.remove @newFile, (error, stat) -> done()
1053
1054      it 'reverts the file to a previous version', (done) ->
1055        @timeout 12 * 1000  # This sequence seems to be quite slow.
1056
1057        @client.revertFile @newFile, @versionTag, (error, stat) =>
1058          expect(error).to.equal null
1059          expect(stat).to.be.instanceOf Dropbox.Stat
1060          expect(stat.path).to.equal @newFile
1061          expect(stat.isRemoved).to.equal false
1062          @client.readFile @newFile, (error, data, stat) =>
1063            expect(error).to.equal null
1064            expect(data).to.equal @textFileData
1065            unless Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers.
1066              expect(stat).to.be.instanceOf Dropbox.Stat
1067              expect(stat.path).to.equal @newFile
1068              expect(stat.isRemoved).to.equal false
1069            done()
1070
1071  describe '#findByName', ->
1072    it 'locates the test folder given a partial name', (done) ->
1073      namePattern = @testFolder.substring 5
1074      @client.search '/', namePattern, (error, matches) =>
1075        expect(error).to.equal null
1076        expect(matches).to.have.length 1
1077        expect(matches[0]).to.be.instanceOf Dropbox.Stat
1078        expect(matches[0].path).to.equal @testFolder
1079        expect(matches[0].isFolder).to.equal true
1080        done()
1081
1082    it 'lists the test folder files given the "test" pattern', (done) ->
1083      @client.search @testFolder, 'test', (error, matches) =>
1084        expect(error).to.equal null
1085        expect(matches).to.have.length 2
1086        done()
1087
1088    it 'only lists one match when given limit 1', (done) ->
1089      @client.search @testFolder, 'test', limit: 1, (error, matches) =>
1090        expect(error).to.equal null
1091        expect(matches).to.have.length 1
1092        done()
1093
1094    describe 'with httpCache', ->
1095      beforeEach ->
1096        @xhr = null
1097        @client.onXhr.addListener (xhr) =>
1098          @xhr = xhr
1099
1100      it 'locates the test folder using Authorize headers', (done) ->
1101        namePattern = @testFolder.substring 5
1102        @client.search '/', namePattern, httpCache: true, (error, matches) =>
1103          if Dropbox.Xhr.ieXdr  # IE's XDR doesn't do headers
1104            expect(@xhr.url).to.contain 'oauth_nonce'
1105          else
1106            expect(@xhr.headers).to.have.key 'Authorization'
1107
1108          expect(error).to.equal null
1109          expect(matches).to.have.length 1
1110          expect(matches[0]).to.be.instanceOf Dropbox.Stat
1111          expect(matches[0].path).to.equal @testFolder
1112          expect(matches[0].isFolder).to.equal true
1113          done()
1114
1115  describe '#makeUrl', ->
1116    describe 'for a short Web URL', ->
1117      it 'returns a shortened Dropbox URL', (done) ->
1118        @client.makeUrl @textFile, (error, publicUrl) ->
1119          expect(error).to.equal null
1120          expect(publicUrl).to.be.instanceOf Dropbox.PublicUrl
1121          expect(publicUrl.isDirect).to.equal false
1122          expect(publicUrl.url).to.contain '//db.tt/'
1123          done()
1124
1125    describe 'for a Web URL created with long: true', ->
1126      it 'returns an URL to a preview page', (done) ->
1127        @client.makeUrl @textFile, { long: true }, (error, publicUrl) =>
1128          expect(error).to.equal null
1129          expect(publicUrl).to.be.instanceOf Dropbox.PublicUrl
1130          expect(publicUrl.isDirect).to.equal false
1131          expect(publicUrl.url).not.to.contain '//db.tt/'
1132
1133          # The cont/ents server does not return CORS headers.
1134          return done() unless @nodejs
1135          Dropbox.Xhr.request 'GET', publicUrl.url, {}, null, (error, data) ->
1136            expect(error).to.equal null
1137            expect(data).to.contain '<!DOCTYPE html>'
1138            done()
1139
1140    describe 'for a Web URL created with longUrl: true', ->
1141      it 'returns an URL to a preview page', (done) ->
1142        @client.makeUrl @textFile, { longUrl: true }, (error, publicUrl) =>
1143          expect(error).to.equal null
1144          expect(publicUrl).to.be.instanceOf Dropbox.PublicUrl
1145          expect(publicUrl.isDirect).to.equal false
1146          expect(publicUrl.url).not.to.contain '//db.tt/'
1147          done()
1148
1149    describe 'for a direct download URL', ->
1150      it 'gets a direct download URL', (done) ->
1151        @client.makeUrl @textFile, { download: true }, (error, publicUrl) =>
1152          expect(error).to.equal null
1153          expect(publicUrl).to.be.instanceOf Dropbox.PublicUrl
1154          expect(publicUrl.isDirect).to.equal true
1155          expect(publicUrl.url).not.to.contain '//db.tt/'
1156
1157          # The contents server does not return CORS headers.
1158          return done() unless @nodejs
1159          Dropbox.Xhr.request 'GET', publicUrl.url, {}, null, (error, data) =>
1160            expect(error).to.equal null
1161            expect(data).to.equal @textFileData
1162            done()
1163
1164    describe 'for a direct download URL created with downloadHack: true', ->
1165      it 'gets a direct long-lived download URL', (done) ->
1166        @client.makeUrl @textFile, { downloadHack: true }, (error, publicUrl) =>
1167          expect(error).to.equal null
1168          expect(publicUrl).to.be.instanceOf Dropbox.PublicUrl
1169          expect(publicUrl.isDirect).to.equal true
1170          expect(publicUrl.url).not.to.contain '//db.tt/'
1171          expect(publicUrl.expiresAt - Date.now()).to.be.above 86400000
1172
1173          # The download server does not return CORS headers.
1174          return done() unless @nodejs
1175          Dropbox.Xhr.request 'GET', publicUrl.url, {}, null, (error, data) =>
1176            expect(error).to.equal null
1177            expect(data).to.equal @textFileData
1178            done()
1179
1180  describe '#pullChanges', ->
1181    beforeEach ->
1182      # Pulling an entire Dropbox can take a lot of time, so we need fan

Large files files are truncated, but you can click here to view the full file