fix(editor): Fix schema view in AI tools (#11089)
Some checks are pending
Test Master / install-and-build (push) Waiting to run
Test Master / Unit tests (18.x) (push) Blocked by required conditions
Test Master / Unit tests (20.x) (push) Blocked by required conditions
Test Master / Unit tests (22.4) (push) Blocked by required conditions
Test Master / Lint (push) Blocked by required conditions
Test Master / Notify Slack on failure (push) Blocked by required conditions

This commit is contained in:
Elias Meire 2024-10-04 14:29:42 +02:00 committed by GitHub
parent cc009559ee
commit 09cfdbd181
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 357 additions and 11 deletions

View file

@ -246,8 +246,8 @@ export default defineComponent({
isSchemaView(): boolean {
return this.displayMode === 'schema';
},
isInputSchemaView(): boolean {
return this.isSchemaView && this.paneType === 'input';
displaysMultipleNodes(): boolean {
return this.isSchemaView && this.paneType === 'input' && this.nodes.length > 0;
},
isTriggerNode(): boolean {
if (this.node === null) {
@ -1307,7 +1307,7 @@ export default defineComponent({
</div>
<div
v-if="maxRunIndex > 0 && !isInputSchemaView"
v-if="maxRunIndex > 0 && !displaysMultipleNodes"
v-show="!editMode.enabled"
:class="$style.runSelector"
>
@ -1349,7 +1349,7 @@ export default defineComponent({
<slot name="run-info"></slot>
</div>
<slot v-if="!isInputSchemaView" name="before-data" />
<slot v-if="!displaysMultipleNodes" name="before-data" />
<n8n-callout
v-for="hint in getNodeHints()"
@ -1361,7 +1361,7 @@ export default defineComponent({
</n8n-callout>
<div
v-if="maxOutputIndex > 0 && branches.length > 1 && !isInputSchemaView"
v-if="maxOutputIndex > 0 && branches.length > 1 && !displaysMultipleNodes"
:class="$style.outputs"
data-test-id="branches"
>
@ -1382,7 +1382,7 @@ export default defineComponent({
hasNodeRun &&
((dataCount > 0 && maxRunIndex === 0) || search) &&
!isArtificialRecoveredEventItem &&
!isInputSchemaView
!displaysMultipleNodes
"
v-show="!editMode.enabled && !hasRunError"
:class="[$style.itemsCount, { [$style.muted]: paneType === 'input' && maxRunIndex === 0 }]"
@ -1443,12 +1443,15 @@ export default defineComponent({
<slot name="node-waiting">xxx</slot>
</div>
<div v-else-if="!hasNodeRun && !(isInputSchemaView && node?.disabled)" :class="$style.center">
<div
v-else-if="!hasNodeRun && !(displaysMultipleNodes && node?.disabled)"
:class="$style.center"
>
<slot name="node-not-run"></slot>
</div>
<div
v-else-if="paneType === 'input' && !isInputSchemaView && node?.disabled"
v-else-if="paneType === 'input' && !displaysMultipleNodes && node?.disabled"
:class="$style.center"
>
<n8n-text>

View file

@ -95,7 +95,7 @@ const nodes = computed(() => {
return {
node: fullNode,
connectedOutputIndexes: node.indicies,
connectedOutputIndexes: node.indicies.length > 0 ? node.indicies : [0],
depth: node.depth,
itemsCount,
nodeType,
@ -264,7 +264,10 @@ watch(
</script>
<template>
<div v-if="paneType === 'input'" :class="[$style.schemaWrapper, { highlightSchema: highlight }]">
<div
v-if="paneType === 'input' && nodes.length > 0"
:class="[$style.schemaWrapper, { highlightSchema: highlight }]"
>
<div v-if="search && nodes.length > 0 && filteredNodes.length === 0" :class="$style.noMatch">
<n8n-text tag="h3" size="large">{{
$locale.baseText('ndv.search.noNodeMatch.title')

View file

@ -44,13 +44,20 @@ const ifNode = createTestNode({
disabled: false,
});
const aiTool = createTestNode({
name: 'AI Tool',
type: '@n8n/n8n-nodes-langchain.memoryBufferWindow',
typeVersion: 1,
disabled: false,
});
async function setupStore() {
const workflow = mock<IWorkflowDb>({
id: '123',
name: 'Test Workflow',
connections: {},
active: true,
nodes: [mockNode1, mockNode2, disabledNode, ifNode],
nodes: [mockNode1, mockNode2, disabledNode, ifNode, aiTool],
});
const pinia = createPinia();
@ -239,6 +246,49 @@ describe('RunDataSchema.vue', () => {
});
});
it('renders previous nodes schema for AI tools', async () => {
mockNodeOutputData(
'If',
[
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' },
],
0,
);
const { getByTestId } = renderComponent({
props: {
nodes: [
{
name: 'If',
indicies: [], // indicies are not set for AI tools
depth: 2,
},
],
node: aiTool,
},
});
await waitFor(() => {
expect(getByTestId('run-data-schema-node-name')).toHaveTextContent('If');
expect(getByTestId('run-data-schema-node-item-count')).toHaveTextContent('2 items');
expect(getByTestId('run-data-schema-node-schema')).toMatchSnapshot();
});
});
it('renders its own data for AI tools in debug mode', async () => {
const { getByTestId } = renderComponent({
props: {
nodes: [], // in debug mode nodes are empty
node: aiTool,
data: [{ output: 'AI tool output' }],
},
});
await waitFor(() => {
expect(getByTestId('run-data-schema-node-schema')).toMatchSnapshot();
});
});
test.each([[[{ tx: false }, { tx: false }]], [[{ tx: '' }, { tx: '' }]], [[{ tx: [] }]]])(
'renders schema instead of showing no data for %o',
(data) => {

View file

@ -1,5 +1,295 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
exports[`RunDataSchema.vue > renders its own data for AI tools in debug mode 1`] = `
<div
class="schema"
data-test-id="run-data-schema-node-schema"
data-v-46dade00=""
>
<div
class="item"
data-test-id="run-data-schema-item"
data-v-46dade00=""
>
<div
class="itemContent"
>
<!--v-if-->
<!--v-if-->
</div>
<!--v-if-->
<!--v-if-->
<div
class="sub"
>
<div
class="innerSub"
>
<div
class="item"
data-test-id="run-data-schema-item"
>
<div
class="itemContent"
>
<div
class="pill mappable"
title="string"
>
<span
class="label"
data-depth="1"
data-name="output"
data-path=".output"
data-target="mappable"
data-value="{{ $json.output }}"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-font fa-w-14 fa-sm"
data-icon="font"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
class=""
d="M432 416h-23.41L277.88 53.69A32 32 0 0 0 247.58 32h-47.16a32 32 0 0 0-30.3 21.69L39.41 416H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16h-19.58l23.3-64h152.56l23.3 64H304a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM176.85 272L224 142.51 271.15 272z"
fill="currentColor"
/>
</svg>
<!--v-if-->
<span
class="content"
>
<span>
<!--v-if-->
output
</span>
</span>
</span>
</div>
<span
class="text"
data-test-id="run-data-schema-item-value"
>
<!--v-if-->
<span
class="content"
>
<span>
<!--v-if-->
AI tool output
</span>
</span>
</span>
</div>
<!--v-if-->
<!--v-if-->
<!--v-if-->
</div>
</div>
</div>
</div>
</div>
`;
exports[`RunDataSchema.vue > renders previous nodes schema for AI tools 1`] = `
<div
class="schema animated"
data-test-id="run-data-schema-node-schema"
data-v-46dade00=""
>
<div
class="innerSchema"
data-v-46dade00=""
>
<div
class="item"
data-test-id="run-data-schema-item"
data-v-46dade00=""
>
<div
class="itemContent"
>
<!--v-if-->
<!--v-if-->
</div>
<!--v-if-->
<!--v-if-->
<div
class="sub"
>
<div
class="innerSub"
>
<div
class="item"
data-test-id="run-data-schema-item"
>
<div
class="itemContent"
>
<div
class="pill mappable"
title="number"
>
<span
class="label"
data-depth="1"
data-name="id"
data-path=".id"
data-target="mappable"
data-value="{{ $('If').item.json.id }}"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-hashtag fa-w-14 fa-sm"
data-icon="hashtag"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
class=""
d="M440.667 182.109l7.143-40c1.313-7.355-4.342-14.109-11.813-14.109h-74.81l14.623-81.891C377.123 38.754 371.468 32 363.997 32h-40.632a12 12 0 0 0-11.813 9.891L296.175 128H197.54l14.623-81.891C213.477 38.754 207.822 32 200.35 32h-40.632a12 12 0 0 0-11.813 9.891L132.528 128H53.432a12 12 0 0 0-11.813 9.891l-7.143 40C33.163 185.246 38.818 192 46.289 192h74.81L98.242 320H19.146a12 12 0 0 0-11.813 9.891l-7.143 40C-1.123 377.246 4.532 384 12.003 384h74.81L72.19 465.891C70.877 473.246 76.532 480 84.003 480h40.632a12 12 0 0 0 11.813-9.891L151.826 384h98.634l-14.623 81.891C234.523 473.246 240.178 480 247.65 480h40.632a12 12 0 0 0 11.813-9.891L315.472 384h79.096a12 12 0 0 0 11.813-9.891l7.143-40c1.313-7.355-4.342-14.109-11.813-14.109h-74.81l22.857-128h79.096a12 12 0 0 0 11.813-9.891zM261.889 320h-98.634l22.857-128h98.634l-22.857 128z"
fill="currentColor"
/>
</svg>
<!--v-if-->
<span
class="content"
>
<span>
<!--v-if-->
id
</span>
</span>
</span>
</div>
<span
class="text"
data-test-id="run-data-schema-item-value"
>
<!--v-if-->
<span
class="content"
>
<span>
<!--v-if-->
1
</span>
</span>
</span>
</div>
<!--v-if-->
<!--v-if-->
<!--v-if-->
</div>
<div
class="item"
data-test-id="run-data-schema-item"
>
<div
class="itemContent"
>
<div
class="pill mappable"
title="string"
>
<span
class="label"
data-depth="1"
data-name="name"
data-path=".name"
data-target="mappable"
data-value="{{ $('If').item.json.name }}"
>
<svg
aria-hidden="true"
class="svg-inline--fa fa-font fa-w-14 fa-sm"
data-icon="font"
data-prefix="fas"
focusable="false"
role="img"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
class=""
d="M432 416h-23.41L277.88 53.69A32 32 0 0 0 247.58 32h-47.16a32 32 0 0 0-30.3 21.69L39.41 416H16a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16h-19.58l23.3-64h152.56l23.3 64H304a16 16 0 0 0-16 16v32a16 16 0 0 0 16 16h128a16 16 0 0 0 16-16v-32a16 16 0 0 0-16-16zM176.85 272L224 142.51 271.15 272z"
fill="currentColor"
/>
</svg>
<!--v-if-->
<span
class="content"
>
<span>
<!--v-if-->
name
</span>
</span>
</span>
</div>
<span
class="text"
data-test-id="run-data-schema-item-value"
>
<!--v-if-->
<span
class="content"
>
<span>
<!--v-if-->
John
</span>
</span>
</span>
</div>
<!--v-if-->
<!--v-if-->
<!--v-if-->
</div>
</div>
</div>
</div>
</div>
</div>
`;
exports[`RunDataSchema.vue > renders schema for correct output branch 1`] = `
<div
class="schema animated"