Skip to content

Commit

Permalink
test: add test to the Tree component (#1505)
Browse files Browse the repository at this point in the history
* test: add test to the Tree component

fix: #1423

* fix: correct messages in specs

* fix: delete unnecessary spec

* fix: modify tests according to the last comments

* fix: modify test names

Co-authored-by: Jose Leandro Torres <jtorressicilia@gmail.com>
  • Loading branch information
rgah2107 and LeandroTorresSicilia authored Apr 30, 2020
1 parent 496aff1 commit 171d27f
Show file tree
Hide file tree
Showing 11 changed files with 355 additions and 4 deletions.
64 changes: 64 additions & 0 deletions integration/specs/Tree/tree-1.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
const PageTree = require('../../../src/components/Tree/pageObject');
const { TAB_KEY, ENTER_KEY, SPACE_KEY } = require('../../constants');

const TREE = '#tree-component-1';

describe('Tree basic', () => {
beforeAll(() => {
browser.url('/#!/Tree/1');
});
beforeEach(() => {
browser.refresh();
const component = $(TREE);
component.waitForExist();
});

it('should expand the node when it is collapse and its button icon is clicked', () => {
const tree = new PageTree(TREE);
const node = tree.getNode(3);
node.click();
expect(node.isExpanded()).toBe(true);
});
it('should collapse the node when it is expand and its button icon is clicked', () => {
const tree = new PageTree(TREE);
const node = tree.getNode(2);
node.click();
expect(node.isExpanded()).toBe(false);
});
it('should move focus to the next button icon when the first button icon is focused and press tab', () => {
const tree = new PageTree(TREE);
const firstNode = tree.getNode(2);
const secondNode = tree.getNode(3);
firstNode.click();
browser.keys(TAB_KEY);
expect(secondNode.hasFocus()).toBe(true);
});
it('should expand the node when its button icon is focused, press enter and the node was initially expanded', () => {
const tree = new PageTree(TREE);
const node = tree.getNode(2);
node.click();
browser.keys(ENTER_KEY);
expect(node.isExpanded()).toBe(true);
});
it('should collapse the node when its button icon is focused, press enter and the node was initially collapse', () => {
const tree = new PageTree(TREE);
const node = tree.getNode(3);
node.click();
browser.keys(ENTER_KEY);
expect(node.isExpanded()).toBe(false);
});
it('should expand the node when its button icon is focused, press space and the node was initially expanded', () => {
const tree = new PageTree(TREE);
const node = tree.getNode(2);
node.click();
browser.keys(SPACE_KEY);
expect(node.isExpanded()).toBe(true);
});
it('should collapse the node when its button icon is focused, press space and the node was initially collapse', () => {
const tree = new PageTree(TREE);
const node = tree.getNode(3);
node.click();
browser.keys(SPACE_KEY);
expect(node.isExpanded()).toBe(false);
});
});
24 changes: 24 additions & 0 deletions src/components/Tree/__test__/child.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';
import { mount } from 'enzyme';
import Child from './../child';

describe('<Child/>', () => {
it('should render the PrimitiveCheckbox component when isChecked prop has the right value', () => {
[true, false, 'indeterminate'].forEach(value => {
const component = mount(<Child isChecked={value} />);
expect(component.find('PrimitiveCheckbox').exists()).toBe(true);
});
});
it('should not render the PrimitiveCheckbox component when isChecked prop has the wrong value', () => {
['indeterminates', 'one', 'six'].forEach(value => {
const component = mount(<Child isChecked={value} />);
expect(component.find('PrimitiveCheckbox').exists()).toBe(false);
});
});
it('should render the TreeChildren component when children prop is not undefined', () => {
const children = [{ label: 'Tree Item' }, { label: 'Tree Item' }];
// eslint-disable-next-line react/no-children-prop
const component = mount(<Child children={children} isExpanded />);
expect(component.find('TreeChildren').exists()).toBe(true);
});
});
40 changes: 40 additions & 0 deletions src/components/Tree/__test__/expandCollapseButton.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import { mount } from 'enzyme';
import ExpandCollapseButton from './../expandCollapseButton';

describe('<ExpandCollapseButton/>', () => {
it('should return the Spinner component when isLoading prop is true', () => {
const component = mount(<ExpandCollapseButton isLoading />);
expect(component.find('Spinner').exists()).toBe(true);
});
it('should return the ButtonIcon component when hasChildren prop is true', () => {
const component = mount(<ExpandCollapseButton hasChildren />);
expect(component.find('ButtonIcon').exists()).toBe(true);
});
it('should set the right icon when isExpanded prop is true', () => {
const component = mount(<ExpandCollapseButton isExpanded hasChildren />);
expect(
component
.find('ButtonIcon')
.find('DownArrow')
.exists(),
).toBe(true);
});
it('should set the right icon when isExpanded prop is false', () => {
const component = mount(<ExpandCollapseButton isExpanded={false} hasChildren />);
expect(
component
.find('ButtonIcon')
.find('RightArrow')
.exists(),
).toBe(true);
});
it('should fire onclick callback when ButtonIcon is clicked', () => {
const onClickMock = jest.fn();
const component = mount(
<ExpandCollapseButton isExpanded hasChildren onClick={onClickMock} />,
);
component.find('ButtonIcon').simulate('click');
expect(onClickMock).toHaveBeenCalledTimes(1);
});
});
67 changes: 67 additions & 0 deletions src/components/Tree/__test__/tree.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React from 'react';
import { mount } from 'enzyme';
import Tree from '../index';

const data = [
{ label: 'Tree Item', isChecked: false },
{ label: 'Tree Item', isChecked: false },
{
label: 'Tree Branch',
isLoading: false,
isExpanded: true,
isChecked: false,
children: [
{ label: 'Tree Item', isChecked: false },
{
label: 'Tree Branch',
isLoading: false,
isExpanded: true,
isChecked: false,
children: [{ label: 'Tree Item', isChecked: false }],
},
],
},
{
label: 'Tree Branch',
isExpanded: true,
isChecked: false,
children: [
{ label: 'Tree Item', isChecked: false },
{
label: 'Tree Branch',
isLoading: false,
isExpanded: true,
isChecked: false,
children: [{ label: 'Tree Item', isChecked: false }],
},
],
},
];

describe('<Tree/>', () => {
it('should call onExpandCollapse with the right parameters when the button is clicked', () => {
const nodePath = [2, 1];
const onExpandCollapsekMock = jest.fn();
const component = mount(<Tree data={data} onExpandCollapse={onExpandCollapsekMock} />);
component
.find('ButtonIcon')
.at(1)
.simulate('click');
expect(onExpandCollapsekMock).toHaveBeenCalledWith({ nodePath });
});
it('should call onSelect with the right parameters when the node is selected', () => {
const nodePath = [2];
const onSelectMock = jest.fn();
const component = mount(<Tree data={data} onSelect={onSelectMock} />);
component
.find('PrimitiveCheckbox')
.at(2)
.find('input')
.simulate('change');
expect(onSelectMock).toHaveBeenCalledWith({ nodePath });
});
it('should render the correct number of children', () => {
const component = mount(<Tree data={data} />);
expect(component.find('Child').length).toBe(10);
});
});
4 changes: 2 additions & 2 deletions src/components/Tree/child.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ export default function Child(props) {
const hasCheckbox = typeof isChecked === 'boolean' || isChecked === 'indeterminate';
const hasIcon = !!icon;
return (
<ItemContainerLi hasChildren={hasChildren} icon={icon}>
<NodeContainer>
<ItemContainerLi hasChildren={hasChildren} icon={icon} data-id="node-element-li">
<NodeContainer data-id="node-element">
<ExpandCollapseButton
hasChildren={hasChildren}
isExpanded={isExpanded === true}
Expand Down
56 changes: 56 additions & 0 deletions src/components/Tree/helpers/__test__/getNode.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import getNode from '../getNode';

const tree = [
{ label: 'Tree Item' },
{ label: 'Tree Item' },
{
label: 'Tree Branch',
isExpanded: true,
children: [
{ label: 'Tree Item' },
{
label: 'Tree Branch',
isLoading: false,
children: [{ label: 'Tree Item' }],
},
],
},
{
label: 'Tree Branch',
children: [
{ label: 'Tree Item' },
{ label: 'Tree Item' },
{ label: 'Tree Item' },
{ label: 'Tree Item' },
{ label: 'Tree Item' },
],
},
];

describe('getNode', () => {
it('should return the right node when nodePath has only one element', () => {
const nodePath = [2];
const expectedNode = {
label: 'Tree Branch',
isExpanded: true,
children: [
{ label: 'Tree Item' },
{
label: 'Tree Branch',
isLoading: false,
children: [{ label: 'Tree Item' }],
},
],
};
expect(getNode(tree, nodePath)).toStrictEqual(expectedNode);
});
it('should return the right node when nodePath has more than one element', () => {
const nodePath = [2, 1];
const expectedNode = {
label: 'Tree Branch',
isLoading: false,
children: [{ label: 'Tree Item' }],
};
expect(getNode(tree, nodePath)).toStrictEqual(expectedNode);
});
});
2 changes: 2 additions & 0 deletions src/components/Tree/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ interface DataItem {
label?: ReactNode;
icon?: ReactNode;
isExpanded?: boolean;
isLoading?: boolean;
isChecked?: boolean | 'indeterminate';
children?: DataItem[];
id?: string;
}

export interface TreeProps extends BaseProps {
Expand Down
8 changes: 6 additions & 2 deletions src/components/Tree/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ import getNode from './helpers/getNode';
* @category Layout
*/
export default function Tree(props) {
const { data, onExpandCollapse, onSelect, className, style } = props;
const { data, onExpandCollapse, onSelect, className, style, id } = props;

return (
<TreeContainerUl className={className} style={style}>
<TreeContainerUl className={className} style={style} id={id}>
<TreeChildren
data={data}
onExpandCollapse={onExpandCollapse}
Expand All @@ -31,6 +31,7 @@ Tree.propTypes = {
label: PropTypes.node,
icon: PropTypes.node,
isExpanded: PropTypes.bool,
isLoading: PropTypes.bool,
isChecked: PropTypes.oneOf([true, false, 'indeterminate']),
children: PropTypes.array,
}),
Expand All @@ -43,6 +44,8 @@ Tree.propTypes = {
className: PropTypes.string,
/** An object with custom style applied for the outer element. */
style: PropTypes.object,
/** The id of the outer element. */
id: PropTypes.string,
};

Tree.defaultProps = {
Expand All @@ -51,6 +54,7 @@ Tree.defaultProps = {
onSelect: () => {},
className: undefined,
style: undefined,
id: undefined,
};

/**
Expand Down
33 changes: 33 additions & 0 deletions src/components/Tree/pageObject/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const PageNodeItem = require('./node');

/**
* Tree page object class.
* @class
*/
class PageTree {
/**
* Create a new Tree page object.
* @constructor
* @param {string} rootElement - The selector of the Tree root element.
*/
constructor(rootElement) {
this.rootElement = rootElement;
}

/**
* Returns a new Node page object of the element in item position.
* @method
* @param {number} itemPosition - The base 0 index of the Node.
*/
getNode(itemPosition) {
const items = $(this.rootElement).$$('[data-id="node-element-li"]');
if (items[itemPosition]) {
return new PageNodeItem(
`${this.rootElement} [data-id="node-element-li"]:nth-child(${itemPosition + 1})`,
);
}
return null;
}
}

module.exports = PageTree;
Loading

0 comments on commit 171d27f

Please sign in to comment.