mirror of
https://github.com/AikidoSec/safe-chain.git
synced 2026-05-26 12:10:49 +00:00
Mock filesystem in configFile.spec.js
This commit is contained in:
parent
5304a7744a
commit
1e7cd74364
2 changed files with 71 additions and 36 deletions
|
|
@ -5,7 +5,10 @@ import { ui } from "../environment/userInteraction.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} SafeChainConfig
|
* @typedef {Object} SafeChainConfig
|
||||||
* @property {any} scanTimeout // This should be a number
|
*
|
||||||
|
* This should be a number, but can be anything because it is user-input.
|
||||||
|
* We cannot trust the input and should add the necessary validations.
|
||||||
|
* @property {any} scanTimeout
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,32 @@
|
||||||
import { describe, it, beforeEach, afterEach } from "node:test";
|
import { describe, it, beforeEach, afterEach, mock } from "node:test";
|
||||||
import assert from "node:assert";
|
import assert from "node:assert";
|
||||||
import { getScanTimeout } from "./configFile.js";
|
|
||||||
import fs from "fs";
|
|
||||||
import path from "path";
|
|
||||||
import os from "os";
|
|
||||||
|
|
||||||
describe("getScanTimeout", () => {
|
describe("getScanTimeout", () => {
|
||||||
let originalEnv;
|
let originalEnv;
|
||||||
let aikidoDir;
|
let fsMock;
|
||||||
let configPath;
|
let getScanTimeout;
|
||||||
let configBackupPath;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(async () => {
|
||||||
// Save original environment
|
// Save original environment
|
||||||
originalEnv = process.env.AIKIDO_SCAN_TIMEOUT_MS;
|
originalEnv = process.env.AIKIDO_SCAN_TIMEOUT_MS;
|
||||||
|
|
||||||
// Use the actual .aikido directory
|
// Mock fs module
|
||||||
aikidoDir = path.join(os.homedir(), ".aikido");
|
fsMock = {
|
||||||
configPath = path.join(aikidoDir, "config.json");
|
existsSync: mock.fn(() => false),
|
||||||
configBackupPath = path.join(aikidoDir, "config.json.backup");
|
readFileSync: mock.fn(() => "{}"),
|
||||||
|
writeFileSync: mock.fn(),
|
||||||
|
mkdirSync: mock.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
// Backup existing config if it exists
|
mock.module("fs", {
|
||||||
if (fs.existsSync(configPath)) {
|
namedExports: fsMock,
|
||||||
fs.copyFileSync(configPath, configBackupPath);
|
});
|
||||||
}
|
|
||||||
|
// Re-import the module to get the mocked version
|
||||||
|
const configFileModule = await import(
|
||||||
|
`./configFile.js?update=${Date.now()}`
|
||||||
|
);
|
||||||
|
getScanTimeout = configFileModule.getScanTimeout;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|
@ -34,20 +37,14 @@ describe("getScanTimeout", () => {
|
||||||
delete process.env.AIKIDO_SCAN_TIMEOUT_MS;
|
delete process.env.AIKIDO_SCAN_TIMEOUT_MS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore original config file
|
// Reset all mocks
|
||||||
if (fs.existsSync(configBackupPath)) {
|
mock.restoreAll();
|
||||||
fs.copyFileSync(configBackupPath, configPath);
|
|
||||||
fs.unlinkSync(configBackupPath);
|
|
||||||
} else if (fs.existsSync(configPath)) {
|
|
||||||
fs.unlinkSync(configPath);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return default timeout of 10000ms when no config or env var is set", () => {
|
it("should return default timeout of 10000ms when no config or env var is set", () => {
|
||||||
delete process.env.AIKIDO_SCAN_TIMEOUT_MS;
|
delete process.env.AIKIDO_SCAN_TIMEOUT_MS;
|
||||||
if (fs.existsSync(configPath)) {
|
// Mock: config file doesn't exist
|
||||||
fs.unlinkSync(configPath);
|
fsMock.existsSync.mock.mockImplementation(() => false);
|
||||||
}
|
|
||||||
|
|
||||||
const timeout = getScanTimeout();
|
const timeout = getScanTimeout();
|
||||||
|
|
||||||
|
|
@ -56,7 +53,11 @@ describe("getScanTimeout", () => {
|
||||||
|
|
||||||
it("should return timeout from config file when set", () => {
|
it("should return timeout from config file when set", () => {
|
||||||
delete process.env.AIKIDO_SCAN_TIMEOUT_MS;
|
delete process.env.AIKIDO_SCAN_TIMEOUT_MS;
|
||||||
fs.writeFileSync(configPath, JSON.stringify({ scanTimeout: 5000 }));
|
// Mock: config file exists with scanTimeout: 5000
|
||||||
|
fsMock.existsSync.mock.mockImplementation(() => true);
|
||||||
|
fsMock.readFileSync.mock.mockImplementation(() =>
|
||||||
|
JSON.stringify({ scanTimeout: 5000 })
|
||||||
|
);
|
||||||
|
|
||||||
const timeout = getScanTimeout();
|
const timeout = getScanTimeout();
|
||||||
|
|
||||||
|
|
@ -65,7 +66,11 @@ describe("getScanTimeout", () => {
|
||||||
|
|
||||||
it("should prioritize environment variable over config file", () => {
|
it("should prioritize environment variable over config file", () => {
|
||||||
process.env.AIKIDO_SCAN_TIMEOUT_MS = "20000";
|
process.env.AIKIDO_SCAN_TIMEOUT_MS = "20000";
|
||||||
fs.writeFileSync(configPath, JSON.stringify({ scanTimeout: 5000 }));
|
// Mock: config file exists with scanTimeout: 5000
|
||||||
|
fsMock.existsSync.mock.mockImplementation(() => true);
|
||||||
|
fsMock.readFileSync.mock.mockImplementation(() =>
|
||||||
|
JSON.stringify({ scanTimeout: 5000 })
|
||||||
|
);
|
||||||
|
|
||||||
const timeout = getScanTimeout();
|
const timeout = getScanTimeout();
|
||||||
|
|
||||||
|
|
@ -74,7 +79,11 @@ describe("getScanTimeout", () => {
|
||||||
|
|
||||||
it("should handle invalid environment variable and fall back to config", () => {
|
it("should handle invalid environment variable and fall back to config", () => {
|
||||||
process.env.AIKIDO_SCAN_TIMEOUT_MS = "invalid";
|
process.env.AIKIDO_SCAN_TIMEOUT_MS = "invalid";
|
||||||
fs.writeFileSync(configPath, JSON.stringify({ scanTimeout: 7000 }));
|
// Mock: config file exists with scanTimeout: 7000
|
||||||
|
fsMock.existsSync.mock.mockImplementation(() => true);
|
||||||
|
fsMock.readFileSync.mock.mockImplementation(() =>
|
||||||
|
JSON.stringify({ scanTimeout: 7000 })
|
||||||
|
);
|
||||||
|
|
||||||
const timeout = getScanTimeout();
|
const timeout = getScanTimeout();
|
||||||
|
|
||||||
|
|
@ -82,6 +91,9 @@ describe("getScanTimeout", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should ignore zero and negative values and fall back to default", () => {
|
it("should ignore zero and negative values and fall back to default", () => {
|
||||||
|
// Mock: config file doesn't exist
|
||||||
|
fsMock.existsSync.mock.mockImplementation(() => false);
|
||||||
|
|
||||||
process.env.AIKIDO_SCAN_TIMEOUT_MS = "0";
|
process.env.AIKIDO_SCAN_TIMEOUT_MS = "0";
|
||||||
|
|
||||||
let timeout = getScanTimeout();
|
let timeout = getScanTimeout();
|
||||||
|
|
@ -95,7 +107,11 @@ describe("getScanTimeout", () => {
|
||||||
|
|
||||||
it("should ignore textual non-numeric values in environment variable and fall back to config", () => {
|
it("should ignore textual non-numeric values in environment variable and fall back to config", () => {
|
||||||
process.env.AIKIDO_SCAN_TIMEOUT_MS = "fast";
|
process.env.AIKIDO_SCAN_TIMEOUT_MS = "fast";
|
||||||
fs.writeFileSync(configPath, JSON.stringify({ scanTimeout: 8000 }));
|
// Mock: config file exists with scanTimeout: 8000
|
||||||
|
fsMock.existsSync.mock.mockImplementation(() => true);
|
||||||
|
fsMock.readFileSync.mock.mockImplementation(() =>
|
||||||
|
JSON.stringify({ scanTimeout: 8000 })
|
||||||
|
);
|
||||||
|
|
||||||
const timeout = getScanTimeout();
|
const timeout = getScanTimeout();
|
||||||
|
|
||||||
|
|
@ -104,7 +120,11 @@ describe("getScanTimeout", () => {
|
||||||
|
|
||||||
it("should ignore textual non-numeric values in config file and fall back to default", () => {
|
it("should ignore textual non-numeric values in config file and fall back to default", () => {
|
||||||
delete process.env.AIKIDO_SCAN_TIMEOUT_MS;
|
delete process.env.AIKIDO_SCAN_TIMEOUT_MS;
|
||||||
fs.writeFileSync(configPath, JSON.stringify({ scanTimeout: "slow" }));
|
// Mock: config file exists with scanTimeout: "slow"
|
||||||
|
fsMock.existsSync.mock.mockImplementation(() => true);
|
||||||
|
fsMock.readFileSync.mock.mockImplementation(() =>
|
||||||
|
JSON.stringify({ scanTimeout: "slow" })
|
||||||
|
);
|
||||||
|
|
||||||
const timeout = getScanTimeout();
|
const timeout = getScanTimeout();
|
||||||
|
|
||||||
|
|
@ -113,7 +133,11 @@ describe("getScanTimeout", () => {
|
||||||
|
|
||||||
it("should ignore textual non-numeric values in both env and config, fall back to default", () => {
|
it("should ignore textual non-numeric values in both env and config, fall back to default", () => {
|
||||||
process.env.AIKIDO_SCAN_TIMEOUT_MS = "quick";
|
process.env.AIKIDO_SCAN_TIMEOUT_MS = "quick";
|
||||||
fs.writeFileSync(configPath, JSON.stringify({ scanTimeout: "medium" }));
|
// Mock: config file exists with scanTimeout: "medium"
|
||||||
|
fsMock.existsSync.mock.mockImplementation(() => true);
|
||||||
|
fsMock.readFileSync.mock.mockImplementation(() =>
|
||||||
|
JSON.stringify({ scanTimeout: "medium" })
|
||||||
|
);
|
||||||
|
|
||||||
const timeout = getScanTimeout();
|
const timeout = getScanTimeout();
|
||||||
|
|
||||||
|
|
@ -122,7 +146,11 @@ describe("getScanTimeout", () => {
|
||||||
|
|
||||||
it("should ignore mixed alphanumeric strings in environment variable", () => {
|
it("should ignore mixed alphanumeric strings in environment variable", () => {
|
||||||
process.env.AIKIDO_SCAN_TIMEOUT_MS = "5000ms";
|
process.env.AIKIDO_SCAN_TIMEOUT_MS = "5000ms";
|
||||||
fs.writeFileSync(configPath, JSON.stringify({ scanTimeout: 6000 }));
|
// Mock: config file exists with scanTimeout: 6000
|
||||||
|
fsMock.existsSync.mock.mockImplementation(() => true);
|
||||||
|
fsMock.readFileSync.mock.mockImplementation(() =>
|
||||||
|
JSON.stringify({ scanTimeout: 6000 })
|
||||||
|
);
|
||||||
|
|
||||||
const timeout = getScanTimeout();
|
const timeout = getScanTimeout();
|
||||||
|
|
||||||
|
|
@ -131,7 +159,11 @@ describe("getScanTimeout", () => {
|
||||||
|
|
||||||
it("should ignore mixed alphanumeric strings in config file", () => {
|
it("should ignore mixed alphanumeric strings in config file", () => {
|
||||||
delete process.env.AIKIDO_SCAN_TIMEOUT_MS;
|
delete process.env.AIKIDO_SCAN_TIMEOUT_MS;
|
||||||
fs.writeFileSync(configPath, JSON.stringify({ scanTimeout: "3000ms" }));
|
// Mock: config file exists with scanTimeout: "3000ms"
|
||||||
|
fsMock.existsSync.mock.mockImplementation(() => true);
|
||||||
|
fsMock.readFileSync.mock.mockImplementation(() =>
|
||||||
|
JSON.stringify({ scanTimeout: "3000ms" })
|
||||||
|
);
|
||||||
|
|
||||||
const timeout = getScanTimeout();
|
const timeout = getScanTimeout();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue