344 lines
10 KiB
C#
Executable File
344 lines
10 KiB
C#
Executable File
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
using Microsoft.Extensions.Logging;
|
|
using MarketAlly.AIPlugin.Context.Configuration;
|
|
using MarketAlly.AIPlugin.Context.Security;
|
|
using System.Text.Json;
|
|
|
|
namespace MarketAlly.AIPlugin.Context.Tests
|
|
{
|
|
[TestClass]
|
|
public class ContextStoragePluginTests
|
|
{
|
|
private ContextStoragePlugin _plugin = null!;
|
|
private string _testDirectory = null!;
|
|
private ILogger<ContextStoragePlugin> _logger = null!;
|
|
|
|
[TestInitialize]
|
|
public void Setup()
|
|
{
|
|
_testDirectory = Path.Combine(Path.GetTempPath(), $"context-test-{Guid.NewGuid():N}");
|
|
Directory.CreateDirectory(_testDirectory);
|
|
|
|
var loggerFactory = LoggerFactory.Create(builder => builder.AddConsole());
|
|
_logger = loggerFactory.CreateLogger<ContextStoragePlugin>();
|
|
_plugin = new ContextStoragePlugin();
|
|
}
|
|
|
|
[TestCleanup]
|
|
public void Cleanup()
|
|
{
|
|
if (Directory.Exists(_testDirectory))
|
|
{
|
|
Directory.Delete(_testDirectory, recursive: true);
|
|
}
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task StoreContextEntry_ValidData_ReturnsSuccess()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["contextType"] = "decision",
|
|
["content"] = "Test decision content",
|
|
["summary"] = "Test summary",
|
|
["projectPath"] = _testDirectory,
|
|
["priority"] = "high",
|
|
["tags"] = "test,unit-test"
|
|
};
|
|
|
|
// Act
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success, $"Expected success but got: {result.Message}");
|
|
Assert.IsNotNull(result.Data);
|
|
|
|
var resultData = JsonSerializer.Deserialize<JsonElement>(JsonSerializer.Serialize(result.Data));
|
|
Assert.IsTrue(resultData.TryGetProperty("Success", out var successProp));
|
|
Assert.IsTrue(successProp.GetBoolean());
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task StoreContextEntry_MissingContent_ReturnsError()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["contextType"] = "decision",
|
|
["summary"] = "Test summary",
|
|
["projectPath"] = _testDirectory
|
|
};
|
|
|
|
// Act
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsFalse(result.Success);
|
|
Assert.IsTrue(result.Message.Contains("content") || result.Message.Contains("required"));
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task StoreContextEntry_MultipleEntries_StoresInCorrectOrder()
|
|
{
|
|
// Arrange
|
|
var entries = new[]
|
|
{
|
|
new { content = "First entry", summary = "First", timestamp = DateTime.UtcNow.AddMinutes(-2) },
|
|
new { content = "Second entry", summary = "Second", timestamp = DateTime.UtcNow.AddMinutes(-1) },
|
|
new { content = "Third entry", summary = "Third", timestamp = DateTime.UtcNow }
|
|
};
|
|
|
|
// Act
|
|
foreach (var entry in entries)
|
|
{
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["contextType"] = "test",
|
|
["content"] = entry.content,
|
|
["summary"] = entry.summary,
|
|
["projectPath"] = _testDirectory
|
|
};
|
|
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
Assert.IsTrue(result.Success);
|
|
}
|
|
|
|
// Assert - Check if entries are stored in chronological order (newest first)
|
|
var contextFiles = Directory.GetFiles(Path.Combine(_testDirectory, ".context"), "context-*.json");
|
|
Assert.IsTrue(contextFiles.Length >= 1);
|
|
|
|
var fileContent = await File.ReadAllTextAsync(contextFiles[0]);
|
|
var storedEntries = JsonSerializer.Deserialize<List<StoredContextEntry>>(fileContent);
|
|
|
|
Assert.IsNotNull(storedEntries);
|
|
Assert.AreEqual(3, storedEntries.Count);
|
|
|
|
// Verify order (newest first)
|
|
Assert.AreEqual("Third", storedEntries[0].Summary);
|
|
Assert.AreEqual("Second", storedEntries[1].Summary);
|
|
Assert.AreEqual("First", storedEntries[2].Summary);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task StoreContextEntry_CaseInsensitiveParameters_Works()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["contexttype"] = "decision", // lowercase
|
|
["content"] = "Test content", // lowercase to match SupportedParameters
|
|
["summary"] = "Test summary", // lowercase to match SupportedParameters
|
|
["projectpath"] = _testDirectory,
|
|
["priority"] = "medium"
|
|
};
|
|
|
|
// Act
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task StoreContextEntry_CreatesContextDirectory_WhenNotExists()
|
|
{
|
|
// Arrange
|
|
var nonExistentDir = Path.Combine(_testDirectory, "new-project");
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["contextType"] = "test",
|
|
["content"] = "Test content",
|
|
["summary"] = "Test summary",
|
|
["projectPath"] = nonExistentDir
|
|
};
|
|
|
|
// Act
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
Assert.IsTrue(Directory.Exists(Path.Combine(nonExistentDir, ".context")));
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task StoreContextEntry_UpdatesIndex_Correctly()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["contextType"] = "decision",
|
|
["content"] = "Test content for indexing",
|
|
["summary"] = "Test summary for index",
|
|
["tags"] = "index,test",
|
|
["projectPath"] = _testDirectory,
|
|
["priority"] = "high"
|
|
};
|
|
|
|
// Act
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var indexPath = Path.Combine(_testDirectory, ".context", "context-index.json");
|
|
Assert.IsTrue(File.Exists(indexPath));
|
|
|
|
var indexContent = await File.ReadAllTextAsync(indexPath);
|
|
var indexEntries = JsonSerializer.Deserialize<List<ContextIndexEntry>>(indexContent);
|
|
|
|
Assert.IsNotNull(indexEntries);
|
|
Assert.AreEqual(1, indexEntries.Count);
|
|
Assert.AreEqual("Test summary for index", indexEntries[0].Summary);
|
|
Assert.AreEqual("decision", indexEntries[0].Type);
|
|
Assert.AreEqual("high", indexEntries[0].Priority);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task StoreContextEntry_WithMetadata_StoresCorrectly()
|
|
{
|
|
// Arrange
|
|
var metadata = new { source = "unit-test", version = 1.0, automated = true };
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["contextType"] = "insight",
|
|
["content"] = "Content with metadata",
|
|
["summary"] = "Summary with metadata",
|
|
["projectPath"] = _testDirectory,
|
|
["metadata"] = JsonSerializer.Serialize(metadata)
|
|
};
|
|
|
|
// Act
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var contextFiles = Directory.GetFiles(Path.Combine(_testDirectory, ".context"), "context-*.json");
|
|
var fileContent = await File.ReadAllTextAsync(contextFiles[0]);
|
|
var storedEntries = JsonSerializer.Deserialize<List<StoredContextEntry>>(fileContent);
|
|
|
|
Assert.IsNotNull(storedEntries);
|
|
Assert.AreEqual(1, storedEntries.Count);
|
|
|
|
var entry = storedEntries[0];
|
|
Assert.IsTrue(entry.Metadata.ContainsKey("source"));
|
|
Assert.AreEqual("unit-test", entry.Metadata["source"].ToString());
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task StoreContextEntry_EmptyTags_HandledCorrectly()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["contextType"] = "test",
|
|
["content"] = "Content without tags",
|
|
["summary"] = "Summary without tags",
|
|
["projectPath"] = _testDirectory,
|
|
["tags"] = "" // Empty tags
|
|
};
|
|
|
|
// Act
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var contextFiles = Directory.GetFiles(Path.Combine(_testDirectory, ".context"), "context-*.json");
|
|
var fileContent = await File.ReadAllTextAsync(contextFiles[0]);
|
|
var storedEntries = JsonSerializer.Deserialize<List<StoredContextEntry>>(fileContent);
|
|
|
|
Assert.IsNotNull(storedEntries);
|
|
Assert.AreEqual(1, storedEntries.Count);
|
|
// Empty tags string should result in empty list after filtering
|
|
Assert.AreEqual(0, storedEntries[0].Tags.Count);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task StoreContextEntry_DefaultValues_AppliedCorrectly()
|
|
{
|
|
// Arrange
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["content"] = "Minimal content",
|
|
["summary"] = "Minimal summary",
|
|
["projectPath"] = _testDirectory
|
|
};
|
|
|
|
// Act
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var contextFiles = Directory.GetFiles(Path.Combine(_testDirectory, ".context"), "context-*.json");
|
|
var fileContent = await File.ReadAllTextAsync(contextFiles[0]);
|
|
var storedEntries = JsonSerializer.Deserialize<List<StoredContextEntry>>(fileContent);
|
|
|
|
Assert.IsNotNull(storedEntries);
|
|
Assert.AreEqual(1, storedEntries.Count);
|
|
|
|
var entry = storedEntries[0];
|
|
Assert.AreEqual("conversation", entry.Type); // Default contextType
|
|
Assert.AreEqual("medium", entry.Priority); // Default priority
|
|
Assert.AreEqual(_testDirectory, entry.ProjectPath); // Should use provided path
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task StoreContextEntry_LargeContent_HandledCorrectly()
|
|
{
|
|
// Arrange
|
|
var largeContent = new string('x', 50000); // 50KB content
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["contextType"] = "large-test",
|
|
["content"] = largeContent,
|
|
["summary"] = "Large content test",
|
|
["projectPath"] = _testDirectory
|
|
};
|
|
|
|
// Act
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var contextFiles = Directory.GetFiles(Path.Combine(_testDirectory, ".context"), "context-*.json");
|
|
var fileContent = await File.ReadAllTextAsync(contextFiles[0]);
|
|
var storedEntries = JsonSerializer.Deserialize<List<StoredContextEntry>>(fileContent);
|
|
|
|
Assert.IsNotNull(storedEntries);
|
|
Assert.AreEqual(1, storedEntries.Count);
|
|
Assert.AreEqual(largeContent, storedEntries[0].Content);
|
|
}
|
|
|
|
[TestMethod]
|
|
public async Task StoreContextEntry_SpecialCharacters_EncodedCorrectly()
|
|
{
|
|
// Arrange
|
|
var specialContent = "Content with special chars: <>&\"'🚀\n\r\t";
|
|
var parameters = new Dictionary<string, object>
|
|
{
|
|
["contextType"] = "encoding-test",
|
|
["content"] = specialContent,
|
|
["summary"] = "Special characters test",
|
|
["projectPath"] = _testDirectory
|
|
};
|
|
|
|
// Act
|
|
var result = await _plugin.ExecuteAsync(parameters);
|
|
|
|
// Assert
|
|
Assert.IsTrue(result.Success);
|
|
|
|
var contextFiles = Directory.GetFiles(Path.Combine(_testDirectory, ".context"), "context-*.json");
|
|
var fileContent = await File.ReadAllTextAsync(contextFiles[0]);
|
|
var storedEntries = JsonSerializer.Deserialize<List<StoredContextEntry>>(fileContent);
|
|
|
|
Assert.IsNotNull(storedEntries);
|
|
Assert.AreEqual(1, storedEntries.Count);
|
|
Assert.AreEqual(specialContent, storedEntries[0].Content);
|
|
}
|
|
}
|
|
} |