203 lines
5.8 KiB
TypeScript
203 lines
5.8 KiB
TypeScript
import { expect, test, describe, beforeEach, afterEach } from "vitest";
|
|
import {
|
|
existsSync,
|
|
mkdirSync,
|
|
rmSync,
|
|
writeFileSync,
|
|
realpathSync,
|
|
} from "node:fs";
|
|
import { homedir, tmpdir } from "node:os";
|
|
import path from "node:path";
|
|
|
|
import {
|
|
getConfigDir,
|
|
getMnemonicsDir,
|
|
getDataDir,
|
|
getWalletConfigPath,
|
|
resolveMnemonicFilePath,
|
|
} from "../../src/utils/paths";
|
|
|
|
describe("paths utilities", () => {
|
|
const originalConfigDir = process.env["XO_CONFIG_DIR"];
|
|
|
|
beforeEach(() => {
|
|
delete process.env["XO_CONFIG_DIR"];
|
|
});
|
|
|
|
afterEach(() => {
|
|
if (originalConfigDir === undefined) {
|
|
delete process.env["XO_CONFIG_DIR"];
|
|
} else {
|
|
process.env["XO_CONFIG_DIR"] = originalConfigDir;
|
|
}
|
|
});
|
|
|
|
describe("getConfigDir", () => {
|
|
test("returns path under ~/.config/xo-cli", () => {
|
|
const configDir = getConfigDir();
|
|
|
|
expect(configDir).toBe(path.join(homedir(), ".config", "xo-cli"));
|
|
});
|
|
|
|
test("creates the directory if it does not exist", () => {
|
|
const configDir = getConfigDir();
|
|
|
|
expect(existsSync(configDir)).toBe(true);
|
|
});
|
|
|
|
test("uses XO_CONFIG_DIR when configured", () => {
|
|
const customDir = path.join(tmpdir(), `xo-cli-config-test-${Date.now()}`);
|
|
process.env["XO_CONFIG_DIR"] = customDir;
|
|
|
|
try {
|
|
expect(getConfigDir()).toBe(customDir);
|
|
expect(getMnemonicsDir()).toBe(path.join(customDir, "mnemonics"));
|
|
expect(getDataDir()).toBe(path.join(customDir, "data"));
|
|
expect(getWalletConfigPath()).toBe(path.join(customDir, ".wallet"));
|
|
} finally {
|
|
rmSync(customDir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
|
|
test("uses the default when XO_CONFIG_DIR is empty", () => {
|
|
process.env["XO_CONFIG_DIR"] = "";
|
|
|
|
expect(getConfigDir()).toBe(path.join(homedir(), ".config", "xo-cli"));
|
|
});
|
|
});
|
|
|
|
describe("getMnemonicsDir", () => {
|
|
test("returns path under config dir", () => {
|
|
const mnemonicsDir = getMnemonicsDir();
|
|
|
|
expect(mnemonicsDir).toBe(
|
|
path.join(homedir(), ".config", "xo-cli", "mnemonics"),
|
|
);
|
|
});
|
|
|
|
test("creates the directory if it does not exist", () => {
|
|
const mnemonicsDir = getMnemonicsDir();
|
|
|
|
expect(existsSync(mnemonicsDir)).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("getDataDir", () => {
|
|
test("returns path under config dir", () => {
|
|
const dataDir = getDataDir();
|
|
|
|
expect(dataDir).toBe(path.join(homedir(), ".config", "xo-cli", "data"));
|
|
});
|
|
|
|
test("creates the directory if it does not exist", () => {
|
|
const dataDir = getDataDir();
|
|
|
|
expect(existsSync(dataDir)).toBe(true);
|
|
});
|
|
});
|
|
|
|
describe("getWalletConfigPath", () => {
|
|
test("returns .wallet file path under config dir", () => {
|
|
const walletConfigPath = getWalletConfigPath();
|
|
|
|
expect(walletConfigPath).toBe(
|
|
path.join(homedir(), ".config", "xo-cli", ".wallet"),
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("resolveMnemonicFilePath (global)", () => {
|
|
let tempDir: string;
|
|
|
|
beforeEach(() => {
|
|
tempDir = path.join(tmpdir(), `xo-cli-paths-test-${Date.now()}`);
|
|
mkdirSync(tempDir, { recursive: true });
|
|
});
|
|
|
|
afterEach(() => {
|
|
rmSync(tempDir, { recursive: true, force: true });
|
|
});
|
|
|
|
test("resolves absolute path when file exists", () => {
|
|
const filePath = path.join(tempDir, "mnemonic-test");
|
|
writeFileSync(filePath, "test");
|
|
|
|
const resolved = resolveMnemonicFilePath(filePath);
|
|
expect(resolved).toBe(filePath);
|
|
});
|
|
|
|
test("resolves path relative to cwd when file exists", () => {
|
|
const originalCwd = process.cwd();
|
|
process.chdir(tempDir);
|
|
|
|
try {
|
|
writeFileSync(path.join(tempDir, "mnemonic-cwd-test"), "test");
|
|
const resolved = resolveMnemonicFilePath("mnemonic-cwd-test");
|
|
|
|
// Due to some weird MacOS behavior we need to use realpathSync to get the correct path
|
|
// Basically, tmpDir() returns a symlink, but moving to that path puts us at `/private/${tmpDir()}`
|
|
const expectedPath = realpathSync(
|
|
path.join(tempDir, "mnemonic-cwd-test"),
|
|
);
|
|
|
|
// Compare to the expected path
|
|
expect(resolved).toBe(expectedPath);
|
|
} finally {
|
|
process.chdir(originalCwd);
|
|
}
|
|
});
|
|
|
|
test("resolves from global mnemonics dir when file exists there", () => {
|
|
process.env["XO_CONFIG_DIR"] = tempDir;
|
|
const mnemonicsDir = getMnemonicsDir();
|
|
const testFile = path.join(mnemonicsDir, "mnemonic-global-test");
|
|
|
|
try {
|
|
writeFileSync(testFile, "test");
|
|
const resolved = resolveMnemonicFilePath("mnemonic-global-test");
|
|
expect(resolved).toBe(testFile);
|
|
} finally {
|
|
if (existsSync(testFile)) {
|
|
rmSync(testFile);
|
|
}
|
|
}
|
|
});
|
|
|
|
test("throws when file not found anywhere", () => {
|
|
expect(() =>
|
|
resolveMnemonicFilePath("nonexistent-mnemonic-file-xyz"),
|
|
).toThrow(/Mnemonic file not found/);
|
|
});
|
|
|
|
test("does not resolve absolute path if file does not exist", () => {
|
|
const nonExistentPath = "/nonexistent/path/mnemonic-test";
|
|
expect(() => resolveMnemonicFilePath(nonExistentPath)).toThrow(
|
|
/Mnemonic file not found/,
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("path hierarchy", () => {
|
|
test("mnemonics dir is under config dir", () => {
|
|
const configDir = getConfigDir();
|
|
const mnemonicsDir = getMnemonicsDir();
|
|
|
|
expect(mnemonicsDir.startsWith(configDir)).toBe(true);
|
|
});
|
|
|
|
test("data dir is under config dir", () => {
|
|
const configDir = getConfigDir();
|
|
const dataDir = getDataDir();
|
|
|
|
expect(dataDir.startsWith(configDir)).toBe(true);
|
|
});
|
|
|
|
test("wallet config is under config dir", () => {
|
|
const configDir = getConfigDir();
|
|
const walletConfig = getWalletConfigPath();
|
|
|
|
expect(walletConfig.startsWith(configDir)).toBe(true);
|
|
});
|
|
});
|
|
});
|