dnssweeper-cli
Version:
CLI tool for detecting and analyzing unused DNS records
194 lines • 8.46 kB
JavaScript
;
/**
* analyzeコマンドのテスト
*/
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const analyze_1 = require("./analyze");
const fs_1 = require("fs");
const globals_1 = require("@jest/globals");
const path_1 = __importDefault(require("path"));
// パターン設定のモック
const mockPatternConfig = {
version: '1.0.0',
description: 'テスト用パターン',
patterns: {
prefixes: {
high: ['old-', 'temp-', 'test-'],
medium: ['backup-', 'legacy-'],
low: ['new-', 'beta-'],
},
suffixes: {
high: ['-old', '-temp', '-test'],
medium: ['-backup', '-legacy'],
low: ['-new', '-beta'],
},
keywords: {
high: ['obsolete', 'deprecated'],
medium: ['archive'],
low: ['upcoming'],
},
},
scoring: {
high: 80,
medium: 50,
low: 20,
base: 10,
},
thresholds: {
critical: 90,
high: 70,
medium: 40,
low: 10,
safe: 0,
},
};
globals_1.jest.mock('../patterns/patternLoader');
// テスト用のCSVコンテンツ生成
const createTestCSVContent = (records) => {
const header = 'Name,Type,Content,TTL,Proxied,Created,Modified';
const rows = records.map(record => `${record.name},${record.type},${record.content},${record.ttl},${record.proxied},${record.created},${record.modified}`);
return [header, ...rows].join('\n');
};
// テスト用データ
const testRecords = [
{
name: 'test.example.com',
type: 'A',
content: '192.168.1.1',
ttl: 300,
proxied: false,
created: '2023-01-15T10:00:00Z',
modified: new Date().toISOString(),
},
{
name: 'api.example.com',
type: 'A',
content: '192.168.1.2',
ttl: 300,
proxied: true,
created: '2023-01-15T10:00:00Z',
modified: new Date().toISOString(),
},
];
describe('analyzeCommand', () => {
const tempDir = path_1.default.join(__dirname, '../../test/temp');
const testFile = path_1.default.join(tempDir, 'test.csv');
const outputFile = path_1.default.join(tempDir, 'output.csv');
beforeEach(async () => {
// モック関数をリセット
globals_1.jest.clearAllMocks();
// fs操作をモック
const csvContent = createTestCSVContent(testRecords);
globals_1.jest.spyOn(fs_1.promises, 'access').mockResolvedValue(undefined);
globals_1.jest.spyOn(fs_1.promises, 'readFile').mockResolvedValue(csvContent);
globals_1.jest.spyOn(fs_1.promises, 'writeFile').mockResolvedValue(undefined);
// パターン設定をモック
const { loadPatternConfig } = require('../patterns/patternLoader');
loadPatternConfig.mockResolvedValue(mockPatternConfig);
});
afterEach(async () => {
// モックをリストア
globals_1.jest.restoreAllMocks();
});
describe('基本機能', () => {
it('正常な分析が実行される', async () => {
const options = { output: 'table' };
await expect((0, analyze_1.analyzeCommand)(testFile, options)).resolves.not.toThrow();
});
it('英語オプションが動作する', async () => {
const options = { output: 'table', english: true };
await expect((0, analyze_1.analyzeCommand)(testFile, options)).resolves.not.toThrow();
});
it('verboseオプションが動作する', async () => {
const options = { output: 'table', verbose: true };
await expect((0, analyze_1.analyzeCommand)(testFile, options)).resolves.not.toThrow();
});
});
describe('リスクレベルフィルタリング', () => {
it('risk-levelオプションでフィルタリングが実行される', async () => {
const options = { output: 'table', riskLevel: 'high' };
await expect((0, analyze_1.analyzeCommand)(testFile, options)).resolves.not.toThrow();
});
it('各リスクレベルでフィルタリングできる', async () => {
const riskLevels = ['critical', 'high', 'medium', 'low'];
for (const riskLevel of riskLevels) {
const options = { output: 'table', riskLevel };
await expect((0, analyze_1.analyzeCommand)(testFile, options)).resolves.not.toThrow();
}
});
});
describe('ファイル出力機能', () => {
it('output-fileオプションでCSVファイルが出力される', async () => {
const options = {
output: 'table',
outputFile: outputFile,
};
await (0, analyze_1.analyzeCommand)(testFile, options);
expect(fs_1.promises.writeFile).toHaveBeenCalledWith(outputFile, expect.stringContaining('DNSweeper分析結果'));
});
it('英語モードでの出力ファイルが正しく生成される', async () => {
const outputFileEn = path_1.default.join(tempDir, 'output-en.csv');
const options = {
output: 'table',
outputFile: outputFileEn,
english: true,
};
await (0, analyze_1.analyzeCommand)(testFile, options);
expect(fs_1.promises.writeFile).toHaveBeenCalledWith(outputFileEn, expect.stringContaining('DNSweeper Analysis Results'));
});
it('リスクレベルフィルタリングと出力ファイルの組み合わせが動作する', async () => {
const highRiskFile = path_1.default.join(tempDir, 'high-risk.csv');
const options = {
output: 'table',
riskLevel: 'high',
outputFile: highRiskFile,
};
await (0, analyze_1.analyzeCommand)(testFile, options);
expect(fs_1.promises.writeFile).toHaveBeenCalledWith(highRiskFile, expect.stringContaining('DNSweeper分析結果'));
});
});
describe('出力形式', () => {
it('JSON出力が動作する', async () => {
const options = { output: 'json' };
await expect((0, analyze_1.analyzeCommand)(testFile, options)).resolves.not.toThrow();
});
it('CSV出力が動作する', async () => {
const options = { output: 'csv' };
await expect((0, analyze_1.analyzeCommand)(testFile, options)).resolves.not.toThrow();
});
});
describe('エラーハンドリング', () => {
it('存在しないファイルでエラーが発生する', async () => {
// fs.accessをリジェクトするようにオーバーライド
globals_1.jest
.spyOn(fs_1.promises, 'access')
.mockRejectedValue(new Error('ENOENT: no such file or directory'));
const options = { output: 'table' };
await expect((0, analyze_1.analyzeCommand)('nonexistent.csv', options)).rejects.toThrow();
});
it('不正なCSVファイルでも処理が続行される', async () => {
// 不正なCSVコンテンツを返すようにオーバーライド(必須フィールドが不足)
globals_1.jest.spyOn(fs_1.promises, 'access').mockResolvedValue(undefined);
globals_1.jest
.spyOn(fs_1.promises, 'readFile')
.mockResolvedValue('invalid,csv,content\nwithout,proper,headers');
const options = { output: 'table' };
// CSVパーサーは不正なレコードを警告してフィルタリングし、処理を続行する
await expect((0, analyze_1.analyzeCommand)('invalid.csv', options)).resolves.not.toThrow();
});
});
});
// テスト終了後のクリーンアップ
afterAll(() => {
// ファイルシステム関連のモックをクリア
globals_1.jest.restoreAllMocks();
// 一時ファイルのクリーンアップ
const tempDir = path_1.default.join(process.cwd(), 'test', 'temp');
fs_1.promises.rmdir(tempDir, { recursive: true }).catch(() => {
// エラーは無視(ディレクトリが存在しない場合)
});
});
//# sourceMappingURL=analyze.test.js.map