Skip to content

Commit

Permalink
fix: expand tree for searches on initial mount. fixes #223
Browse files Browse the repository at this point in the history
  • Loading branch information
fritz-c committed Jan 13, 2018
1 parent b214065 commit 64a984a
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 6 deletions.
15 changes: 10 additions & 5 deletions src/react-sortable-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,9 @@ class ReactSortableTree extends Component {
this.handleDndMonitorChange = this.handleDndMonitorChange.bind(this);
}

componentWillMount() {
componentDidMount() {
this.loadLazyChildren();
this.search(this.props, false, false);
this.ignoreOneTreeUpdate = false;
this.search(this.props);

// Hook into react-dnd state changes to detect when the drag ends
// TODO: This is very brittle, so it needs to be replaced if react-dnd
Expand All @@ -130,14 +129,17 @@ class ReactSortableTree extends Component {
}

componentWillReceiveProps(nextProps) {
this.setState({ searchFocusTreeIndex: null });
if (this.props.treeData !== nextProps.treeData) {
// Ignore updates caused by search, in order to avoid infinite looping
if (this.ignoreOneTreeUpdate) {
this.ignoreOneTreeUpdate = false;
} else {
this.loadLazyChildren(nextProps);
// Reset the focused index if the tree has changed
this.setState({ searchFocusTreeIndex: null });

// Load any children defined by a function
this.loadLazyChildren(nextProps);

this.search(nextProps, false, false);
}

Expand Down Expand Up @@ -353,6 +355,9 @@ class ReactSortableTree extends Component {
newNode: ({ node }) => ({ ...node, expanded: true }),
getNodeKey: this.props.getNodeKey,
}),
// reset the scroll focus so it doesn't jump back
// to a search result while dragging
searchFocusTreeIndex: null,
});
}

Expand Down
53 changes: 52 additions & 1 deletion src/react-sortable-tree.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import PropTypes from 'prop-types';
import renderer from 'react-test-renderer';
import { mount } from 'enzyme';
import { List } from 'react-virtualized';
import SortableTree from './react-sortable-tree';
import SortableTree, {
SortableTreeWithoutDndContext,
} from './react-sortable-tree';
import sortableTreeStyles from './react-sortable-tree.scss';
import TreeNode from './tree-node';
import treeNodeStyles from './tree-node.scss';
Expand Down Expand Up @@ -268,4 +270,53 @@ describe('<SortableTree />', () => {

expect(wrapper.find(FakeNode).length).toEqual(1);
});

it('search should call searchFinishCallback', () => {
const searchFinishCallback = jest.fn();
mount(
<SortableTree
treeData={[{ title: 'a', children: [{ title: 'b' }] }]}
searchQuery="b"
searchFocusOffset={0}
searchFinishCallback={searchFinishCallback}
onChange={() => {}}
/>
);

expect(searchFinishCallback).toHaveBeenCalledWith([
// Node should be found expanded
{ node: { title: 'b' }, path: [0, 1], treeIndex: 1 },
]);
});

it('search should expand all matches and seek out the focus offset', () => {
const wrapper = mount(
<SortableTree
treeData={[
{ title: 'a', children: [{ title: 'b' }] },
{ title: 'a', children: [{ title: 'be' }] },
]}
searchQuery="b"
onChange={() => {}}
/>
);

const tree = wrapper.find(SortableTreeWithoutDndContext).instance();
expect(tree.state.searchMatches).toEqual([
{ node: { title: 'b' }, path: [0, 1], treeIndex: 1 },
{ node: { title: 'be' }, path: [2, 3], treeIndex: 3 },
]);
expect(tree.state.searchFocusTreeIndex).toEqual(null);

wrapper.setProps({ searchFocusOffset: 0 });
expect(tree.state.searchFocusTreeIndex).toEqual(1);

wrapper.setProps({ searchFocusOffset: 1 });
// As the empty `onChange` we use here doesn't actually change
// the tree, the expansion of all nodes doesn't get preserved
// after the first mount, and this change in searchFocusOffset
// only triggers the opening of a single path.
// Therefore it's 2 instead of 3.
expect(tree.state.searchFocusTreeIndex).toEqual(2);
});
});

0 comments on commit 64a984a

Please sign in to comment.