mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-09-22 16:26:08 +08:00
4f34c8403f
Summary: This diff centralizes logic for creating common tasks for things like moving to trash, archive, etc. TaskFactory exposes a set of convenience methods and hides the whole "and also remove the current label" business from the user. This diff also formally separates the concept of "moving to trash" and "archiving" so that "remove" isn't used in an unclear way. I also refactored where selection is managed. Previously you'd fire some action like archiveSelection and it'd clear the selection, but if you selected some items and used another method to archive a few, they were still selected. The selection is now bound to the ModelView as intended, so if items are removed from the modelView, they are removed from it's attached selection. This means that it shouldn't /technically/ be possible to have selected items which are not in view. I haven't refactored the tests yet. They are likely broken... Fix next/prev logic Test Plan: Run tests Reviewers: evan Reviewed By: evan Differential Revision: https://phab.nylas.com/D2157
184 lines
6.7 KiB
CoffeeScript
184 lines
6.7 KiB
CoffeeScript
_ = require 'underscore'
|
|
React = require "react/addons"
|
|
ReactTestUtils = React.addons.TestUtils
|
|
CategoryPicker = require '../lib/category-picker'
|
|
{Popover} = require 'nylas-component-kit'
|
|
|
|
{Utils,
|
|
Label,
|
|
Folder,
|
|
Thread,
|
|
Actions,
|
|
CategoryStore,
|
|
DatabaseStore,
|
|
TaskFactory,
|
|
SyncbackCategoryTask,
|
|
FocusedMailViewStore,
|
|
TaskQueueStatusStore} = require 'nylas-exports'
|
|
|
|
fdescribe 'CategoryPicker', ->
|
|
beforeEach ->
|
|
CategoryStore._categoryCache = {}
|
|
|
|
afterEach ->
|
|
atom.testOrganizationUnit = null
|
|
|
|
setupFor = (organizationUnit) ->
|
|
atom.testOrganizationUnit = organizationUnit
|
|
klass = if organizationUnit is "label" then Label else Folder
|
|
|
|
@inboxCategory = new klass(id: 'id-123', name: 'inbox', displayName: "INBOX")
|
|
@archiveCategory = new klass(id: 'id-456', name: 'archive', displayName: "ArCHIVe")
|
|
@userCategory = new klass(id: 'id-789', name: null, displayName: "MyCategory")
|
|
|
|
spyOn(CategoryStore, "getStandardCategories").andReturn [ @inboxCategory, @archiveCategory ]
|
|
spyOn(CategoryStore, "getUserCategories").andReturn [ @userCategory ]
|
|
spyOn(CategoryStore, "getStandardCategory").andReturn @inboxCategory
|
|
|
|
# By default we're going to set to "inbox". This has implications for
|
|
# what categories get filtered out of the list.
|
|
f = FocusedMailViewStore
|
|
f._setMailView f._defaultMailView()
|
|
|
|
setupForCreateNew = (orgUnit = "folder") ->
|
|
setupFor.call(@, orgUnit)
|
|
|
|
@testThread = new Thread(id: 't1', subject: "fake")
|
|
@picker = ReactTestUtils.renderIntoDocument(
|
|
<CategoryPicker thread={@testThread} />
|
|
)
|
|
|
|
@popover = ReactTestUtils.findRenderedComponentWithType @picker, Popover
|
|
@popover.open()
|
|
|
|
describe 'when using labels', ->
|
|
beforeEach ->
|
|
setupFor.call(@, "label")
|
|
|
|
describe 'when using folders', ->
|
|
beforeEach ->
|
|
setupFor.call(@, "folder")
|
|
|
|
@testThread = new Thread(id: 't1', subject: "fake")
|
|
@picker = ReactTestUtils.renderIntoDocument(
|
|
<CategoryPicker thread={@testThread} />
|
|
)
|
|
|
|
it 'lists the desired categories', ->
|
|
data = @picker.state.categoryData
|
|
# NOTE: The inbox category is not included here because it's the
|
|
# currently focused category, which gets filtered out of the list.
|
|
expect(data[0].id).toBe "id-456"
|
|
expect(data[0].name).toBe "archive"
|
|
expect(data[0].category).toBe @archiveCategory
|
|
expect(data[1].divider).toBe true
|
|
expect(data[1].id).toBe "category-divider"
|
|
expect(data[2].id).toBe "id-789"
|
|
expect(data[2].name).toBeUndefined()
|
|
expect(data[2].category).toBe @userCategory
|
|
|
|
describe "'create new' item", ->
|
|
beforeEach ->
|
|
setupForCreateNew.call @
|
|
|
|
afterEach -> atom.testOrganizationUnit = null
|
|
|
|
it "is not visible when the search box is empty", ->
|
|
count = ReactTestUtils.scryRenderedDOMComponentsWithClass(@picker, 'category-create-new').length
|
|
expect(count).toBe 0
|
|
|
|
it "is visible when the search box has text", ->
|
|
inputNode = React.findDOMNode(ReactTestUtils.scryRenderedDOMComponentsWithTag(@picker, "input")[0])
|
|
ReactTestUtils.Simulate.change inputNode, target: { value: "calendar" }
|
|
count = ReactTestUtils.scryRenderedDOMComponentsWithClass(@picker, 'category-create-new').length
|
|
expect(count).toBe 1
|
|
|
|
it "shows folder icon if we're using exchange", ->
|
|
inputNode = React.findDOMNode(ReactTestUtils.scryRenderedDOMComponentsWithTag(@picker, "input")[0])
|
|
ReactTestUtils.Simulate.change inputNode, target: { value: "calendar" }
|
|
count = ReactTestUtils.scryRenderedDOMComponentsWithClass(@picker, 'category-create-new-folder').length
|
|
expect(count).toBe 1
|
|
|
|
describe "'create new' item with labels", ->
|
|
beforeEach ->
|
|
setupForCreateNew.call @, "label"
|
|
|
|
it "shows label icon if we're using gmail", ->
|
|
inputNode = React.findDOMNode(ReactTestUtils.scryRenderedDOMComponentsWithTag(@picker, "input")[0])
|
|
ReactTestUtils.Simulate.change inputNode, target: { value: "calendar" }
|
|
count = ReactTestUtils.scryRenderedDOMComponentsWithClass(@picker, 'category-create-new-tag').length
|
|
expect(count).toBe 1
|
|
|
|
describe "_onSelectCategory()", ->
|
|
beforeEach ->
|
|
setupForCreateNew.call @, "folder"
|
|
spyOn(TaskFactory, 'taskForRemovingCategory').andCallThrough()
|
|
spyOn(TaskFactory, 'taskForApplyingCategory').andCallThrough()
|
|
spyOn(Actions, "queueTask")
|
|
|
|
it "closes the popover", ->
|
|
spyOn(@popover, "close")
|
|
@picker._onSelectCategory { usage: 0, category: "asdf" }
|
|
expect(@popover.close).toHaveBeenCalled()
|
|
|
|
describe "when selecting a category currently on all the selected items", ->
|
|
it "fires a task to remove the category", ->
|
|
input =
|
|
category: "asdf"
|
|
usage: 1
|
|
|
|
@picker._onSelectCategory(input)
|
|
expect(TaskFactory.taskForRemovingCategory).toHaveBeenCalledWith
|
|
threads: [@testThread]
|
|
category: "asdf"
|
|
expect(Actions.queueTask).toHaveBeenCalled()
|
|
|
|
describe "when selecting a category not on all the selected items", ->
|
|
it "fires a task to add the category", ->
|
|
input =
|
|
category: "asdf"
|
|
usage: 0
|
|
|
|
@picker._onSelectCategory(input)
|
|
expect(TaskFactory.taskForApplyingCategory).toHaveBeenCalledWith
|
|
threads: [@testThread]
|
|
category: "asdf"
|
|
expect(Actions.queueTask).toHaveBeenCalled()
|
|
|
|
describe "when selecting a new category", ->
|
|
beforeEach ->
|
|
input =
|
|
newCategoryItem: true
|
|
@picker.setState(searchValue: "teSTing!")
|
|
@picker._onSelectCategory(input)
|
|
|
|
it "queues a new syncback task for creating a category", ->
|
|
expect(Actions.queueTask).toHaveBeenCalled()
|
|
syncbackTask = Actions.queueTask.calls[0].args[0]
|
|
newCategory = syncbackTask.category
|
|
expect(syncbackTask.organizationUnit).toBe "label"
|
|
expect(newCategory.displayName).toBe "teSTing!"
|
|
expect(newCategory.accountId).toBe TEST_ACCOUNT_ID
|
|
|
|
it "queues a task for applying the category after it has saved", ->
|
|
label = new Label(displayName: "teSTing!")
|
|
|
|
spyOn(TaskQueueStatusStore, "waitForPerformRemote").andCallFake (task) ->
|
|
expect(task instanceof SyncbackCategoryTask).toBe true
|
|
Promise.resolve()
|
|
|
|
spyOn(DatabaseStore, "findBy").andCallFake (klass, {clientId}) ->
|
|
expect(klass).toBe(Label)
|
|
expect(typeof clientId).toBe("string")
|
|
Promise.resolve(label)
|
|
|
|
waitsFor ->
|
|
Actions.queueTask.calls.length > 1
|
|
label = Actions.queueTask.calls[0].args[0].category
|
|
|
|
runs ->
|
|
expect(TaskFactory.taskForApplyingCategory).toHaveBeenCalledWith
|
|
threads: [@testThread]
|
|
category: label
|
|
expect(TaskFactory.taskForApplyingCategory.callCount).toBe(1)
|