mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-09-24 17:26:06 +08:00
176 lines
6.3 KiB
CoffeeScript
176 lines
6.3 KiB
CoffeeScript
|
Actions = require '../../src/flux/actions'
|
||
|
TaskStore = require '../../src/flux/stores/task-store'
|
||
|
Task = require '../../src/flux/tasks/task'
|
||
|
|
||
|
class TaskSubclassA extends Task
|
||
|
constructor: (val) -> @aProp = val
|
||
|
|
||
|
class TaskSubclassB extends Task
|
||
|
constructor: (val) -> @bProp = val
|
||
|
|
||
|
describe "TaskStore", ->
|
||
|
beforeEach ->
|
||
|
@task = @taskA = new Task
|
||
|
@taskB = new Task
|
||
|
@task.shouldWaitForTask = -> false
|
||
|
@taskWithDependencies = new Task
|
||
|
@taskWithDependencies.shouldWaitForTask = (other) => (other == @taskA)
|
||
|
|
||
|
afterEach ->
|
||
|
TaskStore.reset()
|
||
|
|
||
|
describe "queueTask", =>
|
||
|
it "should be called whenever Actions.queueTask is fired", ->
|
||
|
# TODO: Turns out this is very difficult to test because you can't stub out
|
||
|
# store methods that are registered as listeners.
|
||
|
|
||
|
it "should call the task's performLocal function", ->
|
||
|
spyOn(@task, 'performLocal').andCallFake -> new Promise (resolve, reject) -> @
|
||
|
TaskStore._onQueueTask(@task)
|
||
|
expect(@task.performLocal).toHaveBeenCalled()
|
||
|
|
||
|
it "should immediately put the task on the pending list", ->
|
||
|
expect(TaskStore.pendingTasks().length).toBe(0)
|
||
|
TaskStore._onQueueTask(@task)
|
||
|
expect(TaskStore.pendingTasks().length).toBe(1)
|
||
|
expect(TaskStore.queuedTasks().length).toBe(0)
|
||
|
|
||
|
it "should move the task to the queue list when performLocal has finished", ->
|
||
|
expect(TaskStore.queuedTasks().length).toBe(0)
|
||
|
runs ->
|
||
|
spyOn(@task, 'performLocal').andCallFake ->
|
||
|
new Promise (resolve, reject) ->
|
||
|
setTimeout(resolve, 1)
|
||
|
spyOn(TaskStore, 'performNextTask')
|
||
|
TaskStore._onQueueTask(@task)
|
||
|
advanceClock(2)
|
||
|
waitsFor ->
|
||
|
TaskStore.queuedTasks().length == 1
|
||
|
runs ->
|
||
|
expect(TaskStore.queuedTasks().length).toBe(1)
|
||
|
expect(TaskStore.pendingTasks().length).toBe(0)
|
||
|
|
||
|
describe "abortTask", =>
|
||
|
beforeEach ->
|
||
|
@a1 = new TaskSubclassA('1')
|
||
|
@a2 = new TaskSubclassA('2')
|
||
|
@b1 = new TaskSubclassB('bA')
|
||
|
@b2 = new TaskSubclassB('bB')
|
||
|
|
||
|
TaskStore._queue = [@a1, @b2]
|
||
|
TaskStore._pending = [@a2, @b1]
|
||
|
|
||
|
it "should remove tasks whose JSON match the criteria", ->
|
||
|
TaskStore._onAbortTask({object: 'TaskSubclassA'})
|
||
|
expect(TaskStore._queue).toEqual([@b2])
|
||
|
expect(TaskStore._pending).toEqual([@b1])
|
||
|
|
||
|
TaskStore._onAbortTask({bProp: 'bB'})
|
||
|
expect(TaskStore._queue).toEqual([])
|
||
|
expect(TaskStore._pending).toEqual([@b1])
|
||
|
|
||
|
it "should call cleanup on each removed task", ->
|
||
|
spyOn(@a1, 'cleanup')
|
||
|
TaskStore._onAbortTask({object: 'TaskSubclassA'})
|
||
|
expect(@a1.cleanup).toHaveBeenCalled()
|
||
|
|
||
|
it "should call rollbackLocal on each removed task iff the rollbackLocal flag is passed", ->
|
||
|
spyOn(@a1, 'rollbackLocal')
|
||
|
TaskStore._onAbortTask({aProp: '1'})
|
||
|
expect(@a1.rollbackLocal).toHaveBeenCalled()
|
||
|
|
||
|
spyOn(@a2, 'rollbackLocal')
|
||
|
TaskStore._onAbortTask({aProp: '2'}, {rollbackLocal: false})
|
||
|
expect(@a2.rollbackLocal).not.toHaveBeenCalled()
|
||
|
|
||
|
it "should call abort on each pending removed task", ->
|
||
|
spyOn(@a1, 'abort')
|
||
|
spyOn(@a2, 'abort')
|
||
|
TaskStore._onAbortTask({object: 'TaskSubclassA'})
|
||
|
expect(@a2.abort).toHaveBeenCalled()
|
||
|
expect(@a1.abort).not.toHaveBeenCalled()
|
||
|
|
||
|
|
||
|
describe "canPerformTask", =>
|
||
|
beforeEach ->
|
||
|
TaskStore._queue = [@taskWithDependencies, @taskA]
|
||
|
TaskStore._pending = []
|
||
|
|
||
|
it "should return true if the task provided has no dependencies in the queue", ->
|
||
|
expect(TaskStore.canPerformTask(@taskA)).toBe(true)
|
||
|
|
||
|
it "should return false if the task returns dependencies", ->
|
||
|
expect(TaskStore.canPerformTask(@taskWithDependencies)).toBe(false)
|
||
|
|
||
|
|
||
|
describe "performNextTask", =>
|
||
|
beforeEach ->
|
||
|
TaskStore._queue = [@taskWithDependencies, @taskA, @taskB]
|
||
|
TaskStore._pending = []
|
||
|
|
||
|
it "should remove the first ready task from the queue", ->
|
||
|
expect(TaskStore.canPerformTask(@taskWithDependencies)).toBe(false)
|
||
|
expect(TaskStore.queuedTasks().length).toBe(3)
|
||
|
TaskStore.performNextTask()
|
||
|
expect(TaskStore.queuedTasks().length).toBe(2)
|
||
|
expect(TaskStore.queuedTasks()).toEqual([@taskWithDependencies, @taskB])
|
||
|
|
||
|
it "should add the task to the pending list", ->
|
||
|
TaskStore.performNextTask()
|
||
|
expect(TaskStore.pendingTasks()).toEqual([@taskA])
|
||
|
|
||
|
it "should call the task's performRemote function", ->
|
||
|
spyOn(@taskA, 'performRemote').andReturn(Promise.resolve())
|
||
|
TaskStore.performNextTask()
|
||
|
expect(@taskA.performRemote).toHaveBeenCalled()
|
||
|
|
||
|
describe "when performRemote finishes", ->
|
||
|
beforeEach ->
|
||
|
spyOn(@taskA, 'performRemote').andReturn(Promise.resolve())
|
||
|
|
||
|
it "should clean up the task", ->
|
||
|
spyOn(@taskA, 'cleanup')
|
||
|
waitsForPromise -> TaskStore.performNextTask()
|
||
|
runs ->
|
||
|
expect(@taskA.cleanup).toHaveBeenCalled()
|
||
|
|
||
|
it "should remove the task from the pending list", ->
|
||
|
waitsForPromise -> TaskStore.performNextTask()
|
||
|
runs ->
|
||
|
expect(TaskStore.pendingTasks()).toEqual([])
|
||
|
|
||
|
it "should update the disk cache and perform the next task", ->
|
||
|
spyOn(TaskStore, 'performNextTask').andCallThrough()
|
||
|
spyOn(TaskStore, 'persist').andCallFake (callback) ->
|
||
|
callback() if callback
|
||
|
|
||
|
waitsForPromise -> TaskStore.performNextTask()
|
||
|
runs ->
|
||
|
expect(TaskStore.persist).toHaveBeenCalled()
|
||
|
expect(TaskStore.performNextTask.callCount).toBe(3)
|
||
|
|
||
|
describe "when performRemote finishes with a failure", ->
|
||
|
beforeEach ->
|
||
|
spyOn(TaskStore, '_displayError')
|
||
|
spyOn(@taskA, 'performRemote').andReturn(Promise.reject('An error!'))
|
||
|
|
||
|
describe "when shouldRetry returns true", ->
|
||
|
beforeEach ->
|
||
|
spyOn(@taskA, 'shouldRetry').andReturn(true)
|
||
|
|
||
|
it "should put the task back on the queue", ->
|
||
|
waitsForPromise -> TaskStore.performNextTask()
|
||
|
runs ->
|
||
|
expect(TaskStore.queuedTasks()).toEqual([@taskWithDependencies, @taskB, @taskA])
|
||
|
|
||
|
describe "when shouldRetry returns false", ->
|
||
|
beforeEach ->
|
||
|
spyOn(@taskA, 'shouldRetry').andReturn(false)
|
||
|
|
||
|
it "should roll back the performLocal function and throw out the task", ->
|
||
|
spyOn(@taskA, 'rollbackLocal')
|
||
|
waitsForPromise -> TaskStore.performNextTask()
|
||
|
runs ->
|
||
|
expect(@taskA.rollbackLocal).toHaveBeenCalled()
|
||
|
|