@reltio/components 1.4.2282 → 1.4.2284

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.
@@ -26,18 +26,22 @@ export function DropDownMenuButton(_a) {
26
26
  var styles = useStyles();
27
27
  var buttonRef = useRef(null);
28
28
  var _k = useState(false), isOpen = _k[0], setIsOpen = _k[1];
29
+ // onMenuOpen is fired synchronously in the click handler (below) so it wins the race against a
30
+ // parent's onMouseLeave when the button lives in an unmounting hover overlay; onMenuClose stays
31
+ // deferred to this effect so consumers can keep the button mounted (e.g. delete confirmation).
29
32
  useDidUpdateEffect(function () {
30
- if (isOpen) {
31
- onMenuOpen();
32
- }
33
- else {
33
+ if (!isOpen) {
34
34
  onMenuClose();
35
35
  }
36
36
  }, [isOpen]);
37
37
  var handleToggle = useCallback(function (e) {
38
38
  e === null || e === void 0 ? void 0 : e.stopPropagation();
39
- setIsOpen(function (open) { return !open; });
40
- }, []);
39
+ var nextIsOpen = !isOpen;
40
+ setIsOpen(nextIsOpen);
41
+ if (nextIsOpen) {
42
+ onMenuOpen();
43
+ }
44
+ }, [isOpen, onMenuOpen]);
41
45
  var renderMenuItem = function (item, index) {
42
46
  return React.createElement(MenuItemRenderer, { item: item, key: index, onMenuClose: handleToggle });
43
47
  };
@@ -45,6 +45,17 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
45
45
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
46
46
  }
47
47
  };
48
+ var __rest = (this && this.__rest) || function (s, e) {
49
+ var t = {};
50
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
51
+ t[p] = s[p];
52
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
53
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
54
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
55
+ t[p[i]] = s[p[i]];
56
+ }
57
+ return t;
58
+ };
48
59
  import React from 'react';
49
60
  import { render, screen, within } from '@testing-library/react';
50
61
  import userEvent from '@testing-library/user-event';
@@ -104,4 +115,29 @@ describe('Dropdown menu button tests', function () {
104
115
  }
105
116
  });
106
117
  }); });
118
+ it('should call onMenuOpen synchronously within the click handler, before it is deferred to an effect', function () { return __awaiter(void 0, void 0, void 0, function () {
119
+ var callOrder, ButtonComponent, onMenuOpen, user;
120
+ return __generator(this, function (_a) {
121
+ switch (_a.label) {
122
+ case 0:
123
+ callOrder = [];
124
+ ButtonComponent = React.forwardRef(function (_a, ref) {
125
+ var onClick = _a.onClick, children = _a.children, rest = __rest(_a, ["onClick", "children"]);
126
+ return (React.createElement("button", __assign({ ref: ref }, rest, { onClick: function (e) {
127
+ onClick === null || onClick === void 0 ? void 0 : onClick(e);
128
+ callOrder.push('afterClick');
129
+ } }), children));
130
+ });
131
+ ButtonComponent.displayName = 'ButtonComponent';
132
+ onMenuOpen = jest.fn(function () { return callOrder.push('menuOpen'); });
133
+ user = setUp(__assign(__assign({}, defaultProps), { buttonComponent: ButtonComponent, onMenuOpen: onMenuOpen })).user;
134
+ return [4 /*yield*/, user.click(screen.getByText('content'))];
135
+ case 1:
136
+ _a.sent();
137
+ expect(onMenuOpen).toHaveBeenCalledTimes(1);
138
+ expect(callOrder).toEqual(['menuOpen', 'afterClick']);
139
+ return [2 /*return*/];
140
+ }
141
+ });
142
+ }); });
107
143
  });
