diff --git a/package-lock.json b/package-lock.json index deefff9e84..d9c94e761b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5545,6 +5545,21 @@ "node": ">=8.0.0" } }, + "node_modules/@pinia/testing": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/@pinia/testing/-/testing-0.0.14.tgz", + "integrity": "sha512-ZmZwVNd/NnKYLIfjfuKl0zlJ3UdiXFpsHzSlL6wCeezSlyrqGMxsIQKv0J6fleu38gyCNTPBEipfxrt8V4+VIg==", + "dev": true, + "dependencies": { + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "pinia": ">=2.0.19" + } + }, "node_modules/@rollup/pluginutils": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", @@ -36176,15 +36191,6 @@ "vue": ">=2" } }, - "node_modules/vue-json-pretty": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/vue-json-pretty/-/vue-json-pretty-1.9.2.tgz", - "integrity": "sha512-FHAYmZAazhVC6Wi+Zi9DVYha+oZb9uylJPGkl/yTYLxlqLMxmnaVC2R8ZwaYzt6TBGvkLe3Y2D2vgyJCDBJy1w==", - "engines": { - "node": ">= 10.0.0", - "npm": ">= 5.0.0" - } - }, "node_modules/vue-loader": { "version": "15.10.0", "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.10.0.tgz", @@ -38741,7 +38747,7 @@ "vue-agile": "^2.0.0", "vue-fragment": "1.5.1", "vue-i18n": "^8.26.7", - "vue-json-pretty": "1.9.2", + "vue-json-pretty": "1.9.3", "vue-prism-editor": "^0.3.0", "vue-router": "^3.0.6", "vue-template-compiler": "~2.7.10", @@ -38755,6 +38761,7 @@ "devDependencies": { "@intlify/vue-i18n-loader": "^1.1.0", "@n8n_io/eslint-config": "", + "@pinia/testing": "^0.0.14", "@testing-library/jest-dom": "^5.16.5", "@testing-library/vue": "^5.8.3", "@types/dateformat": "^3.0.0", @@ -38795,6 +38802,15 @@ "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==", "dev": true }, + "packages/editor-ui/node_modules/vue-json-pretty": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/vue-json-pretty/-/vue-json-pretty-1.9.3.tgz", + "integrity": "sha512-b13DP1WGQ+ACUU2K5hmwFfHrHnydCFSTerE7fppeYMojSWN/5EOPODQECfIIRaJ7zzHtPW9OifkThFGPyY0xRg==", + "engines": { + "node": ">= 10.0.0", + "npm": ">= 5.0.0" + } + }, "packages/node-dev": { "name": "n8n-node-dev", "version": "0.80.0", @@ -43018,7 +43034,7 @@ "functional-red-black-tree": "^1.0.1", "glob-parent": "^6.0.1", "globals": "^13.15.0", - "globby": "^11.0.2", + "globby": "^11.1.0", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "import-fresh": "^3.0.0", @@ -43600,6 +43616,15 @@ "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.2.0.tgz", "integrity": "sha512-0nBr+VZNKm9tvNDZFstI3Pq1fCTEDK5OZTnVKNvBNAKgd0yIvmwsP4m61rEv7ZP+tOUjWJhROpxK5MsnlF911g==" }, + "@pinia/testing": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/@pinia/testing/-/testing-0.0.14.tgz", + "integrity": "sha512-ZmZwVNd/NnKYLIfjfuKl0zlJ3UdiXFpsHzSlL6wCeezSlyrqGMxsIQKv0J6fleu38gyCNTPBEipfxrt8V4+VIg==", + "dev": true, + "requires": { + "vue-demi": "*" + } + }, "@rollup/pluginutils": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", @@ -59265,6 +59290,7 @@ "@fortawesome/vue-fontawesome": "^2.0.2", "@intlify/vue-i18n-loader": "^1.1.0", "@n8n_io/eslint-config": "", + "@pinia/testing": "^0.0.14", "@testing-library/jest-dom": "^5.16.5", "@testing-library/vue": "^5.8.3", "@types/dateformat": "^3.0.0", @@ -59327,7 +59353,7 @@ "vue-agile": "^2.0.0", "vue-fragment": "1.5.1", "vue-i18n": "^8.26.7", - "vue-json-pretty": "1.9.2", + "vue-json-pretty": "1.9.3", "vue-prism-editor": "^0.3.0", "vue-router": "^3.0.6", "vue-template-compiler": "~2.7.10", @@ -59345,6 +59371,11 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==", "dev": true + }, + "vue-json-pretty": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/vue-json-pretty/-/vue-json-pretty-1.9.3.tgz", + "integrity": "sha512-b13DP1WGQ+ACUU2K5hmwFfHrHnydCFSTerE7fppeYMojSWN/5EOPODQECfIIRaJ7zzHtPW9OifkThFGPyY0xRg==" } } }, @@ -68376,11 +68407,6 @@ "integrity": "sha512-hQN3mzLmWM33Ua2Oua5OgF8/BJjP6+T1Wzea5xHDRYCwVvJo2pxSJLhVqluaeBe3PB5vquMddceaKC4mhLe25A==", "dev": true }, - "vue-json-pretty": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/vue-json-pretty/-/vue-json-pretty-1.9.2.tgz", - "integrity": "sha512-FHAYmZAazhVC6Wi+Zi9DVYha+oZb9uylJPGkl/yTYLxlqLMxmnaVC2R8ZwaYzt6TBGvkLe3Y2D2vgyJCDBJy1w==" - }, "vue-loader": { "version": "15.10.0", "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.10.0.tgz", diff --git a/packages/editor-ui/package.json b/packages/editor-ui/package.json index 17fc30c1a3..87ee34d555 100644 --- a/packages/editor-ui/package.json +++ b/packages/editor-ui/package.json @@ -68,7 +68,7 @@ "vue-agile": "^2.0.0", "vue-fragment": "1.5.1", "vue-i18n": "^8.26.7", - "vue-json-pretty": "1.9.2", + "vue-json-pretty": "1.9.3", "vue-prism-editor": "^0.3.0", "vue-router": "^3.0.6", "vue-template-compiler": "~2.7.10", @@ -82,6 +82,7 @@ "devDependencies": { "@intlify/vue-i18n-loader": "^1.1.0", "@n8n_io/eslint-config": "", + "@pinia/testing": "^0.0.14", "@testing-library/jest-dom": "^5.16.5", "@testing-library/vue": "^5.8.3", "@types/dateformat": "^3.0.0", diff --git a/packages/editor-ui/src/__tests__/setup.ts b/packages/editor-ui/src/__tests__/setup.ts index 7b0828bfa8..95a38f1216 100644 --- a/packages/editor-ui/src/__tests__/setup.ts +++ b/packages/editor-ui/src/__tests__/setup.ts @@ -1 +1,11 @@ import '@testing-library/jest-dom'; +import Vue from 'vue'; + +Vue.config.productionTip = false; +Vue.config.devtools = false; + +// TODO: Investigate why this is needed +// Without having this 3rd party library imported like this, any component test using 'vue-json-pretty' fail with: +// [Vue warn]: Failed to mount component: template or render function not defined. +Vue.component('vue-json-pretty', require('vue-json-pretty').default); + diff --git a/packages/editor-ui/src/components/RunData.vue b/packages/editor-ui/src/components/RunData.vue index 0fce00bc88..a0e0738ac8 100644 --- a/packages/editor-ui/src/components/RunData.vue +++ b/packages/editor-ui/src/components/RunData.vue @@ -371,14 +371,15 @@ import { pinData } from '@/components/mixins/pinData'; import { CodeEditor } from "@/components/forms"; import { dataPinningEventBus } from '@/event-bus/data-pinning-event-bus'; import { clearJsonKey, executionDataToJson, stringSizeInBytes } from './helpers'; -import RunDataTable from './RunDataTable.vue'; -import RunDataJson from '@/components/RunDataJson.vue'; import { isEmpty } from '@/utils'; import { useWorkflowsStore } from "@/stores/workflows"; import { mapStores } from "pinia"; import { useNDVStore } from "@/stores/ndv"; import { useNodeTypesStore } from "@/stores/nodeTypes"; +const RunDataTable = () => import('@/components/RunDataTable.vue'); +const RunDataJson = () => import('@/components/RunDataJson.vue'); + export type EnterEditModeArgs = { origin: 'editIconButton' | 'insertTestDataLink', }; diff --git a/packages/editor-ui/src/components/RunDataJson.test.ts b/packages/editor-ui/src/components/RunDataJson.test.ts new file mode 100644 index 0000000000..8b3bcf70a8 --- /dev/null +++ b/packages/editor-ui/src/components/RunDataJson.test.ts @@ -0,0 +1,61 @@ +import Vue from 'vue'; +import { PiniaVuePlugin } from 'pinia'; +import { createTestingPinia } from '@pinia/testing'; +import { render, screen } from '@testing-library/vue'; +import RunDataJson from '@/components/RunDataJson.vue'; + +Vue.use(PiniaVuePlugin); + +describe('RunDataJson.vue', () => { + it('renders json values properly', () => { + render(RunDataJson, { + pinia: createTestingPinia(), + props: { + mappingEnabled: true, + editMode: { enabled: false }, + inputData: [{ + json: { + list: [1,2,3], + record: { name: 'Joe' }, + myNumber: 123, + myStringNumber: '456', + myStringText: 'abc', + nil: null, + d: undefined, + }, + }], + node: { + parameters: { + keepOnlySet: false, + values: {}, + options: {}, + }, + id: '820ea733-d8a6-4379-8e73-88a2347ea003', + name: 'Set', + type: 'n8n-nodes-base.set', + typeVersion: 1, + position: [ + 380, + 1060, + ], + disabled: false, + }, + }, + mocks: { + $locale: { + baseText() { + return ''; + }, + }, + $store: { + getters: {}, + }, + }, + }); + expect(screen.getByText('123')).toBeInTheDocument(); + expect(screen.getByText('"456"')).toBeInTheDocument(); + expect(screen.getByText('"abc"')).toBeInTheDocument(); + expect(screen.getByText('null')).toBeInTheDocument(); + expect(screen.queryByText('undefined')).not.toBeInTheDocument(); + }); +}); diff --git a/packages/editor-ui/src/components/RunDataJson.vue b/packages/editor-ui/src/components/RunDataJson.vue index bc9b8b41bc..aef5085c06 100644 --- a/packages/editor-ui/src/components/RunDataJson.vue +++ b/packages/editor-ui/src/components/RunDataJson.vue @@ -62,7 +62,7 @@ import VueJsonPretty from 'vue-json-pretty'; import { LOCAL_STORAGE_MAPPING_FLAG } from '@/constants'; import { IDataObject, INodeExecutionData } from "n8n-workflow"; import Draggable from '@/components/Draggable.vue'; -import { convertPath, executionDataToJson, isString, isStringNumber } from "@/components/helpers"; +import { convertPath, executionDataToJson, isString } from "@/components/helpers"; import { INodeUi } from "@/Interface"; import { shorten } from './helpers'; import { externalHooks } from "@/components/mixins/externalHooks"; @@ -143,7 +143,7 @@ export default mixins(externalHooks).extend({ useNDVStore, ), jsonData(): IDataObject[] { - return executionDataToJson(this.inputData as INodeExecutionData[]); + return executionDataToJson(this.inputData); }, showHint(): boolean { return ( @@ -195,8 +195,8 @@ export default mixins(externalHooks).extend({ this.$telemetry.track('User dragged data for mapping', telemetryPayload); }, 1000); // ensure dest data gets set if drop }, - getContent(value: string): string { - return isString(value) && !isStringNumber(value) ? `"${ value }"` : value; + getContent(value: unknown): string { + return isString(value) ? `"${ value }"` : JSON.stringify(value); }, }, });