mirror of
https://github.com/logos-storage/logos-storage-installer.git
synced 2026-01-22 07:13:09 +00:00
sets up mocks. rolls out menuloop
This commit is contained in:
parent
a9c94057e8
commit
1f694f7534
15
src/__mocks__/service.mocks.js
Normal file
15
src/__mocks__/service.mocks.js
Normal file
@ -0,0 +1,15 @@
|
||||
import { vi } from "vitest";
|
||||
|
||||
export const mockUiService = {
|
||||
showLogo: vi.fn(),
|
||||
showInfoMessage: vi.fn(),
|
||||
showErrorMessage: vi.fn(),
|
||||
askMultipleChoice: vi.fn(),
|
||||
askPrompt: vi.fn()
|
||||
};
|
||||
|
||||
export const mockConfigService = {
|
||||
get: vi.fn(),
|
||||
saveConfig: vi.fn(),
|
||||
loadConfig: vi.fn(),
|
||||
};
|
||||
9
src/__mocks__/ui.mocks.js
Normal file
9
src/__mocks__/ui.mocks.js
Normal file
@ -0,0 +1,9 @@
|
||||
import { vi } from "vitest";
|
||||
|
||||
export const mockInstallMenu = {
|
||||
show: vi.fn()
|
||||
};
|
||||
|
||||
export const mockConfigMenu = {
|
||||
show: vi.fn()
|
||||
};
|
||||
16
src/__mocks__/utils.mocks.js
Normal file
16
src/__mocks__/utils.mocks.js
Normal file
@ -0,0 +1,16 @@
|
||||
import { vi } from "vitest";
|
||||
|
||||
export const mockPathSelector = {
|
||||
show: vi.fn(),
|
||||
};
|
||||
|
||||
export const mockNumberSelector = {
|
||||
show: vi.fn(),
|
||||
};
|
||||
|
||||
export const mockMenuLoop = {
|
||||
initialize: vi.fn(),
|
||||
showOnce: vi.fn(),
|
||||
showLoop: vi.fn(),
|
||||
stopLoop: vi.fn(),
|
||||
};
|
||||
144
src/ui/configmenu.test.js
Normal file
144
src/ui/configmenu.test.js
Normal file
@ -0,0 +1,144 @@
|
||||
import { describe, beforeEach, it, expect, vi } from "vitest";
|
||||
import { ConfigMenu } from "./configmenu.js";
|
||||
import { mockUiService } from "../__mocks__/service.mocks.js";
|
||||
import { mockConfigService } from "../__mocks__/service.mocks.js";
|
||||
import { mockPathSelector, mockNumberSelector } from "../__mocks__/ui.mocks.js";
|
||||
|
||||
describe("ConfigMenu", () => {
|
||||
let configMenu;
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
mockConfigService.get.mockReturnValue({
|
||||
dataDir: "/data",
|
||||
logsDir: "/logs",
|
||||
storageQuota: 1024 * 1024 * 1024,
|
||||
ports: {
|
||||
discPort: 8090,
|
||||
listenPort: 8070,
|
||||
apiPort: 8080,
|
||||
}
|
||||
});
|
||||
|
||||
configMenu = new ConfigMenu(
|
||||
mockUiService,
|
||||
mockConfigService,
|
||||
mockPathSelector,
|
||||
mockNumberSelector
|
||||
);
|
||||
});
|
||||
|
||||
// it("displays the configuration menu", async () => {
|
||||
// configMenu.running = false; // Prevent infinite loop
|
||||
// await configMenu.show();
|
||||
|
||||
// expect(mockUiService.showInfoMessage).toHaveBeenCalledWith(
|
||||
// "Codex Configuration",
|
||||
// );
|
||||
// expect(mockUiService.askMultipleChoice).toHaveBeenCalledWith([
|
||||
// {
|
||||
// label: `Data path = "${mockConfigService.get().dataDir}"`,
|
||||
// action: configMenu.editDataDir,
|
||||
// },
|
||||
// {
|
||||
// label: `Logs path = "${mockConfigService.get().logsDir}"`,
|
||||
// action: configMenu.editLogsDir,
|
||||
// },
|
||||
// {
|
||||
// label: `Storage quota = 1Gb`,
|
||||
// action: configMenu.editStorageQuota,
|
||||
// },
|
||||
// {
|
||||
// label: `Discovery port = ${mockConfigService.get().ports.discPort}`,
|
||||
// action: configMenu.editDiscPort,
|
||||
// },
|
||||
// {
|
||||
// label: `P2P listen port = ${mockConfigService.get().ports.listenPort}`,
|
||||
// action: configMenu.editListenPort,
|
||||
// },
|
||||
// {
|
||||
// label: `API port = ${mockConfigService.get().ports.apiPort}`,
|
||||
// action: configMenu.editApiPort,
|
||||
// },
|
||||
// {
|
||||
// label: "Save changes and exit",
|
||||
// action: configMenu.saveChangesAndExit,
|
||||
// },
|
||||
// {
|
||||
// label: "Discard changes and exit",
|
||||
// action: configMenu.discardChangesAndExit,
|
||||
// }
|
||||
// ]);
|
||||
// });
|
||||
|
||||
// it("edits the logs directory", async () => {
|
||||
// mockPathSelector.show.mockResolvedValue("/new-logs");
|
||||
// await configMenu.editLogsDir();
|
||||
|
||||
// expect(mockPathSelector.show).toHaveBeenCalledWith("/logs", true);
|
||||
// expect(configMenu.config.logsDir).toEqual("/new-logs");
|
||||
// });
|
||||
|
||||
// it("edits the storage quota", async () => {
|
||||
// mockNumberSelector.show.mockResolvedValue(200 * 1024 * 1024);
|
||||
// await configMenu.editStorageQuota();
|
||||
|
||||
// expect(mockUiService.showInfoMessage).toHaveBeenCalledWith(
|
||||
// "You can use: 'GB' or 'gb', etc.",
|
||||
// );
|
||||
// expect(mockNumberSelector.show).toHaveBeenCalledWith(
|
||||
// 1024 * 1024 * 1024,
|
||||
// "Storage quota",
|
||||
// true,
|
||||
// );
|
||||
// expect(configMenu.config.storageQuota).toEqual(200 * 1024 * 1024);
|
||||
// });
|
||||
|
||||
// it("shows an error if storage quota is too small", async () => {
|
||||
// mockNumberSelector.show.mockResolvedValue(50 * 1024 * 1024);
|
||||
// await configMenu.editStorageQuota();
|
||||
|
||||
// expect(mockUiService.showErrorMessage).toHaveBeenCalledWith(
|
||||
// "Storage quote should be >= 100mb.",
|
||||
// );
|
||||
// expect(configMenu.config.storageQuota).toEqual(1024 * 1024 * 1024); // Unchanged
|
||||
// });
|
||||
|
||||
// it("edits the discovery port", async () => {
|
||||
// mockNumberSelector.show.mockResolvedValue(9000);
|
||||
// await configMenu.editDiscPort();
|
||||
|
||||
// expect(mockNumberSelector.show).toHaveBeenCalledWith(8090, "Discovery port", false);
|
||||
// expect(configMenu.config.ports.discPort).toEqual(9000);
|
||||
// });
|
||||
|
||||
// it("shows an error if port is out of range", async () => {
|
||||
// mockNumberSelector.show.mockResolvedValue(1000);
|
||||
// await configMenu.editDiscPort();
|
||||
|
||||
// expect(mockUiService.showErrorMessage).toHaveBeenCalledWith(
|
||||
// "Port should be between 1024 and 65535.",
|
||||
// );
|
||||
// expect(configMenu.config.ports.discPort).toEqual(8090); // Unchanged
|
||||
// });
|
||||
|
||||
// it("saves changes and exits", async () => {
|
||||
// await configMenu.saveChangesAndExit();
|
||||
|
||||
// expect(mockConfigService.saveConfig).toHaveBeenCalled();
|
||||
// expect(mockUiService.showInfoMessage).toHaveBeenCalledWith(
|
||||
// "Configuration changes saved.",
|
||||
// );
|
||||
// expect(configMenu.running).toEqual(false);
|
||||
// });
|
||||
|
||||
// it("discards changes and exits", async () => {
|
||||
// await configMenu.discardChangesAndExit();
|
||||
|
||||
// expect(mockConfigService.loadConfig).toHaveBeenCalled();
|
||||
// expect(mockUiService.showInfoMessage).toHaveBeenCalledWith(
|
||||
// "Changes discarded.",
|
||||
// );
|
||||
// expect(configMenu.running).toEqual(false);
|
||||
// });
|
||||
});
|
||||
@ -1,18 +1,17 @@
|
||||
export class MainMenu {
|
||||
constructor(uiService, installMenu, configMenu) {
|
||||
constructor(uiService, menuLoop, installMenu, configMenu) {
|
||||
this.ui = uiService;
|
||||
this.loop = menuLoop;
|
||||
this.installMenu = installMenu;
|
||||
this.configMenu = configMenu;
|
||||
this.running = true;
|
||||
|
||||
this.loop.initialize(this.promptMainMenu);
|
||||
}
|
||||
|
||||
show = async () => {
|
||||
this.ui.showLogo();
|
||||
this.ui.showInfoMessage("hello");
|
||||
|
||||
while (this.running) {
|
||||
await this.promptMainMenu();
|
||||
}
|
||||
await this.loop.showLoop();
|
||||
|
||||
this.ui.showInfoMessage("K-THX-BYE");
|
||||
};
|
||||
@ -29,12 +28,8 @@ export class MainMenu {
|
||||
},
|
||||
{
|
||||
label: "Exit",
|
||||
action: this.closeMainMenu,
|
||||
action: this.loop.stopLoop,
|
||||
},
|
||||
]);
|
||||
};
|
||||
|
||||
closeMainMenu = async () => {
|
||||
this.running = false;
|
||||
};
|
||||
}
|
||||
|
||||
@ -1,56 +1,49 @@
|
||||
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 { mockMenuLoop } from "../__mocks__/utils.mocks.js";
|
||||
|
||||
describe("mainmenu", () => {
|
||||
let mainmenu;
|
||||
const mockUiService = {
|
||||
showLogo: vi.fn(),
|
||||
showInfoMessage: vi.fn(),
|
||||
askMultipleChoice: vi.fn(),
|
||||
};
|
||||
const mockInstallMenu = {
|
||||
show: vi.fn(),
|
||||
};
|
||||
|
||||
const mockConfigMenu = {
|
||||
show: vi.fn(),
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
|
||||
mainmenu = new MainMenu(mockUiService, mockInstallMenu, mockConfigMenu);
|
||||
|
||||
// Presents test getting stuck in main loop.
|
||||
const originalPrompt = mainmenu.promptMainMenu;
|
||||
mainmenu.promptMainMenu = async () => {
|
||||
mainmenu.running = false;
|
||||
await originalPrompt();
|
||||
};
|
||||
mainmenu = new MainMenu(mockUiService, mockMenuLoop, mockInstallMenu, mockConfigMenu);
|
||||
});
|
||||
|
||||
it("shows the main menu", async () => {
|
||||
it("initializes the menu loop with the promptMainMenu function", () => {
|
||||
expect(mockMenuLoop.initialize).toHaveBeenCalledWith(mainmenu.promptMainMenu);
|
||||
});
|
||||
|
||||
it("shows the logo", async () => {
|
||||
await mainmenu.show();
|
||||
|
||||
expect(mockUiService.showLogo).toHaveBeenCalled();
|
||||
expect(mockUiService.showInfoMessage).toHaveBeenCalledWith("hello"); // example, delete this later.
|
||||
expect(mockUiService.showInfoMessage).toHaveBeenCalledWith("K-THX-BYE"); // example, delete this later.
|
||||
});
|
||||
|
||||
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("prompts the main menu with multiple choices", async () => {
|
||||
await mainmenu.promptMainMenu();
|
||||
expect(mockUiService.askMultipleChoice).toHaveBeenCalledWith(
|
||||
"Select an option",
|
||||
[
|
||||
{ label: "Install Codex", action: mockInstallMenu.show },
|
||||
{ label: "Configure Codex", action: mockConfigMenu.show },
|
||||
{ label: "Exit", action: mainmenu.closeMainMenu },
|
||||
{ label: "Exit", action: mockMenuLoop.stopLoop },
|
||||
],
|
||||
);
|
||||
});
|
||||
|
||||
it("sets running to false when closeMainMenu is called", async () => {
|
||||
mainmenu.running = true;
|
||||
|
||||
await mainmenu.closeMainMenu();
|
||||
|
||||
expect(mainmenu.running).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
20
src/utils/menuLoop.js
Normal file
20
src/utils/menuLoop.js
Normal file
@ -0,0 +1,20 @@
|
||||
export class MenuLoop {
|
||||
initialize = (menuPrompt) => {
|
||||
this.menuPrompt = menuPrompt;
|
||||
}
|
||||
|
||||
showOnce = async () => {
|
||||
await this.menuPrompt();
|
||||
}
|
||||
|
||||
showLoop = async () => {
|
||||
this.running = true;
|
||||
while (this.running) {
|
||||
await this.menuPrompt();
|
||||
}
|
||||
}
|
||||
|
||||
stopLoop = () => {
|
||||
this.running = false;
|
||||
}
|
||||
}
|
||||
42
src/utils/menuLoop.test.js
Normal file
42
src/utils/menuLoop.test.js
Normal file
@ -0,0 +1,42 @@
|
||||
import { describe, beforeEach, it, expect, vi } from "vitest";
|
||||
import { MenuLoop } from "./menuLoop.js";
|
||||
|
||||
describe("MenuLoop", () => {
|
||||
let menuLoop;
|
||||
const mockPrompt = vi.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
menuLoop = new MenuLoop();
|
||||
menuLoop.initialize(mockPrompt);
|
||||
});
|
||||
|
||||
it("can show menu once", async () => {
|
||||
await menuLoop.showOnce();
|
||||
expect(mockPrompt).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("can stop the menu loop", async () => {
|
||||
mockPrompt.mockImplementation(() => {
|
||||
menuLoop.stopLoop();
|
||||
});
|
||||
await menuLoop.showLoop();
|
||||
|
||||
expect(mockPrompt).toHaveBeenCalledTimes(1);
|
||||
expect(menuLoop.running).toBe(false);
|
||||
});
|
||||
|
||||
it("can run menu in a loop", async () => {
|
||||
let calls = 0;
|
||||
mockPrompt.mockImplementation(() => {
|
||||
calls++;
|
||||
if (calls >= 3) {
|
||||
menuLoop.stopLoop();
|
||||
}
|
||||
});
|
||||
|
||||
await menuLoop.showLoop();
|
||||
|
||||
expect(mockPrompt).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
});
|
||||
@ -16,7 +16,7 @@ describe("number selector", () => {
|
||||
});
|
||||
|
||||
it("shows the prompt", async () => {
|
||||
await numberSelector.showNumberSelector(0, prompt, false);
|
||||
await numberSelector.show(0, prompt, false);
|
||||
|
||||
expect(mockUiService.askPrompt).toHaveBeenCalledWith(prompt);
|
||||
});
|
||||
@ -24,7 +24,7 @@ describe("number selector", () => {
|
||||
it("returns a number given valid input", async () => {
|
||||
mockUiService.askPrompt.mockResolvedValue("123");
|
||||
|
||||
const number = await numberSelector.showNumberSelector(0, prompt, false);
|
||||
const number = await numberSelector.show(0, prompt, false);
|
||||
|
||||
expect(number).toEqual(123);
|
||||
});
|
||||
@ -34,7 +34,7 @@ describe("number selector", () => {
|
||||
|
||||
mockUiService.askPrompt.mockResolvedValue("what?!");
|
||||
|
||||
const number = await numberSelector.showNumberSelector(
|
||||
const number = await numberSelector.show(
|
||||
currentValue,
|
||||
prompt,
|
||||
false,
|
||||
@ -45,7 +45,7 @@ describe("number selector", () => {
|
||||
|
||||
async function run(input) {
|
||||
mockUiService.askPrompt.mockResolvedValue(input);
|
||||
return await numberSelector.showNumberSelector(0, prompt, true);
|
||||
return await numberSelector.show(0, prompt, true);
|
||||
}
|
||||
|
||||
it("allows for metric postfixes (k)", async () => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user