@teleporthq/teleport-plugin-next-workflows 0.43.34 → 0.43.35

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.
@@ -0,0 +1,85 @@
1
+ import { NextWorkflowProjectPlugin } from '../src/workflow-project-plugin'
2
+
3
+ /**
4
+ * Regression: `generateGlobalWorkflowsHook` must never emit a `clientNodeHandlers`
5
+ * map entry that references a handler function it did not also define.
6
+ *
7
+ * Bug: `handlers` (the function definitions) was gated on `if (nodeRegistry[t])`,
8
+ * while `handlerEntries` (the map) mapped over EVERY collected client node type.
9
+ * A client-segment node whose type has no registry generator — e.g. a
10
+ * `general-comment`, or an `event-*` trigger node that got collected into the
11
+ * type set — therefore produced a map value `'general-comment': general_comment`
12
+ * with no `general_comment` defined anywhere in the file. That is a bare
13
+ * reference to an undefined identifier; it throws `ReferenceError: general_comment
14
+ * is not defined` when the module/hook is evaluated in production, crashing the
15
+ * Vercel build (global-workflows.js is pulled into the global client bundle for
16
+ * every page via `useGlobalWorkflows()`). The two lists must stay paired.
17
+ */
18
+
19
+ // A GLOBAL workflow (custom-triggered) whose client segment mixes a REGISTERED
20
+ // handler node (`state-update-local-state`) with an UNREGISTERED node type
21
+ // (`general-comment`, which has no entry in `nodeRegistry`). `general-comment`
22
+ // resolves to a client segment by default, so it lands in the handler type set.
23
+ const globalWorkflowWithUnregisteredNode = {
24
+ id: 'global-wf-unregistered',
25
+ trigger: { type: 'event-custom-triggered', config: { eventName: 'store-locations-loaded' } },
26
+ nodes: [
27
+ {
28
+ id: 'node-registered',
29
+ type: 'state-update-local-state',
30
+ config: { property: 'selectedPickupStore', value: '' },
31
+ stepNumber: 1,
32
+ },
33
+ {
34
+ id: 'node-unregistered',
35
+ type: 'general-comment',
36
+ config: { text: 'a designer note that must not become a handler' },
37
+ stepNumber: 2,
38
+ },
39
+ ],
40
+ edges: [{ id: 'edge-1', source: 'node-registered', target: 'node-unregistered' }],
41
+ }
42
+
43
+ function generateHook(): string {
44
+ const plugin = new NextWorkflowProjectPlugin()
45
+ // generateGlobalWorkflowsHook is private; call it directly for a unit test.
46
+ return (plugin as any).generateGlobalWorkflowsHook([globalWorkflowWithUnregisteredNode])
47
+ }
48
+
49
+ describe('generateGlobalWorkflowsHook — clientNodeHandlers map integrity', () => {
50
+ const code = generateHook()
51
+
52
+ it('defines a function for every identifier referenced in the handler map', () => {
53
+ // Match handler-map entries of the shape `'node-type': node_type` (the value
54
+ // identifier is the key with hyphens turned to underscores).
55
+ const entry = /['"]([a-z0-9]+(?:-[a-z0-9]+)+)['"]\s*:\s*([a-z0-9]+(?:_[a-z0-9]+)+)\b/g
56
+ const dangling: string[] = []
57
+ let m: RegExpExecArray | null = entry.exec(code)
58
+ while (m !== null) {
59
+ const [, key, ident] = m
60
+ if (key.replace(/-/g, '_') !== ident) {
61
+ m = entry.exec(code)
62
+ continue // not a handler-map entry
63
+ }
64
+ const isDefined = new RegExp(
65
+ `(?:async\\s+function|function|const|let|var)\\s+${ident}\\b`
66
+ ).test(code)
67
+ if (!isDefined) {
68
+ dangling.push(ident)
69
+ }
70
+ m = entry.exec(code)
71
+ }
72
+ expect(dangling).toEqual([])
73
+ })
74
+
75
+ it('keeps the registered handler in the map with its definition', () => {
76
+ expect(code).toContain("'state-update-local-state': state_update_local_state")
77
+ expect(code).toMatch(/(?:async\s+)?function state_update_local_state\s*\(/)
78
+ })
79
+
80
+ it('omits an unregistered node type (general-comment) entirely — no dangling reference', () => {
81
+ // Neither a definition nor a map entry for the unregistered type may appear.
82
+ expect(code).not.toContain('general_comment')
83
+ expect(code).not.toContain("'general-comment'")
84
+ })
85
+ })