@@ -55,18 +55,22 @@ function DropDownMenuButton(_a) {
55
55
  var styles = (0, styles_1.useStyles)();
56
56
  var buttonRef = (0, react_1.useRef)(null);
57
57
  var _k = (0, react_1.useState)(false), isOpen = _k[0], setIsOpen = _k[1];
58
+ // onMenuOpen is fired synchronously in the click handler (below) so it wins the race against a
59
+ // parent's onMouseLeave when the button lives in an unmounting hover overlay; onMenuClose stays
60
+ // deferred to this effect so consumers can keep the button mounted (e.g. delete confirmation).
58
61
  (0, useDidUpdateEffect_1.useDidUpdateEffect)(function () {
59
- if (isOpen) {
60
- onMenuOpen();
61
- }
62
- else {
62
+ if (!isOpen) {
63
63
  onMenuClose();
64
64
  }
65
65
  }, [isOpen]);
66
66
  var handleToggle = (0, react_1.useCallback)(function (e) {
67
67
  e === null || e === void 0 ? void 0 : e.stopPropagation();
68
- setIsOpen(function (open) { return !open; });
69
- }, []);
68
+ var nextIsOpen = !isOpen;
69
+ setIsOpen(nextIsOpen);
70
+ if (nextIsOpen) {
71
+ onMenuOpen();
72
+ }
73
+ }, [isOpen, onMenuOpen]);
70
74
  var renderMenuItem = function (item, index) {
71
75
  return react_1.default.createElement(MenuItemRenderer, { item: item, key: index, onMenuClose: handleToggle });
72
76
  };
@@ -46,6 +46,17 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
46
46
  if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
47
  }
48
48
  };
49
+ var __rest = (this && this.__rest) || function (s, e) {
50
+ var t = {};
51
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
52
+ t[p] = s[p];
53
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
54
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
55
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
56
+ t[p[i]] = s[p[i]];
57
+ }
58
+ return t;
59
+ };
49
60
  var __importDefault = (this && this.__importDefault) || function (mod) {
50
61
  return (mod && mod.__esModule) ? mod : { "default": mod };
51
62
  };
@@ -109,4 +120,29 @@ describe('Dropdown menu button tests', function () {
109
120
  }
110
121
  });
111
122
  }); });
123
+ it('should call onMenuOpen synchronously within the click handler, before it is deferred to an effect', function () { return __awaiter(void 0, void 0, void 0, function () {
124
+ var callOrder, ButtonComponent, onMenuOpen, user;
125
+ return __generator(this, function (_a) {
126
+ switch (_a.label) {
127
+ case 0:
128
+ callOrder = [];
129
+ ButtonComponent = react_1.default.forwardRef(function (_a, ref) {
130
+ var onClick = _a.onClick, children = _a.children, rest = __rest(_a, ["onClick", "children"]);
131
+ return (react_1.default.createElement("button", __assign({ ref: ref }, rest, { onClick: function (e) {
132
+ onClick === null || onClick === void 0 ? void 0 : onClick(e);
133
+ callOrder.push('afterClick');
134
+ } }), children));
135
+ });
136
+ ButtonComponent.displayName = 'ButtonComponent';
137
+ onMenuOpen = jest.fn(function () { return callOrder.push('menuOpen'); });
138
+ user = setUp(__assign(__assign({}, defaultProps), { buttonComponent: ButtonComponent, onMenuOpen: onMenuOpen })).user;
139
+ return [4 /*yield*/, user.click(react_2.screen.getByText('content'))];
140
+ case 1:
141
+ _a.sent();
142
+ expect(onMenuOpen).toHaveBeenCalledTimes(1);
143
+ expect(callOrder).toEqual(['menuOpen', 'afterClick']);
144
+ return [2 /*return*/];
145
+ }
146
+ });
147
+ }); });
112
148
  });
