_ = 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,
ChangeLabelsTask,
ChangeFolderTask,
SyncbackCategoryTask,
FocusedMailViewStore,
TaskQueueStatusStore} = require 'nylas-exports'
describe '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(
)
@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(
)
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
xdescribe 'when picking for a single Thread', ->
it 'renders a picker', ->
expect(ReactTestUtils.isCompositeComponentWithType @picker, CategoryPicker).toBe true
it "does not include a newItem prompt if there's no search", ->
outData = @picker._recalculateState().categoryData
newItem = _.findWhere(outData, newCategoryItem: true)
l1 = _.findWhere(outData, id: 'id-123')
expect(newItem).toBeUndefined()
expect(l1.name).toBe "inbox"
it "includes a newItem selector with the current search term", ->
xdescribe 'when picking labels for a single Thread', ->
beforeEach ->
atom.testOrganizationUnit = "label"
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()", ->
describe "using labels", ->
beforeEach ->
setupForCreateNew.call @, "label"
spyOn Actions, "queueTask"
it "adds a label if it was previously unused", ->
input = { usage: 0, newCategoryItem: undefined, category: "asdf" }
@picker._onSelectCategory input
expect(Actions.queueTask).toHaveBeenCalled()
labelsToAdd = Actions.queueTask.calls[0].args[0].labelsToAdd
expect(labelsToAdd.length).toBe 1
expect(labelsToAdd[0]).toEqual input.category
threadsToUpdate = Actions.queueTask.calls[0].args[0].threads
expect(threadsToUpdate).toEqual [ @testThread ]
it "removes a label if it was previously used", ->
input = { usage: 1, newCategoryItem: undefined, category: "asdf" }
@picker._onSelectCategory input
expect(Actions.queueTask).toHaveBeenCalled()
labelsToRemove = Actions.queueTask.calls[0].args[0].labelsToRemove
expect(labelsToRemove.length).toBe 1
expect(labelsToRemove[0]).toEqual input.category
threadsToUpdate = Actions.queueTask.calls[0].args[0].threads
expect(threadsToUpdate).toEqual [ @testThread ]
it "creates a new label task", ->
input = { newCategoryItem: true }
@picker.setState searchValue: "teSTing!"
@picker._onSelectCategory input
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 change label task after performRemote for creating it", ->
input = { newCategoryItem: true }
label = new Label(clientId: "local-123")
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
runs ->
@picker.setState searchValue: "teSTing!"
@picker._onSelectCategory input
waitsFor -> Actions.queueTask.calls.length > 1
runs ->
changeLabelsTask = Actions.queueTask.calls[1].args[0]
expect(changeLabelsTask instanceof ChangeLabelsTask).toBe true
expect(changeLabelsTask.labelsToAdd).toEqual [ label ]
expect(changeLabelsTask.threads).toEqual [ @testThread ]
it "doesn't queue any duplicate syncback tasks", ->
input = { newCategoryItem: true }
label = new Label(clientId: "local-123")
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
runs ->
@picker.setState searchValue: "teSTing!"
@picker._onSelectCategory input
waitsFor -> Actions.queueTask.calls.length > 1
runs ->
allInputs = Actions.queueTask.calls.map (c) -> c.args[0]
syncbackTasks = allInputs.filter (i) -> i instanceof SyncbackCategoryTask
expect(syncbackTasks.length).toBe 1
describe "using folders", ->
beforeEach ->
setupForCreateNew.call @, "folder"
spyOn Actions, "queueTask"
spyOn Actions, "moveThread"
spyOn Actions, "moveThreads"
it "moves a thread if the component has one", ->
input = { category: "blah" }
@picker._onSelectCategory input
expect(Actions.moveThread).toHaveBeenCalled()
args = Actions.moveThread.calls[0].args
expect(args[0]).toEqual @testThread
expect(args[1].folder).toEqual input.category
expect(args[1].threads).toEqual [ @testThread ]
it "moves threads if the component has no thread but has items", ->
@picker = ReactTestUtils.renderIntoDocument(
)
@popover = ReactTestUtils.findRenderedComponentWithType @picker, Popover
@popover.open()
input = { category: "blah" }
@picker._onSelectCategory input
expect(Actions.moveThreads).toHaveBeenCalled()
it "creates a new folder task", ->
input = { newCategoryItem: true }
folder = new Folder(clientId: "local-456", serverId: "yes.")
spyOn(TaskQueueStatusStore, "waitForPerformRemote").andCallFake (task) ->
expect(task instanceof SyncbackCategoryTask).toBe true
Promise.resolve()
spyOn(DatabaseStore, "findBy").andCallFake (klass, {clientId}) ->
expect(klass).toBe Folder
expect(typeof clientId).toBe "string"
Promise.resolve folder
runs ->
@picker.setState searchValue: "teSTing!"
@picker._onSelectCategory input
waitsFor -> Actions.moveThread.calls.length > 0
runs ->
changeFoldersTask = Actions.moveThread.calls[0].args[1]
expect(changeFoldersTask instanceof ChangeFolderTask).toBe true
expect(changeFoldersTask.folder).toEqual folder
expect(changeFoldersTask.threads).toEqual [ @testThread ]
it "closes the popover", ->
setupForCreateNew.call @, "folder"
spyOn @popover, "close"
spyOn Actions, "moveThread"
@picker._onSelectCategory { usage: 0, category: "asdf" }
expect(@popover.close).toHaveBeenCalled()