Skip to main content
Glama
constitution.test.ts5.71 kB
import { describe, it, expect, beforeEach, afterEach } from 'vitest'; import * as fs from 'fs/promises'; import * as path from 'path'; import * as os from 'os'; import { constitutionCreate, ConstitutionCreateSchema } from '../../src/tools/constitution.js'; describe('constitution_create', () => { let testDir: string; beforeEach(async () => { // Create temporary test directory testDir = await fs.mkdtemp(path.join(os.tmpdir(), 'constitution-test-')); }); afterEach(async () => { // Clean up test directory await fs.rm(testDir, { recursive: true, force: true }); }); it('should create constitution.md with principles and constraints', async () => { const params = ConstitutionCreateSchema.parse({ projectName: 'test-project', principles: [ 'Prefer functional patterns', 'Write tests first', 'Keep it simple' ], constraints: [ 'Support Node 20+', 'Max bundle size: 500KB', 'Zero runtime dependencies' ], workspacePath: testDir }); const result = await constitutionCreate(params); // Verify result structure expect(result.content).toBeDefined(); expect(result.content[0].type).toBe('text'); const response = JSON.parse(result.content[0].text); expect(response.success).toBe(true); expect(response.projectName).toBe('test-project'); expect(response.principlesCount).toBe(3); expect(response.constraintsCount).toBe(3); // Verify file was created const constitutionPath = response.constitutionPath; expect(constitutionPath).toBeDefined(); const content = await fs.readFile(constitutionPath, 'utf-8'); // Verify content structure expect(content).toContain('# test-project Constitution'); expect(content).toContain('## 🎯 Project Principles'); expect(content).toContain('## 🔒 Technical Constraints'); expect(content).toContain('Prefer functional patterns'); expect(content).toContain('Write tests first'); expect(content).toContain('Keep it simple'); expect(content).toContain('Support Node 20+'); expect(content).toContain('Max bundle size: 500KB'); expect(content).toContain('Zero runtime dependencies'); }); it('should create constitution with preferences', async () => { const params = ConstitutionCreateSchema.parse({ projectName: 'web-app', principles: ['User experience first'], constraints: ['Browser support: Chrome, Firefox, Safari'], preferences: { libraries: ['React Query over Redux', 'Tailwind over Bootstrap'], patterns: ['Repository pattern for data access', 'Composition over inheritance'], style: 'Functional programming preferred' }, workspacePath: testDir }); const result = await constitutionCreate(params); const response = JSON.parse(result.content[0].text); const content = await fs.readFile(response.constitutionPath, 'utf-8'); // Verify preferences section expect(content).toContain('## 📚 Preferences'); expect(content).toContain('React Query over Redux'); expect(content).toContain('Tailwind over Bootstrap'); expect(content).toContain('Repository pattern for data access'); expect(content).toContain('Functional programming preferred'); }); it('should create constitution without preferences', async () => { const params = ConstitutionCreateSchema.parse({ projectName: 'minimal-project', principles: ['Simplicity'], constraints: ['MIT licensed'], workspacePath: testDir }); const result = await constitutionCreate(params); const response = JSON.parse(result.content[0].text); const content = await fs.readFile(response.constitutionPath, 'utf-8'); // Verify it handles missing preferences gracefully expect(content).toContain('_No library preferences specified_'); expect(content).toContain('_No pattern preferences specified_'); expect(content).toContain('_No style preference specified_'); }); it('should validate schema correctly', () => { // Valid schema expect(() => { ConstitutionCreateSchema.parse({ projectName: 'valid-project', principles: ['Principle 1'], constraints: ['Constraint 1'] }); }).not.toThrow(); // Invalid - missing principles expect(() => { ConstitutionCreateSchema.parse({ projectName: 'invalid-project', constraints: ['Constraint 1'] }); }).toThrow(); // Invalid - missing constraints expect(() => { ConstitutionCreateSchema.parse({ projectName: 'invalid-project', principles: ['Principle 1'] }); }).toThrow(); // Invalid - empty arrays expect(() => { ConstitutionCreateSchema.parse({ projectName: 'invalid-project', principles: [], constraints: [] }); }).not.toThrow(); // Should allow empty arrays }); it('should create constitution in correct directory structure', async () => { const params = ConstitutionCreateSchema.parse({ projectName: 'structured-project', principles: ['Good structure'], constraints: ['Well organized'], workspacePath: testDir }); const result = await constitutionCreate(params); const response = JSON.parse(result.content[0].text); // Verify directory structure const constitutionPath = response.constitutionPath; expect(constitutionPath).toMatch(/structured-project[/\\]constitution\.md$/); // Check parent directory exists const parentDir = path.dirname(constitutionPath); const stats = await fs.stat(parentDir); expect(stats.isDirectory()).toBe(true); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/flight505/MCP_DinCoder'

If you have feedback or need assistance with the MCP directory API, please join our Discord server