mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-09-08 13:44:53 +08:00
test(folders): adding specs for changing folders and labels
Summary: ChangeLabelsTask specs adding change folders task Adding tests for ChangeFolderTask Test Plan: edgehill --test Reviewers: bengotow Reviewed By: bengotow Differential Revision: https://phab.nylas.com/D1806
This commit is contained in:
parent
83197fabd7
commit
b3f7e40588
5 changed files with 459 additions and 37 deletions
263
spec-nylas/tasks/change-folder-task-spec.coffee
Normal file
263
spec-nylas/tasks/change-folder-task-spec.coffee
Normal file
|
@ -0,0 +1,263 @@
|
|||
_ = require 'underscore'
|
||||
Folder = require '../../src/flux/models/folder'
|
||||
Thread = require '../../src/flux/models/thread'
|
||||
Message = require '../../src/flux/models/message'
|
||||
Actions = require '../../src/flux/actions'
|
||||
NylasAPI = require '../../src/flux/nylas-api'
|
||||
DatabaseStore = require '../../src/flux/stores/database-store'
|
||||
ChangeFolderTask = require '../../src/flux/tasks/change-folder-task'
|
||||
|
||||
{APIError} = require '../../src/flux/errors'
|
||||
{Utils} = require '../../src/flux/models/utils'
|
||||
|
||||
testFolders = {}
|
||||
testThreads = {}
|
||||
testMessages = {}
|
||||
|
||||
describe "ChangeFolderTask", ->
|
||||
beforeEach ->
|
||||
spyOn(DatabaseStore, 'persistModel').andCallFake -> Promise.resolve()
|
||||
spyOn(DatabaseStore, 'persistModels').andCallFake -> Promise.resolve()
|
||||
spyOn(DatabaseStore, 'find').andCallFake (klass, id) =>
|
||||
if klass is Thread
|
||||
Promise.resolve(testThreads[id])
|
||||
else if klass is Message
|
||||
Promise.resolve(testMessages[id])
|
||||
else if klass is Folder
|
||||
Promise.resolve(testFolders[id])
|
||||
else
|
||||
throw new Error("Not stubbed!")
|
||||
|
||||
spyOn(DatabaseStore, 'findAll').andCallFake (klass, finder) =>
|
||||
if klass is Message
|
||||
Promise.resolve(_.values(testMessages))
|
||||
else if klass is Thread
|
||||
Promise.resolve(_.values(testThreads))
|
||||
else if klass is Folder
|
||||
Promise.resolve(_.values(testFolders))
|
||||
else
|
||||
throw new Error("Not stubbed!")
|
||||
|
||||
testFolders = @testFolders =
|
||||
"f1": new Folder({name: 'inbox', id: 'f1', displayName: "INBOX"}),
|
||||
"f2": new Folder({name: 'drafts', id: 'f2', displayName: "MyDrafts"})
|
||||
"f3": new Folder({name: null, id: 'f3', displayName: "My Folder"})
|
||||
|
||||
testThreads = @testThreads =
|
||||
't1': new Thread(id: 't1', folders: [@testFolders['f1']])
|
||||
't2': new Thread(id: 't2', folders: _.values(@testFolders))
|
||||
't3': new Thread(id: 't3', folders: [@testFolders['f2'], @testFolders['f3']])
|
||||
|
||||
testMessages = @testMessages =
|
||||
'm1': new Message(id: 'm1', folder: @testFolders['f1'])
|
||||
'm2': new Message(id: 'm2', folder: @testFolders['f2'])
|
||||
'm3': new Message(id: 'm3', folder: @testFolders['f3'])
|
||||
|
||||
@basicThreadTask = new ChangeFolderTask
|
||||
folderOrId: "f1"
|
||||
threadIds: ['t1']
|
||||
|
||||
@basicMessageTask = new ChangeFolderTask
|
||||
folderOrId: @testFolders['f2']
|
||||
messageIds: ['m1']
|
||||
|
||||
describe "shouldWaitForTask", ->
|
||||
it "should return true if another, older ChangeFolderTask involves the same threads", ->
|
||||
a = new ChangeFolderTask(threadIds: ['t1', 't2', 't3'])
|
||||
a.creationDate = new Date(1000)
|
||||
b = new ChangeFolderTask(threadIds: ['t3', 't4', 't7'])
|
||||
b.creationDate = new Date(2000)
|
||||
c = new ChangeFolderTask(threadIds: ['t0', 't7'])
|
||||
c.creationDate = new Date(3000)
|
||||
expect(a.shouldWaitForTask(b)).toEqual(false)
|
||||
expect(a.shouldWaitForTask(c)).toEqual(false)
|
||||
expect(b.shouldWaitForTask(a)).toEqual(true)
|
||||
expect(c.shouldWaitForTask(a)).toEqual(false)
|
||||
expect(c.shouldWaitForTask(b)).toEqual(true)
|
||||
|
||||
describe "performLocal", ->
|
||||
it "should throw an exception if task has not been given a folder", ->
|
||||
badTasks = [
|
||||
new ChangeFolderTask(),
|
||||
new ChangeFolderTask(threadIds: [123]),
|
||||
new ChangeFolderTask(threadIds: [123], messageIds: ["foo"]),
|
||||
new ChangeFolderTask(threadIds: "Thread"),
|
||||
]
|
||||
goodTasks = [
|
||||
new ChangeFolderTask(
|
||||
folderOrId: 'f2'
|
||||
threadIds: ['t1', 't2']
|
||||
)
|
||||
new ChangeFolderTask(
|
||||
folderOrId: @testFolders['f2']
|
||||
messageIds: ['m1']
|
||||
)
|
||||
]
|
||||
caught = []
|
||||
succeeded = []
|
||||
|
||||
runs ->
|
||||
[].concat(badTasks, goodTasks).forEach (task) ->
|
||||
task.performLocal()
|
||||
.then -> succeeded.push(task)
|
||||
.catch (err) -> caught.push(task)
|
||||
waitsFor ->
|
||||
succeeded.length + caught.length == 6
|
||||
runs ->
|
||||
expect(caught.length).toEqual(badTasks.length)
|
||||
expect(succeeded.length).toEqual(goodTasks.length)
|
||||
|
||||
it "throws an error if an undo task isn't passed undo data", ->
|
||||
t = new ChangeFolderTask
|
||||
folderOrId: 'f1'
|
||||
threadIds: ['t1', 't2']
|
||||
t._isUndoTask = true
|
||||
waitsForPromise ->
|
||||
t.performLocal().catch (error) ->
|
||||
expect(error.message).toBe "Must pass an `undoData` to rollback folder changes"
|
||||
it "throws an error if an undo task isn't passed undo data", ->
|
||||
t = new ChangeFolderTask
|
||||
folderOrId: 'f1'
|
||||
undoData: {}
|
||||
threadIds: ['t1', 't2']
|
||||
t._isUndoTask = true
|
||||
waitsForPromise ->
|
||||
t.performLocal().catch (error) ->
|
||||
expect(error.message).toBe "Must pass an `undoData` to rollback folder changes"
|
||||
|
||||
it 'finds the folder to add by id', ->
|
||||
waitsForPromise =>
|
||||
@basicThreadTask.collectCategories().then (categories) =>
|
||||
expect(categories.folder).toEqual @testFolders['f1']
|
||||
|
||||
it 'finds the folder to add by folder object', ->
|
||||
waitsForPromise =>
|
||||
@basicMessageTask.collectCategories().then (categories) =>
|
||||
expect(categories.folder).toEqual @testFolders['f2']
|
||||
|
||||
it 'increments optimistic changes', ->
|
||||
spyOn(@basicThreadTask, "localUpdateThread").andReturn Promise.resolve()
|
||||
spyOn(NylasAPI, "incrementOptimisticChangeCount")
|
||||
@basicThreadTask.performLocal().then ->
|
||||
expect(NylasAPI.incrementOptimisticChangeCount)
|
||||
.toHaveBeenCalledWith(Thread, 't1')
|
||||
|
||||
it 'decrements optimistic changes if reverting', ->
|
||||
spyOn(@basicThreadTask, "localUpdateThread").andReturn Promise.resolve()
|
||||
spyOn(NylasAPI, "decrementOptimisticChangeCount")
|
||||
@basicThreadTask.performLocal(reverting: true).then ->
|
||||
expect(NylasAPI.decrementOptimisticChangeCount)
|
||||
.toHaveBeenCalledWith(Thread, 't1')
|
||||
|
||||
describe "When it's a Regular Task", ->
|
||||
it 'sets undo data and ignores messages that already have the folder we want', ->
|
||||
@basicThreadTask.performLocal().then =>
|
||||
expectedData =
|
||||
originalMessageFolder:
|
||||
m2: @testFolders['f2']
|
||||
m3: @testFolders['f3']
|
||||
originalThreadFolders:
|
||||
t1: [@testFolders['f1']]
|
||||
expect(expectedData).toEqual @basicThreadTask.undoData
|
||||
|
||||
it 'updates a thread with the new folder', ->
|
||||
@basicThreadTask.performLocal().then =>
|
||||
thread = DatabaseStore.persistModel.calls[0].args[0]
|
||||
expect(thread.folders).toEqual [@testFolders['f1']]
|
||||
|
||||
it "updates a thread's messages with the new folder and ignores messages that already have the same folder", ->
|
||||
# Our stub of DatabaseStore.findAll ignores the scoping parameter.
|
||||
# We simply return all messages.
|
||||
|
||||
expectedFolder = @testFolders['f1']
|
||||
@basicThreadTask.performLocal().then ->
|
||||
messages = DatabaseStore.persistModels.calls[0].args[0]
|
||||
# We expect 2 because 1 of our 3 messages already has the folder
|
||||
# we want.
|
||||
expect(messages.length).toBe 2
|
||||
for message in messages
|
||||
expect(message.folder).toEqual expectedFolder
|
||||
|
||||
## MORE TESTS COMING SOON
|
||||
|
||||
# describe "When it's an Undo Task", ->
|
||||
#
|
||||
# xit "doesn't botter updating the message if it already has the correct folder", ->
|
||||
# @testMessages['m4'] =
|
||||
# new Message(id: 'm4', folder: [@testFolders['f1'], @testFolders['f2']])
|
||||
# @testMessages['m5'] =
|
||||
# new Message(id: 'm5', folder: [])
|
||||
#
|
||||
# expectedFolder = [@testFolders['f1'], @testFolders['f2']]
|
||||
# @basicThreadTask.performLocal().then =>
|
||||
# messages = DatabaseStore.persistModels.calls[0].args[0]
|
||||
# expect(messages.length).toBe 4
|
||||
# for message in messages
|
||||
# expect(message.folder).toEqual expectedFolder
|
||||
# expect(@testMessages['m4'] not in messages).toBe true
|
||||
#
|
||||
# xit 'updates a message with the new folder on a message task', ->
|
||||
# expectedFolder = [@testFolders['f1'], @testFolders['f2']]
|
||||
# @basicMessageTask.performLocal().then ->
|
||||
# thread = DatabaseStore.persistModel.calls[0].args[0]
|
||||
# expect(thread.folder).toEqual expectedFolder
|
||||
#
|
||||
# xit 'saves the new folder set to an instance variable on the task so performRemote can access it later', ->
|
||||
# expectedFolder = [@testFolders['f1'], @testFolders['f2']]
|
||||
# @basicThreadTask.performLocal().then =>
|
||||
# expect(@basicThreadTask._newFolder['t1']).toEqual expectedFolder
|
||||
#
|
||||
# xdescribe 'performRemote', ->
|
||||
# beforeEach ->
|
||||
# spyOn(NylasAPI, "makeRequest").andCallFake (options) ->
|
||||
# options.beforeProcessing?(options.body)
|
||||
# return Promise.resolve()
|
||||
#
|
||||
# @multiThreadTask = new ChangeFolderTask
|
||||
# folderOrId: ["f1", "f2"]
|
||||
# folderToRemove: ["f3"]
|
||||
# threadIds: ['t1', 't2']
|
||||
#
|
||||
# @multiMessageTask = new ChangeFolderTask
|
||||
# folderOrId: ["f1", "f2"]
|
||||
# folderToRemove: ["f3"]
|
||||
# messageIds: ['m1', 'm2']
|
||||
#
|
||||
# expectedFolder = [@testFolders['f1'], @testFolders['f2']]
|
||||
# @multiThreadTask._newFolder['t1'] = expectedFolder
|
||||
# @multiThreadTask._newFolder['t2'] = expectedFolder
|
||||
# @multiMessageTask._newFolder['m1'] = expectedFolder
|
||||
# @multiMessageTask._newFolder['m2'] = expectedFolder
|
||||
#
|
||||
# it 'makes a new request object for each object', ->
|
||||
# @multiThreadTask.performRemote().then ->
|
||||
# expect(NylasAPI.makeRequest.calls.length).toBe 2
|
||||
#
|
||||
# it 'decrements the optimistic change count on each request', ->
|
||||
# spyOn(NylasAPI, "decrementOptimisticChangeCount")
|
||||
# @multiThreadTask.performRemote().then ->
|
||||
# klass = NylasAPI.decrementOptimisticChangeCount.calls[0].args[0]
|
||||
# expect(NylasAPI.decrementOptimisticChangeCount.calls.length).toBe 2
|
||||
# expect(klass).toBe Thread
|
||||
#
|
||||
# it 'decrements the optimistic change for messages too', ->
|
||||
# spyOn(NylasAPI, "decrementOptimisticChangeCount")
|
||||
# @multiMessageTask.performRemote().then ->
|
||||
# klass = NylasAPI.decrementOptimisticChangeCount.calls[0].args[0]
|
||||
# expect(NylasAPI.decrementOptimisticChangeCount.calls.length).toBe 2
|
||||
# expect(klass).toBe Message
|
||||
#
|
||||
# it 'properly passes the folder IDs to the body', ->
|
||||
# @multiThreadTask.performRemote().then ->
|
||||
# opts = NylasAPI.makeRequest.calls[0].args[0]
|
||||
# expect(opts.body).toEqual folder: ['f1', 'f2']
|
||||
#
|
||||
# it 'gets the correct endpoint for the thread tasks', ->
|
||||
# @multiThreadTask.performRemote().then ->
|
||||
# opts = NylasAPI.makeRequest.calls[0].args[0]
|
||||
# expect(opts.path).toEqual "/n/nsid/threads/t1"
|
||||
#
|
||||
# it 'gets the correct endpoint for the message tasks', ->
|
||||
# @multiMessageTask.performRemote().then ->
|
||||
# opts = NylasAPI.makeRequest.calls[0].args[0]
|
||||
# expect(opts.path).toEqual "/n/nsid/messages/m1"
|
|
@ -10,9 +10,9 @@ ChangeLabelsTask = require '../../src/flux/tasks/change-labels-task'
|
|||
{APIError} = require '../../src/flux/errors'
|
||||
{Utils} = require '../../src/flux/models/utils'
|
||||
|
||||
testLabels = null
|
||||
testThread = null
|
||||
testMessage = null
|
||||
testLabels = {}
|
||||
testThreads = {}
|
||||
testMessages = {}
|
||||
|
||||
describe "ChangeLabelsTask", ->
|
||||
beforeEach ->
|
||||
|
@ -20,9 +20,9 @@ describe "ChangeLabelsTask", ->
|
|||
spyOn(DatabaseStore, 'persistModels').andCallFake -> Promise.resolve()
|
||||
spyOn(DatabaseStore, 'find').andCallFake (klass, id) =>
|
||||
if klass is Thread
|
||||
Promise.resolve(testThread)
|
||||
Promise.resolve(testThreads[id])
|
||||
else if klass is Message
|
||||
Promise.resolve(testMessage)
|
||||
Promise.resolve(testMessages[id])
|
||||
else if klass is Label
|
||||
Promise.resolve(testLabels[id])
|
||||
else
|
||||
|
@ -30,10 +30,39 @@ describe "ChangeLabelsTask", ->
|
|||
|
||||
spyOn(DatabaseStore, 'findAll').andCallFake (klass, finder) =>
|
||||
if klass is Message
|
||||
Promise.resolve([testMessage])
|
||||
Promise.resolve(_.values(testMessages))
|
||||
else if klass is Thread
|
||||
Promise.resolve(_.values(testThreads))
|
||||
else if klass is Label
|
||||
Promise.resolve(_.values(testLabels))
|
||||
else
|
||||
throw new Error("Not stubbed!")
|
||||
|
||||
testLabels = @testLabels =
|
||||
"l1": new Label({name: 'inbox', id: 'l1', displayName: "INBOX"}),
|
||||
"l2": new Label({name: 'drafts', id: 'l2', displayName: "MyDrafts"})
|
||||
"l3": new Label({name: null, id: 'l3', displayName: "My Label"})
|
||||
|
||||
testThreads = @testThreads =
|
||||
't1': new Thread(id: 't1', labels: [@testLabels['l1']])
|
||||
't2': new Thread(id: 't2', labels: _.values(@testLabels))
|
||||
't3': new Thread(id: 't3', labels: [@testLabels['l2'], @testLabels['l3']])
|
||||
|
||||
testMessages = @testMessages =
|
||||
'm1': new Message(id: 'm1', labels: [@testLabels['l1']])
|
||||
'm2': new Message(id: 'm2', labels: _.values(@testLabels))
|
||||
'm3': new Message(id: 'm3', labels: [@testLabels['l2'], @testLabels['l3']])
|
||||
|
||||
@basicThreadTask = new ChangeLabelsTask
|
||||
labelsToAdd: ["l1", "l2"]
|
||||
labelsToRemove: ["l3"]
|
||||
threadIds: ['t1']
|
||||
|
||||
@basicMessageTask = new ChangeLabelsTask
|
||||
labelsToAdd: ["l1", "l2"]
|
||||
labelsToRemove: ["l3"]
|
||||
messageIds: ['m1']
|
||||
|
||||
describe "shouldWaitForTask", ->
|
||||
it "should return true if another, older ChangeLabelsTask involves the same threads", ->
|
||||
a = new ChangeLabelsTask(threadIds: ['t1', 't2', 't3'])
|
||||
|
@ -49,21 +78,6 @@ describe "ChangeLabelsTask", ->
|
|||
expect(c.shouldWaitForTask(b)).toEqual(true)
|
||||
|
||||
describe "performLocal", ->
|
||||
beforeEach ->
|
||||
|
||||
testLabels =
|
||||
"l1": new Label({name: 'inbox', id: 'l1', displayName: "INBOX"}),
|
||||
"l2": new Label({name: 'drafts', id: 'l2', displayName: "MyDrafts"})
|
||||
"l3": new Label({name: null, id: 'l3', displayName: "My Label"})
|
||||
|
||||
testThread = new Thread
|
||||
id: 'thread-id'
|
||||
labels: _.values(testLabels)
|
||||
|
||||
testMessage = new Message
|
||||
id: 'message-id'
|
||||
labels: _.values(testLabels)
|
||||
|
||||
it "should throw an exception if task has not been given a thread", ->
|
||||
badTasks = [
|
||||
new ChangeLabelsTask(),
|
||||
|
@ -75,12 +89,12 @@ describe "ChangeLabelsTask", ->
|
|||
new ChangeLabelsTask(
|
||||
labelsToAdd: ['l2']
|
||||
labelsToRemove: ['l1']
|
||||
threadIds: [testThread.id]
|
||||
threadIds: ['t1']
|
||||
)
|
||||
new ChangeLabelsTask(
|
||||
labelsToAdd: ['l2']
|
||||
labelsToRemove: []
|
||||
messageIds: [testMessage.id]
|
||||
messageIds: ['m1']
|
||||
)
|
||||
]
|
||||
caught = []
|
||||
|
@ -97,10 +111,150 @@ describe "ChangeLabelsTask", ->
|
|||
expect(caught.length).toEqual(badTasks.length)
|
||||
expect(succeeded.length).toEqual(goodTasks.length)
|
||||
|
||||
it 'adds labels to a Thread', ->
|
||||
it 'finds all of the labels to add by id', ->
|
||||
waitsForPromise =>
|
||||
@basicThreadTask.collectCategories().then (categories) =>
|
||||
expect(categories.labelsToAdd).toEqual [@testLabels['l1'], @testLabels['l2']]
|
||||
expect(categories.labelsToRemove).toEqual [@testLabels['l3']]
|
||||
|
||||
it 'adds labels to a Message', ->
|
||||
it 'finds all of the labels to add by object', ->
|
||||
task = new ChangeLabelsTask
|
||||
labelsToAdd: [@testLabels['l1'], @testLabels['l2']]
|
||||
labelsToRemove: []
|
||||
threadIds: ['t1']
|
||||
|
||||
it 'removes labels from a Thread', ->
|
||||
waitsForPromise =>
|
||||
task.collectCategories().then (categories) =>
|
||||
expect(categories.labelsToAdd).toEqual [@testLabels['l1'], @testLabels['l2']]
|
||||
expect(categories.labelsToRemove).toEqual []
|
||||
|
||||
it 'removes labels from a Message', ->
|
||||
it 'increments optimistic changes', ->
|
||||
spyOn(@basicThreadTask, "localUpdateThread").andReturn Promise.resolve()
|
||||
spyOn(NylasAPI, "incrementOptimisticChangeCount")
|
||||
@basicThreadTask.performLocal().then ->
|
||||
expect(NylasAPI.incrementOptimisticChangeCount)
|
||||
.toHaveBeenCalledWith(Thread, 't1')
|
||||
|
||||
it 'decrements optimistic changes if reverting', ->
|
||||
spyOn(@basicThreadTask, "localUpdateThread").andReturn Promise.resolve()
|
||||
spyOn(NylasAPI, "decrementOptimisticChangeCount")
|
||||
@basicThreadTask.performLocal(reverting: true).then ->
|
||||
expect(NylasAPI.decrementOptimisticChangeCount)
|
||||
.toHaveBeenCalledWith(Thread, 't1')
|
||||
|
||||
describe 'when creating a _newLabelSet', ->
|
||||
it 'properly adds labels', ->
|
||||
t1 = @testThreads['t1']
|
||||
toAdd = [@testLabels['l1'], @testLabels['l2']]
|
||||
out = @basicThreadTask._newLabelSet(t1, labelsToAdd: toAdd)
|
||||
expect(out).toEqual toAdd
|
||||
|
||||
it 'properly removes labels', ->
|
||||
t3 = @testThreads['t3']
|
||||
toRemove = [@testLabels['l1'], @testLabels['l2']]
|
||||
out = @basicThreadTask._newLabelSet(t3, labelsToRemove: toRemove)
|
||||
expect(out).toEqual [@testLabels['l3']]
|
||||
|
||||
it 'properly adds and removes labels', ->
|
||||
t1 = @testThreads['t1']
|
||||
toAdd = [@testLabels['l1'], @testLabels['l2']]
|
||||
toRemove = [@testLabels['l2'], @testLabels['l3']]
|
||||
out = @basicThreadTask._newLabelSet(t1, labelsToAdd: toAdd, labelsToRemove: toRemove)
|
||||
expect(out).toEqual [@testLabels['l1']]
|
||||
|
||||
it 'updates a thread with the new labels', ->
|
||||
expectedLabels = [@testLabels['l1'], @testLabels['l2']]
|
||||
@basicThreadTask.performLocal().then ->
|
||||
thread = DatabaseStore.persistModel.calls[0].args[0]
|
||||
expect(thread.labels).toEqual expectedLabels
|
||||
|
||||
it "updates a thread's messages with the new labels", ->
|
||||
# Our stub of DatabaseStore.findAll ignores the scoping parameter.
|
||||
# We simply return all messages.
|
||||
|
||||
expectedLabels = [@testLabels['l1'], @testLabels['l2']]
|
||||
@basicThreadTask.performLocal().then ->
|
||||
messages = DatabaseStore.persistModels.calls[0].args[0]
|
||||
expect(messages.length).toBe 3
|
||||
for message in messages
|
||||
expect(message.labels).toEqual expectedLabels
|
||||
|
||||
it "doesn't botter updating the message if it already has the correct labels", ->
|
||||
@testMessages['m4'] =
|
||||
new Message(id: 'm4', labels: [@testLabels['l1'], @testLabels['l2']])
|
||||
@testMessages['m5'] =
|
||||
new Message(id: 'm5', labels: [])
|
||||
|
||||
expectedLabels = [@testLabels['l1'], @testLabels['l2']]
|
||||
@basicThreadTask.performLocal().then =>
|
||||
messages = DatabaseStore.persistModels.calls[0].args[0]
|
||||
expect(messages.length).toBe 4
|
||||
for message in messages
|
||||
expect(message.labels).toEqual expectedLabels
|
||||
expect(@testMessages['m4'] not in messages).toBe true
|
||||
|
||||
it 'updates a message with the new labels on a message task', ->
|
||||
expectedLabels = [@testLabels['l1'], @testLabels['l2']]
|
||||
@basicMessageTask.performLocal().then ->
|
||||
thread = DatabaseStore.persistModel.calls[0].args[0]
|
||||
expect(thread.labels).toEqual expectedLabels
|
||||
|
||||
it 'saves the new label set to an instance variable on the task so performRemote can access it later', ->
|
||||
expectedLabels = [@testLabels['l1'], @testLabels['l2']]
|
||||
@basicThreadTask.performLocal().then =>
|
||||
expect(@basicThreadTask._newLabels['t1']).toEqual expectedLabels
|
||||
|
||||
describe 'performRemote', ->
|
||||
beforeEach ->
|
||||
spyOn(NylasAPI, "makeRequest").andCallFake (options) ->
|
||||
options.beforeProcessing?(options.body)
|
||||
return Promise.resolve()
|
||||
|
||||
@multiThreadTask = new ChangeLabelsTask
|
||||
labelsToAdd: ["l1", "l2"]
|
||||
labelsToRemove: ["l3"]
|
||||
threadIds: ['t1', 't2']
|
||||
|
||||
@multiMessageTask = new ChangeLabelsTask
|
||||
labelsToAdd: ["l1", "l2"]
|
||||
labelsToRemove: ["l3"]
|
||||
messageIds: ['m1', 'm2']
|
||||
|
||||
expectedLabels = [@testLabels['l1'], @testLabels['l2']]
|
||||
@multiThreadTask._newLabels['t1'] = expectedLabels
|
||||
@multiThreadTask._newLabels['t2'] = expectedLabels
|
||||
@multiMessageTask._newLabels['m1'] = expectedLabels
|
||||
@multiMessageTask._newLabels['m2'] = expectedLabels
|
||||
|
||||
it 'makes a new request object for each object', ->
|
||||
@multiThreadTask.performRemote().then ->
|
||||
expect(NylasAPI.makeRequest.calls.length).toBe 2
|
||||
|
||||
it 'decrements the optimistic change count on each request', ->
|
||||
spyOn(NylasAPI, "decrementOptimisticChangeCount")
|
||||
@multiThreadTask.performRemote().then ->
|
||||
klass = NylasAPI.decrementOptimisticChangeCount.calls[0].args[0]
|
||||
expect(NylasAPI.decrementOptimisticChangeCount.calls.length).toBe 2
|
||||
expect(klass).toBe Thread
|
||||
|
||||
it 'decrements the optimistic change for messages too', ->
|
||||
spyOn(NylasAPI, "decrementOptimisticChangeCount")
|
||||
@multiMessageTask.performRemote().then ->
|
||||
klass = NylasAPI.decrementOptimisticChangeCount.calls[0].args[0]
|
||||
expect(NylasAPI.decrementOptimisticChangeCount.calls.length).toBe 2
|
||||
expect(klass).toBe Message
|
||||
|
||||
it 'properly passes the label IDs to the body', ->
|
||||
@multiThreadTask.performRemote().then ->
|
||||
opts = NylasAPI.makeRequest.calls[0].args[0]
|
||||
expect(opts.body).toEqual labels: ['l1', 'l2']
|
||||
|
||||
it 'gets the correct endpoint for the thread tasks', ->
|
||||
@multiThreadTask.performRemote().then ->
|
||||
opts = NylasAPI.makeRequest.calls[0].args[0]
|
||||
expect(opts.path).toEqual "/n/nsid/threads/t1"
|
||||
|
||||
it 'gets the correct endpoint for the message tasks', ->
|
||||
@multiMessageTask.performRemote().then ->
|
||||
opts = NylasAPI.makeRequest.calls[0].args[0]
|
||||
expect(opts.path).toEqual "/n/nsid/messages/m1"
|
||||
|
|
|
@ -34,6 +34,11 @@ class ChangeCategoryTask extends Task
|
|||
if @threadIds.length > 0 then return "threads"
|
||||
else if @messageIds.length > 0 then return "messages"
|
||||
|
||||
_klass: ->
|
||||
if @threadIds.length > 0 then Klass = Thread
|
||||
else if @messageIds.length > 0 then Klass = Message
|
||||
return Klass
|
||||
|
||||
performLocal: ({reverting} = {}) ->
|
||||
@_isReverting = reverting
|
||||
err = @verifyArgs()
|
||||
|
@ -41,17 +46,15 @@ class ChangeCategoryTask extends Task
|
|||
|
||||
@collectCategories().then (categories) =>
|
||||
promises = @objectIds.map (objectId) =>
|
||||
if @threadIds.length > 0 then Klass = Thread
|
||||
else if @messageIds.length > 0 then Klass = Message
|
||||
DatabaseStore.find(Klass, objectId).then (object) =>
|
||||
DatabaseStore.find(@_klass(), objectId).then (object) =>
|
||||
# Mark that we are optimistically changing this model. This will prevent
|
||||
# inbound delta syncs from changing it back to it's old state. Only the
|
||||
# operation that changes `optimisticChangeCount` back to zero will
|
||||
# apply the server's version of the model to our cache.
|
||||
if reverting is true
|
||||
NylasAPI.decrementOptimisticChangeCount(Klass, object.id)
|
||||
NylasAPI.decrementOptimisticChangeCount(@_klass(), object.id)
|
||||
else
|
||||
NylasAPI.incrementOptimisticChangeCount(Klass, object.id)
|
||||
NylasAPI.incrementOptimisticChangeCount(@_klass(), object.id)
|
||||
|
||||
if @threadIds.length > 0
|
||||
return @localUpdateThread(object, categories)
|
||||
|
@ -68,8 +71,8 @@ class ChangeCategoryTask extends Task
|
|||
method: 'PUT'
|
||||
body: @requestBody(id)
|
||||
returnsModel: true
|
||||
beforeProcessing: (body) ->
|
||||
NylasAPI.decrementOptimisticChangeCount(Thread, id)
|
||||
beforeProcessing: (body) =>
|
||||
NylasAPI.decrementOptimisticChangeCount(@_klass(), id)
|
||||
body
|
||||
|
||||
Promise.all(promises)
|
||||
|
|
|
@ -142,7 +142,7 @@ class ChangeFolderTask extends ChangeCategoryTask
|
|||
if not @folderOrId
|
||||
return Promise.reject(new Error("Must specify a `folder`"))
|
||||
|
||||
if @_isUndoTask and not @undoData
|
||||
if @_isUndoTask and (not @undoData or Object.keys(@undoData).length is 0)
|
||||
return Promise.reject(new Error("Must pass an `undoData` to rollback folder changes"))
|
||||
|
||||
return super()
|
||||
|
|
|
@ -72,8 +72,10 @@ class ChangeLabelsTask extends ChangeCategoryTask
|
|||
messagesToSave = []
|
||||
newIds = newLabels.map (l) -> l.id
|
||||
for message in messages
|
||||
existing = (message.labels ? []).map (l) -> l.id
|
||||
if _.intersection(existing, newIds).length isnt existing.length
|
||||
existingIds = (message.labels ? []).map (l) -> l.id
|
||||
if _.isEqual(existingIds, newIds)
|
||||
continue
|
||||
else
|
||||
message.labels = newLabels
|
||||
messagesToSave.push(message)
|
||||
DatabaseStore.persistModels(messagesToSave)
|
||||
|
|
Loading…
Add table
Reference in a new issue