106 lines
4.1 KiB
JavaScript
106 lines
4.1 KiB
JavaScript
// git.test.mjs — Integration tests for the git-forensics scanner
|
|
//
|
|
// The evil-project-health fixture is not a standalone git repo, but it may sit
|
|
// inside a parent git repo. The scanner uses `git rev-parse` which walks up the
|
|
// directory tree, so it may detect the parent repo. Both 'skipped' (truly no git)
|
|
// and 'ok' (parent repo detected) are valid outcomes.
|
|
//
|
|
// This test suite verifies:
|
|
// - Graceful handling: status is 'ok' or 'skipped', never 'error' with no findings
|
|
// - Correct structure of the scanner result envelope
|
|
// - All findings (if any) have the DS-GIT- prefix
|
|
|
|
import { describe, it, beforeEach } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { resolve } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { resetCounter } from '../../scanners/lib/output.mjs';
|
|
import { scan } from '../../scanners/git-forensics.mjs';
|
|
|
|
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
|
const FIXTURE = resolve(__dirname, '../../examples/malicious-skill-demo/evil-project-health');
|
|
// The plugin root — may or may not be a standalone git repo
|
|
const PLUGIN_ROOT = resolve(__dirname, '../..');
|
|
|
|
describe('git-forensics integration', () => {
|
|
beforeEach(() => {
|
|
resetCounter();
|
|
});
|
|
|
|
it('returns skipped or ok for the fixture directory (graceful handling)', async () => {
|
|
// If the fixture is inside a git repo, scanner returns 'ok'.
|
|
// If it is a bare directory with no git ancestry, scanner returns 'skipped'.
|
|
const result = await scan(FIXTURE, {});
|
|
const validStatuses = ['ok', 'skipped'];
|
|
assert.ok(
|
|
validStatuses.includes(result.status),
|
|
`Expected 'skipped' or 'ok', got '${result.status}'`
|
|
);
|
|
});
|
|
|
|
it('returns 0 or few findings for the fixture directory', async () => {
|
|
// The fixture has no git history of its own. If the parent repo is detected,
|
|
// findings reflect the parent repo's history — should be <= 10 for a clean repo.
|
|
const result = await scan(FIXTURE, {});
|
|
if (result.status === 'skipped') {
|
|
assert.equal(result.findings.length, 0, 'skipped should produce 0 findings');
|
|
} else {
|
|
assert.ok(
|
|
result.findings.length <= 10,
|
|
`Expected <= 10 findings for fixture dir (parent repo detected), got ${result.findings.length}`
|
|
);
|
|
}
|
|
});
|
|
|
|
it('scanner name is git-forensics', async () => {
|
|
const result = await scan(FIXTURE, {});
|
|
assert.equal(result.scanner, 'git-forensics', `Expected 'git-forensics', got '${result.scanner}'`);
|
|
});
|
|
|
|
it('returns ok or skipped for the plugin root (graceful handling)', async () => {
|
|
resetCounter();
|
|
const result = await scan(PLUGIN_ROOT, {});
|
|
const validStatuses = ['ok', 'skipped', 'error'];
|
|
assert.ok(
|
|
validStatuses.includes(result.status),
|
|
`Expected ok/skipped/error for plugin root, got '${result.status}'`
|
|
);
|
|
});
|
|
|
|
it('findings count is reasonable for the plugin root', async () => {
|
|
resetCounter();
|
|
const result = await scan(PLUGIN_ROOT, {});
|
|
if (result.status === 'skipped') {
|
|
assert.equal(result.findings.length, 0);
|
|
} else {
|
|
assert.ok(
|
|
result.findings.length <= 20,
|
|
`Expected <= 20 findings for plugin root, got ${result.findings.length}`
|
|
);
|
|
}
|
|
});
|
|
|
|
it('all findings have DS-GIT- prefix', async () => {
|
|
resetCounter();
|
|
const result = await scan(FIXTURE, {});
|
|
const wrongPrefix = result.findings.filter(f => !f.id.startsWith('DS-GIT-'));
|
|
assert.equal(
|
|
wrongPrefix.length, 0,
|
|
`All git findings should have DS-GIT- prefix. Wrong: ${wrongPrefix.map(f => f.id).join(', ')}`
|
|
);
|
|
});
|
|
|
|
it('counts object has expected severity keys', async () => {
|
|
const result = await scan(FIXTURE, {});
|
|
const expectedKeys = ['critical', 'high', 'medium', 'low', 'info'];
|
|
for (const key of expectedKeys) {
|
|
assert.ok(key in result.counts, `counts should have key '${key}'`);
|
|
}
|
|
});
|
|
|
|
it('duration_ms is a non-negative number', async () => {
|
|
const result = await scan(FIXTURE, {});
|
|
assert.ok(typeof result.duration_ms === 'number', 'duration_ms should be a number');
|
|
assert.ok(result.duration_ms >= 0, 'duration_ms should be non-negative');
|
|
});
|
|
});
|