@elizaos/cli 1.3.2 → 1.4.2

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 (122) hide show
  1. package/README.md +46 -0
  2. package/dist/{bun-exec-6CQHTS4F.js → bun-exec-ULMPAIQC.js} +1 -1
  3. package/dist/{chunk-E6XYTE3A.js → chunk-D3QSET5H.js} +69 -72
  4. package/dist/{chunk-FDEDLANP.js → chunk-FQYWRHLX.js} +1 -1
  5. package/dist/{chunk-T2QDIXGU.js → chunk-FSSUAWXQ.js} +3 -3
  6. package/dist/{chunk-D3Q2UZLZ.js → chunk-I4L4T7QX.js} +1 -1
  7. package/dist/{chunk-5GUS4CFO.js → chunk-SMZBJQJR.js} +1 -1
  8. package/dist/commands/agent/actions/index.js +3 -3
  9. package/dist/commands/agent/index.js +3 -3
  10. package/dist/commands/create/actions/index.js +4 -4
  11. package/dist/commands/create/index.js +5 -5
  12. package/dist/index.js +134 -109
  13. package/dist/{plugin-creator-H26ZLR6H.js → plugin-creator-TCUFII32.js} +2 -2
  14. package/dist/{registry-433S5F3Y.js → registry-RF6PW3EN.js} +3 -3
  15. package/dist/templates/plugin-quick-starter/README.md +52 -10
  16. package/dist/templates/plugin-quick-starter/package.json +2 -2
  17. package/dist/templates/plugin-quick-starter/src/__tests__/e2e/README.md +140 -0
  18. package/dist/templates/plugin-quick-starter/src/__tests__/e2e/plugin-quick-starter.e2e.ts +339 -0
  19. package/dist/templates/plugin-quick-starter/src/__tests__/plugin.test.ts +55 -17
  20. package/dist/templates/plugin-quick-starter/src/plugin.ts +14 -14
  21. package/dist/templates/plugin-starter/README.md +124 -49
  22. package/dist/templates/plugin-starter/package.json +2 -2
  23. package/dist/templates/plugin-starter/src/__tests__/e2e/README.md +44 -9
  24. package/{templates/plugin-starter/src/__tests__/e2e/starter-plugin.ts → dist/templates/plugin-starter/src/__tests__/e2e/plugin-starter.e2e.ts} +13 -20
  25. package/dist/templates/plugin-starter/src/plugin.ts +5 -7
  26. package/dist/templates/project-starter/README.md +24 -11
  27. package/dist/templates/project-starter/package.json +4 -4
  28. package/dist/templates/project-starter/src/__tests__/actions.test.ts +2 -2
  29. package/dist/templates/project-starter/src/__tests__/e2e/README.md +103 -0
  30. package/dist/templates/project-starter/src/__tests__/e2e/project-starter.e2e.ts +575 -0
  31. package/dist/templates/project-starter/src/__tests__/integration.test.ts +1 -1
  32. package/dist/templates/project-starter/src/__tests__/models.test.ts +3 -3
  33. package/dist/templates/project-starter/src/__tests__/plugin.test.ts +3 -3
  34. package/dist/templates/project-starter/src/__tests__/provider.test.ts +2 -2
  35. package/dist/templates/project-starter/src/index.ts +4 -3
  36. package/dist/templates/project-starter/src/plugin.ts +5 -5
  37. package/dist/templates/project-tee-starter/README.md +44 -5
  38. package/dist/templates/project-tee-starter/package.json +4 -4
  39. package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/build-order.test.ts +1 -1
  40. package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/character.test.ts +1 -1
  41. package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/config.test.ts +1 -1
  42. package/dist/templates/project-tee-starter/src/__tests__/e2e/README.md +128 -0
  43. package/dist/templates/project-tee-starter/src/__tests__/e2e/project-tee-starter.e2e.ts +280 -0
  44. package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/env.test.ts +1 -1
  45. package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/error-handling.test.ts +2 -2
  46. package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/events.test.ts +1 -1
  47. package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/file-structure.test.ts +2 -2
  48. package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/integration.test.ts +2 -2
  49. package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/models.test.ts +1 -1
  50. package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/plugin.test.ts +1 -1
  51. package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/provider.test.ts +2 -2
  52. package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/routes.test.ts +1 -1
  53. package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/tee-validation.test.ts +1 -1
  54. package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/test-utils.ts +2 -2
  55. package/{templates/project-tee-starter → dist/templates/project-tee-starter/src}/__tests__/vite-config-utils.ts +14 -2
  56. package/dist/templates/project-tee-starter/src/index.ts +2 -0
  57. package/dist/templates/project-tee-starter/src/plugin.ts +19 -7
  58. package/dist/{utils-DBLSDYBF.js → utils-5HPZSIF6.js} +3 -3
  59. package/package.json +6 -6
  60. package/templates/plugin-quick-starter/README.md +52 -10
  61. package/templates/plugin-quick-starter/package.json +2 -2
  62. package/templates/plugin-quick-starter/src/__tests__/e2e/README.md +140 -0
  63. package/templates/plugin-quick-starter/src/__tests__/e2e/plugin-quick-starter.e2e.ts +339 -0
  64. package/templates/plugin-quick-starter/src/__tests__/plugin.test.ts +55 -17
  65. package/templates/plugin-quick-starter/src/plugin.ts +14 -14
  66. package/templates/plugin-starter/README.md +124 -49
  67. package/templates/plugin-starter/package.json +2 -2
  68. package/templates/plugin-starter/src/__tests__/e2e/README.md +44 -9
  69. package/{dist/templates/plugin-starter/src/__tests__/e2e/starter-plugin.ts → templates/plugin-starter/src/__tests__/e2e/plugin-starter.e2e.ts} +13 -20
  70. package/templates/plugin-starter/src/plugin.ts +5 -7
  71. package/templates/project-starter/README.md +24 -11
  72. package/templates/project-starter/package.json +4 -4
  73. package/templates/project-starter/src/__tests__/actions.test.ts +2 -2
  74. package/templates/project-starter/src/__tests__/e2e/README.md +103 -0
  75. package/templates/project-starter/src/__tests__/e2e/project-starter.e2e.ts +575 -0
  76. package/templates/project-starter/src/__tests__/integration.test.ts +1 -1
  77. package/templates/project-starter/src/__tests__/models.test.ts +3 -3
  78. package/templates/project-starter/src/__tests__/plugin.test.ts +3 -3
  79. package/templates/project-starter/src/__tests__/provider.test.ts +2 -2
  80. package/templates/project-starter/src/index.ts +4 -3
  81. package/templates/project-starter/src/plugin.ts +5 -5
  82. package/templates/project-tee-starter/README.md +44 -5
  83. package/templates/project-tee-starter/package.json +4 -4
  84. package/templates/project-tee-starter/{__tests__ → src/__tests__}/build-order.test.ts +1 -1
  85. package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/character.test.ts +1 -1
  86. package/templates/project-tee-starter/{__tests__ → src/__tests__}/config.test.ts +1 -1
  87. package/templates/project-tee-starter/src/__tests__/e2e/README.md +128 -0
  88. package/templates/project-tee-starter/src/__tests__/e2e/project-tee-starter.e2e.ts +280 -0
  89. package/templates/project-tee-starter/{__tests__ → src/__tests__}/env.test.ts +1 -1
  90. package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/error-handling.test.ts +2 -2
  91. package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/events.test.ts +1 -1
  92. package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/file-structure.test.ts +2 -2
  93. package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/integration.test.ts +2 -2
  94. package/templates/project-tee-starter/{__tests__ → src/__tests__}/models.test.ts +1 -1
  95. package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/plugin.test.ts +1 -1
  96. package/templates/project-tee-starter/{__tests__ → src/__tests__}/provider.test.ts +2 -2
  97. package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/routes.test.ts +1 -1
  98. package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/tee-validation.test.ts +1 -1
  99. package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/test-utils.ts +2 -2
  100. package/{dist/templates/project-tee-starter → templates/project-tee-starter/src}/__tests__/vite-config-utils.ts +14 -2
  101. package/templates/project-tee-starter/src/index.ts +2 -0
  102. package/templates/project-tee-starter/src/plugin.ts +19 -7
  103. package/dist/templates/plugin-starter/src/tests.ts +0 -6
  104. package/dist/templates/project-starter/src/__tests__/e2e/index.ts +0 -14
  105. package/dist/templates/project-starter/src/__tests__/e2e/natural-language.test.ts +0 -246
  106. package/dist/templates/project-starter/src/__tests__/e2e/project.test.ts +0 -155
  107. package/dist/templates/project-starter/src/__tests__/e2e/starter-plugin.test.ts +0 -421
  108. package/dist/templates/project-tee-starter/e2e/project.test.ts +0 -38
  109. package/dist/templates/project-tee-starter/e2e/starter-plugin.test.ts +0 -92
  110. package/templates/plugin-starter/src/tests.ts +0 -6
  111. package/templates/project-starter/src/__tests__/e2e/index.ts +0 -14
  112. package/templates/project-starter/src/__tests__/e2e/natural-language.test.ts +0 -246
  113. package/templates/project-starter/src/__tests__/e2e/project.test.ts +0 -155
  114. package/templates/project-starter/src/__tests__/e2e/starter-plugin.test.ts +0 -421
  115. package/templates/project-tee-starter/e2e/project.test.ts +0 -38
  116. package/templates/project-tee-starter/e2e/starter-plugin.test.ts +0 -92
  117. /package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/actions.test.ts +0 -0
  118. /package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/frontend.test.ts +0 -0
  119. /package/dist/templates/project-tee-starter/{__tests__ → src/__tests__}/utils/core-test-utils.ts +0 -0
  120. /package/templates/project-tee-starter/{__tests__ → src/__tests__}/actions.test.ts +0 -0
  121. /package/templates/project-tee-starter/{__tests__ → src/__tests__}/frontend.test.ts +0 -0
  122. /package/templates/project-tee-starter/{__tests__ → src/__tests__}/utils/core-test-utils.ts +0 -0
