@elizaos/cli 1.0.8 → 1.0.10

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 (242) hide show
  1. package/README.md +9 -16
  2. package/dist/assets/{index-CZAd5zm2.js → index-CmuPnu0u.js} +72 -89
  3. package/dist/assets/index-CmuPnu0u.js.br +0 -0
  4. package/dist/assets/index-CmuPnu0u.js.map +1 -0
  5. package/dist/assets/{index-CaEsCLCC.js → index-DDQnwxzL.js} +28798 -16391
  6. package/dist/assets/{index-CaEsCLCC.js.map → index-DDQnwxzL.js.map} +1 -1
  7. package/dist/assets/index-Df1AFSuJ.css +1 -0
  8. package/dist/assets/index-Df1AFSuJ.css.br +0 -0
  9. package/dist/assets/vendor-DSdxb8P-.js.map +1 -1
  10. package/dist/{chunk-REBZFQYE.js → chunk-7HYEGM5V.js} +967 -1597
  11. package/dist/{chunk-W3HS2NP6.js → chunk-B4KJXECB.js} +13 -18
  12. package/dist/{chunk-33BHGAF7.js → chunk-GWQB7PBK.js} +59 -32
  13. package/dist/{chunk-CVADLFW6.js → chunk-LQ6XHF53.js} +4543 -3043
  14. package/dist/{chunk-GYTAJJOD.js → chunk-RIAWNDYI.js} +16 -2
  15. package/dist/{chunk-IEKLJDUU.js → chunk-WS4DWCDZ.js} +54 -32
  16. package/dist/commands/agent/actions/index.d.ts +5 -1
  17. package/dist/commands/agent/actions/index.js +5 -4
  18. package/dist/commands/agent/index.js +3 -4
  19. package/dist/commands/create/actions/index.js +4 -5
  20. package/dist/commands/create/index.js +5 -6
  21. package/dist/{fileFromPath-DCRQMDLJ.js → fileFromPath-KB6XMTJ4.js} +1 -0
  22. package/dist/index.html +2 -2
  23. package/dist/index.js +9346 -102098
  24. package/dist/{migrator-KZLCVEIH.js → migrator-JREQPDN3.js} +42 -220
  25. package/dist/pglite.data +0 -0
  26. package/dist/pglite.wasm +0 -0
  27. package/dist/plugin-creator-T4K2673C.js +910 -0
  28. package/dist/{registry-XFOSZFU4.js → registry-CBMRMYCG.js} +3 -4
  29. package/dist/templates/plugin-starter/README.md +255 -0
  30. package/dist/templates/plugin-starter/bunfig.toml +6 -0
  31. package/dist/templates/plugin-starter/cypress.config.ts +18 -0
  32. package/dist/templates/plugin-starter/index.html +13 -0
  33. package/dist/templates/plugin-starter/package.json +95 -0
  34. package/dist/templates/plugin-starter/postcss.config.js +3 -0
  35. package/dist/templates/plugin-starter/scripts/test-e2e-manual.js +201 -0
  36. package/dist/templates/plugin-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +404 -0
  37. package/dist/templates/plugin-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +287 -0
  38. package/dist/templates/plugin-starter/src/__tests__/cypress/support/commands.ts +38 -0
  39. package/dist/templates/plugin-starter/src/__tests__/cypress/support/component-index.html +11 -0
  40. package/dist/templates/plugin-starter/src/__tests__/cypress/support/component.ts +33 -0
  41. package/dist/templates/plugin-starter/src/__tests__/cypress/support/e2e.ts +11 -0
  42. package/dist/templates/plugin-starter/src/__tests__/cypress/tsconfig.json +10 -0
  43. package/dist/templates/plugin-starter/src/__tests__/e2e/README.md +47 -0
  44. package/dist/templates/plugin-starter/src/__tests__/e2e/starter-plugin.ts +320 -0
  45. package/{templates/plugin-starter → dist/templates/plugin-starter/src}/__tests__/integration.test.ts +22 -17
  46. package/{templates/plugin-starter → dist/templates/plugin-starter/src}/__tests__/plugin.test.ts +8 -8
  47. package/{templates/plugin-starter → dist/templates/plugin-starter/src}/__tests__/test-utils.ts +17 -17
  48. package/dist/templates/plugin-starter/src/frontend/index.css +77 -0
  49. package/dist/templates/plugin-starter/src/frontend/index.tsx +164 -0
  50. package/dist/templates/plugin-starter/src/frontend/utils.ts +6 -0
  51. package/dist/templates/plugin-starter/src/index.ts +274 -0
  52. package/dist/templates/plugin-starter/src/tests.ts +6 -0
  53. package/dist/templates/plugin-starter/tailwind.config.js +62 -0
  54. package/dist/templates/plugin-starter/tsconfig.build.json +11 -0
  55. package/dist/templates/plugin-starter/tsconfig.json +28 -0
  56. package/dist/templates/plugin-starter/tsup.config.ts +20 -0
  57. package/dist/templates/plugin-starter/vite.config.ts +20 -0
  58. package/dist/templates/project-starter/.env.example +153 -0
  59. package/dist/templates/project-starter/README.md +109 -0
  60. package/dist/templates/project-starter/bunfig.toml +6 -0
  61. package/dist/templates/project-starter/cypress.config.ts +31 -0
  62. package/dist/templates/project-starter/index.html +13 -0
  63. package/dist/templates/project-starter/package.json +83 -0
  64. package/dist/templates/project-starter/postcss.config.js +3 -0
  65. package/dist/templates/project-starter/scripts/test-all.sh +101 -0
  66. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/actions.test.ts +6 -6
  67. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/character.test.ts +3 -3
  68. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/config.test.ts +18 -18
  69. package/dist/templates/project-starter/src/__tests__/cypress/component/Accessibility.cy.tsx +271 -0
  70. package/dist/templates/project-starter/src/__tests__/cypress/component/ApiIntegration.cy.tsx +220 -0
  71. package/dist/templates/project-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +146 -0
  72. package/dist/templates/project-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +51 -0
  73. package/dist/templates/project-starter/src/__tests__/cypress/e2e/agent-chat.cy.ts +235 -0
  74. package/dist/templates/project-starter/src/__tests__/cypress/e2e/dashboard.cy.ts +146 -0
  75. package/dist/templates/project-starter/src/__tests__/cypress/e2e/user-workflow.cy.ts +257 -0
  76. package/dist/templates/project-starter/src/__tests__/cypress/support/commands.ts +44 -0
  77. package/dist/templates/project-starter/src/__tests__/cypress/support/component-index.html +11 -0
  78. package/dist/templates/project-starter/src/__tests__/cypress/support/component.ts +33 -0
  79. package/dist/templates/project-starter/src/__tests__/cypress/support/e2e.ts +179 -0
  80. package/dist/templates/project-starter/src/__tests__/e2e/index.ts +14 -0
  81. package/dist/templates/project-starter/src/__tests__/e2e/natural-language.test.ts +246 -0
  82. package/dist/templates/project-starter/src/__tests__/e2e/project.test.ts +155 -0
  83. package/dist/templates/project-starter/src/__tests__/e2e/starter-plugin.test.ts +421 -0
  84. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/env.test.ts +2 -2
  85. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/error-handling.test.ts +17 -17
  86. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/events.test.ts +7 -7
  87. package/dist/templates/project-starter/src/__tests__/file-structure.test.ts +135 -0
  88. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/integration.test.ts +25 -25
  89. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/models.test.ts +6 -6
  90. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/plugin.test.ts +9 -9
  91. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/provider.test.ts +7 -7
  92. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/routes.test.ts +3 -3
  93. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/test-utils.ts +17 -17
  94. package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/utils/core-test-utils.ts +3 -3
  95. package/dist/templates/project-starter/src/frontend/index.css +77 -0
  96. package/dist/templates/project-starter/src/frontend/index.html +19 -0
  97. package/dist/templates/project-starter/src/frontend/index.tsx +98 -0
  98. package/dist/templates/project-starter/src/frontend/utils.ts +6 -0
  99. package/dist/templates/project-starter/src/index.ts +153 -0
  100. package/dist/templates/project-starter/src/plugin.ts +255 -0
  101. package/dist/templates/project-starter/tailwind.config.js +62 -0
  102. package/dist/templates/project-starter/tsconfig.build.json +20 -0
  103. package/dist/templates/project-starter/tsconfig.json +39 -0
  104. package/dist/templates/project-starter/tsup.config.ts +19 -0
  105. package/dist/templates/project-starter/vite.config.ts +39 -0
  106. package/dist/templates/project-tee-starter/.dockerignore +20 -0
  107. package/dist/templates/project-tee-starter/.env.example +55 -0
  108. package/dist/templates/project-tee-starter/Dockerfile +66 -0
  109. package/dist/templates/project-tee-starter/GUIDE.md +235 -0
  110. package/dist/templates/project-tee-starter/README.md +173 -0
  111. package/dist/templates/project-tee-starter/__tests__/actions.test.ts +9 -0
  112. package/dist/templates/project-tee-starter/__tests__/character.test.ts +86 -0
  113. package/dist/templates/project-tee-starter/__tests__/config.test.ts +31 -0
  114. package/dist/templates/project-tee-starter/__tests__/env.test.ts +87 -0
  115. package/dist/templates/project-tee-starter/__tests__/error-handling.test.ts +30 -0
  116. package/dist/templates/project-tee-starter/__tests__/events.test.ts +21 -0
  117. package/{templates/project-starter → dist/templates/project-tee-starter}/__tests__/file-structure.test.ts +6 -6
  118. package/dist/templates/project-tee-starter/__tests__/integration.test.ts +205 -0
  119. package/dist/templates/project-tee-starter/__tests__/models.test.ts +22 -0
  120. package/dist/templates/project-tee-starter/__tests__/plugin.test.ts +38 -0
  121. package/dist/templates/project-tee-starter/__tests__/provider.test.ts +189 -0
  122. package/dist/templates/project-tee-starter/__tests__/routes.test.ts +21 -0
  123. package/dist/templates/project-tee-starter/__tests__/test-utils.ts +121 -0
  124. package/dist/templates/project-tee-starter/__tests__/utils/core-test-utils.ts +167 -0
  125. package/dist/templates/project-tee-starter/assets/mr-tee-portrait.jpg +0 -0
  126. package/dist/templates/project-tee-starter/bunfig.toml +6 -0
  127. package/dist/templates/project-tee-starter/docker-compose.yaml +57 -0
  128. package/dist/templates/project-tee-starter/e2e/project.test.ts +38 -0
  129. package/dist/templates/project-tee-starter/e2e/starter-plugin.test.ts +92 -0
  130. package/dist/templates/project-tee-starter/package.json +74 -0
  131. package/dist/templates/project-tee-starter/src/character.ts +257 -0
  132. package/dist/templates/project-tee-starter/src/index.ts +33 -0
  133. package/dist/templates/project-tee-starter/src/plugin.ts +169 -0
  134. package/dist/templates/project-tee-starter/tsconfig.build.json +13 -0
  135. package/dist/templates/project-tee-starter/tsconfig.json +30 -0
  136. package/dist/templates/project-tee-starter/tsup.config.ts +19 -0
  137. package/dist/{utils-DIZZ3HNZ.js → utils-TIALZU53.js} +9 -8
  138. package/package.json +29 -12
  139. package/templates/plugin-starter/README.md +38 -13
  140. package/templates/plugin-starter/bunfig.toml +6 -0
  141. package/templates/plugin-starter/cypress.config.ts +18 -0
  142. package/templates/plugin-starter/index.html +13 -0
  143. package/templates/plugin-starter/package.json +19 -7
  144. package/templates/plugin-starter/postcss.config.js +3 -0
  145. package/templates/plugin-starter/scripts/test-e2e-manual.js +201 -0
  146. package/templates/plugin-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +404 -0
  147. package/templates/plugin-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +287 -0
  148. package/templates/plugin-starter/src/__tests__/cypress/support/commands.ts +38 -0
  149. package/templates/plugin-starter/src/__tests__/cypress/support/component-index.html +11 -0
  150. package/templates/plugin-starter/src/__tests__/cypress/support/component.ts +33 -0
  151. package/templates/plugin-starter/src/__tests__/cypress/support/e2e.ts +11 -0
  152. package/templates/plugin-starter/src/__tests__/cypress/tsconfig.json +10 -0
  153. package/templates/plugin-starter/src/__tests__/e2e/README.md +47 -0
  154. package/templates/plugin-starter/src/__tests__/e2e/starter-plugin.ts +320 -0
  155. package/templates/plugin-starter/src/__tests__/integration.test.ts +138 -0
  156. package/templates/plugin-starter/src/__tests__/plugin.test.ts +182 -0
  157. package/templates/plugin-starter/src/__tests__/test-utils.ts +162 -0
  158. package/templates/plugin-starter/src/frontend/index.css +77 -0
  159. package/templates/plugin-starter/src/frontend/index.tsx +164 -0
  160. package/templates/plugin-starter/src/frontend/utils.ts +6 -0
  161. package/templates/plugin-starter/src/index.ts +31 -8
  162. package/templates/plugin-starter/src/tests.ts +6 -0
  163. package/templates/plugin-starter/tailwind.config.js +62 -0
  164. package/templates/plugin-starter/tsconfig.json +8 -8
  165. package/templates/plugin-starter/vite.config.ts +20 -0
  166. package/templates/project-starter/bunfig.toml +6 -0
  167. package/templates/project-starter/cypress.config.ts +31 -0
  168. package/templates/project-starter/index.html +13 -0
  169. package/templates/project-starter/package.json +37 -14
  170. package/templates/project-starter/postcss.config.js +3 -0
  171. package/templates/project-starter/scripts/test-all.sh +101 -0
  172. package/templates/project-starter/src/__tests__/actions.test.ts +155 -0
  173. package/templates/project-starter/src/__tests__/character.test.ts +86 -0
  174. package/templates/project-starter/src/__tests__/config.test.ts +193 -0
  175. package/templates/project-starter/src/__tests__/cypress/component/Accessibility.cy.tsx +271 -0
  176. package/templates/project-starter/src/__tests__/cypress/component/ApiIntegration.cy.tsx +220 -0
  177. package/templates/project-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +146 -0
  178. package/templates/project-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +51 -0
  179. package/templates/project-starter/src/__tests__/cypress/e2e/agent-chat.cy.ts +235 -0
  180. package/templates/project-starter/src/__tests__/cypress/e2e/dashboard.cy.ts +146 -0
  181. package/templates/project-starter/src/__tests__/cypress/e2e/user-workflow.cy.ts +257 -0
  182. package/templates/project-starter/src/__tests__/cypress/support/commands.ts +44 -0
  183. package/templates/project-starter/src/__tests__/cypress/support/component-index.html +11 -0
  184. package/templates/project-starter/src/__tests__/cypress/support/component.ts +33 -0
  185. package/templates/project-starter/src/__tests__/cypress/support/e2e.ts +179 -0
  186. package/templates/project-starter/src/__tests__/e2e/index.ts +14 -0
  187. package/templates/project-starter/src/__tests__/e2e/natural-language.test.ts +246 -0
  188. package/templates/project-starter/src/__tests__/e2e/project.test.ts +155 -0
  189. package/templates/project-starter/src/__tests__/e2e/starter-plugin.test.ts +421 -0
  190. package/templates/project-starter/src/__tests__/env.test.ts +87 -0
  191. package/templates/project-starter/src/__tests__/error-handling.test.ts +177 -0
  192. package/templates/project-starter/src/__tests__/events.test.ts +144 -0
  193. package/templates/project-starter/src/__tests__/file-structure.test.ts +135 -0
  194. package/templates/project-starter/src/__tests__/integration.test.ts +209 -0
  195. package/templates/project-starter/src/__tests__/models.test.ts +152 -0
  196. package/templates/project-starter/src/__tests__/plugin.test.ts +393 -0
  197. package/templates/project-starter/src/__tests__/provider.test.ts +325 -0
  198. package/templates/project-starter/src/__tests__/routes.test.ts +79 -0
  199. package/templates/project-starter/src/__tests__/test-utils.ts +121 -0
  200. package/templates/project-starter/src/__tests__/utils/core-test-utils.ts +180 -0
  201. package/templates/project-starter/src/frontend/index.css +77 -0
  202. package/templates/project-starter/src/frontend/index.html +19 -0
  203. package/templates/project-starter/src/frontend/index.tsx +98 -0
  204. package/templates/project-starter/src/frontend/utils.ts +6 -0
  205. package/templates/project-starter/src/index.ts +9 -1
  206. package/templates/project-starter/tailwind.config.js +62 -0
  207. package/templates/project-starter/tsconfig.build.json +9 -2
  208. package/templates/project-starter/tsconfig.json +15 -6
  209. package/templates/project-starter/tsup.config.ts +1 -1
  210. package/templates/project-starter/vite.config.ts +39 -0
  211. package/templates/project-tee-starter/__tests__/actions.test.ts +1 -1
  212. package/templates/project-tee-starter/__tests__/character.test.ts +1 -1
  213. package/templates/project-tee-starter/__tests__/config.test.ts +1 -1
  214. package/templates/project-tee-starter/__tests__/env.test.ts +2 -2
  215. package/templates/project-tee-starter/__tests__/error-handling.test.ts +1 -1
  216. package/templates/project-tee-starter/__tests__/events.test.ts +1 -1
  217. package/templates/project-tee-starter/__tests__/file-structure.test.ts +5 -5
  218. package/templates/project-tee-starter/__tests__/integration.test.ts +22 -26
  219. package/templates/project-tee-starter/__tests__/models.test.ts +1 -1
  220. package/templates/project-tee-starter/__tests__/plugin.test.ts +6 -12
  221. package/templates/project-tee-starter/__tests__/provider.test.ts +6 -6
  222. package/templates/project-tee-starter/__tests__/routes.test.ts +1 -1
  223. package/templates/project-tee-starter/__tests__/test-utils.ts +15 -15
  224. package/templates/project-tee-starter/__tests__/utils/core-test-utils.ts +3 -3
  225. package/templates/project-tee-starter/bunfig.toml +6 -0
  226. package/templates/project-tee-starter/package.json +10 -12
  227. package/dist/assets/index-CZAd5zm2.js.br +0 -0
  228. package/dist/assets/index-CZAd5zm2.js.map +0 -1
  229. package/dist/assets/index-DyA-lndn.css +0 -1
  230. package/dist/assets/index-DyA-lndn.css.br +0 -0
  231. package/dist/chunk-CEE6RKN5.js +0 -2746
  232. package/dist/chunk-MA2ZXPG6.js +0 -260
  233. package/dist/chunk-TUAYJIF2.js +0 -3649
  234. package/dist/lib-NAGYZHVV.js +0 -9
  235. package/dist/plugin-creator-IC42XOHG.js +0 -29165
  236. package/templates/plugin-starter/e2e/starter-plugin.test.ts +0 -171
  237. package/templates/plugin-starter/images/README.md +0 -24
  238. package/templates/plugin-starter/vitest.config.ts +0 -16
  239. package/templates/project-starter/e2e/project.test.ts +0 -34
  240. package/templates/project-starter/e2e/starter-plugin.test.ts +0 -217
  241. package/templates/project-starter/vitest.config.ts +0 -16
  242. package/templates/project-tee-starter/vitest.config.ts +0 -19
