Mailspring/spec/components/multiselect-split-interaction-handler-spec.coffee
Juan Tejada 56258991fb fix(composer-focus): Fix focus behavior + update InjectedComponent props
Summary:
- Fixes bug with Composer focus caused by injected component. The composer body
  was being focused, but the cursor remained at the beginning of the content
  instead of at the end. This was caused because the focus method was being
  called before the content had actually been rendered to the dom.
  - Adds a callback to check when injected comp was actually rendered, and uses
    that to focus the body at the correct time.
  - Updates specs
- Updates behavior of focusing composer body when selecting threads in split
  mode --  resolves #T3444
  - It will focus the body when a thread is selcted via a click
  - It wont focus the body when a thread is selected via arrow keys
  - It will focus the body when a new inline reply is created
  - Updates specs

Test Plan: - Unit tests

Reviewers: evan, bengotow

Reviewed By: bengotow

Differential Revision: https://phab.nylas.com/D2393
2015-12-29 21:28:15 -05:00

164 lines
6.9 KiB
CoffeeScript

MultiselectSplitInteractionHandler = require '../../src/components/multiselect-split-interaction-handler'
WorkspaceStore = require '../../src/flux/stores/workspace-store'
FocusedContentStore = require '../../src/flux/stores/focused-content-store'
Thread = require '../../src/flux/models/thread'
Actions = require '../../src/flux/actions'
_ = require 'underscore'
describe "MultiselectSplitInteractionHandler", ->
beforeEach ->
@item = new Thread(id:'123')
@itemFocus = new Thread({id: 'focus'})
@itemKeyboardFocus = new Thread({id: 'keyboard-focus'})
@itemAfterFocus = new Thread(id:'after-focus')
@itemAfterKeyboardFocus = new Thread(id:'after-keyboard-focus')
data = [@item, @itemFocus, @itemAfterFocus, @itemKeyboardFocus, @itemAfterKeyboardFocus]
@selection = []
@dataView =
selection:
toggle: jasmine.createSpy('toggle')
expandTo: jasmine.createSpy('expandTo')
add: jasmine.createSpy('add')
walk: jasmine.createSpy('walk')
clear: jasmine.createSpy('clear')
count: => @selection.length
items: => @selection
top: => @selection[-1]
get: (idx) ->
data[idx]
getById: (id) ->
_.find data, (item) -> item.id is id
indexOfId: (id) ->
_.findIndex data, (item) -> item.id is id
count: -> data.length
@collection = 'threads'
@handler = new MultiselectSplitInteractionHandler(@dataView, @collection)
@isRootSheet = true
spyOn(WorkspaceStore, 'topSheet').andCallFake => {root: @isRootSheet}
spyOn(Actions, 'setFocus')
spyOn(Actions, 'setCursorPosition')
it "should always show focus", ->
expect(@handler.shouldShowFocus()).toEqual(true)
it "should show the keyboard cursor when multiple items are selected", ->
@selection = []
expect(@handler.shouldShowKeyboardCursor()).toEqual(false)
@selection = [@item]
expect(@handler.shouldShowKeyboardCursor()).toEqual(false)
@selection = [@item, @itemFocus]
expect(@handler.shouldShowKeyboardCursor()).toEqual(true)
describe "onClick", ->
it "should focus the list item and indicate it was focused via click", ->
@handler.onClick(@item)
expect(Actions.setFocus).toHaveBeenCalledWith({
collection: @collection
item: @item
usingClick: true
})
describe "onMetaClick", ->
describe "when there is currently a focused item", ->
beforeEach ->
spyOn(FocusedContentStore, 'focused').andCallFake => @itemFocus
spyOn(FocusedContentStore, 'focusedId').andCallFake -> 'focus'
it "should turn the focused item into the first selected item", ->
@handler.onMetaClick(@item)
expect(@dataView.selection.add).toHaveBeenCalledWith(@itemFocus)
it "should clear the focus", ->
@handler.onMetaClick(@item)
expect(Actions.setFocus).toHaveBeenCalledWith({collection: @collection, item: null})
it "should toggle selection", ->
@handler.onMetaClick(@item)
expect(@dataView.selection.toggle).toHaveBeenCalledWith(@item)
it "should call _checkSelectionAndFocusConsistency", ->
spyOn(@handler, '_checkSelectionAndFocusConsistency')
@handler.onMetaClick(@item)
expect(@handler._checkSelectionAndFocusConsistency).toHaveBeenCalled()
describe "onShiftClick", ->
describe "when there is currently a focused item", ->
beforeEach ->
spyOn(FocusedContentStore, 'focused').andCallFake => @itemFocus
spyOn(FocusedContentStore, 'focusedId').andCallFake -> 'focus'
it "should turn the focused item into the first selected item", ->
@handler.onMetaClick(@item)
expect(@dataView.selection.add).toHaveBeenCalledWith(@itemFocus)
it "should clear the focus", ->
@handler.onMetaClick(@item)
expect(Actions.setFocus).toHaveBeenCalledWith({collection: @collection, item: null})
it "should expand selection", ->
@handler.onShiftClick(@item)
expect(@dataView.selection.expandTo).toHaveBeenCalledWith(@item)
it "should call _checkSelectionAndFocusConsistency", ->
spyOn(@handler, '_checkSelectionAndFocusConsistency')
@handler.onMetaClick(@item)
expect(@handler._checkSelectionAndFocusConsistency).toHaveBeenCalled()
describe "onEnter", ->
describe "onSelect (x key on keyboard)", ->
it "should call _checkSelectionAndFocusConsistency", ->
spyOn(@handler, '_checkSelectionAndFocusConsistency')
@handler.onMetaClick(@item)
expect(@handler._checkSelectionAndFocusConsistency).toHaveBeenCalled()
describe "onShift", ->
it "should call _checkSelectionAndFocusConsistency", ->
spyOn(@handler, '_checkSelectionAndFocusConsistency')
@handler.onMetaClick(@item)
expect(@handler._checkSelectionAndFocusConsistency).toHaveBeenCalled()
describe "when the select option is passed", ->
it "should turn the existing focused item into a selected item", ->
spyOn(FocusedContentStore, 'focused').andCallFake => @itemFocus
spyOn(FocusedContentStore, 'focusedId').andCallFake -> 'focus'
@handler.onShift(1, {select: true})
expect(@dataView.selection.add).toHaveBeenCalledWith(@itemFocus)
it "should walk the selection to the shift target", ->
spyOn(FocusedContentStore, 'focused').andCallFake => @itemFocus
spyOn(FocusedContentStore, 'focusedId').andCallFake -> 'focus'
@handler.onShift(1, {select: true})
expect(@dataView.selection.walk).toHaveBeenCalledWith({current: @itemFocus, next: @itemAfterFocus})
describe "when one or more items is selected", ->
it "should move the keyboard cursor", ->
@selection = [@itemFocus, @itemAfterFocus, @itemKeyboardFocus]
spyOn(FocusedContentStore, 'keyboardCursor').andCallFake => @itemKeyboardFocus
spyOn(FocusedContentStore, 'keyboardCursorId').andCallFake -> 'keyboard-focus'
@handler.onShift(1, {})
expect(Actions.setCursorPosition).toHaveBeenCalledWith({collection: @collection, item: @itemAfterKeyboardFocus})
describe "when no items are selected", ->
it "should move the focus", ->
spyOn(FocusedContentStore, 'focused').andCallFake => @itemFocus
spyOn(FocusedContentStore, 'focusedId').andCallFake -> 'focus'
@handler.onShift(1, {})
expect(Actions.setFocus).toHaveBeenCalledWith({collection: @collection, item: @itemAfterFocus})
describe "_checkSelectionAndFocusConsistency", ->
describe "when only one item is selected", ->
beforeEach ->
spyOn(FocusedContentStore, 'focused').andCallFake -> null
spyOn(FocusedContentStore, 'focusedId').andCallFake -> null
@selection = [@item]
it "should clear the selection and make the item focused", ->
@handler._checkSelectionAndFocusConsistency()
expect(@dataView.selection.clear).toHaveBeenCalled()
expect(Actions.setFocus).toHaveBeenCalledWith({collection: @collection, item: @item})