UNPKG

@salesforce/design-system-react

Version:

Salesforce Lightning Design System for React

307 lines (268 loc) 7.24 kB
import React from 'react'; import chai, { expect } from 'chai'; import chaiEnzyme from 'chai-enzyme'; import { mount } from 'enzyme'; /* Enzyme Helpers that can mount and unmount React component instances to * the DOM and set `this.wrapper` and `this.dom` within Mocha's `this` * context [full source here](tests/enzyme-helpers.js). `this` can * only be referenced if inside `function () {}`. */ import { createMountNode, destroyMountNode, } from '../../../tests/enzyme-helpers'; import Accordion from '../../accordion'; import IconSettings from '../../icon-settings'; import Panel from '../../accordion/panel'; import Dropdown from '../../menu-dropdown'; /* Set Chai to use chaiEnzyme for enzyme compatible assertions: * https://github.com/producthunt/chai-enzyme */ chai.use(chaiEnzyme()); /* Re-usable demo component. */ const propTypes = {}; const defaultProps = {}; class AccordionExample extends React.Component { constructor(props) { super(props); this.state = { expandedPanels: {}, items: [ { id: '1', summary: 'Accordion Summary', details: 'Accordion details - A', }, { id: '2', summary: 'Accordion Summary', details: 'Accordion details - B', }, { id: '3', summary: 'Accordion Summary', details: 'Accordion details - C', }, ], }; } menuDropdown(selectedItem) { return ( <Dropdown align="right" id="ButtonGroupExampleDropdown" assistiveText={{ icon: 'More Options' }} buttonVariant="icon" buttonClassName="slds-shrink-none" iconCategory="utility" iconName="down" iconVariant="border-filled" onSelect={(option) => { if (option.label === 'delete') { this.setState((state) => ({ ...state, items: state.items.filter((item) => item.id !== selectedItem.id), })); } else if (console) { console.log('onSelect', event, option); } }} options={[ { label: 'delete', value: 'A0', }, { label: 'redo', value: 'B0', }, { label: 'activate', value: 'C0', }, ]} iconSize="x-small" /> ); } togglePanel(id) { this.setState((state) => ({ ...state, expandedPanels: { ...state.expandedPanels, [id]: !state.expandedPanels[id], }, })); } render() { return ( <IconSettings iconPath="/assets/icons"> <Accordion id="base-example-accordion"> {this.state.items.map((item) => ( <Panel expanded={!!this.state.expandedPanels[item.id]} id={item.id} panelContentActions={this.menuDropdown(item)} key={item.id} onTogglePanel={() => this.togglePanel(item.id)} summary={item.summary} > {item.details} </Panel> ))} </Accordion> </IconSettings> ); } } AccordionExample.displayName = 'AccordionExampleComponent'; AccordionExample.propTypes = propTypes; AccordionExample.defaultProps = defaultProps; class AccordionWithOnePanelExample extends React.Component { constructor(props) { super(props); this.state = { expandedPanels: {}, item: { id: '1', summary: 'Accordion Summary', details: 'Accordion Details', }, }; } togglePanel(id) { this.setState((state) => ({ ...state, expandedPanels: { ...state.expandedPanels, [id]: !state.expandedPanels[id], }, })); } render() { const { item } = this.state; return ( <IconSettings iconPath="/assets/icons"> <Accordion id="base-example-accordion"> <Panel expanded={!!this.state.expandedPanels[item.id]} id={item.id} key={item.id} onTogglePanel={() => this.togglePanel(item.id)} summary={item.summary} > {item.details} </Panel> </Accordion> </IconSettings> ); } } AccordionWithOnePanelExample.displayName = 'AccordionWithOnePanelExampleComponent'; AccordionWithOnePanelExample.propTypes = propTypes; AccordionWithOnePanelExample.defaultProps = defaultProps; /* Accordion rendering tests */ describe('Accordion', function describeFunction() { describe('Renders Accordion', () => { let mountNode; let wrapper; beforeEach(() => { mountNode = createMountNode({ context: this }); }); afterEach(() => { destroyMountNode({ wrapper, mountNode }); }); it('renders an accordion', () => { wrapper = mount(<AccordionExample />, { attachTo: mountNode }); const accordion = wrapper.find(Accordion); expect(accordion).to.be.present; }); it('renders `panelContentActions` component, if passed', () => { wrapper = mount(<AccordionExample />, { attachTo: mountNode, }); const panelContentActions = wrapper.find('div .slds-dropdown-trigger'); expect(panelContentActions, 'panel dropdown component exists').to.exist; }); it('renders accordion with only one panel', () => { wrapper = mount(<AccordionWithOnePanelExample />, { attachTo: mountNode, }); const accordion = wrapper.find(Accordion); expect(accordion).to.be.present; }); }); describe('Interactions keyboard', () => { let mountNode; let wrapper; beforeEach(() => { mountNode = createMountNode({ context: this }); }); afterEach(() => { destroyMountNode({ wrapper, mountNode }); }); it('focuses the next accordion button on arrow down', () => { wrapper = mount(<AccordionExample />, { attachTo: mountNode }); const accordionButtons = wrapper.find( 'button.slds-accordion__summary-action' ); accordionButtons.at(0).simulate('keyDown', { key: 'ArrowDown', keyCode: 40, which: 40, }); expect( accordionButtons.at(1).getDOMNode() === document.activeElement ).to.equal(true); }); it('focuses the previous accordion button on arrow up', () => { wrapper = mount(<AccordionExample />, { attachTo: mountNode }); const accordionButtons = wrapper.find( 'button.slds-accordion__summary-action' ); accordionButtons.at(0).simulate('keyDown', { key: 'ArrowUp', keyCode: 38, which: 38, }); const lastAccordionButton = accordionButtons.at( accordionButtons.length - 1 ); expect( lastAccordionButton.getDOMNode() === document.activeElement ).to.equal(true); }); }); describe('Open panel', () => { let mountNode; let wrapper; beforeEach(() => { mountNode = createMountNode({ context: this }); }); afterEach(() => { destroyMountNode({ wrapper, mountNode }); }); it('triggers a change callback on panel select', () => { wrapper = mount(<AccordionExample />, { attachTo: mountNode }); const panel = () => wrapper.find('SLDSAccordionPanel').first(); expect(panel()).to.have.prop('expanded', false); panel() .find('button.slds-accordion__summary-action') .simulate('click'); expect(panel()).to.have.prop('expanded', true); }); it('`aria-expanded` set to true on panel select', () => { wrapper = mount(<AccordionExample />, { attachTo: mountNode }); const panel = () => wrapper.find('SLDSAccordionPanel').first(); panel() .find('button.slds-accordion__summary-action') .simulate('click'); expect( panel().find('button.slds-accordion__summary-action') ).to.have.prop('aria-expanded', true); }); }); });