@@ -0,0 +1,404 @@
1
+ /// <reference types="cypress" />
2
+ /// <reference types="@cypress/react" />
3
+ /// <reference types="@testing-library/cypress" />
4
+
5
+ import React from 'react';
6
+ import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query';
7
+ import '../../../frontend/index.css';
8
+
9
+ // Define the interface for time response
10
+ interface TimeResponse {
11
+ timestamp: string;
12
+ unix: number;
13
+ formatted: string;
14
+ timezone: string;
15
+ }
16
+
17
+ // Define ELIZA config interface
18
+ interface ElizaConfig {
19
+ agentId: string;
20
+ apiBase?: string; // Make optional to fix type error
21
+ }
22
+
23
+ declare global {
24
+ interface Window {
25
+ ELIZA_CONFIG: ElizaConfig | undefined;
26
+ }
27
+ }
28
+
29
+ describe('ExampleRoute Component Tests', () => {
30
+ // Component definitions inside describe block to have access to cy
31
+ const TimeDisplay = ({ apiBase }: { apiBase: string }) => {
32
+ const { data, isLoading, error, refetch } = useQuery<TimeResponse>({
33
+ queryKey: ['currentTime'],
34
+ queryFn: async () => {
35
+ const response = await fetch(`${apiBase}/api/time`);
36
+ if (!response.ok) {
37
+ throw new Error('Failed to fetch time');
38
+ }
39
+ return response.json();
40
+ },
41
+ refetchInterval: 1000, // Refresh every second
42
+ });
43
+
44
+ if (isLoading) {
45
+ return <div className="text-gray-600">Loading time...</div>;
46
+ }
47
+
48
+ if (error) {
49
+ return (
50
+ <div className="text-red-600">
51
+ Error fetching time: {error instanceof Error ? error.message : 'Unknown error'}
52
+ </div>
53
+ );
54
+ }
55
+
56
+ return (
57
+ <div className="space-y-2" data-testid="time-display">
58
+ <h2 className="text-lg font-semibold">Current Time</h2>
59
+ <div className="space-y-1 text-sm">
60
+ <div>
61
+ <span className="font-medium">Formatted:</span> {data?.formatted}
62
+ </div>
63
+ <div>
64
+ <span className="font-medium">Timezone:</span> {data?.timezone}
65
+ </div>
66
+ <div>
67
+ <span className="font-medium">Unix:</span> {data?.unix}
68
+ </div>
69
+ </div>
70
+ <button
71
+ onClick={() => refetch()}
72
+ className="px-3 py-1 text-sm bg-primary text-primary-foreground rounded hover:opacity-90"
73
+ data-testid="refresh-button"
74
+ >
75
+ Refresh
76
+ </button>
77
+ </div>
78
+ );
79
+ };
80
+
81
+ const ExampleRoute = () => {
82
+ const [config] = React.useState(window.ELIZA_CONFIG);
83
+ const apiBase = config?.apiBase || 'http://localhost:3000';
84
+
85
+ React.useEffect(() => {
86
+ document.documentElement.classList.add('dark');
87
+ }, []);
88
+
89
+ if (!config?.agentId) {
90
+ return (
91
+ <div className="p-4 text-center">
92
+ <div className="text-red-600 font-medium">Error: Agent ID not found</div>
93
+ <div className="text-sm text-gray-600 mt-2">
94
+ The server should inject the agent ID configuration.
95
+ </div>
96
+ </div>
97
+ );
98
+ }
99
+
100
+ return (
101
+ <QueryClientProvider client={new QueryClient()}>
102
+ <div className="p-6 space-y-6">
103
+ <div>
104
+ <h1 className="text-2xl font-bold mb-2">Plugin Starter Example</h1>
105
+ <div className="text-sm text-muted-foreground">Agent ID: {config.agentId}</div>
106
+ </div>
107
+ <TimeDisplay apiBase={apiBase} />
108
+ </div>
109
+ </QueryClientProvider>
110
+ );
111
+ };
112
+
113
+ describe('Component Rendering', () => {
114
+ it('should apply dark mode on mount', () => {
115
+ cy.mount(<ExampleRoute />);
116
+ cy.shouldBeDarkMode();
117
+ });
118
+
119
+ it('should show error when agent ID is missing', () => {
120
+ // Clear the config before mounting
121
+ cy.window().then((win) => {
122
+ win.ELIZA_CONFIG = undefined;
123
+ });
124
+
125
+ cy.mount(<ExampleRoute />);
126
+
127
+ // Check error message is displayed
128
+ cy.contains('Error: Agent ID not found').should('be.visible');
129
+ cy.contains('The server should inject the agent ID configuration.').should('be.visible');
130
+ });
131
+
132
+ it('should render correctly with agent ID', () => {
133
+ const testAgentId = '12345678-1234-1234-1234-123456789abc';
134
+
135
+ // Set config before mounting
136
+ cy.window().then((win) => {
137
+ win.ELIZA_CONFIG = {
138
+ agentId: testAgentId,
139
+ apiBase: 'http://localhost:3000',
140
+ };
141
+ });
142
+
143
+ cy.mount(<ExampleRoute />);
144
+
145
+ // Check that the agent ID is displayed
146
+ cy.contains('Plugin Starter Example').should('be.visible');
147
+ cy.contains(`Agent ID: ${testAgentId}`).should('be.visible');
148
+ });
149
+ });
150
+
151
+ describe('API Communication', () => {
152
+ beforeEach(() => {
153
+ // Set up ELIZA_CONFIG
154
+ cy.window().then((win) => {
155
+ win.ELIZA_CONFIG = {
156
+ agentId: 'test-agent-123',
157
+ apiBase: 'http://localhost:3000',
158
+ };
159
+ });
160
+ });
161
+
162
+ it('should fetch and display time from backend', () => {
163
+ // Mock the API response
164
+ cy.intercept('GET', '**/api/time', {
165
+ statusCode: 200,
166
+ body: {
167
+ timestamp: '2024-01-01T12:00:00.000Z',
168
+ unix: 1704110400,
169
+ formatted: '1/1/2024, 12:00:00 PM',
170
+ timezone: 'UTC',
171
+ },
172
+ }).as('getTime');
173
+
174
+ cy.mount(<ExampleRoute />);
175
+
176
+ // Wait for the API call
177
+ cy.wait('@getTime');
178
+
179
+ // Check that time data is displayed
180
+ cy.get('[data-testid="time-display"]').should('be.visible');
181
+ cy.contains('Current Time').should('be.visible');
182
+ cy.contains('Formatted: 1/1/2024, 12:00:00 PM').should('be.visible');
183
+ cy.contains('Timezone: UTC').should('be.visible');
184
+ cy.contains('Unix: 1704110400').should('be.visible');
185
+ });
186
+
187
+ it('should refresh time when refresh button is clicked', () => {
188
+ let callCount = 0;
189
+
190
+ // Mock multiple API responses
191
+ cy.intercept('GET', '**/api/time', (req) => {
192
+ callCount++;
193
+ req.reply({
194
+ statusCode: 200,
195
+ body: {
196
+ timestamp: new Date().toISOString(),
197
+ unix: Math.floor(Date.now() / 1000) + callCount,
198
+ formatted: `Call ${callCount}: ${new Date().toLocaleString()}`,
199
+ timezone: 'UTC',
200
+ },
201
+ });
202
+ }).as('getTime');
203
+
204
+ cy.mount(<ExampleRoute />);
205
+
206
+ // Wait for initial load
207
+ cy.wait('@getTime');
208
+ cy.contains('Call 1:').should('be.visible');
209
+
210
+ // Click refresh button
211
+ cy.get('[data-testid="refresh-button"]').click();
212
+
213
+ // Wait for refresh
214
+ cy.wait('@getTime');
215
+ cy.contains('Call 2:').should('be.visible');
216
+ });
217
+
218
+ it('should verify auto-refresh behavior', () => {
219
+ let callCount = 0;
220
+
221
+ cy.intercept('GET', '**/api/time', (req) => {
222
+ callCount++;
223
+ req.reply({
224
+ statusCode: 200,
225
+ body: {
226
+ timestamp: new Date().toISOString(),
227
+ unix: Math.floor(Date.now() / 1000),
228
+ formatted: `Update ${callCount}`,
229
+ timezone: 'UTC',
230
+ },
231
+ });
232
+ }).as('getTime');
233
+
234
+ cy.mount(<ExampleRoute />);
235
+
236
+ // Wait for initial load
237
+ cy.wait('@getTime');
238
+ cy.contains('Update 1').should('be.visible');
239
+
240
+ // Verify multiple API calls happen due to auto-refresh
241
+ cy.wait('@getTime', { timeout: 2000 });
242
+ cy.get('@getTime.all').should('have.length.greaterThan', 1);
243
+ });
244
+
245
+ it('should show loading state', () => {
246
+ // Add delay to see loading state
247
+ cy.intercept('GET', '**/api/time', (req) => {
248
+ // Instead of req.reply with a callback, use a simpler approach
249
+ req.reply({
250
+ statusCode: 200,
251
+ body: {
252
+ timestamp: new Date().toISOString(),
253
+ unix: Math.floor(Date.now() / 1000),
254
+ formatted: new Date().toLocaleString(),
255
+ timezone: 'UTC',
256
+ },
257
+ delay: 1000, // Add delay directly
258
+ });
259
+ }).as('getTimeDelayed');
260
+
261
+ cy.mount(<ExampleRoute />);
262
+
263
+ // Check loading state
264
+ cy.contains('Loading time...').should('be.visible');
265
+
266
+ // Wait for data to load
267
+ cy.wait('@getTimeDelayed');
268
+ cy.contains('Loading time...').should('not.exist');
269
+ cy.get('[data-testid="time-display"]').should('be.visible');
270
+ });
271
+ });
272
+
273
+ describe('Configuration Handling', () => {
274
+ it('should handle different API base URLs', () => {
275
+ const customApiBase = 'https://api.example.com';
276
+
277
+ cy.window().then((win) => {
278
+ win.ELIZA_CONFIG = {
279
+ agentId: 'test-agent',
280
+ apiBase: customApiBase,
281
+ };
282
+ });
283
+
284
+ // Intercept with custom base URL
285
+ cy.intercept('GET', `${customApiBase}/api/time`, {
286
+ statusCode: 200,
287
+ body: {
288
+ timestamp: new Date().toISOString(),
289
+ unix: Math.floor(Date.now() / 1000),
290
+ formatted: 'Custom API Response',
291
+ timezone: 'UTC',
292
+ },
293
+ }).as('getTimeCustom');
294
+
295
+ cy.mount(<ExampleRoute />);
296
+
297
+ cy.wait('@getTimeCustom');
298
+ cy.contains('Custom API Response').should('be.visible');
299
+ });
300
+
301
+ it('should use default API base when not provided', () => {
302
+ cy.window().then((win) => {
303
+ win.ELIZA_CONFIG = {
304
+ agentId: 'test-agent',
305
+ // No apiBase provided - this is now valid with optional apiBase
306
+ };
307
+ });
308
+
309
+ // Intercept with default base URL
310
+ cy.intercept('GET', 'http://localhost:3000/api/time', {
311
+ statusCode: 200,
312
+ body: {
313
+ timestamp: new Date().toISOString(),
314
+ unix: Math.floor(Date.now() / 1000),
315
+ formatted: 'Default API Response',
316
+ timezone: 'UTC',
317
+ },
318
+ }).as('getTimeDefault');
319
+
320
+ cy.mount(<ExampleRoute />);
321
+
322
+ cy.wait('@getTimeDefault');
323
+ cy.contains('Default API Response').should('be.visible');
324
+ });
325
+ });
326
+
327
+ describe('Accessibility', () => {
328
+ beforeEach(() => {
329
+ cy.window().then((win) => {
330
+ win.ELIZA_CONFIG = {
331
+ agentId: 'test-agent',
332
+ apiBase: 'http://localhost:3000',
333
+ };
334
+ });
335
+
336
+ cy.intercept('GET', '**/api/time', {
337
+ statusCode: 200,
338
+ body: {
339
+ timestamp: new Date().toISOString(),
340
+ unix: Math.floor(Date.now() / 1000),
341
+ formatted: new Date().toLocaleString(),
342
+ timezone: 'UTC',
343
+ },
344
+ }).as('getTime');
345
+ });
346
+
347
+ it('should have proper heading hierarchy', () => {
348
+ cy.mount(<ExampleRoute />);
349
+ cy.wait('@getTime');
350
+
351
+ // Check h1 exists
352
+ cy.get('h1').contains('Plugin Starter Example').should('be.visible');
353
+
354
+ // Check h2 exists
355
+ cy.get('h2').contains('Current Time').should('be.visible');
356
+ });
357
+
358
+ it('should have accessible button', () => {
359
+ cy.mount(<ExampleRoute />);
360
+ cy.wait('@getTime');
361
+
362
+ // Button should be focusable and clickable
363
+ cy.get('[data-testid="refresh-button"]')
364
+ .should('be.visible')
365
+ .should('not.be.disabled')
366
+ .focus()
367
+ .should('have.focus');
368
+ });
369
+ });
370
+ });
371
+
372
+ /**
373
+ * TESTING PATTERNS FOR FRONTEND COMPONENTS IN ELIZAOS
374
+ *
375
+ * 1. COMPONENT ISOLATION
376
+ * - Test components in isolation using cy.mount()
377
+ * - Mock external dependencies (like API calls)
378
+ * - Use data-testid attributes for reliable element selection
379
+ *
380
+ * 2. CONFIGURATION TESTING
381
+ * - Always test with and without ELIZA_CONFIG
382
+ * - Test with invalid/malformed configurations
383
+ * - Verify error states and fallbacks
384
+ *
385
+ * 3. DARK MODE SUPPORT
386
+ * - Ensure components work in both light and dark modes
387
+ * - Use the custom shouldBeDarkMode() command
388
+ *
389
+ * 4. QUERY CLIENT TESTING
390
+ * - Mock API responses for react-query
391
+ * - Test loading, error, and success states
392
+ * - Verify cache behavior
393
+ *
394
+ * 5. ACCESSIBILITY
395
+ * - Use Testing Library queries (findByRole, findByText)
396
+ * - Test keyboard navigation
397
+ * - Verify ARIA attributes
398
+ *
399
+ * 6. API INTEGRATION TESTING
400
+ * - Mock all external API calls
401
+ * - Test error handling
402
+ * - Verify retry logic
403
+ * - Test different response scenarios
404
+ */
@@ -0,0 +1,287 @@
1
+ import React from 'react';
2
+ import { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query';
3
+ import { panels } from '../../../frontend/index';
4
+
5
+ // Time response interface
6
+ interface TimeResponse {
7
+ timestamp: string;
8
+ unix: number;
9
+ formatted: string;
10
+ timezone: string;
11
+ }
12
+
13
+ // Enhanced Panel Component with time display
14
+ const EnhancedPanelComponent: React.FC<{ agentId: string }> = ({ agentId }) => {
15
+ const apiBase = window.ELIZA_CONFIG?.apiBase || 'http://localhost:3000';
16
+
17
+ const {
18
+ data: timeData,
19
+ isLoading,
20
+ error,
21
+ } = useQuery<TimeResponse>({
22
+ queryKey: ['panelTime', agentId],
23
+ queryFn: async () => {
24
+ const response = await fetch(`${apiBase}/api/time`);
25
+ if (!response.ok) {
26
+ throw new Error('Failed to fetch time');
27
+ }
28
+ return response.json();
29
+ },
30
+ refetchInterval: 5000, // Refresh every 5 seconds
31
+ });
32
+
33
+ return (
34
+ <div className="p-4 space-y-4">
35
+ <div>
36
+ <h2 className="text-lg font-semibold mb-2">Example Panel</h2>
37
+ <div>Hello {agentId}!</div>
38
+ </div>
39
+
40
+ <div className="border-t pt-4">
41
+ <h3 className="text-md font-medium mb-2">Server Time</h3>
42
+ {isLoading && <div className="text-gray-600">Loading time...</div>}
43
+ {error && <div className="text-red-600">Error loading time</div>}
44
+ {timeData && (
45
+ <div className="text-sm space-y-1">
46
+ <div>Time: {timeData.formatted}</div>
47
+ <div className="text-gray-600">Timezone: {timeData.timezone}</div>
48
+ </div>
49
+ )}
50
+ </div>
51
+ </div>
52
+ );
53
+ };
54
+
55
+ describe('PanelComponent Tests', () => {
56
+ // Get the Panel component from the exported panels
57
+ const PanelComponent = panels[0]?.component;
58
+
59
+ describe('Panel Registration', () => {
60
+ it('should export panels array with correct structure', () => {
61
+ expect(panels).to.be.an('array');
62
+ expect(panels).to.have.length.greaterThan(0);
63
+
64
+ const panel = panels[0];
65
+ expect(panel).to.have.property('name', 'Example');
66
+ expect(panel).to.have.property('path', 'example');
67
+ expect(panel).to.have.property('component');
68
+ expect(panel).to.have.property('icon', 'Book');
69
+ expect(panel).to.have.property('public', false);
70
+ expect(panel).to.have.property('shortLabel', 'Example');
71
+ });
72
+ });
73
+
74
+ describe('Component Rendering', () => {
75
+ it('should render with agent ID', () => {
76
+ const testAgentId = 'test-agent-12345';
77
+
78
+ if (!PanelComponent) {
79
+ throw new Error('PanelComponent not found in panels export');
80
+ }
81
+
82
+ cy.mount(<PanelComponent agentId={testAgentId} />);
83
+
84
+ // Updated to match the corrected text in the component
85
+ cy.contains(`Hello ${testAgentId}!`).should('be.visible');
86
+ });
87
+
88
+ it('should handle different agent IDs', () => {
89
+ const agentIds = ['agent-1', 'agent-2', '12345678-1234-1234-1234-123456789abc', 'test-agent'];
90
+
91
+ agentIds.forEach((agentId) => {
92
+ cy.mount(<PanelComponent agentId={agentId} />);
93
+ cy.contains(`Hello ${agentId}!`).should('be.visible');
94
+ });
95
+ });
96
+
97
+ it('should render without crashing with empty agent ID', () => {
98
+ cy.mount(<PanelComponent agentId="" />);
99
+ cy.contains('Hello !').should('be.visible');
100
+ });
101
+ });
102
+
103
+ describe('Enhanced Panel with Time Display', () => {
104
+ const queryClient = new QueryClient({
105
+ defaultOptions: {
106
+ queries: {
107
+ retry: false,
108
+ },
109
+ },
110
+ });
111
+
112
+ beforeEach(() => {
113
+ // Set up ELIZA_CONFIG for API testing
114
+ cy.window().then((win) => {
115
+ win.ELIZA_CONFIG = {
116
+ agentId: 'test-agent',
117
+ apiBase: 'http://localhost:3000',
118
+ };
119
+ });
120
+ });
121
+
122
+ it('should fetch and display time in panel', () => {
123
+ cy.intercept('GET', '**/api/time', {
124
+ statusCode: 200,
125
+ body: {
126
+ timestamp: '2024-01-01T12:00:00.000Z',
127
+ unix: 1704110400,
128
+ formatted: '1/1/2024, 12:00:00 PM',
129
+ timezone: 'America/New_York',
130
+ },
131
+ }).as('getPanelTime');
132
+
133
+ cy.mount(
134
+ <QueryClientProvider client={queryClient}>
135
+ <EnhancedPanelComponent agentId="test-panel-123" />
136
+ </QueryClientProvider>
137
+ );
138
+
139
+ // Wait for API call
140
+ cy.wait('@getPanelTime');
141
+
142
+ // Check panel content
143
+ cy.contains('Example Panel').should('be.visible');
144
+ cy.contains('Hello test-panel-123!').should('be.visible');
145
+
146
+ // Check time display
147
+ cy.contains('Server Time').should('be.visible');
148
+ cy.contains('Time: 1/1/2024, 12:00:00 PM').should('be.visible');
149
+ cy.contains('Timezone: America/New_York').should('be.visible');
150
+ });
151
+
152
+ it('should handle API errors in panel', () => {
153
+ cy.intercept('GET', '**/api/time', {
154
+ statusCode: 500,
155
+ body: { error: 'Server error' },
156
+ }).as('getPanelTimeError');
157
+
158
+ cy.mount(
159
+ <QueryClientProvider client={queryClient}>
160
+ <EnhancedPanelComponent agentId="test-panel-error" />
161
+ </QueryClientProvider>
162
+ );
163
+
164
+ // Wait for failed API call
165
+ cy.wait('@getPanelTimeError');
166
+
167
+ // Check error display
168
+ cy.contains('Error loading time').should('be.visible');
169
+ });
170
+
171
+ it('should show loading state in panel', () => {
172
+ cy.intercept('GET', '**/api/time', (req) => {
173
+ // Use simpler delay approach
174
+ req.reply({
175
+ statusCode: 200,
176
+ body: {
177
+ timestamp: new Date().toISOString(),
178
+ unix: Math.floor(Date.now() / 1000),
179
+ formatted: new Date().toLocaleString(),
180
+ timezone: 'UTC',
181
+ },
182
+ delay: 1000, // Add delay directly
183
+ });
184
+ }).as('getPanelTimeDelayed');
185
+
186
+ cy.mount(
187
+ <QueryClientProvider client={queryClient}>
188
+ <EnhancedPanelComponent agentId="test-panel-loading" />
189
+ </QueryClientProvider>
190
+ );
191
+
192
+ // Check loading state
193
+ cy.contains('Loading time...').should('be.visible');
194
+
195
+ // Wait for data
196
+ cy.wait('@getPanelTimeDelayed');
197
+ cy.contains('Loading time...').should('not.exist');
198
+ });
199
+ });
200
+
201
+ describe('Panel Integration', () => {
202
+ it('should integrate with agent UI system', () => {
203
+ // Verify panel can be used in the agent UI
204
+ const panel = panels[0];
205
+
206
+ // Create a mock agent UI container
207
+ const AgentUIContainer = ({ agentId }: { agentId: string }) => {
208
+ const Component = panel.component;
209
+ return (
210
+ <div className="agent-ui-container">
211
+ <div className="panel-header">
212
+ <span className="panel-icon">{panel.icon}</span>
213
+ <span className="panel-name">{panel.name}</span>
214
+ </div>
215
+ <div className="panel-content">
216
+ <Component agentId={agentId} />
217
+ </div>
218
+ </div>
219
+ );
220
+ };
221
+
222
+ cy.mount(<AgentUIContainer agentId="ui-test-agent" />);
223
+
224
+ // Verify integration
225
+ cy.get('.agent-ui-container').should('be.visible');
226
+ cy.get('.panel-icon').contains('Book').should('be.visible');
227
+ cy.get('.panel-name').contains('Example').should('be.visible');
228
+ cy.get('.panel-content').contains('Hello ui-test-agent!').should('be.visible');
229
+ });
230
+
231
+ it('should handle panel switching', () => {
232
+ // Simulate multiple panels
233
+ const mockPanels = [
234
+ ...panels,
235
+ {
236
+ name: 'Second Panel',
237
+ path: 'second',
238
+ component: ({ agentId }: { agentId: string }) => <div>Second panel for {agentId}</div>,
239
+ icon: 'Settings',
240
+ public: false,
241
+ shortLabel: 'Second',
242
+ },
243
+ ];
244
+
245
+ let currentPanel = 0;
246
+
247
+ const PanelSwitcher = () => {
248
+ const [activePanel, setActivePanel] = React.useState(0);
249
+ const ActiveComponent = mockPanels[activePanel].component;
250
+
251
+ return (
252
+ <div>
253
+ <div className="panel-tabs">
254
+ {mockPanels.map((panel, index) => (
255
+ <button
256
+ key={panel.path}
257
+ onClick={() => setActivePanel(index)}
258
+ className={activePanel === index ? 'active' : ''}
259
+ data-testid={`tab-${panel.path}`}
260
+ >
261
+ {panel.name}
262
+ </button>
263
+ ))}
264
+ </div>
265
+ <div className="panel-content">
266
+ <ActiveComponent agentId="switch-test" />
267
+ </div>
268
+ </div>
269
+ );
270
+ };
271
+
272
+ cy.mount(<PanelSwitcher />);
273
+
274
+ // Check initial panel
275
+ cy.contains('Hello switch-test!').should('be.visible');
276
+
277
+ // Switch to second panel
278
+ cy.get('[data-testid="tab-second"]').click();
279
+ cy.contains('Second panel for switch-test').should('be.visible');
280
+ cy.contains('Hello switch-test!').should('not.exist');
281
+
282
+ // Switch back
283
+ cy.get('[data-testid="tab-example"]').click();
284
+ cy.contains('Hello switch-test!').should('be.visible');
285
+ });
286
+ });
287
+ });