Skip to main content
Glama
projectService.test.ts•4.92 kB
import { ProjectService } from '../../services/projectService'; import { CacheService } from '../../services/cacheService'; import { createTestProject, TestData, Assertions, MockUtils } from '../../test/helpers'; import { ProjectStatus } from '../../models/types'; import { NotFoundError } from '../../utils/errors'; describe('ProjectService', () => { beforeEach(() => { MockUtils.resetMocks(); }); describe('createProject', () => { it('should create a project and invalidate cache', async () => { const projectData = TestData.project({ name: 'New Project', description: 'Project Description', status: ProjectStatus.PLANNED, }); const invalidateSpy = MockUtils.cacheSpy('invalidate'); const project = await ProjectService.createProject(projectData); Assertions.matchesData(project, projectData); Assertions.hasValidDates(project, ['startDate', 'endDate', 'createdAt', 'updatedAt']); expect(invalidateSpy).toHaveBeenCalledWith(project.id); }); }); describe('getProjects', () => { it('should return projects from cache if available', async () => { const project = await createTestProject(); const cacheKey = CacheService.projectKey(); await CacheService.set(cacheKey, [project]); const getSpy = MockUtils.cacheSpy('get'); const projects = await ProjectService.getProjects(); Assertions.matchesData(projects[0], project); Assertions.hasValidDates(projects[0], ['startDate', 'endDate', 'createdAt', 'updatedAt']); expect(getSpy).toHaveBeenCalledWith(cacheKey); }); it('should fetch from database and cache if not in cache', async () => { const project = await createTestProject(); const cacheKey = CacheService.projectKey(); const setSpy = MockUtils.cacheSpy('set'); const projects = await ProjectService.getProjects(); Assertions.matchesData(projects[0], project); Assertions.hasValidDates(projects[0], ['startDate', 'endDate', 'createdAt', 'updatedAt']); expect(setSpy).toHaveBeenCalledWith(cacheKey, expect.any(Array)); }); it('should filter projects by status', async () => { await createTestProject({ status: ProjectStatus.COMPLETED }); await createTestProject({ status: ProjectStatus.IN_PROGRESS }); const projects = await ProjectService.getProjects({ status: ProjectStatus.IN_PROGRESS }); expect(projects.length).toBeGreaterThan(0); Assertions.allHaveProperty(projects, 'status', ProjectStatus.IN_PROGRESS); }); }); describe('getProjectById', () => { it('should return project from cache if available', async () => { const project = await createTestProject(); const cacheKey = CacheService.projectKey(project.id); await CacheService.set(cacheKey, project); const getSpy = MockUtils.cacheSpy('get'); const result = await ProjectService.getProjectById(project.id); Assertions.matchesData(result, project); Assertions.hasValidDates(result, ['startDate', 'endDate', 'createdAt', 'updatedAt']); expect(getSpy).toHaveBeenCalledWith(cacheKey); }); it('should throw NotFoundError for non-existent project', async () => { await expect(ProjectService.getProjectById('non-existent-id')).rejects.toThrow(NotFoundError); }); }); describe('updateProject', () => { it('should update project and invalidate cache', async () => { const project = await createTestProject(); const updateData = { name: 'Updated Name' }; const invalidateSpy = MockUtils.cacheSpy('invalidate'); const updated = await ProjectService.updateProject(project.id, updateData); expect(updated.name).toBe(updateData.name); Assertions.hasValidDates(updated, ['startDate', 'endDate', 'createdAt', 'updatedAt']); expect(invalidateSpy).toHaveBeenCalledWith(project.id); }); it('should throw NotFoundError for non-existent project', async () => { await expect( ProjectService.updateProject('non-existent-id', { name: 'Test' }), ).rejects.toThrow(NotFoundError); }); }); describe('deleteProject', () => { it('should delete project and invalidate cache', async () => { const project = await createTestProject(); const invalidateSpy = MockUtils.cacheSpy('invalidate'); const deleted = await ProjectService.deleteProject(project.id); expect(deleted.id).toBe(project.id); Assertions.hasValidDates(deleted, ['startDate', 'endDate', 'createdAt', 'updatedAt']); expect(invalidateSpy).toHaveBeenCalledWith(project.id); await expect(ProjectService.getProjectById(project.id)).rejects.toThrow(NotFoundError); }); it('should throw NotFoundError for non-existent project', async () => { await expect(ProjectService.deleteProject('non-existent-id')).rejects.toThrow(NotFoundError); }); }); });

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/jatinderbhola/mcp-taskflow-tracker-api'

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