import { assert } from "chai" ; import { mount } from "enzyme" ; import * as React from "react" ; import * as sinon from "sinon" ; import { Classes as CoreClasses , Keys , Tag } from "@blueprintjs/core" ; import { dispatchTestKeyboardEventWithCode } from "@blueprintjs/test-commons" ; import { IFilm , renderFilm , TOP_100_FILMS } from "../../docs-app/src/common/films" ; import { IItemRendererProps , IMultiSelectProps , IMultiSelectState , MultiSelect } from "../src" ; import { selectComponentSuite } from "./selectComponentSuite" ; describe ( "<MultiSelect>" , ( ) => { const FilmMultiSelect = MultiSelect . ofType < IFilm > ( ) ; const defaultProps = { items : TOP_100_FILMS , popoverProps : { isOpen : true , usePortal : false } , query : "" , selectedItems : [ ] as IFilm [ ] , tagRenderer : renderTag , } ; let handlers ; beforeEach ( ( ) => { handlers = { itemPredicate : sinon . spy ( filterByYear ) , itemRenderer : sinon . spy ( renderFilm ) , onItemSelect : sinon . spy ( ) , } ; } ) ; selectComponentSuite < IMultiSelectProps < IFilm > , IMultiSelectState > ( props => mount ( < MultiSelect { ... props } popoverProps = { { isOpen : true , usePortal : false } } tagRenderer = { renderTag } / > ) ) ; it ( "placeholder can be controlled with placeholder prop" , ( ) => { const placeholder = "look here" ; const input = multiselect ( { placeholder } ) . find ( "input" ) ; assert . equal ( ( input . getDOMNode ( ) as HTMLInputElement ) . placeholder , placeholder ) ; } ) ; it ( "placeholder can be controlled with TagInput's inputProps" , ( ) => { const placeholder = "look here" ; const input = multiselect ( { tagInputProps : { placeholder } } ) . find ( "input" ) ; assert . equal ( ( input . getDOMNode ( ) as HTMLInputElement ) . placeholder , placeholder ) ; } ) ; it ( "tagRenderer can return JSX" , ( ) => { const wrapper = multiselect ( { selectedItems : [ TOP_100_FILMS [ 0 ] ] , tagRenderer : film => < strong > { film . title } < /strong>, } ) ; assert . equal ( wrapper . find ( Tag ) . find ( "strong" ) . length , 1 ) ; } ) ; it ( "selectedItems is optional" , ( ) => { assert . doesNotThrow ( ( ) => multiselect ( { selectedItems : undefined } ) ) ; } ) ; it ( "only triggers QueryList key up events when focus is on TagInput's <input>" , ( ) => { const itemSelectSpy = sinon . spy ( ) ; const wrapper = multiselect ( { onItemSelect : itemSelectSpy , selectedItems : [ TOP_100_FILMS [ 1 ] ] , } ) ; const firstTagRemoveButton = wrapper . find ( `.${ CoreClasses . TAG_REMOVE }` ) . at ( 0 ) . getDOMNode ( ) ; dispatchTestKeyboardEventWithCode ( firstTagRemoveButton , "keyup" , "Enter" , Keys . ENTER ) ; assert . isFalse ( itemSelectSpy . calledWith ( TOP_100_FILMS [ 0 ] ) ) ; } ) ; it ( "triggers onRemove" , ( ) => { const handleRemove = sinon . spy ( ) ; const wrapper = multiselect ( { onRemove : handleRemove , selectedItems : [ TOP_100_FILMS [ 2 ] , TOP_100_FILMS [ 3 ] , TOP_100_FILMS [ 4 ] ] , } ) ; wrapper . find ( `.${ CoreClasses . TAG_REMOVE }` ) . at ( 1 ) . simulate ( "click" ) ; assert . isTrue ( handleRemove . calledOnceWithExactly ( TOP_100_FILMS [ 3 ] , 1 ) ) ; } ) ; function multiselect ( props = { } , query ? ) { const wrapper = mount ( < FilmMultiSelect { ... defaultProps } { ... handlers } { ... props } > < article /> < /FilmMultiSelect>); if ( query !== undefined ) { wrapper . setState ( { query } ) ; } return wrapper ; } } ) ; function renderTag ( film ) { return film . title ; } function filterByYear ( query , film ) { return query === "" || film . year . toString ( ) === query ; }