From ad1f0d995d35dc270cfb3d092f4b42b85060ee4f Mon Sep 17 00:00:00 2001 From: Allen Hutchison Date: Wed, 12 Nov 2025 15:17:38 -0800 Subject: [PATCH] refactor: move toml-loader.test.ts to use real filesystem (#12969) --- packages/core/src/policy/toml-loader.test.ts | 177 +++++-------------- 1 file changed, 46 insertions(+), 131 deletions(-) diff --git a/packages/core/src/policy/toml-loader.test.ts b/packages/core/src/policy/toml-loader.test.ts index 38f29b15fd..75c743dfd7 100644 --- a/packages/core/src/policy/toml-loader.test.ts +++ b/packages/core/src/policy/toml-loader.test.ts @@ -4,72 +4,41 @@ * 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 type { Dirent } from 'node:fs'; -import nodePath from 'node:path'; +import * as fs from 'node:fs/promises'; +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'; -async function runLoadPoliciesFromToml( - tomlContent: string, - fileName = 'test.toml', -): Promise { - const actualFs = - await vi.importActual( - 'node:fs/promises', - ); - - const mockReaddir = vi.fn( - async ( - path: string, - _options?: { withFileTypes: boolean }, - ): Promise => { - 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 => { - 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', () => { - beforeEach(() => { - vi.resetModules(); + let tempDir: string; + + beforeEach(async () => { + tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'policy-test-')); }); - afterEach(() => { - vi.restoreAllMocks(); - vi.doUnmock('node:fs/promises'); + afterEach(async () => { + if (tempDir) { + await fs.rm(tempDir, { + recursive: true, + force: true, + maxRetries: 3, + retryDelay: 10, + }); + } }); + async function runLoadPoliciesFromToml( + tomlContent: string, + fileName = 'test.toml', + ): Promise { + await fs.writeFile(path.join(tempDir, fileName), tomlContent); + const getPolicyTier = (_dir: string) => 1; + return loadPoliciesFromToml(ApprovalMode.DEFAULT, [tempDir], getPolicyTier); + } + describe('loadPoliciesFromToml', () => { it('should load and parse a simple policy file', async () => { const result = await runLoadPoliciesFromToml(` @@ -277,73 +246,30 @@ priority = 100 }); it('should handle a mix of valid and invalid policy files', async () => { - const actualFs = - await vi.importActual( - 'node:fs/promises', - ); - - const mockReaddir = vi.fn( - async ( - path: string, - _options?: { withFileTypes: boolean }, - ): Promise => { - 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 => { - if ( - nodePath.normalize(path) === - nodePath.normalize(nodePath.join('/policies', 'valid.toml')) - ) { - return ` + await fs.writeFile( + path.join(tempDir, 'valid.toml'), + ` [[rule]] toolName = "glob" decision = "allow" priority = 100 -`; - } - if ( - nodePath.normalize(path) === - nodePath.normalize(nodePath.join('/policies', 'invalid.toml')) - ) { - return ` +`, + ); + + await fs.writeFile( + path.join(tempDir, 'invalid.toml'), + ` [[rule]] toolName = "grep" decision = "allow" 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 result = await load( + const result = await loadPoliciesFromToml( ApprovalMode.DEFAULT, - ['/policies'], + [tempDir], getPolicyTier, ); @@ -354,6 +280,7 @@ priority = -1 expect(result.errors[0].errorType).toBe('schema_validation'); }); }); + describe('Negative Tests', () => { it('should return a schema_validation error if priority is missing', async () => { const result = await runLoadPoliciesFromToml(` @@ -507,26 +434,14 @@ priority = 100 }); it('should return a file_read error if readdir fails', async () => { - const actualFs = - await vi.importActual( - 'node:fs/promises', - ); + // Create a file and pass it as a directory to trigger ENOTDIR + const filePath = path.join(tempDir, 'not-a-dir'); + 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 result = await load( + const result = await loadPoliciesFromToml( ApprovalMode.DEFAULT, - ['/policies'], + [filePath], getPolicyTier, );