UNPKG

@boundless-oss/atlas

Version:

Atlas - MCP Server for comprehensive startup project management

339 lines (285 loc) 12.5 kB
import { describe, it, expect, beforeEach, vi } from 'vitest'; import { BusinessAnalyzer } from '../analyzer.js'; import { BusinessPlan, MarketAnalysis, CompetitorAnalysis } from '../types.js'; import { ConfigManager } from '../../../config/config-manager.js'; // Mock ConfigManager vi.mock('../../../config/config-manager.js'); // Mock fs vi.mock('fs', () => ({ promises: { readFile: vi.fn().mockRejectedValue(new Error('File not found')), writeFile: vi.fn().mockResolvedValue(undefined), mkdir: vi.fn().mockResolvedValue(undefined) } })); describe('BusinessAnalyzer', () => { let businessAnalyzer: BusinessAnalyzer; let mockConfigManager: vi.Mocked<ConfigManager>; it('should create BusinessAnalyzer instance', () => { const config = {} as any; const analyzer = new BusinessAnalyzer(config); expect(analyzer).toBeInstanceOf(BusinessAnalyzer); }); beforeEach(async () => { mockConfigManager = { getStorageManager: vi.fn().mockReturnValue({ getStorageLocation: vi.fn().mockResolvedValue({ data: '/tmp/test-data' }) }) } as any; businessAnalyzer = new BusinessAnalyzer(mockConfigManager); await businessAnalyzer.init(); }); describe('generateBusinessPlan', () => { it('should generate business plan with lean canvas template', async () => { const options = { businessIdea: 'AI-powered project management tool', targetMarket: 'Software development teams', businessModel: 'SaaS subscription', timeline: 12, template: 'lean_canvas' as const, }; const businessPlan = await businessAnalyzer.generateBusinessPlan(options); expect(businessPlan.id).toMatch(/^plan-[a-z0-9-]+$/); expect(businessPlan.businessIdea).toBe(options.businessIdea); expect(businessPlan.targetMarket).toBe(options.targetMarket); expect(businessPlan.businessModel).toBe(options.businessModel); expect(businessPlan.timeline).toBe(options.timeline); expect(businessPlan.template).toBe('lean_canvas'); expect(businessPlan.sections).toBeDefined(); expect(businessPlan.sections.length).toBeGreaterThan(0); }); it('should generate business plan with traditional template', async () => { const options = { businessIdea: 'E-commerce platform', targetMarket: 'Small businesses', businessModel: 'Commission-based', timeline: 24, template: 'traditional' as const, }; const businessPlan = await businessAnalyzer.generateBusinessPlan(options); expect(businessPlan.template).toBe('traditional'); expect(businessPlan.sections).toBeDefined(); expect(businessPlan.createdAt).toBeDefined(); expect(businessPlan.updatedAt).toBeDefined(); }); it('should include financial projections', async () => { const options = { businessIdea: 'Mobile app', targetMarket: 'Consumers', businessModel: 'Freemium', timeline: 18, includeFinancials: true, template: 'traditional', }; const businessPlan = await businessAnalyzer.generateBusinessPlan(options); expect(businessPlan.financials).toBeDefined(); expect(businessPlan.financials?.revenue).toBeDefined(); expect(businessPlan.financials?.expenses).toBeDefined(); expect(businessPlan.financials?.projections).toBeDefined(); }); }); describe('analyzeMarket', () => { it('should analyze market for given industry and target market', async () => { const options = { industry: 'Software Development', targetMarket: 'Small to medium businesses', geographicScope: 'North America', }; const marketAnalysis = await businessAnalyzer.analyzeMarket(options); expect(marketAnalysis.id).toMatch(/^market-[a-z0-9-]+$/); expect(marketAnalysis.industry).toBe(options.industry); expect(marketAnalysis.targetMarket).toBe(options.targetMarket); expect(marketAnalysis.geographicScope).toBe(options.geographicScope); expect(marketAnalysis.marketSize).toBeDefined(); expect(marketAnalysis.trends).toBeDefined(); expect(marketAnalysis.trends.length).toBeGreaterThan(0); expect(marketAnalysis.opportunities).toBeDefined(); expect(marketAnalysis.challenges).toBeDefined(); }); it('should include demographic analysis when requested', async () => { const options = { industry: 'E-commerce', targetMarket: 'Millennials', geographicScope: 'United States', includeDemographics: true, }; const marketAnalysis = await businessAnalyzer.analyzeMarket(options); expect(marketAnalysis.demographics).toBeDefined(); expect(marketAnalysis.demographics?.ageRange).toBeDefined(); expect(marketAnalysis.demographics?.income).toBeDefined(); expect(marketAnalysis.demographics?.behavior).toBeDefined(); }); }); describe('analyzeCompetitors', () => { it('should analyze competitors in the industry', async () => { const options = { businessIdea: 'AI-powered project management tool', industry: 'Project Management Software', competitors: ['Asana', 'Jira', 'Trello'], analysisDepth: 'detailed', includeStrengthWeakness: true, }; const competitorAnalysis = await businessAnalyzer.analyzeCompetitors(options); expect(competitorAnalysis).toBeDefined(); expect(competitorAnalysis.industry).toBe(options.industry); expect(competitorAnalysis.competitors).toBeDefined(); expect(competitorAnalysis.competitors.length).toBeGreaterThan(0); const firstCompetitor = competitorAnalysis.competitors[0]; expect(firstCompetitor.name).toBeDefined(); expect(firstCompetitor.marketShare).toBeDefined(); expect(firstCompetitor.strengths).toBeDefined(); expect(firstCompetitor.weaknesses).toBeDefined(); expect(firstCompetitor.pricingModel).toBeDefined(); }); it('should include competitive positioning', async () => { const options = { businessIdea: 'Simple CRM for freelancers', industry: 'CRM Software', competitors: ['Salesforce', 'HubSpot', 'Pipedrive'], analysisDepth: 'comprehensive', includeStrengthWeakness: true, }; const competitorAnalysis = await businessAnalyzer.analyzeCompetitors(options); expect(competitorAnalysis.positioning).toBeDefined(); expect(competitorAnalysis.positioning?.marketGaps).toBeDefined(); expect(competitorAnalysis.positioning?.differentiationOpportunities).toBeDefined(); expect(competitorAnalysis.positioning?.competitiveAdvantages).toBeDefined(); }); }); describe('generatePitchDeck', () => { it('should generate pitch deck with standard slides', async () => { const options = { businessIdea: 'AI-powered project management', problemStatement: 'Teams struggle with project complexity', solution: 'AI assistant that simplifies project management', targetMarket: 'Software development teams', businessModel: 'SaaS subscription', competitiveAdvantage: 'AI-driven insights', fundingAsk: '$2M seed round', template: 'investor', }; const pitchDeck = await businessAnalyzer.generatePitchDeck(options); expect(pitchDeck).toBeDefined(); expect(pitchDeck.businessIdea).toBe(options.businessIdea); expect(pitchDeck.template).toBe(options.template); expect(pitchDeck.markdown).toBeDefined(); expect(pitchDeck.keyMessages).toBeDefined(); expect(pitchDeck.presentationTips).toBeDefined(); }); it('should customize slides for different audiences', async () => { const optionsForPartners = { businessIdea: 'B2B marketplace platform', problemStatement: 'Suppliers struggle to find buyers', solution: 'Digital marketplace connecting suppliers and buyers', targetMarket: 'Manufacturing industry', businessModel: 'Transaction fees', competitiveAdvantage: 'Industry-specific features', template: 'partner', }; const pitchDeck = await businessAnalyzer.generatePitchDeck(optionsForPartners); expect(pitchDeck.template).toBe('partner'); expect(pitchDeck.markdown).toBeDefined(); }); }); describe('assessStartup', () => { it('should assess startup maturity across all dimensions', async () => { const options = { businessPlanId: 'plan-789', currentStage: 'mvp', teamSize: 5, monthsInDevelopment: 8, hasCustomers: true, monthlyRevenue: 5000, }; const assessment = await businessAnalyzer.assessStartup(options); expect(assessment.id).toMatch(/^assessment-[a-f0-9-]+$/); expect(assessment.businessPlanId).toBe(options.businessPlanId); expect(assessment.overallScore).toBeGreaterThan(0); expect(assessment.overallScore).toBeLessThanOrEqual(100); expect(assessment.maturityLevel).toBeDefined(); expect(assessment.dimensions).toBeDefined(); // Check all key dimensions are assessed expect(assessment.dimensions.product).toBeDefined(); expect(assessment.dimensions.market).toBeDefined(); expect(assessment.dimensions.team).toBeDefined(); expect(assessment.dimensions.financial).toBeDefined(); expect(assessment.dimensions.operations).toBeDefined(); }); it('should provide recommendations for improvement', async () => { const options = { businessPlanId: 'plan-101', currentStage: 'idea', teamSize: 1, monthsInDevelopment: 1, hasCustomers: false, monthlyRevenue: 0, }; const assessment = await businessAnalyzer.assessStartup(options); expect(assessment.recommendations).toBeDefined(); expect(assessment.recommendations.length).toBeGreaterThan(0); expect(assessment.nextSteps).toBeDefined(); expect(assessment.nextSteps.length).toBeGreaterThan(0); }); }); describe('planFundingStrategy', () => { it('should plan funding strategy based on business needs', async () => { const options = { businessPlanId: 'plan-202', fundingGoal: 500000, currentStage: 'mvp', useOfFunds: ['product-development', 'marketing', 'hiring'], timeline: 6, }; const fundingStrategy = await businessAnalyzer.planFundingStrategy(options); expect(fundingStrategy.id).toMatch(/^funding-[a-f0-9-]+$/); expect(fundingStrategy.businessPlanId).toBe(options.businessPlanId); expect(fundingStrategy.fundingGoal).toBe(options.fundingGoal); expect(fundingStrategy.recommendedSources).toBeDefined(); expect(fundingStrategy.recommendedSources.length).toBeGreaterThan(0); expect(fundingStrategy.timeline).toBeDefined(); expect(fundingStrategy.milestones).toBeDefined(); }); it('should recommend appropriate funding sources for stage', async () => { const seedStageOptions = { businessPlanId: 'plan-303', fundingGoal: 100000, currentStage: 'idea', timeline: 3, }; const seedStrategy = await businessAnalyzer.planFundingStrategy(seedStageOptions); expect(seedStrategy.recommendedSources).toContain('angel-investors'); expect(seedStrategy.recommendedSources).toContain('grants'); const seriesAOptions = { businessPlanId: 'plan-404', fundingGoal: 2000000, currentStage: 'growth', timeline: 12, }; const seriesAStrategy = await businessAnalyzer.planFundingStrategy(seriesAOptions); expect(seriesAStrategy.recommendedSources).toContain('venture-capital'); }); }); describe('error handling', () => { it('should handle invalid business plan parameters', async () => { const invalidOptions = { businessIdea: '', // Empty business idea targetMarket: 'Invalid market', businessModel: 'Unknown model', timeline: -1, // Invalid timeline }; await expect( businessAnalyzer.generateBusinessPlan(invalidOptions) ).rejects.toThrow(); }); it('should handle missing required parameters', async () => { const incompleteOptions = { // Missing required fields }; await expect( businessAnalyzer.analyzeMarket(incompleteOptions as any) ).rejects.toThrow(); }); }); });