Skip to content

Commit

Permalink
Merge e38e8a7 into a30d80a
Browse files Browse the repository at this point in the history
  • Loading branch information
frosetti committed Feb 8, 2018
2 parents a30d80a + e38e8a7 commit 9f52022
Show file tree
Hide file tree
Showing 3 changed files with 276 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Detailed API and example usage can be found in the sample application in tests/d
| `Attribute` | `itemTypeKey` | `string` | | Optional: With `itemTypeKey` set, it will be used to identify a list item's type. It will also be used for accessing the hash of components within `componentKeyNamesForTypes`. |
| `Attribute` | `itemDefinitions` | `hash` | | Optional: A set of components that are to be used in the list as the `item` component. Note that this had to be used in conjunction with `componentKeyNamesForTypes` |
| `Attribute` | `itemExpansionDefinitions` | `hash` | | Optional: A set of components that are to be used in the list as the `itemExpansion` component. Note that this had to be used in conjunction with `componentKeyNamesForTypes` |
| `Attribute` | `disableDeselectAll` | `boolean` | false | Optional: disables deselect all click turning frost list into a multi-select type list |


### Infinite scroll
Expand Down
10 changes: 10 additions & 0 deletions addon/components/frost-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export default Component.extend({
])).isRequired,

// Options - general
disableDeselectAll: PropTypes.bool,
expandedItems: PropTypes.arrayOf(PropTypes.oneOfType([
PropTypes.EmberObject,
PropTypes.object
Expand Down Expand Up @@ -100,6 +101,7 @@ export default Component.extend({
getDefaultProps () {
return {
// Options - general
disableDeselectAll: false,
scrollTop: 0,
size: 'medium',
isDynamicRowHeight: false,
Expand Down Expand Up @@ -320,14 +322,21 @@ export default Component.extend({
this.onExpansionChange(clonedItems)
},

/* eslint-disable complexity */
_select ({isRangeSelect, isSpecificSelect, item}) {
isRangeSelect = !!isRangeSelect // isRangeSelect can come in as undefined
if (this.onSelectionChange) {
const items = this.get('items')
const itemKey = this.get('itemKey')
const _itemComparator = this.get('_itemComparator')
const clonedSelectedItems = A(this.get('selectedItems').slice())
const _rangeState = this.get('_rangeState')

if (isRangeSelect === false && this.get('disableDeselectAll') === true) {
// Ensure we are not interrupting a range select prior to forcing a isSpecificSelect
isSpecificSelect = true
}

// Selects are proccessed in order of precedence: specific, range, basic
if (isSpecificSelect) {
selection.specific(clonedSelectedItems, item, _rangeState, _itemComparator)
Expand All @@ -340,5 +349,6 @@ export default Component.extend({
this.onSelectionChange(clonedSelectedItems)
}
}
/* eslint-enable complexity */
}
})
265 changes: 265 additions & 0 deletions tests/integration/components/frost-list-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,29 @@ import {afterEach, beforeEach, describe, it} from 'mocha'
import sinon from 'sinon'

const test = integration('frost-list')

/**
* It helper for selectedItems length
* @param {Number} length - expected length of selectedItems
*/
function itShouldHaveSelectedItemsLength (length) {
it(`should have selectedItems length to be ${length}`, function () {
expect(this.get('selectedItems').length).to.eql(length)
})
}

/**
* It helper for whether item is selected or not
* @param {Number} index - index of selected item.
* @param {Boolean} isSelected - whether item is selected or not.
*/
function itShouldHaveItemSelectedState (index, isSelected) {
const state = isSelected ? 'selected' : 'deselected'
it(`should have item ${index} ${state}`, function () {
expect($hook('myList-itemContent-item-container', {index}).hasClass('is-selected')).to.eql(isSelected)
})
}

describe(test.label, function () {
test.setup()

Expand Down Expand Up @@ -1298,4 +1321,246 @@ describe(test.label, function () {
})
})
})

describe('When using disableDeselectAll property', function () {
beforeEach(function () {
const testItems = A([
Ember.Object.create({id: '0'}),
Ember.Object.create({id: '1'})
])

this.setProperties({
disableDeselectAll: true,
items: testItems,
selectedItems: A([]),
onSelectionChange: (selectedItems) => {
this.get('selectedItems').setObjects(selectedItems)
}
})

this.render(hbs`
{{frost-list
disableDeselectAll=disableDeselectAll
item=(component 'frost-list-item')
hook='myList'
items=items
selectedItems=selectedItems
onSelectionChange=onSelectionChange
itemKey='id'
}}
`)
return wait()
})

describe('When using specific click', function () {
describe('When selecting item 0', function () {
beforeEach(function () {
$hook('myList-itemContent-selection', {index: 0}).click()
return wait()
})

itShouldHaveItemSelectedState(0, true)
itShouldHaveItemSelectedState(1, false)
itShouldHaveSelectedItemsLength(1)

describe('When deselecting item 1', function () {
beforeEach(function () {
$hook('myList-itemContent-selection', {index: 0}).click()
return wait()
})

itShouldHaveItemSelectedState(0, false)
itShouldHaveItemSelectedState(1, false)
itShouldHaveSelectedItemsLength(0)
})
})

describe('When selecting every item', function () {
beforeEach(function () {
$hook('myList-itemContent-selection', {index: 0}).click()
$hook('myList-itemContent-selection', {index: 1}).click()
return wait()
})

itShouldHaveItemSelectedState(0, true)
itShouldHaveItemSelectedState(1, true)
itShouldHaveSelectedItemsLength(2)

describe('When deselecting every item', function () {
beforeEach(function () {
$hook('myList-itemContent-selection', {index: 0}).click()
$hook('myList-itemContent-selection', {index: 1}).click()
return wait()
})

itShouldHaveItemSelectedState(0, false)
itShouldHaveItemSelectedState(1, false)
itShouldHaveSelectedItemsLength(0)
})
})
})

describe('When using ranged base clicks', function () {
beforeEach(function () {
const testItems = A([
Ember.Object.create({id: '0'}),
Ember.Object.create({id: '1'}),
Ember.Object.create({id: '2'}),
Ember.Object.create({id: '3'}),
Ember.Object.create({id: '4'}),
Ember.Object.create({id: '5'}),
Ember.Object.create({id: '6'})
])
this.set('items', testItems)
return wait()
})

describe('When using shift click from item1-5', function () {
beforeEach(function () {
const clickEvent = $.Event('click')
clickEvent.shiftKey = true
const clickEvent2 = $.Event('click')
clickEvent2.shiftKey = true
$hook('myList-itemContent-item', {index: 1}).trigger(clickEvent)
$hook('myList-itemContent-item', {index: 5}).trigger(clickEvent2)
return wait()
})

itShouldHaveItemSelectedState(0, false)
itShouldHaveItemSelectedState(1, true)
itShouldHaveItemSelectedState(2, true)
itShouldHaveItemSelectedState(3, true)
itShouldHaveItemSelectedState(4, true)
itShouldHaveItemSelectedState(5, true)
itShouldHaveItemSelectedState(6, false)
itShouldHaveSelectedItemsLength(5)
})

describe('When using shift click on item 1', function () {
beforeEach(function () {
const clickEvent = $.Event('click')
clickEvent.shiftKey = true
$hook('myList-itemContent-item', {index: 1}).trigger(clickEvent)
return wait()
})

itShouldHaveItemSelectedState(0, false)
itShouldHaveItemSelectedState(1, true)
itShouldHaveItemSelectedState(2, false)
itShouldHaveItemSelectedState(3, false)
itShouldHaveItemSelectedState(4, false)
itShouldHaveItemSelectedState(5, false)
itShouldHaveItemSelectedState(6, false)
itShouldHaveSelectedItemsLength(1)

describe('When using shift click on item 3', function () {
beforeEach(function () {
const clickEvent = $.Event('click')
clickEvent.shiftKey = true
$hook('myList-itemContent-item', {index: 3}).trigger(clickEvent)
return wait()
})

itShouldHaveItemSelectedState(0, false)
itShouldHaveItemSelectedState(1, true)
itShouldHaveItemSelectedState(2, true)
itShouldHaveItemSelectedState(3, true)
itShouldHaveItemSelectedState(4, false)
itShouldHaveItemSelectedState(5, false)
itShouldHaveItemSelectedState(6, false)
itShouldHaveSelectedItemsLength(3)

describe('When using shift click on item 5', function () {
beforeEach(function () {
const clickEvent = $.Event('click')
clickEvent.shiftKey = true
$hook('myList-itemContent-item', {index: 5}).trigger(clickEvent)
return wait()
})

itShouldHaveItemSelectedState(0, false)
itShouldHaveItemSelectedState(1, true)
itShouldHaveItemSelectedState(2, true)
itShouldHaveItemSelectedState(3, true)
itShouldHaveItemSelectedState(4, true)
itShouldHaveItemSelectedState(5, true)
itShouldHaveItemSelectedState(6, false)
itShouldHaveSelectedItemsLength(5)

describe('When using shift click on item 1', function () {
beforeEach(function () {
const clickEvent = $.Event('click')
clickEvent.shiftKey = true
$hook('myList-itemContent-item', {index: 1}).trigger(clickEvent)
return wait()
})

itShouldHaveItemSelectedState(0, false)
itShouldHaveItemSelectedState(1, true)
itShouldHaveItemSelectedState(2, false)
itShouldHaveItemSelectedState(3, false)
itShouldHaveItemSelectedState(4, false)
itShouldHaveItemSelectedState(5, false)
itShouldHaveItemSelectedState(6, false)
itShouldHaveSelectedItemsLength(1)
})

describe('When using shift click on item 0', function () {
beforeEach(function () {
const clickEvent = $.Event('click')
clickEvent.shiftKey = true
$hook('myList-itemContent-item', {index: 0}).trigger(clickEvent)
return wait()
})

itShouldHaveItemSelectedState(0, true)
itShouldHaveItemSelectedState(1, true)
itShouldHaveItemSelectedState(2, false)
itShouldHaveItemSelectedState(3, false)
itShouldHaveItemSelectedState(4, false)
itShouldHaveItemSelectedState(5, false)
itShouldHaveItemSelectedState(6, false)
itShouldHaveSelectedItemsLength(2)
})
})
})
})
})

describe('When using basic click', function () {
// Basic click should behave like an isSpecificSelect click now.
describe('When selecting item 0', function () {
beforeEach(function () {
$hook('myList-itemContent-item', {index: 0}).click()
return wait()
})

itShouldHaveItemSelectedState(0, true)
itShouldHaveItemSelectedState(1, false)
itShouldHaveSelectedItemsLength(1)

describe('When selecting item 1', function () {
beforeEach(function () {
$hook('myList-itemContent-item', {index: 1}).click()
return wait()
})

itShouldHaveItemSelectedState(0, true)
itShouldHaveItemSelectedState(1, true)
itShouldHaveSelectedItemsLength(2)

describe('When deselecting item 0', function () {
beforeEach(function () {
$hook('myList-itemContent-item', {index: 0}).click()
return wait()
})

itShouldHaveItemSelectedState(0, false)
itShouldHaveItemSelectedState(1, true)
itShouldHaveSelectedItemsLength(1)
})
})
})
})
})
})

0 comments on commit 9f52022

Please sign in to comment.