@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.
- package/README.md +9 -16
- package/dist/assets/{index-CZAd5zm2.js → index-CmuPnu0u.js} +72 -89
- package/dist/assets/index-CmuPnu0u.js.br +0 -0
- package/dist/assets/index-CmuPnu0u.js.map +1 -0
- package/dist/assets/{index-CaEsCLCC.js → index-DDQnwxzL.js} +28798 -16391
- package/dist/assets/{index-CaEsCLCC.js.map → index-DDQnwxzL.js.map} +1 -1
- package/dist/assets/index-Df1AFSuJ.css +1 -0
- package/dist/assets/index-Df1AFSuJ.css.br +0 -0
- package/dist/assets/vendor-DSdxb8P-.js.map +1 -1
- package/dist/{chunk-REBZFQYE.js → chunk-7HYEGM5V.js} +967 -1597
- package/dist/{chunk-W3HS2NP6.js → chunk-B4KJXECB.js} +13 -18
- package/dist/{chunk-33BHGAF7.js → chunk-GWQB7PBK.js} +59 -32
- package/dist/{chunk-CVADLFW6.js → chunk-LQ6XHF53.js} +4543 -3043
- package/dist/{chunk-GYTAJJOD.js → chunk-RIAWNDYI.js} +16 -2
- package/dist/{chunk-IEKLJDUU.js → chunk-WS4DWCDZ.js} +54 -32
- package/dist/commands/agent/actions/index.d.ts +5 -1
- package/dist/commands/agent/actions/index.js +5 -4
- package/dist/commands/agent/index.js +3 -4
- package/dist/commands/create/actions/index.js +4 -5
- package/dist/commands/create/index.js +5 -6
- package/dist/{fileFromPath-DCRQMDLJ.js → fileFromPath-KB6XMTJ4.js} +1 -0
- package/dist/index.html +2 -2
- package/dist/index.js +9346 -102098
- package/dist/{migrator-KZLCVEIH.js → migrator-JREQPDN3.js} +42 -220
- package/dist/pglite.data +0 -0
- package/dist/pglite.wasm +0 -0
- package/dist/plugin-creator-T4K2673C.js +910 -0
- package/dist/{registry-XFOSZFU4.js → registry-CBMRMYCG.js} +3 -4
- package/dist/templates/plugin-starter/README.md +255 -0
- package/dist/templates/plugin-starter/bunfig.toml +6 -0
- package/dist/templates/plugin-starter/cypress.config.ts +18 -0
- package/dist/templates/plugin-starter/index.html +13 -0
- package/dist/templates/plugin-starter/package.json +95 -0
- package/dist/templates/plugin-starter/postcss.config.js +3 -0
- package/dist/templates/plugin-starter/scripts/test-e2e-manual.js +201 -0
- package/dist/templates/plugin-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +404 -0
- package/dist/templates/plugin-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +287 -0
- package/dist/templates/plugin-starter/src/__tests__/cypress/support/commands.ts +38 -0
- package/dist/templates/plugin-starter/src/__tests__/cypress/support/component-index.html +11 -0
- package/dist/templates/plugin-starter/src/__tests__/cypress/support/component.ts +33 -0
- package/dist/templates/plugin-starter/src/__tests__/cypress/support/e2e.ts +11 -0
- package/dist/templates/plugin-starter/src/__tests__/cypress/tsconfig.json +10 -0
- package/dist/templates/plugin-starter/src/__tests__/e2e/README.md +47 -0
- package/dist/templates/plugin-starter/src/__tests__/e2e/starter-plugin.ts +320 -0
- package/{templates/plugin-starter → dist/templates/plugin-starter/src}/__tests__/integration.test.ts +22 -17
- package/{templates/plugin-starter → dist/templates/plugin-starter/src}/__tests__/plugin.test.ts +8 -8
- package/{templates/plugin-starter → dist/templates/plugin-starter/src}/__tests__/test-utils.ts +17 -17
- package/dist/templates/plugin-starter/src/frontend/index.css +77 -0
- package/dist/templates/plugin-starter/src/frontend/index.tsx +164 -0
- package/dist/templates/plugin-starter/src/frontend/utils.ts +6 -0
- package/dist/templates/plugin-starter/src/index.ts +274 -0
- package/dist/templates/plugin-starter/src/tests.ts +6 -0
- package/dist/templates/plugin-starter/tailwind.config.js +62 -0
- package/dist/templates/plugin-starter/tsconfig.build.json +11 -0
- package/dist/templates/plugin-starter/tsconfig.json +28 -0
- package/dist/templates/plugin-starter/tsup.config.ts +20 -0
- package/dist/templates/plugin-starter/vite.config.ts +20 -0
- package/dist/templates/project-starter/.env.example +153 -0
- package/dist/templates/project-starter/README.md +109 -0
- package/dist/templates/project-starter/bunfig.toml +6 -0
- package/dist/templates/project-starter/cypress.config.ts +31 -0
- package/dist/templates/project-starter/index.html +13 -0
- package/dist/templates/project-starter/package.json +83 -0
- package/dist/templates/project-starter/postcss.config.js +3 -0
- package/dist/templates/project-starter/scripts/test-all.sh +101 -0
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/actions.test.ts +6 -6
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/character.test.ts +3 -3
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/config.test.ts +18 -18
- package/dist/templates/project-starter/src/__tests__/cypress/component/Accessibility.cy.tsx +271 -0
- package/dist/templates/project-starter/src/__tests__/cypress/component/ApiIntegration.cy.tsx +220 -0
- package/dist/templates/project-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +146 -0
- package/dist/templates/project-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +51 -0
- package/dist/templates/project-starter/src/__tests__/cypress/e2e/agent-chat.cy.ts +235 -0
- package/dist/templates/project-starter/src/__tests__/cypress/e2e/dashboard.cy.ts +146 -0
- package/dist/templates/project-starter/src/__tests__/cypress/e2e/user-workflow.cy.ts +257 -0
- package/dist/templates/project-starter/src/__tests__/cypress/support/commands.ts +44 -0
- package/dist/templates/project-starter/src/__tests__/cypress/support/component-index.html +11 -0
- package/dist/templates/project-starter/src/__tests__/cypress/support/component.ts +33 -0
- package/dist/templates/project-starter/src/__tests__/cypress/support/e2e.ts +179 -0
- package/dist/templates/project-starter/src/__tests__/e2e/index.ts +14 -0
- package/dist/templates/project-starter/src/__tests__/e2e/natural-language.test.ts +246 -0
- package/dist/templates/project-starter/src/__tests__/e2e/project.test.ts +155 -0
- package/dist/templates/project-starter/src/__tests__/e2e/starter-plugin.test.ts +421 -0
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/env.test.ts +2 -2
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/error-handling.test.ts +17 -17
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/events.test.ts +7 -7
- package/dist/templates/project-starter/src/__tests__/file-structure.test.ts +135 -0
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/integration.test.ts +25 -25
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/models.test.ts +6 -6
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/plugin.test.ts +9 -9
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/provider.test.ts +7 -7
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/routes.test.ts +3 -3
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/test-utils.ts +17 -17
- package/{templates/project-starter → dist/templates/project-starter/src}/__tests__/utils/core-test-utils.ts +3 -3
- package/dist/templates/project-starter/src/frontend/index.css +77 -0
- package/dist/templates/project-starter/src/frontend/index.html +19 -0
- package/dist/templates/project-starter/src/frontend/index.tsx +98 -0
- package/dist/templates/project-starter/src/frontend/utils.ts +6 -0
- package/dist/templates/project-starter/src/index.ts +153 -0
- package/dist/templates/project-starter/src/plugin.ts +255 -0
- package/dist/templates/project-starter/tailwind.config.js +62 -0
- package/dist/templates/project-starter/tsconfig.build.json +20 -0
- package/dist/templates/project-starter/tsconfig.json +39 -0
- package/dist/templates/project-starter/tsup.config.ts +19 -0
- package/dist/templates/project-starter/vite.config.ts +39 -0
- package/dist/templates/project-tee-starter/.dockerignore +20 -0
- package/dist/templates/project-tee-starter/.env.example +55 -0
- package/dist/templates/project-tee-starter/Dockerfile +66 -0
- package/dist/templates/project-tee-starter/GUIDE.md +235 -0
- package/dist/templates/project-tee-starter/README.md +173 -0
- package/dist/templates/project-tee-starter/__tests__/actions.test.ts +9 -0
- package/dist/templates/project-tee-starter/__tests__/character.test.ts +86 -0
- package/dist/templates/project-tee-starter/__tests__/config.test.ts +31 -0
- package/dist/templates/project-tee-starter/__tests__/env.test.ts +87 -0
- package/dist/templates/project-tee-starter/__tests__/error-handling.test.ts +30 -0
- package/dist/templates/project-tee-starter/__tests__/events.test.ts +21 -0
- package/{templates/project-starter → dist/templates/project-tee-starter}/__tests__/file-structure.test.ts +6 -6
- package/dist/templates/project-tee-starter/__tests__/integration.test.ts +205 -0
- package/dist/templates/project-tee-starter/__tests__/models.test.ts +22 -0
- package/dist/templates/project-tee-starter/__tests__/plugin.test.ts +38 -0
- package/dist/templates/project-tee-starter/__tests__/provider.test.ts +189 -0
- package/dist/templates/project-tee-starter/__tests__/routes.test.ts +21 -0
- package/dist/templates/project-tee-starter/__tests__/test-utils.ts +121 -0
- package/dist/templates/project-tee-starter/__tests__/utils/core-test-utils.ts +167 -0
- package/dist/templates/project-tee-starter/assets/mr-tee-portrait.jpg +0 -0
- package/dist/templates/project-tee-starter/bunfig.toml +6 -0
- package/dist/templates/project-tee-starter/docker-compose.yaml +57 -0
- package/dist/templates/project-tee-starter/e2e/project.test.ts +38 -0
- package/dist/templates/project-tee-starter/e2e/starter-plugin.test.ts +92 -0
- package/dist/templates/project-tee-starter/package.json +74 -0
- package/dist/templates/project-tee-starter/src/character.ts +257 -0
- package/dist/templates/project-tee-starter/src/index.ts +33 -0
- package/dist/templates/project-tee-starter/src/plugin.ts +169 -0
- package/dist/templates/project-tee-starter/tsconfig.build.json +13 -0
- package/dist/templates/project-tee-starter/tsconfig.json +30 -0
- package/dist/templates/project-tee-starter/tsup.config.ts +19 -0
- package/dist/{utils-DIZZ3HNZ.js → utils-TIALZU53.js} +9 -8
- package/package.json +29 -12
- package/templates/plugin-starter/README.md +38 -13
- package/templates/plugin-starter/bunfig.toml +6 -0
- package/templates/plugin-starter/cypress.config.ts +18 -0
- package/templates/plugin-starter/index.html +13 -0
- package/templates/plugin-starter/package.json +19 -7
- package/templates/plugin-starter/postcss.config.js +3 -0
- package/templates/plugin-starter/scripts/test-e2e-manual.js +201 -0
- package/templates/plugin-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +404 -0
- package/templates/plugin-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +287 -0
- package/templates/plugin-starter/src/__tests__/cypress/support/commands.ts +38 -0
- package/templates/plugin-starter/src/__tests__/cypress/support/component-index.html +11 -0
- package/templates/plugin-starter/src/__tests__/cypress/support/component.ts +33 -0
- package/templates/plugin-starter/src/__tests__/cypress/support/e2e.ts +11 -0
- package/templates/plugin-starter/src/__tests__/cypress/tsconfig.json +10 -0
- package/templates/plugin-starter/src/__tests__/e2e/README.md +47 -0
- package/templates/plugin-starter/src/__tests__/e2e/starter-plugin.ts +320 -0
- package/templates/plugin-starter/src/__tests__/integration.test.ts +138 -0
- package/templates/plugin-starter/src/__tests__/plugin.test.ts +182 -0
- package/templates/plugin-starter/src/__tests__/test-utils.ts +162 -0
- package/templates/plugin-starter/src/frontend/index.css +77 -0
- package/templates/plugin-starter/src/frontend/index.tsx +164 -0
- package/templates/plugin-starter/src/frontend/utils.ts +6 -0
- package/templates/plugin-starter/src/index.ts +31 -8
- package/templates/plugin-starter/src/tests.ts +6 -0
- package/templates/plugin-starter/tailwind.config.js +62 -0
- package/templates/plugin-starter/tsconfig.json +8 -8
- package/templates/plugin-starter/vite.config.ts +20 -0
- package/templates/project-starter/bunfig.toml +6 -0
- package/templates/project-starter/cypress.config.ts +31 -0
- package/templates/project-starter/index.html +13 -0
- package/templates/project-starter/package.json +37 -14
- package/templates/project-starter/postcss.config.js +3 -0
- package/templates/project-starter/scripts/test-all.sh +101 -0
- package/templates/project-starter/src/__tests__/actions.test.ts +155 -0
- package/templates/project-starter/src/__tests__/character.test.ts +86 -0
- package/templates/project-starter/src/__tests__/config.test.ts +193 -0
- package/templates/project-starter/src/__tests__/cypress/component/Accessibility.cy.tsx +271 -0
- package/templates/project-starter/src/__tests__/cypress/component/ApiIntegration.cy.tsx +220 -0
- package/templates/project-starter/src/__tests__/cypress/component/ExampleRoute.cy.tsx +146 -0
- package/templates/project-starter/src/__tests__/cypress/component/PanelComponent.cy.tsx +51 -0
- package/templates/project-starter/src/__tests__/cypress/e2e/agent-chat.cy.ts +235 -0
- package/templates/project-starter/src/__tests__/cypress/e2e/dashboard.cy.ts +146 -0
- package/templates/project-starter/src/__tests__/cypress/e2e/user-workflow.cy.ts +257 -0
- package/templates/project-starter/src/__tests__/cypress/support/commands.ts +44 -0
- package/templates/project-starter/src/__tests__/cypress/support/component-index.html +11 -0
- package/templates/project-starter/src/__tests__/cypress/support/component.ts +33 -0
- package/templates/project-starter/src/__tests__/cypress/support/e2e.ts +179 -0
- package/templates/project-starter/src/__tests__/e2e/index.ts +14 -0
- package/templates/project-starter/src/__tests__/e2e/natural-language.test.ts +246 -0
- package/templates/project-starter/src/__tests__/e2e/project.test.ts +155 -0
- package/templates/project-starter/src/__tests__/e2e/starter-plugin.test.ts +421 -0
- package/templates/project-starter/src/__tests__/env.test.ts +87 -0
- package/templates/project-starter/src/__tests__/error-handling.test.ts +177 -0
- package/templates/project-starter/src/__tests__/events.test.ts +144 -0
- package/templates/project-starter/src/__tests__/file-structure.test.ts +135 -0
- package/templates/project-starter/src/__tests__/integration.test.ts +209 -0
- package/templates/project-starter/src/__tests__/models.test.ts +152 -0
- package/templates/project-starter/src/__tests__/plugin.test.ts +393 -0
- package/templates/project-starter/src/__tests__/provider.test.ts +325 -0
- package/templates/project-starter/src/__tests__/routes.test.ts +79 -0
- package/templates/project-starter/src/__tests__/test-utils.ts +121 -0
- package/templates/project-starter/src/__tests__/utils/core-test-utils.ts +180 -0
- package/templates/project-starter/src/frontend/index.css +77 -0
- package/templates/project-starter/src/frontend/index.html +19 -0
- package/templates/project-starter/src/frontend/index.tsx +98 -0
- package/templates/project-starter/src/frontend/utils.ts +6 -0
- package/templates/project-starter/src/index.ts +9 -1
- package/templates/project-starter/tailwind.config.js +62 -0
- package/templates/project-starter/tsconfig.build.json +9 -2
- package/templates/project-starter/tsconfig.json +15 -6
- package/templates/project-starter/tsup.config.ts +1 -1
- package/templates/project-starter/vite.config.ts +39 -0
- package/templates/project-tee-starter/__tests__/actions.test.ts +1 -1
- package/templates/project-tee-starter/__tests__/character.test.ts +1 -1
- package/templates/project-tee-starter/__tests__/config.test.ts +1 -1
- package/templates/project-tee-starter/__tests__/env.test.ts +2 -2
- package/templates/project-tee-starter/__tests__/error-handling.test.ts +1 -1
- package/templates/project-tee-starter/__tests__/events.test.ts +1 -1
- package/templates/project-tee-starter/__tests__/file-structure.test.ts +5 -5
- package/templates/project-tee-starter/__tests__/integration.test.ts +22 -26
- package/templates/project-tee-starter/__tests__/models.test.ts +1 -1
- package/templates/project-tee-starter/__tests__/plugin.test.ts +6 -12
- package/templates/project-tee-starter/__tests__/provider.test.ts +6 -6
- package/templates/project-tee-starter/__tests__/routes.test.ts +1 -1
- package/templates/project-tee-starter/__tests__/test-utils.ts +15 -15
- package/templates/project-tee-starter/__tests__/utils/core-test-utils.ts +3 -3
- package/templates/project-tee-starter/bunfig.toml +6 -0
- package/templates/project-tee-starter/package.json +10 -12
- package/dist/assets/index-CZAd5zm2.js.br +0 -0
- package/dist/assets/index-CZAd5zm2.js.map +0 -1
- package/dist/assets/index-DyA-lndn.css +0 -1
- package/dist/assets/index-DyA-lndn.css.br +0 -0
- package/dist/chunk-CEE6RKN5.js +0 -2746
- package/dist/chunk-MA2ZXPG6.js +0 -260
- package/dist/chunk-TUAYJIF2.js +0 -3649
- package/dist/lib-NAGYZHVV.js +0 -9
- package/dist/plugin-creator-IC42XOHG.js +0 -29165
- package/templates/plugin-starter/e2e/starter-plugin.test.ts +0 -171
- package/templates/plugin-starter/images/README.md +0 -24
- package/templates/plugin-starter/vitest.config.ts +0 -16
- package/templates/project-starter/e2e/project.test.ts +0 -34
- package/templates/project-starter/e2e/starter-plugin.test.ts +0 -217
- package/templates/project-starter/vitest.config.ts +0 -16
- package/templates/project-tee-starter/vitest.config.ts +0 -19
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import '../../../frontend/index.css';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Example accessible form component
|
|
6
|
+
*/
|
|
7
|
+
const AccessibleForm: React.FC<{ onSubmit: (data: any) => void }> = ({ onSubmit }) => {
|
|
8
|
+
const [formData, setFormData] = React.useState({
|
|
9
|
+
name: '',
|
|
10
|
+
email: '',
|
|
11
|
+
message: '',
|
|
12
|
+
});
|
|
13
|
+
const [errors, setErrors] = React.useState<Record<string, string>>({});
|
|
14
|
+
|
|
15
|
+
const handleSubmit = (e: React.FormEvent) => {
|
|
16
|
+
e.preventDefault();
|
|
17
|
+
const newErrors: Record<string, string> = {};
|
|
18
|
+
|
|
19
|
+
if (!formData.name) newErrors.name = 'Name is required';
|
|
20
|
+
if (!formData.email) newErrors.email = 'Email is required';
|
|
21
|
+
if (formData.email && !formData.email.includes('@')) {
|
|
22
|
+
newErrors.email = 'Please enter a valid email';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (Object.keys(newErrors).length > 0) {
|
|
26
|
+
setErrors(newErrors);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
onSubmit(formData);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<form onSubmit={handleSubmit} className="space-y-4 p-4">
|
|
35
|
+
<h1 className="text-2xl font-bold">Contact Agent</h1>
|
|
36
|
+
|
|
37
|
+
<div>
|
|
38
|
+
<label htmlFor="name" className="block text-sm font-medium mb-1">
|
|
39
|
+
Name{' '}
|
|
40
|
+
<span className="text-red-500" aria-label="required">
|
|
41
|
+
*
|
|
42
|
+
</span>
|
|
43
|
+
</label>
|
|
44
|
+
<input
|
|
45
|
+
id="name"
|
|
46
|
+
type="text"
|
|
47
|
+
value={formData.name}
|
|
48
|
+
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
|
|
49
|
+
aria-invalid={!!errors.name}
|
|
50
|
+
aria-describedby={errors.name ? 'name-error' : undefined}
|
|
51
|
+
className="w-full px-3 py-2 border rounded-md"
|
|
52
|
+
/>
|
|
53
|
+
{errors.name && (
|
|
54
|
+
<p id="name-error" role="alert" className="text-red-500 text-sm mt-1">
|
|
55
|
+
{errors.name}
|
|
56
|
+
</p>
|
|
57
|
+
)}
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<div>
|
|
61
|
+
<label htmlFor="email" className="block text-sm font-medium mb-1">
|
|
62
|
+
Email{' '}
|
|
63
|
+
<span className="text-red-500" aria-label="required">
|
|
64
|
+
*
|
|
65
|
+
</span>
|
|
66
|
+
</label>
|
|
67
|
+
<input
|
|
68
|
+
id="email"
|
|
69
|
+
type="email"
|
|
70
|
+
value={formData.email}
|
|
71
|
+
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
|
72
|
+
aria-invalid={!!errors.email}
|
|
73
|
+
aria-describedby={errors.email ? 'email-error' : undefined}
|
|
74
|
+
className="w-full px-3 py-2 border rounded-md"
|
|
75
|
+
/>
|
|
76
|
+
{errors.email && (
|
|
77
|
+
<p id="email-error" role="alert" className="text-red-500 text-sm mt-1">
|
|
78
|
+
{errors.email}
|
|
79
|
+
</p>
|
|
80
|
+
)}
|
|
81
|
+
</div>
|
|
82
|
+
|
|
83
|
+
<div>
|
|
84
|
+
<label htmlFor="message" className="block text-sm font-medium mb-1">
|
|
85
|
+
Message
|
|
86
|
+
</label>
|
|
87
|
+
<textarea
|
|
88
|
+
id="message"
|
|
89
|
+
value={formData.message}
|
|
90
|
+
onChange={(e) => setFormData({ ...formData, message: e.target.value })}
|
|
91
|
+
rows={4}
|
|
92
|
+
className="w-full px-3 py-2 border rounded-md"
|
|
93
|
+
/>
|
|
94
|
+
</div>
|
|
95
|
+
|
|
96
|
+
<button
|
|
97
|
+
type="submit"
|
|
98
|
+
className="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
|
99
|
+
>
|
|
100
|
+
Send Message
|
|
101
|
+
</button>
|
|
102
|
+
</form>
|
|
103
|
+
);
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
describe('Accessibility Tests', () => {
|
|
107
|
+
describe('Form Accessibility', () => {
|
|
108
|
+
it('should have proper labels for all form fields', () => {
|
|
109
|
+
cy.mount(<AccessibleForm onSubmit={cy.stub()} />);
|
|
110
|
+
|
|
111
|
+
// Check that labels are properly associated
|
|
112
|
+
cy.get('label[for="name"]').should('exist');
|
|
113
|
+
cy.get('label[for="email"]').should('exist');
|
|
114
|
+
cy.get('label[for="message"]').should('exist');
|
|
115
|
+
|
|
116
|
+
// Check that inputs have matching IDs
|
|
117
|
+
cy.get('input#name').should('exist');
|
|
118
|
+
cy.get('input#email').should('exist');
|
|
119
|
+
cy.get('textarea#message').should('exist');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it('should indicate required fields', () => {
|
|
123
|
+
cy.mount(<AccessibleForm onSubmit={cy.stub()} />);
|
|
124
|
+
|
|
125
|
+
// Check for required field indicators
|
|
126
|
+
cy.get('label[for="name"]').within(() => {
|
|
127
|
+
cy.get('[aria-label="required"]').should('exist');
|
|
128
|
+
});
|
|
129
|
+
cy.get('label[for="email"]').within(() => {
|
|
130
|
+
cy.get('[aria-label="required"]').should('exist');
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it('should show accessible error messages', () => {
|
|
135
|
+
cy.mount(<AccessibleForm onSubmit={cy.stub()} />);
|
|
136
|
+
|
|
137
|
+
// Submit empty form
|
|
138
|
+
cy.get('button[type="submit"]').click();
|
|
139
|
+
|
|
140
|
+
// Check error messages have proper ARIA attributes
|
|
141
|
+
cy.get('#name-error').should('have.attr', 'role', 'alert');
|
|
142
|
+
cy.get('#email-error').should('have.attr', 'role', 'alert');
|
|
143
|
+
|
|
144
|
+
// Check inputs are marked as invalid
|
|
145
|
+
cy.get('input#name').should('have.attr', 'aria-invalid', 'true');
|
|
146
|
+
cy.get('input#email').should('have.attr', 'aria-invalid', 'true');
|
|
147
|
+
|
|
148
|
+
// Check aria-describedby links errors to inputs
|
|
149
|
+
cy.get('input#name').should('have.attr', 'aria-describedby', 'name-error');
|
|
150
|
+
cy.get('input#email').should('have.attr', 'aria-describedby', 'email-error');
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('should be keyboard navigable', () => {
|
|
154
|
+
cy.mount(<AccessibleForm onSubmit={cy.stub()} />);
|
|
155
|
+
|
|
156
|
+
// Verify all form elements can receive focus
|
|
157
|
+
cy.get('input#name').focus();
|
|
158
|
+
cy.focused().should('have.attr', 'id', 'name');
|
|
159
|
+
|
|
160
|
+
cy.get('input#email').focus();
|
|
161
|
+
cy.focused().should('have.attr', 'id', 'email');
|
|
162
|
+
|
|
163
|
+
cy.get('textarea#message').focus();
|
|
164
|
+
cy.focused().should('have.attr', 'id', 'message');
|
|
165
|
+
|
|
166
|
+
cy.get('button[type="submit"]').focus();
|
|
167
|
+
cy.focused().should('contain', 'Send Message');
|
|
168
|
+
|
|
169
|
+
// Verify tabindex is not preventing keyboard access
|
|
170
|
+
cy.get('input, textarea, button').should('not.have.attr', 'tabindex', '-1');
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('should have proper focus indicators', () => {
|
|
174
|
+
cy.mount(<AccessibleForm onSubmit={cy.stub()} />);
|
|
175
|
+
|
|
176
|
+
// Check focus ring on button
|
|
177
|
+
cy.get('button[type="submit"]').focus();
|
|
178
|
+
cy.get('button[type="submit"]').should('have.class', 'focus:ring-2');
|
|
179
|
+
});
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
describe('Color Contrast', () => {
|
|
183
|
+
it('should maintain readable contrast in dark mode', () => {
|
|
184
|
+
cy.mount(
|
|
185
|
+
<div className="dark bg-gray-900 p-4">
|
|
186
|
+
<h1 className="text-white">High Contrast Title</h1>
|
|
187
|
+
<p className="text-gray-300">Body text with good contrast</p>
|
|
188
|
+
<button className="bg-blue-600 text-white px-4 py-2">Action Button</button>
|
|
189
|
+
</div>
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
// Visual check - in real tests you might use cypress-axe
|
|
193
|
+
cy.get('h1').should('have.class', 'text-white');
|
|
194
|
+
cy.get('p').should('have.class', 'text-gray-300');
|
|
195
|
+
});
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
describe('Screen Reader Support', () => {
|
|
199
|
+
it('should have proper heading hierarchy', () => {
|
|
200
|
+
cy.mount(
|
|
201
|
+
<article>
|
|
202
|
+
<h1>Main Title</h1>
|
|
203
|
+
<section>
|
|
204
|
+
<h2>Section Title</h2>
|
|
205
|
+
<p>Content</p>
|
|
206
|
+
<h3>Subsection</h3>
|
|
207
|
+
<p>More content</p>
|
|
208
|
+
</section>
|
|
209
|
+
</article>
|
|
210
|
+
);
|
|
211
|
+
|
|
212
|
+
// Check heading hierarchy
|
|
213
|
+
cy.get('h1').should('have.length', 1);
|
|
214
|
+
cy.get('h2').should('exist');
|
|
215
|
+
cy.get('h3').should('exist');
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it('should use semantic HTML elements', () => {
|
|
219
|
+
cy.mount(
|
|
220
|
+
<nav aria-label="Main navigation">
|
|
221
|
+
<ul>
|
|
222
|
+
<li>
|
|
223
|
+
<a href="#home">Home</a>
|
|
224
|
+
</li>
|
|
225
|
+
<li>
|
|
226
|
+
<a href="#about">About</a>
|
|
227
|
+
</li>
|
|
228
|
+
</ul>
|
|
229
|
+
</nav>
|
|
230
|
+
);
|
|
231
|
+
|
|
232
|
+
cy.get('nav').should('have.attr', 'aria-label', 'Main navigation');
|
|
233
|
+
cy.get('nav ul').should('exist');
|
|
234
|
+
cy.get('nav a').should('have.length', 2);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* ACCESSIBILITY TESTING PATTERNS
|
|
241
|
+
*
|
|
242
|
+
* 1. ARIA ATTRIBUTES
|
|
243
|
+
* - Test aria-label, aria-describedby, aria-invalid
|
|
244
|
+
* - Verify role attributes for dynamic content
|
|
245
|
+
* - Check live regions for updates
|
|
246
|
+
*
|
|
247
|
+
* 2. KEYBOARD NAVIGATION
|
|
248
|
+
* - Test tab order
|
|
249
|
+
* - Verify all interactive elements are reachable
|
|
250
|
+
* - Check focus indicators
|
|
251
|
+
*
|
|
252
|
+
* 3. FORM ACCESSIBILITY
|
|
253
|
+
* - Labels properly associated with inputs
|
|
254
|
+
* - Error messages linked to fields
|
|
255
|
+
* - Required fields indicated
|
|
256
|
+
*
|
|
257
|
+
* 4. COLOR CONTRAST
|
|
258
|
+
* - Test in both light and dark modes
|
|
259
|
+
* - Ensure text is readable
|
|
260
|
+
* - Check focus indicators visibility
|
|
261
|
+
*
|
|
262
|
+
* 5. SCREEN READER SUPPORT
|
|
263
|
+
* - Proper heading hierarchy
|
|
264
|
+
* - Semantic HTML usage
|
|
265
|
+
* - Alternative text for images
|
|
266
|
+
*
|
|
267
|
+
* TOOLS TO CONSIDER:
|
|
268
|
+
* - cypress-axe: Automated accessibility testing
|
|
269
|
+
* - cypress-tab: Better keyboard navigation testing
|
|
270
|
+
* - cypress-real-events: Test with real browser events
|
|
271
|
+
*/
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import '../../../frontend/index.css';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Example component that fetches data from an API using React state
|
|
6
|
+
*/
|
|
7
|
+
const DataFetchingComponent: React.FC<{ agentId: string }> = ({ agentId }) => {
|
|
8
|
+
const [data, setData] = React.useState<any>(null);
|
|
9
|
+
const [isLoading, setIsLoading] = React.useState(true);
|
|
10
|
+
const [error, setError] = React.useState<Error | null>(null);
|
|
11
|
+
|
|
12
|
+
React.useEffect(() => {
|
|
13
|
+
const fetchData = async () => {
|
|
14
|
+
try {
|
|
15
|
+
setIsLoading(true);
|
|
16
|
+
setError(null);
|
|
17
|
+
const response = await fetch(`/api/agent/${agentId}/data`);
|
|
18
|
+
if (!response.ok) {
|
|
19
|
+
throw new Error('Failed to fetch data');
|
|
20
|
+
}
|
|
21
|
+
const result = await response.json();
|
|
22
|
+
setData(result);
|
|
23
|
+
} catch (err) {
|
|
24
|
+
setError(err as Error);
|
|
25
|
+
} finally {
|
|
26
|
+
setIsLoading(false);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
fetchData();
|
|
31
|
+
}, [agentId]);
|
|
32
|
+
|
|
33
|
+
if (isLoading) return <div data-testid="loading">Loading agent data...</div>;
|
|
34
|
+
if (error)
|
|
35
|
+
return (
|
|
36
|
+
<div data-testid="error" className="text-red-500">
|
|
37
|
+
Error: {error.message}
|
|
38
|
+
</div>
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<div data-testid="data-display">
|
|
43
|
+
<h2>Agent: {agentId}</h2>
|
|
44
|
+
<ul>{data?.items?.map((item: string, index: number) => <li key={index}>{item}</li>)}</ul>
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
describe('API Integration Tests', () => {
|
|
50
|
+
describe('Data Fetching', () => {
|
|
51
|
+
it('should display loading state initially', () => {
|
|
52
|
+
cy.intercept('GET', '/api/agent/*/data', {
|
|
53
|
+
delay: 1000,
|
|
54
|
+
body: { items: [] },
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
cy.mount(<DataFetchingComponent agentId="test-123" />);
|
|
58
|
+
cy.get('[data-testid="loading"]').should('be.visible');
|
|
59
|
+
cy.get('[data-testid="loading"]').should('contain', 'Loading agent data...');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('should fetch and display data successfully', () => {
|
|
63
|
+
const mockData = {
|
|
64
|
+
items: ['Action 1', 'Action 2', 'Action 3'],
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
cy.intercept('GET', '/api/agent/test-123/data', {
|
|
68
|
+
statusCode: 200,
|
|
69
|
+
body: mockData,
|
|
70
|
+
}).as('getAgentData');
|
|
71
|
+
|
|
72
|
+
cy.mount(<DataFetchingComponent agentId="test-123" />);
|
|
73
|
+
|
|
74
|
+
// Wait for the API call
|
|
75
|
+
cy.wait('@getAgentData');
|
|
76
|
+
|
|
77
|
+
// Check data is displayed
|
|
78
|
+
cy.get('[data-testid="data-display"]').should('be.visible');
|
|
79
|
+
cy.contains('Agent: test-123').should('be.visible');
|
|
80
|
+
cy.contains('Action 1').should('be.visible');
|
|
81
|
+
cy.contains('Action 2').should('be.visible');
|
|
82
|
+
cy.contains('Action 3').should('be.visible');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should handle API errors gracefully', () => {
|
|
86
|
+
cy.intercept('GET', '/api/agent/test-123/data', {
|
|
87
|
+
statusCode: 500,
|
|
88
|
+
body: { error: 'Internal Server Error' },
|
|
89
|
+
}).as('getAgentDataError');
|
|
90
|
+
|
|
91
|
+
cy.mount(<DataFetchingComponent agentId="test-123" />);
|
|
92
|
+
|
|
93
|
+
// Wait for the failed API call
|
|
94
|
+
cy.wait('@getAgentDataError');
|
|
95
|
+
|
|
96
|
+
// Check error is displayed
|
|
97
|
+
cy.get('[data-testid="error"]').should('be.visible');
|
|
98
|
+
cy.get('[data-testid="error"]').should('contain', 'Failed to fetch data');
|
|
99
|
+
cy.get('[data-testid="error"]').should('have.class', 'text-red-500');
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it('should handle network errors', () => {
|
|
103
|
+
cy.intercept('GET', '/api/agent/test-123/data', {
|
|
104
|
+
forceNetworkError: true,
|
|
105
|
+
}).as('networkError');
|
|
106
|
+
|
|
107
|
+
cy.mount(<DataFetchingComponent agentId="test-123" />);
|
|
108
|
+
|
|
109
|
+
// Network errors might not trigger the wait, so we check for error directly
|
|
110
|
+
cy.get('[data-testid="error"]', { timeout: 10000 }).should('be.visible');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('should refetch data when agent ID changes', () => {
|
|
114
|
+
const firstMockData = { items: ['First Agent Action'] };
|
|
115
|
+
const secondMockData = { items: ['Second Agent Action'] };
|
|
116
|
+
|
|
117
|
+
cy.intercept('GET', '/api/agent/agent-1/data', {
|
|
118
|
+
body: firstMockData,
|
|
119
|
+
}).as('getFirstAgent');
|
|
120
|
+
|
|
121
|
+
cy.intercept('GET', '/api/agent/agent-2/data', {
|
|
122
|
+
body: secondMockData,
|
|
123
|
+
}).as('getSecondAgent');
|
|
124
|
+
|
|
125
|
+
// Create a component that can change agent ID
|
|
126
|
+
const TestWrapper = () => {
|
|
127
|
+
const [agentId, setAgentId] = React.useState('agent-1');
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<>
|
|
131
|
+
<button onClick={() => setAgentId('agent-2')} data-testid="change-agent">
|
|
132
|
+
Change Agent
|
|
133
|
+
</button>
|
|
134
|
+
<DataFetchingComponent agentId={agentId} />
|
|
135
|
+
</>
|
|
136
|
+
);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
cy.mount(<TestWrapper />);
|
|
140
|
+
cy.wait('@getFirstAgent');
|
|
141
|
+
cy.contains('First Agent Action').should('be.visible');
|
|
142
|
+
|
|
143
|
+
// Click to change agent
|
|
144
|
+
cy.get('[data-testid="change-agent"]').click();
|
|
145
|
+
cy.wait('@getSecondAgent');
|
|
146
|
+
cy.contains('Second Agent Action').should('be.visible');
|
|
147
|
+
cy.contains('First Agent Action').should('not.exist');
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('Request Validation', () => {
|
|
152
|
+
it('should send correct headers', () => {
|
|
153
|
+
cy.intercept('GET', '/api/agent/*/data', (req) => {
|
|
154
|
+
expect(req.headers).to.have.property('accept');
|
|
155
|
+
req.reply({ items: [] });
|
|
156
|
+
}).as('checkHeaders');
|
|
157
|
+
|
|
158
|
+
cy.mount(<DataFetchingComponent agentId="test-123" />);
|
|
159
|
+
cy.wait('@checkHeaders');
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it('should handle different response formats', () => {
|
|
163
|
+
// Test empty response
|
|
164
|
+
cy.intercept('GET', '/api/agent/empty/data', {
|
|
165
|
+
body: {},
|
|
166
|
+
}).as('emptyResponse');
|
|
167
|
+
cy.mount(<DataFetchingComponent agentId="empty" />);
|
|
168
|
+
cy.wait('@emptyResponse');
|
|
169
|
+
cy.get('[data-testid="data-display"]').should('be.visible');
|
|
170
|
+
|
|
171
|
+
// Test null items
|
|
172
|
+
cy.intercept('GET', '/api/agent/null/data', {
|
|
173
|
+
body: { items: null },
|
|
174
|
+
}).as('nullResponse');
|
|
175
|
+
// Create a new mount point for the second test
|
|
176
|
+
cy.then(() => {
|
|
177
|
+
cy.mount(<DataFetchingComponent agentId="null" />);
|
|
178
|
+
cy.wait('@nullResponse');
|
|
179
|
+
cy.get('[data-testid="data-display"]').should('be.visible');
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* API TESTING PATTERNS IN CYPRESS
|
|
187
|
+
*
|
|
188
|
+
* 1. INTERCEPTING REQUESTS
|
|
189
|
+
* cy.intercept() allows you to:
|
|
190
|
+
* - Mock responses
|
|
191
|
+
* - Delay responses
|
|
192
|
+
* - Force errors
|
|
193
|
+
* - Validate request data
|
|
194
|
+
*
|
|
195
|
+
* 2. WAITING FOR REQUESTS
|
|
196
|
+
* Use aliases with .as() and cy.wait() to ensure
|
|
197
|
+
* requests complete before making assertions
|
|
198
|
+
*
|
|
199
|
+
* 3. ERROR SCENARIOS
|
|
200
|
+
* Test all error cases:
|
|
201
|
+
* - Server errors (4xx, 5xx)
|
|
202
|
+
* - Network failures
|
|
203
|
+
* - Timeout scenarios
|
|
204
|
+
* - Invalid responses
|
|
205
|
+
*
|
|
206
|
+
* 4. LOADING STATES
|
|
207
|
+
* Always test loading indicators
|
|
208
|
+
* Use delays to ensure they appear
|
|
209
|
+
*
|
|
210
|
+
* 5. DATA UPDATES
|
|
211
|
+
* Test how components handle:
|
|
212
|
+
* - Prop changes
|
|
213
|
+
* - Refetching
|
|
214
|
+
* - Cache invalidation
|
|
215
|
+
*
|
|
216
|
+
* NOTE: This example uses plain React state instead of React Query
|
|
217
|
+
* to avoid dependency optimization issues in the test environment.
|
|
218
|
+
* In production, you would typically use React Query or similar
|
|
219
|
+
* libraries for better caching and request management.
|
|
220
|
+
*/
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
3
|
+
import '../../../frontend/index.css';
|
|
4
|
+
|
|
5
|
+
// We need to import the component directly since it's not exported
|
|
6
|
+
// In a real scenario, you'd export the component from index.tsx
|
|
7
|
+
const ExampleRoute = () => {
|
|
8
|
+
const [config, setConfig] = React.useState(window.ELIZA_CONFIG);
|
|
9
|
+
|
|
10
|
+
React.useEffect(() => {
|
|
11
|
+
document.documentElement.classList.add('dark');
|
|
12
|
+
}, []);
|
|
13
|
+
|
|
14
|
+
if (!config?.agentId) {
|
|
15
|
+
return (
|
|
16
|
+
<div className="p-4 text-center">
|
|
17
|
+
<div className="text-red-600 font-medium">Error: Agent ID not found</div>
|
|
18
|
+
<div className="text-sm text-gray-600 mt-2">
|
|
19
|
+
The server should inject the agent ID configuration.
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<QueryClientProvider client={new QueryClient()}>
|
|
27
|
+
<div>Hello {config.agentId}</div>
|
|
28
|
+
</QueryClientProvider>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
describe('ExampleRoute Component Tests', () => {
|
|
33
|
+
describe('Component Rendering', () => {
|
|
34
|
+
it('should apply dark mode on mount', () => {
|
|
35
|
+
cy.mount(<ExampleRoute />);
|
|
36
|
+
cy.shouldBeDarkMode();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should show error when agent ID is missing', () => {
|
|
40
|
+
// Clear the config before mounting
|
|
41
|
+
cy.window().then((win) => {
|
|
42
|
+
win.ELIZA_CONFIG = undefined;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
cy.mount(<ExampleRoute />);
|
|
46
|
+
|
|
47
|
+
// Check error message is displayed
|
|
48
|
+
cy.contains('Error: Agent ID not found').should('be.visible');
|
|
49
|
+
cy.contains('The server should inject the agent ID configuration.').should('be.visible');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should render correctly with agent ID', () => {
|
|
53
|
+
const testAgentId = '12345678-1234-1234-1234-123456789abc';
|
|
54
|
+
|
|
55
|
+
// Set config before mounting
|
|
56
|
+
cy.window().then((win) => {
|
|
57
|
+
win.ELIZA_CONFIG = {
|
|
58
|
+
agentId: testAgentId,
|
|
59
|
+
apiBase: 'http://localhost:3000',
|
|
60
|
+
};
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
cy.mount(<ExampleRoute />);
|
|
64
|
+
|
|
65
|
+
// Check that the agent ID is displayed
|
|
66
|
+
cy.contains(`Hello ${testAgentId}`).should('be.visible');
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
describe('Configuration Handling', () => {
|
|
71
|
+
it('should handle ELIZA_CONFIG changes', () => {
|
|
72
|
+
const initialAgentId = 'initial-agent-id';
|
|
73
|
+
const updatedAgentId = 'updated-agent-id';
|
|
74
|
+
|
|
75
|
+
// Set initial config
|
|
76
|
+
cy.window().then((win) => {
|
|
77
|
+
win.ELIZA_CONFIG = {
|
|
78
|
+
agentId: initialAgentId,
|
|
79
|
+
apiBase: 'http://localhost:3000',
|
|
80
|
+
};
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
cy.mount(<ExampleRoute />);
|
|
84
|
+
cy.contains(`Hello ${initialAgentId}`).should('be.visible');
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* TESTING PATTERNS FOR FRONTEND COMPONENTS IN ELIZAOS
|
|
91
|
+
*
|
|
92
|
+
* 1. COMPONENT ISOLATION
|
|
93
|
+
* - Test components in isolation using cy.mount()
|
|
94
|
+
* - Mock external dependencies (like API calls)
|
|
95
|
+
* - Use data-testid attributes for reliable element selection
|
|
96
|
+
*
|
|
97
|
+
* 2. CONFIGURATION TESTING
|
|
98
|
+
* - Always test with and without ELIZA_CONFIG
|
|
99
|
+
* - Test with invalid/malformed configurations
|
|
100
|
+
* - Verify error states and fallbacks
|
|
101
|
+
*
|
|
102
|
+
* 3. DARK MODE SUPPORT
|
|
103
|
+
* - Ensure components work in both light and dark modes
|
|
104
|
+
* - Use the custom shouldBeDarkMode() command
|
|
105
|
+
*
|
|
106
|
+
* 4. QUERY CLIENT TESTING
|
|
107
|
+
* - Mock API responses for react-query
|
|
108
|
+
* - Test loading, error, and success states
|
|
109
|
+
* - Verify cache behavior
|
|
110
|
+
*
|
|
111
|
+
* 5. ACCESSIBILITY
|
|
112
|
+
* - Use Testing Library queries (findByRole, findByText)
|
|
113
|
+
* - Test keyboard navigation
|
|
114
|
+
* - Verify ARIA attributes
|
|
115
|
+
*
|
|
116
|
+
* EXAMPLE TEST STRUCTURE:
|
|
117
|
+
*
|
|
118
|
+
* describe('Component Name', () => {
|
|
119
|
+
* beforeEach(() => {
|
|
120
|
+
* // Set up common test data
|
|
121
|
+
* cy.setElizaConfig({ agentId: 'test-id', apiBase: 'http://localhost:3000' });
|
|
122
|
+
* });
|
|
123
|
+
*
|
|
124
|
+
* describe('Rendering', () => {
|
|
125
|
+
* it('should render correctly', () => {
|
|
126
|
+
* cy.mount(<Component />);
|
|
127
|
+
* // Assertions
|
|
128
|
+
* });
|
|
129
|
+
* });
|
|
130
|
+
*
|
|
131
|
+
* describe('User Interactions', () => {
|
|
132
|
+
* it('should handle click events', () => {
|
|
133
|
+
* cy.mount(<Component />);
|
|
134
|
+
* cy.findByRole('button').click();
|
|
135
|
+
* // Assertions
|
|
136
|
+
* });
|
|
137
|
+
* });
|
|
138
|
+
*
|
|
139
|
+
* describe('API Integration', () => {
|
|
140
|
+
* it('should fetch and display data', () => {
|
|
141
|
+
* cy.intercept('GET', '/api/data', { fixture: 'mockData.json' });
|
|
142
|
+
* cy.mount(<Component />);
|
|
143
|
+
* // Assertions
|
|
144
|
+
* });
|
|
145
|
+
* });
|
|
146
|
+
* }); */
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { panels } from '../../../frontend/index';
|
|
3
|
+
|
|
4
|
+
describe('PanelComponent Tests', () => {
|
|
5
|
+
// Get the Panel component from the exported panels
|
|
6
|
+
const PanelComponent = panels[0]?.component;
|
|
7
|
+
|
|
8
|
+
describe('Panel Registration', () => {
|
|
9
|
+
it('should export panels array with correct structure', () => {
|
|
10
|
+
expect(panels).to.be.an('array');
|
|
11
|
+
expect(panels).to.have.length.greaterThan(0);
|
|
12
|
+
|
|
13
|
+
const panel = panels[0];
|
|
14
|
+
expect(panel).to.have.property('name', 'Example');
|
|
15
|
+
expect(panel).to.have.property('path', 'example');
|
|
16
|
+
expect(panel).to.have.property('component');
|
|
17
|
+
expect(panel).to.have.property('icon', 'Book');
|
|
18
|
+
expect(panel).to.have.property('public', false);
|
|
19
|
+
expect(panel).to.have.property('shortLabel', 'Example');
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe('Component Rendering', () => {
|
|
24
|
+
it('should render with agent ID', () => {
|
|
25
|
+
const testAgentId = 'test-agent-12345';
|
|
26
|
+
|
|
27
|
+
if (!PanelComponent) {
|
|
28
|
+
throw new Error('PanelComponent not found in panels export');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
cy.mount(<PanelComponent agentId={testAgentId} />);
|
|
32
|
+
|
|
33
|
+
// Note: The component has a typo "Helllo" instead of "Hello"
|
|
34
|
+
cy.contains(`Helllo ${testAgentId}!`).should('be.visible');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should handle different agent IDs', () => {
|
|
38
|
+
const agentIds = ['agent-1', 'agent-2', '12345678-1234-1234-1234-123456789abc', 'test-agent'];
|
|
39
|
+
|
|
40
|
+
agentIds.forEach((agentId) => {
|
|
41
|
+
cy.mount(<PanelComponent agentId={agentId} />);
|
|
42
|
+
cy.contains(`Helllo ${agentId}!`).should('be.visible');
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should render without crashing with empty agent ID', () => {
|
|
47
|
+
cy.mount(<PanelComponent agentId="" />);
|
|
48
|
+
cy.contains('Helllo !').should('be.visible');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
});
|