genlayer 0.5.0 → 0.5.1-beta.0
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/.env.example +71 -0
- package/CHANGELOG.md +7 -0
- package/dist/index.js +327 -415
- package/docker-compose.yml +144 -0
- package/package.json +3 -2
- package/scripts/postinstall.js +18 -0
- package/src/commands/general/index.ts +0 -4
- package/src/commands/general/init.ts +4 -43
- package/src/commands/general/start.ts +2 -16
- package/src/lib/config/simulator.ts +5 -6
- package/src/lib/interfaces/ISimulatorService.ts +1 -8
- package/src/lib/services/simulator.ts +48 -90
- package/tests/actions/init.test.ts +25 -84
- package/tests/actions/start.test.ts +1 -17
- package/tests/commands/init.test.ts +0 -17
- package/tests/commands/up.test.ts +1 -13
- package/tests/services/simulator.test.ts +111 -65
- package/vitest.config.ts +1 -1
|
@@ -5,6 +5,13 @@ import { initAction } from "../../src/commands/general/init";
|
|
|
5
5
|
import { tmpdir } from "os";
|
|
6
6
|
import {mkdtempSync} from "fs";
|
|
7
7
|
import {join} from "path";
|
|
8
|
+
import fs from "fs";
|
|
9
|
+
import * as dotenv from "dotenv";
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
vi.mock("fs");
|
|
13
|
+
vi.mock("dotenv");
|
|
14
|
+
|
|
8
15
|
|
|
9
16
|
const tempDir = mkdtempSync(join(tmpdir(), "test-initAction-"));
|
|
10
17
|
const defaultActionOptions = { numValidators: 5, branch: "main", location: tempDir, headless: false, resetDb: false };
|
|
@@ -18,9 +25,7 @@ describe("init action", () => {
|
|
|
18
25
|
let simServCheckVersionRequirements: ReturnType<any>;
|
|
19
26
|
let simServResetDockerContainers: ReturnType<any>;
|
|
20
27
|
let simServResetDockerImages: ReturnType<any>;
|
|
21
|
-
let simServDownloadSimulator: ReturnType<any>;
|
|
22
28
|
let simServgetAiProvidersOptions: ReturnType<any>;
|
|
23
|
-
let simServConfigSimulator: ReturnType<any>;
|
|
24
29
|
let simServRunSimulator: ReturnType<any>;
|
|
25
30
|
let simServWaitForSimulator: ReturnType<any>;
|
|
26
31
|
let simServPullOllamaModel: ReturnType<any>;
|
|
@@ -28,6 +33,7 @@ describe("init action", () => {
|
|
|
28
33
|
let simServCreateRandomValidators: ReturnType<any>;
|
|
29
34
|
let simServOpenFrontend: ReturnType<any>;
|
|
30
35
|
let simGetSimulatorUrl: ReturnType<any>;
|
|
36
|
+
let simAddConfigToEnvFile: ReturnType<any>;
|
|
31
37
|
|
|
32
38
|
beforeEach(() => {
|
|
33
39
|
vi.clearAllMocks();
|
|
@@ -40,8 +46,6 @@ describe("init action", () => {
|
|
|
40
46
|
simServCheckVersionRequirements = vi.spyOn(simulatorService, "checkVersionRequirements");
|
|
41
47
|
simServResetDockerContainers = vi.spyOn(simulatorService, "resetDockerContainers");
|
|
42
48
|
simServResetDockerImages = vi.spyOn(simulatorService, "resetDockerImages");
|
|
43
|
-
simServDownloadSimulator = vi.spyOn(simulatorService, "downloadSimulator");
|
|
44
|
-
simServConfigSimulator = vi.spyOn(simulatorService, "configSimulator");
|
|
45
49
|
simServgetAiProvidersOptions = vi.spyOn(simulatorService, "getAiProvidersOptions");
|
|
46
50
|
simServRunSimulator = vi.spyOn(simulatorService, "runSimulator");
|
|
47
51
|
simServWaitForSimulator = vi.spyOn(simulatorService, "waitForSimulatorToBeReady");
|
|
@@ -50,6 +54,7 @@ describe("init action", () => {
|
|
|
50
54
|
simServCreateRandomValidators = vi.spyOn(simulatorService, "createRandomValidators");
|
|
51
55
|
simServOpenFrontend = vi.spyOn(simulatorService, "openFrontend");
|
|
52
56
|
simGetSimulatorUrl = vi.spyOn(simulatorService, "getFrontendUrl")
|
|
57
|
+
simAddConfigToEnvFile = vi.spyOn(simulatorService, "addConfigToEnvFile")
|
|
53
58
|
|
|
54
59
|
simServCheckVersionRequirements.mockResolvedValue({
|
|
55
60
|
node: '',
|
|
@@ -59,22 +64,17 @@ describe("init action", () => {
|
|
|
59
64
|
git: true,
|
|
60
65
|
docker: true,
|
|
61
66
|
})
|
|
67
|
+
simAddConfigToEnvFile.mockResolvedValue(true);
|
|
68
|
+
const mockEnvContent = "FRONTEND_PORT=8080";
|
|
69
|
+
const mockEnvConfig = { FRONTEND_PORT: "8080" };
|
|
70
|
+
vi.mocked(fs.readFileSync).mockReturnValue(mockEnvContent);
|
|
71
|
+
vi.mocked(dotenv.parse).mockReturnValue(mockEnvConfig);
|
|
62
72
|
});
|
|
63
73
|
|
|
64
74
|
afterEach(() => {
|
|
65
75
|
vi.restoreAllMocks();
|
|
66
76
|
});
|
|
67
77
|
|
|
68
|
-
test("if both requirements are missing, then the execution fails", async () => {
|
|
69
|
-
simServCheckInstallRequirements.mockResolvedValue({ git: false, docker: false });
|
|
70
|
-
|
|
71
|
-
await initAction(defaultActionOptions, simulatorService);
|
|
72
|
-
|
|
73
|
-
expect(error).toHaveBeenCalledWith(
|
|
74
|
-
"Git and Docker are not installed. Please install them and try again.\n"
|
|
75
|
-
);
|
|
76
|
-
});
|
|
77
|
-
|
|
78
78
|
test("if only docker is missing, then the execution fails", async () => {
|
|
79
79
|
simServCheckInstallRequirements.mockResolvedValue({ git: true, docker: false });
|
|
80
80
|
|
|
@@ -83,14 +83,6 @@ describe("init action", () => {
|
|
|
83
83
|
expect(error).toHaveBeenCalledWith("Docker is not installed. Please install Docker and try again.\n");
|
|
84
84
|
});
|
|
85
85
|
|
|
86
|
-
test("if only git is missing, then the execution fails", async () => {
|
|
87
|
-
simServCheckInstallRequirements.mockResolvedValue({ git: false, docker: true });
|
|
88
|
-
|
|
89
|
-
await initAction(defaultActionOptions, simulatorService);
|
|
90
|
-
|
|
91
|
-
expect(error).toHaveBeenCalledWith("Git is not installed. Please install Git and try again.\n");
|
|
92
|
-
});
|
|
93
|
-
|
|
94
86
|
test("if check install requirements fail, then the execution aborts", async () => {
|
|
95
87
|
simServCheckInstallRequirements.mockRejectedValue(new Error("Error"));
|
|
96
88
|
|
|
@@ -169,7 +161,6 @@ describe("init action", () => {
|
|
|
169
161
|
{ name: "OpenAI", value: "openai" },
|
|
170
162
|
{ name: "Heurist", value: "heuristai" },
|
|
171
163
|
]);
|
|
172
|
-
simServConfigSimulator.mockResolvedValue(true);
|
|
173
164
|
simServRunSimulator.mockResolvedValue(true);
|
|
174
165
|
simServWaitForSimulator.mockResolvedValue({ initialized: true });
|
|
175
166
|
simServPullOllamaModel.mockResolvedValue(true);
|
|
@@ -200,7 +191,6 @@ describe("init action", () => {
|
|
|
200
191
|
{ name: "OpenAI", value: "openai" },
|
|
201
192
|
{ name: "Heurist", value: "heuristai" },
|
|
202
193
|
]);
|
|
203
|
-
simServConfigSimulator.mockResolvedValue(true);
|
|
204
194
|
simServRunSimulator.mockResolvedValue(true);
|
|
205
195
|
simServWaitForSimulator.mockResolvedValue({ initialized: true });
|
|
206
196
|
simServPullOllamaModel.mockResolvedValue(true);
|
|
@@ -230,7 +220,6 @@ describe("init action", () => {
|
|
|
230
220
|
{ name: "OpenAI", value: "openai" },
|
|
231
221
|
{ name: "Heurist", value: "heuristai" },
|
|
232
222
|
]);
|
|
233
|
-
simServConfigSimulator.mockResolvedValue(true);
|
|
234
223
|
simServRunSimulator.mockResolvedValue(true);
|
|
235
224
|
simServWaitForSimulator.mockResolvedValue({ initialized: true });
|
|
236
225
|
simServPullOllamaModel.mockResolvedValue(true);
|
|
@@ -248,18 +237,6 @@ describe("init action", () => {
|
|
|
248
237
|
expect(error).toHaveBeenCalledWith('Unable to initialize the validators.');
|
|
249
238
|
});
|
|
250
239
|
|
|
251
|
-
|
|
252
|
-
test("if configSimulator fails, then the execution aborts", async () => {
|
|
253
|
-
inquirerPrompt.mockResolvedValue({ confirmReset: true, confirmDownload: true, selectedLlmProviders: [] });
|
|
254
|
-
simServConfigSimulator.mockRejectedValue(new Error("Error"));
|
|
255
|
-
simServResetDockerContainers.mockResolvedValue(true);
|
|
256
|
-
simServResetDockerImages.mockResolvedValue(true);
|
|
257
|
-
|
|
258
|
-
await initAction(defaultActionOptions, simulatorService);
|
|
259
|
-
|
|
260
|
-
expect(error).toHaveBeenCalledWith(new Error("Error"));
|
|
261
|
-
});
|
|
262
|
-
|
|
263
240
|
test("if runSimulator fails, then the execution aborts", async () => {
|
|
264
241
|
inquirerPrompt.mockResolvedValue({ confirmReset: true, confirmDownload: true, selectedLlmProviders: [] });
|
|
265
242
|
simServRunSimulator.mockRejectedValue(new Error("Error"));
|
|
@@ -285,7 +262,7 @@ describe("init action", () => {
|
|
|
285
262
|
{ name: "Heurist", value: "heuristai" },
|
|
286
263
|
{ name: "Ollama", value: "ollama" },
|
|
287
264
|
]);
|
|
288
|
-
|
|
265
|
+
|
|
289
266
|
simServRunSimulator.mockResolvedValue(true);
|
|
290
267
|
simServWaitForSimulator.mockResolvedValue({ initialized: true });
|
|
291
268
|
simServPullOllamaModel.mockResolvedValue(true);
|
|
@@ -308,20 +285,6 @@ describe("init action", () => {
|
|
|
308
285
|
expect(error).toHaveBeenCalledWith(errorMsg);
|
|
309
286
|
});
|
|
310
287
|
|
|
311
|
-
test("logs 'Aborted!' if confirmDownload is false", async () => {
|
|
312
|
-
inquirerPrompt
|
|
313
|
-
.mockResolvedValueOnce({ confirmReset: true })
|
|
314
|
-
.mockResolvedValueOnce({ confirmDownload: false });
|
|
315
|
-
|
|
316
|
-
simServCheckInstallRequirements.mockResolvedValue({ git: true, docker: true });
|
|
317
|
-
simServResetDockerContainers.mockResolvedValue(true);
|
|
318
|
-
simServResetDockerImages.mockResolvedValue(true);
|
|
319
|
-
|
|
320
|
-
await initAction(defaultActionOptions, simulatorService);
|
|
321
|
-
|
|
322
|
-
expect(log).toHaveBeenCalledWith("Aborted!");
|
|
323
|
-
});
|
|
324
|
-
|
|
325
288
|
test("logs error if resetDockerContainers throws", async () => {
|
|
326
289
|
inquirerPrompt.mockResolvedValue({ confirmReset: true });
|
|
327
290
|
simServCheckInstallRequirements.mockResolvedValue({ git: true, docker: true });
|
|
@@ -334,9 +297,11 @@ describe("init action", () => {
|
|
|
334
297
|
});
|
|
335
298
|
|
|
336
299
|
test("prompts for LLM providers and validates that at least one is selected", async () => {
|
|
300
|
+
const mockEnvContent = "FRONTEND_PORT=8080";
|
|
301
|
+
vi.mocked(fs.readFileSync).mockReturnValue(mockEnvContent);
|
|
302
|
+
|
|
337
303
|
inquirerPrompt
|
|
338
304
|
.mockResolvedValueOnce({ confirmReset: true })
|
|
339
|
-
.mockResolvedValueOnce({ confirmDownload: true })
|
|
340
305
|
.mockImplementation((questions: any) => {
|
|
341
306
|
if (questions[0].type === "checkbox") {
|
|
342
307
|
const validateFunction = questions[0].validate;
|
|
@@ -353,11 +318,9 @@ describe("init action", () => {
|
|
|
353
318
|
}
|
|
354
319
|
});
|
|
355
320
|
|
|
356
|
-
simServCheckInstallRequirements.mockResolvedValue({
|
|
321
|
+
simServCheckInstallRequirements.mockResolvedValue({ docker: true });
|
|
357
322
|
simServResetDockerContainers.mockResolvedValue(true);
|
|
358
323
|
simServResetDockerImages.mockResolvedValue(true);
|
|
359
|
-
simServDownloadSimulator.mockResolvedValue({ wasInstalled: false });
|
|
360
|
-
simServConfigSimulator.mockResolvedValue(true);
|
|
361
324
|
simServRunSimulator.mockResolvedValue(true);
|
|
362
325
|
simServWaitForSimulator.mockResolvedValue({ initialized: true });
|
|
363
326
|
simServDeleteAllValidators.mockResolvedValue(true);
|
|
@@ -367,31 +330,16 @@ describe("init action", () => {
|
|
|
367
330
|
await initAction(defaultActionOptions, simulatorService);
|
|
368
331
|
});
|
|
369
332
|
|
|
370
|
-
test("logs error if downloadSimulator throws", async () => {
|
|
371
|
-
inquirerPrompt.mockResolvedValue({ confirmReset: true, confirmDownload: true });
|
|
372
|
-
simServCheckInstallRequirements.mockResolvedValue({ git: true, docker: true });
|
|
373
|
-
simServResetDockerContainers.mockResolvedValue(true);
|
|
374
|
-
simServResetDockerImages.mockResolvedValue(true);
|
|
375
|
-
const errorMsg = new Error("downloadSimulator error");
|
|
376
|
-
simServDownloadSimulator.mockRejectedValueOnce(errorMsg);
|
|
377
|
-
|
|
378
|
-
await initAction(defaultActionOptions, simulatorService);
|
|
379
|
-
|
|
380
|
-
expect(error).toHaveBeenCalledWith(errorMsg);
|
|
381
|
-
});
|
|
382
333
|
|
|
383
334
|
test("logs error message if simulator fails to initialize with ERROR code", async () => {
|
|
384
335
|
inquirerPrompt
|
|
385
336
|
.mockResolvedValueOnce({ confirmReset: true })
|
|
386
|
-
.mockResolvedValueOnce({ confirmDownload: true })
|
|
387
337
|
.mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
|
|
388
338
|
.mockResolvedValueOnce({ openai: "API_KEY1" });
|
|
389
339
|
|
|
390
|
-
simServCheckInstallRequirements.mockResolvedValue({
|
|
340
|
+
simServCheckInstallRequirements.mockResolvedValue({ docker: true });
|
|
391
341
|
simServResetDockerContainers.mockResolvedValue(true);
|
|
392
342
|
simServResetDockerImages.mockResolvedValue(true);
|
|
393
|
-
simServDownloadSimulator.mockResolvedValue({ wasInstalled: false });
|
|
394
|
-
simServConfigSimulator.mockResolvedValue(true);
|
|
395
343
|
simServRunSimulator.mockResolvedValue(true);
|
|
396
344
|
|
|
397
345
|
simServWaitForSimulator.mockResolvedValue({
|
|
@@ -416,8 +364,6 @@ describe("init action", () => {
|
|
|
416
364
|
simServCheckInstallRequirements.mockResolvedValue({ git: true, docker: true });
|
|
417
365
|
simServResetDockerContainers.mockResolvedValue(true);
|
|
418
366
|
simServResetDockerImages.mockResolvedValue(true);
|
|
419
|
-
simServDownloadSimulator.mockResolvedValue({ wasInstalled: false });
|
|
420
|
-
simServConfigSimulator.mockResolvedValue(true);
|
|
421
367
|
const errorMsg = new Error("runSimulator error");
|
|
422
368
|
simServRunSimulator.mockRejectedValueOnce(errorMsg);
|
|
423
369
|
|
|
@@ -436,8 +382,6 @@ describe("init action", () => {
|
|
|
436
382
|
simServCheckInstallRequirements.mockResolvedValue({ git: true, docker: true });
|
|
437
383
|
simServResetDockerContainers.mockResolvedValue(true);
|
|
438
384
|
simServResetDockerImages.mockResolvedValue(true);
|
|
439
|
-
simServDownloadSimulator.mockResolvedValue({ wasInstalled: false });
|
|
440
|
-
simServConfigSimulator.mockResolvedValue(true);
|
|
441
385
|
simServRunSimulator.mockResolvedValue(true);
|
|
442
386
|
simServWaitForSimulator.mockResolvedValue({
|
|
443
387
|
initialized: false,
|
|
@@ -455,15 +399,12 @@ describe("init action", () => {
|
|
|
455
399
|
test("catches and logs error if waitForSimulatorToBeReady throws an exception", async () => {
|
|
456
400
|
inquirerPrompt
|
|
457
401
|
.mockResolvedValueOnce({ confirmReset: true })
|
|
458
|
-
.mockResolvedValueOnce({ confirmDownload: true })
|
|
459
402
|
.mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
|
|
460
403
|
.mockResolvedValueOnce({ openai: "API_KEY1" });
|
|
461
404
|
|
|
462
|
-
simServCheckInstallRequirements.mockResolvedValue({
|
|
405
|
+
simServCheckInstallRequirements.mockResolvedValue({ docker: true });
|
|
463
406
|
simServResetDockerContainers.mockResolvedValue(true);
|
|
464
407
|
simServResetDockerImages.mockResolvedValue(true);
|
|
465
|
-
simServDownloadSimulator.mockResolvedValue({ wasInstalled: false });
|
|
466
|
-
simServConfigSimulator.mockResolvedValue(true);
|
|
467
408
|
simServRunSimulator.mockResolvedValue(true);
|
|
468
409
|
|
|
469
410
|
const errorMsg = new Error("Unexpected simulator error");
|
|
@@ -475,17 +416,17 @@ describe("init action", () => {
|
|
|
475
416
|
});
|
|
476
417
|
|
|
477
418
|
test("catches and logs error if openFrontend throws an exception", async () => {
|
|
419
|
+
const mockEnvContent = "FRONTEND_PORT=8080";
|
|
420
|
+
vi.mocked(fs.readFileSync).mockReturnValue(mockEnvContent);
|
|
421
|
+
|
|
478
422
|
inquirerPrompt
|
|
479
423
|
.mockResolvedValueOnce({ confirmReset: true })
|
|
480
|
-
.mockResolvedValueOnce({ confirmDownload: true })
|
|
481
424
|
.mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
|
|
482
425
|
.mockResolvedValueOnce({ openai: "API_KEY1" });
|
|
483
426
|
|
|
484
|
-
simServCheckInstallRequirements.mockResolvedValue({
|
|
427
|
+
simServCheckInstallRequirements.mockResolvedValue({ docker: true });
|
|
485
428
|
simServResetDockerContainers.mockResolvedValue(true);
|
|
486
429
|
simServResetDockerImages.mockResolvedValue(true);
|
|
487
|
-
simServDownloadSimulator.mockResolvedValue({ wasInstalled: false });
|
|
488
|
-
simServConfigSimulator.mockResolvedValue(true);
|
|
489
430
|
simServRunSimulator.mockResolvedValue(true);
|
|
490
431
|
simServWaitForSimulator.mockResolvedValue({ initialized: true });
|
|
491
432
|
simServDeleteAllValidators.mockResolvedValue(true);
|
|
@@ -12,8 +12,6 @@ describe("startAction - Additional Tests", () => {
|
|
|
12
12
|
const defaultOptions: StartActionOptions = {
|
|
13
13
|
resetValidators: false,
|
|
14
14
|
numValidators: 5,
|
|
15
|
-
branch: "main",
|
|
16
|
-
location: '',
|
|
17
15
|
headless: false,
|
|
18
16
|
resetDb: false
|
|
19
17
|
};
|
|
@@ -49,13 +47,10 @@ describe("startAction - Additional Tests", () => {
|
|
|
49
47
|
test("runs successfully with default options and keeps existing validators", async () => {
|
|
50
48
|
await startAction(defaultOptions, simulatorService);
|
|
51
49
|
|
|
52
|
-
expect(simulatorService.updateSimulator).toHaveBeenCalledWith("main");
|
|
53
50
|
expect(simulatorService.runSimulator).toHaveBeenCalled();
|
|
54
51
|
expect(simulatorService.waitForSimulatorToBeReady).toHaveBeenCalled();
|
|
55
52
|
|
|
56
53
|
expect(logSpy).toHaveBeenCalledWith("Starting GenLayer simulator keeping the existing validators");
|
|
57
|
-
expect(logSpy).toHaveBeenCalledWith("Updating GenLayer Simulator...");
|
|
58
|
-
expect(logSpy).toHaveBeenCalledWith("Running the GenLayer Simulator...");
|
|
59
54
|
expect(logSpy).toHaveBeenCalledWith("Simulator is running!");
|
|
60
55
|
expect(logSpy).toHaveBeenCalledWith("GenLayer simulator initialized successfully! Go to http://localhost:8080 in your browser to access it.");
|
|
61
56
|
|
|
@@ -65,26 +60,15 @@ describe("startAction - Additional Tests", () => {
|
|
|
65
60
|
test("runs successfully with custom options and keeps existing validators", async () => {
|
|
66
61
|
await startAction({...defaultOptions, headless: true, resetDb: true}, simulatorService);
|
|
67
62
|
|
|
68
|
-
expect(simulatorService.updateSimulator).toHaveBeenCalledWith("main");
|
|
69
63
|
expect(simulatorService.runSimulator).toHaveBeenCalled();
|
|
70
64
|
expect(simulatorService.waitForSimulatorToBeReady).toHaveBeenCalled();
|
|
71
65
|
|
|
72
66
|
expect(logSpy).toHaveBeenCalledWith("Starting GenLayer simulator keeping the existing validators");
|
|
73
|
-
|
|
74
|
-
expect(logSpy).toHaveBeenCalledWith("Running the GenLayer Simulator...");
|
|
67
|
+
|
|
75
68
|
expect(logSpy).toHaveBeenCalledWith("Simulator is running!");
|
|
76
69
|
expect(logSpy).toHaveBeenCalledWith("GenLayer simulator initialized successfully! ");
|
|
77
70
|
});
|
|
78
71
|
|
|
79
|
-
test("logs error and stops if updateSimulator fails", async () => {
|
|
80
|
-
const errorMsg = new Error("updateSimulator error");
|
|
81
|
-
(simulatorService.updateSimulator as Mock).mockRejectedValueOnce(errorMsg);
|
|
82
|
-
|
|
83
|
-
await startAction(defaultOptions, simulatorService);
|
|
84
|
-
|
|
85
|
-
expect(errorSpy).toHaveBeenCalledWith(errorMsg);
|
|
86
|
-
expect(simulatorService.runSimulator).not.toHaveBeenCalled();
|
|
87
|
-
});
|
|
88
72
|
|
|
89
73
|
test("logs error and stops if runSimulator fails", async () => {
|
|
90
74
|
const errorMsg = new Error("runSimulator error");
|
|
@@ -7,8 +7,6 @@ import simulatorService from '../../src/lib/services/simulator'
|
|
|
7
7
|
const openFrontendSpy = vi.spyOn(simulatorService, "openFrontend");
|
|
8
8
|
const defaultOptions = {
|
|
9
9
|
numValidators: "5",
|
|
10
|
-
branch: "main",
|
|
11
|
-
location: process.cwd(),
|
|
12
10
|
headless: false,
|
|
13
11
|
resetDb: false
|
|
14
12
|
}
|
|
@@ -52,21 +50,6 @@ describe("init command", () => {
|
|
|
52
50
|
expect(numValidatorsOption?.defaultValue).toBe("5");
|
|
53
51
|
});
|
|
54
52
|
|
|
55
|
-
test("option --branch is accepted", async () => {
|
|
56
|
-
expect(() => program.parse(["node", "test", "init", "--branch", "example"])).not.toThrow();
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test("option --branch default value is main", async () => {
|
|
60
|
-
const branchOption = getCommandOption(initCommand, "--branch");
|
|
61
|
-
expect(branchOption?.defaultValue).toBe("main");
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
test("option --location default value is user's current directory", async () => {
|
|
65
|
-
// Given // When
|
|
66
|
-
const locationOption = getCommandOption(initCommand, "--location");
|
|
67
|
-
expect(locationOption?.defaultValue).toBe(process.cwd());
|
|
68
|
-
});
|
|
69
|
-
|
|
70
53
|
|
|
71
54
|
test("random option is not accepted", async () => {
|
|
72
55
|
initCommand?.exitOverride();
|
|
@@ -10,8 +10,6 @@ const action = vi.fn();
|
|
|
10
10
|
const defaultOptions = {
|
|
11
11
|
resetValidators: false,
|
|
12
12
|
numValidators: "5",
|
|
13
|
-
branch: "main",
|
|
14
|
-
location: process.cwd(),
|
|
15
13
|
headless: false ,
|
|
16
14
|
resetDb: false
|
|
17
15
|
}
|
|
@@ -58,14 +56,6 @@ describe("up command", () => {
|
|
|
58
56
|
expect(numValidatorsOption?.defaultValue).toBe("5");
|
|
59
57
|
});
|
|
60
58
|
|
|
61
|
-
test("option --branch is accepted", async () => {
|
|
62
|
-
expect(() => program.parse(["node", "test", "up", "--branch", "development"])).not.toThrow();
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
test("option --branch default value is main", async () => {
|
|
66
|
-
const branchOption = getCommandOption(upCommand, "--branch");
|
|
67
|
-
expect(branchOption?.defaultValue).toBe("main");
|
|
68
|
-
});
|
|
69
59
|
|
|
70
60
|
test("unrecognized option is not accepted", async () => {
|
|
71
61
|
upCommand?.exitOverride();
|
|
@@ -91,15 +81,13 @@ describe("up command", () => {
|
|
|
91
81
|
"--reset-validators",
|
|
92
82
|
"--numValidators",
|
|
93
83
|
"10",
|
|
94
|
-
"--branch",
|
|
95
|
-
"development",
|
|
96
84
|
"--headless",
|
|
97
85
|
"true",
|
|
98
86
|
"--reset-db",
|
|
99
87
|
"true"
|
|
100
88
|
]);
|
|
101
89
|
expect(action).toHaveBeenCalledTimes(1);
|
|
102
|
-
expect(action).toHaveBeenCalledWith({...defaultOptions, headless: true,
|
|
90
|
+
expect(action).toHaveBeenCalledWith({...defaultOptions, headless: true, numValidators: '10', resetValidators: true, resetDb: true});
|
|
103
91
|
expect(openFrontendSpy).not.toHaveBeenCalled();
|
|
104
92
|
});
|
|
105
93
|
});
|
|
@@ -12,8 +12,6 @@ import {
|
|
|
12
12
|
import {
|
|
13
13
|
DOCKER_IMAGES_AND_CONTAINERS_NAME_PREFIX,
|
|
14
14
|
VERSION_REQUIREMENTS,
|
|
15
|
-
} from "../../src/lib/config/simulator";
|
|
16
|
-
import {
|
|
17
15
|
STARTING_TIMEOUT_ATTEMPTS,
|
|
18
16
|
DEFAULT_RUN_SIMULATOR_COMMAND,
|
|
19
17
|
} from "../../src/lib/config/simulator";
|
|
@@ -59,23 +57,14 @@ describe("SimulatorService - Basic Tests", () => {
|
|
|
59
57
|
vi.mocked(path.join).mockImplementation((...args) => args.join("/"));
|
|
60
58
|
});
|
|
61
59
|
|
|
62
|
-
test("should return the correct simulator location path", () => {
|
|
63
|
-
const expectedPath = "/mock/home/genlayer-simulator";
|
|
64
|
-
simulatorService.setSimulatorLocation("/mock/home/genlayer-simulator");
|
|
65
|
-
const simulatorLocation = simulatorService.getSimulatorLocation();
|
|
66
|
-
expect(simulatorLocation).toBe(expectedPath);
|
|
67
|
-
});
|
|
68
60
|
|
|
69
61
|
test("should read the correct frontend URL from .env config", () => {
|
|
70
|
-
const mockEnvFilePath = "/mock/home/genlayer-simulator/.env";
|
|
71
62
|
const mockEnvContent = "FRONTEND_PORT=8080";
|
|
72
63
|
const mockEnvConfig = { FRONTEND_PORT: "8080" };
|
|
73
64
|
vi.mocked(fs.readFileSync).mockReturnValue(mockEnvContent);
|
|
74
65
|
vi.mocked(dotenv.parse).mockReturnValue(mockEnvConfig);
|
|
75
|
-
simulatorService.setSimulatorLocation("/mock/home/genlayer-simulator");
|
|
76
66
|
const frontendUrl = simulatorService.getFrontendUrl();
|
|
77
67
|
expect(frontendUrl).toBe("http://localhost:8080");
|
|
78
|
-
expect(fs.readFileSync).toHaveBeenCalledWith(mockEnvFilePath, "utf8");
|
|
79
68
|
});
|
|
80
69
|
|
|
81
70
|
test("should check version requirements and return missing versions", async () => {
|
|
@@ -95,20 +84,6 @@ describe("SimulatorService - Basic Tests", () => {
|
|
|
95
84
|
await expect(simulatorService.checkVersion("14.0.0", "node")).rejects.toThrow();
|
|
96
85
|
});
|
|
97
86
|
|
|
98
|
-
test("should download simulator if not already installed", async () => {
|
|
99
|
-
const result = await simulatorService.downloadSimulator();
|
|
100
|
-
expect(result.wasInstalled).toBe(false);
|
|
101
|
-
expect(executeCommand).toHaveBeenCalled();
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
test("should skip download if simulator is already installed", async () => {
|
|
105
|
-
vi.mocked(executeCommand).mockRejectedValueOnce(new Error("Mocked command error"));
|
|
106
|
-
vi.spyOn(fs, "existsSync").mockReturnValue(true);
|
|
107
|
-
const result = await simulatorService.downloadSimulator();
|
|
108
|
-
expect(result.wasInstalled).toBe(true);
|
|
109
|
-
expect(executeCommand).toHaveBeenCalled();
|
|
110
|
-
expect(fs.existsSync).toHaveBeenCalled();
|
|
111
|
-
});
|
|
112
87
|
|
|
113
88
|
test("should return initialized true when simulator responds with OK (result.status = OK)", async () => {
|
|
114
89
|
vi.mocked(rpcClient.request).mockResolvedValueOnce({ result: {status: 'OK'} });
|
|
@@ -150,7 +125,7 @@ describe("SimulatorService - Basic Tests", () => {
|
|
|
150
125
|
stderr: "",
|
|
151
126
|
});
|
|
152
127
|
const result = await simulatorService.runSimulator();
|
|
153
|
-
const expectedCommand = DEFAULT_RUN_SIMULATOR_COMMAND(
|
|
128
|
+
const expectedCommand = DEFAULT_RUN_SIMULATOR_COMMAND(simulatorService.location, '');
|
|
154
129
|
expect(executeCommand).toHaveBeenCalledWith(expectedCommand);
|
|
155
130
|
expect(result).toEqual({ stdout: "Simulator started", stderr: "" });
|
|
156
131
|
});
|
|
@@ -163,11 +138,57 @@ describe("SimulatorService - Basic Tests", () => {
|
|
|
163
138
|
simulatorService.setComposeOptions(true)
|
|
164
139
|
const commandOption = simulatorService.getComposeOptions();
|
|
165
140
|
const result = await simulatorService.runSimulator();
|
|
166
|
-
const expectedCommand = DEFAULT_RUN_SIMULATOR_COMMAND(
|
|
141
|
+
const expectedCommand = DEFAULT_RUN_SIMULATOR_COMMAND(simulatorService.location, commandOption);
|
|
167
142
|
expect(executeCommand).toHaveBeenCalledWith(expectedCommand);
|
|
168
143
|
expect(result).toEqual({ stdout: "Simulator started", stderr: "" });
|
|
169
144
|
});
|
|
170
145
|
|
|
146
|
+
test("should create a backup of the .env file and add new config", () => {
|
|
147
|
+
const envFilePath = `/.env`;
|
|
148
|
+
const originalEnvContent = "KEY1=value1\nKEY2=value2";
|
|
149
|
+
const parsedEnvConfig = { KEY1: "value1", KEY2: "value2" };
|
|
150
|
+
const newConfig = { KEY3: "value3", KEY2: "newValue2" };
|
|
151
|
+
|
|
152
|
+
vi.mocked(fs.readFileSync).mockImplementation((filePath: any) => {
|
|
153
|
+
if (filePath === envFilePath) return originalEnvContent;
|
|
154
|
+
return "";
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
vi.mocked(dotenv.parse).mockReturnValue(parsedEnvConfig);
|
|
158
|
+
const writeFileSyncMock = vi.mocked(fs.writeFileSync);
|
|
159
|
+
|
|
160
|
+
simulatorService.addConfigToEnvFile(newConfig);
|
|
161
|
+
|
|
162
|
+
const expectedUpdatedContent = `KEY1=value1\nKEY2=newValue2\nKEY3=value3`;
|
|
163
|
+
expect(writeFileSyncMock).toHaveBeenCalledWith(envFilePath, expectedUpdatedContent);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test("should handle empty .env file and add new config", () => {
|
|
167
|
+
const envFilePath = `/.env`;
|
|
168
|
+
const newConfig = { NEW_KEY: "newValue" };
|
|
169
|
+
|
|
170
|
+
vi.mocked(fs.readFileSync).mockReturnValue("");
|
|
171
|
+
vi.mocked(dotenv.parse).mockReturnValue({});
|
|
172
|
+
const writeFileSyncMock = vi.mocked(fs.writeFileSync);
|
|
173
|
+
|
|
174
|
+
simulatorService.addConfigToEnvFile(newConfig);
|
|
175
|
+
|
|
176
|
+
expect(writeFileSyncMock).toHaveBeenCalledWith(`${envFilePath}.bak`, "");
|
|
177
|
+
const expectedUpdatedContent = `NEW_KEY=newValue`;
|
|
178
|
+
expect(writeFileSyncMock).toHaveBeenCalledWith(envFilePath, expectedUpdatedContent);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("should throw error when .env file does not exist", () => {
|
|
182
|
+
vi.mocked(fs.readFileSync).mockImplementation(() => {
|
|
183
|
+
throw new Error("File not found");
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
expect(() => simulatorService.addConfigToEnvFile({ KEY: "value" })).toThrow(
|
|
187
|
+
"File not found"
|
|
188
|
+
);
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
|
|
171
192
|
test("should open the frontend URL and return true", async () => {
|
|
172
193
|
vi.spyOn(simulatorService, "getFrontendUrl").mockReturnValue("http://localhost:8080");
|
|
173
194
|
const result = await simulatorService.openFrontend();
|
|
@@ -242,47 +263,14 @@ describe("SimulatorService - Basic Tests", () => {
|
|
|
242
263
|
expect(result).toEqual({ initialized: false, errorCode: "ERROR", errorMessage: fetchError.message });
|
|
243
264
|
});
|
|
244
265
|
|
|
245
|
-
test("should throw an error if executeCommand fails and simulator location does not exist", async () => {
|
|
246
|
-
const mockError = new Error("git clone failed");
|
|
247
|
-
vi.mocked(executeCommand).mockRejectedValueOnce(mockError);
|
|
248
|
-
vi.mocked(fs.existsSync).mockReturnValue(false);
|
|
249
|
-
await expect(simulatorService.downloadSimulator()).rejects.toThrow("git clone failed");
|
|
250
|
-
expect(executeCommand).toHaveBeenCalled();
|
|
251
|
-
expect(fs.existsSync).toHaveBeenCalledWith("/mock/home/genlayer-simulator");
|
|
252
|
-
});
|
|
253
|
-
|
|
254
266
|
test("should call executeCommand if docker ps command fails", async () => {
|
|
255
267
|
vi.mocked(checkCommand)
|
|
256
268
|
.mockResolvedValueOnce(undefined)
|
|
257
269
|
|
|
258
|
-
|
|
259
270
|
const result = await simulatorService.checkInstallRequirements();
|
|
260
271
|
expect(result.docker).toBe(true);
|
|
261
|
-
expect(result.git).toBe(true);
|
|
262
272
|
});
|
|
263
273
|
|
|
264
|
-
test("should update envConfig with newConfig values", () => {
|
|
265
|
-
const envFilePath = path.join("/mock/home/genlayer-simulator", ".env");
|
|
266
|
-
const originalEnvContent = "KEY1=value1\nKEY2=value2";
|
|
267
|
-
const envConfig = { KEY1: "value1", KEY2: "value2" };
|
|
268
|
-
const newConfig = { KEY2: "new_value2", KEY3: "value3" };
|
|
269
|
-
vi.mocked(fs.readFileSync)
|
|
270
|
-
.mockReturnValueOnce(originalEnvContent)
|
|
271
|
-
.mockReturnValueOnce(originalEnvContent);
|
|
272
|
-
vi.mocked(dotenv.parse).mockReturnValue(envConfig);
|
|
273
|
-
const writeFileSyncSpy = vi.spyOn(fs, "writeFileSync");
|
|
274
|
-
simulatorService["addConfigToEnvFile"](newConfig);
|
|
275
|
-
expect(envConfig).toEqual({
|
|
276
|
-
KEY1: "value1",
|
|
277
|
-
KEY2: "new_value2",
|
|
278
|
-
KEY3: "value3",
|
|
279
|
-
});
|
|
280
|
-
expect(writeFileSyncSpy).toHaveBeenCalledWith(`${envFilePath}.bak`, originalEnvContent);
|
|
281
|
-
expect(writeFileSyncSpy).toHaveBeenCalledWith(
|
|
282
|
-
envFilePath,
|
|
283
|
-
"KEY1=value1\nKEY2=new_value2\nKEY3=value3"
|
|
284
|
-
);
|
|
285
|
-
});
|
|
286
274
|
|
|
287
275
|
test("should return providers without errors", () => {
|
|
288
276
|
expect(simulatorService.getAiProvidersOptions(true)).toEqual(expect.any(Array));
|
|
@@ -314,8 +302,60 @@ describe("SimulatorService - Docker Tests", () => {
|
|
|
314
302
|
mockPing = vi.mocked(Docker.prototype.ping);
|
|
315
303
|
});
|
|
316
304
|
|
|
317
|
-
test("should
|
|
318
|
-
|
|
305
|
+
test("should handle errors during the execution of pullOllamaModel gracefully", async () => {
|
|
306
|
+
const mockExec = vi.fn();
|
|
307
|
+
const mockStart = vi.fn();
|
|
308
|
+
|
|
309
|
+
mockExec.mockResolvedValue({
|
|
310
|
+
start: mockStart,
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
const mockStream = {
|
|
314
|
+
on: vi.fn((event, callback) => {
|
|
315
|
+
if (event === "data") callback("Mock data chunk");
|
|
316
|
+
if (event === "error") callback(new Error("Mock error during stream"));
|
|
317
|
+
}),
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
mockStart.mockResolvedValue(mockStream);
|
|
321
|
+
|
|
322
|
+
mockGetContainer.mockReturnValueOnce({
|
|
323
|
+
exec: mockExec,
|
|
324
|
+
} as unknown as Docker.Container);
|
|
325
|
+
|
|
326
|
+
const result = await simulatorService.pullOllamaModel();
|
|
327
|
+
|
|
328
|
+
expect(result).toBe(false);
|
|
329
|
+
expect(mockGetContainer).toHaveBeenCalledWith("ollama");
|
|
330
|
+
expect(mockExec).toHaveBeenCalledWith({
|
|
331
|
+
Cmd: ["ollama", "pull", "llama3"],
|
|
332
|
+
AttachStdout: true,
|
|
333
|
+
AttachStderr: true,
|
|
334
|
+
});
|
|
335
|
+
expect(mockStart).toHaveBeenCalledWith({ Detach: false, Tty: false });
|
|
336
|
+
expect(mockStream.on).toHaveBeenCalledWith("error", expect.any(Function));
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
test("should successfully execute pullOllamaModel and return true", async () => {
|
|
340
|
+
const mockExec = vi.fn();
|
|
341
|
+
const mockStart = vi.fn();
|
|
342
|
+
|
|
343
|
+
mockExec.mockResolvedValue({
|
|
344
|
+
start: mockStart,
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
const mockStream = {
|
|
348
|
+
on: vi.fn((event, callback) => {
|
|
349
|
+
if (event === "data") callback("Mock data chunk");
|
|
350
|
+
if (event === "end") callback();
|
|
351
|
+
}),
|
|
352
|
+
};
|
|
353
|
+
|
|
354
|
+
mockStart.mockResolvedValue(mockStream);
|
|
355
|
+
|
|
356
|
+
mockGetContainer.mockReturnValueOnce({
|
|
357
|
+
exec: mockExec,
|
|
358
|
+
} as unknown as Docker.Container);
|
|
319
359
|
|
|
320
360
|
const result = await simulatorService.pullOllamaModel();
|
|
321
361
|
|
|
@@ -323,9 +363,15 @@ describe("SimulatorService - Docker Tests", () => {
|
|
|
323
363
|
expect(mockGetContainer).toHaveBeenCalledWith("ollama");
|
|
324
364
|
expect(mockExec).toHaveBeenCalledWith({
|
|
325
365
|
Cmd: ["ollama", "pull", "llama3"],
|
|
366
|
+
AttachStdout: true,
|
|
367
|
+
AttachStderr: true,
|
|
326
368
|
});
|
|
369
|
+
expect(mockStart).toHaveBeenCalledWith({ Detach: false, Tty: false });
|
|
370
|
+
expect(mockStream.on).toHaveBeenCalledWith("data", expect.any(Function));
|
|
371
|
+
expect(mockStream.on).toHaveBeenCalledWith("end", expect.any(Function));
|
|
327
372
|
});
|
|
328
373
|
|
|
374
|
+
|
|
329
375
|
test("should stop and remove Docker containers with the specified prefix", async () => {
|
|
330
376
|
const mockContainers = [
|
|
331
377
|
{
|
|
@@ -411,12 +457,12 @@ describe("SimulatorService - Docker Tests", () => {
|
|
|
411
457
|
expect(executeCommand).toHaveBeenCalledTimes(1);
|
|
412
458
|
});
|
|
413
459
|
|
|
414
|
-
test("should
|
|
460
|
+
test("should call execute command again to start docker service", async () => {
|
|
415
461
|
vi.mocked(checkCommand)
|
|
416
462
|
.mockResolvedValueOnce(undefined)
|
|
417
463
|
.mockRejectedValue(undefined);
|
|
418
|
-
mockPing.mockRejectedValueOnce("
|
|
419
|
-
await expect(simulatorService.checkInstallRequirements()).
|
|
464
|
+
mockPing.mockRejectedValueOnce("");
|
|
465
|
+
await expect(simulatorService.checkInstallRequirements()).resolves.toStrictEqual({ docker: true });
|
|
420
466
|
});
|
|
421
467
|
|
|
422
468
|
test("should warn the user when an update is available", async () => {
|
package/vitest.config.ts
CHANGED
|
@@ -5,7 +5,7 @@ export default defineConfig({
|
|
|
5
5
|
globals: true,
|
|
6
6
|
environment: 'jsdom',
|
|
7
7
|
coverage: {
|
|
8
|
-
exclude: [...configDefaults.exclude, '*.js', 'tests/**/*.ts', 'src/types'],
|
|
8
|
+
exclude: [...configDefaults.exclude, '*.js', 'tests/**/*.ts', 'src/types', 'scripts'],
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
});
|