@blucca/n8n-check 0.0.0-stage → 0.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/Dockerfile +10 -0
  2. package/LICENSE +21 -0
  3. package/README.md +323 -2
  4. package/bin/n8n-check.mjs +62 -0
  5. package/examples/agregado-enrichment/README.md +68 -0
  6. package/examples/agregado-enrichment/n8n-synthetic +11 -0
  7. package/examples/agregado-enrichment/observed-results.json +806 -0
  8. package/examples/agregado-enrichment/prepare.mjs +39 -0
  9. package/examples/identity-projection/README.md +39 -0
  10. package/examples/identity-projection/case.json +33 -0
  11. package/examples/identity-projection/observed-results.json +117 -0
  12. package/examples/identity-projection/workflow.json +71 -0
  13. package/examples/identity-projection/wrong-id.json +71 -0
  14. package/examples/morsof-invoice-history/README.md +77 -0
  15. package/examples/morsof-invoice-history/UPSTREAM-LICENSE +21 -0
  16. package/examples/morsof-invoice-history/n8n-datatable.cjs +28 -0
  17. package/examples/morsof-invoice-history/observed-results.json +113 -0
  18. package/examples/morsof-invoice-history/prepare.mjs +57 -0
  19. package/examples/morsof-invoice-history/replay.mjs +35 -0
  20. package/examples/morsof-invoice-history/run.sh +19 -0
  21. package/examples/object-body/broken.json +74 -0
  22. package/examples/object-body/case.json +81 -0
  23. package/examples/object-body/fixed.json +74 -0
  24. package/examples/object-body/observed-results.json +449 -0
  25. package/examples/object-body/retry-case.json +112 -0
  26. package/examples/object-body/retry.json +77 -0
  27. package/examples/propfind-body/README.md +75 -0
  28. package/examples/propfind-body/case.json +51 -0
  29. package/examples/propfind-body/no-body-control.json +96 -0
  30. package/examples/propfind-body/observed-results.json +307 -0
  31. package/examples/propfind-body/workflow.json +96 -0
  32. package/examples/raw-response/README.md +71 -0
  33. package/examples/raw-response/file-case.json +54 -0
  34. package/examples/raw-response/json-body.json +58 -0
  35. package/examples/raw-response/json-case.json +52 -0
  36. package/examples/raw-response/observed-results.json +383 -0
  37. package/examples/raw-response/raw-file.json +88 -0
  38. package/examples/raw-response/raw-json.json +58 -0
  39. package/examples/raw-response/raw-text.json +58 -0
  40. package/examples/raw-response/text-case.json +50 -0
  41. package/examples/retry-isolation/README.md +71 -0
  42. package/examples/retry-isolation/direct-case.json +112 -0
  43. package/examples/retry-isolation/direct.json +101 -0
  44. package/examples/retry-isolation/editor-template.json +168 -0
  45. package/examples/retry-isolation/http-batching-case.json +112 -0
  46. package/examples/retry-isolation/http-batching.json +107 -0
  47. package/examples/retry-isolation/loop-case.json +117 -0
  48. package/examples/retry-isolation/loop.json +133 -0
  49. package/examples/retry-isolation/observed-results.json +155 -0
  50. package/examples/silent-filter/README.md +57 -0
  51. package/examples/silent-filter/broken.json +96 -0
  52. package/examples/silent-filter/case.json +120 -0
  53. package/examples/silent-filter/fixed.json +96 -0
  54. package/examples/silent-filter/observed-results.json +273 -0
  55. package/examples/stop-after/README.md +66 -0
  56. package/examples/stop-after/broken.json +134 -0
  57. package/examples/stop-after/case.json +34 -0
  58. package/examples/stop-after/fixed.json +134 -0
  59. package/examples/stop-after/observed-results.json +162 -0
  60. package/examples/vapi-tool-contract/README.md +67 -0
  61. package/examples/vapi-tool-contract/backend-503.case.json +113 -0
  62. package/examples/vapi-tool-contract/empty-orders.case.json +113 -0
  63. package/examples/vapi-tool-contract/observed-results.json +234 -0
  64. package/examples/vapi-tool-contract/success.case.json +118 -0
  65. package/examples/vapi-tool-contract/workflow.json +143 -0
  66. package/examples/vapi-tool-contract/wrong-id.json +143 -0
  67. package/examples/version-matrix/README.md +65 -0
  68. package/examples/version-matrix/observed-results.json +307 -0
  69. package/examples/version-matrix/upgrade-check.yml +32 -0
  70. package/package.json +41 -4
  71. package/src/action.mjs +108 -0
  72. package/src/case-draft.mjs +163 -0
  73. package/src/local-bundle.mjs +154 -0
  74. package/src/mock.mjs +72 -0
  75. package/src/report.mjs +73 -0
  76. package/src/runner.mjs +111 -0
  77. package/src/version.mjs +3 -0
  78. package/src/workflow.mjs +140 -0
