406 lines
12 KiB
C#
Executable File
406 lines
12 KiB
C#
Executable File
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
using Microsoft.Extensions.Logging;
|
|
using System.Text.Json;
|
|
|
|
namespace MarketAlly.AIPlugin.Context.Tests
|
|
{
|
|
[TestClass]
|
|
public class ContextSearchPluginTests
|
|
{
|
|
private ContextSearchPlugin _searchPlugin = null!;
|
|
private ContextStoragePlugin _storagePlugin = null!;
|
|
private string _testDirectory = null!;
|
|
private ILogger<ContextSearchPlugin> _logger = null!;
|
|
|
|
[TestInitialize]
|
|
public async Task Setup()
|
|
{
|
|
_testDirectory = Path.Combine(Path.GetTempPath(), $"context-search-test-{Guid.NewGuid():N}");
|
|
Directory.CreateDirectory(_testDirectory);
|
|
|
|
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
|
|
_logger = loggerFactory.CreateLogger<ContextSearchPlugin>();
|
|
_searchPlugin = new ContextSearchPlugin();
|
|
_storagePlugin = new ContextStoragePlugin();
|
|
|
|
// Create test data
|
|
await CreateTestData();
|
|
}
|
|
|
|
[TestCleanup]
|
|
public void Cleanup()
|
|
{
|
|
if (Directory.Exists(_testDirectory))
|
|
{
|
|
Directory.Delete(_testDirectory, recursive: true);
|
|
}
|
|
}
|
|
|
|
private async Task CreateTestData()
|
|
{
|
|
var testEntries = new[]
|
|
{
|
|
new { type = "decision", content = "We decided to use React for the frontend", summary = "Frontend framework decision", tags = "react,frontend,decision", priority = "high" },
|
|
new { type = "insight", content = "The API performance improved by 50% after optimization", summary = "API performance insight", tags = "api,performance,optimization", priority = "medium" },
|
|
new { type = "codechange", content = "Refactored authentication module using JWT tokens", summary = "Authentication refactoring", tags = "auth,jwt,refactor", priority = "high" },
|
|
new { type = "conversation", content = "Discussed database migration strategy with the team", summary = "Database migration discussion", tags = "database,migration,team", priority = "low" },
|
|
new { type = "milestone", content = "Completed user authentication system implementation", summary = "Auth system milestone", tags = "auth,milestone,complete", priority = "critical" }
|
|
};
|
|
|
|
foreach (var entry in testEntries)
|
|
{
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["contextType"] = entry.type,
|
|
["content"] = entry.content,
|
|
["summary"] = entry.summary,
|
|
["tags"] = entry.tags,
|
|
["priority"] = entry.priority,
|
|
["projectPath"] = _testDirectory
|
|
};
|
|
|
|
await _storagePlugin.ExecuteAsync(parameters);
|
|
await Task.Delay(10); // Small delay to ensure different timestamps
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Search_BasicKeyword_ReturnsRelevantResults()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["query"] = "authentication",
|
|
["projectPath"] = _testDirectory,
|
|
["maxResults"] = 10
|
|
};
|
|
|
|
// Act
|
|
var result = await _searchPlugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var resultData = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(result.Data));
|
|
Assert.IsTrue(resultData.TryGetProperty("Results", out var resultsArray));
|
|
|
|
var results = resultsArray.EnumerateArray().ToList();
|
|
Assert.IsTrue(results.Count >= 2); // Should find auth-related entries
|
|
|
|
// Verify that results contain auth-related content
|
|
var foundAuthEntries = results.Any(r =>
|
|
r.TryGetProperty("Summary", out var summary) &&
|
|
summary.GetString()!.Contains("Auth", StringComparison.OrdinalIgnoreCase));
|
|
Assert.IsTrue(foundAuthEntries);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Search_MultipleKeywords_CombinesResults()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["query"] = "api performance optimization",
|
|
["projectPath"] = _testDirectory,
|
|
["includeContent"] = true
|
|
};
|
|
|
|
// Act
|
|
var result = await _searchPlugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var resultData = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(result.Data));
|
|
Assert.IsTrue(resultData.TryGetProperty("Results", out var resultsArray));
|
|
|
|
var results = resultsArray.EnumerateArray().ToList();
|
|
Assert.IsTrue(results.Count >= 1);
|
|
|
|
// Should find the API performance entry
|
|
var foundApiEntry = results.Any(r =>
|
|
r.TryGetProperty("Summary", out var summary) &&
|
|
summary.GetString()!.Contains("API performance", StringComparison.OrdinalIgnoreCase));
|
|
Assert.IsTrue(foundApiEntry);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Search_ByContextType_FiltersCorrectly()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["query"] = "system",
|
|
["contextType"] = "decision",
|
|
["projectPath"] = _testDirectory
|
|
};
|
|
|
|
// Act
|
|
var result = await _searchPlugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var resultData = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(result.Data));
|
|
Assert.IsTrue(resultData.TryGetProperty("Results", out var resultsArray));
|
|
|
|
var results = resultsArray.EnumerateArray().ToList();
|
|
|
|
// All results should be of type "decision"
|
|
foreach (var resultItem in results)
|
|
{
|
|
Assert.IsTrue(resultItem.TryGetProperty("Type", out var type));
|
|
Assert.AreEqual("decision", type.GetString());
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Search_ByPriority_FiltersCorrectly()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["query"] = "auth",
|
|
["priority"] = "high",
|
|
["projectPath"] = _testDirectory
|
|
};
|
|
|
|
// Act
|
|
var result = await _searchPlugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var resultData = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(result.Data));
|
|
Assert.IsTrue(resultData.TryGetProperty("Results", out var resultsArray));
|
|
|
|
var results = resultsArray.EnumerateArray().ToList();
|
|
|
|
// All results should be high priority
|
|
foreach (var resultItem in results)
|
|
{
|
|
Assert.IsTrue(resultItem.TryGetProperty("Priority", out var priority));
|
|
Assert.AreEqual("high", priority.GetString());
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Search_ByTags_FiltersCorrectly()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["query"] = "system",
|
|
["tags"] = "frontend,api",
|
|
["projectPath"] = _testDirectory
|
|
};
|
|
|
|
// Act
|
|
var result = await _searchPlugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var resultData = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(result.Data));
|
|
Assert.IsTrue(resultData.TryGetProperty("Results", out var resultsArray));
|
|
|
|
var results = resultsArray.EnumerateArray().ToList();
|
|
|
|
// Results should contain entries with frontend or api tags
|
|
// Note: May return 0 results if no entries match the tag filter
|
|
Assert.IsTrue(results.Count >= 0);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Search_MaxResults_LimitsOutput()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["query"] = "system", // Should match multiple entries
|
|
["maxResults"] = 2,
|
|
["projectPath"] = _testDirectory
|
|
};
|
|
|
|
// Act
|
|
var result = await _searchPlugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var resultData = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(result.Data));
|
|
Assert.IsTrue(resultData.TryGetProperty("Results", out var resultsArray));
|
|
|
|
var results = resultsArray.EnumerateArray().ToList();
|
|
Assert.IsTrue(results.Count <= 2);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Search_IncludeContentFalse_ExcludesContent()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["query"] = "authentication",
|
|
["includeContent"] = false,
|
|
["projectPath"] = _testDirectory
|
|
};
|
|
|
|
// Act
|
|
var result = await _searchPlugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var resultData = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(result.Data));
|
|
Assert.IsTrue(resultData.TryGetProperty("Results", out var resultsArray));
|
|
|
|
var results = resultsArray.EnumerateArray().ToList();
|
|
|
|
// Content should be null or empty for all results
|
|
foreach (var resultItem in results)
|
|
{
|
|
if (resultItem.TryGetProperty("Content", out var content))
|
|
{
|
|
var contentValue = content.GetString();
|
|
Assert.IsTrue(string.IsNullOrEmpty(contentValue));
|
|
}
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Search_NoStorageDirectory_ReturnsEmptyResults()
|
|
{
|
|
// Arrange
|
|
var nonExistentDir = Path.Combine(_testDirectory, "non-existent");
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["query"] = "anything",
|
|
["projectPath"] = nonExistentDir
|
|
};
|
|
|
|
// Act
|
|
var result = await _searchPlugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var resultData = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(result.Data));
|
|
Assert.IsTrue(resultData.TryGetProperty("Results", out var resultsArray));
|
|
Assert.IsTrue(resultData.TryGetProperty("TotalFound", out var totalFound));
|
|
|
|
var results = resultsArray.EnumerateArray().ToList();
|
|
Assert.AreEqual(0, results.Count);
|
|
Assert.AreEqual(0, totalFound.GetInt32());
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Search_EmptyQuery_ReturnsError()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["query"] = "",
|
|
["projectPath"] = _testDirectory
|
|
};
|
|
|
|
// Act
|
|
var result = await _searchPlugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsFalse(result.Success);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Search_CaseInsensitive_FindsResults()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["query"] = "REACT FRONTEND", // Uppercase query
|
|
["projectPath"] = _testDirectory
|
|
};
|
|
|
|
// Act
|
|
var result = await _searchPlugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var resultData = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(result.Data));
|
|
Assert.IsTrue(resultData.TryGetProperty("Results", out var resultsArray));
|
|
|
|
var results = resultsArray.EnumerateArray().ToList();
|
|
Assert.IsTrue(results.Count >= 1); // Should find React entry despite case difference
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Search_RelevanceScoring_OrdersResultsCorrectly()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["query"] = "authentication JWT",
|
|
["projectPath"] = _testDirectory,
|
|
["includeContent"] = true
|
|
};
|
|
|
|
// Act
|
|
var result = await _searchPlugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var resultData = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(result.Data));
|
|
Assert.IsTrue(resultData.TryGetProperty("Results", out var resultsArray));
|
|
|
|
var results = resultsArray.EnumerateArray().ToList();
|
|
|
|
if (results.Count > 1)
|
|
{
|
|
// Verify that results with "JWT" come before those without
|
|
var firstResult = results[0];
|
|
Assert.IsTrue(firstResult.TryGetProperty("Summary", out var summary) ||
|
|
firstResult.TryGetProperty("Content", out var content));
|
|
|
|
var hasJWT = (firstResult.TryGetProperty("Summary", out var sum) &&
|
|
sum.GetString()!.Contains("JWT", StringComparison.OrdinalIgnoreCase)) ||
|
|
(firstResult.TryGetProperty("Content", out var cont) &&
|
|
cont.GetString()!.Contains("JWT", StringComparison.OrdinalIgnoreCase));
|
|
|
|
Assert.IsTrue(hasJWT, "Most relevant result should contain JWT");
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task Search_WithMatchedTerms_ReturnsMatchInfo()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["query"] = "React frontend framework",
|
|
["projectPath"] = _testDirectory
|
|
};
|
|
|
|
// Act
|
|
var result = await _searchPlugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var resultData = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(result.Data));
|
|
Assert.IsTrue(resultData.TryGetProperty("Results", out var resultsArray));
|
|
|
|
var results = resultsArray.EnumerateArray().ToList();
|
|
|
|
if (results.Count > 0)
|
|
{
|
|
var firstResult = results[0];
|
|
Assert.IsTrue(firstResult.TryGetProperty("MatchedTerms", out var matchedTerms));
|
|
|
|
var terms = matchedTerms.EnumerateArray().Select(t => t.GetString()).ToList();
|
|
Assert.IsTrue(terms.Count > 0, "Should have matched terms");
|
|
}
|
|
}
|
|
}
|
|
} |