feat: Add testing framework and initial test cases for various tools and database operations

This commit is contained in:
ethan.chen
2026-01-07 10:05:04 +08:00
parent 372b52b214
commit 47ecc40186
23 changed files with 1781 additions and 40 deletions

View File

@@ -0,0 +1,71 @@
/**
* Code review tools tests
*/
import { describe, test, expect, beforeEach } from "bun:test";
import { registerCodeReviewTools } from "../../../../src/tools/programming/codeReview.js";
import { callTool } from "../../../helpers/tool-helper.js";
describe("Code Review Tools", () => {
beforeEach(() => {
registerCodeReviewTools();
});
test("should review code and find issues", async () => {
const result = await callTool("code_review", {
code: "let x: any = 1;",
language: "typescript",
});
expect(result.content[0].text).toContain("Code Review");
expect(result.content[0].text).toContain("any");
});
test("should suggest improvements", async () => {
const result = await callTool("code_review", {
code: "console.log('test');",
language: "javascript",
});
expect(result.content[0].text).toContain("Suggestions");
expect(result.content[0].text).toContain("console.log");
});
test("should detect var usage", async () => {
const result = await callTool("code_review", {
code: "var x = 1;",
language: "javascript",
});
expect(result.content[0].text).toContain("var");
});
test("should provide optimization suggestions", async () => {
const result = await callTool("code_optimize", {
code: "if (x == 1) { }",
language: "javascript",
});
expect(result.content[0].text).toContain("Optimization");
expect(result.content[0].text).toContain("===");
});
test("should suggest Vue optimizations", async () => {
const result = await callTool("code_optimize", {
code: "<div v-for='item in items'>",
language: "vue",
});
expect(result.content[0].text).toContain("Optimization");
expect(result.content[0].text).toContain(":key");
});
test("should handle code with no issues", async () => {
const result = await callTool("code_review", {
code: "const x: number = 1;",
language: "typescript",
});
expect(result.content[0].text).toContain("Code Review");
});
});

View File

@@ -0,0 +1,100 @@
/**
* Code snippet tools tests
*/
import { describe, test, expect, beforeEach, afterEach } from "bun:test";
import { registerCodeSnippetTools } from "../../../../src/tools/programming/codeSnippet.js";
import { callTool } from "../../../helpers/tool-helper.js";
import { createTempDir } from "../../../helpers/test-utils.js";
import { setupTestDatabase } from "../../../helpers/database-helper.js";
describe("Code Snippet Tools", () => {
let testContext: ReturnType<typeof createTempDir>;
let cleanupDb: () => void;
beforeEach(() => {
testContext = createTempDir();
cleanupDb = setupTestDatabase(testContext);
registerCodeSnippetTools();
});
afterEach(() => {
cleanupDb();
testContext.cleanup();
});
test("should save code snippet", async () => {
const result = await callTool("code_snippet_save", {
title: "Test Snippet",
code: "const x = 1;",
language: "typescript",
tags: ["test"],
});
expect(result.content[0].text).toContain("saved successfully");
expect(result.content[0].text).toContain("Test Snippet");
});
test("should search code snippets", async () => {
// First save a snippet
await callTool("code_snippet_save", {
title: "Test Snippet",
code: "const x = 1;",
language: "typescript",
tags: ["test"],
});
// Then search
const result = await callTool("code_snippet_search", {
query: "Test",
});
expect(result.content[0].text).toContain("Found");
expect(result.content[0].text).toContain("Test Snippet");
});
test("should list code snippets", async () => {
// Save a snippet
await callTool("code_snippet_save", {
title: "Test Snippet",
code: "const x = 1;",
language: "typescript",
tags: ["test"],
});
const result = await callTool("code_snippet_list", {});
expect(result.content[0].text).toContain("Total");
expect(result.content[0].text).toContain("Test Snippet");
});
test("should delete code snippet", async () => {
// Save a snippet
const saveResult = await callTool("code_snippet_save", {
title: "Test Snippet",
code: "const x = 1;",
language: "typescript",
tags: ["test"],
});
// Extract ID from save result
const idMatch = saveResult.content[0].text.match(/ID: ([a-f0-9-]+)/);
if (!idMatch) {
throw new Error("Could not extract ID from save result");
}
const id = idMatch[1];
// Delete it
const result = await callTool("code_snippet_delete", { id });
expect(result.content[0].text).toContain("deleted successfully");
});
test("should handle search with no results", async () => {
const result = await callTool("code_snippet_search", {
query: "NonExistent",
});
expect(result.content[0].text).toContain("No code snippets found");
});
});

View File

