1
1
import { createComponentRenderer } from '@/__tests__/render' ;
2
- import { SETTINGS_STORE_DEFAULT_STATE } from '@/__tests__/utils' ;
2
+
3
3
import NodeErrorView from '@/components/Error/NodeErrorView.vue' ;
4
- import { STORES } from '@/constants' ;
4
+
5
5
import { createTestingPinia } from '@pinia/testing' ;
6
- import { type INode } from 'n8n-workflow' ;
6
+ import type { NodeError } from 'n8n-workflow' ;
7
7
import { useAssistantStore } from '@/stores/assistant.store' ;
8
8
import { useNodeTypesStore } from '@/stores/nodeTypes.store' ;
9
+ import { mockedStore } from '@/__tests__/utils' ;
10
+ import userEvent from '@testing-library/user-event' ;
11
+ import { useNDVStore } from '@/stores/ndv.store' ;
9
12
10
- const DEFAULT_SETUP = {
11
- pinia : createTestingPinia ( {
12
- initialState : {
13
- [ STORES . SETTINGS ] : SETTINGS_STORE_DEFAULT_STATE ,
14
- } ,
15
- } ) ,
16
- } ;
13
+ const renderComponent = createComponentRenderer ( NodeErrorView ) ;
17
14
18
- const renderComponent = createComponentRenderer ( NodeErrorView , DEFAULT_SETUP ) ;
15
+ let mockAiAssistantStore : ReturnType < typeof mockedStore < typeof useAssistantStore > > ;
16
+ let mockNodeTypeStore : ReturnType < typeof mockedStore < typeof useNodeTypesStore > > ;
17
+ let mockNdvStore : ReturnType < typeof mockedStore < typeof useNDVStore > > ;
19
18
20
19
describe ( 'NodeErrorView.vue' , ( ) => {
21
- let mockNode : INode ;
22
- afterEach ( ( ) => {
23
- mockNode = {
24
- parameters : {
25
- mode : 'runOnceForAllItems' ,
26
- language : 'javaScript' ,
27
- jsCode : 'cons error = 9;' ,
28
- notice : '' ,
20
+ let error : NodeError ;
21
+
22
+ beforeEach ( ( ) => {
23
+ createTestingPinia ( ) ;
24
+
25
+ mockAiAssistantStore = mockedStore ( useAssistantStore ) ;
26
+ mockNodeTypeStore = mockedStore ( useNodeTypesStore ) ;
27
+ mockNdvStore = mockedStore ( useNDVStore ) ;
28
+ //@ts -expect-error
29
+ error = {
30
+ name : 'NodeOperationError' ,
31
+ message : 'Test error message' ,
32
+ description : 'Test error description' ,
33
+ context : {
34
+ descriptionKey : 'noInputConnection' ,
35
+ nodeCause : 'Test node cause' ,
36
+ runIndex : '1' ,
37
+ itemIndex : '2' ,
38
+ parameter : 'testParameter' ,
39
+ data : { key : 'value' } ,
40
+ causeDetailed : 'Detailed cause' ,
29
41
} ,
30
- id : 'd1ce5dc9-f9ae-4ac6-84e5-0696ba175dd9' ,
31
- name : 'Code' ,
32
- type : 'n8n-nodes-base.code' ,
33
- typeVersion : 2 ,
34
- position : [ 940 , 240 ] ,
42
+ node : {
43
+ parameters : {
44
+ mode : 'runOnceForAllItems' ,
45
+ language : 'javaScript' ,
46
+ jsCode : 'cons error = 9;' ,
47
+ notice : '' ,
48
+ } ,
49
+ id : 'd1ce5dc9-f9ae-4ac6-84e5-0696ba175dd9' ,
50
+ name : 'ErrorCode' ,
51
+ type : 'n8n-nodes-base.code' ,
52
+ typeVersion : 2 ,
53
+ position : [ 940 , 240 ] ,
54
+ } ,
55
+ stack : 'Test stack trace' ,
35
56
} ;
57
+ } ) ;
58
+ afterEach ( ( ) => {
36
59
vi . clearAllMocks ( ) ;
37
60
} ) ;
38
61
39
62
it ( 'renders an Error with a messages array' , async ( ) => {
40
63
const { getByTestId } = renderComponent ( {
41
64
props : {
42
65
error : {
43
- node : mockNode ,
66
+ node : error . node ,
44
67
messages : [ 'Unexpected identifier [line 1]' ] ,
45
68
} ,
46
69
} ,
@@ -55,7 +78,7 @@ describe('NodeErrorView.vue', () => {
55
78
const { getByTestId } = renderComponent ( {
56
79
props : {
57
80
error : {
58
- node : mockNode ,
81
+ node : error . node ,
59
82
message : 'Unexpected identifier [line 1]' ,
60
83
} ,
61
84
} ,
@@ -67,24 +90,20 @@ describe('NodeErrorView.vue', () => {
67
90
} ) ;
68
91
69
92
it ( 'should not render AI assistant button when error happens in deprecated function node' , async ( ) => {
70
- const aiAssistantStore = useAssistantStore ( DEFAULT_SETUP . pinia ) ;
71
- const nodeTypeStore = useNodeTypesStore ( DEFAULT_SETUP . pinia ) ;
72
-
73
93
//@ts -expect-error
74
- nodeTypeStore . getNodeType = vi . fn ( ( ) => ( {
94
+ mockNodeTypeStore . getNodeType = vi . fn ( ( ) => ( {
75
95
type : 'n8n-nodes-base.function' ,
76
96
typeVersion : 1 ,
77
97
hidden : true ,
78
98
} ) ) ;
79
99
80
- //@ts -expect-error
81
- aiAssistantStore . canShowAssistantButtonsOnCanvas = true ;
100
+ mockAiAssistantStore . canShowAssistantButtonsOnCanvas = true ;
82
101
83
102
const { queryByTestId } = renderComponent ( {
84
103
props : {
85
104
error : {
86
105
node : {
87
- ...mockNode ,
106
+ ...error . node ,
88
107
type : 'n8n-nodes-base.function' ,
89
108
typeVersion : 1 ,
90
109
} ,
@@ -96,4 +115,73 @@ describe('NodeErrorView.vue', () => {
96
115
97
116
expect ( aiAssistantButton ) . toBeNull ( ) ;
98
117
} ) ;
118
+
119
+ it ( 'renders error message' , ( ) => {
120
+ const { getByTestId } = renderComponent ( {
121
+ props : { error } ,
122
+ } ) ;
123
+ expect ( getByTestId ( 'node-error-message' ) . textContent ) . toContain ( 'Test error message' ) ;
124
+ } ) ;
125
+
126
+ it ( 'renders error description' , ( ) => {
127
+ const { getByTestId } = renderComponent ( {
128
+ props : { error } ,
129
+ } ) ;
130
+ expect ( getByTestId ( 'node-error-description' ) . innerHTML ) . toContain (
131
+ 'This node has no input data. Please make sure this node is connected to another node.' ,
132
+ ) ;
133
+ } ) ;
134
+
135
+ it ( 'renders stack trace' , ( ) => {
136
+ const { getByText } = renderComponent ( {
137
+ props : { error } ,
138
+ } ) ;
139
+ expect ( getByText ( 'Test stack trace' ) ) . toBeTruthy ( ) ;
140
+ } ) ;
141
+
142
+ it ( 'renders open node button when the error is in sub node' , ( ) => {
143
+ const { getByTestId, queryByTestId } = renderComponent ( {
144
+ props : {
145
+ error : {
146
+ ...error ,
147
+ name : 'NodeOperationError' ,
148
+ functionality : 'configuration-node' ,
149
+ } ,
150
+ } ,
151
+ } ) ;
152
+
153
+ expect ( getByTestId ( 'node-error-view-open-node-button' ) ) . toHaveTextContent ( 'Open errored node' ) ;
154
+
155
+ expect ( queryByTestId ( 'ask-assistant-button' ) ) . not . toBeInTheDocument ( ) ;
156
+ } ) ;
157
+
158
+ it ( 'does not renders open node button when the error is in sub node' , ( ) => {
159
+ mockAiAssistantStore . canShowAssistantButtonsOnCanvas = true ;
160
+ const { getByTestId, queryByTestId } = renderComponent ( {
161
+ props : {
162
+ error,
163
+ } ,
164
+ } ) ;
165
+
166
+ expect ( queryByTestId ( 'node-error-view-open-node-button' ) ) . not . toBeInTheDocument ( ) ;
167
+
168
+ expect ( getByTestId ( 'ask-assistant-button' ) ) . toBeInTheDocument ( ) ;
169
+ } ) ;
170
+
171
+ it ( 'open error node details when open error node is clicked' , async ( ) => {
172
+ const { getByTestId, emitted } = renderComponent ( {
173
+ props : {
174
+ error : {
175
+ ...error ,
176
+ name : 'NodeOperationError' ,
177
+ functionality : 'configuration-node' ,
178
+ } ,
179
+ } ,
180
+ } ) ;
181
+
182
+ await userEvent . click ( getByTestId ( 'node-error-view-open-node-button' ) ) ;
183
+
184
+ expect ( emitted ( ) . click ) . toHaveLength ( 1 ) ;
185
+ expect ( mockNdvStore . activeNodeName ) . toBe ( error . node . name ) ;
186
+ } ) ;
99
187
} ) ;
0 commit comments