diff --git a/.gitignore b/.gitignore index 2a761ed4..9a818189 100644 --- a/.gitignore +++ b/.gitignore @@ -136,3 +136,5 @@ dist .yarn/build-state.yml .yarn/install-state.gz .pnp.* + +/.vs/ diff --git a/dotnet/G5e.AzureDevOpsServerMCP.slnx b/dotnet/G5e.AzureDevOpsServerMCP.slnx index 23d638c5..fc4e6c0a 100644 --- a/dotnet/G5e.AzureDevOpsServerMCP.slnx +++ b/dotnet/G5e.AzureDevOpsServerMCP.slnx @@ -1,5 +1,6 @@ + diff --git a/dotnet/tests/Directory.Packages.props b/dotnet/tests/Directory.Packages.props index 3558c38f..804053dc 100644 --- a/dotnet/tests/Directory.Packages.props +++ b/dotnet/tests/Directory.Packages.props @@ -5,8 +5,8 @@ - - + + diff --git a/dotnet/tests/G5e.AzureDevOpsServerMCP.IntegrationTests/G5e.AzureDevOpsServerMCP.IntegrationTests.csproj b/dotnet/tests/G5e.AzureDevOpsServerMCP.IntegrationTests/G5e.AzureDevOpsServerMCP.IntegrationTests.csproj index b5392cdf..c061b067 100644 --- a/dotnet/tests/G5e.AzureDevOpsServerMCP.IntegrationTests/G5e.AzureDevOpsServerMCP.IntegrationTests.csproj +++ b/dotnet/tests/G5e.AzureDevOpsServerMCP.IntegrationTests/G5e.AzureDevOpsServerMCP.IntegrationTests.csproj @@ -3,12 +3,8 @@ - - - - - - + + @@ -22,4 +18,4 @@ - \ No newline at end of file + diff --git a/dotnet/tests/G5e.AzureDevOpsServerMCP.IntegrationTests/RepositoryToolsFixtureTests.cs b/dotnet/tests/G5e.AzureDevOpsServerMCP.IntegrationTests/RepositoryToolsFixtureTests.cs index 1b6835bc..1024b055 100644 --- a/dotnet/tests/G5e.AzureDevOpsServerMCP.IntegrationTests/RepositoryToolsFixtureTests.cs +++ b/dotnet/tests/G5e.AzureDevOpsServerMCP.IntegrationTests/RepositoryToolsFixtureTests.cs @@ -1,12 +1,14 @@ using System.Text.Json; using G5e.AzureDevOpsServerMCP.Application.Services; using G5e.AzureDevOpsServerMCP.Tools; +using Microsoft.VisualStudio.TestTools.UnitTesting; namespace G5e.AzureDevOpsServerMCP.IntegrationTests; +[TestClass] public class RepositoryToolsFixtureTests { - [Fact] + [TestMethod] public async Task CreateFeatureBranch_UsesFixtureBackedService_AndSerializesExpectedShape() { // Arrange @@ -20,12 +22,12 @@ public async Task CreateFeatureBranch_UsesFixtureBackedService_AndSerializesExpe using var document = JsonDocument.Parse(json); var root = document.RootElement; - Assert.Equal("feature/TEST-123", root.GetProperty("branchName").GetString()); - Assert.NotEmpty(root.GetProperty("objectId").GetString()!); - Assert.True(root.GetProperty("success").GetBoolean()); + Assert.AreEqual("feature/TEST-123", root.GetProperty("branchName").GetString()); + Assert.IsFalse(string.IsNullOrEmpty(root.GetProperty("objectId").GetString())); + Assert.IsTrue(root.GetProperty("success").GetBoolean()); } - [Fact] + [TestMethod] public async Task CreateFeatureBranch_WhenServiceThrows_ReturnsSerializedError() { // Arrange @@ -39,10 +41,11 @@ public async Task CreateFeatureBranch_WhenServiceThrows_ReturnsSerializedError() using var document = JsonDocument.Parse(json); var root = document.RootElement; - Assert.Equal("Branch already exists", root.GetProperty("error").GetString()); - Assert.Equal("InvalidOperationException", root.GetProperty("type").GetString()); + Assert.AreEqual("Branch already exists", root.GetProperty("error").GetString()); + Assert.AreEqual("InvalidOperationException", root.GetProperty("type").GetString()); } - [Fact] + + [TestMethod] public async Task CreatePullRequestForWorkItem_ReturnsSerializedResult() { var sut = new RepositoryTools(new FakeRepositoryService()); @@ -60,13 +63,13 @@ public async Task CreatePullRequestForWorkItem_ReturnsSerializedResult() using var document = JsonDocument.Parse(json); var root = document.RootElement; - Assert.Equal(99, root.GetProperty("pullRequestId").GetInt32()); - Assert.Equal("Implement TEST-123", root.GetProperty("title").GetString()); - Assert.Equal("active", root.GetProperty("status").GetString()); - Assert.True(root.GetProperty("success").GetBoolean()); + Assert.AreEqual(99, root.GetProperty("pullRequestId").GetInt32()); + Assert.AreEqual("Implement TEST-123", root.GetProperty("title").GetString()); + Assert.AreEqual("active", root.GetProperty("status").GetString()); + Assert.IsTrue(root.GetProperty("success").GetBoolean()); } - [Fact] + [TestMethod] public async Task CreatePullRequestForWorkItem_WhenServiceThrows_ReturnsSerializedError() { var sut = new RepositoryTools(new ThrowingRepositoryService(new InvalidOperationException("source branch not found"))); @@ -84,41 +87,41 @@ public async Task CreatePullRequestForWorkItem_WhenServiceThrows_ReturnsSerializ using var document = JsonDocument.Parse(json); var root = document.RootElement; - Assert.Equal("source branch not found", root.GetProperty("error").GetString()); - Assert.Equal("InvalidOperationException", root.GetProperty("type").GetString()); + Assert.AreEqual("source branch not found", root.GetProperty("error").GetString()); + Assert.AreEqual("InvalidOperationException", root.GetProperty("type").GetString()); } - [Fact] - public async Task LinkBranchToWorkItem_ReturnsSerializedResult() - { - var sut = new RepositoryTools(new FakeRepositoryService()); + [TestMethod] + public async Task LinkBranchToWorkItem_ReturnsSerializedResult() + { + var sut = new RepositoryTools(new FakeRepositoryService()); - var json = await sut.LinkBranchToWorkItem("DefaultCollection", "TestProject", "TestRepo", "feature/TEST-123", 42); + var json = await sut.LinkBranchToWorkItem("DefaultCollection", "TestProject", "TestRepo", "feature/TEST-123", 42); - using var document = JsonDocument.Parse(json); - var root = document.RootElement; + using var document = JsonDocument.Parse(json); + var root = document.RootElement; - Assert.Equal(42, root.GetProperty("workItemId").GetInt32()); - Assert.Equal("feature/TEST-123", root.GetProperty("branchName").GetString()); - Assert.Equal("TestRepo", root.GetProperty("repository").GetString()); - Assert.True(root.GetProperty("success").GetBoolean()); - } + Assert.AreEqual(42, root.GetProperty("workItemId").GetInt32()); + Assert.AreEqual("feature/TEST-123", root.GetProperty("branchName").GetString()); + Assert.AreEqual("TestRepo", root.GetProperty("repository").GetString()); + Assert.IsTrue(root.GetProperty("success").GetBoolean()); + } - [Fact] - public async Task LinkBranchToWorkItem_WhenServiceThrows_ReturnsSerializedError() - { - var sut = new RepositoryTools(new ThrowingRepositoryService(new InvalidOperationException("repository not found"))); + [TestMethod] + public async Task LinkBranchToWorkItem_WhenServiceThrows_ReturnsSerializedError() + { + var sut = new RepositoryTools(new ThrowingRepositoryService(new InvalidOperationException("repository not found"))); - var json = await sut.LinkBranchToWorkItem("DefaultCollection", "TestProject", "TestRepo", "feature/TEST-123", 42); + var json = await sut.LinkBranchToWorkItem("DefaultCollection", "TestProject", "TestRepo", "feature/TEST-123", 42); - using var document = JsonDocument.Parse(json); - var root = document.RootElement; + using var document = JsonDocument.Parse(json); + var root = document.RootElement; - Assert.Equal("repository not found", root.GetProperty("error").GetString()); - Assert.Equal("InvalidOperationException", root.GetProperty("type").GetString()); - } + Assert.AreEqual("repository not found", root.GetProperty("error").GetString()); + Assert.AreEqual("InvalidOperationException", root.GetProperty("type").GetString()); + } - private sealed class FakeRepositoryService : IRepositoryService + private sealed class FakeRepositoryService : IRepositoryService { public Task CreateBranchAsync( string collection, diff --git a/dotnet/tests/G5e.AzureDevOpsServerMCP.IntegrationTests/WorkItemToolsFixtureTests.cs b/dotnet/tests/G5e.AzureDevOpsServerMCP.IntegrationTests/WorkItemToolsFixtureTests.cs index 5e680072..219319e9 100644 --- a/dotnet/tests/G5e.AzureDevOpsServerMCP.IntegrationTests/WorkItemToolsFixtureTests.cs +++ b/dotnet/tests/G5e.AzureDevOpsServerMCP.IntegrationTests/WorkItemToolsFixtureTests.cs @@ -1,12 +1,14 @@ -using System.Text.Json; +using System.Text.Json; using G5e.AzureDevOpsServerMCP.Application.Services; using G5e.AzureDevOpsServerMCP.Tools; +using Microsoft.VisualStudio.TestTools.UnitTesting; namespace G5e.AzureDevOpsServerMCP.IntegrationTests; +[TestClass] public class WorkItemToolsFixtureTests { - [Fact] + [TestMethod] public async Task GetWorkItemContext_UsesFixtureBackedService_AndSerializesExpectedShape() { var fixturePath = Path.Combine(AppContext.BaseDirectory, "Fixtures", "work-item-context-result.json"); @@ -20,17 +22,17 @@ public async Task GetWorkItemContext_UsesFixtureBackedService_AndSerializesExpec var workItem = root.GetProperty("workItem"); var comments = root.GetProperty("comments"); - Assert.Equal(1, workItem.GetProperty("id").GetInt32()); - Assert.Equal("Als ontwikkelaar wil ik work items ophalen via een MCP server zodat mijn AI-assistent context heeft over mijn taken", workItem.GetProperty("title").GetString()); - Assert.Equal("User Story", workItem.GetProperty("type").GetString()); - Assert.Equal("New", workItem.GetProperty("state").GetString()); - Assert.Equal("Gadeyne Bram", workItem.GetProperty("assignedTo").GetString()); - Assert.Equal(1, root.GetProperty("commentCount").GetInt32()); - Assert.Equal(1, comments.GetArrayLength()); - Assert.Contains("Spike afgerond", comments[0].GetProperty("content").GetString(), StringComparison.OrdinalIgnoreCase); + Assert.AreEqual(1, workItem.GetProperty("id").GetInt32()); + Assert.AreEqual("Als ontwikkelaar wil ik work items ophalen via een MCP server zodat mijn AI-assistent context heeft over mijn taken", workItem.GetProperty("title").GetString()); + Assert.AreEqual("User Story", workItem.GetProperty("type").GetString()); + Assert.AreEqual("New", workItem.GetProperty("state").GetString()); + Assert.AreEqual("Gadeyne Bram", workItem.GetProperty("assignedTo").GetString()); + Assert.AreEqual(1, root.GetProperty("commentCount").GetInt32()); + Assert.AreEqual(1, comments.GetArrayLength()); + StringAssert.Contains(comments[0].GetProperty("content").GetString(), "Spike afgerond", StringComparison.OrdinalIgnoreCase); } - [Fact] + [TestMethod] public async Task GetWorkItemContext_WhenServiceThrows_ReturnsSerializedError() { var sut = new WorkItemTools(new ThrowingWorkItemContextService(new InvalidOperationException("fixture failure"))); @@ -40,8 +42,8 @@ public async Task GetWorkItemContext_WhenServiceThrows_ReturnsSerializedError() using var document = JsonDocument.Parse(json); var root = document.RootElement; - Assert.Equal("fixture failure", root.GetProperty("error").GetString()); - Assert.Equal("InvalidOperationException", root.GetProperty("type").GetString()); + Assert.AreEqual("fixture failure", root.GetProperty("error").GetString()); + Assert.AreEqual("InvalidOperationException", root.GetProperty("type").GetString()); } private sealed class FixtureBackedWorkItemContextService : IWorkItemContextService @@ -98,7 +100,7 @@ public Task CreateWorkItemAsync(string collection, string => Task.FromException(_exception); } - [Fact] + [TestMethod] public async Task AddWorkItemComment_ReturnsSerializedCommentId() { var sut = new WorkItemTools(new FakeAddCommentWorkItemContextService()); @@ -108,11 +110,11 @@ public async Task AddWorkItemComment_ReturnsSerializedCommentId() using var document = JsonDocument.Parse(json); var root = document.RootElement; - Assert.Equal(42, root.GetProperty("commentId").GetInt32()); - Assert.True(root.GetProperty("success").GetBoolean()); + Assert.AreEqual(42, root.GetProperty("commentId").GetInt32()); + Assert.IsTrue(root.GetProperty("success").GetBoolean()); } - [Fact] + [TestMethod] public async Task AddWorkItemComment_WhenServiceThrows_ReturnsSerializedError() { var sut = new WorkItemTools(new ThrowingWorkItemContextService(new InvalidOperationException("comment failed"))); @@ -122,8 +124,8 @@ public async Task AddWorkItemComment_WhenServiceThrows_ReturnsSerializedError() using var document = JsonDocument.Parse(json); var root = document.RootElement; - Assert.Equal("comment failed", root.GetProperty("error").GetString()); - Assert.Equal("InvalidOperationException", root.GetProperty("type").GetString()); + Assert.AreEqual("comment failed", root.GetProperty("error").GetString()); + Assert.AreEqual("InvalidOperationException", root.GetProperty("type").GetString()); } private sealed class FakeAddCommentWorkItemContextService : IWorkItemContextService @@ -141,7 +143,7 @@ public Task CreateWorkItemAsync(string collection, string => Task.FromResult(new CreateWorkItemResult { WorkItemId = 3, Title = title, Type = workItemType, Url = string.Empty }); } - [Fact] + [TestMethod] public async Task UpdateWorkItemComment_ReturnsSerializedCommentDetails() { var sut = new WorkItemTools(new FakeAddCommentWorkItemContextService()); @@ -151,14 +153,14 @@ public async Task UpdateWorkItemComment_ReturnsSerializedCommentDetails() using var document = JsonDocument.Parse(json); var root = document.RootElement; - Assert.Equal(100, root.GetProperty("commentId").GetInt32()); - Assert.Equal(1, root.GetProperty("workItemId").GetInt32()); - Assert.Equal("Updated comment text via MCP", root.GetProperty("text").GetString()); - Assert.Equal(2, root.GetProperty("version").GetInt32()); - Assert.True(root.GetProperty("success").GetBoolean()); + Assert.AreEqual(100, root.GetProperty("commentId").GetInt32()); + Assert.AreEqual(1, root.GetProperty("workItemId").GetInt32()); + Assert.AreEqual("Updated comment text via MCP", root.GetProperty("text").GetString()); + Assert.AreEqual(2, root.GetProperty("version").GetInt32()); + Assert.IsTrue(root.GetProperty("success").GetBoolean()); } - [Fact] + [TestMethod] public async Task UpdateWorkItemComment_WhenServiceThrows_ReturnsSerializedError() { var sut = new WorkItemTools(new ThrowingWorkItemContextService(new InvalidOperationException("update failed"))); @@ -168,45 +170,45 @@ public async Task UpdateWorkItemComment_WhenServiceThrows_ReturnsSerializedError using var document = JsonDocument.Parse(json); var root = document.RootElement; - Assert.Equal("update failed", root.GetProperty("error").GetString()); - Assert.Equal("InvalidOperationException", root.GetProperty("type").GetString()); + Assert.AreEqual("update failed", root.GetProperty("error").GetString()); + Assert.AreEqual("InvalidOperationException", root.GetProperty("type").GetString()); } - [Fact] + [TestMethod] public async Task CreateWorkItem_ReturnsSerializedWorkItemDetails() { var sut = new WorkItemTools(new FakeCreateWorkItemService()); var json = await sut.CreateWorkItem("DefaultCollection", "UZG.IZ.PrestIZ", "Task", "New task via MCP"); using var document = JsonDocument.Parse(json); var root = document.RootElement; - Assert.Equal(99, root.GetProperty("workItemId").GetInt32()); - Assert.Equal("New task via MCP", root.GetProperty("title").GetString()); - Assert.Equal("Task", root.GetProperty("type").GetString()); - Assert.True(root.GetProperty("success").GetBoolean()); + Assert.AreEqual(99, root.GetProperty("workItemId").GetInt32()); + Assert.AreEqual("New task via MCP", root.GetProperty("title").GetString()); + Assert.AreEqual("Task", root.GetProperty("type").GetString()); + Assert.IsTrue(root.GetProperty("success").GetBoolean()); } - [Fact] + [TestMethod] public async Task CreateWorkItem_WithDescription_ReturnsSerializedWorkItem() { var sut = new WorkItemTools(new FakeCreateWorkItemService()); var json = await sut.CreateWorkItem("DefaultCollection", "UZG.IZ.PrestIZ", "Bug", "Critical bug", "This is a critical issue that needs fixing"); using var document = JsonDocument.Parse(json); var root = document.RootElement; - Assert.Equal(99, root.GetProperty("workItemId").GetInt32()); - Assert.Equal("Critical bug", root.GetProperty("title").GetString()); - Assert.Equal("Bug", root.GetProperty("type").GetString()); - Assert.True(root.GetProperty("success").GetBoolean()); + Assert.AreEqual(99, root.GetProperty("workItemId").GetInt32()); + Assert.AreEqual("Critical bug", root.GetProperty("title").GetString()); + Assert.AreEqual("Bug", root.GetProperty("type").GetString()); + Assert.IsTrue(root.GetProperty("success").GetBoolean()); } - [Fact] + [TestMethod] public async Task CreateWorkItem_WhenServiceThrows_ReturnsSerializedError() { var sut = new WorkItemTools(new ThrowingWorkItemContextService(new InvalidOperationException("Invalid work item type"))); var json = await sut.CreateWorkItem("DefaultCollection", "UZG.IZ.PrestIZ", "InvalidType", "Test"); using var document = JsonDocument.Parse(json); var root = document.RootElement; - Assert.Equal("Invalid work item type", root.GetProperty("error").GetString()); - Assert.Equal("InvalidOperationException", root.GetProperty("type").GetString()); + Assert.AreEqual("Invalid work item type", root.GetProperty("error").GetString()); + Assert.AreEqual("InvalidOperationException", root.GetProperty("type").GetString()); } private sealed class FakeCreateWorkItemService : IWorkItemContextService diff --git a/dotnet/tests/G5e.AzureDevOpsServerMCP.UnitTests/G5e.AzureDevOpsServerMCP.UnitTests.csproj b/dotnet/tests/G5e.AzureDevOpsServerMCP.UnitTests/G5e.AzureDevOpsServerMCP.UnitTests.csproj index 1695ad4f..8875ff52 100644 --- a/dotnet/tests/G5e.AzureDevOpsServerMCP.UnitTests/G5e.AzureDevOpsServerMCP.UnitTests.csproj +++ b/dotnet/tests/G5e.AzureDevOpsServerMCP.UnitTests/G5e.AzureDevOpsServerMCP.UnitTests.csproj @@ -3,8 +3,8 @@ - - + + @@ -12,8 +12,4 @@ - - - - - \ No newline at end of file +