@@ -0,0 +1,61 @@
/**
* Documentation tools tests
*/
import { describe, test, expect, beforeEach } from "bun:test";
import { registerDocsTools } from "../../../../src/tools/programming/docs.js";
import { callTool } from "../../../helpers/tool-helper.js";
describe("Documentation Tools", () => {
beforeEach(() => {
registerDocsTools();
});
test("should get TypeScript documentation", async () => {
const result = await callTool("docs_typescript", {});
expect(result.content[0].text).toContain("TypeScript Documentation");
expect(result.content[0].text).toContain("typescriptlang.org");
});
test("should get TypeScript documentation with topic", async () => {
const result = await callTool("docs_typescript", {
topic: "generics",
});
expect(result.content[0].text).toContain("TypeScript Documentation");
expect(result.content[0].text).toContain("generics");
});
test("should get Vue3 documentation", async () => {
const result = await callTool("docs_vue3", {});
expect(result.content[0].text).toContain("Vue 3 Documentation");
expect(result.content[0].text).toContain("vuejs.org");
});
test("should get Vue3 documentation with topic", async () => {
const result = await callTool("docs_vue3", {
topic: "composition",
});
expect(result.content[0].text).toContain("Vue 3 Documentation");
expect(result.content[0].text).toContain("composition");
});
test("should get Bun documentation", async () => {
const result = await callTool("docs_bun", {});
expect(result.content[0].text).toContain("Bun Documentation");
expect(result.content[0].text).toContain("bun.sh");
});
test("should get Bun documentation with topic", async () => {
const result = await callTool("docs_bun", {
topic: "runtime",
});
expect(result.content[0].text).toContain("Bun Documentation");
expect(result.content[0].text).toContain("runtime");
});
});

View File

@@ -0,0 +1,98 @@
/**
* Project template tools tests
*/
import { describe, test, expect, beforeEach, afterEach } from "bun:test";
import { registerProjectTemplateTools } from "../../../../src/tools/programming/projectTemplate.js";
import { callTool } from "../../../helpers/tool-helper.js";
import { createTempDir } from "../../../helpers/test-utils.js";
import { existsSync, readFileSync } from "fs";
import { join } from "path";
describe("Project Template Tools", () => {
let testContext: ReturnType<typeof createTempDir>;
beforeEach(() => {
testContext = createTempDir();
registerProjectTemplateTools();
});
afterEach(() => {
testContext.cleanup();
});
test("should create Vite + Vue3 project", async () => {
const projectName = "test-vue-project";
const projectPath = join(testContext.tempDir, projectName);
const result = await callTool("project_template_create", {
name: projectName,
path: testContext.tempDir,
});
expect(result.content[0].text).toContain("created successfully");
expect(existsSync(join(projectPath, "package.json"))).toBe(true);
expect(existsSync(join(projectPath, "vite.config.ts"))).toBe(true);
expect(existsSync(join(projectPath, "src", "main.ts"))).toBe(true);
expect(existsSync(join(projectPath, "src", "App.vue"))).toBe(true);
});
test("should create project with Pinia", async () => {
const projectName = "test-vue-pinia";
const projectPath = join(testContext.tempDir, projectName);
await callTool("project_template_create", {
name: projectName,
path: testContext.tempDir,
usePinia: true,
});
const packageJson = JSON.parse(
readFileSync(join(projectPath, "package.json"), "utf-8")
);
expect(packageJson.dependencies.pinia).toBeDefined();
});
test("should create fullstack project", async () => {
const projectName = "test-fullstack";
const projectPath = join(testContext.tempDir, projectName);
const result = await callTool("project_template_create_fullstack", {
name: projectName,
path: testContext.tempDir,
});
expect(result.content[0].text).toContain("created successfully");
expect(existsSync(join(projectPath, "frontend", "package.json"))).toBe(
true
);
expect(existsSync(join(projectPath, "backend", "package.json"))).toBe(true);
expect(existsSync(join(projectPath, "backend", "src", "index.ts"))).toBe(
true
);
});
test("should list available templates", async () => {
const result = await callTool("project_template_list", {});
expect(result.content[0].text).toContain("Available project templates");
expect(result.content[0].text).toContain("Vite + Vue3");
expect(result.content[0].text).toContain("Fullstack");
});
test("should handle existing directory error", async () => {
const projectName = "existing-project";
const projectPath = join(testContext.tempDir, projectName);
// Create directory first
const { mkdirSync } = await import("fs");
mkdirSync(projectPath, { recursive: true });
const result = await callTool("project_template_create", {
name: projectName,
path: testContext.tempDir,
});
expect(result.content[0].text).toContain("already exists");
});
});