Skip to main content
Glama
para-methodology.test.ts17.6 kB
/** * PARA 방법론 통합 테스트 * Projects, Areas, Resources, Archives 카테고리 검증 */ import { executeTool } from '../../src/tools'; import { createTestContext, cleanupTestContext } from '../test-helpers'; import type { ToolExecutionContext } from '../../src/tools/types'; describe('PARA Methodology Integration Tests', () => { let context: ToolExecutionContext; beforeEach(() => { context = createTestContext(); }); afterEach(() => { cleanupTestContext(context); }); describe('Projects 카테고리', () => { it('프로젝트 노트를 생성하고 프로젝트별로 필터링할 수 있다', async () => { // 프로젝트 관련 노트 생성 await executeTool( 'create_note', { title: '웹사이트 리디자인 계획', content: '## 목표\n- 현대적인 UI/UX\n- 성능 개선\n\n## 마감일\n2025-12-31', category: 'Projects', project: 'website-redesign', tags: ['planning', 'ui', 'performance'], }, context ); await executeTool( 'create_note', { title: 'DB 스키마 설계', content: '웹사이트 리디자인을 위한 데이터베이스 스키마', category: 'Projects', project: 'website-redesign', tags: ['database', 'schema'], }, context ); await executeTool( 'create_note', { title: 'API 마이그레이션', content: '별도 프로젝트', category: 'Projects', project: 'api-migration', tags: ['api'], }, context ); // 프로젝트별 필터링 const redesignNotes = await executeTool( 'list_notes', { project: 'website-redesign' }, context ); const text = redesignNotes.content[0]?.text || ''; expect(text).toContain('웹사이트 리디자인 계획'); expect(text).toContain('DB 스키마 설계'); expect(text).not.toContain('API 마이그레이션'); // 메타데이터 확인 const metadata = redesignNotes._meta?.metadata as any; expect(metadata?.total).toBe(2); }); it('프로젝트 완료 시 Archives로 이동할 수 있다', async () => { // 프로젝트 노트 생성 const projectNote = await executeTool( 'create_note', { title: '완료된 프로젝트', content: '프로젝트 내용', category: 'Projects', project: 'completed-project', tags: ['active'], }, context ); const uid = projectNote._meta?.metadata?.id; // Projects 카테고리에 있는지 확인 const activeProjects = await executeTool( 'list_notes', { category: 'Projects' }, context ); expect(activeProjects.content[0]?.text).toContain('완료된 프로젝트'); // Archives로 이동 await executeTool( 'update_note', { uid, category: 'Archives', tags: ['active', 'completed'], }, context ); // Projects에서 사라짐 const updatedProjects = await executeTool( 'list_notes', { category: 'Projects' }, context ); expect(updatedProjects.content[0]?.text || '').not.toContain( '완료된 프로젝트' ); // Archives에 나타남 const archives = await executeTool( 'list_notes', { category: 'Archives' }, context ); expect(archives.content[0]?.text).toContain('완료된 프로젝트'); }); }); describe('Areas 카테고리', () => { it('지속적인 책임 영역을 관리할 수 있다', async () => { // 여러 Areas 노트 생성 await executeTool( 'create_note', { title: '건강 관리 루틴', content: '## 일일 습관\n- 운동 30분\n- 물 8잔\n- 7시간 수면', category: 'Areas', tags: ['health', 'routine', 'habits'], }, context ); await executeTool( 'create_note', { title: '재정 관리 원칙', content: '## 월별 예산\n- 저축: 30%\n- 필수: 50%\n- 여가: 20%', category: 'Areas', tags: ['finance', 'budget'], }, context ); await executeTool( 'create_note', { title: '팀 리더십', content: '## 핵심 책임\n- 1:1 미팅\n- 코드 리뷰\n- 멘토링', category: 'Areas', tags: ['leadership', 'team'], }, context ); // Areas 카테고리 전체 조회 const areas = await executeTool( 'list_notes', { category: 'Areas' }, context ); const text = areas.content[0]?.text || ''; expect(text).toContain('건강 관리 루틴'); expect(text).toContain('재정 관리 원칙'); expect(text).toContain('팀 리더십'); const metadata = areas._meta?.metadata as any; expect(metadata?.total).toBe(3); }); it('특정 영역의 노트를 태그로 검색할 수 있다', async () => { await executeTool( 'create_note', { title: '건강 체크리스트', content: '건강 관련 내용', category: 'Areas', tags: ['health'], }, context ); await executeTool( 'create_note', { title: '재정 보고서', content: '재정 관련 내용', category: 'Areas', tags: ['finance'], }, context ); // 태그로 필터링 const healthNotes = await executeTool( 'list_notes', { category: 'Areas', tags: ['health'] }, context ); expect(healthNotes.content[0]?.text).toContain('건강 체크리스트'); expect(healthNotes.content[0]?.text || '').not.toContain('재정 보고서'); }); }); describe('Resources 카테고리', () => { it('참고 자료를 저장하고 재사용할 수 있다', async () => { // 리소스 노트 생성 const resource1 = await executeTool( 'create_note', { title: 'TypeScript 타입 가드 패턴', content: '```typescript\nfunction isString(value: unknown): value is string {\n return typeof value === "string";\n}\n```', category: 'Resources', tags: ['typescript', 'patterns', 'type-guards'], }, context ); const resource2 = await executeTool( 'create_note', { title: 'REST API 상태 코드', content: '- 200: OK\n- 201: Created\n- 400: Bad Request\n- 404: Not Found\n- 500: Server Error', category: 'Resources', tags: ['api', 'http', 'reference'], }, context ); // 프로젝트에서 리소스 참조 const projectNote = await executeTool( 'create_note', { title: 'API 개발 작업', content: 'REST API 상태 코드를 참조하여 구현', category: 'Projects', project: 'api-dev', links: [resource2._meta?.metadata?.id], }, context ); // 리소스 검색 const searchResult = await executeTool( 'search_memory', { query: 'TypeScript', category: 'Resources' }, context ); expect(searchResult.content[0]?.text).toContain('TypeScript'); }); it('여러 프로젝트에서 동일 리소스를 참조할 수 있다', async () => { // 공통 리소스 const designSystem = await executeTool( 'create_note', { title: '회사 디자인 시스템 가이드', content: '## 색상\n- Primary: #0066CC\n## 타이포그래피\n- Heading: Inter', category: 'Resources', tags: ['design-system', 'ui'], }, context ); const resourceUid = designSystem._meta?.metadata?.id; // 여러 프로젝트에서 참조 await executeTool( 'create_note', { title: '마케팅 랜딩 페이지', content: '디자인 시스템 가이드에 따라 구현', category: 'Projects', project: 'marketing-landing', links: [resourceUid], }, context ); await executeTool( 'create_note', { title: '고객 포털 리뉴얼', content: '브랜드 가이드라인 준수', category: 'Projects', project: 'customer-portal', links: [resourceUid], }, context ); await executeTool( 'create_note', { title: '모바일 앱 UI 개선', content: '일관된 디자인 시스템 적용', category: 'Projects', project: 'mobile-ui', links: [resourceUid], }, context ); // 리소스 노트 확인 const resourceWithLinks = await executeTool( 'read_note', { uid: resourceUid }, context ); const text = resourceWithLinks.content[0]?.text || ''; expect(text).toContain('디자인 시스템'); // 프로젝트들이 리소스를 참조하고 있는지 확인 (front matter links 배열) // 실제 백링크 그래프는 인덱싱 시점에 구축됨 const projectNotesResult = await executeTool( 'list_notes', { category: 'Projects' }, context ); // 모든 프로젝트가 생성되었는지 확인 expect(projectNotesResult._meta?.metadata as any).toHaveProperty('total', 3); }); }); describe('Archives 카테고리', () => { it('완료되거나 비활성화된 항목을 보관할 수 있다', async () => { // 보관 노트들 생성 await executeTool( 'create_note', { title: '2024 Q4 마케팅 캠페인', content: '## 완료됨\n- ROI: 150%\n- 신규 고객: 500명', category: 'Archives', tags: ['completed', 'marketing', '2024'], }, context ); await executeTool( 'create_note', { title: '이전 팀 프로세스', content: '더 이상 사용하지 않는 프로세스', category: 'Archives', tags: ['legacy', 'process'], }, context ); await executeTool( 'create_note', { title: 'React Class Components (구버전)', content: 'Hooks 이전 방식', category: 'Archives', tags: ['react', 'legacy'], }, context ); // Archives 조회 const archives = await executeTool( 'list_notes', { category: 'Archives' }, context ); const metadata = archives._meta?.metadata as any; expect(metadata?.total).toBe(3); // 연도별 태그 필터링 (검색 인덱스가 없으므로 태그로 확인) const archives2024 = await executeTool( 'list_notes', { category: 'Archives', tags: ['2024'] }, context ); expect(archives2024.content[0]?.text).toContain('마케팅 캠페인'); }); }); describe('PARA 카테고리 간 워크플로우', () => { it('영역에서 프로젝트로 전환할 수 있다', async () => { // 1. 영역 정의 const learningArea = await executeTool( 'create_note', { title: '기술 학습', content: '## 학습 분야\n- 클라우드 컴퓨팅\n- 머신러닝\n- DevOps', category: 'Areas', tags: ['learning', 'technology'], }, context ); const areaUid = learningArea._meta?.metadata?.id; // 2. 영역에서 구체적인 프로젝트 생성 const certProject = await executeTool( 'create_note', { title: 'AWS Solutions Architect 자격증 취득', content: '## 목표\n자격증 취득 by 2025-06-30\n\n## 참조\n기술 학습 영역에서 파생', category: 'Projects', project: 'aws-certification', tags: ['aws', 'certification', 'learning'], links: [areaUid], }, context ); const projectUid = certProject._meta?.metadata?.id; // 3. 영역 노트 업데이트 await executeTool( 'update_note', { uid: areaUid, content: '## 학습 분야\n- 클라우드 컴퓨팅\n- 머신러닝\n- DevOps\n\n## 현재 프로젝트\n- AWS 자격증 취득', links: [projectUid], }, context ); // 4. 업데이트된 영역 노트 확인 const areaWithLinks = await executeTool( 'read_note', { uid: areaUid }, context ); const areaText = areaWithLinks.content[0]?.text || ''; expect(areaText).toContain('기술 학습'); expect(areaText).toContain('현재 프로젝트'); // Front matter에 links 배열이 업데이트되었는지 확인 const areaMetadata = areaWithLinks._meta?.metadata as any; expect(areaMetadata?.links).toContain(projectUid); }); it('모든 PARA 카테고리를 동시에 사용할 수 있다', async () => { // 각 카테고리에 하나씩 생성 await executeTool( 'create_note', { title: '현재 진행 중인 프로젝트', content: '프로젝트 내용', category: 'Projects', }, context ); await executeTool( 'create_note', { title: '지속적인 책임 영역', content: '영역 내용', category: 'Areas', }, context ); await executeTool( 'create_note', { title: '참고 자료', content: '리소스 내용', category: 'Resources', }, context ); await executeTool( 'create_note', { title: '보관된 항목', content: '보관 내용', category: 'Archives', }, context ); // 전체 노트 수 확인 const allNotes = await executeTool('list_notes', {}, context); const metadata = allNotes._meta?.metadata as any; expect(metadata?.total).toBe(4); // 각 카테고리별로 1개씩 for (const category of ['Projects', 'Areas', 'Resources', 'Archives']) { const categoryNotes = await executeTool( 'list_notes', { category }, context ); expect(categoryNotes._meta?.metadata?.total).toBe(1); } }); }); describe('PARA 방법론 실용 시나리오', () => { it('프로젝트 생명주기 전체를 관리할 수 있다', async () => { // 1. 프로젝트 시작 const projectHub = await executeTool( 'create_note', { title: '사용자 대시보드 기능 개발', content: '## 요구사항\n- 실시간 통계\n- 커스텀 위젯\n- 데이터 내보내기', category: 'Projects', project: 'user-dashboard', tags: ['feature', 'dashboard', 'in-progress'], }, context ); const hubUid = projectHub._meta?.metadata?.id; // 2. 작업 노트들 생성 const taskNote1 = await executeTool( 'create_note', { title: '대시보드 DB 스키마', content: '## Tables\n- user_widgets\n- dashboard_layouts\n- widget_data', category: 'Projects', project: 'user-dashboard', tags: ['database'], links: [hubUid], }, context ); const taskNote2 = await executeTool( 'create_note', { title: '대시보드 API 엔드포인트', content: '## Endpoints\n- GET /dashboard\n- POST /widgets', category: 'Projects', project: 'user-dashboard', tags: ['api'], links: [hubUid], }, context ); // 3. 프로젝트 노트 조회 const dashboardNotes = await executeTool( 'list_notes', { project: 'user-dashboard' }, context ); expect(dashboardNotes._meta?.metadata?.total).toBe(3); // 4. 프로젝트 완료 처리 const allDashboardNotes = [hubUid, taskNote1._meta?.metadata?.id, taskNote2._meta?.metadata?.id]; for (const uid of allDashboardNotes) { const readResult = await executeTool('read_note', { uid }, context); const currentTags = readResult._meta?.metadata?.tags || []; await executeTool( 'update_note', { uid, category: 'Archives', tags: [...currentTags, 'completed'], }, context ); } // 5. Projects에서 사라짐 const activeProjects = await executeTool( 'list_notes', { category: 'Projects', project: 'user-dashboard' }, context ); expect(activeProjects._meta?.metadata?.total).toBe(0); // 6. Archives에 나타남 const archivedNotes = await executeTool( 'list_notes', { category: 'Archives', project: 'user-dashboard' }, context ); expect(archivedNotes._meta?.metadata?.total).toBe(3); }); }); });

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/inchan/memory-mcp'

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