refactor: move toml-loader.test.ts to use real filesystem (#12969)

This commit is contained in:
Allen Hutchison
2025-11-12 15:17:38 -08:00
committed by GitHub
parent 1ed163a666
commit ad1f0d995d
+46 -131
View File
@@ -4,72 +4,41 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { ApprovalMode, PolicyDecision } from './types.js'; import { ApprovalMode, PolicyDecision } from './types.js';
import type { Dirent } from 'node:fs'; import * as fs from 'node:fs/promises';
import nodePath from 'node:path'; import * as path from 'node:path';
import * as os from 'node:os';
import { loadPoliciesFromToml } from './toml-loader.js';
import type { PolicyLoadResult } from './toml-loader.js'; import type { PolicyLoadResult } from './toml-loader.js';
async function runLoadPoliciesFromToml(
tomlContent: string,
fileName = 'test.toml',
): Promise<PolicyLoadResult> {
const actualFs =
await vi.importActual<typeof import('node:fs/promises')>(
'node:fs/promises',
);
const mockReaddir = vi.fn(
async (
path: string,
_options?: { withFileTypes: boolean },
): Promise<Dirent[]> => {
if (nodePath.normalize(path) === nodePath.normalize('/policies')) {
return [
{
name: fileName,
isFile: () => true,
isDirectory: () => false,
} as Dirent,
];
}
return [];
},
);
const mockReadFile = vi.fn(async (path: string): Promise<string> => {
if (
nodePath.normalize(path) ===
nodePath.normalize(nodePath.join('/policies', fileName))
) {
return tomlContent;
}
throw new Error('File not found');
});
vi.doMock('node:fs/promises', () => ({
...actualFs,
default: { ...actualFs, readFile: mockReadFile, readdir: mockReaddir },
readFile: mockReadFile,
readdir: mockReaddir,
}));
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
const getPolicyTier = (_dir: string) => 1;
return load(ApprovalMode.DEFAULT, ['/policies'], getPolicyTier);
}
describe('policy-toml-loader', () => { describe('policy-toml-loader', () => {
beforeEach(() => { let tempDir: string;
vi.resetModules();
beforeEach(async () => {
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'policy-test-'));
}); });
afterEach(() => { afterEach(async () => {
vi.restoreAllMocks(); if (tempDir) {
vi.doUnmock('node:fs/promises'); await fs.rm(tempDir, {
recursive: true,
force: true,
maxRetries: 3,
retryDelay: 10,
});
}
}); });
async function runLoadPoliciesFromToml(
tomlContent: string,
fileName = 'test.toml',
): Promise<PolicyLoadResult> {
await fs.writeFile(path.join(tempDir, fileName), tomlContent);
const getPolicyTier = (_dir: string) => 1;
return loadPoliciesFromToml(ApprovalMode.DEFAULT, [tempDir], getPolicyTier);
}
describe('loadPoliciesFromToml', () => { describe('loadPoliciesFromToml', () => {
it('should load and parse a simple policy file', async () => { it('should load and parse a simple policy file', async () => {
const result = await runLoadPoliciesFromToml(` const result = await runLoadPoliciesFromToml(`
@@ -277,73 +246,30 @@ priority = 100
}); });
it('should handle a mix of valid and invalid policy files', async () => { it('should handle a mix of valid and invalid policy files', async () => {
const actualFs = await fs.writeFile(
await vi.importActual<typeof import('node:fs/promises')>( path.join(tempDir, 'valid.toml'),
'node:fs/promises', `
);
const mockReaddir = vi.fn(
async (
path: string,
_options?: { withFileTypes: boolean },
): Promise<Dirent[]> => {
if (nodePath.normalize(path) === nodePath.normalize('/policies')) {
return [
{
name: 'valid.toml',
isFile: () => true,
isDirectory: () => false,
} as Dirent,
{
name: 'invalid.toml',
isFile: () => true,
isDirectory: () => false,
} as Dirent,
];
}
return [];
},
);
const mockReadFile = vi.fn(async (path: string): Promise<string> => {
if (
nodePath.normalize(path) ===
nodePath.normalize(nodePath.join('/policies', 'valid.toml'))
) {
return `
[[rule]] [[rule]]
toolName = "glob" toolName = "glob"
decision = "allow" decision = "allow"
priority = 100 priority = 100
`; `,
} );
if (
nodePath.normalize(path) === await fs.writeFile(
nodePath.normalize(nodePath.join('/policies', 'invalid.toml')) path.join(tempDir, 'invalid.toml'),
) { `
return `
[[rule]] [[rule]]
toolName = "grep" toolName = "grep"
decision = "allow" decision = "allow"
priority = -1 priority = -1
`; `,
} );
throw new Error('File not found');
});
vi.doMock('node:fs/promises', () => ({
...actualFs,
default: { ...actualFs, readFile: mockReadFile, readdir: mockReaddir },
readFile: mockReadFile,
readdir: mockReaddir,
}));
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
const getPolicyTier = (_dir: string) => 1; const getPolicyTier = (_dir: string) => 1;
const result = await load( const result = await loadPoliciesFromToml(
ApprovalMode.DEFAULT, ApprovalMode.DEFAULT,
['/policies'], [tempDir],
getPolicyTier, getPolicyTier,
); );
@@ -354,6 +280,7 @@ priority = -1
expect(result.errors[0].errorType).toBe('schema_validation'); expect(result.errors[0].errorType).toBe('schema_validation');
}); });
}); });
describe('Negative Tests', () => { describe('Negative Tests', () => {
it('should return a schema_validation error if priority is missing', async () => { it('should return a schema_validation error if priority is missing', async () => {
const result = await runLoadPoliciesFromToml(` const result = await runLoadPoliciesFromToml(`
@@ -507,26 +434,14 @@ priority = 100
}); });
it('should return a file_read error if readdir fails', async () => { it('should return a file_read error if readdir fails', async () => {
const actualFs = // Create a file and pass it as a directory to trigger ENOTDIR
await vi.importActual<typeof import('node:fs/promises')>( const filePath = path.join(tempDir, 'not-a-dir');
'node:fs/promises', await fs.writeFile(filePath, 'content');
);
const mockReaddir = vi.fn(async () => {
throw new Error('Permission denied');
});
vi.doMock('node:fs/promises', () => ({
...actualFs,
default: { ...actualFs, readdir: mockReaddir },
readdir: mockReaddir,
}));
const { loadPoliciesFromToml: load } = await import('./toml-loader.js');
const getPolicyTier = (_dir: string) => 1; const getPolicyTier = (_dir: string) => 1;
const result = await load( const result = await loadPoliciesFromToml(
ApprovalMode.DEFAULT, ApprovalMode.DEFAULT,
['/policies'], [filePath],
getPolicyTier, getPolicyTier,
); );