@@ -37,6 +37,7 @@ var useAPI = function (config) {
37
37
  var workerRef = (0, react_1.useRef)(null);
38
38
  var entityRef = (0, react_1.useRef)(null);
39
39
  var searchQueryRef = (0, react_1.useRef)(null);
40
+ var qxApiRef = (0, react_1.useRef)(null);
40
41
  var requestListeners = (0, react_1.useRef)({});
41
42
  var responseListeners = (0, react_1.useRef)({});
42
43
  var sanitizeHtml = (0, useHtmlSanitizer_1.useHtmlSanitizer)();
@@ -148,7 +149,7 @@ var useAPI = function (config) {
148
149
  }
149
150
  case mdm_sdk_1.CustomAction.REQUEST: {
150
151
  var processedTask = (0, customScript_1.getProcessedTask)(task, apiPath, reltioPath, tenant);
151
- (0, API_1.processRequest)(__assign({ params: processedTask.params, permissions: config.action.permissions, worker: worker, metadata: metadata, config: config, user: user, servicesPath: servicesPath, apiPath: reltioPath, tenant: tenant, workflowPath: workflowPath, entity: entityRef.current, entityUri: (_b = entityRef.current) === null || _b === void 0 ? void 0 : _b.uri, environment: environment, query: searchQueryRef.current, openSearch: openSearch, workflowCheckPermission: workflowCheckPermission }, qxApi));
152
+ (0, API_1.processRequest)(__assign({ params: processedTask.params, permissions: config.action.permissions, worker: worker, metadata: metadata, config: config, user: user, servicesPath: servicesPath, apiPath: reltioPath, tenant: tenant, workflowPath: workflowPath, entity: entityRef.current, entityUri: (_b = entityRef.current) === null || _b === void 0 ? void 0 : _b.uri, environment: environment, query: searchQueryRef.current, openSearch: openSearch, workflowCheckPermission: workflowCheckPermission }, qxApiRef.current));
152
153
  break;
153
154
  }
154
155
  case mdm_sdk_1.CustomAction.RETURN_PROCESSED_API_RESPONSE: {
@@ -228,6 +229,9 @@ var useAPI = function (config) {
228
229
  searchQueryRef.current = searchQuery;
229
230
  postEventMessage('changeSearchQuery', searchQuery);
230
231
  }, [searchQuery]);
232
+ (0, react_1.useEffect)(function () {
233
+ qxApiRef.current = qxApi;
234
+ }, [qxApi]);
231
235
  (0, react_1.useEffect)(function () {
232
236
  postEventMessage('changeVisibility', visible);
233
237
  }, [visible]);
@@ -153,18 +153,21 @@ var sandbox = {
153
153
  setEntityUri: jest.fn().mockImplementation(function (entityUri, listener) { return setTimeout(listener, 1000); })
154
154
  };
155
155
  var setUp = function (_a) {
156
- var _b = _a === void 0 ? {} : _a, _c = _b.config, config = _c === void 0 ? (0, config_test_data_1.createConfig)() : _c, _d = _b.mdmValues, mdmValues = _d === void 0 ? defaultMdmValues : _d;
156
+ var _b = _a === void 0 ? {} : _a, _c = _b.config, config = _c === void 0 ? (0, config_test_data_1.createConfig)() : _c, _d = _b.mdmValues, mdmValues = _d === void 0 ? defaultMdmValues : _d, _e = _b.sandboxValue, sandboxValue = _e === void 0 ? sandbox : _e;
157
157
  var updateMdmValues;
158
+ var updateSandbox;
158
159
  var Providers = function (_a) {
159
160
  var children = _a.children;
160
161
  var _b = (0, react_1.useState)(mdmValues), mdmValuesState = _b[0], setMdmValuesState = _b[1];
162
+ var _c = (0, react_1.useState)(sandboxValue), sandboxState = _c[0], setSandboxState = _c[1];
161
163
  updateMdmValues = setMdmValuesState;
164
+ updateSandbox = setSandboxState;
162
165
  return (react_1.default.createElement(MdmModuleContext_1.MdmModuleProvider, { values: mdmValuesState, actions: mdmActions },
163
166
  react_1.default.createElement(SnackbarContext_1.SnackbarContext.Provider, { value: showSnackbarMessage },
164
- react_1.default.createElement(SandboxAPIContext_1.SandboxAPIContext.Provider, { value: sandbox },
167
+ react_1.default.createElement(SandboxAPIContext_1.SandboxAPIContext.Provider, { value: sandboxState },
165
168
  react_1.default.createElement(InterceptHandlersContext_1.InterceptHandlersContext.Provider, { value: interceptors }, children)))));
166
169
  };
167
- return __assign(__assign({}, (0, react_2.renderHook)(useAPI_1.useAPI, { initialProps: config, wrapper: Providers })), { updateMdmValues: updateMdmValues });
170
+ return __assign(__assign({}, (0, react_2.renderHook)(useAPI_1.useAPI, { initialProps: config, wrapper: Providers })), { updateMdmValues: updateMdmValues, updateSandbox: updateSandbox });
168
171
  };
169
172
  describe('useAPI custom sandbox behavior', function () {
170
173
  var postMessage = jest.fn();
@@ -943,6 +946,28 @@ describe('useAPI custom sandbox behavior', function () {
943
946
  return [2 /*return*/];
944
947
  });
945
948
  }); });
