mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 18:12:04 +00:00
fix(editor): Fix inaccurate message in log view when input data is empty (#16234)
This commit is contained in:
@@ -193,7 +193,8 @@ const contextItems = computed(() => {
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const fields: Renders[] = flattenSchema({ schema, depth: 1 }).flatMap((renderItem) => {
|
const flatSchema = flattenSchema({ schema, depth: 1, isDataEmpty: false });
|
||||||
|
const fields: Renders[] = flatSchema.flatMap((renderItem) => {
|
||||||
const isVars =
|
const isVars =
|
||||||
renderItem.type === 'item' && renderItem.depth === 1 && renderItem.title === '$vars';
|
renderItem.type === 'item' && renderItem.depth === 1 && renderItem.title === '$vars';
|
||||||
|
|
||||||
@@ -320,7 +321,14 @@ const flattenedNodes = computed(() =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
const flattenNodeSchema = computed(() =>
|
const flattenNodeSchema = computed(() =>
|
||||||
nodeSchema.value ? flattenSchema({ schema: nodeSchema.value, depth: 0, level: -1 }) : [],
|
nodeSchema.value
|
||||||
|
? flattenSchema({
|
||||||
|
schema: nodeSchema.value,
|
||||||
|
depth: 0,
|
||||||
|
level: -1,
|
||||||
|
isDataEmpty: props.data.length === 0,
|
||||||
|
})
|
||||||
|
: [],
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -817,6 +817,7 @@ describe('useFlattenSchema', () => {
|
|||||||
expect(
|
expect(
|
||||||
useFlattenSchema().flattenSchema({
|
useFlattenSchema().flattenSchema({
|
||||||
schema,
|
schema,
|
||||||
|
isDataEmpty: false,
|
||||||
}).length,
|
}).length,
|
||||||
).toBe(3);
|
).toBe(3);
|
||||||
});
|
});
|
||||||
@@ -835,8 +836,18 @@ describe('useFlattenSchema', () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
const node1Schema = flattenSchema({ schema, expressionPrefix: '$("First Node")', depth: 1 });
|
const node1Schema = flattenSchema({
|
||||||
const node2Schema = flattenSchema({ schema, expressionPrefix: '$("Second Node")', depth: 1 });
|
schema,
|
||||||
|
expressionPrefix: '$("First Node")',
|
||||||
|
depth: 1,
|
||||||
|
isDataEmpty: false,
|
||||||
|
});
|
||||||
|
const node2Schema = flattenSchema({
|
||||||
|
schema,
|
||||||
|
expressionPrefix: '$("Second Node")',
|
||||||
|
depth: 1,
|
||||||
|
isDataEmpty: false,
|
||||||
|
});
|
||||||
|
|
||||||
expect(node1Schema[0].id).not.toBe(node2Schema[0].id);
|
expect(node1Schema[0].id).not.toBe(node2Schema[0].id);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -347,6 +347,7 @@ export const useFlattenSchema = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const flattenSchema = ({
|
const flattenSchema = ({
|
||||||
|
isDataEmpty,
|
||||||
schema,
|
schema,
|
||||||
nodeType,
|
nodeType,
|
||||||
nodeName,
|
nodeName,
|
||||||
@@ -356,6 +357,7 @@ export const useFlattenSchema = () => {
|
|||||||
level = 0,
|
level = 0,
|
||||||
preview,
|
preview,
|
||||||
}: {
|
}: {
|
||||||
|
isDataEmpty: boolean;
|
||||||
schema: Schema;
|
schema: Schema;
|
||||||
expressionPrefix?: string;
|
expressionPrefix?: string;
|
||||||
nodeType?: string;
|
nodeType?: string;
|
||||||
@@ -367,7 +369,7 @@ export const useFlattenSchema = () => {
|
|||||||
}): Renders[] => {
|
}): Renders[] => {
|
||||||
// only show empty item for the first level
|
// only show empty item for the first level
|
||||||
if (isEmptySchema(schema) && level < 0) {
|
if (isEmptySchema(schema) && level < 0) {
|
||||||
return [emptyItem('emptyData')];
|
return [emptyItem(isDataEmpty ? 'emptyData' : 'emptySchema')];
|
||||||
}
|
}
|
||||||
|
|
||||||
const expression = `{{ ${expressionPrefix ? expressionPrefix + schema.path : schema.path.slice(1)} }}`;
|
const expression = `{{ ${expressionPrefix ? expressionPrefix + schema.path : schema.path.slice(1)} }}`;
|
||||||
@@ -403,6 +405,7 @@ export const useFlattenSchema = () => {
|
|||||||
.map((item) => {
|
.map((item) => {
|
||||||
const itemPrefix = schema.type === 'array' ? schema.key : '';
|
const itemPrefix = schema.type === 'array' ? schema.key : '';
|
||||||
return flattenSchema({
|
return flattenSchema({
|
||||||
|
isDataEmpty,
|
||||||
schema: item,
|
schema: item,
|
||||||
expressionPrefix,
|
expressionPrefix,
|
||||||
nodeType,
|
nodeType,
|
||||||
@@ -474,6 +477,7 @@ export const useFlattenSchema = () => {
|
|||||||
|
|
||||||
acc = acc.concat(
|
acc = acc.concat(
|
||||||
flattenSchema({
|
flattenSchema({
|
||||||
|
isDataEmpty: item.isDataEmpty,
|
||||||
schema: item.schema,
|
schema: item.schema,
|
||||||
depth: item.depth,
|
depth: item.depth,
|
||||||
nodeType: item.node.type,
|
nodeType: item.node.type,
|
||||||
|
|||||||
@@ -10,16 +10,13 @@ import {
|
|||||||
createTestWorkflow,
|
createTestWorkflow,
|
||||||
createTestWorkflowObject,
|
createTestWorkflowObject,
|
||||||
} from '@/__tests__/mocks';
|
} from '@/__tests__/mocks';
|
||||||
import { mockedStore } from '@/__tests__/utils';
|
|
||||||
import { useSettingsStore } from '@/stores/settings.store';
|
|
||||||
import { type FrontendSettings } from '@n8n/api-types';
|
|
||||||
import { LOG_DETAILS_PANEL_STATE } from '@/features/logs/logs.constants';
|
import { LOG_DETAILS_PANEL_STATE } from '@/features/logs/logs.constants';
|
||||||
import type { LogEntry } from '../logs.types';
|
import type { LogEntry } from '../logs.types';
|
||||||
import { createTestLogEntry } from '../__test__/mocks';
|
import { createTestLogEntry } from '../__test__/mocks';
|
||||||
|
import { NodeConnectionTypes } from 'n8n-workflow';
|
||||||
|
|
||||||
describe('LogDetailsPanel', () => {
|
describe('LogDetailsPanel', () => {
|
||||||
let pinia: TestingPinia;
|
let pinia: TestingPinia;
|
||||||
let settingsStore: ReturnType<typeof mockedStore<typeof useSettingsStore>>;
|
|
||||||
|
|
||||||
const aiNode = createTestNode({ name: 'AI Agent' });
|
const aiNode = createTestNode({ name: 'AI Agent' });
|
||||||
const workflowData = createTestWorkflow({
|
const workflowData = createTestWorkflow({
|
||||||
@@ -84,11 +81,6 @@ describe('LogDetailsPanel', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
pinia = createTestingPinia({ stubActions: false, fakeApp: true });
|
pinia = createTestingPinia({ stubActions: false, fakeApp: true });
|
||||||
|
|
||||||
settingsStore = mockedStore(useSettingsStore);
|
|
||||||
settingsStore.isEnterpriseFeatureEnabled = {} as FrontendSettings['enterprise'];
|
|
||||||
|
|
||||||
localStorage.clear();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show name, run status, input, and output of the node', async () => {
|
it('should show name, run status, input, and output of the node', async () => {
|
||||||
@@ -155,4 +147,29 @@ describe('LogDetailsPanel', () => {
|
|||||||
|
|
||||||
expect(rendered.emitted()).toEqual({ toggleOutputOpen: [[false]] });
|
expect(rendered.emitted()).toEqual({ toggleOutputOpen: [[false]] });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should display correct message when input data is empty', async () => {
|
||||||
|
const nodeA = createTestNode({ name: 'A' });
|
||||||
|
const nodeB = createTestNode({ name: 'B' });
|
||||||
|
const runDataA = createTestTaskData({ data: { [NodeConnectionTypes.Main]: [[{ json: {} }]] } });
|
||||||
|
const runDataB = createTestTaskData({ source: [{ previousNode: 'A' }] });
|
||||||
|
const workflow = createTestWorkflowObject({ nodes: [nodeA, nodeB] });
|
||||||
|
const rendered = render({
|
||||||
|
isOpen: true,
|
||||||
|
logEntry: createLogEntry({
|
||||||
|
node: nodeB,
|
||||||
|
runIndex: 0,
|
||||||
|
runData: runDataB,
|
||||||
|
workflow,
|
||||||
|
execution: { resultData: { runData: { A: [runDataA], B: [runDataB] } } },
|
||||||
|
}),
|
||||||
|
panels: LOG_DETAILS_PANEL_STATE.BOTH,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(
|
||||||
|
await within(rendered.getByTestId('log-details-input')).findByText(
|
||||||
|
"No fields - item(s) exist, but they're empty",
|
||||||
|
),
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user