@@ -9,6 +9,7 @@ import {
9
9
  ModelType,
10
10
  logger,
11
11
  EventType,
12
+ Action,
12
13
  } from '@elizaos/core';
13
14
  import dotenv from 'dotenv';
14
15
  import {
@@ -19,6 +20,38 @@ import {
19
20
  testFixtures,
20
21
  } from './test-utils';
21
22
 
23
+ // Define proper interfaces for test mocking
24
+ interface MockLoggerMethod {
25
+ calls?: any[];
26
+ }
27
+
28
+ interface MockLogger {
29
+ info: MockLoggerMethod;
30
+ error: MockLoggerMethod;
31
+ debug: MockLoggerMethod;
32
+ warn: MockLoggerMethod;
33
+ }
34
+
35
+ interface PluginConfig {
36
+ EXAMPLE_PLUGIN_VARIABLE?: string | number;
37
+ }
38
+
39
+ interface TestCallbackContent {
40
+ text?: string;
41
+ actions?: string[];
42
+ source?: string;
43
+ }
44
+
45
+ interface TestActionResult {
46
+ text?: string;
47
+ success: boolean;
48
+ data?: {
49
+ actions?: string[];
50
+ source?: string;
51
+ };
52
+ error?: Error;
53
+ }
54
+
22
55
  // Setup environment variables
23
56
  dotenv.config();
24
57
 
@@ -79,7 +112,7 @@ describe('Plugin Configuration', () => {
79
112
  const invalidConfig = { EXAMPLE_PLUGIN_VARIABLE: 123 }; // Should be string
80
113
 
81
114
  if (starterPlugin.init) {
82
- await expect(starterPlugin.init(invalidConfig as any, runtime)).rejects.toThrow(
115
+ await expect(starterPlugin.init(invalidConfig as PluginConfig, runtime)).rejects.toThrow(
83
116
  'Invalid plugin configuration'
84
117
  );
85
118
  }
@@ -88,21 +121,22 @@ describe('Plugin Configuration', () => {
88
121
 
89
122
  describe('Hello World Action', () => {
90
123
  let runtime: IAgentRuntime;
91
- let helloWorldAction: any;
124
+ let helloWorldAction: Action;
92
125
 
93
126
  beforeEach(() => {
94
127
  runtime = createMockRuntime();
95
- helloWorldAction = starterPlugin.actions?.[0];
128
+ helloWorldAction = starterPlugin?.actions?.[0] as Action;
96
129
  // Clear all spies before each test
97
- (logger.info as any).calls = [];
98
- (logger.error as any).calls = [];
99
- (logger.debug as any).calls = [];
100
- (logger.warn as any).calls = [];
130
+ const mockLogger = logger as unknown as MockLogger;
131
+ mockLogger.info.calls = [];
132
+ mockLogger.error.calls = [];
133
+ mockLogger.debug.calls = [];
134
+ mockLogger.warn.calls = [];
101
135
  });
102
136
 
103
137
  it('should have hello world action', () => {
104
138
  expect(helloWorldAction).toBeDefined();
105
- expect(helloWorldAction?.name).toBe('HELLO_WORLD');
139
+ expect(helloWorldAction?.name).toBe('QUICK_ACTION');
106
140
  });
107
141
 
108
142
  it('should always validate messages (current implementation)', async () => {
@@ -180,9 +214,9 @@ describe('Hello World Action', () => {
180
214
  content: { text: 'say hello', source: 'test' },
181
215
  });
182
216
 
183
- let callbackContent: any = null;
217
+ let callbackContent: TestCallbackContent | null = null;
184
218
  const callback: HandlerCallback = async (content: Content) => {
185
- callbackContent = content;
219
+ callbackContent = content as TestCallbackContent;
186
220
  return [];
187
221
  };
188
222
 
@@ -191,12 +225,13 @@ describe('Hello World Action', () => {
191
225
  expect(result).toHaveProperty('text', 'Hello world!');
192
226
  expect(result).toHaveProperty('success', true);
193
227
  expect(result).toHaveProperty('data');
194
- expect((result as any).data).toHaveProperty('actions', ['HELLO_WORLD']);
195
- expect((result as any).data).toHaveProperty('source', 'test');
228
+ const typedResult = result as TestActionResult;
229
+ expect(typedResult.data).toHaveProperty('actions', ['QUICK_ACTION']);
230
+ expect(typedResult.data).toHaveProperty('source', 'test');
196
231
 
197
232
  expect(callbackContent).toEqual({
198
233
  text: 'Hello world!',
199
- actions: ['HELLO_WORLD'],
234
+ actions: ['QUICK_ACTION'],
200
235
  source: 'test',
201
236
  });
202
237
  });
@@ -224,7 +259,8 @@ describe('Hello World Action', () => {
224
259
 
225
260
  expect(result).toHaveProperty('success', false);
226
261
  expect(result).toHaveProperty('error');
227
- expect((result as any).error?.message).toBe('Callback error');
262
+ const typedResult = result as TestActionResult;
263
+ expect(typedResult.error?.message).toBe('Callback error');
228
264
  // Quick-starter plugin doesn't log errors
229
265
  });
230
266
 
@@ -278,7 +314,7 @@ describe('Hello World Provider', () => {
278
314
 
279
315
  it('should have hello world provider', () => {
280
316
  expect(provider).toBeDefined();
281
- expect(provider?.name).toBe('HELLO_WORLD_PROVIDER');
317
+ expect(provider?.name).toBe('QUICK_PROVIDER');
282
318
  });
283
319
 
284
320
  it('should provide hello world data', async () => {
@@ -310,9 +346,11 @@ describe('Hello World Provider', () => {
310
346
  const result2 = await provider.get(runtime, message, state);
311
347
 
312
348
  // Text and structure should be consistent
349
+ expect(result1.text).toBeDefined();
350
+ expect(result2.text).toBeDefined();
313
351
  expect(result1.text).toBe(result2.text);
314
- expect(result1.values).toEqual(result2.values);
315
- expect(result1.data).toEqual(result2.data);
352
+ expect(result1.values || {}).toEqual(result2.values || {});
353
+ expect(result1.data || {}).toEqual(result2.data || {});
316
354
  });
317
355
  });
318
356
 
@@ -51,9 +51,9 @@ const configSchema = z.object({
51
51
  * @property {Function} handler - Asynchronous function to handle the action and generate a response.
52
52
  * @property {Object[]} examples - An array of example inputs and expected outputs for the action.
53
53
  */
54
- const helloWorldAction: Action = {
55
- name: 'HELLO_WORLD',
56
- similes: ['GREET', 'SAY_HELLO'],
54
+ const quickAction: Action = {
55
+ name: 'QUICK_ACTION',
56
+ similes: ['GREET', 'SAY_HELLO', 'HELLO_WORLD'],
57
57
  description: 'Responds with a simple hello world message',
58
58
 
59
59
  validate: async (
@@ -79,7 +79,7 @@ const helloWorldAction: Action = {
79
79
  if (callback) {
80
80
  await callback({
81
81
  text: response,
82
- actions: ['HELLO_WORLD'],
82
+ actions: ['QUICK_ACTION'],
83
83
  source: message.content.source,
84
84
  });
85
85
  }
@@ -88,7 +88,7 @@ const helloWorldAction: Action = {
88
88
  text: response,
89
89
  success: true,
90
90
  data: {
91
- actions: ['HELLO_WORLD'],
91
+ actions: ['QUICK_ACTION'],
92
92
  source: message.content.source,
93
93
  },
94
94
  };
@@ -112,7 +112,7 @@ const helloWorldAction: Action = {
112
112
  name: '{{name2}}',
113
113
  content: {
114
114
  text: 'hello world!',
115
- actions: ['HELLO_WORLD'],
115
+ actions: ['QUICK_ACTION'],
116
116
  },
117
117
  },
118
118
  ],
@@ -123,8 +123,8 @@ const helloWorldAction: Action = {
123
123
  * Example Hello World Provider
124
124
  * This demonstrates the simplest possible provider implementation
125
125
  */
126
- const helloWorldProvider: Provider = {
127
- name: 'HELLO_WORLD_PROVIDER',
126
+ const quickProvider: Provider = {
127
+ name: 'QUICK_PROVIDER',
128
128
  description: 'A simple example provider',
129
129
 
130
130
  get: async (
@@ -235,31 +235,31 @@ export const starterPlugin: Plugin = {
235
235
  [EventType.MESSAGE_RECEIVED]: [
236
236
  async (params: MessagePayload) => {
237
237
  logger.debug('MESSAGE_RECEIVED event received');
238
- logger.debug('Message:', params.message);
238
+ logger.debug({ message: params.message }, 'Message:');
239
239
  },
240
240
  ],
241
241
  [EventType.VOICE_MESSAGE_RECEIVED]: [
242
242
  async (params: MessagePayload) => {
243
243
  logger.debug('VOICE_MESSAGE_RECEIVED event received');
244
- logger.debug('Message:', params.message);
244
+ logger.debug({ message: params.message }, 'Message:');
245
245
  },
246
246
  ],
247
247
  [EventType.WORLD_CONNECTED]: [
248
248
  async (params: WorldPayload) => {
249
249
  logger.debug('WORLD_CONNECTED event received');
250
- logger.debug('World:', params.world);
250
+ logger.debug({ world: params.world }, 'World:');
251
251
  },
252
252
  ],
253
253
  [EventType.WORLD_JOINED]: [
254
254
  async (params: WorldPayload) => {
255
255
  logger.debug('WORLD_JOINED event received');
256
- logger.debug('World:', params.world);
256
+ logger.debug({ world: params.world }, 'World:');
257
257
  },
258
258
  ],
259
259
  },
260
260
  services: [StarterService],
261
- actions: [helloWorldAction],
262
- providers: [helloWorldProvider],
261
+ actions: [quickAction],
262
+ providers: [quickProvider],
263
263
  // dependencies: ['@elizaos/plugin-knowledge'], <--- plugin dependencies go here (if requires another plugin)
264
264
  };
265
265
 
@@ -34,89 +34,164 @@ elizaos test
34
34
 
35
35
  ## Testing
36
36
 
37
- ElizaOS provides a comprehensive testing structure for plugins:
37
+ ElizaOS uses a dual testing approach that combines Bun's native test runner for component tests with a custom E2E test runner for integration testing within a live ElizaOS runtime.
38
38
 
39
39
  ### Test Structure
40
40
 
41
- - **Component Tests** (`__tests__/` directory):
42
-
43
- - **Unit Tests**: Test individual functions/classes in isolation
44
- - **Integration Tests**: Test how components work together
45
- - Run with: `elizaos test component`
46
-
47
- - **End-to-End Tests** (`__tests__/e2e/` directory):
48
-
49
- - Test the plugin within a full ElizaOS runtime
50
- - Validate complete user scenarios with a real agent
51
- - Run with: `elizaos test e2e`
41
+ ```
42
+ src/
43
+ __tests__/ # All tests live inside src
44
+ *.test.ts # Component tests (use Bun test runner)
45
+ e2e/ # E2E tests (use ElizaOS test runner)
46
+ *.ts # E2E test files
47
+ README.md # E2E testing documentation
48
+ ```
52
49
 
53
- - **Running All Tests**:
54
- - `elizaos test` runs both component and e2e tests
50
+ ### Two Types of Tests
55
51
 
56
- ### Writing Tests
52
+ #### 1. Component Tests (Bun Test Runner)
57
53
 
58
- Component tests use bun:test:
54
+ - **Purpose**: Test individual functions/classes in isolation
55
+ - **Location**: `src/__tests__/*.test.ts`
56
+ - **Runner**: Bun's built-in test runner
57
+ - **Command**: `bun test`
58
+ - **Features**: Fast, isolated, uses mocks
59
59
 
60
60
  ```typescript
61
- // Unit test example (__tests__/plugin.test.ts)
61
+ // Example: src/__tests__/plugin.test.ts
62
+ import { describe, it, expect } from 'bun:test';
63
+ import { starterPlugin } from '../plugin';
64
+
62
65
  describe('Plugin Configuration', () => {
63
66
  it('should have correct plugin metadata', () => {
64
67
  expect(starterPlugin.name).toBe('plugin-starter');
65
68
  });
66
69
  });
67
-
68
- // Integration test example (__tests__/integration.test.ts)
69
- describe('Integration: HelloWorld Action with StarterService', () => {
70
- it('should handle HelloWorld action with StarterService', async () => {
71
- // Test interactions between components
72
- });
73
- });
74
70
  ```
75
71
 
76
- E2E tests run in a real ElizaOS runtime:
72
+ #### 2. E2E Tests (ElizaOS Test Runner)
73
+
74
+ - **Purpose**: Test plugin behavior within a real ElizaOS runtime
75
+ - **Location**: `src/__tests__/e2e/*.ts`
76
+ - **Runner**: ElizaOS custom test runner
77
+ - **Command**: `elizaos test --type e2e`
78
+ - **Features**: Real runtime, real database, full integration
77
79
 
78
80
  ```typescript
79
- // E2E test example (__tests__/e2e/starter-plugin.ts)
81
+ // Example: src/__tests__/e2e/starter-plugin.ts
82
+ import { type TestSuite } from '@elizaos/core';
83
+
80
84
  export const StarterPluginTestSuite: TestSuite = {
81
85
  name: 'plugin_starter_test_suite',
82
- description: 'E2E tests for the starter plugin',
83
86
  tests: [
84
87
  {
85
88
  name: 'hello_world_action_test',
86
89
  fn: async (runtime) => {
87
- // Simulate user asking agent to say hello
88
- const testMessage = {
89
- content: { text: 'Can you say hello?' }
90
- };
91
-
92
- // Execute action and capture response
93
- const response = await helloWorldAction.handler(runtime, testMessage, ...);
94
-
95
- // Verify agent responds with "hello world"
96
- if (!response.text.includes('hello world')) {
97
- throw new Error('Expected "hello world" in response');
90
+ // Test with real runtime - no mocks needed!
91
+ const action = runtime.actions.find((a) => a.name === 'HELLO_WORLD');
92
+ if (!action) {
93
+ throw new Error('Action not found');
98
94
  }
95
+ // Test real behavior...
99
96
  },
100
97
  },
101
98
  ],
102
99
  };
103
100
  ```
104
101
 
105
- #### Key E2E Testing Features:
102
+ ### Running Tests
103
+
104
+ ```bash
105
+ # Run all tests (both component and E2E)
106
+ elizaos test
107
+
108
+ # Run only component tests (fast, for TDD)
109
+ bun test
110
+ # or
111
+ elizaos test --type component
112
+
113
+ # Run only E2E tests (slower, full integration)
114
+ elizaos test --type e2e
115
+ ```
116
+
117
+ ### Key Differences
118
+
119
+ | Aspect | Component Tests | E2E Tests |
120
+ | --------------- | -------------------- | ----------------------- |
121
+ | **Runner** | Bun test | ElizaOS TestRunner |
122
+ | **Environment** | Mocked | Real runtime |
123
+ | **Database** | Mocked | Real (PGLite) |
124
+ | **Speed** | Fast (ms) | Slower (seconds) |
125
+ | **Use Case** | TDD, component logic | Integration, user flows |
126
+
127
+ ### E2E Test Integration
128
+
129
+ E2E tests are integrated into your plugin by:
130
+
131
+ 1. **Creating the test suite** in `src/__tests__/e2e/`
132
+ 2. **Importing directly** in your plugin definition:
133
+
134
+ ```typescript
135
+ // src/plugin.ts
136
+ import { StarterPluginTestSuite } from './__tests__/e2e/starter-plugin';
137
+
138
+ export const starterPlugin: Plugin = {
139
+ name: 'plugin-starter',
140
+ // ... other properties
141
+ tests: [StarterPluginTestSuite], // Direct import, no tests.ts needed
142
+ };
143
+ ```
144
+
145
+ ### Writing Effective E2E Tests
146
+
147
+ E2E tests receive a real `IAgentRuntime` instance, allowing you to:
148
+
149
+ - Access real actions, providers, and services
150
+ - Interact with the actual database
151
+ - Test complete user scenarios
152
+ - Validate plugin behavior in production-like conditions
153
+
154
+ ```typescript
155
+ {
156
+ name: 'service_lifecycle_test',
157
+ fn: async (runtime) => {
158
+ // Get the real service
159
+ const service = runtime.getService('starter');
160
+ if (!service) {
161
+ throw new Error('Service not initialized');
162
+ }
163
+
164
+ // Test real behavior
165
+ await service.stop();
166
+ // Verify cleanup happened...
167
+ },
168
+ }
169
+ ```
170
+
171
+ ### Best Practices
172
+
173
+ 1. **Use Component Tests for**:
174
+
175
+ - Algorithm logic
176
+ - Data transformations
177
+ - Input validation
178
+ - Error handling
106
179
 
107
- - **Real Runtime Environment**: Tests run with a fully initialized ElizaOS runtime
108
- - **Plugin Interaction**: Test how your plugin behaves with the actual agent
109
- - **Scenario Testing**: Validate complete user interactions, not just individual functions
110
- - **No Mock Required**: Access real services, actions, and providers
180
+ 2. **Use E2E Tests for**:
111
181
 
112
- #### Writing New E2E Tests:
182
+ - User scenarios
183
+ - Action execution flows
184
+ - Provider data integration
185
+ - Service lifecycle
186
+ - Plugin interactions
113
187
 
114
- 1. Add a new test object to the `tests` array in your test suite
115
- 2. Each test receives the runtime instance as a parameter
116
- 3. Throw errors to indicate test failures (no assertion library needed)
117
- 4. See the comprehensive documentation in `__tests__/e2e/starter-plugin.ts` for detailed examples
188
+ 3. **Test Organization**:
189
+ - Keep related tests together
190
+ - Use descriptive test names
191
+ - Include failure scenarios
192
+ - Document complex test setups
118
193
 
119
- The test utilities in `__tests__/test-utils.ts` provide mock objects and setup functions to simplify writing component tests.
194
+ The comprehensive E2E test documentation in `src/__tests__/e2e/README.md` provides detailed examples and patterns for writing effective tests.
120
195
 
121
196
  ## Publishing & Continuous Development
122
197
 
@@ -41,7 +41,7 @@
41
41
  "tsup.config.ts"
42
42
  ],
43
43
  "dependencies": {
44
- "@elizaos/core": "1.3.2",
44
+ "@elizaos/core": "1.4.2",
45
45
  "@tanstack/react-query": "^5.80.7",
46
46
  "clsx": "^2.1.1",
47
47
  "tailwind-merge": "^3.3.1",
@@ -50,7 +50,7 @@
50
50
  "zod": "3.24.2"
51
51
  },
52
52
  "devDependencies": {
53
- "@elizaos/cli": "1.3.2",
53
+ "@elizaos/cli": "1.4.2",
54
54
  "@tailwindcss/vite": "^4.1.10",
55
55
  "@vitejs/plugin-react-swc": "^3.10.2",
56
56
  "dotenv": "16.4.5",
@@ -2,9 +2,26 @@
2
2
 
3
3
  This directory contains end-to-end tests for the ElizaOS plugin starter template.
4
4
 
5
+ ## ElizaOS Testing Philosophy
6
+
7
+ ElizaOS employs a dual testing strategy:
8
+
9
+ 1. **Component Tests** (`src/__tests__/*.test.ts`)
10
+
11
+ - Run with Bun's native test runner
12
+ - Fast, isolated tests using mocks
13
+ - Perfect for TDD and component logic
14
+ - Command: `bun test`
15
+
16
+ 2. **E2E Tests** (`src/__tests__/e2e/*.ts`)
17
+ - Run with ElizaOS custom test runner
18
+ - Real runtime with actual database (PGLite)
19
+ - Test complete user scenarios
20
+ - Command: `elizaos test --type e2e`
21
+
5
22
  ## Overview
6
23
 
7
- E2E tests run in a real ElizaOS runtime environment, allowing you to test your plugin's behavior as it would work in production.
24
+ E2E tests run in a real ElizaOS runtime environment, allowing you to test your plugin's behavior as it would work in production. Unlike component tests, E2E tests provide access to a fully initialized runtime with all services, actions, and providers available.
8
25
 
9
26
  ## Test Structure
10
27
 
@@ -15,24 +32,42 @@ E2E tests run in a real ElizaOS runtime environment, allowing you to test your p
15
32
  - `hello_world_provider_test` - Tests provider functionality
16
33
  - `starter_service_test` - Tests service lifecycle
17
34
 
35
+ ## Integration with Plugin
36
+
37
+ E2E tests are integrated directly into your plugin without the need for an intermediate export file:
38
+
39
+ ```typescript
40
+ // src/plugin.ts
41
+ import { StarterPluginTestSuite } from './__tests__/e2e/plugin-starter.e2e';
42
+
43
+ export const myPlugin: Plugin = {
44
+ name: 'my-plugin',
45
+ // ... other properties
46
+ tests: [StarterPluginTestSuite], // Direct import!
47
+ };
48
+ ```
49
+
18
50
  ## Running Tests
19
51
 
20
52
  ```bash
21
53
  # Run all tests (component + e2e)
22
- npm test
54
+ elizaos test
23
55
 
24
- # Run only e2e tests
25
- npm run test:e2e
56
+ # Run only e2e tests (slower, full integration)
57
+ elizaos test --type e2e
26
58
 
27
- # Run only component tests
28
- npm run test:component
59
+ # Run only component tests (fast, for TDD)
60
+ bun test
61
+ # or
62
+ elizaos test --type component
29
63
  ```
30
64
 
31
65
  ## Implementation Details
32
66
 
33
- 1. **Test Export**: Tests are exported through `src/tests.ts` to be included in the plugin build
67
+ 1. **Direct Import**: Tests are imported directly from the e2e test file - no intermediate export file needed
34
68
  2. **Plugin Integration**: The test suite is added to the plugin's `tests` array
35
- 3. **Runtime Access**: Each test receives a real runtime instance with full access to:
69
+ 3. **Test Discovery**: The ElizaOS test runner automatically finds and executes tests from the plugin's `tests` array
70
+ 4. **Runtime Access**: Each test receives a real runtime instance with full access to:
36
71
  - Plugin actions, providers, and services
37
72
  - Agent character configuration
38
73
  - Database and model access
@@ -44,4 +79,4 @@ npm run test:component
44
79
 
45
80
  ## Writing New Tests
46
81
 
47
- See the comprehensive documentation at the top of `starter-plugin.ts` for detailed instructions on adding new tests.
82
+ See the comprehensive documentation at the top of `plugin-starter.e2e.ts` for detailed instructions on adding new tests.
@@ -1,4 +1,9 @@
1
- import { type Content, type HandlerCallback } from '@elizaos/core';
1
+ import {
2
+ type Content,
3
+ type HandlerCallback,
4
+ type IAgentRuntime,
5
+ type TestSuite,
6
+ } from '@elizaos/core';
2
7
 
3
8
  /**
4
9
  * E2E (End-to-End) Test Suite for ElizaOS Plugins
@@ -31,7 +36,7 @@ import { type Content, type HandlerCallback } from '@elizaos/core';
31
36
  * ```typescript
32
37
  * {
33
38
  * name: 'my_new_test',
34
- * fn: async (runtime) => {
39
+ * fn: async (runtime: IAgentRuntime) => {
35
40
  * // Your test logic here
36
41
  * if (someCondition !== expected) {
37
42
  * throw new Error('Test failed: reason');
@@ -60,16 +65,6 @@ import { type Content, type HandlerCallback } from '@elizaos/core';
60
65
  * For more details, see the ElizaOS documentation.
61
66
  */
62
67
 
63
- // Define a minimal TestSuite interface that matches what's needed
64
- interface TestSuite {
65
- name: string;
66
- description?: string;
67
- tests: Array<{
68
- name: string;
69
- fn: (runtime: any) => Promise<any>;
70
- }>;
71
- }
72
-
73
68
  // Define minimal interfaces for the types we need
74
69
  type UUID = `${string}-${string}-${string}-${string}-${string}`;
75
70
 
@@ -91,8 +86,6 @@ interface State {
91
86
 
92
87
  export const StarterPluginTestSuite: TestSuite = {
93
88
  name: 'plugin_starter_test_suite',
94
- description: 'E2E tests for the starter plugin',
95
-
96
89
  tests: [
97
90
  /**
98
91
  * Basic Plugin Verification Test
@@ -102,7 +95,7 @@ export const StarterPluginTestSuite: TestSuite = {
102
95
  */
103
96
  {
104
97
  name: 'example_test',
105
- fn: async (runtime) => {
98
+ fn: async (runtime: IAgentRuntime) => {
106
99
  // Test the character name
107
100
  if (runtime.character.name !== 'Eliza') {
108
101
  throw new Error(
@@ -125,7 +118,7 @@ export const StarterPluginTestSuite: TestSuite = {
125
118
  */
126
119
  {
127
120
  name: 'should_have_hello_world_action',
128
- fn: async (runtime) => {
121
+ fn: async (runtime: IAgentRuntime) => {
129
122
  // Access actions through runtime.actions instead of getPlugin
130
123
  const actionExists = runtime.actions?.some((a) => a.name === 'HELLO_WORLD');
131
124
  if (!actionExists) {
@@ -147,7 +140,7 @@ export const StarterPluginTestSuite: TestSuite = {
147
140
  */
148
141
  {
149
142
  name: 'hello_world_action_test',
150
- fn: async (runtime) => {
143
+ fn: async (runtime: IAgentRuntime) => {
151
144
  // Create a test message asking the agent to say hello
152
145
  const testMessage: Memory = {
153
146
  entityId: '12345678-1234-1234-1234-123456789012' as UUID,
@@ -215,7 +208,7 @@ export const StarterPluginTestSuite: TestSuite = {
215
208
  */
216
209
  {
217
210
  name: 'hello_world_provider_test',
218
- fn: async (runtime) => {
211
+ fn: async (runtime: IAgentRuntime) => {
219
212
  // Create a test message
220
213
  const testMessage: Memory = {
221
214
  entityId: '12345678-1234-1234-1234-123456789012' as UUID,
@@ -258,7 +251,7 @@ export const StarterPluginTestSuite: TestSuite = {
258
251
  */
259
252
  {
260
253
  name: 'starter_service_test',
261
- fn: async (runtime) => {
254
+ fn: async (runtime: IAgentRuntime) => {
262
255
  // Get the service from the runtime
263
256
  const service = runtime.getService('starter');
264
257
  if (!service) {
@@ -287,7 +280,7 @@ export const StarterPluginTestSuite: TestSuite = {
287
280
  * ```typescript
288
281
  * {
289
282
  * name: 'your_test_name',
290
- * fn: async (runtime) => {
283
+ * fn: async (runtime: IAgentRuntime) => {
291
284
  * // Setup: Create any test data needed
292
285
  *
293
286
  * // Action: Perform the operation you want to test