orc-shared 5.99.0-dev.5 → 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.
@@ -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
+ })();
@@ -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,6 +1,6 @@
1
1
  {
2
2
  "name": "orc-shared",
3
- "version": "5.99.0-dev.5",
3
+ "version": "5.99.0-dev.6",
4
4
  "description": "Shared code for Orckestra applications",
5
5
  "main": "./src/index.js",
6
6
  "exports": {
@@ -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
- export const selectEventUpdater = memoize(update => value => update(value));
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.update, selectEventUpdater(update));
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={options} selectProps={selectProps} />;
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, { selectEventUpdater } from "./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
- <SelectMUI
51
- value={["English"]}
52
- disableUnderline={true}
53
- IconComponent={chevronDown}
54
- error={false}
55
- multiple={true}
56
- renderValue={selected => selected.join(", ")}
57
- >
58
- <MenuItem key="English" value="English">
59
- <TooltippedTypography children="English" titleValue="English" />
60
- </MenuItem>
61
- <MenuItem key="Francais" value="Francais">
62
- <TooltippedTypography noWrap children="Francais" titleValue="Francais" />
63
- </MenuItem>
64
- </SelectMUI>
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 an error", () => {
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
- required={true}
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
- <div>
85
- <SelectMUI value={[""]} disableUnderline={true} IconComponent={chevronDown} error={true} multiple={true}>
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
- <div></div>
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
- describe("selectEventUpdater", () => {
101
- let update;
102
- beforeEach(() => {
103
- update = sinon.spy().named("update");
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("creates a handler for an event and calls update with the value of the target", () =>
107
- expect(selectEventUpdater, "called with", [update], "called with", ["foo"]).then(() =>
108
- expect(update, "to have calls satisfying", [{ args: ["foo"] }]),
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
- it("is memoized", () => expect(selectEventUpdater, "called with", [update], "to be", selectEventUpdater(update)));
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, selectEventUpdater(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, { selectEventUpdater } from "./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
- describe("selectEventUpdater", () => {
94
- let update;
95
- beforeEach(() => {
96
- update = sinon.spy().named("update");
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
- it("creates a handler for an event and calls update with the value of the target", () =>
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
- it("is memoized", () => expect(selectEventUpdater, "called with", [update], "to be", selectEventUpdater(update)));
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
  });