Mailspring/spec/stores/message-store-spec.coffee

190 lines
7.8 KiB
CoffeeScript
Raw Normal View History

_ = require 'underscore'
Thread = require('../../src/flux/models/thread').default
Category = require '../../src/flux/models/category'
Message = require('../../src/flux/models/message').default
FocusedContentStore = require '../../src/flux/stores/focused-content-store'
FocusedPerspectiveStore = require '../../src/flux/stores/focused-perspective-store'
MessageStore = require '../../src/flux/stores/message-store'
DatabaseStore = require '../../src/flux/stores/database-store'
ChangeUnreadTask = require('../../src/flux/tasks/change-unread-task').default
Actions = require '../../src/flux/actions'
testThread = new Thread(id: '123', accountId: TEST_ACCOUNT_ID)
testMessage1 = new Message(id: 'a', body: '123', files: [], accountId: TEST_ACCOUNT_ID)
testMessage2 = new Message(id: 'b', body: '123', files: [], accountId: TEST_ACCOUNT_ID)
testMessage3 = new Message(id: 'c', body: '123', files: [], accountId: TEST_ACCOUNT_ID)
describe "MessageStore", ->
describe "when the receiving focus changes from the FocusedContentStore", ->
beforeEach ->
if MessageStore._onFocusChangedTimer
clearTimeout(MessageStore._onFocusChangedTimer)
MessageStore._onFocusChangedTimer = null
spyOn(MessageStore, '_onApplyFocusChange')
afterEach ->
if MessageStore._onFocusChangedTimer
clearTimeout(MessageStore._onFocusChangedTimer)
MessageStore._onFocusChangedTimer = null
describe "if no change has happened in the last 100ms", ->
it "should apply immediately", ->
FocusedContentStore.trigger(impactsCollection: (c) -> true )
expect(MessageStore._onApplyFocusChange).toHaveBeenCalled()
describe "if a change has happened in the last 100ms", ->
it "should not apply immediately", ->
noop = =>
MessageStore._onFocusChangedTimer = setTimeout(noop, 100)
FocusedContentStore.trigger(impactsCollection: (c) -> true )
expect(MessageStore._onApplyFocusChange).not.toHaveBeenCalled()
it "should apply 100ms after the last focus change and reset", ->
FocusedContentStore.trigger(impactsCollection: (c) -> true )
expect(MessageStore._onApplyFocusChange.callCount).toBe(1)
advanceClock(50)
FocusedContentStore.trigger(impactsCollection: (c) -> true )
expect(MessageStore._onApplyFocusChange.callCount).toBe(1)
advanceClock(50)
FocusedContentStore.trigger(impactsCollection: (c) -> true )
expect(MessageStore._onApplyFocusChange.callCount).toBe(1)
advanceClock(150)
FocusedContentStore.trigger(impactsCollection: (c) -> true )
expect(MessageStore._onApplyFocusChange.callCount).toBe(3)
advanceClock(150)
FocusedContentStore.trigger(impactsCollection: (c) -> true )
expect(MessageStore._onApplyFocusChange.callCount).toBe(5)
describe "items", ->
beforeEach ->
MessageStore._showingHiddenItems = false
MessageStore._items = [
new Message(categories: [new Category(displayName: 'bla'), new Category(name: 'trash')]),
new Message(categories: [new Category(name: 'inbox')]),
new Message(categories: [new Category(name: 'bla'), new Category(name: 'spam')]),
new Message(categories: []),
new Message(categories: [], draft: true),
]
describe "when showing hidden items", ->
it "should return the entire items array", ->
MessageStore._showingHiddenItems = true
expect(MessageStore.items().length).toBe(5)
describe "when in trash or spam", ->
it "should show only the message which are in trash or spam, and drafts", ->
spyOn(FocusedPerspectiveStore, 'current').andReturn({categoriesSharedName: => 'trash'})
expect(MessageStore.items()).toEqual([
MessageStore._items[0],
MessageStore._items[2],
MessageStore._items[4],
])
describe "when in another folder", ->
it "should hide all of the messages which are in trash or spam", ->
spyOn(FocusedPerspectiveStore, 'current').andReturn({categoriesSharedName: => 'inbox'})
expect(MessageStore.items()).toEqual([
MessageStore._items[1],
MessageStore._items[3],
MessageStore._items[4],
])
describe "when applying focus changes", ->
beforeEach ->
MessageStore._lastLoadedThreadId = null
@focus = null
spyOn(FocusedContentStore, 'focused').andCallFake (collection) =>
if collection is 'thread'
@focus
else
null
spyOn(FocusedContentStore, 'focusedId').andCallFake (collection) =>
if collection is 'thread'
@focus?.id
else
null
spyOn(DatabaseStore, 'findAll').andCallFake ->
include: -> @
where: -> @
then: (callback) -> callback([testMessage1, testMessage2])
it "should retrieve the focused thread", ->
@focus = testThread
MessageStore._thread = null
MessageStore._onApplyFocusChange()
expect(DatabaseStore.findAll).toHaveBeenCalled()
expect(DatabaseStore.findAll.mostRecentCall.args[0]).toBe(Message)
describe "when the thread is already focused", ->
it "should do nothing", ->
@focus = testThread
MessageStore._thread = @focus
MessageStore._onApplyFocusChange()
expect(DatabaseStore.findAll).not.toHaveBeenCalled()
describe "when the thread is unread", ->
beforeEach ->
@focus = null
MessageStore._onApplyFocusChange()
testThread.unread = true
spyOn(Actions, 'queueTask')
refactor(env): new NylasEnv global Converted all references of global atom to NylasEnv Temporary rename atom.io find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.io/temporaryAtomIoReplacement/g' atom.config to NylasEnv.config find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.config/NylasEnv.config/g' atom.packages -> NylasEnv.packages atom.commands -> NylasEnv.commands atom.getLoadSettings find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.commands/NylasEnv.commands/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.getLoadSettings/NylasEnv.getLoadSettings/g' More common atom methods find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.styles/NylasEnv.styles/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.emitError/NylasEnv.emitError/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.inSpecMode/NylasEnv.inSpecMode/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.inDevMode/NylasEnv.inDevMode/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.getWindowType/NylasEnv.getWindowType/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.displayWindow/NylasEnv.displayWindow/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.quit/NylasEnv.quit/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.close/NylasEnv.close/g' More atom method changes find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.keymaps/NylasEnv.keymaps/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.hide/NylasEnv.hide/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.getCurrentWindow/NylasEnv.getCurrentWindow/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.menu/NylasEnv.menu/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.getConfigDirPath/NylasEnv.getConfigDirPath/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.isMainWindow/NylasEnv.isMainWindow/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.finishUnload/NylasEnv.finishUnload/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.isWorkWindow/NylasEnv.isWorkWindow/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.showSaveDialog/NylasEnv.showSaveDialog/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.append/NylasEnv.append/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.confirm/NylasEnv.confirm/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.clipboard/NylasEnv.clipboard/g' find -E . -regex ".*\.(coffee|cjsx|js|md|cmd|es6)" -print0 | xargs -0 sed -i "" 's/atom.getVersion/NylasEnv.getVersion/g' More atom renaming Rename atom methods More atom methods Fix grunt config variable Change atom.cmd to N1.cmd Rename atom.coffee and atom.js to nylas-env.coffee nylas-env.js Fix atom global reference in specs manually Fix atom requires Change engine from atom to nylas got rid of global/nylas-env rename to nylas-win-bootup Fix onWindowPropsChanged to onWindowPropsReceived fix nylas-workspace atom-text-editor to nylas-theme-wrap atom-text-editor -> nylas-theme-wrap Replacing atom keyword AtomWindow -> NylasWindow Replace Atom -> N1 Rename atom items nylas.asar -> atom.asar Remove more atom references Remove 6to5 references Remove license exception for atom
2015-11-12 02:25:11 +08:00
spyOn(NylasEnv.config, 'get').andCallFake (key) =>
if key is 'core.reading.markAsReadDelay'
return 600
it "should queue a task to mark the thread as read", ->
@focus = testThread
MessageStore._onApplyFocusChange()
advanceClock(500)
expect(Actions.queueTask).not.toHaveBeenCalled()
advanceClock(500)
expect(Actions.queueTask).toHaveBeenCalled()
perf(*): Add indexes, optimize "shouldAcceptModel", optimize Tasks Summary: Consolidate the smarts from ChangeFolderTask into a generic ChangeMailTask ChangeMailTask: - only makes requests for threads / messages that actually changed - handles incrementing / decrementing locks - writes changes to the database in a single pass, and only writes modified models - encapsulates the undo state that was built into ChangeFolderTask This change means that ChangeLabelsTask enjoys the same "smarts" as ChangeFolderTask. Label changes resulting in no-ops do not create web requests, you can undo label changes and they go back to the correct previous state. Replace "UpdateThreadsTask" and "UpdateNylasObjectsTask" with subclasses based on the same code used for folder/labels This means that the naming and parameter sets are consistent for all thread/message changing tasks. It also means that starring/marking as use the same (tested) business logic and starring 999 already-starred threads doesn't create 999 requests. Go away DraftCountStore - nobody wants you in secondary windows Add "Debug query plans" option which prints out the steps the database is taking. Look for "SCAN" to now you're having a bad time. Make "version" field queryable, when we receive deltas/API response, find all versions of existing models in a single query without loading or parsing the objects Contact: Add index for lookup by email Label: add index for lookup by name Message: Add index for message body join table Test Plan: Run tests Reviewers: evan Reviewed By: evan Differential Revision: https://phab.nylas.com/D1840
2015-08-06 06:53:08 +08:00
expect(Actions.queueTask.mostRecentCall.args[0] instanceof ChangeUnreadTask).toBe(true)
it "should not queue a task to mark the thread as read if the thread is no longer selected 500msec later", ->
@focus = testThread
MessageStore._onApplyFocusChange()
advanceClock(500)
expect(Actions.queueTask).not.toHaveBeenCalled()
@focus = null
MessageStore._onApplyFocusChange()
advanceClock(500)
expect(Actions.queueTask).not.toHaveBeenCalled()
it "should not re-mark the thread as read when made unread", ->
@focus = testThread
testThread.unread = false
MessageStore._onApplyFocusChange()
advanceClock(500)
expect(Actions.queueTask).not.toHaveBeenCalled()
# This simulates a DB change or some attribute changing on the
# thread.
testThread.unread = true
MessageStore._fetchFromCache()
advanceClock(500)
expect(Actions.queueTask).not.toHaveBeenCalled()
describe "when toggling expansion of all messages", ->
beforeEach ->
MessageStore._items = [testMessage1, testMessage2, testMessage3]
spyOn(MessageStore, '_fetchExpandedAttachments')
it 'should expand all when at default state', ->
MessageStore._itemsExpanded = {c: 'default'}
Actions.toggleAllMessagesExpanded()
expect(MessageStore._itemsExpanded).toEqual a: 'explicit', b: 'explicit', c: 'explicit'
it 'should expand all when at least one item is collapsed', ->
MessageStore._itemsExpanded = {b: 'explicit', c: 'explicit'}
Actions.toggleAllMessagesExpanded()
expect(MessageStore._itemsExpanded).toEqual a: 'explicit', b: 'explicit', c: 'explicit'
it 'should collapse all except the latest message when all expanded', ->
MessageStore._itemsExpanded = {a: 'explicit', b: 'explicit', c: 'explicit'}
Actions.toggleAllMessagesExpanded()
expect(MessageStore._itemsExpanded).toEqual c: 'explicit'