@khanacademy/wonder-blocks-dropdown 5.3.5 → 5.3.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/components/dropdown-core.d.ts +4 -0
- package/dist/components/select-opener.d.ts +14 -2
- package/dist/es/index.js +126 -82
- package/dist/index.js +125 -81
- package/package.json +5 -5
- package/src/components/__tests__/dropdown-core.test.tsx +76 -0
- package/src/components/__tests__/multi-select.test.tsx +161 -25
- package/src/components/__tests__/select-opener.test.tsx +220 -0
- package/src/components/__tests__/single-select.test.tsx +181 -28
- package/src/components/dropdown-core.tsx +7 -3
- package/src/components/multi-select.tsx +8 -1
- package/src/components/select-opener.tsx +165 -106
- package/src/components/single-select.tsx +8 -1
- package/tsconfig-build.tsbuildinfo +1 -1
package/dist/index.js
CHANGED
|
@@ -20,7 +20,6 @@ var reactPopper = require('react-popper');
|
|
|
20
20
|
var wonderBlocksModal = require('@khanacademy/wonder-blocks-modal');
|
|
21
21
|
var core = require('@popperjs/core');
|
|
22
22
|
var caretDownIcon = require('@phosphor-icons/core/bold/caret-down-bold.svg');
|
|
23
|
-
var reactRouter = require('react-router');
|
|
24
23
|
|
|
25
24
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
26
25
|
|
|
@@ -1305,11 +1304,12 @@ class DropdownCore extends React__namespace.Component {
|
|
|
1305
1304
|
open,
|
|
1306
1305
|
opener,
|
|
1307
1306
|
style,
|
|
1308
|
-
className
|
|
1307
|
+
className,
|
|
1308
|
+
disabled
|
|
1309
1309
|
} = this.props;
|
|
1310
1310
|
return React__namespace.createElement(wonderBlocksCore.View, {
|
|
1311
|
-
onKeyDown: this.handleKeyDown,
|
|
1312
|
-
onKeyUp: this.handleKeyUp,
|
|
1311
|
+
onKeyDown: !disabled ? this.handleKeyDown : undefined,
|
|
1312
|
+
onKeyUp: !disabled ? this.handleKeyUp : undefined,
|
|
1313
1313
|
style: [styles$4.menuWrapper, style],
|
|
1314
1314
|
className: className
|
|
1315
1315
|
}, this.renderLiveRegion(), opener, open && this.renderDropdown());
|
|
@@ -1660,16 +1660,37 @@ const styles$2 = aphrodite.StyleSheet.create({
|
|
|
1660
1660
|
const _excluded$2 = ["children", "disabled", "error", "id", "isPlaceholder", "light", "open", "testId", "onOpenChanged"];
|
|
1661
1661
|
const StyledButton = wonderBlocksCore.addStyle("button");
|
|
1662
1662
|
class SelectOpener extends React__namespace.Component {
|
|
1663
|
-
constructor(
|
|
1664
|
-
super(
|
|
1663
|
+
constructor(props) {
|
|
1664
|
+
super(props);
|
|
1665
1665
|
this.handleClick = e => {
|
|
1666
1666
|
const {
|
|
1667
1667
|
open
|
|
1668
1668
|
} = this.props;
|
|
1669
1669
|
this.props.onOpenChanged(!open);
|
|
1670
1670
|
};
|
|
1671
|
+
this.handleKeyDown = e => {
|
|
1672
|
+
const keyCode = e.key;
|
|
1673
|
+
if (keyCode === "Enter" || keyCode === " ") {
|
|
1674
|
+
this.setState({
|
|
1675
|
+
pressed: true
|
|
1676
|
+
});
|
|
1677
|
+
e.preventDefault();
|
|
1678
|
+
}
|
|
1679
|
+
};
|
|
1680
|
+
this.handleKeyUp = e => {
|
|
1681
|
+
const keyCode = e.key;
|
|
1682
|
+
if (keyCode === "Enter" || keyCode === " ") {
|
|
1683
|
+
this.setState({
|
|
1684
|
+
pressed: false
|
|
1685
|
+
});
|
|
1686
|
+
this.handleClick(e);
|
|
1687
|
+
}
|
|
1688
|
+
};
|
|
1689
|
+
this.state = {
|
|
1690
|
+
pressed: false
|
|
1691
|
+
};
|
|
1671
1692
|
}
|
|
1672
|
-
|
|
1693
|
+
render() {
|
|
1673
1694
|
const _this$props = this.props,
|
|
1674
1695
|
{
|
|
1675
1696
|
children,
|
|
@@ -1682,40 +1703,29 @@ class SelectOpener extends React__namespace.Component {
|
|
|
1682
1703
|
testId
|
|
1683
1704
|
} = _this$props,
|
|
1684
1705
|
sharedProps = _objectWithoutPropertiesLoose(_this$props, _excluded$2);
|
|
1685
|
-
const
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
}, children || "\u00A0"), React__namespace.createElement(wonderBlocksIcon.PhosphorIcon, {
|
|
1709
|
-
icon: caretDownIcon__default["default"],
|
|
1710
|
-
color: iconColor,
|
|
1711
|
-
size: "small",
|
|
1712
|
-
style: styles$1.caret,
|
|
1713
|
-
"aria-hidden": "true"
|
|
1714
|
-
}));
|
|
1715
|
-
});
|
|
1716
|
-
}
|
|
1717
|
-
render() {
|
|
1718
|
-
return React__namespace.createElement(reactRouter.__RouterContext.Consumer, null, router => this.renderClickableBehavior(router));
|
|
1706
|
+
const stateStyles = _generateStyles(light, isPlaceholder, error);
|
|
1707
|
+
const iconColor = light ? disabled || error ? "currentColor" : tokens__namespace.color.white : disabled ? tokens__namespace.color.offBlack32 : tokens__namespace.color.offBlack64;
|
|
1708
|
+
const style = [styles$1.shared, stateStyles.default, disabled && stateStyles.disabled, !disabled && this.state.pressed && stateStyles.pressed];
|
|
1709
|
+
return React__namespace.createElement(StyledButton, _extends({}, sharedProps, {
|
|
1710
|
+
"aria-disabled": disabled,
|
|
1711
|
+
"aria-expanded": open ? "true" : "false",
|
|
1712
|
+
"aria-haspopup": "listbox",
|
|
1713
|
+
"data-testid": testId,
|
|
1714
|
+
id: id,
|
|
1715
|
+
style: style,
|
|
1716
|
+
type: "button",
|
|
1717
|
+
onClick: !disabled ? this.handleClick : undefined,
|
|
1718
|
+
onKeyDown: !disabled ? this.handleKeyDown : undefined,
|
|
1719
|
+
onKeyUp: !disabled ? this.handleKeyUp : undefined
|
|
1720
|
+
}), React__namespace.createElement(wonderBlocksTypography.LabelMedium, {
|
|
1721
|
+
style: styles$1.text
|
|
1722
|
+
}, children || "\u00A0"), React__namespace.createElement(wonderBlocksIcon.PhosphorIcon, {
|
|
1723
|
+
icon: caretDownIcon__default["default"],
|
|
1724
|
+
color: iconColor,
|
|
1725
|
+
size: "small",
|
|
1726
|
+
style: styles$1.caret,
|
|
1727
|
+
"aria-hidden": "true"
|
|
1728
|
+
}));
|
|
1719
1729
|
}
|
|
1720
1730
|
}
|
|
1721
1731
|
SelectOpener.defaultProps = {
|
|
@@ -1764,61 +1774,91 @@ const _generateStyles = (light, placeholder, error) => {
|
|
|
1764
1774
|
}
|
|
1765
1775
|
let newStyles = {};
|
|
1766
1776
|
if (light) {
|
|
1777
|
+
const focusHoverStyling = {
|
|
1778
|
+
borderColor: error ? tokens__namespace.color.red : tokens__namespace.color.white,
|
|
1779
|
+
borderWidth: tokens__namespace.spacing.xxxxSmall_2,
|
|
1780
|
+
paddingLeft: adjustedPaddingLeft,
|
|
1781
|
+
paddingRight: adjustedPaddingRight
|
|
1782
|
+
};
|
|
1783
|
+
const activePressedStyling = {
|
|
1784
|
+
paddingLeft: adjustedPaddingLeft,
|
|
1785
|
+
paddingRight: adjustedPaddingRight,
|
|
1786
|
+
borderColor: error ? tokens__namespace.color.red : tokens__namespace.color.fadedBlue,
|
|
1787
|
+
borderWidth: tokens__namespace.border.width.thin,
|
|
1788
|
+
color: error ? tokens__namespace.color.offBlack64 : placeholder ? tokens.mix(tokens__namespace.color.white32, tokens__namespace.color.blue) : tokens__namespace.color.fadedBlue,
|
|
1789
|
+
backgroundColor: error ? tokens__namespace.color.fadedRed : tokens__namespace.color.activeBlue
|
|
1790
|
+
};
|
|
1767
1791
|
newStyles = {
|
|
1768
1792
|
default: {
|
|
1769
1793
|
background: error ? tokens__namespace.color.fadedRed8 : "transparent",
|
|
1770
|
-
color: placeholder ? tokens__namespace.color.white50 : tokens__namespace.color.white,
|
|
1794
|
+
color: error ? tokens__namespace.color.offBlack64 : placeholder ? tokens__namespace.color.white50 : tokens__namespace.color.white,
|
|
1771
1795
|
borderColor: error ? tokens__namespace.color.red : tokens__namespace.color.white50,
|
|
1772
|
-
borderWidth: tokens__namespace.border.width.hairline
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
borderWidth: tokens__namespace.border.width.thin,
|
|
1785
|
-
color: placeholder ? tokens.mix(tokens__namespace.color.white32, tokens__namespace.color.blue) : tokens__namespace.color.fadedBlue,
|
|
1786
|
-
backgroundColor: error ? tokens__namespace.color.fadedRed : tokens__namespace.color.activeBlue
|
|
1796
|
+
borderWidth: tokens__namespace.border.width.hairline,
|
|
1797
|
+
":hover:not([aria-disabled=true])": focusHoverStyling,
|
|
1798
|
+
["@media not (hover: hover)"]: {
|
|
1799
|
+
":hover:not([aria-disabled=true])": {
|
|
1800
|
+
borderColor: error ? tokens__namespace.color.red : tokens__namespace.color.white50,
|
|
1801
|
+
borderWidth: tokens__namespace.border.width.hairline,
|
|
1802
|
+
paddingLeft: tokens__namespace.spacing.medium_16,
|
|
1803
|
+
paddingRight: tokens__namespace.spacing.small_12
|
|
1804
|
+
}
|
|
1805
|
+
},
|
|
1806
|
+
":focus-visible:not([aria-disabled=true])": focusHoverStyling,
|
|
1807
|
+
":active:not([aria-disabled=true])": activePressedStyling
|
|
1787
1808
|
},
|
|
1788
1809
|
disabled: {
|
|
1789
1810
|
background: "transparent",
|
|
1790
1811
|
borderColor: tokens.mix(tokens__namespace.color.white32, tokens__namespace.color.blue),
|
|
1791
1812
|
color: tokens.mix(tokens__namespace.color.white32, tokens__namespace.color.blue),
|
|
1792
|
-
cursor: "
|
|
1793
|
-
|
|
1813
|
+
cursor: "not-allowed",
|
|
1814
|
+
":focus-visible": {
|
|
1815
|
+
boxShadow: `0 0 0 1px ${tokens__namespace.color.offBlack32}, 0 0 0 3px ${tokens__namespace.color.fadedBlue}`
|
|
1816
|
+
}
|
|
1817
|
+
},
|
|
1818
|
+
pressed: activePressedStyling
|
|
1794
1819
|
};
|
|
1795
1820
|
} else {
|
|
1821
|
+
const focusHoverStyling = {
|
|
1822
|
+
borderColor: error ? tokens__namespace.color.red : tokens__namespace.color.blue,
|
|
1823
|
+
borderWidth: tokens__namespace.border.width.thin,
|
|
1824
|
+
paddingLeft: adjustedPaddingLeft,
|
|
1825
|
+
paddingRight: adjustedPaddingRight
|
|
1826
|
+
};
|
|
1827
|
+
const activePressedStyling = {
|
|
1828
|
+
background: error ? tokens__namespace.color.fadedRed : tokens__namespace.color.fadedBlue,
|
|
1829
|
+
borderColor: error ? tokens__namespace.color.red : tokens__namespace.color.activeBlue,
|
|
1830
|
+
borderWidth: tokens__namespace.border.width.thin,
|
|
1831
|
+
paddingLeft: adjustedPaddingLeft,
|
|
1832
|
+
paddingRight: adjustedPaddingRight
|
|
1833
|
+
};
|
|
1796
1834
|
newStyles = {
|
|
1797
1835
|
default: {
|
|
1798
1836
|
background: error ? tokens__namespace.color.fadedRed8 : tokens__namespace.color.white,
|
|
1799
1837
|
borderColor: error ? tokens__namespace.color.red : tokens__namespace.color.offBlack16,
|
|
1800
1838
|
borderWidth: tokens__namespace.border.width.hairline,
|
|
1801
|
-
color: placeholder ? tokens__namespace.color.offBlack64 : tokens__namespace.color.offBlack
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
paddingLeft: adjustedPaddingLeft,
|
|
1814
|
-
paddingRight: adjustedPaddingRight
|
|
1839
|
+
color: placeholder ? tokens__namespace.color.offBlack64 : tokens__namespace.color.offBlack,
|
|
1840
|
+
":hover:not([aria-disabled=true])": focusHoverStyling,
|
|
1841
|
+
["@media not (hover: hover)"]: {
|
|
1842
|
+
":hover:not([aria-disabled=true])": {
|
|
1843
|
+
borderColor: error ? tokens__namespace.color.red : tokens__namespace.color.offBlack16,
|
|
1844
|
+
borderWidth: tokens__namespace.border.width.hairline,
|
|
1845
|
+
paddingLeft: tokens__namespace.spacing.medium_16,
|
|
1846
|
+
paddingRight: tokens__namespace.spacing.small_12
|
|
1847
|
+
}
|
|
1848
|
+
},
|
|
1849
|
+
":focus-visible:not([aria-disabled=true])": focusHoverStyling,
|
|
1850
|
+
":active:not([aria-disabled=true])": activePressedStyling
|
|
1815
1851
|
},
|
|
1816
1852
|
disabled: {
|
|
1817
1853
|
background: tokens__namespace.color.offWhite,
|
|
1818
1854
|
borderColor: tokens__namespace.color.offBlack16,
|
|
1819
1855
|
color: tokens__namespace.color.offBlack64,
|
|
1820
|
-
cursor: "
|
|
1821
|
-
|
|
1856
|
+
cursor: "not-allowed",
|
|
1857
|
+
":focus-visible": {
|
|
1858
|
+
boxShadow: `0 0 0 1px ${tokens__namespace.color.white}, 0 0 0 3px ${tokens__namespace.color.offBlack32}`
|
|
1859
|
+
}
|
|
1860
|
+
},
|
|
1861
|
+
pressed: activePressedStyling
|
|
1822
1862
|
};
|
|
1823
1863
|
}
|
|
1824
1864
|
stateStyles[styleKey] = aphrodite.StyleSheet.create(newStyles);
|
|
@@ -1904,7 +1944,7 @@ class SingleSelect extends React__namespace.Component {
|
|
|
1904
1944
|
}
|
|
1905
1945
|
static getDerivedStateFromProps(props, state) {
|
|
1906
1946
|
return {
|
|
1907
|
-
open: typeof props.opened === "boolean" ? props.opened : state.open
|
|
1947
|
+
open: props.disabled ? false : typeof props.opened === "boolean" ? props.opened : state.open
|
|
1908
1948
|
};
|
|
1909
1949
|
}
|
|
1910
1950
|
filterChildren(children) {
|
|
@@ -1971,7 +2011,8 @@ class SingleSelect extends React__namespace.Component {
|
|
|
1971
2011
|
light,
|
|
1972
2012
|
style,
|
|
1973
2013
|
"aria-invalid": ariaInvalid,
|
|
1974
|
-
"aria-required": ariaRequired
|
|
2014
|
+
"aria-required": ariaRequired,
|
|
2015
|
+
disabled
|
|
1975
2016
|
} = this.props;
|
|
1976
2017
|
const {
|
|
1977
2018
|
searchText
|
|
@@ -2000,7 +2041,8 @@ class SingleSelect extends React__namespace.Component {
|
|
|
2000
2041
|
searchText: isFilterable ? searchText : "",
|
|
2001
2042
|
labels: labels,
|
|
2002
2043
|
"aria-invalid": ariaInvalid,
|
|
2003
|
-
"aria-required": ariaRequired
|
|
2044
|
+
"aria-required": ariaRequired,
|
|
2045
|
+
disabled: disabled
|
|
2004
2046
|
});
|
|
2005
2047
|
}
|
|
2006
2048
|
}
|
|
@@ -2104,7 +2146,7 @@ class MultiSelect extends React__namespace.Component {
|
|
|
2104
2146
|
}
|
|
2105
2147
|
static getDerivedStateFromProps(props, state) {
|
|
2106
2148
|
return {
|
|
2107
|
-
open: typeof props.opened === "boolean" ? props.opened : state.open
|
|
2149
|
+
open: props.disabled ? false : typeof props.opened === "boolean" ? props.opened : state.open
|
|
2108
2150
|
};
|
|
2109
2151
|
}
|
|
2110
2152
|
componentDidUpdate(prevProps) {
|
|
@@ -2269,7 +2311,8 @@ class MultiSelect extends React__namespace.Component {
|
|
|
2269
2311
|
children,
|
|
2270
2312
|
isFilterable,
|
|
2271
2313
|
"aria-invalid": ariaInvalid,
|
|
2272
|
-
"aria-required": ariaRequired
|
|
2314
|
+
"aria-required": ariaRequired,
|
|
2315
|
+
disabled
|
|
2273
2316
|
} = this.props;
|
|
2274
2317
|
const {
|
|
2275
2318
|
open,
|
|
@@ -2308,7 +2351,8 @@ class MultiSelect extends React__namespace.Component {
|
|
|
2308
2351
|
someResults: someSelected
|
|
2309
2352
|
},
|
|
2310
2353
|
"aria-invalid": ariaInvalid,
|
|
2311
|
-
"aria-required": ariaRequired
|
|
2354
|
+
"aria-required": ariaRequired,
|
|
2355
|
+
disabled: disabled
|
|
2312
2356
|
});
|
|
2313
2357
|
}
|
|
2314
2358
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@khanacademy/wonder-blocks-dropdown",
|
|
3
|
-
"version": "5.3.
|
|
3
|
+
"version": "5.3.7",
|
|
4
4
|
"design": "v1",
|
|
5
5
|
"description": "Dropdown variants for Wonder Blocks.",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -16,13 +16,13 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@babel/runtime": "^7.18.6",
|
|
19
|
-
"@khanacademy/wonder-blocks-cell": "^3.3.
|
|
19
|
+
"@khanacademy/wonder-blocks-cell": "^3.3.7",
|
|
20
20
|
"@khanacademy/wonder-blocks-clickable": "^4.2.2",
|
|
21
21
|
"@khanacademy/wonder-blocks-core": "^6.4.1",
|
|
22
22
|
"@khanacademy/wonder-blocks-icon": "^4.1.1",
|
|
23
|
-
"@khanacademy/wonder-blocks-layout": "^2.0
|
|
24
|
-
"@khanacademy/wonder-blocks-modal": "^5.1.
|
|
25
|
-
"@khanacademy/wonder-blocks-search-field": "^2.2.
|
|
23
|
+
"@khanacademy/wonder-blocks-layout": "^2.1.0",
|
|
24
|
+
"@khanacademy/wonder-blocks-modal": "^5.1.4",
|
|
25
|
+
"@khanacademy/wonder-blocks-search-field": "^2.2.15",
|
|
26
26
|
"@khanacademy/wonder-blocks-timing": "^5.0.0",
|
|
27
27
|
"@khanacademy/wonder-blocks-tokens": "^1.3.0",
|
|
28
28
|
"@khanacademy/wonder-blocks-typography": "^2.1.12"
|
|
@@ -772,4 +772,80 @@ describe("DropdownCore", () => {
|
|
|
772
772
|
expect(container).toHaveTextContent("3 items");
|
|
773
773
|
});
|
|
774
774
|
});
|
|
775
|
+
|
|
776
|
+
describe("onOpenChanged", () => {
|
|
777
|
+
it("Should be triggered when the down key is pressed and the menu is closed", async () => {
|
|
778
|
+
// Arrange
|
|
779
|
+
const onOpenMock = jest.fn();
|
|
780
|
+
|
|
781
|
+
render(
|
|
782
|
+
<DropdownCore
|
|
783
|
+
initialFocusedIndex={undefined}
|
|
784
|
+
onSearchTextChanged={jest.fn()}
|
|
785
|
+
// mock the items (3 options)
|
|
786
|
+
items={items}
|
|
787
|
+
role="listbox"
|
|
788
|
+
open={false}
|
|
789
|
+
// mock the opener elements
|
|
790
|
+
opener={<button />}
|
|
791
|
+
onOpenChanged={onOpenMock}
|
|
792
|
+
/>,
|
|
793
|
+
);
|
|
794
|
+
// Act
|
|
795
|
+
// Press the button
|
|
796
|
+
const button = await screen.findByRole("button");
|
|
797
|
+
// NOTE: we need to use fireEvent here because await userEvent doesn't
|
|
798
|
+
// support keyUp/Down events and we use these handlers to override
|
|
799
|
+
// the default behavior of the button.
|
|
800
|
+
// eslint-disable-next-line testing-library/prefer-user-event
|
|
801
|
+
fireEvent.keyDown(button, {
|
|
802
|
+
keyCode: 40,
|
|
803
|
+
});
|
|
804
|
+
// eslint-disable-next-line testing-library/prefer-user-event
|
|
805
|
+
fireEvent.keyUp(button, {
|
|
806
|
+
keyCode: 40,
|
|
807
|
+
});
|
|
808
|
+
|
|
809
|
+
// Assert
|
|
810
|
+
expect(onOpenMock).toHaveBeenCalledTimes(1);
|
|
811
|
+
expect(onOpenMock).toHaveBeenCalledWith(true);
|
|
812
|
+
});
|
|
813
|
+
|
|
814
|
+
it("Should not be triggered when the dropdown is disabled and the down key is pressed and the menu is closed", async () => {
|
|
815
|
+
// Arrange
|
|
816
|
+
const onOpenMock = jest.fn();
|
|
817
|
+
|
|
818
|
+
render(
|
|
819
|
+
<DropdownCore
|
|
820
|
+
initialFocusedIndex={undefined}
|
|
821
|
+
onSearchTextChanged={jest.fn()}
|
|
822
|
+
// mock the items (3 options)
|
|
823
|
+
items={items}
|
|
824
|
+
role="listbox"
|
|
825
|
+
open={false}
|
|
826
|
+
// mock the opener elements
|
|
827
|
+
opener={<button />}
|
|
828
|
+
onOpenChanged={onOpenMock}
|
|
829
|
+
disabled={true}
|
|
830
|
+
/>,
|
|
831
|
+
);
|
|
832
|
+
// Act
|
|
833
|
+
// Press the button
|
|
834
|
+
const button = await screen.findByRole("button");
|
|
835
|
+
// NOTE: we need to use fireEvent here because await userEvent doesn't
|
|
836
|
+
// support keyUp/Down events and we use these handlers to override
|
|
837
|
+
// the default behavior of the button.
|
|
838
|
+
// eslint-disable-next-line testing-library/prefer-user-event
|
|
839
|
+
fireEvent.keyDown(button, {
|
|
840
|
+
keyCode: 40,
|
|
841
|
+
});
|
|
842
|
+
// eslint-disable-next-line testing-library/prefer-user-event
|
|
843
|
+
fireEvent.keyUp(button, {
|
|
844
|
+
keyCode: 40,
|
|
845
|
+
});
|
|
846
|
+
|
|
847
|
+
// Assert
|
|
848
|
+
expect(onOpenMock).toHaveBeenCalledTimes(0);
|
|
849
|
+
});
|
|
850
|
+
});
|
|
775
851
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable no-constant-condition */
|
|
2
2
|
/* eslint-disable max-lines */
|
|
3
3
|
import * as React from "react";
|
|
4
|
-
import {
|
|
4
|
+
import {render, screen, waitFor} from "@testing-library/react";
|
|
5
5
|
import {
|
|
6
6
|
userEvent as ue,
|
|
7
7
|
PointerEventsCheckLevel,
|
|
@@ -1539,55 +1539,191 @@ describe("MultiSelect", () => {
|
|
|
1539
1539
|
});
|
|
1540
1540
|
});
|
|
1541
1541
|
|
|
1542
|
-
describe("
|
|
1543
|
-
it("should
|
|
1542
|
+
describe("a11y > Focusable", () => {
|
|
1543
|
+
it("should be focusable", () => {
|
|
1544
1544
|
// Arrange
|
|
1545
|
-
|
|
1545
|
+
doRender(
|
|
1546
|
+
<MultiSelect onChange={jest.fn()} testId="select-focus-test">
|
|
1547
|
+
<OptionItem label="item 1" value="1" />
|
|
1548
|
+
<OptionItem label="item 2" value="2" />
|
|
1549
|
+
<OptionItem label="item 3" value="3" />
|
|
1550
|
+
</MultiSelect>,
|
|
1551
|
+
);
|
|
1552
|
+
|
|
1553
|
+
// Act
|
|
1554
|
+
const multiSelect = screen.getByTestId("select-focus-test");
|
|
1555
|
+
multiSelect.focus();
|
|
1556
|
+
|
|
1557
|
+
// Assert
|
|
1558
|
+
expect(multiSelect).toHaveFocus();
|
|
1559
|
+
});
|
|
1560
|
+
|
|
1561
|
+
it("should be focusable when disabled", () => {
|
|
1562
|
+
// Arrange
|
|
1563
|
+
doRender(
|
|
1546
1564
|
<MultiSelect
|
|
1547
1565
|
onChange={jest.fn()}
|
|
1548
|
-
|
|
1549
|
-
|
|
1566
|
+
testId="select-focus-test"
|
|
1567
|
+
disabled={true}
|
|
1550
1568
|
>
|
|
1551
|
-
|
|
1569
|
+
<OptionItem label="item 1" value="1" />
|
|
1570
|
+
<OptionItem label="item 2" value="2" />
|
|
1571
|
+
<OptionItem label="item 3" value="3" />
|
|
1552
1572
|
</MultiSelect>,
|
|
1553
1573
|
);
|
|
1554
|
-
const dropdown = await screen.findByTestId(
|
|
1555
|
-
"multiselect-error-hover",
|
|
1556
|
-
);
|
|
1557
1574
|
|
|
1558
1575
|
// Act
|
|
1559
|
-
|
|
1576
|
+
const multiSelect = screen.getByTestId("select-focus-test");
|
|
1577
|
+
multiSelect.focus();
|
|
1560
1578
|
|
|
1561
1579
|
// Assert
|
|
1562
|
-
expect(
|
|
1563
|
-
expect(dropdown).toHaveStyle("border-width: 2px");
|
|
1580
|
+
expect(multiSelect).toHaveFocus();
|
|
1564
1581
|
});
|
|
1582
|
+
});
|
|
1565
1583
|
|
|
1566
|
-
|
|
1584
|
+
describe("Disabled state", () => {
|
|
1585
|
+
it("should set the `aria-disabled` attribute to `true` if `disabled` prop is `true`", () => {
|
|
1567
1586
|
// Arrange
|
|
1587
|
+
|
|
1588
|
+
// Act
|
|
1568
1589
|
doRender(
|
|
1569
1590
|
<MultiSelect
|
|
1570
1591
|
onChange={jest.fn()}
|
|
1571
|
-
|
|
1572
|
-
|
|
1592
|
+
testId="select-focus-test"
|
|
1593
|
+
disabled={true}
|
|
1573
1594
|
>
|
|
1574
|
-
|
|
1595
|
+
<OptionItem label="item 1" value="1" />
|
|
1596
|
+
<OptionItem label="item 2" value="2" />
|
|
1597
|
+
<OptionItem label="item 3" value="3" />
|
|
1575
1598
|
</MultiSelect>,
|
|
1576
1599
|
);
|
|
1577
|
-
const
|
|
1578
|
-
|
|
1600
|
+
const multiSelect = screen.getByTestId("select-focus-test");
|
|
1601
|
+
|
|
1602
|
+
// Assert
|
|
1603
|
+
expect(multiSelect).toHaveAttribute("aria-disabled", "true");
|
|
1604
|
+
});
|
|
1605
|
+
|
|
1606
|
+
it("should not set the `disabled` attribute if `disabled` prop is `true` since `aria-disabled` is used instead", () => {
|
|
1607
|
+
// Arrange
|
|
1608
|
+
|
|
1609
|
+
// Act
|
|
1610
|
+
doRender(
|
|
1611
|
+
<MultiSelect
|
|
1612
|
+
onChange={jest.fn()}
|
|
1613
|
+
testId="select-focus-test"
|
|
1614
|
+
disabled={true}
|
|
1615
|
+
>
|
|
1616
|
+
<OptionItem label="item 1" value="1" />
|
|
1617
|
+
<OptionItem label="item 2" value="2" />
|
|
1618
|
+
<OptionItem label="item 3" value="3" />
|
|
1619
|
+
</MultiSelect>,
|
|
1579
1620
|
);
|
|
1621
|
+
const multiSelect = screen.getByTestId("select-focus-test");
|
|
1622
|
+
|
|
1623
|
+
// Assert
|
|
1624
|
+
expect(multiSelect).not.toHaveAttribute("disabled");
|
|
1625
|
+
});
|
|
1626
|
+
|
|
1627
|
+
it("should not be opened if it is disabled and `open` prop is set to true", () => {
|
|
1628
|
+
// Arrange
|
|
1580
1629
|
|
|
1581
1630
|
// Act
|
|
1582
|
-
|
|
1583
|
-
|
|
1631
|
+
doRender(
|
|
1632
|
+
<MultiSelect onChange={jest.fn()} disabled={true} opened={true}>
|
|
1633
|
+
<OptionItem label="item 1" value="1" />
|
|
1634
|
+
<OptionItem label="item 2" value="2" />
|
|
1635
|
+
<OptionItem label="item 3" value="3" />
|
|
1636
|
+
</MultiSelect>,
|
|
1637
|
+
);
|
|
1584
1638
|
|
|
1585
1639
|
// Assert
|
|
1586
|
-
expect(
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1640
|
+
expect(screen.queryByRole("listbox")).not.toBeInTheDocument();
|
|
1641
|
+
});
|
|
1642
|
+
});
|
|
1643
|
+
|
|
1644
|
+
describe("a11y > Focusable", () => {
|
|
1645
|
+
it("should be focusable", () => {
|
|
1646
|
+
// Arrange
|
|
1647
|
+
doRender(
|
|
1648
|
+
<MultiSelect onChange={jest.fn()} testId="select-focus-test">
|
|
1649
|
+
<OptionItem label="item 1" value="1" />
|
|
1650
|
+
<OptionItem label="item 2" value="2" />
|
|
1651
|
+
<OptionItem label="item 3" value="3" />
|
|
1652
|
+
</MultiSelect>,
|
|
1653
|
+
);
|
|
1654
|
+
|
|
1655
|
+
// Act
|
|
1656
|
+
const multiSelect = screen.getByTestId("select-focus-test");
|
|
1657
|
+
multiSelect.focus();
|
|
1658
|
+
|
|
1659
|
+
// Assert
|
|
1660
|
+
expect(multiSelect).toHaveFocus();
|
|
1661
|
+
});
|
|
1662
|
+
|
|
1663
|
+
it("should be focusable when disabled", () => {
|
|
1664
|
+
// Arrange
|
|
1665
|
+
doRender(
|
|
1666
|
+
<MultiSelect
|
|
1667
|
+
onChange={jest.fn()}
|
|
1668
|
+
testId="select-focus-test"
|
|
1669
|
+
disabled={true}
|
|
1670
|
+
>
|
|
1671
|
+
<OptionItem label="item 1" value="1" />
|
|
1672
|
+
<OptionItem label="item 2" value="2" />
|
|
1673
|
+
<OptionItem label="item 3" value="3" />
|
|
1674
|
+
</MultiSelect>,
|
|
1675
|
+
);
|
|
1676
|
+
|
|
1677
|
+
// Act
|
|
1678
|
+
const multiSelect = screen.getByTestId("select-focus-test");
|
|
1679
|
+
multiSelect.focus();
|
|
1680
|
+
|
|
1681
|
+
// Assert
|
|
1682
|
+
expect(multiSelect).toHaveFocus();
|
|
1683
|
+
});
|
|
1684
|
+
});
|
|
1685
|
+
|
|
1686
|
+
describe("Disabled state", () => {
|
|
1687
|
+
it("should set the `aria-disabled` attribute to `true` if `disabled` prop is `true`", () => {
|
|
1688
|
+
// Arrange
|
|
1689
|
+
|
|
1690
|
+
// Act
|
|
1691
|
+
doRender(
|
|
1692
|
+
<MultiSelect
|
|
1693
|
+
onChange={jest.fn()}
|
|
1694
|
+
testId="select-focus-test"
|
|
1695
|
+
disabled={true}
|
|
1696
|
+
>
|
|
1697
|
+
<OptionItem label="item 1" value="1" />
|
|
1698
|
+
<OptionItem label="item 2" value="2" />
|
|
1699
|
+
<OptionItem label="item 3" value="3" />
|
|
1700
|
+
</MultiSelect>,
|
|
1701
|
+
);
|
|
1702
|
+
const multiSelect = screen.getByTestId("select-focus-test");
|
|
1703
|
+
|
|
1704
|
+
// Assert
|
|
1705
|
+
expect(multiSelect).toHaveAttribute("aria-disabled", "true");
|
|
1706
|
+
});
|
|
1707
|
+
|
|
1708
|
+
it("should not set the `disabled` attribute if `disabled` prop is `true` since `aria-disabled` is used instead", () => {
|
|
1709
|
+
// Arrange
|
|
1710
|
+
|
|
1711
|
+
// Act
|
|
1712
|
+
doRender(
|
|
1713
|
+
<MultiSelect
|
|
1714
|
+
onChange={jest.fn()}
|
|
1715
|
+
testId="select-focus-test"
|
|
1716
|
+
disabled={true}
|
|
1717
|
+
>
|
|
1718
|
+
<OptionItem label="item 1" value="1" />
|
|
1719
|
+
<OptionItem label="item 2" value="2" />
|
|
1720
|
+
<OptionItem label="item 3" value="3" />
|
|
1721
|
+
</MultiSelect>,
|
|
1590
1722
|
);
|
|
1723
|
+
const multiSelect = screen.getByTestId("select-focus-test");
|
|
1724
|
+
|
|
1725
|
+
// Assert
|
|
1726
|
+
expect(multiSelect).not.toHaveAttribute("disabled");
|
|
1591
1727
|
});
|
|
1592
1728
|
});
|
|
1593
1729
|
});
|