diff --git a/CHANGELOG.md b/CHANGELOG.md index 0437fe6d..7560f281 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ All notable changes to [`@bpmn-io/properties-panel`](https://github.com/bpmn-io/ ___Note:__ Yet to be released changes appear here._ +* `FEAT`: do not sort list items alphabetically ([#311](https://github.com/bpmn-io/properties-panel/issues/311)) +* `CHORE`: remove `shouldSort` behavior for list groups ([#353](https://github.com/bpmn-io/properties-panel/pull/353)) +* `CHORE`: remove `compareFn` prop for `List` component, the caller may decide on insertion points of new items ([#353](https://github.com/bpmn-io/properties-panel/pull/353)) + ## 3.18.2 * `FIX`: provide accessible label to FEEL editor ([#349](https://github.com/bpmn-io/properties-panel/pull/349)) diff --git a/src/PropertiesPanel.js b/src/PropertiesPanel.js index a808a411..f2273059 100644 --- a/src/PropertiesPanel.js +++ b/src/PropertiesPanel.js @@ -62,7 +62,6 @@ const DEFAULT_TOOLTIP = {}; * id: String, * items: Array, * label: String, - * shouldSort?: Boolean, * shouldOpen?: Boolean * } } ListGroupDefinition * diff --git a/src/components/ListGroup.js b/src/components/ListGroup.js index 36a4b349..393cfe8a 100644 --- a/src/components/ListGroup.js +++ b/src/components/ListGroup.js @@ -10,11 +10,6 @@ import Tooltip from './entries/Tooltip'; import classnames from 'classnames'; -import { - find, - sortBy -} from 'min-dash'; - import { useErrors, useLayoutState, @@ -44,10 +39,14 @@ export default function ListGroup(props) { id, items, label, - shouldOpen = true, - shouldSort = true + shouldOpen = true } = props; + useEffect(() => { + if (props.shouldSort != undefined) { + console.warn('the property \'shouldSort\' is no longer supported'); + } + }, [ props.shouldSort ]); const groupRef = useRef(null); @@ -60,101 +59,56 @@ export default function ListGroup(props) { const onShow = useCallback(() => setOpen(true), [ setOpen ]); - const [ ordering, setOrdering ] = useState([]); - const [ newItemAdded, setNewItemAdded ] = useState(false); + const [ localItems, setLocalItems ] = useState([]); + const [ newlyAddedItemIds, setNewlyAddedItemIds ] = useState([]); // Flag to mark that add button was clicked in the last render cycle const [ addTriggered, setAddTriggered ] = useState(false); - const prevItems = usePrevious(items); const prevElement = usePrevious(element); const elementChanged = element !== prevElement; - const shouldHandleEffects = !elementChanged && (shouldSort || shouldOpen); - - // reset initial ordering when element changes (before first render) - if (elementChanged) { - setOrdering(createOrdering(shouldSort ? sortItems(items) : items)); - } - - // keep ordering in sync to items - and open changes - - // (0) set initial ordering from given items + const shouldHandleEffects = !elementChanged && shouldOpen; + + // (0) delay setting items + // + // We need to this to align the render cycles of items + // with the detection of newly added items. + // This is important, because the autoOpen property can + // only set per list item on its very first render. useEffect(() => { - if (!prevItems || !shouldSort) { - setOrdering(createOrdering(items)); - } - }, [ items, element ]); + setLocalItems(items); + }, [ items ]); - // (1) items were added + // (1) handle auto opening when items were added useEffect(() => { // reset addTriggered flag setAddTriggered(false); - if (shouldHandleEffects && prevItems && items.length > prevItems.length) { - - let add = []; - - items.forEach(item => { - if (!ordering.includes(item.id)) { - add.push(item.id); + if (shouldHandleEffects && localItems) { + if (addTriggered) { + const previousItemIds = localItems.map(item => item.id); + const currentItemsIds = items.map(item => item.id); + const newItemIds = currentItemsIds.filter(itemId => !previousItemIds.includes(itemId)); + + // open if not open, configured and triggered by add button + // + // TODO(marstamm): remove once we refactor layout handling for listGroups. + // Ideally, opening should be handled as part of the `add` callback and + // not be a concern for the ListGroup component. + if (!open && shouldOpen && newItemIds.length > 0) { + toggleOpen(); } - }); - - let newOrdering = ordering; - - // open if not open, configured and triggered by add button - // - // TODO(marstamm): remove once we refactor layout handling for listGroups. - // Ideally, opening should be handled as part of the `add` callback and - // not be a concern for the ListGroup component. - if (addTriggered && !open && shouldOpen) { - toggleOpen(); - } - // filter when not open and configured - if (!open && shouldSort) { - newOrdering = createOrdering(sortItems(items)); - } - - // add new items on top or bottom depending on sorting behavior - newOrdering = newOrdering.filter(item => !add.includes(item)); - if (shouldSort) { - newOrdering.unshift(...add); + setNewlyAddedItemIds(newItemIds); } else { - newOrdering.push(...add); - } - - setOrdering(newOrdering); - setNewItemAdded(addTriggered); - } else { - setNewItemAdded(false); - } - }, [ items, open, shouldHandleEffects, addTriggered ]); - - // (2) sort items on open if shouldSort is set - useEffect(() => { - - if (shouldSort && open && !newItemAdded) { - setOrdering(createOrdering(sortItems(items))); - } - }, [ open, shouldSort ]); - - // (3) items were deleted - useEffect(() => { - if (shouldHandleEffects && prevItems && items.length < prevItems.length) { - let keep = []; - - ordering.forEach(o => { - if (getItem(items, o)) { - keep.push(o); - } - }); - setOrdering(keep); + // ignore newly added items that do not result from a triggered add + setNewlyAddedItemIds([]); + } } - }, [ items, shouldHandleEffects ]); + }, [ items, open, shouldHandleEffects, addTriggered, localItems ]); // set css class when group is sticky to top useStickyIntersectionObserver(groupRef, 'div.bio-properties-panel-scroll-container', setSticky); @@ -266,9 +220,7 @@ export default function ListGroup(props) { { - ordering.map((o, index) => { - const item = getItem(items, o); - + localItems.map((item, index) => { if (!item) { return; } @@ -277,7 +229,7 @@ export default function ListGroup(props) { // if item was added, open it // Existing items will not be affected as autoOpen is only applied on first render - const autoOpen = newItemAdded; + const autoOpen = newlyAddedItemIds.includes(item.id); return ( ; -} - - -// helpers //////////////////// - -/** - * Sorts given items alphanumeric by label - */ -function sortItems(items) { - return sortBy(items, i => i.label.toLowerCase()); -} - -function getItem(items, id) { - return find(items, i => i.id === id); -} - -function createOrdering(items) { - return items.map(i => i.id); -} +} \ No newline at end of file diff --git a/src/components/entries/List.js b/src/components/entries/List.js index 11e20e7e..40e3c370 100644 --- a/src/components/entries/List.js +++ b/src/components/entries/List.js @@ -1,6 +1,5 @@ import { useEffect, - useRef, useState } from 'preact/hooks'; @@ -37,7 +36,6 @@ import { * @param {Item[]} [props.items] * @param {boolean} [props.open] * @param {string|boolean} [props.autoFocusEntry] either a custom selector string or true to focus the first input - * @param {(a: Item, b: Item) => -1 | 0 | 1} [props.compareFn] * @returns */ export default function List(props) { @@ -51,7 +49,6 @@ export default function List(props) { onAdd, onRemove, autoFocusEntry, - compareFn, ...restProps } = props; @@ -60,11 +57,7 @@ export default function List(props) { const hasItems = !!items.length; const toggleOpen = () => hasItems && setOpen(!open); - const opening = !usePrevious(open) && open; const elementChanged = usePrevious(element) !== element; - const shouldReset = opening || elementChanged; - const sortedItems = useSortedItems(items, compareFn, shouldReset); - const newItems = useNewItems(items, elementChanged); useEffect(() => { @@ -151,7 +144,7 @@ export default function List(props) { component={ component } element={ element } id={ id } - items={ sortedItems } + items={ items } newItems={ newItems } onRemove={ onRemove } open={ open } @@ -236,44 +229,6 @@ function ItemsList(props) { ; } -/** - * Place new items in the beginning of the list and sort the rest with provided function. - * - * @template Item - * @param {Item[]} currentItems - * @param {(a: Item, b: Item) => 0 | 1 | -1} [compareFn] function used to sort items - * @param {boolean} [shouldReset=false] set to `true` to reset state of the hook - * @returns {Item[]} - */ -function useSortedItems(currentItems, compareFn, shouldReset = false) { - const itemsRef = useRef(currentItems.slice()); - - // (1) Reset and optionally sort. - if (shouldReset) { - itemsRef.current = currentItems.slice(); - - if (compareFn) { - itemsRef.current.sort(compareFn); - } - } else { - const items = itemsRef.current; - - // (2) Add new item to the list. - for (const item of currentItems) { - if (!items.includes(item)) { - - // Unshift or push depending on whether we have a compareFn - compareFn ? items.unshift(item) : items.push(item); - } - } - - // (3) Filter out removed items. - itemsRef.current = items.filter(item => currentItems.includes(item)); - } - - return itemsRef.current; -} - function useNewItems(items = [], shouldReset) { const previousItems = usePrevious(items.slice()) || []; diff --git a/test/spec/components/List.spec.js b/test/spec/components/List.spec.js index 9f129810..f4f18322 100644 --- a/test/spec/components/List.spec.js +++ b/test/spec/components/List.spec.js @@ -1,7 +1,6 @@ import { act, - render, - waitFor + render } from '@testing-library/preact/pure'; import TestContainer from 'mocha-test-container-support'; @@ -184,7 +183,6 @@ describe('', function() { open: true, component: Component, foo, - compareFn: defaultCompareFn }; // when @@ -201,7 +199,7 @@ describe('', function() { describe('auto-focus', function() { - it('should auto-focus first input entry added', async function() { + it('should auto-focus first input on first entry', async function() { // given const Component = (props) => { @@ -229,7 +227,6 @@ describe('', function() { onAdd, open: true, component: Component, - compareFn: defaultCompareFn }; const { @@ -245,13 +242,13 @@ describe('', function() { createListEntry(options, rerender); // then - const input = domQuery('[data-id="item-2"]', container); + const input = domQuery('[data-id="item-1"]', container); expect(document.activeElement).to.eql(input); }); - it('should auto-focus first select on entry added', async function() { + it('should auto-focus first select on first entry', async function() { // given const Component = (props) => { @@ -281,8 +278,7 @@ describe('', function() { items, onAdd, open: true, - component: Component, - compareFn: defaultCompareFn + component: Component }; const { @@ -298,7 +294,7 @@ describe('', function() { createListEntry(options, rerender); // then - const select = domQuery('[data-id="item-2"]', container); + const select = domQuery('[data-id="item-1"]', container); expect(document.activeElement).to.eql(select); }); @@ -332,7 +328,6 @@ describe('', function() { onAdd, open: true, component: Component, - compareFn: defaultCompareFn }; const { @@ -353,555 +348,56 @@ describe('', function() { expect(document.activeElement).to.eql(input); }); - }); - - - describe('ordering', function() { - - it('should create initial ordering from items', function() { - - // given - const items = [ - { - id: 'item-1', - label: 'Item 1' - }, - { - id: 'item-2', - label: 'Item 2' - }, - { - id: 'item-3', - label: 'Item 2' - } - ]; - - const { container } = createListEntry({ container: parentContainer, items }); - - const list = domQuery('.bio-properties-panel-list-entry', container); - - // then - expect(getListOrdering(list)).to.eql([ - 'item-1', - 'item-2', - 'item-3' - ]); - }); - - - it('should re-iniate ordering when element changed (unsorted)', async function() { + it('should focus new input once input was added given dynamic selector', async function() { // given - const items = [ - { - id: 'item-1', - label: 'xyz' - }, - { - id: 'item-2', - label: 'ab' - }, - { - id: 'item-3', - label: 'def03' - } - ]; - - const { - container, - rerender - } = createListEntry({ container: parentContainer, items, compareFn: false }); - - const list = domQuery('.bio-properties-panel-list-entry', container); - - // when - const newElement = { - ...noopElement, - id: 'bar' - }; - - // when - createListEntry({ element: newElement, items, compareFn: false }, rerender); - - // then - expect(getListOrdering(list)).to.eql([ - 'item-1', - 'item-2', - 'item-3' - ]); - }); - - - it('should re-iniate ordering when element changed (sorted)', async function() { - - // given - const items = [ - { - id: 'item-1', - label: 'xyz' - }, - { - id: 'item-2', - label: 'ab' - }, - { - id: 'item-3', - label: 'def03' - } - ]; - - const { - container, - rerender - } = createListEntry({ container: parentContainer, items }); - - const list = domQuery('.bio-properties-panel-list-entry', container); + const Component = (props) => { + const { item } = props; - // when - const newElement = { - ...noopElement, - id: 'bar' + return ; }; - // when - createListEntry({ element: newElement, items, compareFn: defaultCompareFn }, rerender); - - // then - expect(getListOrdering(list)).to.eql([ - 'item-2', - 'item-3', - 'item-1' - ]); - }); - - - it('should NOT sort if configured', async function() { - - // given const items = [ { id: 'item-1', - label: 'xyz' - }, - { - id: 'item-2', - label: 'ab' - }, - { - id: 'item-3', - label: 'def03' - }, - { - id: 'item-4', - label: 'def04' + label: 'Item 1' } ]; - const { container } = createListEntry({ container: parentContainer, items, compareFn: false }); - - const header = domQuery('.bio-properties-panel-list-entry-header', container); - - const list = domQuery('.bio-properties-panel-list-entry', container); - - // when - waitFor(async () => { - await header.click(); + const onAdd = () => items.push({ + id: 'item-2', + label: 'Item 2' }); - // then - expect(getListOrdering(list)).to.eql([ - 'item-1', - 'item-2', - 'item-3', - 'item-4' - ]); - }); - - - it('should order alphanumeric on open (label)', async function() { - - // given - const items = [ - { - id: 'item-1', - label: 'xyz' - }, - { - id: 'item-2', - label: 'ab' - }, - { - id: 'item-3', - label: 'def03' - }, - { - id: 'item-4', - label: 'def04' - } - ]; - - const { container } = createListEntry({ + const optionsProvider = () => ({ + autoFocusEntry: `[data-id="item-${items.length}"]`, container: parentContainer, items, - compareFn: defaultCompareFn - }); - - const header = domQuery('.bio-properties-panel-list-entry-header', container); - - const list = domQuery('.bio-properties-panel-list-entry', container); - - // when - waitFor(async () => { - await header.click(); + onAdd, + open: true, + component: Component, }); - // then - expect(getListOrdering(list)).to.eql([ - 'item-2', - 'item-3', - 'item-4', - 'item-1' - ]); - }); - - - it('should add new item on top given sorting is enabled', function() { - - // given - const items = [ - { - id: 'item-1', - label: 'Item 1' - }, - { - id: 'item-2', - label: 'Item 2' - }, - { - id: 'item-3', - label: 'Item 3' - } - ]; - - const { - container, - rerender - } = createListEntry({ container: parentContainer, items }); - - const list = domQuery('.bio-properties-panel-list-entry', container); - - const newItems = [ - ...items, - { - id: 'item-4', - label: 'Item 4' - } - ]; - - // when - createListEntry({ items: newItems, compareFn: defaultCompareFn }, rerender); - - // then - expect(getListOrdering(list)).to.eql([ - 'item-4', - 'item-1', - 'item-2', - 'item-3' - ]); - }); - - - it('should add new item to bottom given sorting is disabled', function() { - - // given - const items = [ - { - id: 'item-1', - label: 'Item 1' - }, - { - id: 'item-2', - label: 'Item 2' - }, - { - id: 'item-3', - label: 'Item 3' - } - ]; - const { container, rerender - } = createListEntry({ container: parentContainer, items, compareFn: false }); - - const list = domQuery('.bio-properties-panel-list-entry', container); - - const newItems = [ - ...items, - { - id: 'item-4', - label: 'Item 4' - } - ]; + } = createListEntry(optionsProvider()); // when - createListEntry({ items: newItems, compareFn: false }, rerender); - - // then - expect(getListOrdering(list)).to.eql([ - 'item-1', - 'item-2', - 'item-3', - 'item-4' - ]); - }); - - - it('should NOT add new items on top - element changed', function() { - - // given - const items = [ - { - id: 'item-1', - label: 'Item 1' - }, - { - id: 'item-2', - label: 'Item 2' - }, - { - id: 'item-3', - label: 'Item 3' - } - ]; - - const { - container, - rerender - } = createListEntry({ container: parentContainer, items }); - - const list = domQuery('.bio-properties-panel-list-entry', container); - - const newItems = [ - ...items, - { - id: 'item-4', - label: 'Item 4' - } - ]; - - const newElement = { - ...noopElement, - id: 'bar' - }; - - // when - createListEntry({ element: newElement, items: newItems }, rerender); - - // then - expect(getListOrdering(list)).to.eql([ - 'item-1', - 'item-2', - 'item-3', - 'item-4' - ]); - }); - - - it('should sort items - closed + added new one', function() { - - // given - const items = [ - { - id: 'item-1', - label: 'xyz' - }, - { - id: 'item-2', - label: 'ab' - } - ]; - - const { - container, - rerender - } = createListEntry({ - container: parentContainer, - label: 'List', - items, - compareFn: defaultCompareFn + await act(() => { + domQuery('.bio-properties-panel-add-entry', container).click(); }); - const newItems = [ - ...items, - { - id: 'item-3', - label: 'foo' - } - ]; - - const list = domQuery('.bio-properties-panel-list-entry', container); - - // assume - expect(getListOrdering(list)).to.eql([ - 'item-2', - 'item-1' - ]); - - // when - createListEntry({ items: newItems, compareFn: defaultCompareFn }, rerender); + createListEntry(optionsProvider(), rerender); // then - expect(getListOrdering(list)).to.eql([ - 'item-3', - 'item-2', - 'item-1' - ]); - }); - - - it('should keep ordering when items count did not change', async function() { - - // given - const items = [ - { - id: 'item-1', - label: 'xyz' - }, - { - id: 'item-2', - label: 'abc' - }, - { - id: 'item-3', - label: 'foo' - } - ]; - - const { - container, - rerender - } = createListEntry({ container: parentContainer, items, compareFn: defaultCompareFn }); - - const header = domQuery('.bio-properties-panel-list-entry-header', container); - - const list = domQuery('.bio-properties-panel-list-entry', container); - - waitFor(async () => { - await header.click(); - }); - - // assume - expect(getListOrdering(list)).to.eql([ - 'item-2', - 'item-3', - 'item-1' - ]); - - items[2].label = 'aaa'; - - // when - createListEntry({ items, compareFn: defaultCompareFn }, rerender); + const input = domQuery('[data-id="item-2"]', container); - // then - expect(getListOrdering(list)).to.eql([ - 'item-2', - 'item-3', - 'item-1' - ]); + expect(document.activeElement).to.eql(input); }); - - it('complex (open -> add -> change -> remove -> close -> open)', async function() { - - // given - let items = [ - { - id: 'item-1', - label: 'xyz' - }, - { - id: 'item-2', - label: 'abc' - } - ]; - - const { - container, - rerender - } = createListEntry({ container: parentContainer, items, compareFn: defaultCompareFn }); - - const header = domQuery('.bio-properties-panel-list-entry-header', container); - - const list = domQuery('.bio-properties-panel-list-entry', container); - - // when - - // (1) open - waitFor(async () => { - await header.click(); - }); - - expect(getListOrdering(list)).to.eql([ - 'item-2', - 'item-1' - ]); - - // (2) add - items = [ - ...items, - { - id: 'item-3', - label: 'foo' - } - ]; - - createListEntry({ items, compareFn: defaultCompareFn }, rerender); - - expect(getListOrdering(list)).to.eql([ - 'item-3', - 'item-2', - 'item-1' - ]); - - // (3) change - items[0].label = 'aaa'; - - createListEntry({ items, compareFn: defaultCompareFn }, rerender); - - expect(getListOrdering(list)).to.eql([ - 'item-3', - 'item-2', - 'item-1' - ]); - - // (4) remove - items.splice(1, 1); - - createListEntry({ items, compareFn: defaultCompareFn }, rerender); - - expect(getListOrdering(list)).to.eql([ - 'item-3', - 'item-1' - ]); - - // (5) close + open - waitFor(async () => { - await header.click(); - }); - - waitFor(async () => { - await header.click(); - }); - - expect(getListOrdering(list)).to.eql([ - 'item-1', - 'item-3' - ]); - }); }); - describe('onRemove', function() { it('should remove items', async function() { @@ -1040,7 +536,6 @@ function createListEntry(options = {}, renderFn = render) { open, container, component = DefaultComponent, - compareFn, autoFocusEntry = false, ...restProps } = options; @@ -1056,7 +551,6 @@ function createListEntry(options = {}, renderFn = render) { onRemove={ onRemove } open={ open } component={ component } - compareFn={ compareFn } autoFocusEntry={ autoFocusEntry } />, { container @@ -1083,7 +577,3 @@ function getListOrdering(list) { return ordering; } - -function defaultCompareFn(a, b) { - return a.label === b.label ? 0 : a.label > b.label ? 1 : -1; -} diff --git a/test/spec/components/ListGroup.spec.js b/test/spec/components/ListGroup.spec.js index cacf0244..cc1dc715 100644 --- a/test/spec/components/ListGroup.spec.js +++ b/test/spec/components/ListGroup.spec.js @@ -260,228 +260,25 @@ describe('', function() { describe('sorting', function() { - it('should sort per default', async function() { + it('should NOT sort initially', async function() { // given const items = [ - { - id: 'item-1', - label: 'Item D' - }, - { - id: 'item-2', - label: 'Item A' - }, - { - id: 'item-3', - label: 'Item B' - }, { id: 'item-4', - label: 'Item C' - } - ]; - - const { container } = createListGroup({ container: parentContainer, items }); - - const header = domQuery('.bio-properties-panel-group-header', container); - - const list = domQuery('.bio-properties-panel-list', container); - - // when - waitFor(async () => { - await header.click(); - }); - - // then - expect(getListOrdering(list)).to.eql([ - 'item-2', - 'item-3', - 'item-4', - 'item-1' - ]); - }); - - - it('should create initial sorting from items', function() { - - // given - const items = [ - { - id: 'item-1', - label: 'Item A' - }, - { - id: 'item-2', - label: 'Item B' - }, - { - id: 'item-3', - label: 'Item C' - } - ]; - - const { container } = createListGroup({ container: parentContainer, items }); - - const list = domQuery('.bio-properties-panel-list', container); - - // then - expect(getListOrdering(list)).to.eql([ - 'item-1', - 'item-2', - 'item-3' - ]); - }); - - - it('should re-iniate sorting when element changed (unsorted)', async function() { - - // given - const items = [ - { - id: 'item-1', - label: 'Item 1' - }, - { - id: 'item-2', - label: 'Item 2' + label: 'Item 4' }, { id: 'item-3', label: 'Item 3' - } - ]; - - const { - container, - rerender - } = createListGroup({ container: parentContainer, items, shouldSort: false }); - - const list = domQuery('.bio-properties-panel-list', container); - - // when - const newElement = { - ...noopElement, - id: 'bar' - }; - - // when - createListGroup({ element: newElement, items, shouldSort: false }, rerender); - - // then - expect(getListOrdering(list)).to.eql([ - 'item-1', - 'item-2', - 'item-3' - ]); - }); - - - it('should re-iniate sorting when element changed (sorted)', async function() { - - // given - const items = [ - { - id: 'item-1', - label: 'Item C' - }, - { - id: 'item-2', - label: 'Item A' - }, - { - id: 'item-3', - label: 'Item B' - } - ]; - - const { - container, - rerender - } = createListGroup({ container: parentContainer, items }); - - const list = domQuery('.bio-properties-panel-list', container); - - // when - const newElement = { - ...noopElement, - id: 'bar' - }; - - // when - createListGroup({ element: newElement, items }, rerender); - - // then - expect(getListOrdering(list)).to.eql([ - 'item-2', - 'item-3', - 'item-1' - ]); - }); - - - it('should NOT sort if configured', async function() { - - // given - const items = [ - { - id: 'item-1', - label: 'Item 1' }, { id: 'item-2', label: 'Item 2' }, - { - id: 'item-3', - label: 'Item 3' - }, - { - id: 'item-4', - label: 'Item 4' - } - ]; - - const { container } = createListGroup({ container: parentContainer, items, shouldSort: false }); - - const header = domQuery('.bio-properties-panel-group-header', container); - - const list = domQuery('.bio-properties-panel-list', container); - - // when - waitFor(async () => { - await header.click(); - }); - - // then - expect(getListOrdering(list)).to.eql([ - 'item-1', - 'item-2', - 'item-3', - 'item-4' - ]); - }); - - - it('should order alphanumeric on open (label)', async function() { - - // given - const items = [ { id: 'item-1', - label: 'Item D' - }, - { - id: 'item-2', - label: 'Item A' - }, - { - id: 'item-3', - label: 'Item B' - }, - { - id: 'item-4', - label: 'Item C' + label: 'Item 1' } ]; @@ -498,14 +295,13 @@ describe('', function() { // then expect(getListOrdering(list)).to.eql([ - 'item-2', - 'item-3', 'item-4', + 'item-3', + 'item-2', 'item-1' ]); }); - it('should NOT add new items on top - element changed', function() { // given @@ -556,116 +352,16 @@ describe('', function() { ]); }); - - it('should sort items - closed + added new one', function() { - - // given - const items = [ - { - id: 'item-1', - label: 'Item C' - }, - { - id: 'item-2', - label: 'Item A' - } - ]; - - const { - container, - rerender - } = createListGroup({ container: parentContainer, label: 'List', items }); - - const newItems = [ - ...items, - { - id: 'item-3', - label: 'Item B' - } - ]; - - const list = domQuery('.bio-properties-panel-list', container); - - // assume - expect(getListOrdering(list)).to.eql([ - 'item-1', - 'item-2' - ]); - - // when - createListGroup({ items: newItems }, rerender); - - // then - expect(getListOrdering(list)).to.eql([ - 'item-3', - 'item-2', - 'item-1' - ]); - }); - - - it('should keep sorting when items count did not change', async function() { - - // given - const items = [ - { - id: 'item-1', - label: 'Item C' - }, - { - id: 'item-2', - label: 'Item A' - }, - { - id: 'item-3', - label: 'Item B' - } - ]; - - const { - container, - rerender - } = createListGroup({ container: parentContainer, items }); - - const header = domQuery('.bio-properties-panel-group-header', container); - - const list = domQuery('.bio-properties-panel-list', container); - - waitFor(async () => { - await header.click(); - }); - - // assume - expect(getListOrdering(list)).to.eql([ - 'item-2', - 'item-3', - 'item-1' - ]); - - items[2].label = 'aaa'; - - // when - createListGroup({ items }, rerender); - - // then - expect(getListOrdering(list)).to.eql([ - 'item-2', - 'item-3', - 'item-1' - ]); - }); - - it('should NOT sort when open on adding items', async function() { // given let items = [ { - id: 'item-1', + id: 'item-4', label: 'Item D' }, { - id: 'item-2', + id: 'item-3', label: 'Item A' } ]; @@ -686,8 +382,8 @@ describe('', function() { }); expect(getListOrdering(list)).to.eql([ - 'item-2', - 'item-1' + 'item-4', + 'item-3' ]); // (1) when @@ -695,7 +391,7 @@ describe('', function() { items = [ ...items, { - id: 'item-3', + id: 'item-2', label: 'Item B' } ]; @@ -704,9 +400,9 @@ describe('', function() { // then expect(getListOrdering(list)).to.eql([ + 'item-4', 'item-3', - 'item-2', - 'item-1' + 'item-2' ]); // (2) when @@ -714,7 +410,7 @@ describe('', function() { items = [ ...items, { - id: 'item-4', + id: 'item-1', label: 'Item C' } ]; @@ -742,9 +438,9 @@ describe('', function() { // then expect(getListOrdering(list)).to.eql([ - 'item-2', - 'item-3', 'item-4', + 'item-3', + 'item-2', 'item-1' ]); }); @@ -755,11 +451,11 @@ describe('', function() { // given let items = [ { - id: 'item-1', + id: 'item-5', label: 'Item C' }, { - id: 'item-2', + id: 'item-4', label: 'Item A' } ]; @@ -781,8 +477,8 @@ describe('', function() { }); expect(getListOrdering(list)).to.eql([ - 'item-2', - 'item-1' + 'item-5', + 'item-4' ]); // (2) add @@ -797,9 +493,9 @@ describe('', function() { createListGroup({ items }, rerender); expect(getListOrdering(list)).to.eql([ - 'item-3', - 'item-2', - 'item-1' + 'item-5', + 'item-4', + 'item-3' ]); // (3) change @@ -808,9 +504,9 @@ describe('', function() { createListGroup({ items }, rerender); expect(getListOrdering(list)).to.eql([ - 'item-3', - 'item-2', - 'item-1' + 'item-5', + 'item-4', + 'item-3' ]); // (4) remove @@ -819,8 +515,8 @@ describe('', function() { createListGroup({ items }, rerender); expect(getListOrdering(list)).to.eql([ - 'item-3', - 'item-1' + 'item-5', + 'item-3' ]); // (5) close + open @@ -833,7 +529,7 @@ describe('', function() { }); expect(getListOrdering(list)).to.eql([ - 'item-1', + 'item-5', 'item-3' ]); }); @@ -843,7 +539,7 @@ describe('', function() { describe('insert top vs bottom', function() { - it('should insert new items to top given sorting enabled', function() { + it('should insert new items to bottom', function() { // given const items = [ @@ -879,52 +575,6 @@ describe('', function() { // when createListGroup({ items: newItems }, rerender); - // then - expect(getListOrdering(list)).to.eql([ - 'item-4', - 'item-1', - 'item-2', - 'item-3' - ]); - }); - - - it('should insert new items to bottom given sorting disabled', function() { - - // given - const items = [ - { - id: 'item-1', - label: 'Item 1' - }, - { - id: 'item-2', - label: 'Item 2' - }, - { - id: 'item-3', - label: 'Item 3' - } - ]; - - const { - container, - rerender - } = createListGroup({ container: parentContainer, items, shouldSort: false }); - - const list = domQuery('.bio-properties-panel-list', container); - - const newItems = [ - ...items, - { - id: 'item-4', - label: 'Item 4' - } - ]; - - // when - createListGroup({ items: newItems, shouldSort: false }, rerender); - // then expect(getListOrdering(list)).to.eql([ 'item-1', @@ -964,7 +614,7 @@ describe('', function() { setTestItems(newItems); }; - return ; + return ; }; const { @@ -992,60 +642,6 @@ describe('', function() { expect(domClasses(list).has('open')).to.be.true; }); - - it('should open on adding new item per default given no sorting', async function() { - - // given - const items = [ - { - id: 'item-1', - label: 'Item 1' - } - ]; - - const newItems = [ - ...items, - { - id: 'item-2', - label: 'Item 2' - } - ]; - - const Component = () => { - const [ testItems, setTestItems ] = useState(items); - - const add = () => { - setTestItems(newItems); - }; - - return ; - }; - - const { - container - } = render(, parentContainer); - - const list = domQuery('.bio-properties-panel-list', container); - const addButton = domQuery('.bio-properties-panel-add-entry', container); - - // assume - expect(domClasses(list).has('open')).to.be.false; - - // when - await act(() => { - addButton.click(); - }); - - // then - const newItem = domQuery('[data-entry-id="item-2"]', container); - const oldItem = domQuery('[data-entry-id="item-1"]', container); - - expect(domClasses(newItem).has('open')).to.be.true; - expect(domClasses(oldItem).has('open')).to.be.false; - expect(domClasses(list).has('open')).to.be.true; - }); - - it('should open on adding new item in the middle', async function() { // given @@ -1074,7 +670,7 @@ describe('', function() { setTestItems(newItems); }; - return ; + return ; }; const { @@ -1332,7 +928,6 @@ function TestGroup(props) { label = 'List', items = [], add, - shouldSort, shouldOpen, tooltip } = props; @@ -1346,7 +941,6 @@ function TestGroup(props) { label={ label } items={ items } add={ add } - shouldSort={ shouldSort } shouldOpen={ shouldOpen } tooltip={ tooltip } /> @@ -1362,7 +956,6 @@ function createListGroup(options = {}, renderFn = render) { label = 'List', items = [], add, - shouldSort, shouldOpen, container, tooltip @@ -1376,7 +969,6 @@ function createListGroup(options = {}, renderFn = render) { label={ label } items={ items } add={ add } - shouldSort={ shouldSort } shouldOpen={ shouldOpen } tooltip={ tooltip } /> ,