integration.test.ts•11.2 kB
/**
* Unit tests for the MCP Kanban server
*
* This test suite tests the data structures and basic functionality
* using mock data instead of a real Planka server connection.
*/
import { describe, expect, test } from "@jest/globals";
// Mock data structures
const mockProject = {
id: 'project-123',
name: 'Test Project',
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z'
};
const mockBoard = {
id: 'board-123',
name: 'Test Board',
position: 1,
projectId: 'project-123',
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z'
};
const mockList = {
id: 'list-123',
name: 'Test List',
position: 1,
boardId: 'board-123',
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z'
};
const mockCard = {
id: 'card-123',
name: 'Test Card',
description: 'Test Description',
position: 1,
listId: 'list-123',
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z'
};
const mockTask = {
id: 'task-123',
name: 'Test Task',
position: 1,
isCompleted: false,
cardId: 'card-123',
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z'
};
const mockComment = {
id: 'comment-123',
text: 'Test Comment',
cardId: 'card-123',
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z'
};
const mockLabel = {
id: 'label-123',
name: 'Test Label',
color: 'berry-red',
position: 1,
boardId: 'board-123',
createdAt: '2024-01-01T00:00:00.000Z',
updatedAt: '2024-01-01T00:00:00.000Z'
};
// Helper functions to simulate operations
let idCounter = 1;
function createProject(name: string) {
return {
...mockProject,
name,
id: `project-${Date.now()}-${idCounter++}`
};
}
function createBoard(projectId: string, name: string, position: number) {
return {
...mockBoard,
projectId,
name,
position,
id: `board-${Date.now()}-${idCounter++}`
};
}
function createCard(listId: string, name: string, description: string) {
return {
...mockCard,
listId,
name,
description,
id: `card-${Date.now()}-${idCounter++}`
};
}
describe("MCP Kanban Unit Tests", () => {
describe("Environment Setup", () => {
test("should have test environment configured", () => {
expect(process.env.NODE_ENV).toBe('test');
expect(process.env.PLANKA_BASE_URL).toBe('http://mock-planka-server.test');
expect(process.env.PLANKA_AGENT_EMAIL).toBe('test@example.com');
});
});
describe("Project Data Structure", () => {
test("should create valid project data", () => {
expect(mockProject).toHaveProperty('id');
expect(mockProject).toHaveProperty('name');
expect(mockProject).toHaveProperty('createdAt');
expect(mockProject).toHaveProperty('updatedAt');
expect(mockProject.name).toBe('Test Project');
});
test("should create project with custom name", () => {
const customProject = createProject('Custom Project Name');
expect(customProject.name).toBe('Custom Project Name');
expect(customProject.id).toContain('project-');
});
test("should validate project properties", () => {
expect(typeof mockProject.id).toBe('string');
expect(typeof mockProject.name).toBe('string');
expect(mockProject.id.length).toBeGreaterThan(0);
expect(mockProject.name.length).toBeGreaterThan(0);
});
});
describe("Board Data Structure", () => {
test("should create valid board data", () => {
expect(mockBoard).toHaveProperty('id');
expect(mockBoard).toHaveProperty('name');
expect(mockBoard).toHaveProperty('projectId');
expect(mockBoard).toHaveProperty('position');
expect(mockBoard.projectId).toBe(mockProject.id);
});
test("should create board with custom properties", () => {
const customBoard = createBoard('proj-456', 'Custom Board', 2);
expect(customBoard.projectId).toBe('proj-456');
expect(customBoard.name).toBe('Custom Board');
expect(customBoard.position).toBe(2);
});
test("should validate board properties", () => {
expect(typeof mockBoard.position).toBe('number');
expect(mockBoard.position).toBeGreaterThan(0);
expect(typeof mockBoard.projectId).toBe('string');
});
});
describe("List Data Structure", () => {
test("should create valid list data", () => {
expect(mockList).toHaveProperty('id');
expect(mockList).toHaveProperty('name');
expect(mockList).toHaveProperty('boardId');
expect(mockList).toHaveProperty('position');
expect(mockList.boardId).toBe(mockBoard.id);
});
test("should validate list relationships", () => {
expect(mockList.boardId).toBe(mockBoard.id);
expect(typeof mockList.position).toBe('number');
});
});
describe("Card Data Structure", () => {
test("should create valid card data", () => {
expect(mockCard).toHaveProperty('id');
expect(mockCard).toHaveProperty('name');
expect(mockCard).toHaveProperty('listId');
expect(mockCard).toHaveProperty('description');
expect(mockCard.listId).toBe(mockList.id);
});
test("should create card with custom properties", () => {
const customCard = createCard('list-789', 'Custom Card', 'Custom Description');
expect(customCard.listId).toBe('list-789');
expect(customCard.name).toBe('Custom Card');
expect(customCard.description).toBe('Custom Description');
});
test("should have optional description", () => {
expect(mockCard).toHaveProperty('description');
expect(typeof mockCard.description).toBe('string');
});
});
describe("Task Data Structure", () => {
test("should create valid task data", () => {
expect(mockTask).toHaveProperty('id');
expect(mockTask).toHaveProperty('name');
expect(mockTask).toHaveProperty('cardId');
expect(mockTask).toHaveProperty('isCompleted');
expect(mockTask.cardId).toBe(mockCard.id);
});
test("should have completion status", () => {
expect(typeof mockTask.isCompleted).toBe('boolean');
expect(mockTask.isCompleted).toBe(false);
});
test("should validate task relationships", () => {
expect(mockTask.cardId).toBe(mockCard.id);
expect(typeof mockTask.position).toBe('number');
});
});
describe("Comment Data Structure", () => {
test("should create valid comment data", () => {
expect(mockComment).toHaveProperty('id');
expect(mockComment).toHaveProperty('text');
expect(mockComment).toHaveProperty('cardId');
expect(mockComment.cardId).toBe(mockCard.id);
});
test("should validate comment content", () => {
expect(typeof mockComment.text).toBe('string');
expect(mockComment.text.length).toBeGreaterThan(0);
});
});
describe("Label Data Structure", () => {
test("should create valid label data", () => {
expect(mockLabel).toHaveProperty('id');
expect(mockLabel).toHaveProperty('name');
expect(mockLabel).toHaveProperty('color');
expect(mockLabel).toHaveProperty('boardId');
expect(mockLabel.boardId).toBe(mockBoard.id);
});
test("should have valid color", () => {
const validColors = [
'berry-red', 'pumpkin-orange', 'lagoon-blue', 'pink-tulip',
'light-mud', 'orange-peel', 'bright-moss', 'antique-blue',
'dark-granite', 'lagune-blue', 'sunny-grass', 'morning-sky'
];
expect(validColors).toContain(mockLabel.color);
});
});
describe("Data Relationships", () => {
test("should maintain proper hierarchy", () => {
// Project -> Board -> List -> Card -> Task/Comment
expect(mockBoard.projectId).toBe(mockProject.id);
expect(mockList.boardId).toBe(mockBoard.id);
expect(mockCard.listId).toBe(mockList.id);
expect(mockTask.cardId).toBe(mockCard.id);
expect(mockComment.cardId).toBe(mockCard.id);
expect(mockLabel.boardId).toBe(mockBoard.id);
});
test("should have unique identifiers", () => {
const ids = [
mockProject.id,
mockBoard.id,
mockList.id,
mockCard.id,
mockTask.id,
mockComment.id,
mockLabel.id
];
const uniqueIds = new Set(ids);
expect(uniqueIds.size).toBe(ids.length);
});
});
describe("MCP Tool Parameters", () => {
test("should validate project manager parameters", () => {
const projectParams = {
action: 'get_projects',
page: 1,
perPage: 10
};
expect(projectParams).toHaveProperty('action');
expect(projectParams).toHaveProperty('page');
expect(projectParams).toHaveProperty('perPage');
expect(typeof projectParams.page).toBe('number');
expect(typeof projectParams.perPage).toBe('number');
});
test("should validate card manager parameters", () => {
const cardParams = {
action: 'create',
listId: 'list-123',
name: 'Test Card',
description: 'Test Description'
};
expect(cardParams).toHaveProperty('action');
expect(cardParams).toHaveProperty('listId');
expect(cardParams).toHaveProperty('name');
expect(cardParams).toHaveProperty('description');
});
test("should validate task manager parameters", () => {
const taskParams = {
action: 'create',
cardId: 'card-123',
name: 'Test Task',
isCompleted: false
};
expect(taskParams).toHaveProperty('action');
expect(taskParams).toHaveProperty('cardId');
expect(taskParams).toHaveProperty('name');
expect(typeof taskParams.isCompleted).toBe('boolean');
});
});
describe("Error Handling", () => {
test("should handle missing required fields", () => {
const incompleteCard = { name: 'Test' };
expect(incompleteCard).not.toHaveProperty('listId');
// Simulate validation
const requiredFields = ['name', 'listId'];
const missingFields = requiredFields.filter(field => !incompleteCard.hasOwnProperty(field));
expect(missingFields).toContain('listId');
});
test("should validate data types", () => {
// Simulate type validation
expect(typeof mockBoard.position).toBe('number');
expect(typeof mockTask.isCompleted).toBe('boolean');
expect(typeof mockCard.name).toBe('string');
});
});
describe("Utility Functions", () => {
test("should generate unique IDs", () => {
const project1 = createProject('Project 1');
const project2 = createProject('Project 2');
expect(project1.id).not.toBe(project2.id);
expect(project1.id).toContain('project-');
expect(project2.id).toContain('project-');
});
test("should preserve data integrity", () => {
const testCard = createCard('list-999', 'Test Card', 'Test Description');
expect(testCard.listId).toBe('list-999');
expect(testCard.name).toBe('Test Card');
expect(testCard.description).toBe('Test Description');
expect(testCard.id).toContain('card-');
});
});
});