genlayer 0.18.0 → 0.18.2-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.
@@ -1,8 +1,8 @@
1
- import { describe, test, vi, beforeEach, afterEach, expect } from "vitest";
1
+ import {describe, test, vi, beforeEach, afterEach, expect} from "vitest";
2
2
  import inquirer from "inquirer";
3
- import { InitAction, InitActionOptions } from "../../src/commands/general/init";
4
- import { SimulatorService } from "../../src/lib/services/simulator";
5
- import { OllamaAction } from "../../src/commands/update/ollama";
3
+ import {InitAction, InitActionOptions} from "../../src/commands/general/init";
4
+ import {SimulatorService} from "../../src/lib/services/simulator";
5
+ import {OllamaAction} from "../../src/commands/update/ollama";
6
6
 
7
7
  describe("InitAction", () => {
8
8
  let initAction: InitAction;
@@ -22,7 +22,7 @@ describe("InitAction", () => {
22
22
  let getFrontendUrlSpy: ReturnType<typeof vi.spyOn>;
23
23
  let normalizeLocalnetVersionSpy: ReturnType<typeof vi.spyOn>;
24
24
 
25
- const defaultConfig = { defaultOllamaModel: "llama3" };
25
+ const defaultConfig = {defaultOllamaModel: "llama3"};
26
26
 
27
27
  const defaultOptions: InitActionOptions = {
28
28
  numValidators: 5,
@@ -44,19 +44,39 @@ describe("InitAction", () => {
44
44
  vi.spyOn(initAction as any, "logError").mockImplementation(() => {});
45
45
  vi.spyOn(initAction, "getConfig").mockReturnValue(defaultConfig);
46
46
  checkCliVersionSpy = vi.spyOn(SimulatorService.prototype, "checkCliVersion").mockResolvedValue(undefined);
47
- checkInstallRequirementsSpy = vi.spyOn(SimulatorService.prototype, "checkInstallRequirements").mockResolvedValue({ git: true, docker: true });
48
- checkVersionRequirementsSpy = vi.spyOn(SimulatorService.prototype, "checkVersionRequirements").mockResolvedValue({ node: "", docker: "" });
49
- resetDockerContainersSpy = vi.spyOn(SimulatorService.prototype, "resetDockerContainers").mockResolvedValue(undefined);
50
- resetDockerImagesSpy = vi.spyOn(SimulatorService.prototype, "resetDockerImages").mockResolvedValue(undefined);
47
+ checkInstallRequirementsSpy = vi
48
+ .spyOn(SimulatorService.prototype, "checkInstallRequirements")
49
+ .mockResolvedValue({git: true, docker: true});
50
+ checkVersionRequirementsSpy = vi
51
+ .spyOn(SimulatorService.prototype, "checkVersionRequirements")
52
+ .mockResolvedValue({node: "", docker: ""});
53
+ resetDockerContainersSpy = vi
54
+ .spyOn(SimulatorService.prototype, "resetDockerContainers")
55
+ .mockResolvedValue(undefined);
56
+ resetDockerImagesSpy = vi
57
+ .spyOn(SimulatorService.prototype, "resetDockerImages")
58
+ .mockResolvedValue(undefined);
51
59
  addConfigToEnvFileSpy = vi.spyOn(SimulatorService.prototype, "addConfigToEnvFile").mockResolvedValue();
52
- runSimulatorSpy = vi.spyOn(SimulatorService.prototype, "runSimulator").mockResolvedValue(undefined as any);
53
- waitForSimulatorSpy = vi.spyOn(SimulatorService.prototype, "waitForSimulatorToBeReady").mockResolvedValue({ initialized: true }) as any;
54
- deleteAllValidatorsSpy = vi.spyOn(SimulatorService.prototype, "deleteAllValidators").mockResolvedValue(undefined);
55
- createRandomValidatorsSpy = vi.spyOn(SimulatorService.prototype, "createRandomValidators").mockResolvedValue(undefined) as any;
60
+ runSimulatorSpy = vi
61
+ .spyOn(SimulatorService.prototype, "runSimulator")
62
+ .mockResolvedValue(undefined as any);
63
+ waitForSimulatorSpy = vi
64
+ .spyOn(SimulatorService.prototype, "waitForSimulatorToBeReady")
65
+ .mockResolvedValue({initialized: true}) as any;
66
+ deleteAllValidatorsSpy = vi
67
+ .spyOn(SimulatorService.prototype, "deleteAllValidators")
68
+ .mockResolvedValue(undefined);
69
+ createRandomValidatorsSpy = vi
70
+ .spyOn(SimulatorService.prototype, "createRandomValidators")
71
+ .mockResolvedValue(undefined) as any;
56
72
  cleanDatabaseSpy = vi.spyOn(SimulatorService.prototype, "cleanDatabase").mockResolvedValue(true);
57
73
  openFrontendSpy = vi.spyOn(SimulatorService.prototype, "openFrontend").mockResolvedValue(true);
58
- getFrontendUrlSpy = vi.spyOn(SimulatorService.prototype, "getFrontendUrl").mockReturnValue("http://localhost:8080");
59
- normalizeLocalnetVersionSpy = vi.spyOn(SimulatorService.prototype, "normalizeLocalnetVersion").mockImplementation((v: string) => v) as any;
74
+ getFrontendUrlSpy = vi
75
+ .spyOn(SimulatorService.prototype, "getFrontendUrl")
76
+ .mockReturnValue("http://localhost:8080");
77
+ normalizeLocalnetVersionSpy = vi
78
+ .spyOn(SimulatorService.prototype, "normalizeLocalnetVersion")
79
+ .mockImplementation((v: string) => v) as any;
60
80
  vi.spyOn(SimulatorService.prototype, "isLocalnetRunning").mockResolvedValue(false);
61
81
  });
62
82
 
@@ -67,64 +87,69 @@ describe("InitAction", () => {
67
87
  describe("Successful Execution", () => {
68
88
  test("should show combined confirmation message when localnet is running", async () => {
69
89
  vi.spyOn(SimulatorService.prototype, "isLocalnetRunning").mockResolvedValue(true);
70
-
90
+
71
91
  const confirmPromptSpy = vi.spyOn(initAction as any, "confirmPrompt").mockResolvedValue(undefined);
72
-
92
+
73
93
  inquirerPromptSpy
74
- .mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
75
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
76
-
94
+ .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
95
+ .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
96
+
77
97
  await initAction.execute(defaultOptions);
78
-
98
+
79
99
  expect(confirmPromptSpy).toHaveBeenCalledWith(
80
- "GenLayer Localnet is already running and this command is going to reset GenLayer docker images and containers, providers API Keys, and GenLayer database (accounts, transactions, validators and logs). Contract code (gpy files) will be kept. Do you want to continue?"
100
+ "GenLayer Localnet is already running and this command is going to reset GenLayer docker images and containers, providers API Keys, and GenLayer database (accounts, transactions, validators and logs). Contract code (gpy files) will be kept. Do you want to continue?",
81
101
  );
82
102
  });
83
-
103
+
84
104
  test("should show standard confirmation message when localnet is not running", async () => {
85
105
  vi.spyOn(SimulatorService.prototype, "isLocalnetRunning").mockResolvedValue(false);
86
-
106
+
87
107
  const confirmPromptSpy = vi.spyOn(initAction as any, "confirmPrompt").mockResolvedValue(undefined);
88
-
108
+
89
109
  inquirerPromptSpy
90
- .mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
91
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
92
-
110
+ .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
111
+ .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
112
+
93
113
  await initAction.execute(defaultOptions);
94
-
114
+
95
115
  expect(confirmPromptSpy).toHaveBeenCalledWith(
96
- "This command is going to reset GenLayer docker images and containers, providers API Keys, and GenLayer database (accounts, transactions, validators and logs). Contract code (gpy files) will be kept. Do you want to continue?"
116
+ "This command is going to reset GenLayer docker images and containers, providers API Keys, and GenLayer database (accounts, transactions, validators and logs). Contract code (gpy files) will be kept. Do you want to continue?",
97
117
  );
98
118
  });
99
-
119
+
100
120
  test("executes the full flow in non-headless mode", async () => {
101
121
  inquirerPromptSpy
102
- .mockResolvedValueOnce({ confirmAction: true })
103
- .mockResolvedValueOnce({ selectedLlmProviders: ["openai", "heuristai"] })
104
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" })
105
- .mockResolvedValueOnce({ heuristai: "API_KEY_HEURIST" });
122
+ .mockResolvedValueOnce({confirmAction: true})
123
+ .mockResolvedValueOnce({selectedLlmProviders: ["openai", "heuristai"]})
124
+ .mockResolvedValueOnce({openai: "API_KEY_OPENAI"})
125
+ .mockResolvedValueOnce({heuristai: "API_KEY_HEURIST"});
106
126
  await initAction.execute(defaultOptions);
107
127
  expect(checkCliVersionSpy).toHaveBeenCalled();
108
128
  expect(checkInstallRequirementsSpy).toHaveBeenCalled();
109
129
  expect(checkVersionRequirementsSpy).toHaveBeenCalled();
110
130
  expect(resetDockerContainersSpy).toHaveBeenCalled();
111
131
  expect(resetDockerImagesSpy).toHaveBeenCalled();
112
- expect(addConfigToEnvFileSpy).toHaveBeenCalledWith({ OPENAIKEY: "API_KEY_OPENAI", HEURISTAIAPIKEY: "API_KEY_HEURIST" });
113
- expect(addConfigToEnvFileSpy).toHaveBeenCalledWith({ LOCALNETVERSION: "v1.0.0" });
132
+ expect(addConfigToEnvFileSpy).toHaveBeenCalledWith({
133
+ OPENAIKEY: "API_KEY_OPENAI",
134
+ HEURISTAIAPIKEY: "API_KEY_HEURIST",
135
+ });
136
+ expect(addConfigToEnvFileSpy).toHaveBeenCalledWith({LOCALNETVERSION: "v1.0.0"});
114
137
  expect(runSimulatorSpy).toHaveBeenCalled();
115
138
  expect(waitForSimulatorSpy).toHaveBeenCalled();
116
139
  expect(deleteAllValidatorsSpy).toHaveBeenCalled();
117
140
  expect(createRandomValidatorsSpy).toHaveBeenCalledWith(5, ["openai", "heuristai"]);
118
141
  expect(getFrontendUrlSpy).toHaveBeenCalled();
119
142
  expect(openFrontendSpy).toHaveBeenCalled();
120
- expect((initAction as any).succeedSpinner).toHaveBeenCalledWith("GenLayer Localnet initialized successfully! Go to http://localhost:8080 in your browser to access it.");
143
+ expect((initAction as any).succeedSpinner).toHaveBeenCalledWith(
144
+ "GenLayer Localnet initialized successfully! Go to http://localhost:8080 in your browser to access it.",
145
+ );
121
146
  });
122
147
 
123
148
  test("executes correctly in headless mode with DB reset and 'ollama' selected", async () => {
124
149
  inquirerPromptSpy
125
- .mockResolvedValueOnce({ confirmAction: true })
126
- .mockResolvedValueOnce({ selectedLlmProviders: ["openai", "ollama"] })
127
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
150
+ .mockResolvedValueOnce({confirmAction: true})
151
+ .mockResolvedValueOnce({selectedLlmProviders: ["openai", "ollama"]})
152
+ .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
128
153
  const ollamaUpdateSpy = vi.spyOn(OllamaAction.prototype, "updateModel").mockResolvedValue(undefined);
129
154
  const headlessOptions: InitActionOptions = {
130
155
  numValidators: 5,
@@ -136,7 +161,9 @@ describe("InitAction", () => {
136
161
  await initAction.execute(headlessOptions);
137
162
  expect(cleanDatabaseSpy).toHaveBeenCalled();
138
163
  expect(openFrontendSpy).not.toHaveBeenCalled();
139
- expect((initAction as any).succeedSpinner).toHaveBeenCalledWith("GenLayer Localnet initialized successfully! ");
164
+ expect((initAction as any).succeedSpinner).toHaveBeenCalledWith(
165
+ "GenLayer Localnet initialized successfully! ",
166
+ );
140
167
  expect(ollamaUpdateSpy).toHaveBeenCalledWith("llama3");
141
168
  });
142
169
 
@@ -144,12 +171,12 @@ describe("InitAction", () => {
144
171
  const customVersion = "custom-v1";
145
172
  normalizeLocalnetVersionSpy.mockReturnValue(customVersion);
146
173
  inquirerPromptSpy
147
- .mockResolvedValueOnce({ confirmAction: true })
148
- .mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
149
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
150
- await initAction.execute({ ...defaultOptions, localnetVersion: customVersion });
174
+ .mockResolvedValueOnce({confirmAction: true})
175
+ .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
176
+ .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
177
+ await initAction.execute({...defaultOptions, localnetVersion: customVersion});
151
178
  expect(normalizeLocalnetVersionSpy).toHaveBeenCalledWith(customVersion);
152
- expect(addConfigToEnvFileSpy).toHaveBeenCalledWith({ LOCALNETVERSION: customVersion });
179
+ expect(addConfigToEnvFileSpy).toHaveBeenCalledWith({LOCALNETVERSION: customVersion});
153
180
  });
154
181
 
155
182
  test("should set defaultOllamaModel to 'llama3' if not provided in config", async () => {
@@ -157,21 +184,21 @@ describe("InitAction", () => {
157
184
  const writeConfigSpy = vi.spyOn(initAction, "writeConfig").mockImplementation(() => {});
158
185
  const ollamaUpdateSpy = vi.spyOn(OllamaAction.prototype, "updateModel").mockResolvedValue(undefined);
159
186
  inquirerPromptSpy
160
- .mockResolvedValueOnce({ confirmAction: true })
161
- .mockResolvedValueOnce({ selectedLlmProviders: ["ollama"] })
162
- .mockResolvedValueOnce({ ollama: "API_KEY_OLLAMA" });
187
+ .mockResolvedValueOnce({confirmAction: true})
188
+ .mockResolvedValueOnce({selectedLlmProviders: ["ollama"]})
189
+ .mockResolvedValueOnce({ollama: "API_KEY_OLLAMA"});
163
190
  await initAction.execute(defaultOptions);
164
191
  expect(writeConfigSpy).toHaveBeenCalledWith("defaultOllamaModel", "llama3");
165
192
  expect(ollamaUpdateSpy).toHaveBeenCalledWith("llama3");
166
193
  });
167
194
 
168
195
  test("validates API key input for configurable provider", async () => {
169
- inquirerPromptSpy.mockResolvedValueOnce({ confirmAction: true });
170
- inquirerPromptSpy.mockResolvedValueOnce({ selectedLlmProviders: ["openai"] });
196
+ inquirerPromptSpy.mockResolvedValueOnce({confirmAction: true});
197
+ inquirerPromptSpy.mockResolvedValueOnce({selectedLlmProviders: ["openai"]});
171
198
  let capturedQuestion: any;
172
199
  inquirerPromptSpy.mockImplementationOnce((questions: any) => {
173
200
  capturedQuestion = questions[0];
174
- return Promise.resolve({ openai: "dummy-key" });
201
+ return Promise.resolve({openai: "dummy-key"});
175
202
  });
176
203
  await initAction.execute(defaultOptions);
177
204
  expect(capturedQuestion).toBeDefined();
@@ -183,12 +210,12 @@ describe("InitAction", () => {
183
210
  test("validates LLM provider selection prompt", async () => {
184
211
  let capturedQuestion: any;
185
212
  inquirerPromptSpy
186
- .mockResolvedValueOnce({ confirmAction: true })
213
+ .mockResolvedValueOnce({confirmAction: true})
187
214
  .mockImplementationOnce((questions: any) => {
188
215
  capturedQuestion = questions[0];
189
- return Promise.resolve({ selectedLlmProviders: ["openai"] });
216
+ return Promise.resolve({selectedLlmProviders: ["openai"]});
190
217
  })
191
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
218
+ .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
192
219
  await initAction.execute(defaultOptions);
193
220
  expect(capturedQuestion.validate([])).toBe("You must choose at least one option.");
194
221
  expect(capturedQuestion.validate(["openai"])).toBe(true);
@@ -221,127 +248,171 @@ describe("InitAction", () => {
221
248
 
222
249
  describe("Error Handling", () => {
223
250
  test("fails if Docker is not installed", async () => {
224
- checkInstallRequirementsSpy.mockResolvedValue({ git: true, docker: false });
251
+ checkInstallRequirementsSpy.mockResolvedValue({git: true, docker: false});
225
252
  await initAction.execute(defaultOptions);
226
- expect((initAction as any).failSpinner).toHaveBeenCalledWith("Docker is not installed. Please install Docker and try again.\n");
253
+ expect((initAction as any).failSpinner).toHaveBeenCalledWith(
254
+ "Docker is not installed. Please install Docker and try again.\n",
255
+ );
227
256
  });
228
257
 
229
258
  test("fails if checkInstallRequirements throws an error", async () => {
230
259
  const error = new Error("Install error");
231
260
  checkInstallRequirementsSpy.mockRejectedValue(error);
232
261
  await initAction.execute(defaultOptions);
233
- expect((initAction as any).failSpinner).toHaveBeenCalledWith("An error occurred during initialization.", error);
262
+ expect((initAction as any).failSpinner).toHaveBeenCalledWith(
263
+ "An error occurred during initialization.",
264
+ error,
265
+ );
234
266
  });
235
267
 
236
268
  test("fails if version requirements are not met (both docker and node)", async () => {
237
269
  const version = "99.9.9";
238
- checkVersionRequirementsSpy.mockResolvedValue({ docker: version, node: version });
270
+ checkVersionRequirementsSpy.mockResolvedValue({docker: version, node: version});
239
271
  await initAction.execute(defaultOptions);
240
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(`Docker version ${version} or higher is required. Please update Docker and try again.\nNode version ${version} or higher is required. Please update Node and try again.\n`);
272
+ expect((initAction as any).failSpinner).toHaveBeenCalledWith(
273
+ `Docker version ${version} or higher is required. Please update Docker and try again.\nNode version ${version} or higher is required. Please update Node and try again.\n`,
274
+ );
241
275
  });
242
276
 
243
277
  test("fails if version requirement for docker is not met", async () => {
244
278
  const version = "99.9.9";
245
- checkVersionRequirementsSpy.mockResolvedValue({ docker: version });
279
+ checkVersionRequirementsSpy.mockResolvedValue({docker: version});
246
280
  await initAction.execute(defaultOptions);
247
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(`Docker version ${version} or higher is required. Please update Docker and try again.\n`);
281
+ expect((initAction as any).failSpinner).toHaveBeenCalledWith(
282
+ `Docker version ${version} or higher is required. Please update Docker and try again.\n`,
283
+ );
248
284
  });
249
285
 
250
286
  test("fails if version requirement for node is not met", async () => {
251
287
  const version = "99.9.9";
252
- checkVersionRequirementsSpy.mockResolvedValue({ node: version });
288
+ checkVersionRequirementsSpy.mockResolvedValue({node: version});
253
289
  await initAction.execute(defaultOptions);
254
- expect((initAction as any).failSpinner).toHaveBeenCalledWith(`Node version ${version} or higher is required. Please update Node and try again.\n`);
290
+ expect((initAction as any).failSpinner).toHaveBeenCalledWith(
291
+ `Node version ${version} or higher is required. Please update Node and try again.\n`,
292
+ );
255
293
  });
256
294
 
257
295
  test("aborts if user does not confirm reset action", async () => {
258
- inquirerPromptSpy.mockResolvedValueOnce({ confirmAction: false });
259
- await initAction.execute(defaultOptions)
296
+ inquirerPromptSpy.mockResolvedValueOnce({confirmAction: false});
297
+ await initAction.execute(defaultOptions);
260
298
  expect((initAction as any).logError).toHaveBeenCalledWith(`Operation aborted!`);
261
299
  });
262
300
 
263
301
  test("fails if resetDockerContainers throws an error", async () => {
264
- inquirerPromptSpy.mockResolvedValueOnce({ confirmAction: true });
302
+ inquirerPromptSpy.mockResolvedValueOnce({confirmAction: true});
265
303
  resetDockerContainersSpy.mockRejectedValue(new Error("Container reset error"));
266
304
  await initAction.execute(defaultOptions);
267
- expect((initAction as any).failSpinner).toHaveBeenCalledWith("An error occurred during initialization.", new Error("Container reset error"));
305
+ expect((initAction as any).failSpinner).toHaveBeenCalledWith(
306
+ "An error occurred during initialization.",
307
+ new Error("Container reset error"),
308
+ );
268
309
  });
269
310
 
270
311
  test("fails if runSimulator throws an error", async () => {
271
312
  inquirerPromptSpy
272
- .mockResolvedValueOnce({ confirmAction: true })
273
- .mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
274
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
313
+ .mockResolvedValueOnce({confirmAction: true})
314
+ .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
315
+ .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
275
316
  runSimulatorSpy.mockRejectedValue(new Error("Run simulator error"));
276
317
  await initAction.execute(defaultOptions);
277
- expect((initAction as any).failSpinner).toHaveBeenCalledWith("An error occurred during initialization.", new Error("Run simulator error"));
318
+ expect((initAction as any).failSpinner).toHaveBeenCalledWith(
319
+ "An error occurred during initialization.",
320
+ new Error("Run simulator error"),
321
+ );
278
322
  });
279
323
 
280
324
  test("fails if waitForSimulatorToBeReady returns ERROR code", async () => {
281
325
  inquirerPromptSpy
282
- .mockResolvedValueOnce({ confirmAction: true })
283
- .mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
284
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
285
- waitForSimulatorSpy.mockResolvedValue({ initialized: false, errorCode: "ERROR", errorMessage: "Initialization failed" });
326
+ .mockResolvedValueOnce({confirmAction: true})
327
+ .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
328
+ .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
329
+ waitForSimulatorSpy.mockResolvedValue({
330
+ initialized: false,
331
+ errorCode: "ERROR",
332
+ errorMessage: "Initialization failed",
333
+ });
286
334
  await initAction.execute(defaultOptions);
287
- expect((initAction as any).failSpinner).toHaveBeenCalledWith("Unable to initialize the GenLayer Localnet: Initialization failed");
335
+ expect((initAction as any).failSpinner).toHaveBeenCalledWith(
336
+ "Unable to initialize the GenLayer Localnet: Initialization failed",
337
+ );
288
338
  });
289
339
 
290
340
  test("fails if waitForSimulatorToBeReady returns TIMEOUT code", async () => {
291
341
  inquirerPromptSpy
292
- .mockResolvedValueOnce({ confirmAction: true })
293
- .mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
294
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
295
- waitForSimulatorSpy.mockResolvedValue({ initialized: false, errorCode: "TIMEOUT", errorMessage: "Timeout" });
342
+ .mockResolvedValueOnce({confirmAction: true})
343
+ .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
344
+ .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
345
+ waitForSimulatorSpy.mockResolvedValue({
346
+ initialized: false,
347
+ errorCode: "TIMEOUT",
348
+ errorMessage: "Timeout",
349
+ });
296
350
  await initAction.execute(defaultOptions);
297
- expect((initAction as any).failSpinner).toHaveBeenCalledWith("The localnet is taking too long to initialize. Please try again after the localnet is ready.");
351
+ expect((initAction as any).failSpinner).toHaveBeenCalledWith(
352
+ "The localnet is taking too long to initialize. Please try again after the localnet is ready.",
353
+ );
298
354
  });
299
355
 
300
356
  test("fails if deleteAllValidators throws an error", async () => {
301
357
  inquirerPromptSpy
302
- .mockResolvedValueOnce({ confirmAction: true })
303
- .mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
304
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
358
+ .mockResolvedValueOnce({confirmAction: true})
359
+ .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
360
+ .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
305
361
  deleteAllValidatorsSpy.mockRejectedValue(new Error("Validator deletion error"));
306
362
  await initAction.execute(defaultOptions);
307
- expect((initAction as any).failSpinner).toHaveBeenCalledWith("An error occurred during initialization.", expect.any(Error));
363
+ expect((initAction as any).failSpinner).toHaveBeenCalledWith(
364
+ "An error occurred during initialization.",
365
+ expect.any(Error),
366
+ );
308
367
  });
309
368
 
310
369
  test("fails if createRandomValidators throws an error", async () => {
311
370
  inquirerPromptSpy
312
- .mockResolvedValueOnce({ confirmAction: true })
313
- .mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
314
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
371
+ .mockResolvedValueOnce({confirmAction: true})
372
+ .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
373
+ .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
315
374
  createRandomValidatorsSpy.mockRejectedValue(new Error("Validator creation error"));
316
375
  await initAction.execute(defaultOptions);
317
- expect((initAction as any).failSpinner).toHaveBeenCalledWith("An error occurred during initialization.", Error("Validator creation error"));
376
+ expect((initAction as any).failSpinner).toHaveBeenCalledWith(
377
+ "An error occurred during initialization.",
378
+ Error("Validator creation error"),
379
+ );
318
380
  });
319
381
 
320
382
  test("fails if cleanDatabase throws an error when resetDb is true", async () => {
321
383
  inquirerPromptSpy
322
- .mockResolvedValueOnce({ confirmAction: true })
323
- .mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
324
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
384
+ .mockResolvedValueOnce({confirmAction: true})
385
+ .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
386
+ .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
325
387
  cleanDatabaseSpy.mockRejectedValue(new Error("Database error"));
326
- const optionsWithResetDb: InitActionOptions = { ...defaultOptions, resetDb: true };
388
+ const optionsWithResetDb: InitActionOptions = {...defaultOptions, resetDb: true};
327
389
  await initAction.execute(optionsWithResetDb);
328
- expect((initAction as any).failSpinner).toHaveBeenCalledWith("An error occurred during initialization.", new Error("Database error"));
390
+ expect((initAction as any).failSpinner).toHaveBeenCalledWith(
391
+ "An error occurred during initialization.",
392
+ new Error("Database error"),
393
+ );
329
394
  });
330
395
 
331
396
  test("fails if openFrontend throws an error", async () => {
332
397
  inquirerPromptSpy
333
- .mockResolvedValueOnce({ confirmAction: true })
334
- .mockResolvedValueOnce({ selectedLlmProviders: ["openai"] })
335
- .mockResolvedValueOnce({ openai: "API_KEY_OPENAI" });
398
+ .mockResolvedValueOnce({confirmAction: true})
399
+ .mockResolvedValueOnce({selectedLlmProviders: ["openai"]})
400
+ .mockResolvedValueOnce({openai: "API_KEY_OPENAI"});
336
401
  openFrontendSpy.mockRejectedValue(new Error("Frontend error"));
337
402
  await initAction.execute(defaultOptions);
338
- expect((initAction as any).failSpinner).toHaveBeenCalledWith("An error occurred during initialization.", new Error("Frontend error"));
403
+ expect((initAction as any).failSpinner).toHaveBeenCalledWith(
404
+ "An error occurred during initialization.",
405
+ new Error("Frontend error"),
406
+ );
339
407
  });
340
408
 
341
409
  test("catches and logs unexpected errors", async () => {
342
410
  inquirerPromptSpy.mockRejectedValueOnce(new Error("Unexpected prompt error"));
343
411
  await initAction.execute(defaultOptions);
344
- expect((initAction as any).failSpinner).toHaveBeenCalledWith("An error occurred during initialization.", new Error("Unexpected prompt error"));
412
+ expect((initAction as any).failSpinner).toHaveBeenCalledWith(
413
+ "An error occurred during initialization.",
414
+ new Error("Unexpected prompt error"),
415
+ );
345
416
  });
346
417
  });
347
- });
418
+ });
@@ -0,0 +1,199 @@
1
+ import {describe, test, vi, beforeEach, afterEach, expect} from "vitest";
2
+ import {NetworkActions} from "../../src/commands/network/setNetwork";
3
+ import {ConfigFileManager} from "../../src/lib/config/ConfigFileManager";
4
+ import inquirer from "inquirer";
5
+ import {localnet, studionet, testnetAsimov} from "genlayer-js/chains";
6
+
7
+ vi.mock("../../src/lib/config/ConfigFileManager");
8
+ vi.mock("inquirer");
9
+
10
+ describe("NetworkActions", () => {
11
+ let networkActions: NetworkActions;
12
+
13
+ beforeEach(() => {
14
+ networkActions = new NetworkActions();
15
+ vi.clearAllMocks();
16
+
17
+ vi.spyOn(networkActions as any, "succeedSpinner").mockImplementation(() => {});
18
+ vi.spyOn(networkActions as any, "failSpinner").mockImplementation(() => {});
19
+ vi.spyOn(networkActions as any, "writeConfig").mockImplementation(() => {});
20
+ });
21
+
22
+ afterEach(() => {
23
+ vi.restoreAllMocks();
24
+ });
25
+
26
+ test("setNetwork method sets network by valid name", async () => {
27
+ await networkActions.setNetwork(localnet.name);
28
+
29
+ expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", JSON.stringify(localnet));
30
+ expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
31
+ `Network successfully set to ${localnet.name}`,
32
+ );
33
+ });
34
+
35
+ test("setNetwork method sets network by valid alias", async () => {
36
+ await networkActions.setNetwork("localnet");
37
+
38
+ expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", JSON.stringify(localnet));
39
+ expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
40
+ `Network successfully set to ${localnet.name}`,
41
+ );
42
+ });
43
+
44
+ test("setNetwork method sets studionet by name", async () => {
45
+ await networkActions.setNetwork(studionet.name);
46
+
47
+ expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", JSON.stringify(studionet));
48
+ expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
49
+ `Network successfully set to ${studionet.name}`,
50
+ );
51
+ });
52
+
53
+ test("setNetwork method sets studionet by alias", async () => {
54
+ await networkActions.setNetwork("studionet");
55
+
56
+ expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", JSON.stringify(studionet));
57
+ expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
58
+ `Network successfully set to ${studionet.name}`,
59
+ );
60
+ });
61
+
62
+ test("setNetwork method sets testnet-asimov by name", async () => {
63
+ await networkActions.setNetwork(testnetAsimov.name);
64
+
65
+ expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", JSON.stringify(testnetAsimov));
66
+ expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
67
+ `Network successfully set to ${testnetAsimov.name}`,
68
+ );
69
+ });
70
+
71
+ test("setNetwork method sets testnet-asimov by alias", async () => {
72
+ await networkActions.setNetwork("testnet-asimov");
73
+
74
+ expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", JSON.stringify(testnetAsimov));
75
+ expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
76
+ `Network successfully set to ${testnetAsimov.name}`,
77
+ );
78
+ });
79
+
80
+ test("setNetwork method fails for invalid network name", async () => {
81
+ await networkActions.setNetwork("invalidNetwork");
82
+
83
+ expect(networkActions["failSpinner"]).toHaveBeenCalledWith("Network invalidNetwork not found");
84
+ expect(networkActions["writeConfig"]).not.toHaveBeenCalled();
85
+ expect(networkActions["succeedSpinner"]).not.toHaveBeenCalled();
86
+ });
87
+
88
+ test("setNetwork method fails for empty network name", async () => {
89
+ await networkActions.setNetwork("");
90
+
91
+ expect(networkActions["failSpinner"]).toHaveBeenCalledWith("Network not found");
92
+ expect(networkActions["writeConfig"]).not.toHaveBeenCalled();
93
+ expect(networkActions["succeedSpinner"]).not.toHaveBeenCalled();
94
+ });
95
+
96
+ test("setNetwork method prompts user when no network name provided", async () => {
97
+ const mockSelectedNetwork = {
98
+ name: localnet.name,
99
+ alias: "localnet",
100
+ value: localnet,
101
+ };
102
+
103
+ vi.mocked(inquirer.prompt).mockResolvedValue({
104
+ selectedNetwork: mockSelectedNetwork,
105
+ });
106
+
107
+ await networkActions.setNetwork();
108
+
109
+ expect(inquirer.prompt).toHaveBeenCalledWith([
110
+ {
111
+ type: "list",
112
+ name: "selectedNetwork",
113
+ message: "Select which network do you want to use:",
114
+ choices: [
115
+ {
116
+ name: localnet.name,
117
+ alias: "localnet",
118
+ value: localnet,
119
+ },
120
+ {
121
+ name: studionet.name,
122
+ alias: "studionet",
123
+ value: studionet,
124
+ },
125
+ {
126
+ name: testnetAsimov.name,
127
+ alias: "testnet-asimov",
128
+ value: testnetAsimov,
129
+ },
130
+ ],
131
+ },
132
+ ]);
133
+ expect(networkActions["writeConfig"]).toHaveBeenCalledWith(
134
+ "network",
135
+ JSON.stringify(mockSelectedNetwork),
136
+ );
137
+ expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
138
+ `Network successfully set to ${mockSelectedNetwork.name}`,
139
+ );
140
+ });
141
+
142
+ test("setNetwork method handles interactive selection of studionet", async () => {
143
+ const mockSelectedNetwork = {
144
+ name: studionet.name,
145
+ alias: "studionet",
146
+ value: studionet,
147
+ };
148
+
149
+ vi.mocked(inquirer.prompt).mockResolvedValue({
150
+ selectedNetwork: mockSelectedNetwork,
151
+ });
152
+
153
+ await networkActions.setNetwork();
154
+
155
+ expect(networkActions["writeConfig"]).toHaveBeenCalledWith(
156
+ "network",
157
+ JSON.stringify(mockSelectedNetwork),
158
+ );
159
+ expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
160
+ `Network successfully set to ${mockSelectedNetwork.name}`,
161
+ );
162
+ });
163
+
164
+ test("setNetwork method handles interactive selection of testnet-asimov", async () => {
165
+ const mockSelectedNetwork = {
166
+ name: testnetAsimov.name,
167
+ alias: "testnet-asimov",
168
+ value: testnetAsimov,
169
+ };
170
+
171
+ vi.mocked(inquirer.prompt).mockResolvedValue({
172
+ selectedNetwork: mockSelectedNetwork,
173
+ });
174
+
175
+ await networkActions.setNetwork();
176
+
177
+ expect(networkActions["writeConfig"]).toHaveBeenCalledWith(
178
+ "network",
179
+ JSON.stringify(mockSelectedNetwork),
180
+ );
181
+ expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
182
+ `Network successfully set to ${mockSelectedNetwork.name}`,
183
+ );
184
+ });
185
+
186
+ test("setNetwork method handles case-sensitive network names", async () => {
187
+ await networkActions.setNetwork("LOCALNET");
188
+
189
+ expect(networkActions["failSpinner"]).toHaveBeenCalledWith("Network LOCALNET not found");
190
+ expect(networkActions["writeConfig"]).not.toHaveBeenCalled();
191
+ });
192
+
193
+ test("setNetwork method handles partial network names", async () => {
194
+ await networkActions.setNetwork("local");
195
+
196
+ expect(networkActions["failSpinner"]).toHaveBeenCalledWith("Network local not found");
197
+ expect(networkActions["writeConfig"]).not.toHaveBeenCalled();
198
+ });
199
+ });