diff --git a/src/__mocks__/service.mocks.js b/src/__mocks__/service.mocks.js index 2bf8515..14b1d81 100644 --- a/src/__mocks__/service.mocks.js +++ b/src/__mocks__/service.mocks.js @@ -68,4 +68,6 @@ export const mockMarketplaceSetup = { export const mockDataService = { upload: vi.fn(), download: vi.fn(), + debugInfo: vi.fn(), + localData: vi.fn(), }; diff --git a/src/__mocks__/ui.mocks.js b/src/__mocks__/ui.mocks.js index 4a5be0c..b63bcb8 100644 --- a/src/__mocks__/ui.mocks.js +++ b/src/__mocks__/ui.mocks.js @@ -11,4 +11,9 @@ export const mockConfigMenu = { export const mockDataMenu = { performUpload: vi.fn(), performDownload: vi.fn(), + showLocalData: vi.fn(), +}; + +export const mockNodeStatusMenu = { + showNodeStatus: vi.fn(), }; diff --git a/src/main.js b/src/main.js index 5d98f36..a910904 100644 --- a/src/main.js +++ b/src/main.js @@ -152,7 +152,11 @@ export async function main() { ); const dataService = new DataService(configService); const dataMenu = new DataMenu(uiService, fsService, dataService); - const nodeStatusMenu = new NodeStatusMenu(uiService, dataService, new MenuLoop()); + const nodeStatusMenu = new NodeStatusMenu( + uiService, + dataService, + new MenuLoop(), + ); const mainMenu = new MainMenu( uiService, new MenuLoop(), @@ -162,7 +166,7 @@ export async function main() { processControl, codexApp, dataMenu, - nodeStatusMenu + nodeStatusMenu, ); await mainMenu.show(); diff --git a/src/services/configService.js b/src/services/configService.js index d17016b..471711d 100644 --- a/src/services/configService.js +++ b/src/services/configService.js @@ -60,7 +60,6 @@ export class ConfigService { this.config = defaultConfig; this.saveConfig(); } - } } catch (error) { console.error( diff --git a/src/ui/dataMenu.js b/src/ui/dataMenu.js index 679f5db..6032a6a 100644 --- a/src/ui/dataMenu.js +++ b/src/ui/dataMenu.js @@ -1,5 +1,3 @@ -import chalk from "chalk"; - export class DataMenu { constructor(uiService, fsService, dataService) { this.ui = uiService; @@ -63,12 +61,12 @@ export class DataMenu { const fileSize = (datasetSize / 1024).toFixed(2); this.ui.showInfoMessage( - `${chalk.cyan("File")} ${index + 1} of ${filesData.content.length}\n\n` + - `${chalk.cyan("Filename:")} ${filename}\n` + - `${chalk.cyan("CID:")} ${cid}\n` + - `${chalk.cyan("Size:")} ${fileSize} KB\n` + - `${chalk.cyan("MIME Type:")} ${mimetype}\n` + - `${chalk.cyan("Protected:")} ${isProtected ? chalk.green("Yes") : chalk.red("No")}`, + `File ${index + 1} of ${filesData.content.length}\n\n` + + `Filename: ${filename}\n` + + `CID: ${cid}\n` + + `Size: ${fileSize} KB\n` + + `MIME Type: ${mimetype}\n` + + `Protected: ${isProtected ? "Yes" : "No"}`, ); }); } else { diff --git a/src/ui/dataMenu.test.js b/src/ui/dataMenu.test.js index df60d71..9be70a9 100644 --- a/src/ui/dataMenu.test.js +++ b/src/ui/dataMenu.test.js @@ -120,4 +120,95 @@ describe("DataMenu", () => { ); }); }); + + describe("showLocalData", () => { + beforeEach(() => { + dataMenu.displayLocalData = vi.fn(); + }); + + it("calls localData on dataService", async () => { + await dataMenu.showLocalData(); + + expect(mockDataService.localData).toHaveBeenCalled(); + }); + + it("passes localData to displayLocalData", async () => { + const someData = "yes"; + + mockDataService.localData.mockResolvedValue(someData); + + await dataMenu.showLocalData(); + + expect(dataMenu.displayLocalData).toHaveBeenCalledWith(someData); + }); + + it("shows an error message when localData raises", async () => { + const error = "Omg error!"; + mockDataService.localData.mockRejectedValue(new Error(error)); + + await dataMenu.showLocalData(); + + expect(dataMenu.displayLocalData).not.toHaveBeenCalled(); + expect(mockUiService.showErrorMessage).toHaveBeenCalledWith( + "Failed to fetch local data: Error: " + error, + ); + }); + }); + + describe("displayLocalData", () => { + const cid = "testCid"; + const datasetSize = 2048; + var isProtected = true; + const filename = "filename.test"; + const mimetype = "test"; + var fileData = {}; + + beforeEach(() => { + fileData = { + content: [ + { + cid: cid, + manifest: { + datasetSize, + protected: isProtected, + filename, + mimetype, + }, + }, + ], + }; + }); + + it("shows no datasets when content is undefined", () => { + fileData.content = undefined; + + dataMenu.displayLocalData(fileData); + + expect(mockUiService.showInfoMessage).toHaveBeenCalledWith( + "Node contains no datasets.", + ); + }); + + it("shows no datasets when content is empty array", () => { + fileData.content = []; + dataMenu.displayLocalData(fileData); + + expect(mockUiService.showInfoMessage).toHaveBeenCalledWith( + "Node contains no datasets.", + ); + }); + + it("shows details for each entry (protected)", () => { + dataMenu.displayLocalData(fileData); + + expect(mockUiService.showInfoMessage).toHaveBeenCalledWith( + `File 1 of 1\n\n` + + `Filename: ${filename}\n` + + `CID: ${cid}\n` + + `Size: ${(datasetSize / 1024).toFixed(2)} KB\n` + + `MIME Type: ${mimetype}\n` + + `Protected: Yes`, + ); + }); + }); }); diff --git a/src/ui/mainMenu.test.js b/src/ui/mainMenu.test.js index 7b9c6f8..bf4b3b3 100644 --- a/src/ui/mainMenu.test.js +++ b/src/ui/mainMenu.test.js @@ -5,6 +5,7 @@ import { mockInstallMenu, mockConfigMenu, mockDataMenu, + mockNodeStatusMenu, } from "../__mocks__/ui.mocks.js"; import { mockInstaller, @@ -27,6 +28,7 @@ describe("mainmenu", () => { mockProcessControl, mockCodexApp, mockDataMenu, + mockNodeStatusMenu, ); }); @@ -115,8 +117,13 @@ describe("mainmenu", () => { [ { label: "Open Codex app", action: mockCodexApp.openCodexApp }, { label: "Stop Codex", action: mainmenu.stopCodex }, + { + label: "Show node status", + action: mockNodeStatusMenu.showNodeStatus, + }, { label: "Upload a file", action: mockDataMenu.performUpload }, { label: "Download a file", action: mockDataMenu.performDownload }, + { label: "Show local data", action: mockDataMenu.showLocalData }, { label: "Exit (Codex keeps running)", action: mockMenuLoop.stopLoop,