Skip to content

Commit

Permalink
feat: 馃幐 added getNumberOfVisibleDescendants to TreeState
Browse files Browse the repository at this point in the history
  • Loading branch information
diogofcunha committed Jan 27, 2019
1 parent 98b98c6 commit d578c06
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 1 deletion.
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ export interface TreeState {
getNodeAt: (state: State, index: number) => Node;
getTree: (state: State) => Node[];
createFromTree: (tree: Node[]) => State;
getNumberOfVisibleDescendants: (state: State, index: number) => number;
}

export const selectors: Selectors;
25 changes: 24 additions & 1 deletion src/state/TreeState.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {getFlattenedTreePaths} from '../selectors/getFlattenedTree';
import {getNodeFromPath} from '../selectors/nodes';

class State {
export class State {
flattenedTree = null;
tree = null;

Expand Down Expand Up @@ -41,6 +41,29 @@ export default class TreeState {
return getNodeFromPath(rowPath, state.tree);
};

/**
* Given a state and an index, finds the number of visible descendants
* @param {State} state - The current state
* @param {number} index - The visible row index
* @return {number} The number of visible descendants
*/
static getNumberOfVisibleDescendants = (state, index) => {
const {id} = TreeState.getNodeAt(state, index);

const {flattenedTree} = state;
let i;

for (i = index; i < flattenedTree.length; i++) {
const path = flattenedTree[i];

if (!path.some(p => p === id)) {
break;
}
}

return Math.max(i - 1 - index, 0);
};

/**
* Given a state, gets the tree
* @param {State} state - The current state
Expand Down
43 changes: 43 additions & 0 deletions src/state/__tests__/TreeState.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,47 @@ describe('TreeState', () => {
expect(() => TreeState.getTree(() => {})).toThrowError('Expected a State instance but got function');
});
});

describe('getNumberOfVisibleDescendants', () => {
test('should fail for when invalid state is supplied', () => {
expect(() => TreeState.getNumberOfVisibleDescendants('state', 0)).toThrowError(
'Expected a State instance but got string',
);
expect(() => TreeState.getNumberOfVisibleDescendants(1225, 0)).toThrowError(
'Expected a State instance but got number',
);
expect(() => TreeState.getNumberOfVisibleDescendants([], 0)).toThrowError(
'Expected a State instance but got object',
);
expect(() => TreeState.getNumberOfVisibleDescendants({}, 0)).toThrowError(
'Expected a State instance but got object',
);
expect(() => TreeState.getNumberOfVisibleDescendants(true, 0)).toThrowError(
'Expected a State instance but got boolean',
);
expect(() => TreeState.getNumberOfVisibleDescendants(() => {}, 0)).toThrowError(
'Expected a State instance but got function',
);
});

test('should get a correct number of descendants for a node with deep descendants', () => {
expect(TreeState.getNumberOfVisibleDescendants(TreeState.createFromTree(Nodes), 0)).toEqual(4);
});

test('should get a correct number of descendants for a node without grand children', () => {
expect(TreeState.getNumberOfVisibleDescendants(TreeState.createFromTree(Nodes), 1)).toEqual(2);
});

test('should get a correct number of descendants for a node with deep descendants', () => {
expect(TreeState.getNumberOfVisibleDescendants(TreeState.createFromTree(Nodes), 0)).toEqual(4);
});

test('should get 0 descendants for a node that does not have any descendants in the root node', () => {
expect(TreeState.getNumberOfVisibleDescendants(TreeState.createFromTree(Nodes), 6)).toEqual(0);
});

test('should get 0 descendants for a node that does not have any descendants', () => {
expect(TreeState.getNumberOfVisibleDescendants(TreeState.createFromTree(Nodes), 3)).toEqual(0);
});
});
});

0 comments on commit d578c06

Please sign in to comment.