diff --git a/.pnp.cjs b/.pnp.cjs index ef9ea868d..ab3486ee8 100755 --- a/.pnp.cjs +++ b/.pnp.cjs @@ -2810,7 +2810,7 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ["@swc/cli", "virtual:babee6e81435a5d101529cd67f2c6b175f4db37a4ab0b58df15adf73dd11be8917ac14caf44ab4e6882a92c61661055072365b349016e85173e049f006fc2305#npm:0.1.55"], ["@swc/core", "npm:1.2.135"], ["@swc/jest", "virtual:babee6e81435a5d101529cd67f2c6b175f4db37a4ab0b58df15adf73dd11be8917ac14caf44ab4e6882a92c61661055072365b349016e85173e049f006fc2305#npm:0.2.17"], - ["jest", "virtual:babee6e81435a5d101529cd67f2c6b175f4db37a4ab0b58df15adf73dd11be8917ac14caf44ab4e6882a92c61661055072365b349016e85173e049f006fc2305#npm:27.4.7"] + ["jest", "virtual:42e288f3c714e1d86d12bf40fb17a72864641a713e0a167e85a3dab47534d11bcd2e71357e431b2f4737000bc9432f95c60dff0c9bfb212cd46e1f0f5bf0ad9f#npm:27.4.7"] ], "linkType": "SOFT", }] @@ -3070,8 +3070,8 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { "packageLocation": "./packages/build/", "packageDependencies": [ ["@lowdefy/build", "workspace:packages/build"], - ["@lowdefy/actions-core", "workspace:packages/plugins/actions/actions-core"], ["@jest/globals", "npm:27.5.1"], + ["@lowdefy/actions-core", "workspace:packages/plugins/actions/actions-core"], ["@lowdefy/ajv", "workspace:packages/utils/ajv"], ["@lowdefy/blocks-antd", "workspace:packages/plugins/blocks/blocks-antd"], ["@lowdefy/blocks-basic", "workspace:packages/plugins/blocks/blocks-basic"], @@ -10506,6 +10506,13 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { }] ]], ["jest", [ + ["npm:27.4.7", { + "packageLocation": "./.yarn/cache/jest-npm-27.4.7-cdda9da561-28ce948b30.zip/node_modules/jest/", + "packageDependencies": [ + ["jest", "npm:27.4.7"] + ], + "linkType": "SOFT", + }], ["npm:27.5.1", { "packageLocation": "./.yarn/cache/jest-npm-27.5.1-bacad4fe2a-96f1d69042.zip/node_modules/jest/", "packageDependencies": [ @@ -10513,6 +10520,22 @@ function $$SETUP_STATE(hydrateRuntimeState, basePath) { ], "linkType": "SOFT", }], + ["virtual:42e288f3c714e1d86d12bf40fb17a72864641a713e0a167e85a3dab47534d11bcd2e71357e431b2f4737000bc9432f95c60dff0c9bfb212cd46e1f0f5bf0ad9f#npm:27.4.7", { + "packageLocation": "./.yarn/__virtual__/jest-virtual-4325f46d83/0/cache/jest-npm-27.4.7-cdda9da561-28ce948b30.zip/node_modules/jest/", + "packageDependencies": [ + ["jest", "virtual:42e288f3c714e1d86d12bf40fb17a72864641a713e0a167e85a3dab47534d11bcd2e71357e431b2f4737000bc9432f95c60dff0c9bfb212cd46e1f0f5bf0ad9f#npm:27.4.7"], + ["@jest/core", "virtual:af105d7a2bc799821f67e8114057f53830abc6c7c9faa96846247605351f361b4158d347970d00ebc3c04dbab6e46e1c1e24df193c1caf1f7d80a00c65068a2a#npm:27.5.1"], + ["@types/node-notifier", null], + ["import-local", "npm:3.1.0"], + ["jest-cli", "virtual:af105d7a2bc799821f67e8114057f53830abc6c7c9faa96846247605351f361b4158d347970d00ebc3c04dbab6e46e1c1e24df193c1caf1f7d80a00c65068a2a#npm:27.5.1"], + ["node-notifier", null] + ], + "packagePeers": [ + "@types/node-notifier", + "node-notifier" + ], + "linkType": "HARD", + }], ["virtual:babee6e81435a5d101529cd67f2c6b175f4db37a4ab0b58df15adf73dd11be8917ac14caf44ab4e6882a92c61661055072365b349016e85173e049f006fc2305#npm:27.5.1", { "packageLocation": "./.yarn/__virtual__/jest-virtual-af105d7a2b/0/cache/jest-npm-27.5.1-bacad4fe2a-96f1d69042.zip/node_modules/jest/", "packageDependencies": [ @@ -23634,7 +23657,7 @@ module.exports = require("path");; /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; -/******/ +/******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache @@ -23648,14 +23671,14 @@ module.exports = require("path");; /******/ // no module.loaded needed /******/ exports: {} /******/ }; -/******/ +/******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); -/******/ +/******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } -/******/ +/******/ /************************************************************************/ /******/ /* webpack/runtime/compat get default export */ /******/ (() => { @@ -23668,7 +23691,7 @@ module.exports = require("path");; /******/ return getter; /******/ }; /******/ })(); -/******/ +/******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports @@ -23680,12 +23703,12 @@ module.exports = require("path");; /******/ } /******/ }; /******/ })(); -/******/ +/******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) /******/ })(); -/******/ +/******/ /************************************************************************/ var __webpack_exports__ = {}; // This entry need to be wrapped in an IIFE because it need to be in strict mode. diff --git a/.yarn/cache/jest-npm-27.4.7-cdda9da561-28ce948b30.zip b/.yarn/cache/jest-npm-27.4.7-cdda9da561-28ce948b30.zip new file mode 100644 index 000000000..feec693d5 Binary files /dev/null and b/.yarn/cache/jest-npm-27.4.7-cdda9da561-28ce948b30.zip differ diff --git a/packages/plugins/actions/actions-core/src/actions/DisplayMessage.js b/packages/plugins/actions/actions-core/src/actions/DisplayMessage.js index fa5c22271..9e7379a51 100644 --- a/packages/plugins/actions/actions-core/src/actions/DisplayMessage.js +++ b/packages/plugins/actions/actions-core/src/actions/DisplayMessage.js @@ -17,11 +17,22 @@ import { type } from '@lowdefy/helpers'; function DisplayMessage({ methods: { displayMessage }, params }) { - let defaultParams = params; - if (type.isObject(params)) { - defaultParams = { ...defaultParams, content: params.content || 'Success' }; + if (!type.isObject(params) && !type.isNone(params)) { + throw new Error( + `Invalid DisplayMessage, check action params. Params must be an object, received "${JSON.stringify( + params + )}".` + ); + } + if (type.isNull(params) || type.isUndefined(params)) { + displayMessage({ content: 'Success' }); + } + if (type.isObject(params)) { + displayMessage({ + ...params, + content: type.isNone(params.content) ? 'Success' : params.content, + }); } - displayMessage(defaultParams); } export default DisplayMessage; diff --git a/packages/plugins/actions/actions-core/src/actions/DisplayMessage.test.js b/packages/plugins/actions/actions-core/src/actions/DisplayMessage.test.js index 8db50cfd6..52d2d2e03 100644 --- a/packages/plugins/actions/actions-core/src/actions/DisplayMessage.test.js +++ b/packages/plugins/actions/actions-core/src/actions/DisplayMessage.test.js @@ -14,15 +14,338 @@ limitations under the License. */ +import testContext from './testContext.js'; import DisplayMessage from './DisplayMessage.js'; -const mockActionMethod = jest.fn(); +const displayMessage = jest.fn(); +const lowdefy = { + _internal: { + actions: { + DisplayMessage, + }, + blockComponents: { + Button: { meta: { category: 'display' } }, + }, + displayMessage, + }, +}; + +const RealDate = Date; +const mockDate = jest.fn(() => ({ date: 0 })); +mockDate.now = jest.fn(() => 0); + +// Comment out to use console +console.log = () => {}; +console.error = () => {}; beforeEach(() => { - mockActionMethod.mockReset(); + displayMessage.mockReset(); }); -test('Message action invocation', async () => { - DisplayMessage({ methods: { displayMessage: mockActionMethod }, params: 'call' }); - expect(mockActionMethod.mock.calls).toEqual([['call']]); +beforeAll(() => { + global.Date = mockDate; +}); + +afterAll(() => { + global.Date = RealDate; +}); + +test('DisplayMessage params is not object', async () => { + const rootBlock = { + id: 'block:root:root:0', + blockId: 'root', + meta: { + category: 'container', + }, + areas: { + content: { + blocks: [ + { + id: 'block:root:button:0', + blockId: 'button', + type: 'Button', + meta: { + category: 'display', + }, + events: { + onClick: [ + { + id: 'a', + type: 'DisplayMessage', + params: 1, + }, + ], + }, + }, + ], + }, + }, + }; + const context = await testContext({ + lowdefy, + rootBlock, + }); + const button = context._internal.RootBlocks.map['block:root:button:0']; + await button.triggerEvent({ name: 'onClick' }); + expect(button.Events.events.onClick.history[0]).toEqual({ + blockId: 'button', + bounced: false, + event: undefined, + eventName: 'onClick', + error: { + action: { + id: 'a', + type: 'DisplayMessage', + params: 1, + }, + error: { + error: new Error( + 'Invalid DisplayMessage, check action params. Params must be an object, received "1".' + ), + index: 0, + type: 'DisplayMessage', + }, + }, + responses: { + a: { + error: new Error( + 'Invalid DisplayMessage, check action params. Params must be an object, received "1".' + ), + type: 'DisplayMessage', + index: 0, + }, + }, + endTimestamp: { date: 0 }, + startTimestamp: { date: 0 }, + success: false, + }); +}); + +test('DisplayMessage params is null or undefined', async () => { + const rootBlock = { + id: 'block:root:root:0', + blockId: 'root', + meta: { + category: 'container', + }, + areas: { + content: { + blocks: [ + { + id: 'block:root:button:0', + blockId: 'button', + type: 'Button', + meta: { + category: 'display', + }, + events: { + onClick: [ + { + id: 'a', + type: 'DisplayMessage', + }, + ], + }, + }, + ], + }, + }, + }; + const context = await testContext({ + lowdefy, + rootBlock, + }); + const button = context._internal.RootBlocks.map['block:root:button:0']; + await button.triggerEvent({ name: 'onClick' }); + expect(button.Events.events.onClick.history[0]).toEqual({ + blockId: 'button', + bounced: false, + event: undefined, + eventName: 'onClick', + responses: { + a: { + response: undefined, + type: 'DisplayMessage', + index: 0, + }, + }, + endTimestamp: { date: 0 }, + startTimestamp: { date: 0 }, + success: true, + }); + expect(displayMessage.mock.calls).toEqual([[{ content: 'Success' }]]); +}); + +test('DisplayMessage params.content is none', async () => { + const rootBlock = { + id: 'block:root:root:0', + blockId: 'root', + meta: { + category: 'container', + }, + areas: { + content: { + blocks: [ + { + id: 'block:root:button:0', + blockId: 'button', + type: 'Button', + meta: { + category: 'display', + }, + events: { + onClick: [ + { + id: 'a', + type: 'DisplayMessage', + params: { + status: 'info', + }, + }, + ], + }, + }, + ], + }, + }, + }; + const context = await testContext({ + lowdefy, + rootBlock, + }); + const button = context._internal.RootBlocks.map['block:root:button:0']; + await button.triggerEvent({ name: 'onClick' }); + expect(button.Events.events.onClick.history[0]).toEqual({ + blockId: 'button', + bounced: false, + event: undefined, + eventName: 'onClick', + responses: { + a: { + response: undefined, + type: 'DisplayMessage', + index: 0, + }, + }, + endTimestamp: { date: 0 }, + startTimestamp: { date: 0 }, + success: true, + }); + expect(displayMessage.mock.calls).toEqual([[{ content: 'Success', status: 'info' }]]); +}); + +test('DisplayMessage params.content is ""', async () => { + const rootBlock = { + id: 'block:root:root:0', + blockId: 'root', + meta: { + category: 'container', + }, + areas: { + content: { + blocks: [ + { + id: 'block:root:button:0', + blockId: 'button', + type: 'Button', + meta: { + category: 'display', + }, + events: { + onClick: [ + { + id: 'a', + type: 'DisplayMessage', + params: { + content: '', + }, + }, + ], + }, + }, + ], + }, + }, + }; + const context = await testContext({ + lowdefy, + rootBlock, + }); + const button = context._internal.RootBlocks.map['block:root:button:0']; + await button.triggerEvent({ name: 'onClick' }); + expect(button.Events.events.onClick.history[0]).toEqual({ + blockId: 'button', + bounced: false, + event: undefined, + eventName: 'onClick', + responses: { + a: { + response: undefined, + type: 'DisplayMessage', + index: 0, + }, + }, + endTimestamp: { date: 0 }, + startTimestamp: { date: 0 }, + success: true, + }); + expect(displayMessage.mock.calls).toEqual([[{ content: '' }]]); +}); + +test('DisplayMessage params.content is falsy', async () => { + const rootBlock = { + id: 'block:root:root:0', + blockId: 'root', + meta: { + category: 'container', + }, + areas: { + content: { + blocks: [ + { + id: 'block:root:button:0', + blockId: 'button', + type: 'Button', + meta: { + category: 'display', + }, + events: { + onClick: [ + { + id: 'a', + type: 'DisplayMessage', + params: { + content: 0, + }, + }, + ], + }, + }, + ], + }, + }, + }; + const context = await testContext({ + lowdefy, + rootBlock, + }); + const button = context._internal.RootBlocks.map['block:root:button:0']; + await button.triggerEvent({ name: 'onClick' }); + expect(button.Events.events.onClick.history[0]).toEqual({ + blockId: 'button', + bounced: false, + event: undefined, + eventName: 'onClick', + responses: { + a: { + response: undefined, + type: 'DisplayMessage', + index: 0, + }, + }, + endTimestamp: { date: 0 }, + startTimestamp: { date: 0 }, + success: true, + }); + expect(displayMessage.mock.calls).toEqual([[{ content: 0 }]]); }); diff --git a/yarn.lock b/yarn.lock index f83565e5c..39e68f408 100644 --- a/yarn.lock +++ b/yarn.lock @@ -960,7 +960,7 @@ __metadata: languageName: node linkType: hard -"@jest/core@npm:^27.5.1": +"@jest/core@npm:^27.4.7, @jest/core@npm:^27.5.1": version: 27.5.1 resolution: "@jest/core@npm:27.5.1" dependencies: @@ -2213,8 +2213,8 @@ __metadata: version: 0.0.0-use.local resolution: "@lowdefy/build@workspace:packages/build" dependencies: - "@lowdefy/actions-core": 4.0.0-alpha.6 "@jest/globals": 27.5.1 + "@lowdefy/actions-core": 4.0.0-alpha.6 "@lowdefy/ajv": 4.0.0-alpha.6 "@lowdefy/blocks-antd": 4.0.0-alpha.6 "@lowdefy/blocks-basic": 4.0.0-alpha.6 @@ -8560,7 +8560,7 @@ __metadata: languageName: node linkType: hard -"jest-cli@npm:^27.5.1": +"jest-cli@npm:^27.4.7, jest-cli@npm:^27.5.1": version: 27.5.1 resolution: "jest-cli@npm:27.5.1" dependencies: @@ -9011,6 +9011,24 @@ __metadata: languageName: node linkType: hard +"jest@npm:27.4.7": + version: 27.4.7 + resolution: "jest@npm:27.4.7" + dependencies: + "@jest/core": ^27.4.7 + import-local: ^3.0.2 + jest-cli: ^27.4.7 + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + bin: + jest: bin/jest.js + checksum: 28ce948b30c074907393f37553acac4422d0f60190776e62b3403e4c742d33dd6012e3a20748254a43e38b5b4ce52d813b13a3a5be1d43d6d12429bd08ce1a23 + languageName: node + linkType: hard + "jest@npm:27.5.1": version: 27.5.1 resolution: "jest@npm:27.5.1"