@railtownai/railtracks-visualizer 0.0.2 → 0.0.4

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 (71) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +52 -23
  3. package/dist/cjs/AgenticFlowVisualizer.js +750 -0
  4. package/dist/cjs/App.js +94 -0
  5. package/dist/cjs/Visualizer.js +16 -0
  6. package/dist/cjs/components/Edge.js +75 -0
  7. package/dist/cjs/components/FileSelector.js +28 -0
  8. package/dist/cjs/components/Node.js +104 -0
  9. package/dist/cjs/components/Timeline.js +122 -0
  10. package/dist/cjs/components/VerticalTimeline.js +160 -0
  11. package/dist/cjs/hooks/index.js +7 -0
  12. package/dist/cjs/hooks/useApi.js +108 -0
  13. package/dist/cjs/hooks/useFlowData.js +53 -0
  14. package/dist/cjs/index.js +40 -0
  15. package/dist/cjs/test/Visualizer.test.js +257 -0
  16. package/dist/cjs/test/setup.js +24 -0
  17. package/dist/{AgenticFlowVisualizer.js → esm/AgenticFlowVisualizer.js} +286 -286
  18. package/dist/{App.js → esm/App.js} +76 -76
  19. package/dist/esm/Visualizer.js +11 -0
  20. package/dist/{components → esm/components}/Edge.js +10 -10
  21. package/dist/{components → esm/components}/Node.js +70 -70
  22. package/dist/{components → esm/components}/VerticalTimeline.js +12 -12
  23. package/dist/{index.js → esm/index.js} +1 -2
  24. package/dist/esm/test/Visualizer.test.js +243 -0
  25. package/dist/{test → esm/test}/setup.js +1 -1
  26. package/dist/{AgenticFlowVisualizer.d.ts → types/AgenticFlowVisualizer.d.ts} +2 -2
  27. package/dist/types/AgenticFlowVisualizer.d.ts.map +1 -0
  28. package/dist/types/App.d.ts.map +1 -0
  29. package/dist/types/Visualizer.d.ts +9 -0
  30. package/dist/types/Visualizer.d.ts.map +1 -0
  31. package/dist/types/components/Edge.d.ts.map +1 -0
  32. package/dist/types/components/FileSelector.d.ts.map +1 -0
  33. package/dist/types/components/Node.d.ts.map +1 -0
  34. package/dist/types/components/Timeline.d.ts.map +1 -0
  35. package/dist/types/components/VerticalTimeline.d.ts.map +1 -0
  36. package/dist/types/hooks/index.d.ts.map +1 -0
  37. package/dist/types/hooks/useApi.d.ts.map +1 -0
  38. package/dist/types/hooks/useFlowData.d.ts.map +1 -0
  39. package/dist/{index.d.ts → types/index.d.ts} +2 -1
  40. package/dist/types/index.d.ts.map +1 -0
  41. package/dist/types/test/Visualizer.test.d.ts +2 -0
  42. package/dist/types/test/Visualizer.test.d.ts.map +1 -0
  43. package/dist/types/test/setup.d.ts.map +1 -0
  44. package/package.json +82 -75
  45. package/dist/AgenticFlowVisualizer.d.ts.map +0 -1
  46. package/dist/App.d.ts.map +0 -1
  47. package/dist/components/Edge.d.ts.map +0 -1
  48. package/dist/components/FileSelector.d.ts.map +0 -1
  49. package/dist/components/Node.d.ts.map +0 -1
  50. package/dist/components/Timeline.d.ts.map +0 -1
  51. package/dist/components/VerticalTimeline.d.ts.map +0 -1
  52. package/dist/hooks/index.d.ts.map +0 -1
  53. package/dist/hooks/useApi.d.ts.map +0 -1
  54. package/dist/hooks/useFlowData.d.ts.map +0 -1
  55. package/dist/index.d.ts.map +0 -1
  56. package/dist/test/setup.d.ts.map +0 -1
  57. /package/dist/{components → esm/components}/FileSelector.js +0 -0
  58. /package/dist/{components → esm/components}/Timeline.js +0 -0
  59. /package/dist/{hooks → esm/hooks}/index.js +0 -0
  60. /package/dist/{hooks → esm/hooks}/useApi.js +0 -0
  61. /package/dist/{hooks → esm/hooks}/useFlowData.js +0 -0
  62. /package/dist/{App.d.ts → types/App.d.ts} +0 -0
  63. /package/dist/{components → types/components}/Edge.d.ts +0 -0
  64. /package/dist/{components → types/components}/FileSelector.d.ts +0 -0
  65. /package/dist/{components → types/components}/Node.d.ts +0 -0
  66. /package/dist/{components → types/components}/Timeline.d.ts +0 -0
  67. /package/dist/{components → types/components}/VerticalTimeline.d.ts +0 -0
  68. /package/dist/{hooks → types/hooks}/index.d.ts +0 -0
  69. /package/dist/{hooks → types/hooks}/useApi.d.ts +0 -0
  70. /package/dist/{hooks → types/hooks}/useFlowData.d.ts +0 -0
  71. /package/dist/{test → types/test}/setup.d.ts +0 -0
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.useApi = void 0;
13
+ const react_1 = require("react");
14
+ // Base URL for the API
15
+ const API_BASE = "/api";
16
+ const useApi = () => {
17
+ const [loading, setLoading] = (0, react_1.useState)(false);
18
+ const [error, setError] = (0, react_1.useState)(null);
19
+ // Function to list all JSON files in the .railtracks directory
20
+ const listJsonFiles = (0, react_1.useCallback)(() => __awaiter(void 0, void 0, void 0, function* () {
21
+ setLoading(true);
22
+ setError(null);
23
+ try {
24
+ console.log("Fetching files from:", `${API_BASE}/files`);
25
+ const response = yield fetch(`${API_BASE}/files`);
26
+ console.log("Response status:", response.status);
27
+ if (!response.ok) {
28
+ throw new Error(`HTTP error! status: ${response.status}`);
29
+ }
30
+ const files = yield response.json();
31
+ console.log("Files received:", files);
32
+ return files;
33
+ }
34
+ catch (err) {
35
+ console.error("Error fetching files:", err);
36
+ const errorMessage = err instanceof Error ? err.message : "Unknown error occurred";
37
+ const apiError = {
38
+ message: errorMessage,
39
+ status: err instanceof Error && "status" in err ? err.status : undefined
40
+ };
41
+ setError(apiError);
42
+ return [];
43
+ }
44
+ finally {
45
+ setLoading(false);
46
+ }
47
+ }), []);
48
+ // Function to load a specific JSON file
49
+ const loadJsonFile = (0, react_1.useCallback)((filename) => __awaiter(void 0, void 0, void 0, function* () {
50
+ setLoading(true);
51
+ setError(null);
52
+ try {
53
+ const response = yield fetch(`${API_BASE}/json/${filename}`);
54
+ if (!response.ok) {
55
+ throw new Error(`HTTP error! status: ${response.status}`);
56
+ }
57
+ const data = yield response.json();
58
+ return data;
59
+ }
60
+ catch (err) {
61
+ const errorMessage = err instanceof Error ? err.message : "Unknown error occurred";
62
+ const apiError = {
63
+ message: errorMessage,
64
+ status: err instanceof Error && "status" in err ? err.status : undefined
65
+ };
66
+ setError(apiError);
67
+ return null;
68
+ }
69
+ finally {
70
+ setLoading(false);
71
+ }
72
+ }), []);
73
+ // Function to trigger a frontend refresh
74
+ const triggerRefresh = (0, react_1.useCallback)(() => __awaiter(void 0, void 0, void 0, function* () {
75
+ setLoading(true);
76
+ setError(null);
77
+ try {
78
+ const response = yield fetch(`${API_BASE}/refresh`, {
79
+ method: "POST"
80
+ });
81
+ if (!response.ok) {
82
+ throw new Error(`HTTP error! status: ${response.status}`);
83
+ }
84
+ const result = yield response.json();
85
+ return result;
86
+ }
87
+ catch (err) {
88
+ const errorMessage = err instanceof Error ? err.message : "Unknown error occurred";
89
+ const apiError = {
90
+ message: errorMessage,
91
+ status: err instanceof Error && "status" in err ? err.status : undefined
92
+ };
93
+ setError(apiError);
94
+ return null;
95
+ }
96
+ finally {
97
+ setLoading(false);
98
+ }
99
+ }), []);
100
+ return {
101
+ loading,
102
+ error,
103
+ listJsonFiles,
104
+ loadJsonFile,
105
+ triggerRefresh
106
+ };
107
+ };
108
+ exports.useApi = useApi;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.useFlowData = void 0;
13
+ const react_1 = require("react");
14
+ const useApi_1 = require("./useApi");
15
+ const useFlowData = () => {
16
+ const { listJsonFiles, loadJsonFile, loading: apiLoading, error: apiError } = (0, useApi_1.useApi)();
17
+ const [state, setState] = (0, react_1.useState)({
18
+ availableFiles: [],
19
+ currentFile: null,
20
+ flowData: null,
21
+ loading: false,
22
+ error: null
23
+ });
24
+ // Load available files on mount
25
+ (0, react_1.useEffect)(() => {
26
+ loadAvailableFiles();
27
+ }, []);
28
+ const loadAvailableFiles = (0, react_1.useCallback)(() => __awaiter(void 0, void 0, void 0, function* () {
29
+ const files = yield listJsonFiles();
30
+ setState((prev) => (Object.assign(Object.assign({}, prev), { availableFiles: files })));
31
+ }), [listJsonFiles]);
32
+ const loadFile = (0, react_1.useCallback)((filename) => __awaiter(void 0, void 0, void 0, function* () {
33
+ setState((prev) => (Object.assign(Object.assign({}, prev), { loading: true, error: null })));
34
+ try {
35
+ const data = yield loadJsonFile(filename);
36
+ if (data) {
37
+ setState((prev) => (Object.assign(Object.assign({}, prev), { currentFile: filename, flowData: data, loading: false, error: null })));
38
+ }
39
+ else {
40
+ setState((prev) => (Object.assign(Object.assign({}, prev), { loading: false, error: "Failed to load file data" })));
41
+ }
42
+ }
43
+ catch (err) {
44
+ setState((prev) => (Object.assign(Object.assign({}, prev), { loading: false, error: err instanceof Error ? err.message : "Unknown error occurred" })));
45
+ }
46
+ }), [loadJsonFile]);
47
+ const refreshFiles = (0, react_1.useCallback)(() => __awaiter(void 0, void 0, void 0, function* () {
48
+ yield loadAvailableFiles();
49
+ }), [loadAvailableFiles]);
50
+ return Object.assign(Object.assign({}, state), { loading: state.loading || apiLoading, error: state.error || (apiError === null || apiError === void 0 ? void 0 : apiError.message) || null, loadFile,
51
+ refreshFiles });
52
+ };
53
+ exports.useFlowData = useFlowData;
@@ -0,0 +1,40 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ var __importDefault = (this && this.__importDefault) || function (mod) {
17
+ return (mod && mod.__esModule) ? mod : { "default": mod };
18
+ };
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.VerticalTimeline = exports.Timeline = exports.Node = exports.FileSelector = exports.Edge = exports.App = exports.AgenticFlowVisualizer = exports.Visualizer = void 0;
21
+ // Library entry point for npm package
22
+ var Visualizer_1 = require("./Visualizer");
23
+ Object.defineProperty(exports, "Visualizer", { enumerable: true, get: function () { return __importDefault(Visualizer_1).default; } });
24
+ var AgenticFlowVisualizer_1 = require("./AgenticFlowVisualizer");
25
+ Object.defineProperty(exports, "AgenticFlowVisualizer", { enumerable: true, get: function () { return __importDefault(AgenticFlowVisualizer_1).default; } });
26
+ var App_1 = require("./App");
27
+ Object.defineProperty(exports, "App", { enumerable: true, get: function () { return __importDefault(App_1).default; } });
28
+ // Export components
29
+ var Edge_1 = require("./components/Edge");
30
+ Object.defineProperty(exports, "Edge", { enumerable: true, get: function () { return Edge_1.Edge; } });
31
+ var FileSelector_1 = require("./components/FileSelector");
32
+ Object.defineProperty(exports, "FileSelector", { enumerable: true, get: function () { return FileSelector_1.FileSelector; } });
33
+ var Node_1 = require("./components/Node");
34
+ Object.defineProperty(exports, "Node", { enumerable: true, get: function () { return Node_1.Node; } });
35
+ var Timeline_1 = require("./components/Timeline");
36
+ Object.defineProperty(exports, "Timeline", { enumerable: true, get: function () { return Timeline_1.Timeline; } });
37
+ var VerticalTimeline_1 = require("./components/VerticalTimeline");
38
+ Object.defineProperty(exports, "VerticalTimeline", { enumerable: true, get: function () { return VerticalTimeline_1.VerticalTimeline; } });
39
+ // Export hooks
40
+ __exportStar(require("./hooks"), exports);
@@ -0,0 +1,257 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ const jsx_runtime_1 = require("react/jsx-runtime");
16
+ const react_1 = __importDefault(require("react"));
17
+ const vitest_1 = require("vitest");
18
+ const react_2 = require("@testing-library/react");
19
+ const Visualizer_1 = __importDefault(require("../Visualizer"));
20
+ // Mock ReactFlow and its provider since we're testing the wrapper, not ReactFlow itself
21
+ vitest_1.vi.mock("reactflow", () => ({
22
+ ReactFlowProvider: ({ children }) => ((0, jsx_runtime_1.jsx)("div", { "data-testid": "react-flow-provider", children: children })),
23
+ useReactFlow: () => ({
24
+ fitView: vitest_1.vi.fn(),
25
+ getNodes: vitest_1.vi.fn(() => []),
26
+ getEdges: vitest_1.vi.fn(() => [])
27
+ })
28
+ }));
29
+ // Mock the AgenticFlowVisualizer component
30
+ vitest_1.vi.mock("../AgenticFlowVisualizer", () => ({
31
+ default: ({ flowData, width, height, className }) => ((0, jsx_runtime_1.jsxs)("div", { "data-testid": "agentic-flow-visualizer", "data-width": width || "", "data-height": height || "", "data-classname": className || "", "data-has-flow-data": !!flowData, children: ["AgenticFlowVisualizer Mock", !flowData && (0, jsx_runtime_1.jsx)("div", { "data-testid": "no-data-state", children: "No flow data available" })] }))
32
+ }));
33
+ // Mock data for testing
34
+ const mockFlowData = {
35
+ nodes: [
36
+ {
37
+ identifier: "node-1",
38
+ node_type: "agent",
39
+ stamp: {
40
+ step: 1,
41
+ time: 1634567890,
42
+ identifier: "stamp-1"
43
+ },
44
+ details: {
45
+ internals: {
46
+ llm_details: [
47
+ {
48
+ model_name: "gpt-4",
49
+ model_provider: "openai",
50
+ input: [{ role: "user", content: "test" }],
51
+ output: { role: "assistant", content: "response" },
52
+ input_tokens: 10,
53
+ output_tokens: 5,
54
+ total_cost: 0.001,
55
+ system_fingerprint: "test-fingerprint"
56
+ }
57
+ ]
58
+ }
59
+ },
60
+ parent: null
61
+ },
62
+ {
63
+ identifier: "node-2",
64
+ node_type: "tool",
65
+ stamp: {
66
+ step: 2,
67
+ time: 1634567891,
68
+ identifier: "stamp-2"
69
+ },
70
+ details: {
71
+ internals: {
72
+ llm_details: []
73
+ }
74
+ },
75
+ parent: null
76
+ }
77
+ ],
78
+ edges: [
79
+ {
80
+ identifier: "edge-1",
81
+ source: "node-1",
82
+ target: "node-2",
83
+ stamp: {
84
+ step: 2,
85
+ time: 1634567891,
86
+ identifier: "edge-stamp-1"
87
+ },
88
+ details: {
89
+ input_args: [],
90
+ output: null
91
+ },
92
+ parent: null
93
+ }
94
+ ],
95
+ stamps: [
96
+ {
97
+ step: 1,
98
+ time: 1634567890,
99
+ identifier: "stamp-1"
100
+ },
101
+ {
102
+ step: 2,
103
+ time: 1634567891,
104
+ identifier: "stamp-2"
105
+ }
106
+ ]
107
+ };
108
+ (0, vitest_1.describe)("Visualizer", () => {
109
+ (0, vitest_1.beforeEach)(() => {
110
+ vitest_1.vi.clearAllMocks();
111
+ });
112
+ (0, vitest_1.describe)("Component Rendering", () => {
113
+ (0, vitest_1.it)("renders successfully without any props", () => {
114
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, {}));
115
+ (0, vitest_1.expect)(react_2.screen.getByTestId("react-flow-provider")).toBeInTheDocument();
116
+ (0, vitest_1.expect)(react_2.screen.getByTestId("agentic-flow-visualizer")).toBeInTheDocument();
117
+ });
118
+ (0, vitest_1.it)("wraps AgenticFlowVisualizer with ReactFlowProvider", () => {
119
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: mockFlowData }));
120
+ const provider = react_2.screen.getByTestId("react-flow-provider");
121
+ const visualizer = react_2.screen.getByTestId("agentic-flow-visualizer");
122
+ (0, vitest_1.expect)(provider).toBeInTheDocument();
123
+ (0, vitest_1.expect)(provider).toContainElement(visualizer);
124
+ });
125
+ (0, vitest_1.it)("renders with valid flow data", () => {
126
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: mockFlowData }));
127
+ const visualizer = react_2.screen.getByTestId("agentic-flow-visualizer");
128
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-has-flow-data", "true");
129
+ (0, vitest_1.expect)(react_2.screen.queryByTestId("no-data-state")).not.toBeInTheDocument();
130
+ });
131
+ (0, vitest_1.it)("handles null flow data gracefully", () => {
132
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: null }));
133
+ const visualizer = react_2.screen.getByTestId("agentic-flow-visualizer");
134
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-has-flow-data", "false");
135
+ });
136
+ (0, vitest_1.it)("handles undefined flow data gracefully", () => {
137
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: undefined }));
138
+ const visualizer = react_2.screen.getByTestId("agentic-flow-visualizer");
139
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-has-flow-data", "false");
140
+ });
141
+ });
142
+ (0, vitest_1.describe)("Props Forwarding", () => {
143
+ (0, vitest_1.it)("forwards flowData prop correctly", () => {
144
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: mockFlowData }));
145
+ const visualizer = react_2.screen.getByTestId("agentic-flow-visualizer");
146
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-has-flow-data", "true");
147
+ });
148
+ (0, vitest_1.it)("forwards width prop correctly", () => {
149
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: mockFlowData, width: "800px" }));
150
+ const visualizer = react_2.screen.getByTestId("agentic-flow-visualizer");
151
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-width", "800px");
152
+ });
153
+ (0, vitest_1.it)("forwards height prop correctly", () => {
154
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: mockFlowData, height: 600 }));
155
+ const visualizer = react_2.screen.getByTestId("agentic-flow-visualizer");
156
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-height", "600");
157
+ });
158
+ (0, vitest_1.it)("forwards className prop correctly", () => {
159
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: mockFlowData, className: "custom-class" }));
160
+ const visualizer = react_2.screen.getByTestId("agentic-flow-visualizer");
161
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-classname", "custom-class");
162
+ });
163
+ (0, vitest_1.it)("forwards all props together correctly", () => {
164
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: mockFlowData, width: "100%", height: "500px", className: "test-visualizer" }));
165
+ const visualizer = react_2.screen.getByTestId("agentic-flow-visualizer");
166
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-has-flow-data", "true");
167
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-width", "100%");
168
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-height", "500px");
169
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-classname", "test-visualizer");
170
+ });
171
+ (0, vitest_1.it)("uses default values when optional props are not provided", () => {
172
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: mockFlowData }));
173
+ const visualizer = react_2.screen.getByTestId("agentic-flow-visualizer");
174
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-width", "");
175
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-height", "");
176
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-classname", "");
177
+ });
178
+ });
179
+ (0, vitest_1.describe)("Integration as NPM Package Component", () => {
180
+ (0, vitest_1.it)("can be imported and used as a standalone component", () => {
181
+ // This test ensures the component works when imported by users
182
+ const TestApp = () => ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("h1", { children: "My App" }), (0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: mockFlowData })] }));
183
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(TestApp, {}));
184
+ (0, vitest_1.expect)(react_2.screen.getByText("My App")).toBeInTheDocument();
185
+ (0, vitest_1.expect)(react_2.screen.getByTestId("react-flow-provider")).toBeInTheDocument();
186
+ (0, vitest_1.expect)(react_2.screen.getByTestId("agentic-flow-visualizer")).toBeInTheDocument();
187
+ });
188
+ (0, vitest_1.it)("works in a React component with state", () => __awaiter(void 0, void 0, void 0, function* () {
189
+ const TestComponent = () => {
190
+ const [data, setData] = react_1.default.useState(null);
191
+ react_1.default.useEffect(() => {
192
+ // Simulate loading data
193
+ setTimeout(() => setData(mockFlowData), 100);
194
+ }, []);
195
+ return ((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)("button", { onClick: () => setData(null), children: "Clear Data" }), (0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: data })] }));
196
+ };
197
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(TestComponent, {}));
198
+ // Initially no data
199
+ (0, vitest_1.expect)(react_2.screen.getByTestId("agentic-flow-visualizer")).toHaveAttribute("data-has-flow-data", "false");
200
+ // Wait for data to load
201
+ yield (0, react_2.waitFor)(() => {
202
+ (0, vitest_1.expect)(react_2.screen.getByTestId("agentic-flow-visualizer")).toHaveAttribute("data-has-flow-data", "true");
203
+ });
204
+ }));
205
+ (0, vitest_1.it)("handles multiple instances on the same page", () => {
206
+ (0, react_2.render)((0, jsx_runtime_1.jsxs)("div", { children: [(0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: mockFlowData, className: "visualizer-1" }), (0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: null, className: "visualizer-2" })] }));
207
+ const visualizers = react_2.screen.getAllByTestId("agentic-flow-visualizer");
208
+ (0, vitest_1.expect)(visualizers).toHaveLength(2);
209
+ (0, vitest_1.expect)(visualizers[0]).toHaveAttribute("data-classname", "visualizer-1");
210
+ (0, vitest_1.expect)(visualizers[0]).toHaveAttribute("data-has-flow-data", "true");
211
+ (0, vitest_1.expect)(visualizers[1]).toHaveAttribute("data-classname", "visualizer-2");
212
+ (0, vitest_1.expect)(visualizers[1]).toHaveAttribute("data-has-flow-data", "false");
213
+ });
214
+ });
215
+ (0, vitest_1.describe)("Error Handling", () => {
216
+ (0, vitest_1.it)("handles malformed flow data gracefully", () => {
217
+ const malformedData = {
218
+ nodes: null,
219
+ edges: undefined
220
+ };
221
+ (0, vitest_1.expect)(() => {
222
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: malformedData }));
223
+ }).not.toThrow();
224
+ (0, vitest_1.expect)(react_2.screen.getByTestId("agentic-flow-visualizer")).toBeInTheDocument();
225
+ });
226
+ (0, vitest_1.it)("handles empty flow data", () => {
227
+ const emptyData = {
228
+ nodes: [],
229
+ edges: [],
230
+ stamps: []
231
+ };
232
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: emptyData }));
233
+ const visualizer = react_2.screen.getByTestId("agentic-flow-visualizer");
234
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-has-flow-data", "true");
235
+ });
236
+ });
237
+ (0, vitest_1.describe)("TypeScript Compatibility", () => {
238
+ (0, vitest_1.it)("accepts correct prop types", () => {
239
+ // This test ensures TypeScript compatibility
240
+ const props = {
241
+ flowData: mockFlowData,
242
+ width: "100%",
243
+ height: 600,
244
+ className: "test-class"
245
+ };
246
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, Object.assign({}, props)));
247
+ (0, vitest_1.expect)(react_2.screen.getByTestId("agentic-flow-visualizer")).toBeInTheDocument();
248
+ });
249
+ (0, vitest_1.it)("works with partial props", () => {
250
+ // Test that optional props work correctly
251
+ (0, react_2.render)((0, jsx_runtime_1.jsx)(Visualizer_1.default, { flowData: mockFlowData, width: "50%" }));
252
+ const visualizer = react_2.screen.getByTestId("agentic-flow-visualizer");
253
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-width", "50%");
254
+ (0, vitest_1.expect)(visualizer).toHaveAttribute("data-height", "");
255
+ });
256
+ });
257
+ });
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ require("@testing-library/jest-dom");
4
+ const vitest_1 = require("vitest");
5
+ // Mock ResizeObserver for React Flow components
6
+ globalThis.ResizeObserver = class ResizeObserver {
7
+ observe() { }
8
+ unobserve() { }
9
+ disconnect() { }
10
+ };
11
+ // Mock window.matchMedia
12
+ Object.defineProperty(window, "matchMedia", {
13
+ writable: true,
14
+ value: vitest_1.vi.fn().mockImplementation((query) => ({
15
+ matches: false,
16
+ media: query,
17
+ onchange: null,
18
+ addListener: vitest_1.vi.fn(), // deprecated
19
+ removeListener: vitest_1.vi.fn(), // deprecated
20
+ addEventListener: vitest_1.vi.fn(),
21
+ removeEventListener: vitest_1.vi.fn(),
22
+ dispatchEvent: vitest_1.vi.fn()
23
+ }))
24
+ });