@@ -0,0 +1,449 @@
1
+ {
2
+ "description": "Actual n8n CLI executions in a Linux loopback-only network namespace. HTTP responses use synthetic local contracts.",
3
+ "cases": [
4
+ {
5
+ "name": "Two render requests preserve object options",
6
+ "startedAt": "2026-10-06T07:11:12.163Z",
7
+ "runnerVersion": "0.1.0",
8
+ "n8nVersion": "2.41.7",
9
+ "nodeVersion": "v26.10.0",
10
+ "status": "failed",
11
+ "exitCode": 1,
12
+ "network": {
13
+ "mode": "loopback-only",
14
+ "enforced": true,
15
+ "interfaces": [
16
+ "lo"
17
+ ]
18
+ },
19
+ "checks": [
20
+ {
21
+ "name": "n8n execution succeeds",
22
+ "passed": false,
23
+ "actual": {
24
+ "cliExitCode": 1,
25
+ "lastNode": "Render",
26
+ "message": "The value in the \"JSON Body\" field is not valid JSON",
27
+ "description": "Unexpected token 'o', ...\"ptions\": [object Obj\"... is not valid JSON",
28
+ "executionFound": true
29
+ }
30
+ },
31
+ {
32
+ "name": "Render: output 0",
33
+ "passed": false,
34
+ "expected": [
35
+ {
36
+ "id": "render-42"
37
+ },
38
+ {
39
+ "id": "render-43"
40
+ }
41
+ ],
42
+ "actual": []
43
+ },
44
+ {
45
+ "name": "mock: all requests match routes",
46
+ "passed": true,
47
+ "actual": []
48
+ },
49
+ {
50
+ "name": "mock: request limits and server",
51
+ "passed": true,
52
+ "actual": []
53
+ },
54
+ {
55
+ "name": "Render: POST /renders request count",
56
+ "passed": false,
57
+ "expected": 2,
58
+ "actual": 0
59
+ },
60
+ {
61
+ "name": "Render: POST /renders request bodies",
62
+ "passed": false,
63
+ "expected": [
64
+ {
65
+ "shortId": 42,
66
+ "renderOptions": {
67
+ "color": "#112233",
68
+ "fontSize": 31
69
+ }
70
+ },
71
+ {
72
+ "shortId": 43,
73
+ "renderOptions": {
74
+ "color": "#aabbcc",
75
+ "fontSize": 47
76
+ }
77
+ }
78
+ ],
79
+ "actual": []
80
+ }
81
+ ],
82
+ "requests": [],
83
+ "source": {
84
+ "workflow": "broken.json",
85
+ "case": "case.json",
86
+ "workflowSha256": "df776b7483357a89f969c27a4dfc0643d181be046a14298e91b9def3054cf04a",
87
+ "caseSha256": "feefda461df6928027dcc9a3932a1879a1b326e97ef414200b3a7863ebbdd6c1"
88
+ }
89
+ },
90
+ {
91
+ "name": "Two render requests preserve object options",
92
+ "startedAt": "2026-10-06T07:09:16.575Z",
93
+ "runnerVersion": "0.1.0",
94
+ "n8nVersion": "2.41.7",
95
+ "nodeVersion": "v26.10.0",
96
+ "status": "passed",
97
+ "exitCode": 0,
98
+ "network": {
99
+ "mode": "loopback-only",
100
+ "enforced": true,
101
+ "interfaces": [
102
+ "lo"
103
+ ]
104
+ },
105
+ "checks": [
106
+ {
107
+ "name": "n8n execution succeeds",
108
+ "passed": true,
109
+ "actual": {
110
+ "cliExitCode": 0,
111
+ "lastNode": "Render",
112
+ "executionFound": true
113
+ }
114
+ },
115
+ {
116
+ "name": "Render: output 0",
117
+ "passed": true,
118
+ "expected": [
119
+ {
120
+ "id": "render-42"
121
+ },
122
+ {
123
+ "id": "render-43"
124
+ }
125
+ ],
126
+ "actual": [
127
+ {
128
+ "id": "render-42"
129
+ },
130
+ {
131
+ "id": "render-43"
132
+ }
133
+ ]
134
+ },
135
+ {
136
+ "name": "mock: all requests match routes",
137
+ "passed": true,
138
+ "actual": []
139
+ },
140
+ {
141
+ "name": "mock: request limits and server",
142
+ "passed": true,
143
+ "actual": []
144
+ },
145
+ {
146
+ "name": "Render: POST /renders request count",
147
+ "passed": true,
148
+ "expected": 2,
149
+ "actual": 2
150
+ },
151
+ {
152
+ "name": "Render: POST /renders request bodies",
153
+ "passed": true,
154
+ "expected": [
155
+ {
156
+ "shortId": 42,
157
+ "renderOptions": {
158
+ "color": "#112233",
159
+ "fontSize": 31
160
+ }
161
+ },
162
+ {
163
+ "shortId": 43,
164
+ "renderOptions": {
165
+ "color": "#aabbcc",
166
+ "fontSize": 47
167
+ }
168
+ }
169
+ ],
170
+ "actual": [
171
+ {
172
+ "shortId": 42,
173
+ "renderOptions": {
174
+ "color": "#112233",
175
+ "fontSize": 31
176
+ }
177
+ },
178
+ {
179
+ "shortId": 43,
180
+ "renderOptions": {
181
+ "color": "#aabbcc",
182
+ "fontSize": 47
183
+ }
184
+ }
185
+ ]
186
+ }
187
+ ],
188
+ "requests": [
189
+ {
190
+ "node": "Render",
191
+ "method": "POST",
192
+ "path": "/renders",
193
+ "body": {
194
+ "shortId": 42,
195
+ "renderOptions": {
196
+ "color": "#112233",
197
+ "fontSize": 31
198
+ }
199
+ },
200
+ "matched": true,
201
+ "status": 200,
202
+ "response": {
203
+ "id": "render-42"
204
+ }
205
+ },
206
+ {
207
+ "node": "Render",
208
+ "method": "POST",
209
+ "path": "/renders",
210
+ "body": {
211
+ "shortId": 43,
212
+ "renderOptions": {
213
+ "color": "#aabbcc",
214
+ "fontSize": 47
215
+ }
216
+ },
217
+ "matched": true,
218
+ "status": 200,
219
+ "response": {
220
+ "id": "render-43"
221
+ }
222
+ }
223
+ ],
224
+ "source": {
225
+ "workflow": "fixed.json",
226
+ "case": "case.json",
227
+ "workflowSha256": "fc1aeb17520ebd6e19e70e37c98742271f6bd323d2f4b8c93dddaffa8ea55574",
228
+ "caseSha256": "feefda461df6928027dcc9a3932a1879a1b326e97ef414200b3a7863ebbdd6c1"
229
+ }
230
+ },
231
+ {
232
+ "name": "HTTP retry preserves both item payloads",
233
+ "startedAt": "2026-10-06T07:12:19.810Z",
234
+ "runnerVersion": "0.1.0",
235
+ "n8nVersion": "2.41.7",
236
+ "nodeVersion": "v26.10.0",
237
+ "status": "passed",
238
+ "exitCode": 0,
239
+ "network": {
240
+ "mode": "loopback-only",
241
+ "enforced": true,
242
+ "interfaces": [
243
+ "lo"
244
+ ]
245
+ },
246
+ "checks": [
247
+ {
248
+ "name": "n8n execution succeeds",
249
+ "passed": true,
250
+ "actual": {
251
+ "cliExitCode": 0,
252
+ "lastNode": "Render",
253
+ "executionFound": true
254
+ }
255
+ },
256
+ {
257
+ "name": "Render: output 0",
258
+ "passed": true,
259
+ "expected": [
260
+ {
261
+ "id": "render-42"
262
+ },
263
+ {
264
+ "id": "render-43"
265
+ }
266
+ ],
267
+ "actual": [
268
+ {
269
+ "id": "render-42"
270
+ },
271
+ {
272
+ "id": "render-43"
273
+ }
274
+ ]
275
+ },
276
+ {
277
+ "name": "mock: all requests match routes",
278
+ "passed": true,
279
+ "actual": []
280
+ },
281
+ {
282
+ "name": "mock: request limits and server",
283
+ "passed": true,
284
+ "actual": []
285
+ },
286
+ {
287
+ "name": "Render: POST /renders/42 request count",
288
+ "passed": true,
289
+ "expected": 2,
290
+ "actual": 2
291
+ },
292
+ {
293
+ "name": "Render: POST /renders/42 request bodies",
294
+ "passed": true,
295
+ "expected": [
296
+ {
297
+ "shortId": 42,
298
+ "renderOptions": {
299
+ "color": "#112233",
300
+ "fontSize": 31
301
+ }
302
+ },
303
+ {
304
+ "shortId": 42,
305
+ "renderOptions": {
306
+ "color": "#112233",
307
+ "fontSize": 31
308
+ }
309
+ }
310
+ ],
311
+ "actual": [
312
+ {
313
+ "shortId": 42,
314
+ "renderOptions": {
315
+ "color": "#112233",
316
+ "fontSize": 31
317
+ }
318
+ },
319
+ {
320
+ "shortId": 42,
321
+ "renderOptions": {
322
+ "color": "#112233",
323
+ "fontSize": 31
324
+ }
325
+ }
326
+ ]
327
+ },
328
+ {
329
+ "name": "Render: POST /renders/43 request count",
330
+ "passed": true,
331
+ "expected": 2,
332
+ "actual": 2
333
+ },
334
+ {
335
+ "name": "Render: POST /renders/43 request bodies",
336
+ "passed": true,
337
+ "expected": [
338
+ {
339
+ "shortId": 43,
340
+ "renderOptions": {
341
+ "color": "#aabbcc",
342
+ "fontSize": 47
343
+ }
344
+ },
345
+ {
346
+ "shortId": 43,
347
+ "renderOptions": {
348
+ "color": "#aabbcc",
349
+ "fontSize": 47
350
+ }
351
+ }
352
+ ],
353
+ "actual": [
354
+ {
355
+ "shortId": 43,
356
+ "renderOptions": {
357
+ "color": "#aabbcc",
358
+ "fontSize": 47
359
+ }
360
+ },
361
+ {
362
+ "shortId": 43,
363
+ "renderOptions": {
364
+ "color": "#aabbcc",
365
+ "fontSize": 47
366
+ }
367
+ }
368
+ ]
369
+ }
370
+ ],
371
+ "requests": [
372
+ {
373
+ "node": "Render",
374
+ "method": "POST",
375
+ "path": "/renders/42",
376
+ "body": {
377
+ "shortId": 42,
378
+ "renderOptions": {
379
+ "color": "#112233",
380
+ "fontSize": 31
381
+ }
382
+ },
383
+ "matched": true,
384
+ "status": 503,
385
+ "response": {
386
+ "error": "temporary fixture failure"
387
+ }
388
+ },
389
+ {
390
+ "node": "Render",
391
+ "method": "POST",
392
+ "path": "/renders/43",
393
+ "body": {
394
+ "shortId": 43,
395
+ "renderOptions": {
396
+ "color": "#aabbcc",
397
+ "fontSize": 47
398
+ }
399
+ },
400
+ "matched": true,
401
+ "status": 200,
402
+ "response": {
403
+ "id": "render-43"
404
+ }
405
+ },
406
+ {
407
+ "node": "Render",
408
+ "method": "POST",
409
+ "path": "/renders/42",
410
+ "body": {
411
+ "shortId": 42,
412
+ "renderOptions": {
413
+ "color": "#112233",
414
+ "fontSize": 31
415
+ }
416
+ },
417
+ "matched": true,
418
+ "status": 200,
419
+ "response": {
420
+ "id": "render-42"
421
+ }
422
+ },
423
+ {
424
+ "node": "Render",
425
+ "method": "POST",
426
+ "path": "/renders/43",
427
+ "body": {
428
+ "shortId": 43,
429
+ "renderOptions": {
430
+ "color": "#aabbcc",
431
+ "fontSize": 47
432
+ }
433
+ },
434
+ "matched": true,
435
+ "status": 200,
436
+ "response": {
437
+ "id": "render-43"
438
+ }
439
+ }
440
+ ],
441
+ "source": {
442
+ "workflow": "retry.json",
443
+ "case": "retry-case.json",
444
+ "workflowSha256": "9dbcef22892070ddb5613e98cee117d3c0db68024bbe30901011658e359baf75",
445
+ "caseSha256": "a86491f50cee02886c8da17477efba03b4245b661f0bd2fde6a07458fa2cdafc"
446
+ }
447
+ }
448
+ ]
449
+ }
@@ -0,0 +1,112 @@
1
+ {
2
+ "version": 1,
3
+ "name": "HTTP retry preserves both item payloads",
4
+ "input": {
5
+ "node": "Fixture",
6
+ "items": [
7
+ {
8
+ "shortId": 42,
9
+ "styling": {
10
+ "color": "#112233",
11
+ "fontSize": 31
12
+ }
13
+ },
14
+ {
15
+ "shortId": 43,
16
+ "styling": {
17
+ "color": "#aabbcc",
18
+ "fontSize": 47
19
+ }
20
+ }
21
+ ]
22
+ },
23
+ "mocks": [
24
+ {
25
+ "node": "Render",
26
+ "url": "/renders/{{ $json.shortId }}",
27
+ "routes": [
28
+ {
29
+ "method": "POST",
30
+ "path": "/renders/42",
31
+ "responses": [
32
+ {
33
+ "status": 503,
34
+ "json": {
35
+ "error": "temporary fixture failure"
36
+ }
37
+ },
38
+ {
39
+ "status": 200,
40
+ "json": {
41
+ "id": "render-42"
42
+ }
43
+ }
44
+ ],
45
+ "expect": {
46
+ "count": 2,
47
+ "bodies": [
48
+ {
49
+ "shortId": 42,
50
+ "renderOptions": {
51
+ "color": "#112233",
52
+ "fontSize": 31
53
+ }
54
+ },
55
+ {
56
+ "shortId": 42,
57
+ "renderOptions": {
58
+ "color": "#112233",
59
+ "fontSize": 31
60
+ }
61
+ }
62
+ ]
63
+ }
64
+ },
65
+ {
66
+ "method": "POST",
67
+ "path": "/renders/43",
68
+ "responses": [
69
+ {
70
+ "status": 200,
71
+ "json": {
72
+ "id": "render-43"
73
+ }
74
+ }
75
+ ],
76
+ "expect": {
77
+ "count": 2,
78
+ "bodies": [
79
+ {
80
+ "shortId": 43,
81
+ "renderOptions": {
82
+ "color": "#aabbcc",
83
+ "fontSize": 47
84
+ }
85
+ },
86
+ {
87
+ "shortId": 43,
88
+ "renderOptions": {
89
+ "color": "#aabbcc",
90
+ "fontSize": 47
91
+ }
92
+ }
93
+ ]
94
+ }
95
+ }
96
+ ]
97
+ }
98
+ ],
99
+ "assertions": [
100
+ {
101
+ "node": "Render",
102
+ "equals": [
103
+ {
104
+ "id": "render-42"
105
+ },
106
+ {
107
+ "id": "render-43"
108
+ }
109
+ ]
110
+ }
111
+ ]
112
+ }
@@ -0,0 +1,77 @@
1
+ {
2
+ "name": "Object body example",
3
+ "nodes": [
4
+ {
5
+ "id": "start",
6
+ "name": "Start",
7
+ "type": "n8n-nodes-base.manualTrigger",
8
+ "typeVersion": 1,
9
+ "position": [
10
+ -400,
11
+ 0
12
+ ],
13
+ "parameters": {}
14
+ },
15
+ {
16
+ "id": "fixture",
17
+ "name": "Fixture",
18
+ "type": "n8n-nodes-base.noOp",
19
+ "typeVersion": 1,
20
+ "position": [
21
+ -200,
22
+ 0
23
+ ],
24
+ "parameters": {}
25
+ },
26
+ {
27
+ "id": "render",
28
+ "name": "Render",
29
+ "type": "n8n-nodes-base.httpRequest",
30
+ "typeVersion": 4.2,
31
+ "position": [
32
+ 0,
33
+ 0
34
+ ],
35
+ "parameters": {
36
+ "method": "POST",
37
+ "url": "https://api.example.com/renders",
38
+ "sendBody": true,
39
+ "specifyBody": "json",
40
+ "jsonBody": "={{ { shortId: $json.shortId, renderOptions: $json.styling } }}",
41
+ "options": {
42
+ "timeout": 10000
43
+ }
44
+ },
45
+ "retryOnFail": true,
46
+ "maxTries": 2,
47
+ "waitBetweenTries": 10
48
+ }
49
+ ],
50
+ "connections": {
51
+ "Start": {
52
+ "main": [
53
+ [
54
+ {
55
+ "node": "Fixture",
56
+ "type": "main",
57
+ "index": 0
58
+ }
59
+ ]
60
+ ]
61
+ },
62
+ "Fixture": {
63
+ "main": [
64
+ [
65
+ {
66
+ "node": "Render",
67
+ "type": "main",
68
+ "index": 0
69
+ }
70
+ ]
71
+ ]
72
+ }
73
+ },
74
+ "settings": {
75
+ "executionOrder": "v1"
76
+ }
77
+ }