闭社主体 forked from https://github.com/tootsuite/mastodon
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
3.5 KiB

  1. import { expect } from 'chai';
  2. import { shallow, mount } from 'enzyme';
  3. import sinon from 'sinon';
  4. import React from 'react';
  5. import DropdownMenu from '../../../app/javascript/mastodon/components/dropdown_menu';
  6. import Dropdown, { DropdownTrigger, DropdownContent } from 'react-simple-dropdown';
  7. describe('<DropdownMenu />', () => {
  8. const icon = 'my-icon';
  9. const size = 123;
  10. const action = sinon.spy();
  11. const items = [
  12. { text: 'first item', action: action, href: '/some/url' },
  13. { text: 'second item', action: 'noop' },
  14. ];
  15. const wrapper = shallow(<DropdownMenu icon={icon} items={items} size={size} />);
  16. it('contains one <Dropdown />', () => {
  17. expect(wrapper).to.have.exactly(1).descendants(Dropdown);
  18. });
  19. it('contains one <DropdownTrigger />', () => {
  20. expect(wrapper.find(Dropdown)).to.have.exactly(1).descendants(DropdownTrigger);
  21. });
  22. it('contains one <DropdownContent />', () => {
  23. expect(wrapper.find(Dropdown)).to.have.exactly(1).descendants(DropdownContent);
  24. });
  25. it('uses props.size for <DropdownTrigger /> style values', () => {
  26. ['font-size', 'width', 'line-height'].map((property) => {
  27. expect(wrapper.find(DropdownTrigger)).to.have.style(property, `${size}px`);
  28. });
  29. });
  30. it('uses props.icon as icon class name', () => {
  31. expect(wrapper.find(DropdownTrigger).find('i')).to.have.className(`fa-${icon}`);
  32. });
  33. it('is not expanded by default', () => {
  34. expect(wrapper.state('expanded')).to.be.equal(false);
  35. });
  36. it('does not render the list elements if not expanded', () => {
  37. const lis = wrapper.find(DropdownContent).find('li');
  38. expect(lis.length).to.be.equal(0);
  39. });
  40. it('sets expanded to true when clicking the trigger', () => {
  41. const wrapper = mount(<DropdownMenu icon={icon} items={items} size={size} />);
  42. wrapper.find(DropdownTrigger).first().simulate('click');
  43. expect(wrapper.state('expanded')).to.be.equal(true);
  44. });
  45. // Error: ReactWrapper::state() can only be called on the root
  46. /*it('sets expanded to false when clicking outside', () => {
  47. const wrapper = mount((
  48. <div>
  49. <DropdownMenu icon={icon} items={items} size={size} />
  50. <span />
  51. </div>
  52. ));
  53. wrapper.find(DropdownTrigger).first().simulate('click');
  54. expect(wrapper.find(DropdownMenu).first().state('expanded')).to.be.equal(true);
  55. wrapper.find('span').first().simulate('click');
  56. expect(wrapper.find(DropdownMenu).first().state('expanded')).to.be.equal(false);
  57. })*/
  58. it('renders list elements for each props.items if expanded', () => {
  59. const wrapper = mount(<DropdownMenu icon={icon} items={items} size={size} />);
  60. wrapper.find(DropdownTrigger).first().simulate('click');
  61. const lis = wrapper.find(DropdownContent).find('li');
  62. expect(lis.length).to.be.equal(items.length);
  63. });
  64. it('uses the href passed in via props.items', () => {
  65. wrapper
  66. .find(DropdownContent).find('li a')
  67. .forEach((a, i) => expect(a).to.have.attr('href', items[i].href));
  68. });
  69. it('uses the text passed in via props.items', () => {
  70. wrapper
  71. .find(DropdownContent).find('li a')
  72. .forEach((a, i) => expect(a).to.have.text(items[i].text));
  73. });
  74. it('uses the action passed in via props.items as click handler', () => {
  75. const wrapper = mount(<DropdownMenu icon={icon} items={items} size={size} />);
  76. wrapper.find(DropdownTrigger).first().simulate('click');
  77. wrapper.find(DropdownContent).find('li a').first().simulate('click');
  78. expect(action.calledOnce).to.equal(true);
  79. });
  80. });