Skip to main content
Glama

DollhouseMCP

by DollhouseMCP
ConfigWizardCheck.test.ts9.18 kB
/** * Unit tests for ConfigWizardCheck * Tests automatic wizard detection and response wrapping functionality */ import { describe, it, expect, beforeEach, jest } from '@jest/globals'; // Mock modules using ESM approach jest.unstable_mockModule('../../../../src/config/ConfigManager.js', () => ({ ConfigManager: { getInstance: jest.fn(), resetForTesting: jest.fn() } })); jest.unstable_mockModule('../../../../src/utils/logger.js', () => ({ logger: { error: jest.fn(), warn: jest.fn(), info: jest.fn(), debug: jest.fn() } })); // Import after mocking const { ConfigManager } = await import('../../../../src/config/ConfigManager.js'); const { logger } = await import('../../../../src/utils/logger.js'); const { ConfigWizardCheck } = await import('../../../../src/config/ConfigWizardCheck.js'); describe('ConfigWizardCheck', () => { let wizardCheck: ConfigWizardCheck; let mockConfigManager: any; beforeEach(() => { jest.clearAllMocks(); // Setup mock ConfigManager instance mockConfigManager = { initialize: jest.fn().mockResolvedValue(undefined), getConfig: jest.fn().mockReturnValue({}), updateSetting: jest.fn().mockResolvedValue(undefined), }; // Mock getInstance to return our mock (ConfigManager.getInstance as jest.Mock).mockReturnValue(mockConfigManager); wizardCheck = new ConfigWizardCheck(); }); describe('checkIfWizardNeeded', () => { it('should return wizard prompt for new installation', async () => { mockConfigManager.getConfig.mockReturnValue({}); const result = await wizardCheck.checkIfWizardNeeded(); expect(result).toContain('Welcome to DollhouseMCP!'); expect(result).toContain('Ready to get started?'); expect(mockConfigManager.initialize).toHaveBeenCalledTimes(1); }); it('should return null when wizard is already completed', async () => { mockConfigManager.getConfig.mockReturnValue({ wizard: { completed: true, dismissed: false } }); const result = await wizardCheck.checkIfWizardNeeded(); expect(result).toBeNull(); }); it('should return null when wizard is dismissed', async () => { mockConfigManager.getConfig.mockReturnValue({ wizard: { dismissed: true, completed: false } }); const result = await wizardCheck.checkIfWizardNeeded(); expect(result).toBeNull(); }); it('should only check once per session', async () => { mockConfigManager.getConfig.mockReturnValue({}); // First call const result1 = await wizardCheck.checkIfWizardNeeded(); expect(result1).toContain('Welcome to DollhouseMCP!'); // Second call should return null without checking config const result2 = await wizardCheck.checkIfWizardNeeded(); expect(result2).toBeNull(); // Config should only be initialized once expect(mockConfigManager.initialize).toHaveBeenCalledTimes(1); }); it('should handle config initialization errors gracefully', async () => { const error = new Error('Config error'); mockConfigManager.initialize.mockRejectedValue(error); const result = await wizardCheck.checkIfWizardNeeded(); expect(result).toBeNull(); expect(logger.error).toHaveBeenCalledWith( 'Error checking config wizard status', { error } ); }); }); describe('wrapResponse', () => { beforeEach(() => { // Reset the hasCheckedWizard flag for each test wizardCheck = new ConfigWizardCheck(); (ConfigManager.getInstance as jest.Mock).mockReturnValue(mockConfigManager); }); it('should wrap response with wizard prompt when needed', async () => { mockConfigManager.getConfig.mockReturnValue({}); const originalResponse = { content: [{ type: 'text', text: 'Original content' }] }; const wrapped = await wizardCheck.wrapResponse(originalResponse); expect(wrapped.content).toHaveLength(3); expect(wrapped.content[0].text).toContain('Welcome to DollhouseMCP!'); expect(wrapped.content[1].text).toBe('\n\n---\n\n'); expect(wrapped.content[2]).toEqual({ type: 'text', text: 'Original content' }); }); it('should not mutate the original response object', async () => { mockConfigManager.getConfig.mockReturnValue({}); const originalResponse = { content: [{ type: 'text', text: 'Original content' }] }; const originalCopy = JSON.parse(JSON.stringify(originalResponse)); await wizardCheck.wrapResponse(originalResponse); expect(originalResponse).toEqual(originalCopy); }); it('should handle non-standard response formats', async () => { mockConfigManager.getConfig.mockReturnValue({}); const response = { text: 'Simple text response' }; const wrapped = await wizardCheck.wrapResponse(response); expect(wrapped.content).toHaveLength(3); expect(wrapped.content[0].text).toContain('Welcome to DollhouseMCP!'); expect(wrapped.content[2].text).toBe('Simple text response'); }); it('should handle response with message property', async () => { mockConfigManager.getConfig.mockReturnValue({}); const response = { message: 'Message response' }; const wrapped = await wizardCheck.wrapResponse(response); expect(wrapped.content).toHaveLength(3); expect(wrapped.content[2].text).toBe('Message response'); }); it('should handle primitive responses', async () => { mockConfigManager.getConfig.mockReturnValue({}); const response = 'String response'; const wrapped = await wizardCheck.wrapResponse(response); expect(wrapped.content).toHaveLength(3); expect(wrapped.content[2].text).toBe('String response'); }); it('should handle null responses', async () => { mockConfigManager.getConfig.mockReturnValue({}); const response = null; const wrapped = await wizardCheck.wrapResponse(response); expect(wrapped.content).toHaveLength(3); expect(wrapped.content[2].text).toBe('Tool executed successfully'); }); it('should return original response when wizard not needed', async () => { mockConfigManager.getConfig.mockReturnValue({ wizard: { completed: true, dismissed: false } }); const originalResponse = { content: [{ type: 'text', text: 'Original' }] }; const wrapped = await wizardCheck.wrapResponse(originalResponse); expect(wrapped).toBe(originalResponse); }); it('should preserve other response properties', async () => { mockConfigManager.getConfig.mockReturnValue({}); const originalResponse = { content: [{ type: 'text', text: 'Original' }], metadata: { key: 'value' }, status: 'success' }; const wrapped = await wizardCheck.wrapResponse(originalResponse); expect(wrapped.metadata).toEqual({ key: 'value' }); expect(wrapped.status).toBe('success'); }); }); describe('markWizardCompleted', () => { it('should update wizard completion settings', async () => { const mockDate = '2025-09-09T18:00:00.000Z'; jest.spyOn(Date.prototype, 'toISOString').mockReturnValue(mockDate); await wizardCheck.markWizardCompleted(); expect(mockConfigManager.updateSetting).toHaveBeenCalledWith('wizard.completed', true); expect(mockConfigManager.updateSetting).toHaveBeenCalledWith('wizard.completedAt', mockDate); }); }); describe('markWizardDismissed', () => { it('should update wizard dismissed setting', async () => { await wizardCheck.markWizardDismissed(); expect(mockConfigManager.updateSetting).toHaveBeenCalledWith('wizard.dismissed', true); }); }); describe('integration scenarios', () => { it('should handle wizard flow from new install to completion', async () => { // Start with new installation mockConfigManager.getConfig.mockReturnValue({}); // First interaction shows wizard const result1 = await wizardCheck.checkIfWizardNeeded(); expect(result1).toContain('Welcome to DollhouseMCP!'); // Subsequent interactions don't show wizard (same session) const result2 = await wizardCheck.checkIfWizardNeeded(); expect(result2).toBeNull(); // Mark as completed await wizardCheck.markWizardCompleted(); expect(mockConfigManager.updateSetting).toHaveBeenCalledWith('wizard.completed', true); }); it('should handle wizard dismissal flow', async () => { mockConfigManager.getConfig.mockReturnValue({}); // First check shows wizard const result1 = await wizardCheck.checkIfWizardNeeded(); expect(result1).toContain('Welcome to DollhouseMCP!'); // User dismisses wizard await wizardCheck.markWizardDismissed(); expect(mockConfigManager.updateSetting).toHaveBeenCalledWith('wizard.dismissed', true); }); }); });

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/DollhouseMCP/DollhouseMCP'

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