UNPKG

@salesforce/design-system-react

Version:

Salesforce Lightning Design System for React

365 lines (315 loc) 15.2 kB
"use strict"; var _react = require("react"); var _react2 = _interopRequireDefault(_react); var _createReactClass = require("create-react-class"); var _createReactClass2 = _interopRequireDefault(_createReactClass); var _propTypes = require("prop-types"); var _propTypes2 = _interopRequireDefault(_propTypes); var _lodash = require("lodash.isfunction"); var _lodash2 = _interopRequireDefault(_lodash); var _lodash3 = require("lodash.clonedeep"); var _lodash4 = _interopRequireDefault(_lodash3); var _chai = require("chai"); var _chai2 = _interopRequireDefault(_chai); var _chaiEnzyme = require("chai-enzyme"); var _chaiEnzyme2 = _interopRequireDefault(_chaiEnzyme); var _enzymeHelpers = require("../../../tests/enzyme-helpers"); var _keyCode = require("../../../utilities/key-code"); var _tree = require("../../../utilities/sample-data/tree"); var _tree2 = _interopRequireDefault(_tree); var _iconSettings = require("../../icon-settings"); var _iconSettings2 = _interopRequireDefault(_iconSettings); var _tree3 = require("../../tree"); var _tree4 = _interopRequireDefault(_tree3); var _search = require("../../forms/input/search"); var _search2 = _interopRequireDefault(_search); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } _chai2.default.use((0, _chaiEnzyme2.default)()); var COMPONENT_CSS_CLASSES = { base: 'slds-tree' }; var DemoTree = (0, _createReactClass2.default)({ displayName: 'DemoTree', // ### Prop Types propTypes: { branchExpandClicked: _propTypes2.default.func, exampleNodesIndex: _propTypes2.default.string, getNodes: _propTypes2.default.func, itemClicked: _propTypes2.default.func, noBranchSelection: _propTypes2.default.bool, searchTerm: _propTypes2.default.string, searchable: _propTypes2.default.bool, singleSelection: _propTypes2.default.bool, treeScrolled: _propTypes2.default.func, loading: _propTypes2.default.bool }, getDefaultProps: function getDefaultProps() { return { exampleNodesIndex: 'sampleNodesDefault', id: 'example-tree', loading: true }; }, getInitialState: function getInitialState() { var initalNodes = this.props.exampleNodesIndex ? _tree2.default[this.props.exampleNodesIndex] : _tree2.default.sampleNodesDefault; return { nodes: (0, _lodash4.default)(initalNodes), searchTerm: this.props.searchable ? 'fruit' : undefined }; }, // By default Tree can have multiple selected nodes and folders/branches can be selected. To disable either of these, you can use the following logic. However, `props` are immutable. The node passed in shouldn't be modified, and due to object and arrays being reference variables, forceUpate is needed. This is just a "working example" not a prescription. handleExpandClick: function handleExpandClick(event, data) { var _this = this; if ((0, _lodash2.default)(this.props.branchExpandClicked)) { this.props.branchExpandClicked(event, data); } data.node.expanded = data.expand; if (this.props.loading) { data.node.loading = data.expand ? true : undefined; // Fake delay to demonstrate use of loading node attibute setTimeout(function (node) { node.loading = false; _this.forceUpdate(); }, 500, data.node); } else { this.forceUpdate(); } }, handleClick: function handleClick(event, data) { if (this.props.singleSelection) { data.node.selected = data.select; this.setState({ singleSelection: data.node }); if (this.state.singleSelection) { this.state.singleSelection.selected = undefined; } this.forceUpdate(); if ((0, _lodash2.default)(this.props.itemClicked)) { this.props.itemClicked(event, data); } } else if (!this.props.noBranchSelection || this.props.noBranchSelection && data.node.type !== 'branch') { data.node.selected = data.select; this.forceUpdate(); if ((0, _lodash2.default)(this.props.itemClicked)) { this.props.itemClicked(event, data); } } }, handleScroll: function handleScroll(event, data) { if ((0, _lodash2.default)(this.props.treeScrolled)) { this.props.treeScrolled(event, data); } }, handleSearchChange: function handleSearchChange(event) { this.setState({ searchTerm: event.target.value }); }, render: function render() { return _react2.default.createElement(_iconSettings2.default, { iconPath: "/assets/icons" }, _react2.default.createElement("div", null, this.props.searchable ? _react2.default.createElement("div", null, _react2.default.createElement(_search2.default, { assistiveText: "Search Tree", value: this.state.searchTerm, onChange: this.handleSearchChange }), _react2.default.createElement("br", null)) : null, _react2.default.createElement(_tree4.default, _extends({ id: "example-tree", getNodes: this.props.getNodes, nodes: this.state.nodes, onExpandClick: this.handleExpandClick, onClick: this.handleClick, onScroll: this.handleScroll, searchTerm: this.state.searchTerm }, this.props)))); } }); describe('Tree: ', function () { /* Tests */ describe('Tree can be navigated up/down using the keyboard', function () { beforeEach((0, _enzymeHelpers.mountComponent)(_react2.default.createElement(DemoTree, null))); afterEach(_enzymeHelpers.unmountComponent); it('moves selection up/down with wrapping when using keyboard up/down keys', function () { // Initial focus selects the item this.wrapper.find('#example-tree-1').simulate('focus'); var itemDiv = this.wrapper.find('#example-tree-1').find('.slds-is-selected'); (0, _chai.expect)(itemDiv).to.have.length(1); // Go to next node this.wrapper.find('#example-tree-1').simulate('keyDown', _keyCode.keyObjects.DOWN); itemDiv = this.wrapper.find('#example-tree-2').find('.slds-is-selected'); (0, _chai.expect)(itemDiv).to.have.length(1); // Go to next node this.wrapper.find('#example-tree-2').simulate('keyDown', _keyCode.keyObjects.DOWN); itemDiv = this.wrapper.find('#example-tree-3').find('.slds-is-selected'); (0, _chai.expect)(itemDiv).to.have.length(1); // Go to next node this.wrapper.find('#example-tree-3').simulate('keyDown', _keyCode.keyObjects.DOWN); itemDiv = this.wrapper.find('#example-tree-7').find('.slds-is-selected'); (0, _chai.expect)(itemDiv).to.have.length(1); // Wrap to first node this.wrapper.find('#example-tree-7').simulate('keyDown', _keyCode.keyObjects.DOWN); itemDiv = this.wrapper.find('#example-tree-1').find('.slds-is-selected'); (0, _chai.expect)(itemDiv).to.have.length(1); // Wrap to last node this.wrapper.find('#example-tree-1').simulate('keyDown', _keyCode.keyObjects.UP); itemDiv = this.wrapper.find('#example-tree-7').find('.slds-is-selected'); (0, _chai.expect)(itemDiv).to.have.length(1); // Go to previous node this.wrapper.find('#example-tree-7').simulate('keyDown', _keyCode.keyObjects.UP); itemDiv = this.wrapper.find('#example-tree-3').find('.slds-is-selected'); (0, _chai.expect)(itemDiv).to.have.length(1); // Go to previous node this.wrapper.find('#example-tree-3').simulate('keyDown', _keyCode.keyObjects.UP); itemDiv = this.wrapper.find('#example-tree-2').find('.slds-is-selected'); (0, _chai.expect)(itemDiv).to.have.length(1); // Go to previous node this.wrapper.find('#example-tree-2').simulate('keyDown', _keyCode.keyObjects.UP); itemDiv = this.wrapper.find('#example-tree-1').find('.slds-is-selected'); (0, _chai.expect)(itemDiv).to.have.length(1); }); }); describe('Tree can be navigated right/left using the keyboard', function () { beforeEach((0, _enzymeHelpers.mountComponent)(_react2.default.createElement(DemoTree, { loading: false }))); afterEach(_enzymeHelpers.unmountComponent); it('expands/collapses branches when using right/left keys', function () { // Initial focus selects the item var item = this.wrapper.find('#example-tree-3'); item.simulate('focus'); var itemDiv = this.wrapper.find('#example-tree-3').find('.slds-is-selected'); (0, _chai.expect)(itemDiv).to.have.length(1); // Expand branch this.wrapper.find('#example-tree-3').simulate('keyDown', _keyCode.keyObjects.RIGHT); var items = this.wrapper.find('li[aria-level=2]'); (0, _chai.expect)(items).to.have.length(4); // Collapse branch this.wrapper.find('#example-tree-3').simulate('keyDown', _keyCode.keyObjects.LEFT); items = this.wrapper.find('li[aria-level=2]'); (0, _chai.expect)(items).to.have.length(0); // Expand branch and select an item this.wrapper.find('#example-tree-3').simulate('keyDown', _keyCode.keyObjects.RIGHT); items = this.wrapper.find('li[aria-level=2]'); (0, _chai.expect)(items).to.have.length(4); // Collapse branch from an item this.wrapper.find('#example-tree-3').simulate('keyDown', _keyCode.keyObjects.DOWN); this.wrapper.find('#example-tree-8').simulate('keyDown', _keyCode.keyObjects.LEFT); items = this.wrapper.find('li[aria-level=2]'); (0, _chai.expect)(items).to.have.length(0); }); }); describe('Default Structure and CSS', function () { var id = 'this-is-a-container-test'; beforeEach((0, _enzymeHelpers.mountComponent)(_react2.default.createElement(DemoTree, { className: "this-is-a-container-test", heading: "Foods", id: id, listClassName: "this-is-an-unordered-list-test", listStyle: { height: '500px' } }))); afterEach(_enzymeHelpers.unmountComponent); it('has tree container class, list class, and heading', function () { var container = this.wrapper.find('.slds-tree_container'); (0, _chai.expect)(container.hasClass('this-is-a-container-test')).to.be.true; var list = this.wrapper.find(".".concat(COMPONENT_CSS_CLASSES.base)); (0, _chai.expect)(list).to.have.length(1); (0, _chai.expect)(list.hasClass('this-is-an-unordered-list-test')).to.be.true; (0, _chai.expect)(list.node.offsetHeight).to.equal(500); var heading = this.wrapper.find("#".concat(id, "__heading")); (0, _chai.expect)(heading).to.have.length(1); }); }); describe('Assistive Technology', function () { beforeEach((0, _enzymeHelpers.mountComponent)(_react2.default.createElement(DemoTree, { assistiveText: "Foods" }))); afterEach(_enzymeHelpers.unmountComponent); it('has heading via assistiveText', function () { var heading = this.wrapper.find('#example-tree__heading.slds-assistive-text'); (0, _chai.expect)(heading).to.have.length(1); var ariaLabelledbyId = this.wrapper.find('.slds-tree[aria-labelledby="example-tree__heading"]'); (0, _chai.expect)(ariaLabelledbyId).to.have.length(1); }); }); describe('Initial Expanded and Selection based on nodes', function () { beforeEach((0, _enzymeHelpers.mountComponent)(_react2.default.createElement(DemoTree, { exampleNodesIndex: "sampleNodesWithInitialState", heading: "Foods" }))); afterEach(_enzymeHelpers.unmountComponent); it('has initial selection', function () { var selectedNode = this.wrapper.find('#example-tree-2').find('.slds-is-selected'); // Fruits, Watermelon, Tree Fruits (0, _chai.expect)(selectedNode).to.have.length(3); selectedNode = this.wrapper.find('#example-tree-5').find('.slds-is-selected'); (0, _chai.expect)(selectedNode).to.have.length(1); }); it('has initial expanded branches', function () { var expandedBranchList = this.wrapper.find('#example-tree-2').find('.slds-is-expanded'); (0, _chai.expect)(expandedBranchList.node.childNodes).to.have.length(2); }); }); describe('Branch expands and selects on click', function () { var itemClicked = sinon.spy(); var expandClicked = sinon.spy(); beforeEach((0, _enzymeHelpers.mountComponent)(_react2.default.createElement(DemoTree, { branchExpandClicked: expandClicked, itemClicked: itemClicked, heading: "Foods" }))); afterEach(_enzymeHelpers.unmountComponent); it('branch calls onExpandClicked and onClick', function () { var branch = this.wrapper.find('#example-tree-2').find('.slds-tree__item'); branch.simulate('click'); (0, _chai.expect)(itemClicked.callCount).to.equal(1); var expandButton = this.wrapper.find('#example-tree-2').find('.slds-button'); expandButton.simulate('click'); (0, _chai.expect)(expandClicked.callCount).to.equal(1); }); }); describe('Item calls onClick', function () { var itemClicked = sinon.spy(); beforeEach((0, _enzymeHelpers.mountComponent)(_react2.default.createElement(DemoTree, { itemClicked: itemClicked, heading: "Foods" }))); afterEach(_enzymeHelpers.unmountComponent); it('item calls itemClicked', function () { var item = this.wrapper.find('#example-tree-1').find('.slds-tree__item'); item.simulate('click'); (0, _chai.expect)(itemClicked.callCount).to.equal(1); }); }); describe('getNodes is called on initial tree', function () { var getNodes = sinon.spy(); beforeEach((0, _enzymeHelpers.mountComponent)(_react2.default.createElement(DemoTree, { exampleNodesIndex: "sampleNodesWithInitialState", getNodes: getNodes, heading: "Foods" }))); afterEach(_enzymeHelpers.unmountComponent); it('getNodes is called on initial tree', function () { (0, _chai.expect)(getNodes.callCount).to.equal(1); }); }); describe('Search term is highlighted', function () { beforeEach((0, _enzymeHelpers.mountComponent)(_react2.default.createElement(DemoTree, { searchTerm: "fruit", heading: "Foods" }))); afterEach(_enzymeHelpers.unmountComponent); it('item calls itemClicked', function () { var markedItem = this.wrapper.find('mark'); (0, _chai.expect)(markedItem).to.have.length(1); }); }); describe('Scrolling calls onScroll', function () { var onScroll = sinon.spy(); beforeEach((0, _enzymeHelpers.mountComponent)(_react2.default.createElement(DemoTree, { exampleNodesIndex: "sampleNodesWithLargeDataset", heading: "Foods", onScroll: onScroll, listStyle: { height: '300px', overflowY: 'auto' } }))); afterEach(_enzymeHelpers.unmountComponent); it('scrolling calls onScroll', function () { var list = this.wrapper.find(".".concat(COMPONENT_CSS_CLASSES.base)); list.simulate('scroll'); (0, _chai.expect)(onScroll.callCount).to.equal(1); }); }); });