Skip to main content
Glama

mcp-prompt-engine

by vasayxtx
main_test.go21.8 kB
package main import ( "bytes" "os" "path/filepath" "regexp" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/stretchr/testify/suite" ) type MainTestSuite struct { suite.Suite tempDir string } func TestMainTestSuite(t *testing.T) { suite.Run(t, new(MainTestSuite)) } func (s *MainTestSuite) SetupTest() { s.tempDir = s.T().TempDir() } // TestRenderTemplateErrorCases tests error cases for template rendering func (s *MainTestSuite) TestRenderTemplateErrorCases() { var buf bytes.Buffer // Test non-existent directory err := renderTemplate(&buf, "/non/existent/directory", "template_name", nil, true) assert.Error(s.T(), err, "renderTemplate() expected error for non-existent directory") // Test template execution error with missing template testFile := s.tempDir + "/error.tmpl" // Create a template that will cause execution error (missing template reference) err = os.WriteFile(testFile, []byte("{{/* Error template */}}\n{{template \"missing_template\" .}}"), 0644) require.NoError(s.T(), err, "Failed to write test file") var errorBuf bytes.Buffer err = renderTemplate(&errorBuf, s.tempDir, "error", nil, true) assert.Error(s.T(), err, "renderTemplate() expected execution error for missing template") // Test error with non-existent template in renderTemplate var nonExistentBuf bytes.Buffer err = renderTemplate(&nonExistentBuf, s.tempDir, "does_not_exist", nil, true) assert.Error(s.T(), err, "renderTemplate() expected error for non-existent template") } // TestRenderTemplate tests template rendering with environment variables and CLI arguments func (s *MainTestSuite) TestRenderTemplate() { tests := []struct { name string templateName string cliArgs map[string]string envVars map[string]string enableJSONArgs bool expectedOutput string shouldError bool }{ { name: "greeting template, no vars set", templateName: "greeting", enableJSONArgs: true, expectedOutput: "Hello <no value>!\nHave a great day!", shouldError: false, }, { name: "greeting template with env var", templateName: "greeting", envVars: map[string]string{ "NAME": "John", }, enableJSONArgs: true, expectedOutput: "Hello John!\nHave a great day!", shouldError: false, }, { name: "greeting template with CLI arg", templateName: "greeting", cliArgs: map[string]string{ "name": "Alice", }, enableJSONArgs: true, expectedOutput: "Hello Alice!\nHave a great day!", shouldError: false, }, { name: "CLI args override env vars", templateName: "greeting", cliArgs: map[string]string{ "name": "CLI_User", }, envVars: map[string]string{ "NAME": "ENV_User", }, enableJSONArgs: true, expectedOutput: "Hello CLI_User!\nHave a great day!", shouldError: false, }, { name: "template with partials, some env vars not set", templateName: "multiple_partials", envVars: map[string]string{ "TITLE": "Test Document", "NAME": "Bob", "VERSION": "1.0.0", }, enableJSONArgs: true, expectedOutput: "# Test Document\nCreated by: <no value>\n## Description\n<no value>\n## Details\nThis is a test template with multiple partials.\nHello Bob!\nVersion: 1.0.0", shouldError: false, }, { name: "template with partials, all env vars set", templateName: "multiple_partials", envVars: map[string]string{ "TITLE": "Test Document", "AUTHOR": "Test Author", "NAME": "Bob", "DESCRIPTION": "This is a test description", "VERSION": "1.0.0", }, expectedOutput: "# Test Document\nCreated by: Test Author\n## Description\nThis is a test description\n## Details\nThis is a test template with multiple partials.\nHello Bob!\nVersion: 1.0.0", enableJSONArgs: true, shouldError: false, }, { name: "conditional greeting with env vars, show extra message true", templateName: "conditional_greeting", envVars: map[string]string{ "NAME": "Alice", "SHOW_EXTRA_MESSAGE": "true", }, expectedOutput: "Hello Alice!\nThis is an extra message just for you.\nHave a good day.", enableJSONArgs: true, shouldError: false, }, { name: "conditional greeting with env vars, show extra message false", templateName: "conditional_greeting", envVars: map[string]string{ "NAME": "Bob", "SHOW_EXTRA_MESSAGE": "", }, expectedOutput: "Hello Bob!\nHave a good day.", enableJSONArgs: true, shouldError: false, }, { name: "conditional greeting with multiple CLI args", templateName: "conditional_greeting", cliArgs: map[string]string{ "name": "Bob", "show_extra_message": "true", }, expectedOutput: "Hello Bob!\nThis is an extra message just for you.\nHave a good day.", enableJSONArgs: true, shouldError: false, }, { name: "mix CLI args and env vars", templateName: "conditional_greeting", cliArgs: map[string]string{ "name": "Charlie", }, envVars: map[string]string{ "SHOW_EXTRA_MESSAGE": "true", }, expectedOutput: "Hello Charlie!\nThis is an extra message just for you.\nHave a good day.", enableJSONArgs: true, shouldError: false, }, { name: "CLI arg with empty value", templateName: "greeting", cliArgs: map[string]string{ "name": "", }, expectedOutput: "Hello !\nHave a great day!", enableJSONArgs: true, shouldError: false, }, { name: "template with logical operators (and/or)", templateName: "logical_operators", envVars: map[string]string{ "IS_ADMIN": "true", "HAS_PERMISSION": "true", "RESOURCE": "server logs", "SHOW_WARNING": "", "SHOW_ERROR": "true", "MESSAGE": "System maintenance scheduled", "IS_PREMIUM": "true", "IS_TRIAL": "", "FEATURE_ENABLED": "true", "FEATURE_NAME": "Advanced Analytics", "USERNAME": "admin_user", }, expectedOutput: "Admin Access: You have full access to server logs.\nAlert: System maintenance scheduled\nPremium Feature: Advanced Analytics is available.\nUser: admin_user", enableJSONArgs: true, shouldError: false, }, { name: "JSON parsing enabled - boolean true", templateName: "conditional_greeting", cliArgs: map[string]string{ "name": "JSONUser", "show_extra_message": "true", }, expectedOutput: "Hello JSONUser!\nThis is an extra message just for you.\nHave a good day.", enableJSONArgs: true, shouldError: false, }, { name: "JSON parsing enabled - boolean false", templateName: "conditional_greeting", cliArgs: map[string]string{ "name": "JSONUser", "show_extra_message": "false", }, expectedOutput: "Hello JSONUser!\nHave a good day.", enableJSONArgs: true, shouldError: false, }, { name: "JSON parsing disabled - boolean string remains string", templateName: "conditional_greeting", cliArgs: map[string]string{ "name": "StringUser", "show_extra_message": "true", }, enableJSONArgs: false, expectedOutput: "Hello StringUser!\nThis is an extra message just for you.\nHave a good day.", shouldError: false, }, { name: "JSON parsing disabled - false string treated as truthy", templateName: "conditional_greeting", cliArgs: map[string]string{ "name": "StringUser", "show_extra_message": "false", }, enableJSONArgs: false, expectedOutput: "Hello StringUser!\nThis is an extra message just for you.\nHave a good day.", shouldError: false, }, { name: "non-existent template", templateName: "non_existent_template", enableJSONArgs: true, expectedOutput: "", shouldError: true, }, } for _, tt := range tests { s.Run(tt.name, func() { // Save original environment originalEnv := make(map[string]string) for k := range tt.envVars { if v, ok := os.LookupEnv(k); ok { originalEnv[k] = v } } defer func() { for k := range tt.envVars { if v, ok := originalEnv[k]; ok { _ = os.Setenv(k, v) } else { _ = os.Unsetenv(k) } } }() // Set test environment variables for k, v := range tt.envVars { _ = os.Setenv(k, v) } var buf bytes.Buffer err := renderTemplate(&buf, "./testdata", tt.templateName, tt.cliArgs, tt.enableJSONArgs) if tt.shouldError { assert.Error(s.T(), err, "expected error but got none") } else { require.NoError(s.T(), err, "unexpected error") } output := normalizeNewlines(buf.String()) assert.Equal(s.T(), tt.expectedOutput, output, "unexpected output") }) } } // normalizeNewlines is a helper function to normalize newlines in strings func normalizeNewlines(s string) string { // Replace multiple consecutive newlines with single newlines for strings.Contains(s, "\n\n") { s = strings.ReplaceAll(s, "\n\n", "\n") } return strings.TrimSpace(s) } // removeANSIColors removes ANSI color escape sequences from a string func removeANSIColors(s string) string { ansiRegex := regexp.MustCompile(`\x1b\[[0-9;]*m`) return ansiRegex.ReplaceAllString(s, "") } // TestListTemplates tests the listTemplates function func (s *MainTestSuite) TestListTemplates() { tests := []struct { name string detailed bool expectedLines []string shouldError bool }{ { name: "list templates basic mode", detailed: false, expectedLines: []string{ templateText("conditional_greeting.tmpl"), templateText("greeting.tmpl"), templateText("greeting_with_partials.tmpl"), templateText("logical_operators.tmpl"), templateText("multiple_partials.tmpl"), templateText("range_scalars.tmpl"), templateText("range_structs.tmpl"), templateText("with_object.tmpl"), }, shouldError: false, }, { name: "list templates verbose mode", detailed: true, expectedLines: []string{ templateText("conditional_greeting.tmpl"), " Description: Conditional greeting template", " Variables: name, show_extra_message", templateText("greeting.tmpl"), " Description: Greeting standalone template with no partials", " Variables: name", templateText("greeting_with_partials.tmpl"), " Description: Greeting template with partial", " Variables: name", templateText("logical_operators.tmpl"), " Description: Template with logical operators (and/or) in if blocks", " Variables: feature_enabled, feature_name, has_permission, is_admin, is_premium, is_trial, message, resource, show_error, show_warning, username", templateText("multiple_partials.tmpl"), " Description: Template with multiple partials", " Variables: author, description, name, title, version", templateText("range_scalars.tmpl"), " Description: Template for testing range with JSON array of scalars", " Variables: numbers, result, tags", templateText("range_structs.tmpl"), " Description: Template for testing range with JSON array of structs", " Variables: age, name, role, total, users", templateText("with_object.tmpl"), " Description: Template for testing with + JSON object", " Variables: config, debug, environment, name, version", }, shouldError: false, }, } for _, tt := range tests { s.Run(tt.name, func() { var buf bytes.Buffer err := listTemplates(&buf, "./testdata", tt.detailed) if tt.shouldError { assert.Error(s.T(), err, "expected error but got none") } else { require.NoError(s.T(), err, "unexpected error") } output := buf.String() lines := strings.Split(strings.TrimSpace(output), "\n") // For basic mode, check exact match if !tt.detailed { assert.Equal(s.T(), len(tt.expectedLines), len(lines), "number of lines should match") for i, expectedLine := range tt.expectedLines { if i < len(lines) { assert.Equal(s.T(), expectedLine, lines[i], "line %d should match", i) } } return } // For detailed mode, check exact match including variables lineIndex := 0 for _, expectedLine := range tt.expectedLines { if lineIndex >= len(lines) { s.T().Fatalf("Not enough lines in output. Expected at least %d, got %d", len(tt.expectedLines), len(lines)) } if strings.HasPrefix(expectedLine, " Variables: ") { // Remove ANSI color codes from the actual line for comparison actualLine := removeANSIColors(lines[lineIndex]) assert.Equal(s.T(), expectedLine, actualLine, "line %d should match (variables are now sorted)", lineIndex) } else { assert.Equal(s.T(), expectedLine, lines[lineIndex], "line %d should match", lineIndex) } lineIndex++ } }) } } // TestListTemplatesErrorCases tests error cases for listTemplates func (s *MainTestSuite) TestListTemplatesErrorCases() { var buf bytes.Buffer // Test non-existent directory err := listTemplates(&buf, "/non/existent/directory", false) assert.Error(s.T(), err, "listTemplates() expected error for non-existent directory") // Test empty directory emptyDir := s.T().TempDir() var emptyBuf bytes.Buffer err = listTemplates(&emptyBuf, emptyDir, true) require.NoError(s.T(), err, "listTemplates() should not error for empty directory") output := emptyBuf.String() assert.Contains(s.T(), output, "No templates found", "should indicate no templates found") emptyBuf.Reset() err = listTemplates(&emptyBuf, emptyDir, false) require.NoError(s.T(), err, "listTemplates() should not error for empty directory") require.Empty(s.T(), emptyBuf.String()) } // TestListTemplatesWithPartials tests that partials are excluded from listing func (s *MainTestSuite) TestListTemplatesWithPartials() { // Create a temp directory with templates and partials tempDir := s.T().TempDir() // Create regular template err := os.WriteFile(tempDir+"/regular.tmpl", []byte("{{/* Regular template */}}\nHello!"), 0644) require.NoError(s.T(), err) // Create partial template (should be excluded) err = os.WriteFile(tempDir+"/_partial.tmpl", []byte("{{/* Partial template */}}\nThis is a partial"), 0644) require.NoError(s.T(), err) var buf bytes.Buffer err = listTemplates(&buf, tempDir, false) require.NoError(s.T(), err) output := buf.String() assert.Contains(s.T(), output, "regular.tmpl", "should include regular template") assert.NotContains(s.T(), output, "_partial.tmpl", "should exclude partial template") } // TestValidateTemplates tests the validateTemplates function func (s *MainTestSuite) TestValidateTemplates() { tests := []struct { name string templateName string templates map[string]string expectedOutput []string shouldError bool }{ { name: "validate all valid templates", templateName: "", templates: map[string]string{ "valid1.tmpl": "{{/* Valid template 1 */}}\nHello {{.name}}!", "valid2.tmpl": "{{/* Valid template 2 */}}\nWelcome {{.user}}!", }, expectedOutput: []string{ "✓ valid1.tmpl - Valid", "✓ valid2.tmpl - Valid", }, shouldError: false, }, { name: "validate specific valid template", templateName: "valid1.tmpl", templates: map[string]string{ "valid1.tmpl": "{{/* Valid template 1 */}}\nHello {{.name}}!", "valid2.tmpl": "{{/* Valid template 2 */}}\nWelcome {{.user}}!", }, expectedOutput: []string{ "✓ valid1.tmpl - Valid", }, shouldError: false, }, { name: "validate specific valid template without extension", templateName: "valid1", templates: map[string]string{ "valid1.tmpl": "{{/* Valid template 1 */}}\nHello {{.name}}!", "valid2.tmpl": "{{/* Valid template 2 */}}\nWelcome {{.user}}!", }, expectedOutput: []string{ "✓ valid1.tmpl - Valid", }, shouldError: false, }, { name: "validate template with missing reference", templateName: "", templates: map[string]string{ "valid.tmpl": "{{/* Valid template */}}\nHello {{.name}}!", "missing_ref.tmpl": "{{/* Template with missing reference */}}\n{{template \"nonexistent\" .}}", }, expectedOutput: []string{ "✗ missing_ref.tmpl - Error:", "✓ valid.tmpl - Valid", }, shouldError: true, }, { name: "validate specific template with missing reference", templateName: "missing_ref.tmpl", templates: map[string]string{ "valid.tmpl": "{{/* Valid template */}}\nHello {{.name}}!", "missing_ref.tmpl": "{{/* Template with missing reference */}}\n{{template \"nonexistent\" .}}", }, expectedOutput: []string{ "✗ missing_ref.tmpl - Error:", }, shouldError: true, }, { name: "validate template with partials", templateName: "", templates: map[string]string{ "main.tmpl": "{{/* Main template */}}\n{{template \"_partial\" .}}", "_partial.tmpl": "{{/* Partial template */}}\nHello {{.name}}!", }, expectedOutput: []string{ "✓ main.tmpl - Valid", }, shouldError: false, }, } for _, tt := range tests { s.Run(tt.name, func() { // Create temp directory and test templates tempDir := s.T().TempDir() for filename, content := range tt.templates { err := os.WriteFile(filepath.Join(tempDir, filename), []byte(content), 0644) require.NoError(s.T(), err) } // Run validateTemplates and capture output from buffer var buf bytes.Buffer err := validateTemplates(&buf, tempDir, tt.templateName) if tt.shouldError { assert.Error(s.T(), err, "expected error but got none") } else { require.NoError(s.T(), err, "unexpected error") } output := buf.String() lines := strings.Split(strings.TrimSpace(output), "\n") // Check that all expected output lines are present for _, expectedLine := range tt.expectedOutput { found := false for _, line := range lines { // Remove ANSI color codes for comparison cleanLine := removeANSIColors(line) cleanExpected := removeANSIColors(expectedLine) if strings.Contains(cleanLine, cleanExpected) || (strings.Contains(cleanExpected, "Error:") && strings.Contains(cleanLine, "Error:")) { found = true break } } assert.True(s.T(), found, "expected line '%s' not found in output: %s", expectedLine, output) } }) } } // TestValidateTemplatesErrorCases tests error cases for validateTemplates func (s *MainTestSuite) TestValidateTemplatesErrorCases() { tests := []struct { name string promptsDir string templateName string setupFunc func(string) error expectedError string }{ { name: "non-existent directory", promptsDir: "/non/existent/directory", templateName: "", expectedError: "read prompts directory", }, { name: "non-existent specific template", promptsDir: "", templateName: "does_not_exist.tmpl", setupFunc: func(dir string) error { return os.WriteFile(filepath.Join(dir, "exists.tmpl"), []byte("{{/* Exists */}}\nHello!"), 0644) }, expectedError: "not found", }, { name: "non-existent specific template without extension", promptsDir: "", templateName: "does_not_exist", setupFunc: func(dir string) error { return os.WriteFile(filepath.Join(dir, "exists.tmpl"), []byte("{{/* Exists */}}\nHello!"), 0644) }, expectedError: "not found", }, { name: "empty directory", promptsDir: "", setupFunc: func(dir string) error { return nil }, }, } for _, tt := range tests { s.Run(tt.name, func() { var tempDir string if tt.promptsDir == "" { tempDir = s.T().TempDir() if tt.setupFunc != nil { err := tt.setupFunc(tempDir) require.NoError(s.T(), err) } } else { tempDir = tt.promptsDir } var buf bytes.Buffer err := validateTemplates(&buf, tempDir, tt.templateName) if tt.expectedError != "" { assert.Error(s.T(), err) assert.Contains(s.T(), err.Error(), tt.expectedError) } else { // For empty directory case, should not error but output warning require.NoError(s.T(), err) output := buf.String() assert.Contains(s.T(), output, "No templates found") } }) } } // TestValidateTemplatesOutput tests the output formatting of validateTemplates func (s *MainTestSuite) TestValidateTemplatesOutput() { // Test with syntax error that occurs during parsing tempDir := s.T().TempDir() // Invalid template with syntax error err := os.WriteFile(filepath.Join(tempDir, "invalid.tmpl"), []byte("{{/* Invalid template */}}\nHello {{.name}"), 0644) require.NoError(s.T(), err) var buf bytes.Buffer err = validateTemplates(&buf, tempDir, "") assert.Error(s.T(), err) assert.Contains(s.T(), err.Error(), "parse prompts directory") // Test with valid templates to verify successful output formatting tempDir2 := s.T().TempDir() // Valid template err = os.WriteFile(filepath.Join(tempDir2, "valid.tmpl"), []byte("{{/* Valid template */}}\nHello {{.name}}!"), 0644) require.NoError(s.T(), err) // Run validateTemplates and capture output from buffer var buf2 bytes.Buffer err = validateTemplates(&buf2, tempDir2, "") require.NoError(s.T(), err) output := buf2.String() cleanOutput := removeANSIColors(output) // Check that output contains the template assert.Contains(s.T(), cleanOutput, "valid.tmpl") // Check formatting - should contain success icon assert.Contains(s.T(), cleanOutput, "✓") // Success icon // Check status message assert.Contains(s.T(), cleanOutput, "Valid") }

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/vasayxtx/mcp-prompt-engine'

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