2015-06-12 02:52:49 +08:00
|
|
|
File = require '../../src/flux/models/file'
|
|
|
|
Actions = require '../../src/flux/actions'
|
|
|
|
FileUploadStore = require '../../src/flux/stores/file-upload-store'
|
2016-01-28 04:33:09 +08:00
|
|
|
{Upload} = FileUploadStore
|
2015-07-16 07:52:43 +08:00
|
|
|
fs = require 'fs'
|
2015-06-12 02:52:49 +08:00
|
|
|
|
|
|
|
msgId = "local-123"
|
|
|
|
fpath = "/foo/bar/test123.jpg"
|
2016-01-28 04:33:09 +08:00
|
|
|
fDir = "/foo/bar"
|
|
|
|
uploadDir = "/uploads"
|
|
|
|
filename = "test123.jpg"
|
|
|
|
argsObj = {messageClientId: msgId, filePath: fpath}
|
2015-06-12 02:52:49 +08:00
|
|
|
|
|
|
|
describe 'FileUploadStore', ->
|
|
|
|
beforeEach ->
|
2016-01-28 04:33:09 +08:00
|
|
|
FileUploadStore._fileUploads = {}
|
2015-11-12 02:25:11 +08:00
|
|
|
spyOn(NylasEnv, "showOpenDialog").andCallFake (props, callback) ->
|
2015-06-12 02:52:49 +08:00
|
|
|
callback(fpath)
|
|
|
|
|
|
|
|
|
2016-01-28 04:33:09 +08:00
|
|
|
describe 'selectAttachment', ->
|
2015-10-22 03:28:41 +08:00
|
|
|
it "throws if no messageClientId is provided", ->
|
2016-01-28 04:33:09 +08:00
|
|
|
expect( -> Actions.selectAttachment()).toThrow()
|
2015-06-12 02:52:49 +08:00
|
|
|
|
2016-01-28 04:33:09 +08:00
|
|
|
it "throws if messageClientId is blank", ->
|
|
|
|
expect( -> Actions.selectAttachment("")).toThrow()
|
|
|
|
|
|
|
|
it "dispatches action to attach file", ->
|
|
|
|
spyOn(Actions, "addAttachment")
|
2015-10-22 03:28:41 +08:00
|
|
|
|
2016-01-28 04:33:09 +08:00
|
|
|
Actions.selectAttachment(messageClientId: msgId)
|
2015-11-12 02:25:11 +08:00
|
|
|
expect(NylasEnv.showOpenDialog).toHaveBeenCalled()
|
2016-01-28 04:33:09 +08:00
|
|
|
expect(Actions.addAttachment).toHaveBeenCalled()
|
|
|
|
args = Actions.addAttachment.calls[0].args[0]
|
2015-08-29 02:12:53 +08:00
|
|
|
expect(args.messageClientId).toBe msgId
|
2016-01-28 04:33:09 +08:00
|
|
|
expect(args.filePath).toBe fpath
|
|
|
|
|
|
|
|
|
|
|
|
describe 'addAttachment', ->
|
|
|
|
beforeEach ->
|
|
|
|
@upload = new Upload(msgId, fpath, {size: 1234, isDirectory: -> false}, 'u1', uploadDir)
|
|
|
|
spyOn(FileUploadStore, '_getFileStats').andCallFake -> Promise.resolve()
|
|
|
|
spyOn(FileUploadStore, '_makeUpload').andCallFake -> Promise.resolve()
|
|
|
|
spyOn(FileUploadStore, '_verifyUpload').andCallFake -> Promise.resolve()
|
|
|
|
spyOn(FileUploadStore, '_prepareTargetDir').andCallFake -> Promise.resolve()
|
|
|
|
spyOn(FileUploadStore, '_copyUpload').andCallFake => Promise.resolve(@upload)
|
|
|
|
spyOn(FileUploadStore, '_saveUpload').andCallThrough()
|
|
|
|
spyOn(FileUploadStore, 'trigger')
|
2015-06-12 02:52:49 +08:00
|
|
|
|
2015-10-22 03:28:41 +08:00
|
|
|
it "throws if no messageClientId or path is provided", ->
|
2016-01-28 04:33:09 +08:00
|
|
|
expect( -> Actions.addAttachment()).toThrow()
|
|
|
|
|
|
|
|
it "executes the required steps and triggers", ->
|
|
|
|
waitsForPromise ->
|
|
|
|
FileUploadStore._onAddAttachment(argsObj)
|
|
|
|
|
|
|
|
runs =>
|
|
|
|
expect(FileUploadStore._getFileStats).toHaveBeenCalled()
|
|
|
|
expect(FileUploadStore._makeUpload).toHaveBeenCalled()
|
|
|
|
expect(FileUploadStore._verifyUpload).toHaveBeenCalled()
|
|
|
|
expect(FileUploadStore._prepareTargetDir).toHaveBeenCalled()
|
|
|
|
expect(FileUploadStore._copyUpload).toHaveBeenCalled()
|
|
|
|
expect(FileUploadStore._saveUpload).toHaveBeenCalled()
|
|
|
|
expect(FileUploadStore.trigger).toHaveBeenCalled()
|
|
|
|
expect(FileUploadStore.uploadsForMessage(msgId)).toEqual [@upload]
|
|
|
|
|
|
|
|
|
|
|
|
describe 'removeAttachment', ->
|
|
|
|
beforeEach ->
|
|
|
|
@upload = new Upload(msgId, fpath, {size: 1234, isDirectory: -> false}, 'u1', uploadDir)
|
|
|
|
spyOn(FileUploadStore, '_deleteUpload').andCallFake => Promise.resolve(@upload)
|
|
|
|
spyOn(FileUploadStore, 'trigger')
|
|
|
|
spyOn(fs, 'rmdir')
|
|
|
|
|
|
|
|
it 'does nothing if msgId does not exist', ->
|
|
|
|
waitsForPromise =>
|
|
|
|
FileUploadStore._onRemoveAttachment(messageClientId: 'xyz')
|
|
|
|
.then ->
|
|
|
|
expect(FileUploadStore.trigger).not.toHaveBeenCalled()
|
|
|
|
|
|
|
|
it 'removes upload correctly', ->
|
|
|
|
FileUploadStore._fileUploads[msgId] = [{id: 'u2'}, @upload]
|
|
|
|
waitsForPromise =>
|
|
|
|
FileUploadStore._onRemoveAttachment(@upload)
|
|
|
|
.then ->
|
|
|
|
expect(FileUploadStore.uploadsForMessage(msgId)).toEqual [{id: 'u2'}]
|
|
|
|
expect(fs.rmdir).not.toHaveBeenCalled()
|
|
|
|
expect(FileUploadStore.trigger).toHaveBeenCalled()
|
|
|
|
|
|
|
|
it 'removes upload and removes directory if no more uploads left dor message', ->
|
|
|
|
FileUploadStore._fileUploads[msgId] = [@upload]
|
|
|
|
waitsForPromise =>
|
|
|
|
FileUploadStore._onRemoveAttachment(@upload)
|
|
|
|
.then ->
|
|
|
|
expect(FileUploadStore.uploadsForMessage(msgId)).toEqual []
|
|
|
|
expect(fs.rmdir).toHaveBeenCalled()
|
|
|
|
expect(FileUploadStore.trigger).toHaveBeenCalled()
|
|
|
|
|
|
|
|
|
|
|
|
describe '_getFileUploadsFromFs', ->
|
|
|
|
# TODO
|
|
|
|
|
2015-06-12 02:52:49 +08:00
|
|
|
|
2016-01-28 04:33:09 +08:00
|
|
|
describe '_getFileStats', ->
|
|
|
|
|
|
|
|
it 'returns the correct stats', ->
|
2015-07-16 07:52:43 +08:00
|
|
|
spyOn(fs, 'stat').andCallFake (path, callback) ->
|
2015-10-22 03:28:41 +08:00
|
|
|
callback(null, {size: 1234, isDirectory: -> false})
|
2016-01-28 04:33:09 +08:00
|
|
|
waitsForPromise ->
|
|
|
|
FileUploadStore._getFileStats(argsObj)
|
|
|
|
.then ({stats}) ->
|
|
|
|
expect(stats.size).toEqual 1234
|
|
|
|
expect(stats.isDirectory()).toBe false
|
|
|
|
|
|
|
|
it 'throws when there is an error reading the file', ->
|
2015-10-22 03:28:41 +08:00
|
|
|
spyOn(fs, 'stat').andCallFake (path, callback) ->
|
2016-01-28 04:33:09 +08:00
|
|
|
callback("Error!", null)
|
|
|
|
waitsForPromise ->
|
|
|
|
FileUploadStore._getFileStats(argsObj)
|
|
|
|
.then -> throw new Error('It should fail.')
|
|
|
|
.catch (msg) ->
|
|
|
|
expect(msg.indexOf(fpath)).toBe 0
|
|
|
|
|
|
|
|
|
|
|
|
describe '_verifyUpload', ->
|
|
|
|
|
|
|
|
it 'throws if upload is a directory', ->
|
|
|
|
upload = new Upload(msgId, fpath, {isDirectory: -> true})
|
|
|
|
waitsForPromise ->
|
|
|
|
FileUploadStore._verifyUpload(upload)
|
|
|
|
.then -> throw new Error('It should fail.')
|
|
|
|
.catch (msg) ->
|
|
|
|
expect(msg.indexOf(filename + ' is a directory')).toBe 0
|
|
|
|
|
|
|
|
it 'throws if the file is more than 25MB', ->
|
|
|
|
upload = new Upload(msgId, fpath, {size: 25*1000000+1, isDirectory: -> false})
|
|
|
|
waitsForPromise ->
|
|
|
|
FileUploadStore._verifyUpload(upload)
|
|
|
|
.then -> throw new Error('It should fail.')
|
|
|
|
.catch (msg) ->
|
|
|
|
expect(msg.indexOf(filename + ' cannot')).toBe 0
|
|
|
|
|
|
|
|
it 'resolves otherwise', ->
|
|
|
|
upload = new Upload(msgId, fpath, {size: 1234, isDirectory: -> false})
|
|
|
|
waitsForPromise ->
|
|
|
|
FileUploadStore._verifyUpload(upload)
|
|
|
|
.then (up)-> expect(up.id).toBe upload.id
|
|
|
|
|
|
|
|
|
|
|
|
describe '_copyUpload', ->
|
|
|
|
|
|
|
|
beforeEach ->
|
|
|
|
stream = require 'stream'
|
|
|
|
@upload = new Upload(msgId, fpath, {size: 1234, isDirectory: -> false}, null, uploadDir)
|
|
|
|
@readStream = stream.Readable()
|
|
|
|
@writeStream = stream.Writable()
|
|
|
|
spyOn(@readStream, 'pipe')
|
|
|
|
spyOn(fs, 'createReadStream').andReturn @readStream
|
|
|
|
spyOn(fs, 'createWriteStream').andReturn @writeStream
|
|
|
|
|
|
|
|
it 'copies the file correctly', ->
|
|
|
|
waitsForPromise =>
|
|
|
|
promise = FileUploadStore._copyUpload(@upload)
|
|
|
|
@readStream.emit 'end'
|
|
|
|
promise.then (up) =>
|
|
|
|
expect(fs.createReadStream).toHaveBeenCalledWith(fpath)
|
|
|
|
expect(fs.createWriteStream).toHaveBeenCalledWith(@upload.targetPath)
|
|
|
|
expect(@readStream.pipe).toHaveBeenCalledWith(@writeStream)
|
|
|
|
expect(up.id).toEqual @upload.id
|
|
|
|
|
|
|
|
it 'throws when there is an error on the read stream', ->
|
|
|
|
waitsForPromise =>
|
|
|
|
promise = FileUploadStore._copyUpload(@upload)
|
|
|
|
@readStream.emit 'error'
|
|
|
|
promise
|
|
|
|
.then => throw new Error('It should fail.')
|
|
|
|
.catch (msg) =>
|
|
|
|
expect(msg).not.toBeUndefined()
|
|
|
|
|
|
|
|
it 'throws when there is an error on the write stream', ->
|
|
|
|
waitsForPromise =>
|
|
|
|
promise = FileUploadStore._copyUpload(@upload)
|
|
|
|
@writeStream.emit 'error'
|
|
|
|
promise
|
|
|
|
.then => throw new Error('It should fail.')
|
|
|
|
.catch (msg) =>
|
|
|
|
expect(msg).not.toBeUndefined()
|
|
|
|
|
|
|
|
|