Skip to content

Commit eb76901

Browse files
committed
Added list of test suites (per test plan)
1 parent 2504b1a commit eb76901

8 files changed

Lines changed: 189 additions & 2 deletions

File tree

CloneDevOpsTemplate/Controllers/TestController.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,17 @@ public async Task<IActionResult> TestPlans(Guid projectId)
2222
testPlans = await _testService.GetTestPlansAsync(projectId) ?? new();
2323
return View(testPlans.Value);
2424
}
25+
26+
public async Task<IActionResult> TestSuites(Guid projectId, int testPlanId)
27+
{
28+
TestSuites testSuites = new();
29+
30+
if (!ModelState.IsValid)
31+
{
32+
return View(testSuites.Value);
33+
}
34+
35+
testSuites = await _testService.GetTestSuitesAsync(projectId, testPlanId) ?? new();
36+
return View(testSuites.Value);
37+
}
2538
}

CloneDevOpsTemplate/IServices/ITestService.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ namespace CloneDevOpsTemplate.IServices;
55
public interface ITestService
66
{
77
Task<TestPlans?> GetTestPlansAsync(Guid projectId);
8+
Task<TestSuites?> GetTestSuitesAsync(Guid projectId, int testPlanId);
89
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
namespace CloneDevOpsTemplate.Models;
2+
3+
public class TestSuites
4+
{
5+
public int Count { get; set; }
6+
public TestSuite[] Value { get; set; } = [];
7+
}
8+
9+
public class TestSuite
10+
{
11+
public int Id { get; set; }
12+
public Project Project { get; set; } = new();
13+
public TestPlanReference Plan { get; set; } = new();
14+
public int Revision { get; set; }
15+
public string Name { get; set; } = string.Empty;
16+
public bool HasChildren { get; set; }
17+
public TestSuite[] Children { get; set; } = [];
18+
public string SuiteType { get; set; } = string.Empty;
19+
public TestSuiteReference ParentSuite { get; set; } = new();
20+
public bool InheritDefaultConfigurations { get; set; }
21+
public TestConfigurationReference[] DefaultConfigurations { get; set; } = [];
22+
public IdentityRef[] DefaultTesters { get; set; } = [];
23+
}
24+
25+
public class TestPlanReference
26+
{
27+
public int Id { get; set; }
28+
public string Name { get; set; } = string.Empty;
29+
}
30+
31+
public class TestConfigurationReference
32+
{
33+
public int Id { get; set; }
34+
public string Name { get; set; } = string.Empty;
35+
}

CloneDevOpsTemplate/Services/TestService.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,9 @@ public class TestService(IHttpClientFactory httpClientFactory) : ITestService
1111
{
1212
return _client.GetFromJsonAsync<TestPlans>($"{projectId}/_apis/testplan/plans");
1313
}
14+
15+
public Task<TestSuites?> GetTestSuitesAsync(Guid projectId, int testPlanId)
16+
{
17+
return _client.GetFromJsonAsync<TestSuites>($"{projectId}/_apis/testplan/plans/{testPlanId}/suites");
18+
}
1419
}

CloneDevOpsTemplate/Views/Test/TestPlans.cshtml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
<th>Name</th>
1414
<th>State</th>
1515
<th>ProjectName</th>
16+
<th>TestSuites</th>
1617
</tr>
1718
</thead>
1819
<tbody>
@@ -22,6 +23,7 @@
2223
<td>@testPlan.Name</td>
2324
<td>@testPlan.State</td>
2425
<td>@testPlan.Project.Name</td>
26+
<td>@Html.ActionLink("Test suites", "TestSuites", "Test", new { projectId = testPlan.Project.Id, testPlanId = testPlan.Id })</td>
2527
</tr>
2628
}
2729
</tbody>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
@model TestSuite[]
2+
@{
3+
ViewData["Title"] = "Test suites";
4+
}
5+
6+
<h1>Test suites</h1>
7+
8+
@Html.ValidationSummary(false, "", new { @class = "text-danger" })
9+
10+
<table class="table">
11+
<thead>
12+
<tr>
13+
<th>Name</th>
14+
<th>Type</th>
15+
<th>ProjectName</th>
16+
</tr>
17+
</thead>
18+
<tbody>
19+
@foreach (var testSuite in Model)
20+
{
21+
<tr>
22+
<td>@testSuite.Name</td>
23+
<td>@testSuite.SuiteType</td>
24+
<td>@testSuite.Project.Name</td>
25+
</tr>
26+
}
27+
</tbody>
28+
</table>

