Skip to main content
Glama
problem-decomposer.test.ts11.7 kB
/** * Unit tests for ProblemDecomposer * * Tests meaningful sub-problem name generation, domain-specific decomposition, * depth handling, and dependency descriptions. * * Requirements: 2.1, 2.2, 2.3, 2.4, 2.5 */ import { beforeEach, describe, expect, it } from "vitest"; import { ProblemDecomposer } from "../../../reasoning/problem-decomposer.js"; describe("ProblemDecomposer", () => { let decomposer: ProblemDecomposer; beforeEach(() => { decomposer = new ProblemDecomposer(); }); describe("Meaningful Name Generation", () => { it("should generate descriptive names instead of generic 'Sub-problem N of:' pattern", () => { const result = decomposer.decompose("Build a scalable e-commerce platform", 2); // Check that no sub-problem uses the generic pattern for (const subProblem of result.subProblems) { expect(subProblem.name).not.toMatch(/Sub-problem \d+ of:/i); expect(subProblem.name.length).toBeGreaterThan(0); } }); it("should extract domain-specific components for e-commerce problems", () => { const result = decomposer.decompose("Build a scalable e-commerce platform", 2); // Should identify e-commerce domain const domains = result.subProblems.map((sp) => sp.domain).filter(Boolean); expect(domains).toContain("ecommerce"); // Should have meaningful component names const names = result.subProblems.map((sp) => sp.name); expect(names.some((n) => n.length > 5)).toBe(true); }); it("should extract domain-specific components for web application problems", () => { const result = decomposer.decompose("Create a web application for task management", 2); // Should identify a valid domain (webapp, general, or any specific domain) const domains = result.subProblems.map((sp) => sp.domain).filter(Boolean); // At minimum, should have identified some domain expect(domains.length).toBeGreaterThan(0); // Should have meaningful sub-problems expect(result.subProblems.length).toBeGreaterThan(1); }); it("should generate action-based names based on problem intent", () => { const buildResult = decomposer.decompose("Build a new authentication system", 2); const improveResult = decomposer.decompose("Improve the performance of the database", 2); const fixResult = decomposer.decompose("Fix the bug in the login flow", 2); // Build intent should use design/implement verbs expect( buildResult.subProblems.some((sp) => /Design|Implement|Create|Develop/i.test(sp.name)) ).toBe(true); // Improve intent should use optimize/enhance verbs expect( improveResult.subProblems.some((sp) => /Optimize|Enhance|Refactor|Upgrade/i.test(sp.name)) ).toBe(true); // Fix intent should use debug/resolve verbs expect( fixResult.subProblems.some((sp) => /Debug|Resolve|Repair|Correct/i.test(sp.name)) ).toBe(true); }); }); describe("Sub-problem Description Quality", () => { it("should provide descriptions that explain what needs to be solved", () => { const result = decomposer.decompose("Design a user authentication system", 2); // Each sub-problem should have a description for (const subProblem of result.subProblems) { expect(subProblem.description).toBeDefined(); expect(subProblem.description.length).toBeGreaterThan(10); } }); it("should include details field with additional context", () => { const result = decomposer.decompose("Build a REST API for user management", 2); // Child sub-problems should have details const childProblems = result.subProblems.filter((sp) => sp.parent); expect(childProblems.length).toBeGreaterThan(0); }); }); describe("Dependency Relationship Descriptions", () => { it("should include meaningful dependency descriptions", () => { const result = decomposer.decompose("Build a scalable web application", 2); // Dependencies should have descriptions for (const dep of result.dependencies) { expect(dep.description).toBeDefined(); expect(dep.description.length).toBeGreaterThan(0); expect(dep.type).toBeDefined(); } }); it("should explain the relationship between components", () => { const result = decomposer.decompose("Create an e-commerce platform with checkout", 2); // Dependency descriptions should explain relationships const descriptions = result.dependencies.map((d) => d.description); expect( descriptions.some( (d) => d.includes("component of") || d.includes("foundation for") || d.includes("completed before") ) ).toBe(true); }); }); describe("Domain Detection", () => { it("should detect e-commerce domain", () => { const result = decomposer.decompose("Build an online store with shopping cart", 2); expect(result.subProblems.some((sp) => sp.domain === "ecommerce")).toBe(true); }); it("should detect API domain", () => { const result = decomposer.decompose("Design a REST API with authentication", 2); expect(result.subProblems.some((sp) => sp.domain === "api" || sp.domain === "security")).toBe( true ); }); it("should detect data/analytics domain", () => { const result = decomposer.decompose("Build a data pipeline for analytics", 2); expect(result.subProblems.some((sp) => sp.domain === "data")).toBe(true); }); it("should detect machine learning domain", () => { const result = decomposer.decompose("Train a machine learning model for prediction", 2); expect(result.subProblems.some((sp) => sp.domain === "ml")).toBe(true); }); it("should detect security domain", () => { const result = decomposer.decompose("Implement security measures for access control", 2); expect(result.subProblems.some((sp) => sp.domain === "security")).toBe(true); }); it("should detect DevOps domain", () => { const result = decomposer.decompose( "Set up devops infrastructure with Docker and Kubernetes", 2 ); expect(result.subProblems.some((sp) => sp.domain === "devops")).toBe(true); }); it("should fall back to general domain for unrecognized problems", () => { const result = decomposer.decompose("Solve the traveling salesman problem", 2); expect(result.subProblems.some((sp) => sp.domain === "general")).toBe(true); }); }); describe("Depth Handling", () => { it("should respect maxDepth=1 and only return root problem", () => { const result = decomposer.decompose("Build a web application", 1); // Should only have root problem at depth 1 expect(result.subProblems.length).toBe(1); expect(result.subProblems[0].depth).toBe(1); expect(result.subProblems[0].parent).toBeUndefined(); }); it("should generate sub-problems at depth 2 when maxDepth >= 2", () => { const result = decomposer.decompose("Build a web application", 2); // Should have problems at depth 1 and 2 const depths = result.subProblems.map((sp) => sp.depth); expect(depths).toContain(1); expect(depths).toContain(2); }); it("should reach maxDepth=3 with at least one path", () => { const result = decomposer.decompose("Build a complex enterprise system", 3); // Should have problems at depth 3 const maxDepth = Math.max(...result.subProblems.map((sp) => sp.depth)); expect(maxDepth).toBe(3); // Verify at least one sub-problem exists at depth 3 const depth3Problems = result.subProblems.filter((sp) => sp.depth === 3); expect(depth3Problems.length).toBeGreaterThan(0); }); it("should reach maxDepth=4 with at least one path", () => { const result = decomposer.decompose("Build a scalable e-commerce platform", 4); // Should have problems at depth 4 const maxDepth = Math.max(...result.subProblems.map((sp) => sp.depth)); expect(maxDepth).toBe(4); // Verify at least one sub-problem exists at depth 4 const depth4Problems = result.subProblems.filter((sp) => sp.depth === 4); expect(depth4Problems.length).toBeGreaterThan(0); }); it("should generate meaningful sub-problems at each depth level", () => { const result = decomposer.decompose("Build a web application with authentication", 3); // Check each depth level has meaningful names for (let depth = 1; depth <= 3; depth++) { const problemsAtDepth = result.subProblems.filter((sp) => sp.depth === depth); expect(problemsAtDepth.length).toBeGreaterThan(0); for (const problem of problemsAtDepth) { // Names should not be generic patterns expect(problem.name).not.toMatch(/Sub-problem \d+ of:/i); expect(problem.name.length).toBeGreaterThan(5); // Descriptions should be meaningful expect(problem.description.length).toBeGreaterThan(10); } } }); it("should create parent-child relationships across all depths", () => { const result = decomposer.decompose("Design a data pipeline for analytics", 3); // All non-root problems should have a parent const nonRootProblems = result.subProblems.filter((sp) => sp.id !== "root"); for (const problem of nonRootProblems) { expect(problem.parent).toBeDefined(); // Parent should exist in the sub-problems list const parentExists = result.subProblems.some((sp) => sp.id === problem.parent); expect(parentExists).toBe(true); } }); }); describe("Root Problem Naming", () => { it("should generate meaningful root problem name", () => { const result = decomposer.decompose("Build a scalable e-commerce platform", 2); const rootProblem = result.subProblems.find((sp) => sp.id === "root"); expect(rootProblem).toBeDefined(); expect(rootProblem!.name).not.toMatch(/Sub-problem/i); expect(rootProblem!.name.length).toBeGreaterThan(5); }); it("should preserve original problem as description", () => { const originalProblem = "Build a scalable e-commerce platform"; const result = decomposer.decompose(originalProblem, 2); const rootProblem = result.subProblems.find((sp) => sp.id === "root"); expect(rootProblem!.description).toBe(originalProblem); }); }); describe("Edge Cases", () => { it("should handle short problem statements", () => { const result = decomposer.decompose("Fix bug", 2); expect(result.subProblems.length).toBeGreaterThan(0); expect(result.subProblems[0].name).toBeDefined(); }); it("should handle long problem statements", () => { const longProblem = "Build a comprehensive enterprise resource planning system that includes inventory management, customer relationship management, human resources, financial accounting, supply chain management, and business intelligence reporting capabilities"; const result = decomposer.decompose(longProblem, 2); expect(result.subProblems.length).toBeGreaterThan(0); // Names should be reasonably sized for (const sp of result.subProblems) { expect(sp.name.length).toBeLessThan(100); } }); it("should handle problems with special characters", () => { const result = decomposer.decompose("Build API v2.0 (REST/GraphQL) with OAuth2.0", 2); expect(result.subProblems.length).toBeGreaterThan(0); expect(result.subProblems[0].name).toBeDefined(); }); }); });

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/keyurgolani/ThoughtMcp'

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