From 03dd11d57efd2b069d3e0fc39c1f0cb9ba0fb044 Mon Sep 17 00:00:00 2001 From: ThatBen Date: Tue, 15 Apr 2025 14:01:44 +0200 Subject: [PATCH] wip --- src/__mocks__/handler.mocks.js | 6 ++ src/handlers/processControl.js | 11 ++- src/services/codexGlobals.js | 3 +- src/services/configService.test.js | 25 +++++- src/services/fsService.js | 1 - src/services/osService.js | 2 +- src/ui/mainMenu.js | 14 +-- src/ui/mainMenu.test.js | 132 ++++++++++++++++++++++++----- 8 files changed, 159 insertions(+), 35 deletions(-) diff --git a/src/__mocks__/handler.mocks.js b/src/__mocks__/handler.mocks.js index 5b8f8df..1780239 100644 --- a/src/__mocks__/handler.mocks.js +++ b/src/__mocks__/handler.mocks.js @@ -6,3 +6,9 @@ export const mockInstaller = { installCodex: vi.fn(), uninstallCodex: vi.fn(), }; + +export const mockProcessControl = { + getNumberOfCodexProcesses: vi.fn(), + stopCodexProcess: vi.fn(), + startCodexProcess: vi.fn(), +}; diff --git a/src/handlers/processControl.js b/src/handlers/processControl.js index cf4423a..8787991 100644 --- a/src/handlers/processControl.js +++ b/src/handlers/processControl.js @@ -27,12 +27,21 @@ export class ProcessControl { const pid = processes[0].pid; process.kill(pid, "SIGINT"); - await new Promise((resolve) => setTimeout(resolve, 2000)); + await this.sleep(); }; startCodexProcess = async () => { await this.saveCodexConfigFile(); await this.startCodex(); + await this.sleep(); + }; + + sleep = async () => { + return new Promise((resolve) => { + setTimeout(() => { + resolve(); + }, 5000); + }); }; saveCodexConfigFile = async () => { diff --git a/src/services/codexGlobals.js b/src/services/codexGlobals.js index d48fa6c..b5bd3dc 100644 --- a/src/services/codexGlobals.js +++ b/src/services/codexGlobals.js @@ -2,7 +2,8 @@ import axios from "axios"; export class CodexGlobals { getPublicIp = async () => { - return (await axios.get(`https://ip.codex.storage`)).data; + const result = (await axios.get(`https://ip.codex.storage`)).data; + return result.replaceAll("\n", ""); }; getTestnetSPRs = async () => { diff --git a/src/services/configService.test.js b/src/services/configService.test.js index 84a99eb..9e7be04 100644 --- a/src/services/configService.test.js +++ b/src/services/configService.test.js @@ -86,6 +86,28 @@ describe("ConfigService", () => { }); }); + describe("validateConfiguration", () => { + var configService; + var config; + + beforeEach(() => { + config = expectedDefaultConfig; + + configService = new ConfigService(mockFsService); + configService.config = config; + }); + + it("throws when codexExe is not set", () => { + config.codexExe = ""; + + expect(configService.validateConfiguration).toThrow( + "Missing config value: codexExe", + ); + }); + + + }); + describe("writecodexConfigFile", () => { const logsPath = "C:\\path\\codex.log"; var configService; @@ -95,6 +117,7 @@ describe("ConfigService", () => { mockFsService.isFile.mockReturnValue(false); configService = new ConfigService(mockFsService); + configService.validateConfiguration = vi.fn(); configService.getLogFilePath = vi.fn(); configService.getLogFilePath.mockReturnValue(logsPath); }); @@ -126,7 +149,7 @@ describe("ConfigService", () => { .map((v) => { return '"' + v + '"'; }) - .join(",")}]`, + .join(",")}]${newLine}`, ); }); }); diff --git a/src/services/fsService.js b/src/services/fsService.js index 9b44a9a..68f108d 100644 --- a/src/services/fsService.js +++ b/src/services/fsService.js @@ -64,7 +64,6 @@ export class FsService { }; writeFile = (filePath, content) => { - console.log("filepath: " + filePath); fs.writeFileSync(filePath, content); }; } diff --git a/src/services/osService.js b/src/services/osService.js index efc12ef..6e9502b 100644 --- a/src/services/osService.js +++ b/src/services/osService.js @@ -23,6 +23,6 @@ export class OsService { }; listProcesses = async () => { - await psList(); + return await psList(); }; } diff --git a/src/ui/mainMenu.js b/src/ui/mainMenu.js index fc28d3f..0ae5703 100644 --- a/src/ui/mainMenu.js +++ b/src/ui/mainMenu.js @@ -26,11 +26,11 @@ export class MainMenu { }; promptMainMenu = async () => { - if ((await this.processControl.getNumberOfCodexProcesses) > 0) { + if ((await this.processControl.getNumberOfCodexProcesses()) > 0) { await this.showRunningMenu(); } else { if (await this.installer.isCodexInstalled()) { - await this.showCodexNotRunningMenu(); + await this.showNotRunningMenu(); } else { await this.showNotInstalledMenu(); } @@ -52,14 +52,14 @@ export class MainMenu { showRunningMenu = async () => { await this.ui.askMultipleChoice("Codex is running", [ - { - label: "Stop Codex", - action: this.processControl.stopCodexProcess, - }, { label: "Open Codex app", action: this.openCodexApp, }, + { + label: "Stop Codex", + action: this.processControl.stopCodexProcess, + }, { label: "Exit", action: this.loop.stopLoop, @@ -71,7 +71,7 @@ export class MainMenu { console.log("todo!"); }; - showCodexNotRunningMenu = async () => { + showNotRunningMenu = async () => { await this.ui.askMultipleChoice("Codex is not running", [ { label: "Start Codex", diff --git a/src/ui/mainMenu.test.js b/src/ui/mainMenu.test.js index 73dfed7..c464c9e 100644 --- a/src/ui/mainMenu.test.js +++ b/src/ui/mainMenu.test.js @@ -2,6 +2,10 @@ import { describe, beforeEach, it, expect, vi } from "vitest"; import { MainMenu } from "./mainMenu.js"; import { mockUiService } from "../__mocks__/service.mocks.js"; import { mockInstallMenu, mockConfigMenu } from "../__mocks__/ui.mocks.js"; +import { + mockInstaller, + mockProcessControl, +} from "../__mocks__/handler.mocks.js"; import { mockMenuLoop } from "../__mocks__/utils.mocks.js"; describe("mainmenu", () => { @@ -15,42 +19,124 @@ describe("mainmenu", () => { mockMenuLoop, mockInstallMenu, mockConfigMenu, + mockInstaller, + mockProcessControl, ); }); - it("initializes the menu loop with the promptMainMenu function", () => { - expect(mockMenuLoop.initialize).toHaveBeenCalledWith( - mainmenu.promptMainMenu, - ); + describe("constructor", () => { + it("initializes the menu loop with the promptMainMenu function", () => { + expect(mockMenuLoop.initialize).toHaveBeenCalledWith( + mainmenu.promptMainMenu, + ); + }); }); - it("shows the logo", async () => { - await mainmenu.show(); + describe("show", () => { + it("shows the logo", async () => { + await mainmenu.show(); - expect(mockUiService.showLogo).toHaveBeenCalled(); + expect(mockUiService.showLogo).toHaveBeenCalled(); + }); + + it("starts the menu loop", async () => { + await mainmenu.show(); + + expect(mockMenuLoop.showLoop).toHaveBeenCalled(); + }); + + it("shows the exit message after the menu loop", async () => { + await mainmenu.show(); + + expect(mockUiService.showInfoMessage).toHaveBeenCalledWith("K-THX-BYE"); + }); }); - it("starts the menu loop", async () => { - await mainmenu.show(); + describe("promptMainMenu", () => { + beforeEach(() => { + mainmenu.showRunningMenu = vi.fn(); + mainmenu.showNotRunningMenu = vi.fn(); + mainmenu.showNotInstalledMenu = vi.fn(); + }); - expect(mockMenuLoop.showLoop).toHaveBeenCalled(); + it("shows running menu when number of codex processes is greater than zero", async () => { + mockProcessControl.getNumberOfCodexProcesses.mockResolvedValue(1); + + await mainmenu.promptMainMenu(); + + expect(mainmenu.showRunningMenu).toHaveBeenCalled(); + expect(mainmenu.showNotRunningMenu).not.toHaveBeenCalled(); + expect(mainmenu.showNotInstalledMenu).not.toHaveBeenCalled(); + }); + + it("shows not running menu when number of codex processes is zero and codex is installed", async () => { + mockProcessControl.getNumberOfCodexProcesses.mockResolvedValue(0); + mockInstaller.isCodexInstalled.mockResolvedValue(true); + + await mainmenu.promptMainMenu(); + + expect(mainmenu.showRunningMenu).not.toHaveBeenCalled(); + expect(mainmenu.showNotRunningMenu).toHaveBeenCalled(); + expect(mainmenu.showNotInstalledMenu).not.toHaveBeenCalled(); + }); + + it("shows not installed menu when number of codex processes is zero and codex is not installed", async () => { + mockProcessControl.getNumberOfCodexProcesses.mockResolvedValue(0); + mockInstaller.isCodexInstalled.mockResolvedValue(false); + + await mainmenu.promptMainMenu(); + + expect(mainmenu.showRunningMenu).not.toHaveBeenCalled(); + expect(mainmenu.showNotRunningMenu).not.toHaveBeenCalled(); + expect(mainmenu.showNotInstalledMenu).toHaveBeenCalled(); + }); }); - it("shows the exit message after the menu loop", async () => { - await mainmenu.show(); + describe("showNotInstalledMenu", () => { + it("shows a menu with options to install Codex or exit", async () => { + await mainmenu.showNotInstalledMenu(); - expect(mockUiService.showInfoMessage).toHaveBeenCalledWith("K-THX-BYE"); + expect(mockUiService.askMultipleChoice).toHaveBeenCalledWith( + "Codex is not installed", + [ + { label: "Install Codex", action: mockInstallMenu.show }, + { label: "Exit", action: mockMenuLoop.stopLoop }, + ], + ); + }); }); - it("prompts the main menu with multiple choices", async () => { - await mainmenu.promptMainMenu(); - expect(mockUiService.askMultipleChoice).toHaveBeenCalledWith( - "Select an option", - [ - { label: "Install/uninstall Codex", action: mockInstallMenu.show }, - { label: "Configure Codex", action: mockConfigMenu.show }, - { label: "Exit", action: mockMenuLoop.stopLoop }, - ], - ); + describe("showRunningMenu", () => { + it("shows a menu with options to stop Codex, open Codex app, or exit", async () => { + await mainmenu.showRunningMenu(); + + expect(mockUiService.askMultipleChoice).toHaveBeenCalledWith( + "Codex is running", + [ + { label: "Open Codex app", action: mainmenu.openCodexApp }, + { label: "Stop Codex", action: mockProcessControl.stopCodexProcess }, + { label: "Exit", action: mockMenuLoop.stopLoop }, + ], + ); + }); + }); + + describe("showNotRunningMenu", () => { + it("shows a menu with options to start Codex, configure, uninstall, or exit", async () => { + await mainmenu.showNotRunningMenu(); + + expect(mockUiService.askMultipleChoice).toHaveBeenCalledWith( + "Codex is not running", + [ + { + label: "Start Codex", + action: mockProcessControl.startCodexProcess, + }, + { label: "Edit Codex config", action: mockConfigMenu.show }, + { label: "Uninstall Codex", action: mockInstallMenu.show }, + { label: "Exit", action: mockMenuLoop.stopLoop }, + ], + ); + }); }); });