select-options.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.selectOptions = exports.deselectOptions = void 0;
  6. var _dom = require("@testing-library/dom");
  7. var _utils = require("./utils");
  8. var _click = require("./click");
  9. var _focus = require("./focus");
  10. var _hover = require("./hover");
  11. function selectOptionsBase(newValue, select, values, init, {
  12. skipPointerEventsCheck = false
  13. } = {}) {
  14. if (!newValue && !select.multiple) {
  15. throw (0, _dom.getConfig)().getElementError(`Unable to deselect an option in a non-multiple select. Use selectOptions to change the selection instead.`, select);
  16. }
  17. const valArray = Array.isArray(values) ? values : [values];
  18. const allOptions = Array.from(select.querySelectorAll('option, [role="option"]'));
  19. const selectedOptions = valArray.map(val => {
  20. if (typeof val !== 'string' && allOptions.includes(val)) {
  21. return val;
  22. } else {
  23. const matchingOption = allOptions.find(o => o.value === val || o.innerHTML === val);
  24. if (matchingOption) {
  25. return matchingOption;
  26. } else {
  27. throw (0, _dom.getConfig)().getElementError(`Value "${String(val)}" not found in options`, select);
  28. }
  29. }
  30. }).filter(option => !(0, _utils.isDisabled)(option));
  31. if ((0, _utils.isDisabled)(select) || !selectedOptions.length) return;
  32. if ((0, _utils.isElementType)(select, 'select')) {
  33. if (select.multiple) {
  34. for (const option of selectedOptions) {
  35. const withPointerEvents = skipPointerEventsCheck ? true : (0, _utils.hasPointerEvents)(option); // events fired for multiple select are weird. Can't use hover...
  36. if (withPointerEvents) {
  37. _dom.fireEvent.pointerOver(option, init);
  38. _dom.fireEvent.pointerEnter(select, init);
  39. _dom.fireEvent.mouseOver(option);
  40. _dom.fireEvent.mouseEnter(select);
  41. _dom.fireEvent.pointerMove(option, init);
  42. _dom.fireEvent.mouseMove(option, init);
  43. _dom.fireEvent.pointerDown(option, init);
  44. _dom.fireEvent.mouseDown(option, init);
  45. }
  46. (0, _focus.focus)(select);
  47. if (withPointerEvents) {
  48. _dom.fireEvent.pointerUp(option, init);
  49. _dom.fireEvent.mouseUp(option, init);
  50. }
  51. selectOption(option);
  52. if (withPointerEvents) {
  53. _dom.fireEvent.click(option, init);
  54. }
  55. }
  56. } else if (selectedOptions.length === 1) {
  57. const withPointerEvents = skipPointerEventsCheck ? true : (0, _utils.hasPointerEvents)(select); // the click to open the select options
  58. if (withPointerEvents) {
  59. (0, _click.click)(select, init, {
  60. skipPointerEventsCheck
  61. });
  62. } else {
  63. (0, _focus.focus)(select);
  64. }
  65. selectOption(selectedOptions[0]);
  66. if (withPointerEvents) {
  67. // the browser triggers another click event on the select for the click on the option
  68. // this second click has no 'down' phase
  69. _dom.fireEvent.pointerOver(select, init);
  70. _dom.fireEvent.pointerEnter(select, init);
  71. _dom.fireEvent.mouseOver(select);
  72. _dom.fireEvent.mouseEnter(select);
  73. _dom.fireEvent.pointerUp(select, init);
  74. _dom.fireEvent.mouseUp(select, init);
  75. _dom.fireEvent.click(select, init);
  76. }
  77. } else {
  78. throw (0, _dom.getConfig)().getElementError(`Cannot select multiple options on a non-multiple select`, select);
  79. }
  80. } else if (select.getAttribute('role') === 'listbox') {
  81. selectedOptions.forEach(option => {
  82. (0, _hover.hover)(option, init, {
  83. skipPointerEventsCheck
  84. });
  85. (0, _click.click)(option, init, {
  86. skipPointerEventsCheck
  87. });
  88. (0, _hover.unhover)(option, init, {
  89. skipPointerEventsCheck
  90. });
  91. });
  92. } else {
  93. throw (0, _dom.getConfig)().getElementError(`Cannot select options on elements that are neither select nor listbox elements`, select);
  94. }
  95. function selectOption(option) {
  96. option.selected = newValue;
  97. (0, _dom.fireEvent)(select, (0, _dom.createEvent)('input', select, {
  98. bubbles: true,
  99. cancelable: false,
  100. composed: true,
  101. ...init
  102. }));
  103. _dom.fireEvent.change(select, init);
  104. }
  105. }
  106. const selectOptions = selectOptionsBase.bind(null, true);
  107. exports.selectOptions = selectOptions;
  108. const deselectOptions = selectOptionsBase.bind(null, false);
  109. exports.deselectOptions = deselectOptions;