@smartsheet/smar-mcp
Version:
A Model Context Protocol (MCP) server for interacting with the Smartsheet API. This server provides tools for searching, retrieving, and updating Smartsheet sheets through the MCP protocol.
226 lines (225 loc) • 10 kB
JavaScript
import { TemplateEngine, PromptAutoCompletion, promptRegistry, createPrompt } from '../prompt-handler.js';
describe('PromptRegistry', () => {
beforeEach(() => {
// Clear the global registry before each test
promptRegistry.prompts.clear();
});
describe('register via createPrompt', () => {
it('should register a valid prompt', () => {
const prompt = {
name: 'test_prompt',
description: 'A test prompt',
template: 'Hello {name}!',
category: 'test',
version: '1.0.0'
};
expect(() => createPrompt(prompt)).not.toThrow();
expect(promptRegistry.has('test_prompt')).toBe(true);
});
it('should throw error for invalid prompt', () => {
const invalidPrompt = {
name: '',
description: 'Invalid prompt'
};
expect(() => createPrompt(invalidPrompt)).toThrow();
});
});
describe('get', () => {
it('should return existing prompt', () => {
const prompt = {
name: 'test_prompt',
description: 'A test prompt',
template: 'Hello {name}!',
category: 'test',
version: '1.0.0'
};
createPrompt(prompt);
const retrieved = promptRegistry.get('test_prompt');
expect(retrieved).toEqual(prompt);
});
it('should return undefined for non-existing prompt', () => {
expect(promptRegistry.get('non_existing')).toBeUndefined();
});
});
describe('getByCategory', () => {
it('should return prompts by category', () => {
const prompt1 = {
name: 'test1',
description: 'Test 1',
template: 'Template 1',
category: 'category1',
version: '1.0.0'
};
const prompt2 = {
name: 'test2',
description: 'Test 2',
template: 'Template 2',
category: 'category1',
version: '1.0.0'
};
const prompt3 = {
name: 'test3',
description: 'Test 3',
template: 'Template 3',
category: 'category2',
version: '1.0.0'
};
createPrompt(prompt1);
createPrompt(prompt2);
createPrompt(prompt3);
const category1Prompts = promptRegistry.getByCategory('category1');
expect(category1Prompts).toHaveLength(2);
expect(category1Prompts.map((p) => p.name)).toEqual(['test1', 'test2']);
});
});
});
describe('TemplateEngine', () => {
describe('substitute', () => {
it('should substitute template variables', () => {
const template = 'Hello {name}, you are {age} years old!';
const variables = { name: 'John', age: 30 };
const result = TemplateEngine.substitute(template, variables);
expect(result).toBe('Hello John, you are 30 years old!');
});
it('should handle missing variables by keeping placeholder', () => {
const template = 'Hello {name}, you are {age} years old!';
const variables = { name: 'John' };
const result = TemplateEngine.substitute(template, variables);
expect(result).toBe('Hello John, you are {age} years old!');
});
it('should handle empty variables object', () => {
const template = 'Hello {name}!';
const variables = {};
const result = TemplateEngine.substitute(template, variables);
expect(result).toBe('Hello {name}!');
});
});
describe('extractVariables', () => {
it('should extract variable names from template', () => {
const template = 'Hello {name}, you have {count} messages and {status} is active';
const variables = TemplateEngine.extractVariables(template);
expect(variables).toEqual(['name', 'count', 'status']);
});
it('should handle template with no variables', () => {
const template = 'Hello world!';
const variables = TemplateEngine.extractVariables(template);
expect(variables).toEqual([]);
});
it('should handle duplicate variables', () => {
const template = 'Hello {name}, goodbye {name}!';
const variables = TemplateEngine.extractVariables(template);
expect(variables).toEqual(['name', 'name']);
});
});
describe('validateVariables', () => {
it('should validate required variables are present', () => {
const template = 'Hello {name}, you are {age} years old!';
const variables = { name: 'John', age: 30 };
const requiredParams = [
{ name: 'name', required: true, type: 'string' },
{ name: 'age', required: true, type: 'number' }
];
const result = TemplateEngine.validateVariables(template, variables, requiredParams);
expect(result.isValid).toBe(true);
expect(result.missingVariables).toEqual([]);
});
it('should identify missing required variables', () => {
const template = 'Hello {name}, you are {age} years old!';
const variables = { name: 'John' };
const requiredParams = [
{ name: 'name', required: true, type: 'string' },
{ name: 'age', required: true, type: 'number' }
];
const result = TemplateEngine.validateVariables(template, variables, requiredParams);
expect(result.isValid).toBe(false);
expect(result.missingVariables).toEqual(['age']);
});
it('should handle optional parameters', () => {
const template = 'Hello {name}!';
const variables = { name: 'John' };
const requiredParams = [
{ name: 'name', required: true, type: 'string' },
{ name: 'age', required: false, type: 'number' }
];
const result = TemplateEngine.validateVariables(template, variables, requiredParams);
expect(result.isValid).toBe(true);
expect(result.missingVariables).toEqual([]);
});
});
});
describe('PromptAutoCompletion', () => {
describe('getSuggestions', () => {
it('should return sheet suggestions for sheet parameters', async () => {
const suggestions = await PromptAutoCompletion.getSuggestions('sheet_name');
expect(suggestions).toContain('Project Dashboard');
expect(suggestions).toContain('Sprint Backlog');
});
it('should return column suggestions for column parameters', async () => {
const suggestions = await PromptAutoCompletion.getSuggestions('column_name');
expect(suggestions).toContain('Task Name');
expect(suggestions).toContain('Status');
});
it('should return user suggestions for user parameters', async () => {
const suggestions = await PromptAutoCompletion.getSuggestions('assigned_user');
expect(suggestions).toContain('John Doe');
expect(suggestions).toContain('Jane Smith');
});
it('should return status suggestions for status parameters', async () => {
const suggestions = await PromptAutoCompletion.getSuggestions('task_status');
expect(suggestions).toContain('In Progress');
expect(suggestions).toContain('Complete');
});
it('should return priority suggestions for priority parameters', async () => {
const suggestions = await PromptAutoCompletion.getSuggestions('task_priority');
expect(suggestions).toContain('High');
expect(suggestions).toContain('Medium');
expect(suggestions).toContain('Low');
});
it('should return empty array for unknown parameter types', async () => {
const suggestions = await PromptAutoCompletion.getSuggestions('unknown_param');
expect(suggestions).toEqual([]);
});
});
});
describe('Global Prompt Registry', () => {
beforeEach(() => {
// Clear the global registry before each test
promptRegistry.prompts.clear();
});
describe('createPrompt', () => {
it('should register prompt in global registry', () => {
const prompt = {
name: 'global_test',
description: 'Global test prompt',
template: 'Global template {param}',
category: 'test',
version: '1.0.0'
};
createPrompt(prompt);
expect(promptRegistry.has('global_test')).toBe(true);
expect(promptRegistry.get('global_test')).toEqual(prompt);
});
it('should throw error for duplicate prompt names', () => {
const prompt = {
name: 'duplicate_test',
description: 'First prompt',
template: 'Template 1',
category: 'test',
version: '1.0.0'
};
createPrompt(prompt);
// Should not throw on first registration
expect(promptRegistry.has('duplicate_test')).toBe(true);
// Registering same name should overwrite (this is the current behavior)
const prompt2 = {
name: 'duplicate_test',
description: 'Second prompt',
template: 'Template 2',
category: 'test',
version: '2.0.0'
};
expect(() => createPrompt(prompt2)).not.toThrow();
expect(promptRegistry.get('duplicate_test')?.description).toBe('Second prompt');
});
});
});