fix(editor): Fix inaccurate message in log view when input data is empty (#16234)

This commit is contained in:
Suguru Inoue
2025-06-16 12:09:57 +02:00
committed by GitHub
parent 3fcabd40b3
commit e93fd1a689
4 changed files with 54 additions and 14 deletions

View File

@@ -193,7 +193,8 @@ const contextItems = computed(() => {
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 =
renderItem.type === 'item' && renderItem.depth === 1 && renderItem.title === '$vars';
@@ -320,7 +321,14 @@ const flattenedNodes = 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,
})
: [],
);
/**

View File

@@ -817,6 +817,7 @@ describe('useFlattenSchema', () => {
expect(
useFlattenSchema().flattenSchema({
schema,
isDataEmpty: false,
}).length,
).toBe(3);
});
@@ -835,8 +836,18 @@ describe('useFlattenSchema', () => {
},
],
};
const node1Schema = flattenSchema({ schema, expressionPrefix: '$("First Node")', depth: 1 });
const node2Schema = flattenSchema({ schema, expressionPrefix: '$("Second Node")', depth: 1 });
const node1Schema = flattenSchema({
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);
});

View File

@@ -347,6 +347,7 @@ export const useFlattenSchema = () => {
};
const flattenSchema = ({
isDataEmpty,
schema,
nodeType,
nodeName,
@@ -356,6 +357,7 @@ export const useFlattenSchema = () => {
level = 0,
preview,
}: {
isDataEmpty: boolean;
schema: Schema;
expressionPrefix?: string;
nodeType?: string;
@@ -367,7 +369,7 @@ export const useFlattenSchema = () => {
}): Renders[] => {
// only show empty item for the first level
if (isEmptySchema(schema) && level < 0) {
return [emptyItem('emptyData')];
return [emptyItem(isDataEmpty ? 'emptyData' : 'emptySchema')];
}
const expression = `{{ ${expressionPrefix ? expressionPrefix + schema.path : schema.path.slice(1)} }}`;
@@ -403,6 +405,7 @@ export const useFlattenSchema = () => {
.map((item) => {
const itemPrefix = schema.type === 'array' ? schema.key : '';
return flattenSchema({
isDataEmpty,
schema: item,
expressionPrefix,
nodeType,
@@ -474,6 +477,7 @@ export const useFlattenSchema = () => {
acc = acc.concat(
flattenSchema({
isDataEmpty: item.isDataEmpty,
schema: item.schema,
depth: item.depth,
nodeType: item.node.type,

View File

@@ -10,16 +10,13 @@ import {
createTestWorkflow,
createTestWorkflowObject,
} 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 type { LogEntry } from '../logs.types';
import { createTestLogEntry } from '../__test__/mocks';
import { NodeConnectionTypes } from 'n8n-workflow';
describe('LogDetailsPanel', () => {
let pinia: TestingPinia;
let settingsStore: ReturnType<typeof mockedStore<typeof useSettingsStore>>;
const aiNode = createTestNode({ name: 'AI Agent' });
const workflowData = createTestWorkflow({
@@ -84,11 +81,6 @@ describe('LogDetailsPanel', () => {
beforeEach(() => {
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 () => {
@@ -155,4 +147,29 @@ describe('LogDetailsPanel', () => {
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();
});
});