orc-shared 5.99.0-dev.4 → 5.99.0-dev.6
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/dist/components/Form/Inputs/MultiSelector.js +67 -12
- package/dist/components/Form/Inputs/Selector.js +13 -10
- package/dist/components/MaterialUI/Inputs/Select.js +164 -114
- package/dist/components/MaterialUI/Inputs/SelectProps.js +10 -2
- package/dist/hocs/withScrollBox.js +3 -8
- package/dist/hooks/useWindowSize.js +88 -0
- package/dist/sharedMessages.js +8 -0
- package/package.json +1 -1
- package/src/components/Form/Inputs/MultiSelector.js +55 -5
- package/src/components/Form/Inputs/MultiSelector.test.js +259 -39
- package/src/components/Form/Inputs/Selector.js +12 -4
- package/src/components/Form/Inputs/Selector.test.js +27 -12
- package/src/components/MaterialUI/Inputs/Select.js +134 -87
- package/src/components/MaterialUI/Inputs/Select.test.js +170 -30
- package/src/components/MaterialUI/Inputs/SelectProps.js +9 -1
- package/src/components/MaterialUI/Inputs/SelectProps.test.js +8 -0
- package/src/hocs/withScrollBox.js +2 -8
- package/src/hooks/useMultipleFieldEditState.test.js +0 -1
- package/src/hooks/useWindowSize.js +39 -0
- package/src/hooks/useWindowSize.test.js +68 -0
- package/src/sharedMessages.js +8 -0
- package/src/translations/en-US.json +2 -0
- package/src/translations/fr-CA.json +2 -0
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.useWindowSize = exports.default = void 0;
|
|
5
|
+
var _react = require("react");
|
|
6
|
+
(function () {
|
|
7
|
+
var enterModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.enterModule : undefined;
|
|
8
|
+
enterModule && enterModule(module);
|
|
9
|
+
})();
|
|
10
|
+
(function () {
|
|
11
|
+
var enterModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.enterModule : undefined;
|
|
12
|
+
enterModule && enterModule(module);
|
|
13
|
+
})();
|
|
14
|
+
function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); }
|
|
15
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
16
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
17
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
18
|
+
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
|
|
19
|
+
function _arrayWithHoles(r) { if (Array.isArray(r)) return r; }
|
|
20
|
+
var __signature__ = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default.signature : function (a) {
|
|
21
|
+
return a;
|
|
22
|
+
};
|
|
23
|
+
var __signature__ = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default.signature : function (a) {
|
|
24
|
+
return a;
|
|
25
|
+
};
|
|
26
|
+
var useWindowSize = exports.useWindowSize = function useWindowSize() {
|
|
27
|
+
var _useState = (0, _react.useState)({
|
|
28
|
+
innerWidth: window.innerWidth,
|
|
29
|
+
innerHeight: window.innerHeight,
|
|
30
|
+
outerWidth: window.outerWidth,
|
|
31
|
+
outerHeight: window.outerHeight
|
|
32
|
+
}),
|
|
33
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
34
|
+
windowSize = _useState2[0],
|
|
35
|
+
setWindowSize = _useState2[1];
|
|
36
|
+
(0, _react.useEffect)(function () {
|
|
37
|
+
var handleResize = function handleResize() {
|
|
38
|
+
var haveChanged = windowSize.innerWidth !== window.innerWidth || windowSize.innerHeight !== window.innerHeight || windowSize.outerWidth !== window.outerWidth || windowSize.outerHeight !== window.outerHeight;
|
|
39
|
+
if (haveChanged) {
|
|
40
|
+
setWindowSize({
|
|
41
|
+
innerWidth: window.innerWidth,
|
|
42
|
+
innerHeight: window.innerHeight,
|
|
43
|
+
outerWidth: window.outerWidth,
|
|
44
|
+
outerHeight: window.outerHeight
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
handleResize();
|
|
49
|
+
window.addEventListener("resize", handleResize);
|
|
50
|
+
return function () {
|
|
51
|
+
return window.removeEventListener("resize", handleResize);
|
|
52
|
+
};
|
|
53
|
+
}, [windowSize]);
|
|
54
|
+
return windowSize;
|
|
55
|
+
};
|
|
56
|
+
__signature__(useWindowSize, "useState{[windowSize, setWindowSize]({\n\t\tinnerWidth: window.innerWidth,\n\t\tinnerHeight: window.innerHeight,\n\t\touterWidth: window.outerWidth,\n\t\touterHeight: window.outerHeight,\n\t})}\nuseEffect{}");
|
|
57
|
+
__signature__(useWindowSize, "useState{[windowSize, setWindowSize]({\n\t\tinnerWidth: window.innerWidth,\n\t\tinnerHeight: window.innerHeight,\n\t\touterWidth: window.outerWidth,\n\t\touterHeight: window.outerHeight,\n\t})}\nuseEffect{}");
|
|
58
|
+
var _default = useWindowSize;
|
|
59
|
+
var _default2 = _default;
|
|
60
|
+
var _default3 = exports.default = _default2;
|
|
61
|
+
;
|
|
62
|
+
(function () {
|
|
63
|
+
var reactHotLoader = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default : undefined;
|
|
64
|
+
if (!reactHotLoader) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
reactHotLoader.register(useWindowSize, "useWindowSize", "/home/vsts/work/1/s/src/hooks/useWindowSize.js");
|
|
68
|
+
reactHotLoader.register(_default, "default", "/home/vsts/work/1/s/src/hooks/useWindowSize.js");
|
|
69
|
+
})();
|
|
70
|
+
;
|
|
71
|
+
(function () {
|
|
72
|
+
var leaveModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.leaveModule : undefined;
|
|
73
|
+
leaveModule && leaveModule(module);
|
|
74
|
+
})();
|
|
75
|
+
;
|
|
76
|
+
(function () {
|
|
77
|
+
var reactHotLoader = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.default : undefined;
|
|
78
|
+
if (!reactHotLoader) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
reactHotLoader.register(useWindowSize, "useWindowSize", "/home/vsts/work/1/s/src/hooks/useWindowSize.js");
|
|
82
|
+
reactHotLoader.register(_default2, "default", "/home/vsts/work/1/s/src/hooks/useWindowSize.js");
|
|
83
|
+
})();
|
|
84
|
+
;
|
|
85
|
+
(function () {
|
|
86
|
+
var leaveModule = typeof reactHotLoaderGlobal !== 'undefined' ? reactHotLoaderGlobal.leaveModule : undefined;
|
|
87
|
+
leaveModule && leaveModule(module);
|
|
88
|
+
})();
|
package/dist/sharedMessages.js
CHANGED
|
@@ -497,6 +497,14 @@ var sharedMessages = (0, _reactIntl.defineMessages)({
|
|
|
497
497
|
december: {
|
|
498
498
|
id: "orc-shared.december",
|
|
499
499
|
defaultMessage: "December"
|
|
500
|
+
},
|
|
501
|
+
selectAll: {
|
|
502
|
+
id: "orc-shared.selectAll",
|
|
503
|
+
defaultMessage: "Select All"
|
|
504
|
+
},
|
|
505
|
+
clear: {
|
|
506
|
+
id: "orc-shared.clear",
|
|
507
|
+
defaultMessage: "Clear"
|
|
500
508
|
}
|
|
501
509
|
});
|
|
502
510
|
var _default = sharedMessages;
|
package/package.json
CHANGED
|
@@ -1,23 +1,73 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import { useIntl } from "react-intl";
|
|
2
3
|
import Select from "../../MaterialUI/Inputs/Select";
|
|
3
|
-
import { memoize } from "../../../utils";
|
|
4
4
|
import SelectProps from "../../MaterialUI/Inputs/SelectProps";
|
|
5
|
+
import sharedMessages from "../../../sharedMessages";
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
const clearValue = "__#Clear#__";
|
|
8
|
+
const selectAllValue = "__#SelectAll#__";
|
|
9
|
+
|
|
10
|
+
const MultiSelector = ({ value, width = 700, options, update, addClearSelectAll, multipleRenderValue, ...props }) => {
|
|
11
|
+
const { formatMessage } = useIntl();
|
|
12
|
+
|
|
13
|
+
const valueUpdater = value => {
|
|
14
|
+
if (value.indexOf(clearValue) >= 0) {
|
|
15
|
+
update([]);
|
|
16
|
+
} else if (value.indexOf(selectAllValue) >= 0) {
|
|
17
|
+
update(options.map(x => x.value));
|
|
18
|
+
} else {
|
|
19
|
+
update(value);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
7
22
|
|
|
8
|
-
const MultiSelector = ({ value, options, update, ...props }) => {
|
|
9
23
|
const selectProps = new SelectProps();
|
|
10
24
|
|
|
25
|
+
const selectionOptions = [];
|
|
26
|
+
|
|
27
|
+
if (addClearSelectAll) {
|
|
28
|
+
if (value.length > 0) {
|
|
29
|
+
selectionOptions.push({
|
|
30
|
+
label: formatMessage(sharedMessages.clear),
|
|
31
|
+
value: clearValue,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (value.length !== options.length) {
|
|
35
|
+
selectionOptions.push({
|
|
36
|
+
label: formatMessage(sharedMessages.selectAll),
|
|
37
|
+
value: selectAllValue,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const allOptions = [...selectionOptions, ...options];
|
|
43
|
+
|
|
11
44
|
selectProps.set(SelectProps.propNames.value, value);
|
|
12
45
|
selectProps.set(SelectProps.propNames.onClose, props.onBlur);
|
|
13
46
|
selectProps.set(SelectProps.propNames.disabled, props.disabled);
|
|
14
47
|
selectProps.set(SelectProps.propNames.multiple, true);
|
|
15
|
-
selectProps.set(SelectProps.propNames.
|
|
48
|
+
selectProps.set(SelectProps.propNames.multipleSelectWidth, width);
|
|
49
|
+
selectProps.set(SelectProps.propNames.update, valueUpdater);
|
|
50
|
+
selectProps.set(SelectProps.propNames.autoWidth, false);
|
|
51
|
+
selectProps.set(SelectProps.propNames.autoFocus, false);
|
|
52
|
+
selectProps.set(
|
|
53
|
+
SelectProps.propNames.renderValue,
|
|
54
|
+
multipleRenderValue ? () => multipleRenderValue(value, options) : null,
|
|
55
|
+
);
|
|
56
|
+
selectProps.set(SelectProps.propNames.positionOverride, {
|
|
57
|
+
anchorOrigin: {
|
|
58
|
+
vertical: "bottom",
|
|
59
|
+
horizontal: "left",
|
|
60
|
+
},
|
|
61
|
+
transformOrigin: {
|
|
62
|
+
vertical: "top",
|
|
63
|
+
horizontal: "left",
|
|
64
|
+
},
|
|
65
|
+
});
|
|
16
66
|
|
|
17
67
|
const hasError = props.required && (!Array.isArray(value) || value.length === 0);
|
|
18
68
|
selectProps.set(SelectProps.propNames.error, hasError);
|
|
19
69
|
|
|
20
|
-
return <Select options={
|
|
70
|
+
return <Select options={allOptions} selectProps={selectProps} />;
|
|
21
71
|
};
|
|
22
72
|
|
|
23
73
|
export default MultiSelector;
|
|
@@ -1,17 +1,23 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import sinon from "sinon";
|
|
3
|
-
import MultiSelector
|
|
4
|
-
import { TestWrapper, createMuiTheme } from "../../../utils/testUtils";
|
|
3
|
+
import MultiSelector from "./MultiSelector";
|
|
4
|
+
import { TestWrapper, createMuiTheme, extractMessages } from "../../../utils/testUtils";
|
|
5
5
|
import Immutable from "immutable";
|
|
6
6
|
import SelectMUI from "@material-ui/core/Select";
|
|
7
7
|
import MenuItem from "@material-ui/core/MenuItem";
|
|
8
8
|
import TooltippedTypography from "../../MaterialUI/DataDisplay/TooltippedElements/TooltippedTypography";
|
|
9
9
|
import Icon from "../../MaterialUI/DataDisplay/Icon";
|
|
10
|
+
import FormControl from "@material-ui/core/FormControl";
|
|
11
|
+
import { render, screen, fireEvent } from "@testing-library/react";
|
|
12
|
+
import sharedMessages from "../../../sharedMessages";
|
|
13
|
+
|
|
14
|
+
const messages = extractMessages(sharedMessages);
|
|
10
15
|
|
|
11
16
|
describe("MultiSelector", () => {
|
|
12
|
-
let update, state, store, chevronDown;
|
|
17
|
+
let update, state, store, chevronDown, multipleRenderValue;
|
|
13
18
|
beforeEach(() => {
|
|
14
19
|
update = sinon.spy().named("update");
|
|
20
|
+
multipleRenderValue = sinon.fake.returns("En, It");
|
|
15
21
|
|
|
16
22
|
state = Immutable.fromJS({
|
|
17
23
|
locale: {
|
|
@@ -34,7 +40,7 @@ describe("MultiSelector", () => {
|
|
|
34
40
|
|
|
35
41
|
it("renders a multi selector with multiple options", () =>
|
|
36
42
|
expect(
|
|
37
|
-
<TestWrapper provider={{ store }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
|
|
43
|
+
<TestWrapper provider={{ store }} intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
|
|
38
44
|
<MultiSelector
|
|
39
45
|
update={update}
|
|
40
46
|
value={["English"]}
|
|
@@ -46,32 +52,34 @@ describe("MultiSelector", () => {
|
|
|
46
52
|
</TestWrapper>,
|
|
47
53
|
"when mounted",
|
|
48
54
|
"to satisfy",
|
|
49
|
-
<TestWrapper provider={{ store }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
<TestWrapper provider={{ store }} intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
|
|
56
|
+
<FormControl>
|
|
57
|
+
<SelectMUI
|
|
58
|
+
value={["English"]}
|
|
59
|
+
disableUnderline={true}
|
|
60
|
+
IconComponent={chevronDown}
|
|
61
|
+
error={false}
|
|
62
|
+
multiple={true}
|
|
63
|
+
renderValue={selected => selected.join(", ")}
|
|
64
|
+
>
|
|
65
|
+
<MenuItem key="English" value="English">
|
|
66
|
+
<TooltippedTypography children="English" titleValue="English" />
|
|
67
|
+
</MenuItem>
|
|
68
|
+
<MenuItem key="Francais" value="Francais">
|
|
69
|
+
<TooltippedTypography noWrap children="Francais" titleValue="Francais" />
|
|
70
|
+
</MenuItem>
|
|
71
|
+
</SelectMUI>
|
|
72
|
+
</FormControl>
|
|
65
73
|
</TestWrapper>,
|
|
66
74
|
));
|
|
67
75
|
|
|
68
|
-
it("renders a multi selector with
|
|
76
|
+
it("renders a multi selector with select all and clear options without errors", () =>
|
|
69
77
|
expect(
|
|
70
|
-
<TestWrapper provider={{ store }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
|
|
78
|
+
<TestWrapper provider={{ store }} intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
|
|
71
79
|
<MultiSelector
|
|
72
80
|
update={update}
|
|
73
|
-
|
|
74
|
-
value={[]}
|
|
81
|
+
addClearSelectAll={true}
|
|
82
|
+
value={["English"]}
|
|
75
83
|
options={[
|
|
76
84
|
{ value: "English", label: "English" },
|
|
77
85
|
{ value: "Francais", label: "Francais" },
|
|
@@ -80,9 +88,16 @@ describe("MultiSelector", () => {
|
|
|
80
88
|
</TestWrapper>,
|
|
81
89
|
"when mounted",
|
|
82
90
|
"to satisfy",
|
|
83
|
-
<TestWrapper provider={{ store }} intlProvider stylesProvider muiThemeProvider={{ theme }}>
|
|
84
|
-
<
|
|
85
|
-
<SelectMUI
|
|
91
|
+
<TestWrapper provider={{ store }} intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
|
|
92
|
+
<FormControl>
|
|
93
|
+
<SelectMUI
|
|
94
|
+
value={["English"]}
|
|
95
|
+
disableUnderline={true}
|
|
96
|
+
IconComponent={chevronDown}
|
|
97
|
+
error={false}
|
|
98
|
+
multiple={false}
|
|
99
|
+
renderValue={selected => selected.join(", ")}
|
|
100
|
+
>
|
|
86
101
|
<MenuItem key="English" value="English">
|
|
87
102
|
<TooltippedTypography children="English" titleValue="English" />
|
|
88
103
|
</MenuItem>
|
|
@@ -90,23 +105,228 @@ describe("MultiSelector", () => {
|
|
|
90
105
|
<TooltippedTypography noWrap children="Francais" titleValue="Francais" />
|
|
91
106
|
</MenuItem>
|
|
92
107
|
</SelectMUI>
|
|
93
|
-
|
|
94
|
-
</div>
|
|
108
|
+
</FormControl>
|
|
95
109
|
</TestWrapper>,
|
|
110
|
+
));
|
|
111
|
+
|
|
112
|
+
it("Expect multipleRenderValue to be called and selection to be rendered correctly", () => {
|
|
113
|
+
const allOptions = [
|
|
114
|
+
{ value: "English", label: "English" },
|
|
115
|
+
{ value: "Francais", label: "Francais" },
|
|
116
|
+
{ value: "Italiano", label: "Italiano" },
|
|
117
|
+
];
|
|
118
|
+
|
|
119
|
+
const multiSelector = (
|
|
120
|
+
<TestWrapper provider={{ store }} intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
|
|
121
|
+
<MultiSelector
|
|
122
|
+
update={update}
|
|
123
|
+
multipleRenderValue={multipleRenderValue}
|
|
124
|
+
value={["English", "Italiano"]}
|
|
125
|
+
options={allOptions}
|
|
126
|
+
/>
|
|
127
|
+
</TestWrapper>
|
|
96
128
|
);
|
|
129
|
+
|
|
130
|
+
render(multiSelector);
|
|
131
|
+
|
|
132
|
+
const selectionText = screen.queryByText("En, It");
|
|
133
|
+
|
|
134
|
+
expect(selectionText, "not to be null");
|
|
135
|
+
expect(multipleRenderValue, "to have a call satisfying", { args: [["English", "Italiano"], allOptions] });
|
|
97
136
|
});
|
|
98
|
-
});
|
|
99
137
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
138
|
+
it("Expect to have both 'Select All' and 'Clear' options to be available with partial selection", () => {
|
|
139
|
+
const multiSelector = (
|
|
140
|
+
<TestWrapper provider={{ store }} intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
|
|
141
|
+
<MultiSelector
|
|
142
|
+
update={update}
|
|
143
|
+
addClearSelectAll={true}
|
|
144
|
+
value={["English"]}
|
|
145
|
+
options={[
|
|
146
|
+
{ value: "English", label: "English" },
|
|
147
|
+
{ value: "Francais", label: "Francais" },
|
|
148
|
+
]}
|
|
149
|
+
/>
|
|
150
|
+
</TestWrapper>
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
render(multiSelector);
|
|
154
|
+
|
|
155
|
+
const selectButton = screen.getByRole("button");
|
|
156
|
+
fireEvent.mouseDown(selectButton);
|
|
157
|
+
|
|
158
|
+
const selectAllOption = screen.queryByText("Select All");
|
|
159
|
+
const clearOption = screen.queryByText("Clear");
|
|
160
|
+
|
|
161
|
+
expect(selectAllOption, "not to be null");
|
|
162
|
+
expect(clearOption, "not to be null");
|
|
104
163
|
});
|
|
105
164
|
|
|
106
|
-
it("
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
165
|
+
it("Expect to have only 'Clear' option to be available with all options being selected", () => {
|
|
166
|
+
const multiSelector = (
|
|
167
|
+
<TestWrapper provider={{ store }} intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
|
|
168
|
+
<MultiSelector
|
|
169
|
+
update={update}
|
|
170
|
+
addClearSelectAll={true}
|
|
171
|
+
value={["English", "Francais"]}
|
|
172
|
+
options={[
|
|
173
|
+
{ value: "English", label: "English" },
|
|
174
|
+
{ value: "Francais", label: "Francais" },
|
|
175
|
+
]}
|
|
176
|
+
/>
|
|
177
|
+
</TestWrapper>
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
render(multiSelector);
|
|
181
|
+
|
|
182
|
+
const selectButton = screen.getByRole("button");
|
|
183
|
+
fireEvent.mouseDown(selectButton);
|
|
184
|
+
|
|
185
|
+
const selectAllOption = screen.queryByText("Select All");
|
|
186
|
+
const clearOption = screen.queryByText("Clear");
|
|
187
|
+
|
|
188
|
+
expect(selectAllOption, "to be null");
|
|
189
|
+
expect(clearOption, "not to be null");
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("Expect to have only 'Select All' option to be available with an empty selection", () => {
|
|
193
|
+
const multiSelector = (
|
|
194
|
+
<TestWrapper provider={{ store }} intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
|
|
195
|
+
<MultiSelector
|
|
196
|
+
update={update}
|
|
197
|
+
addClearSelectAll={true}
|
|
198
|
+
value={[]}
|
|
199
|
+
options={[
|
|
200
|
+
{ value: "English", label: "English" },
|
|
201
|
+
{ value: "Francais", label: "Francais" },
|
|
202
|
+
]}
|
|
203
|
+
/>
|
|
204
|
+
</TestWrapper>
|
|
205
|
+
);
|
|
206
|
+
|
|
207
|
+
render(multiSelector);
|
|
208
|
+
|
|
209
|
+
const selectButton = screen.getByRole("button");
|
|
210
|
+
fireEvent.mouseDown(selectButton);
|
|
211
|
+
|
|
212
|
+
const selectAllOption = screen.queryByText("Select All");
|
|
213
|
+
const clearOption = screen.queryByText("Clear");
|
|
110
214
|
|
|
111
|
-
|
|
215
|
+
expect(selectAllOption, "not to be null");
|
|
216
|
+
expect(clearOption, "to be null");
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it("Picking one selection should update with it along with existing ones", () => {
|
|
220
|
+
const multiSelector = (
|
|
221
|
+
<TestWrapper provider={{ store }} intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
|
|
222
|
+
<MultiSelector
|
|
223
|
+
update={update}
|
|
224
|
+
addClearSelectAll={true}
|
|
225
|
+
value={["English"]}
|
|
226
|
+
options={[
|
|
227
|
+
{ value: "English", label: "English" },
|
|
228
|
+
{ value: "Francais", label: "Francais" },
|
|
229
|
+
{ value: "Italiano", label: "Italiano" },
|
|
230
|
+
]}
|
|
231
|
+
/>
|
|
232
|
+
</TestWrapper>
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
render(multiSelector);
|
|
236
|
+
|
|
237
|
+
const selectButton = screen.getByRole("button");
|
|
238
|
+
fireEvent.mouseDown(selectButton);
|
|
239
|
+
|
|
240
|
+
const optionToSelect = screen.getByText("Italiano");
|
|
241
|
+
fireEvent.click(optionToSelect);
|
|
242
|
+
|
|
243
|
+
expect(update, "to have calls satisfying", [{ args: [["English", "Italiano"]] }]);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it("The 'Select All' option should update with all values", () => {
|
|
247
|
+
const multiSelector = (
|
|
248
|
+
<TestWrapper provider={{ store }} intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
|
|
249
|
+
<MultiSelector
|
|
250
|
+
update={update}
|
|
251
|
+
addClearSelectAll={true}
|
|
252
|
+
value={["English"]}
|
|
253
|
+
options={[
|
|
254
|
+
{ value: "English", label: "English" },
|
|
255
|
+
{ value: "Francais", label: "Francais" },
|
|
256
|
+
{ value: "Italiano", label: "Italiano" },
|
|
257
|
+
]}
|
|
258
|
+
/>
|
|
259
|
+
</TestWrapper>
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
render(multiSelector);
|
|
263
|
+
|
|
264
|
+
const selectButton = screen.getByRole("button");
|
|
265
|
+
fireEvent.mouseDown(selectButton);
|
|
266
|
+
|
|
267
|
+
const optionToSelect = screen.getByText("Select All");
|
|
268
|
+
fireEvent.click(optionToSelect);
|
|
269
|
+
|
|
270
|
+
expect(update, "to have calls satisfying", [{ args: [["English", "Francais", "Italiano"]] }]);
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
it("The 'Clear' option should update with an empty list", () => {
|
|
274
|
+
const multiSelector = (
|
|
275
|
+
<TestWrapper provider={{ store }} intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
|
|
276
|
+
<MultiSelector
|
|
277
|
+
update={update}
|
|
278
|
+
addClearSelectAll={true}
|
|
279
|
+
value={["English"]}
|
|
280
|
+
options={[
|
|
281
|
+
{ value: "English", label: "English" },
|
|
282
|
+
{ value: "Francais", label: "Francais" },
|
|
283
|
+
{ value: "Italiano", label: "Italiano" },
|
|
284
|
+
]}
|
|
285
|
+
/>
|
|
286
|
+
</TestWrapper>
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
render(multiSelector);
|
|
290
|
+
|
|
291
|
+
const selectButton = screen.getByRole("button");
|
|
292
|
+
fireEvent.mouseDown(selectButton);
|
|
293
|
+
|
|
294
|
+
const optionToSelect = screen.getByText("Clear");
|
|
295
|
+
fireEvent.click(optionToSelect);
|
|
296
|
+
|
|
297
|
+
expect(update, "to have calls satisfying", [{ args: [[]] }]);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
it("renders a multi selector with an error", () => {
|
|
301
|
+
expect(
|
|
302
|
+
<TestWrapper provider={{ store }} intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
|
|
303
|
+
<MultiSelector
|
|
304
|
+
update={update}
|
|
305
|
+
required={true}
|
|
306
|
+
value={[]}
|
|
307
|
+
options={[
|
|
308
|
+
{ value: "English", label: "English" },
|
|
309
|
+
{ value: "Francais", label: "Francais" },
|
|
310
|
+
]}
|
|
311
|
+
/>
|
|
312
|
+
</TestWrapper>,
|
|
313
|
+
"when mounted",
|
|
314
|
+
"to satisfy",
|
|
315
|
+
<TestWrapper provider={{ store }} intlProvider={{ messages }} stylesProvider muiThemeProvider={{ theme }}>
|
|
316
|
+
<FormControl>
|
|
317
|
+
<div>
|
|
318
|
+
<SelectMUI value={[""]} disableUnderline={true} IconComponent={chevronDown} error={true} multiple={true}>
|
|
319
|
+
<MenuItem key="English" value="English">
|
|
320
|
+
<TooltippedTypography children="English" titleValue="English" />
|
|
321
|
+
</MenuItem>
|
|
322
|
+
<MenuItem key="Francais" value="Francais">
|
|
323
|
+
<TooltippedTypography noWrap children="Francais" titleValue="Francais" />
|
|
324
|
+
</MenuItem>
|
|
325
|
+
</SelectMUI>
|
|
326
|
+
<div></div>
|
|
327
|
+
</div>
|
|
328
|
+
</FormControl>
|
|
329
|
+
</TestWrapper>,
|
|
330
|
+
);
|
|
331
|
+
});
|
|
112
332
|
});
|
|
@@ -1,17 +1,25 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import Select from "../../MaterialUI/Inputs/Select";
|
|
3
|
-
import { memoize } from "../../../utils";
|
|
4
3
|
import SelectProps from "../../MaterialUI/Inputs/SelectProps";
|
|
5
4
|
|
|
6
|
-
export const selectEventUpdater = memoize(update => value => update(value));
|
|
7
|
-
|
|
8
5
|
const Selector = ({ value, options, update, ...props }) => {
|
|
9
6
|
const selectProps = new SelectProps();
|
|
10
7
|
|
|
11
8
|
selectProps.set(SelectProps.propNames.value, value);
|
|
12
9
|
selectProps.set(SelectProps.propNames.onClose, props.onBlur);
|
|
13
10
|
selectProps.set(SelectProps.propNames.disabled, props.disabled);
|
|
14
|
-
selectProps.set(SelectProps.propNames.update,
|
|
11
|
+
selectProps.set(SelectProps.propNames.update, update);
|
|
12
|
+
selectProps.set(SelectProps.propNames.autoWidth, false);
|
|
13
|
+
selectProps.set(SelectProps.propNames.positionOverride, {
|
|
14
|
+
anchorOrigin: {
|
|
15
|
+
vertical: "bottom",
|
|
16
|
+
horizontal: "left",
|
|
17
|
+
},
|
|
18
|
+
transformOrigin: {
|
|
19
|
+
vertical: "top",
|
|
20
|
+
horizontal: "left",
|
|
21
|
+
},
|
|
22
|
+
});
|
|
15
23
|
|
|
16
24
|
const hasError = props.required && !value ? true : false;
|
|
17
25
|
selectProps.set(SelectProps.propNames.error, hasError);
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import sinon from "sinon";
|
|
3
|
-
import Selector
|
|
3
|
+
import Selector from "./Selector";
|
|
4
4
|
import { TestWrapper, createMuiTheme } from "./../../../utils/testUtils";
|
|
5
5
|
import Immutable from "immutable";
|
|
6
6
|
import SelectMUI from "@material-ui/core/Select";
|
|
7
7
|
import MenuItem from "@material-ui/core/MenuItem";
|
|
8
8
|
import TooltippedTypography from "../../MaterialUI/DataDisplay/TooltippedElements/TooltippedTypography";
|
|
9
9
|
import Icon from "../../MaterialUI/DataDisplay/Icon";
|
|
10
|
+
import { mount } from "enzyme";
|
|
10
11
|
|
|
11
12
|
describe("Selector", () => {
|
|
12
13
|
let update, state, store, chevronDown;
|
|
@@ -88,18 +89,32 @@ describe("Selector", () => {
|
|
|
88
89
|
</TestWrapper>,
|
|
89
90
|
);
|
|
90
91
|
});
|
|
91
|
-
});
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
93
|
+
it("Update is invoked when selection has changed", () => {
|
|
94
|
+
const mountedComponent = mount(
|
|
95
|
+
<TestWrapper provider={{ store }} stylesProvider muiThemeProvider intlProvider>
|
|
96
|
+
<Selector
|
|
97
|
+
update={update}
|
|
98
|
+
required={true}
|
|
99
|
+
value={null}
|
|
100
|
+
options={[
|
|
101
|
+
{ value: "English", label: "English" },
|
|
102
|
+
{ value: "Francais", label: "Francais" },
|
|
103
|
+
]}
|
|
104
|
+
/>
|
|
105
|
+
</TestWrapper>,
|
|
106
|
+
);
|
|
98
107
|
|
|
99
|
-
|
|
100
|
-
expect(selectEventUpdater, "called with", [update], "called with", ["foo"]).then(() =>
|
|
101
|
-
expect(update, "to have calls satisfying", [{ args: ["foo"] }]),
|
|
102
|
-
));
|
|
108
|
+
const selectMui = mountedComponent.find(SelectMUI);
|
|
103
109
|
|
|
104
|
-
|
|
110
|
+
const event = {
|
|
111
|
+
target: {
|
|
112
|
+
value: "Francais",
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
selectMui.invoke("onChange")(event);
|
|
117
|
+
|
|
118
|
+
expect(update, "to have calls satisfying", [{ args: ["Francais"] }]);
|
|
119
|
+
});
|
|
105
120
|
});
|