CloneDevOpsTemplateTest/Controllers/TestControllerTest.cs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,57 @@ public async Task TestPlans_ValidModelState_NullTestPlans_ReturnsViewWithEmptyVa
6666
var viewModel = Assert.IsType<TestPlan[]>(viewResult.Model);
6767
Assert.Empty(viewModel);
6868
}
69-
}
69+
70+
[Fact]
71+
public async Task TestSuites_InvalidModelState_ReturnsViewWithEmptyValue()
72+
{
73+
// Arrange
74+
_controller.ModelState.AddModelError("Error", "Invalid model state");
75+
var projectId = Guid.NewGuid();
76+
var testPlanId = 1;
77+
78+
// Act
79+
var result = await _controller.TestSuites(projectId, testPlanId);
80+
81+
// Assert
82+
var viewResult = Assert.IsType<ViewResult>(result);
83+
var viewModel = Assert.IsType<TestSuite[]>(viewResult.Model);
84+
Assert.Empty(viewModel);
85+
}
86+
87+
[Fact]
88+
public async Task TestSuites_ValidModelState_ReturnsViewWithTestSuitesValue()
89+
{
90+
// Arrange
91+
var projectId = Guid.NewGuid();
92+
var testPlanId = 1;
93+
var testSuites = new TestSuites { Value = [new TestSuite { Name = "Test Suite Value" }] };
94+
_mockTestService.Setup(service => service.GetTestSuitesAsync(projectId, testPlanId))
95+
.ReturnsAsync(testSuites);
96+
97+
// Act
98+
var result = await _controller.TestSuites(projectId, testPlanId);
99+
100+
// Assert
101+
var viewResult = Assert.IsType<ViewResult>(result);
102+
Assert.Equal(testSuites.Value, viewResult.Model);
103+
}
104+
105+
[Fact]
106+
public async Task TestSuites_ValidModelState_NullTestSuites_ReturnsViewWithEmptyValue()
107+
{
108+
// Arrange
109+
var projectId = Guid.NewGuid();
110+
var testPlanId = 1;
111+
_mockTestService.Setup(service => service.GetTestSuitesAsync(projectId, testPlanId))
112+
.ReturnsAsync((TestSuites)null!);
113+
114+
// Act
115+
var result = await _controller.TestSuites(projectId, testPlanId);
116+
117+
// Assert
118+
var viewResult = Assert.IsType<ViewResult>(result);
119+
var viewModel = Assert.IsType<TestSuite[]>(viewResult.Model);
120+
Assert.Empty(viewModel);
121+
}
122+
}

CloneDevOpsTemplateTest/Services/TestServiceTest.cs

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,54 @@ public async Task GetTestPlansAsync_ReturnsNull_WhenApiResponseIsNotFound()
7474
// Act & Assert
7575
await Assert.ThrowsAsync<HttpRequestException>(() => _testService.GetTestPlansAsync(projectId));
7676
}
77-
}
77+
78+
[Fact]
79+
public async Task GetTestSuitesAsync_ReturnsTestSuites_WhenApiResponseIsSuccessful()
80+
{
81+
// Arrange
82+
var projectId = Guid.NewGuid();
83+
var testPlanId = 1;
84+
var expectedTestSuites = new TestSuites { Count = 1, Value = [new TestSuite { Id = 1, Name = "suite" }] };
85+
86+
_httpMessageHandlerMock
87+
.Protected()
88+
.Setup<Task<HttpResponseMessage>>(
89+
"SendAsync",
90+
ItExpr.IsAny<HttpRequestMessage>(),
91+
ItExpr.IsAny<CancellationToken>())
92+
.ReturnsAsync(new HttpResponseMessage
93+
{
94+
StatusCode = HttpStatusCode.OK,
95+
Content = JsonContent.Create(expectedTestSuites)
96+
});
97+
98+
// Act
99+
var result = await _testService.GetTestSuitesAsync(projectId, testPlanId);
100+
101+
// Assert
102+
Assert.NotNull(result);
103+
Assert.Equivalent(expectedTestSuites, result);
104+
}
105+
106+
[Fact]
107+
public async Task GetTestSuitesAsync_ThrowsHttpRequestException_WhenApiResponseIsNotFound()
108+
{
109+
// Arrange
110+
var projectId = Guid.NewGuid();
111+
var testPlanId = 1;
112+
113+
_httpMessageHandlerMock
114+
.Protected()
115+
.Setup<Task<HttpResponseMessage>>(
116+
"SendAsync",
117+
ItExpr.IsAny<HttpRequestMessage>(),
118+
ItExpr.IsAny<CancellationToken>())
119+
.ReturnsAsync(new HttpResponseMessage
120+
{
121+
StatusCode = HttpStatusCode.NotFound
122+
});
123+
124+
// Act & Assert
125+
await Assert.ThrowsAsync<HttpRequestException>(() => _testService.GetTestSuitesAsync(projectId, testPlanId));
126+
}
127+
}

0 commit comments

Comments
 (0)