UNPKG

locker-mcp

Version:

MCP server for file locking and access control for AI code tools

231 lines 10.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const fs = __importStar(require("fs")); const path = __importStar(require("path")); const os = __importStar(require("os")); const metadata_1 = require("../metadata"); describe('MetadataManager', () => { let tempDir; let metadataManager; beforeEach(() => { tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'locker-test-')); metadataManager = new metadata_1.MetadataManager(tempDir); }); afterEach(() => { if (fs.existsSync(tempDir)) { fs.rmSync(tempDir, { recursive: true, force: true }); } }); describe('getEntry', () => { it('should return null for non-existent file', () => { const result = metadataManager.getEntry('non-existent.ts'); expect(result).toBeNull(); }); it('should return entry for existing file', () => { const filePath = 'test.ts'; const id = 'test-id'; const context = 'test context'; const state = 'locked-context'; metadataManager.createEntry(filePath, id, context, state); const result = metadataManager.getEntry(filePath); expect(result).not.toBeNull(); expect(result.filePath).toBe(filePath); expect(result.id).toBe(id); expect(result.context).toBe(context); expect(result.state).toBe(state); expect(result.history).toHaveLength(1); expect(result.history[0].state).toBe(state); }); }); describe('createEntry', () => { it('should create new entry successfully', () => { const filePath = 'test.ts'; const id = 'test-id'; const context = 'test context'; const state = 'locked-context'; const entry = metadataManager.createEntry(filePath, id, context, state); expect(entry.filePath).toBe(filePath); expect(entry.id).toBe(id); expect(entry.context).toBe(context); expect(entry.state).toBe(state); expect(entry.history).toHaveLength(1); expect(entry.history[0].state).toBe(state); expect(entry.history[0].timestamp).toBeDefined(); }); it('should throw error for duplicate entry', () => { const filePath = 'test.ts'; const id = 'test-id'; const context = 'test context'; const state = 'locked-context'; metadataManager.createEntry(filePath, id, context, state); expect(() => { metadataManager.createEntry(filePath, id, context, state); }).toThrow('Entry already exists for file: test.ts'); }); it('should normalize file paths', () => { const filePath = './test/../test.ts'; const normalizedPath = 'test.ts'; const id = 'test-id'; const context = 'test context'; const state = 'locked-context'; const entry = metadataManager.createEntry(filePath, id, context, state); expect(entry.filePath).toBe(normalizedPath); }); }); describe('updateEntry', () => { it('should update state and add history entry', () => { const filePath = 'test.ts'; const id = 'test-id'; const context = 'test context'; const initialState = 'locked-context'; metadataManager.createEntry(filePath, id, context, initialState); const newState = 'locked'; const updatedEntry = metadataManager.updateEntry(filePath, { state: newState }); expect(updatedEntry.state).toBe(newState); expect(updatedEntry.context).toBe(context); expect(updatedEntry.history).toHaveLength(2); expect(updatedEntry.history[1].state).toBe(newState); }); it('should update context without changing state', () => { const filePath = 'test.ts'; const id = 'test-id'; const initialContext = 'test context'; const state = 'locked-context'; metadataManager.createEntry(filePath, id, initialContext, state); const newContext = 'updated context'; const updatedEntry = metadataManager.updateEntry(filePath, { context: newContext }); expect(updatedEntry.context).toBe(newContext); expect(updatedEntry.state).toBe(state); expect(updatedEntry.history).toHaveLength(1); // No state change, no new history entry }); it('should throw error for non-existent file', () => { expect(() => { metadataManager.updateEntry('non-existent.ts', { state: 'locked' }); }).toThrow('No entry found for file: non-existent.ts'); }); }); describe('removeEntry', () => { it('should remove existing entry', () => { const filePath = 'test.ts'; const id = 'test-id'; const context = 'test context'; const state = 'locked-context'; metadataManager.createEntry(filePath, id, context, state); const removed = metadataManager.removeEntry(filePath); expect(removed).toBe(true); expect(metadataManager.getEntry(filePath)).toBeNull(); }); it('should return false for non-existent entry', () => { const removed = metadataManager.removeEntry('non-existent.ts'); expect(removed).toBe(false); }); }); describe('getAllEntries', () => { it('should return empty array when no entries exist', () => { const entries = metadataManager.getAllEntries(); expect(entries).toEqual([]); }); it('should return all entries', () => { const files = ['test1.ts', 'test2.ts', 'test3.ts']; files.forEach((file, index) => { metadataManager.createEntry(file, `id-${index}`, `context-${index}`, 'locked-context'); }); const entries = metadataManager.getAllEntries(); expect(entries).toHaveLength(3); expect(entries.map(e => e.filePath)).toEqual(expect.arrayContaining(files)); }); }); describe('metadata file persistence', () => { it('should persist metadata to file system', () => { const filePath = 'test.ts'; const id = 'test-id'; const context = 'test context'; const state = 'locked-context'; metadataManager.createEntry(filePath, id, context, state); const metadataFile = path.join(tempDir, '.reporepo', 'locker', 'locker.json'); expect(fs.existsSync(metadataFile)).toBe(true); const content = JSON.parse(fs.readFileSync(metadataFile, 'utf-8')); expect(content.entries).toHaveLength(1); expect(content.entries[0].filePath).toBe(filePath); }); it('should load existing metadata from file system', () => { const filePath = 'test.ts'; const id = 'test-id'; const context = 'test context'; const state = 'locked-context'; metadataManager.createEntry(filePath, id, context, state); // Create new manager instance to test loading const newManager = new metadata_1.MetadataManager(tempDir); const entry = newManager.getEntry(filePath); expect(entry).not.toBeNull(); expect(entry.filePath).toBe(filePath); expect(entry.id).toBe(id); expect(entry.context).toBe(context); expect(entry.state).toBe(state); }); it('should handle corrupted metadata file', () => { const metadataDir = path.join(tempDir, '.reporepo', 'locker'); fs.mkdirSync(metadataDir, { recursive: true }); const metadataFile = path.join(metadataDir, 'locker.json'); // Write invalid JSON fs.writeFileSync(metadataFile, 'invalid json content', 'utf-8'); expect(() => { metadataManager.getEntry('test.ts'); }).toThrow('Failed to parse metadata file:'); }); it('should handle file system write errors', () => { const filePath = 'test.ts'; const id = 'test-id'; const context = 'test context'; const state = 'locked-context'; // Create the metadata directory but make it read-only const metadataDir = path.join(tempDir, '.reporepo', 'locker'); fs.mkdirSync(metadataDir, { recursive: true }); // Make directory read-only (this will cause write to fail) fs.chmodSync(metadataDir, 0o444); try { expect(() => { metadataManager.createEntry(filePath, id, context, state); }).toThrow('Failed to save metadata file:'); } finally { // Restore permissions for cleanup fs.chmodSync(metadataDir, 0o755); } }); }); }); //# sourceMappingURL=metadata.test.js.map