+
{{ key }}
@@ -432,7 +432,7 @@
v-if="isViewable(index, key)"
size="small"
:label="$locale.baseText('runData.showBinaryData')"
- class="binary-data-show-data-button"
+ data-test-id="ndv-view-binary-data"
@click="displayBinaryData(index, key)"
/>
@@ -1320,7 +1320,7 @@ export default defineComponent({
},
isViewable(index: number, key: string): boolean {
const { fileType } = this.binaryData[index][key];
- return !!fileType && ['image', 'video', 'text', 'json'].includes(fileType);
+ return !!fileType && ['image', 'audio', 'video', 'text', 'json', 'pdf'].includes(fileType);
},
isDownloadable(index: number, key: string): boolean {
const { mimeType, fileName } = this.binaryData[index][key];
diff --git a/packages/editor-ui/src/components/__tests__/RunData.test.ts b/packages/editor-ui/src/components/__tests__/RunData.test.ts
index cb3b417868..4af1d9292a 100644
--- a/packages/editor-ui/src/components/__tests__/RunData.test.ts
+++ b/packages/editor-ui/src/components/__tests__/RunData.test.ts
@@ -6,30 +6,102 @@ import RunData from '@/components/RunData.vue';
import { STORES, VIEWS } from '@/constants';
import { SETTINGS_STORE_DEFAULT_STATE } from '@/__tests__/utils';
import { createComponentRenderer } from '@/__tests__/render';
-
-const renderComponent = createComponentRenderer(RunData, {
- props: {
- nodeUi: {
- name: 'Test Node',
- },
- },
- data() {
- return {
- canPinData: true,
- };
- },
- global: {
- mocks: {
- $route: {
- name: VIEWS.WORKFLOW,
- },
- },
- },
-});
+import type { IRunDataDisplayMode } from '@/Interface';
describe('RunData', () => {
it('should render data correctly even when "item.json" has another "json" key', async () => {
- const { html, getByText, getAllByTestId, getByTestId } = renderComponent({
+ const { getByText, getAllByTestId, getByTestId } = render(
+ [
+ {
+ json: {
+ id: 1,
+ name: 'Test 1',
+ json: {
+ data: 'Json data 1',
+ },
+ },
+ },
+ {
+ json: {
+ id: 2,
+ name: 'Test 2',
+ json: {
+ data: 'Json data 2',
+ },
+ },
+ },
+ ],
+ 'schema',
+ );
+
+ await userEvent.click(getByTestId('ndv-pin-data'));
+ await waitFor(() => getAllByTestId('run-data-schema-item'), { timeout: 1000 });
+ expect(getByText('Test 1')).toBeInTheDocument();
+ expect(getByText('Json data 1')).toBeInTheDocument();
+ });
+
+ it('should render view and download buttons for PDFs', async () => {
+ const { getByTestId } = render(
+ [
+ {
+ json: {},
+ binary: {
+ data: {
+ fileName: 'test.pdf',
+ fileType: 'pdf',
+ mimeType: 'application/pdf',
+ },
+ },
+ },
+ ],
+ 'binary',
+ );
+ expect(getByTestId('ndv-view-binary-data')).toBeInTheDocument();
+ expect(getByTestId('ndv-download-binary-data')).toBeInTheDocument();
+ expect(getByTestId('ndv-binary-data_0')).toBeInTheDocument();
+ });
+
+ it('should not render a view button for unknown content-type', async () => {
+ const { getByTestId, queryByTestId } = render(
+ [
+ {
+ json: {},
+ binary: {
+ data: {
+ fileName: 'test.xyz',
+ mimeType: 'application/octet-stream',
+ },
+ },
+ },
+ ],
+ 'binary',
+ );
+ expect(queryByTestId('ndv-view-binary-data')).not.toBeInTheDocument();
+ expect(getByTestId('ndv-download-binary-data')).toBeInTheDocument();
+ expect(getByTestId('ndv-binary-data_0')).toBeInTheDocument();
+ });
+
+ const render = (outputData: unknown[], displayMode: IRunDataDisplayMode) =>
+ createComponentRenderer(RunData, {
+ props: {
+ nodeUi: {
+ name: 'Test Node',
+ },
+ },
+ data() {
+ return {
+ canPinData: true,
+ showData: true,
+ };
+ },
+ global: {
+ mocks: {
+ $route: {
+ name: VIEWS.WORKFLOW,
+ },
+ },
+ },
+ })({
props: {
nodeUi: {
id: '1',
@@ -49,7 +121,7 @@ describe('RunData', () => {
},
[STORES.NDV]: {
output: {
- displayMode: 'schema',
+ displayMode,
},
activeNodeName: 'Test Node',
},
@@ -89,28 +161,7 @@ describe('RunData', () => {
startTime: new Date().getTime(),
executionTime: new Date().getTime(),
data: {
- main: [
- [
- {
- json: {
- id: 1,
- name: 'Test 1',
- json: {
- data: 'Json data 1',
- },
- },
- },
- {
- json: {
- id: 2,
- name: 'Test 2',
- json: {
- data: 'Json data 2',
- },
- },
- },
- ],
- ],
+ main: [outputData],
},
source: [null],
},
@@ -123,10 +174,4 @@ describe('RunData', () => {
},
}),
});
-
- await userEvent.click(getByTestId('ndv-pin-data'));
- await waitFor(() => getAllByTestId('run-data-schema-item'), { timeout: 1000 });
- expect(getByText('Test 1')).toBeInTheDocument();
- expect(getByText('Json data 1')).toBeInTheDocument();
- });
});
diff --git a/packages/nodes-base/nodes/ReadPdf/test/ReadPDF-encrypted.workflow.json b/packages/nodes-base/nodes/ReadPdf/test/ReadPDF-encrypted.workflow.json
index 7258819ead..1bf9f597b8 100644
--- a/packages/nodes-base/nodes/ReadPdf/test/ReadPDF-encrypted.workflow.json
+++ b/packages/nodes-base/nodes/ReadPdf/test/ReadPDF-encrypted.workflow.json
@@ -35,6 +35,7 @@
"fileExtension": "pdf",
"fileName": "sample-encrypted.pdf",
"fileSize": "18.9 kB",
+ "fileType": "pdf",
"mimeType": "application/pdf"
}
},
diff --git a/packages/nodes-base/nodes/ReadPdf/test/ReadPDF.workflow.json b/packages/nodes-base/nodes/ReadPdf/test/ReadPDF.workflow.json
index 4a56640108..5b257711ad 100644
--- a/packages/nodes-base/nodes/ReadPdf/test/ReadPDF.workflow.json
+++ b/packages/nodes-base/nodes/ReadPdf/test/ReadPDF.workflow.json
@@ -32,6 +32,7 @@
"fileExtension": "pdf",
"fileName": "sample.pdf",
"fileSize": "17.8 kB",
+ "fileType": "pdf",
"mimeType": "application/pdf"
}
},
diff --git a/packages/workflow/src/Interfaces.ts b/packages/workflow/src/Interfaces.ts
index 1256a1df25..4624c303cd 100644
--- a/packages/workflow/src/Interfaces.ts
+++ b/packages/workflow/src/Interfaces.ts
@@ -35,7 +35,7 @@ export type IAllExecuteFunctions =
| ITriggerFunctions
| IWebhookFunctions;
-export type BinaryFileType = 'text' | 'json' | 'image' | 'video';
+export type BinaryFileType = 'text' | 'json' | 'image' | 'audio' | 'video' | 'pdf';
export interface IBinaryData {
[key: string]: string | undefined;
data: string;
diff --git a/packages/workflow/src/utils.ts b/packages/workflow/src/utils.ts
index 27d96b4dcb..e6c95b0023 100644
--- a/packages/workflow/src/utils.ts
+++ b/packages/workflow/src/utils.ts
@@ -113,8 +113,10 @@ export const sleep = async (ms: number): Promise
=>
export function fileTypeFromMimeType(mimeType: string): BinaryFileType | undefined {
if (mimeType.startsWith('application/json')) return 'json';
if (mimeType.startsWith('image/')) return 'image';
+ if (mimeType.startsWith('audio/')) return 'audio';
if (mimeType.startsWith('video/')) return 'video';
- if (mimeType.startsWith('text/')) return 'text';
+ if (mimeType.startsWith('text/') || mimeType.startsWith('application/javascript')) return 'text';
+ if (mimeType.startsWith('application/pdf')) return 'pdf';
return;
}
diff --git a/packages/workflow/test/utils.test.ts b/packages/workflow/test/utils.test.ts
index e26d964976..f8cbd007f5 100644
--- a/packages/workflow/test/utils.test.ts
+++ b/packages/workflow/test/utils.test.ts
@@ -1,4 +1,4 @@
-import { jsonParse, jsonStringify, deepCopy, isObjectEmpty } from '@/utils';
+import { jsonParse, jsonStringify, deepCopy, isObjectEmpty, fileTypeFromMimeType } from '@/utils';
describe('isObjectEmpty', () => {
it('should handle null and undefined', () => {
@@ -190,3 +190,41 @@ describe('deepCopy', () => {
expect(copy.deep.arr.slice(-1)[0]).not.toBe(object);
});
});
+
+describe('fileTypeFromMimeType', () => {
+ it('should recognize json', () => {
+ expect(fileTypeFromMimeType('application/json')).toEqual('json');
+ });
+
+ it('should recognize image', () => {
+ expect(fileTypeFromMimeType('image/jpeg')).toEqual('image');
+ expect(fileTypeFromMimeType('image/png')).toEqual('image');
+ expect(fileTypeFromMimeType('image/avif')).toEqual('image');
+ expect(fileTypeFromMimeType('image/webp')).toEqual('image');
+ });
+
+ it('should recognize audio', () => {
+ expect(fileTypeFromMimeType('audio/wav')).toEqual('audio');
+ expect(fileTypeFromMimeType('audio/webm')).toEqual('audio');
+ expect(fileTypeFromMimeType('audio/ogg')).toEqual('audio');
+ expect(fileTypeFromMimeType('audio/mp3')).toEqual('audio');
+ });
+
+ it('should recognize video', () => {
+ expect(fileTypeFromMimeType('video/mp4')).toEqual('video');
+ expect(fileTypeFromMimeType('video/webm')).toEqual('video');
+ expect(fileTypeFromMimeType('video/ogg')).toEqual('video');
+ });
+
+ it('should recognize text', () => {
+ expect(fileTypeFromMimeType('text/plain')).toEqual('text');
+ expect(fileTypeFromMimeType('text/css')).toEqual('text');
+ expect(fileTypeFromMimeType('text/html')).toEqual('text');
+ expect(fileTypeFromMimeType('text/javascript')).toEqual('text');
+ expect(fileTypeFromMimeType('application/javascript')).toEqual('text');
+ });
+
+ it('should recognize pdf', () => {
+ expect(fileTypeFromMimeType('application/pdf')).toEqual('pdf');
+ });
+});