949
+ it('should call setEntityUri from the current sandbox after it changes', function () {
950
+ var updateSandbox = setUp().updateSandbox;
951
+ var newSandbox = {
952
+ getCurrentPerspectiveId: jest.fn().mockReturnValue('23'),
953
+ showPerspective: jest.fn(),
954
+ setEntityUri: jest.fn()
955
+ };
956
+ (0, react_2.act)(function () {
957
+ updateSandbox(newSandbox);
958
+ });
959
+ var params = {
960
+ name: mdm_sdk_1.RequestAction.SET_ENTITY_URI,
961
+ id: 23,
962
+ entityUri: 'entities/NEW999'
963
+ };
964
+ (0, react_2.act)(function () {
965
+ onmessageFromWorker({ action: mdm_sdk_1.CustomAction.REQUEST, params: params });
966
+ });
967
+ expect(newSandbox.setEntityUri).toHaveBeenCalledTimes(1);
968
+ expect(newSandbox.setEntityUri.mock.calls[0][0]).toBe(params.entityUri);
969
+ expect(sandbox.setEntityUri).not.toHaveBeenCalled();
970
+ });
946
971
  it('should call showPerspective and getCurrentPerspectiveId from sandbox on setPerspective request', function () {
947
972
  setUp();
948
973
  var params = {
@@ -78,6 +78,7 @@ var useCustomScripts = function (config) {
78
78
  var workers = (0, react_1.useRef)({});
79
79
  var entityRef = (0, react_1.useRef)(null);
80
80
  var searchQueryRef = (0, react_1.useRef)(null);
81
+ var qxApiRef = (0, react_1.useRef)(qxApi);
81
82
  var processMessageFromWorker = function (_a) {
82
83
  var _b;
83
84
  var task = _a.task, worker = _a.worker, config = _a.config;
@@ -93,7 +94,7 @@ var useCustomScripts = function (config) {
93
94
  }
94
95
  case mdm_sdk_1.CustomAction.REQUEST: {
95
96
  var processedTask = (0, customScript_1.getProcessedTask)(task, apiPath, reltioPath, tenant);
96
- (0, useAPI_1.processRequest)(__assign({ params: processedTask.params, permissions: config.action.permissions, worker: worker, metadata: metadata, config: config, user: user, apiPath: reltioPath, servicesPath: servicesPath, tenant: tenant, workflowPath: workflowPath, entity: entityRef.current, entityUri: (_b = entityRef.current) === null || _b === void 0 ? void 0 : _b.uri, environment: environment, query: searchQueryRef.current, openSearch: openSearch, workflowCheckPermission: workflowCheckPermission }, qxApi));
97
+ (0, useAPI_1.processRequest)(__assign({ params: processedTask.params, permissions: config.action.permissions, worker: worker, metadata: metadata, config: config, user: user, apiPath: reltioPath, servicesPath: servicesPath, tenant: tenant, workflowPath: workflowPath, entity: entityRef.current, entityUri: (_b = entityRef.current) === null || _b === void 0 ? void 0 : _b.uri, environment: environment, query: searchQueryRef.current, openSearch: openSearch, workflowCheckPermission: workflowCheckPermission }, qxApiRef.current));
97
98
  break;
98
99
  }
99
100
  case mdm_sdk_1.CustomAction.RETURN_PROCESSED_API_RESPONSE: {
@@ -135,6 +136,9 @@ var useCustomScripts = function (config) {
135
136
  (0, react_1.useEffect)(function () {
136
137
  searchQueryRef.current = searchQuery;
137
138
  }, [searchQuery]);
139
+ (0, react_1.useEffect)(function () {
140
+ qxApiRef.current = qxApi;
141
+ }, [qxApi]);
138
142
  var customScriptRequestInterceptor = function (_a) {
139
143
  var _b;
140
144
  var url = _a.url, next = _a.next, resolve = _a.resolve, _c = _a.options, options = _c === void 0 ? {} : _c;
@@ -81,6 +81,7 @@ var mdm_sdk_1 = require("@reltio/mdm-sdk");
81
81
  var MdmModuleContext_1 = require("../../contexts/MdmModuleContext");
82
82
  var InterceptHandlersContext_1 = require("../../contexts/InterceptHandlersContext");
83
83
  var SnackbarContext_1 = require("../../contexts/SnackbarContext");
84
+ var SandboxAPIContext_1 = require("../../contexts/SandboxAPIContext");
84
85
  var useCustomScripts_1 = require("./useCustomScripts");
85
86
  jest.mock('@reltio/mdm-sdk', function () { return (__assign(__assign({}, jest.requireActual('@reltio/mdm-sdk')), { initializeWebWorker: jest.fn() })); });
86
87
  jest.mock('nanoid', function () { return (__assign(__assign({}, jest.requireActual('nanoid')), { nanoid: jest.fn() })); });
@@ -120,18 +121,27 @@ describe('useCustomScripts', function () {
120
121
  removeInternalRequestInterceptor: requestProvider.removeRequestInterceptor,
121
122
  removeInternalResponseInterceptor: requestProvider.removeResponseInterceptor
122
123
  };
124
+ var sandbox = {
125
+ getCurrentPerspectiveId: jest.fn().mockReturnValue('23'),
126
+ showPerspective: jest.fn(),
127
+ setEntityUri: jest.fn()
128
+ };
123
129
  var setUp = function (_a) {
124
- var _b = _a === void 0 ? {} : _a, _c = _b.mdmValues, mdmValues = _c === void 0 ? defaultMdmValues : _c, _d = _b.config, config = _d === void 0 ? createConfig() : _d;
130
+ var _b = _a === void 0 ? {} : _a, _c = _b.mdmValues, mdmValues = _c === void 0 ? defaultMdmValues : _c, _d = _b.config, config = _d === void 0 ? createConfig() : _d, _e = _b.sandboxValue, sandboxValue = _e === void 0 ? sandbox : _e;
125
131
  var updateMdmValues;
132
+ var updateSandbox;
126
133
  var Providers = function (_a) {
127
134
  var children = _a.children;
128
135
  var _b = react_1.default.useState(mdmValues), mdmValuesState = _b[0], setMdmValuesState = _b[1];
136
+ var _c = react_1.default.useState(sandboxValue), sandboxState = _c[0], setSandboxState = _c[1];
129
137
  updateMdmValues = setMdmValuesState;
138
+ updateSandbox = setSandboxState;
130
139
  return (react_1.default.createElement(MdmModuleContext_1.MdmModuleProvider, { values: mdmValuesState },
131
140
  react_1.default.createElement(SnackbarContext_1.SnackbarContext.Provider, { value: showSnackbarMessage },
132
- react_1.default.createElement(InterceptHandlersContext_1.InterceptHandlersContext.Provider, { value: interceptors }, children))));
141
+ react_1.default.createElement(SandboxAPIContext_1.SandboxAPIContext.Provider, { value: sandboxState },
142
+ react_1.default.createElement(InterceptHandlersContext_1.InterceptHandlersContext.Provider, { value: interceptors }, children)))));
133
143
  };
134
- return __assign(__assign({}, (0, react_2.renderHook)(useCustomScripts_1.useCustomScripts, { initialProps: config, wrapper: Providers })), { updateMdmValues: updateMdmValues });
144
+ return __assign(__assign({}, (0, react_2.renderHook)(useCustomScripts_1.useCustomScripts, { initialProps: config, wrapper: Providers })), { updateMdmValues: updateMdmValues, updateSandbox: updateSandbox });
135
145
  };
136
146
  var postMessage = jest.fn();
137
147
  var onmessageFromWorker;
@@ -532,6 +542,26 @@ describe('useCustomScripts', function () {
532
542
  id: 'id3'
533
543
  });
534
544
  });
545
+ it('should call setEntityUri from the current sandbox after it changes', function () {
546
+ var updateSandbox = setUp().updateSandbox;
547
+ var newSandbox = {
548
+ getCurrentPerspectiveId: jest.fn().mockReturnValue('23'),
549
+ showPerspective: jest.fn(),
550
+ setEntityUri: jest.fn()
551
+ };
552
+ (0, react_2.act)(function () {
553
+ updateSandbox(newSandbox);
554
+ });
555
+ (0, react_2.act)(function () {
556
+ onmessageFromWorker({
557
+ action: mdm_sdk_1.CustomAction.REQUEST,
558
+ params: { name: mdm_sdk_1.RequestAction.SET_ENTITY_URI, id: 'id1', entityUri: 'entities/BBB' }
559
+ });
560
+ });
561
+ expect(newSandbox.setEntityUri).toHaveBeenCalledTimes(1);
562
+ expect(newSandbox.setEntityUri.mock.calls[0][0]).toBe('entities/BBB');
563
+ expect(sandbox.setEntityUri).not.toHaveBeenCalled();
564
+ });
535
565
  it('should resolve getSearchQuery with the current query after it changes', function () {
536
566
  var updateMdmValues = setUp({
537
567
  mdmValues: __assign(__assign({}, defaultMdmValues), { searchProviderData: { type: 'search', data: { query: 'q1' } } })
@@ -34,6 +34,7 @@ export var useAPI = function (config) {
34
34
  var workerRef = useRef(null);
35
35
  var entityRef = useRef(null);
36
36
  var searchQueryRef = useRef(null);
37
+ var qxApiRef = useRef(null);
37
38
  var requestListeners = useRef({});
38
39
  var responseListeners = useRef({});
39
40
  var sanitizeHtml = useHtmlSanitizer();
@@ -145,7 +146,7 @@ export var useAPI = function (config) {
145
146
  }
146
147
  case CustomAction.REQUEST: {
147
148
  var processedTask = getProcessedTask(task, apiPath, reltioPath, tenant);
148
- processRequest(__assign({ params: processedTask.params, permissions: config.action.permissions, worker: worker, metadata: metadata, config: config, user: user, servicesPath: servicesPath, apiPath: reltioPath, tenant: tenant, workflowPath: workflowPath, entity: entityRef.current, entityUri: (_b = entityRef.current) === null || _b === void 0 ? void 0 : _b.uri, environment: environment, query: searchQueryRef.current, openSearch: openSearch, workflowCheckPermission: workflowCheckPermission }, qxApi));
149
+ processRequest(__assign({ params: processedTask.params, permissions: config.action.permissions, worker: worker, metadata: metadata, config: config, user: user, servicesPath: servicesPath, apiPath: reltioPath, tenant: tenant, workflowPath: workflowPath, entity: entityRef.current, entityUri: (_b = entityRef.current) === null || _b === void 0 ? void 0 : _b.uri, environment: environment, query: searchQueryRef.current, openSearch: openSearch, workflowCheckPermission: workflowCheckPermission }, qxApiRef.current));
149
150
  break;
150
151
  }
151
152
  case CustomAction.RETURN_PROCESSED_API_RESPONSE: {
@@ -225,6 +226,9 @@ export var useAPI = function (config) {
225
226
  searchQueryRef.current = searchQuery;
226
227
  postEventMessage('changeSearchQuery', searchQuery);
227
228
  }, [searchQuery]);
229
+ useEffect(function () {
230
+ qxApiRef.current = qxApi;
231
+ }, [qxApi]);
228
232
  useEffect(function () {
229
233
  postEventMessage('changeVisibility', visible);
230
234
  }, [visible]);
@@ -128,18 +128,21 @@ var sandbox = {
128
128
  setEntityUri: jest.fn().mockImplementation(function (entityUri, listener) { return setTimeout(listener, 1000); })
129
129
  };
130
130
  var setUp = function (_a) {
131
- var _b = _a === void 0 ? {} : _a, _c = _b.config, config = _c === void 0 ? createConfig() : _c, _d = _b.mdmValues, mdmValues = _d === void 0 ? defaultMdmValues : _d;
131
+ var _b = _a === void 0 ? {} : _a, _c = _b.config, config = _c === void 0 ? createConfig() : _c, _d = _b.mdmValues, mdmValues = _d === void 0 ? defaultMdmValues : _d, _e = _b.sandboxValue, sandboxValue = _e === void 0 ? sandbox : _e;
132
132
  var updateMdmValues;
133
+ var updateSandbox;
133
134
  var Providers = function (_a) {
134
135
  var children = _a.children;
135
136
  var _b = useState(mdmValues), mdmValuesState = _b[0], setMdmValuesState = _b[1];
137
+ var _c = useState(sandboxValue), sandboxState = _c[0], setSandboxState = _c[1];
136
138
  updateMdmValues = setMdmValuesState;
139
+ updateSandbox = setSandboxState;
137
140
  return (React.createElement(MdmModuleProvider, { values: mdmValuesState, actions: mdmActions },
138
141
  React.createElement(SnackbarContext.Provider, { value: showSnackbarMessage },
139
- React.createElement(SandboxAPIContext.Provider, { value: sandbox },
142
+ React.createElement(SandboxAPIContext.Provider, { value: sandboxState },
140
143
  React.createElement(InterceptHandlersContext.Provider, { value: interceptors }, children)))));
141
144
  };
142
- return __assign(__assign({}, renderHook(useAPI, { initialProps: config, wrapper: Providers })), { updateMdmValues: updateMdmValues });
145
+ return __assign(__assign({}, renderHook(useAPI, { initialProps: config, wrapper: Providers })), { updateMdmValues: updateMdmValues, updateSandbox: updateSandbox });
143
146
  };
144
147
  describe('useAPI custom sandbox behavior', function () {
145
148
  var postMessage = jest.fn();
@@ -918,6 +921,28 @@ describe('useAPI custom sandbox behavior', function () {
918
921
  return [2 /*return*/];
919
922
  });
920
923
  }); });
924
+ it('should call setEntityUri from the current sandbox after it changes', function () {
925
+ var updateSandbox = setUp().updateSandbox;
926
+ var newSandbox = {
927
+ getCurrentPerspectiveId: jest.fn().mockReturnValue('23'),
928
+ showPerspective: jest.fn(),
929
+ setEntityUri: jest.fn()
930
+ };
931
+ act(function () {
932
+ updateSandbox(newSandbox);
933
+ });
934
+ var params = {
935
+ name: RequestAction.SET_ENTITY_URI,
936
+ id: 23,
937
+ entityUri: 'entities/NEW999'
938
+ };
939
+ act(function () {
940
+ onmessageFromWorker({ action: CustomAction.REQUEST, params: params });
941
+ });
942
+ expect(newSandbox.setEntityUri).toHaveBeenCalledTimes(1);
943
+ expect(newSandbox.setEntityUri.mock.calls[0][0]).toBe(params.entityUri);
944
+ expect(sandbox.setEntityUri).not.toHaveBeenCalled();
945
+ });
921
946
  it('should call showPerspective and getCurrentPerspectiveId from sandbox on setPerspective request', function () {
922
947
  setUp();
923
948
  var params = {
@@ -75,6 +75,7 @@ export var useCustomScripts = function (config) {
75
75
  var workers = useRef({});
76
76
  var entityRef = useRef(null);
77
77
  var searchQueryRef = useRef(null);
78
+ var qxApiRef = useRef(qxApi);
78
79
  var processMessageFromWorker = function (_a) {
79
80
  var _b;
80
81
  var task = _a.task, worker = _a.worker, config = _a.config;
@@ -90,7 +91,7 @@ export var useCustomScripts = function (config) {
90
91
  }
91
92
  case CustomAction.REQUEST: {
92
93
  var processedTask = getProcessedTask(task, apiPath, reltioPath, tenant);
93
- processRequest(__assign({ params: processedTask.params, permissions: config.action.permissions, worker: worker, metadata: metadata, config: config, user: user, apiPath: reltioPath, servicesPath: servicesPath, tenant: tenant, workflowPath: workflowPath, entity: entityRef.current, entityUri: (_b = entityRef.current) === null || _b === void 0 ? void 0 : _b.uri, environment: environment, query: searchQueryRef.current, openSearch: openSearch, workflowCheckPermission: workflowCheckPermission }, qxApi));
94
+ processRequest(__assign({ params: processedTask.params, permissions: config.action.permissions, worker: worker, metadata: metadata, config: config, user: user, apiPath: reltioPath, servicesPath: servicesPath, tenant: tenant, workflowPath: workflowPath, entity: entityRef.current, entityUri: (_b = entityRef.current) === null || _b === void 0 ? void 0 : _b.uri, environment: environment, query: searchQueryRef.current, openSearch: openSearch, workflowCheckPermission: workflowCheckPermission }, qxApiRef.current));
94
95
  break;
95
96
  }
96
97
  case CustomAction.RETURN_PROCESSED_API_RESPONSE: {
@@ -132,6 +133,9 @@ export var useCustomScripts = function (config) {
132
133
  useEffect(function () {
133
134
  searchQueryRef.current = searchQuery;
134
135
  }, [searchQuery]);
136
+ useEffect(function () {
137
+ qxApiRef.current = qxApi;
138
+ }, [qxApi]);
135
139
  var customScriptRequestInterceptor = function (_a) {
136
140
  var _b;
137
141
  var url = _a.url, next = _a.next, resolve = _a.resolve, _c = _a.options, options = _c === void 0 ? {} : _c;
@@ -53,6 +53,7 @@ import { CustomAction, CustomScriptPlatform, RequestAction, setRequestProvider,
53
53
  import { MdmModuleProvider } from '../../contexts/MdmModuleContext';
54
54
  import { InterceptHandlersContext } from '../../contexts/InterceptHandlersContext';
55
55
  import { SnackbarContext } from '../../contexts/SnackbarContext';
56
+ import { SandboxAPIContext } from '../../contexts/SandboxAPIContext';
56
57
  import { useCustomScripts } from './useCustomScripts';
57
58
  jest.mock('@reltio/mdm-sdk', function () { return (__assign(__assign({}, jest.requireActual('@reltio/mdm-sdk')), { initializeWebWorker: jest.fn() })); });
58
59
  jest.mock('nanoid', function () { return (__assign(__assign({}, jest.requireActual('nanoid')), { nanoid: jest.fn() })); });
@@ -92,18 +93,27 @@ describe('useCustomScripts', function () {
92
93
  removeInternalRequestInterceptor: requestProvider.removeRequestInterceptor,
93
94
  removeInternalResponseInterceptor: requestProvider.removeResponseInterceptor
94
95
  };
96
+ var sandbox = {
97
+ getCurrentPerspectiveId: jest.fn().mockReturnValue('23'),
98
+ showPerspective: jest.fn(),
99
+ setEntityUri: jest.fn()
100
+ };
95
101
  var setUp = function (_a) {
96
- var _b = _a === void 0 ? {} : _a, _c = _b.mdmValues, mdmValues = _c === void 0 ? defaultMdmValues : _c, _d = _b.config, config = _d === void 0 ? createConfig() : _d;
102
+ var _b = _a === void 0 ? {} : _a, _c = _b.mdmValues, mdmValues = _c === void 0 ? defaultMdmValues : _c, _d = _b.config, config = _d === void 0 ? createConfig() : _d, _e = _b.sandboxValue, sandboxValue = _e === void 0 ? sandbox : _e;
97
103
  var updateMdmValues;
104
+ var updateSandbox;
98
105
  var Providers = function (_a) {
99
106
  var children = _a.children;
100
107
  var _b = React.useState(mdmValues), mdmValuesState = _b[0], setMdmValuesState = _b[1];
108
+ var _c = React.useState(sandboxValue), sandboxState = _c[0], setSandboxState = _c[1];
101
109
  updateMdmValues = setMdmValuesState;
110
+ updateSandbox = setSandboxState;
102
111
  return (React.createElement(MdmModuleProvider, { values: mdmValuesState },
103
112
  React.createElement(SnackbarContext.Provider, { value: showSnackbarMessage },
104
- React.createElement(InterceptHandlersContext.Provider, { value: interceptors }, children))));
113
+ React.createElement(SandboxAPIContext.Provider, { value: sandboxState },
114
+ React.createElement(InterceptHandlersContext.Provider, { value: interceptors }, children)))));
105
115
  };
106
- return __assign(__assign({}, renderHook(useCustomScripts, { initialProps: config, wrapper: Providers })), { updateMdmValues: updateMdmValues });
116
+ return __assign(__assign({}, renderHook(useCustomScripts, { initialProps: config, wrapper: Providers })), { updateMdmValues: updateMdmValues, updateSandbox: updateSandbox });
107
117
  };
108
118
  var postMessage = jest.fn();
109
119
  var onmessageFromWorker;
@@ -504,6 +514,26 @@ describe('useCustomScripts', function () {
504
514
  id: 'id3'
505
515
  });
506
516
  });
517
+ it('should call setEntityUri from the current sandbox after it changes', function () {
518
+ var updateSandbox = setUp().updateSandbox;
519
+ var newSandbox = {
520
+ getCurrentPerspectiveId: jest.fn().mockReturnValue('23'),
521
+ showPerspective: jest.fn(),
522
+ setEntityUri: jest.fn()
523
+ };
524
+ act(function () {
525
+ updateSandbox(newSandbox);
526
+ });
527
+ act(function () {
528
+ onmessageFromWorker({
529
+ action: CustomAction.REQUEST,
530
+ params: { name: RequestAction.SET_ENTITY_URI, id: 'id1', entityUri: 'entities/BBB' }
531
+ });
532
+ });
533
+ expect(newSandbox.setEntityUri).toHaveBeenCalledTimes(1);
534
+ expect(newSandbox.setEntityUri.mock.calls[0][0]).toBe('entities/BBB');
535
+ expect(sandbox.setEntityUri).not.toHaveBeenCalled();
536
+ });
507
537
  it('should resolve getSearchQuery with the current query after it changes', function () {
508
538
  var updateMdmValues = setUp({
509
539
  mdmValues: __assign(__assign({}, defaultMdmValues), { searchProviderData: { type: 'search', data: { query: 'q1' } } })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reltio/components",
3
- "version": "1.4.2282",
3
+ "version": "1.4.2284",
4
4
  "license": "SEE LICENSE IN LICENSE FILE",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./index.js",