Skip to content

Commit 38d67fe

Browse files
author
zelodyc
committed
Correct retrieval of boards in batches (of size reduced to 10), with 'top' and 'skip' properties in URL. Add tests to verify retrieval in batches
1 parent bfc2d81 commit 38d67fe

6 files changed

Lines changed: 280 additions & 223 deletions

File tree

src/YouTrackSharp/Agiles/AgileService.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Collections.Generic;
23
using System.Net.Http;
34
using System.Threading.Tasks;
@@ -35,15 +36,15 @@ public async Task<ICollection<Agile>> GetAgileBoards(bool verbose = false)
3536
{
3637
HttpClient client = await _connection.GetAuthenticatedHttpClient();
3738

38-
const int batchSize = 50;
39+
const int batchSize = 10;
3940
List<Agile> agileBoards = new List<Agile>();
4041
List<Agile> currentBatch;
41-
42+
4243
do
4344
{
4445
string fields = _fieldSyntaxEncoder.Encode(typeof(Agile), verbose);
4546

46-
HttpResponseMessage message = await client.GetAsync($"api/agiles?fields={fields}");
47+
HttpResponseMessage message = await client.GetAsync($"api/agiles?fields={fields}&$top={batchSize}&$skip={agileBoards.Count}");
4748

4849
string response = await message.Content.ReadAsStringAsync();
4950

tests/YouTrackSharp.Tests/Infrastructure/Connections.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ public static string ServerUrl
2626

2727
public static Connection ConnectionStub(string content, HttpStatusCode status = HttpStatusCode.OK)
2828
{
29-
HttpResponseMessage response = new HttpResponseMessage(status);
30-
response.Content = new StringContent(content);
31-
32-
return new ConnectionStub(_ => response);
29+
HttpResponseMessage response = new HttpResponseMessage(status);
30+
response.Content = new StringContent(content);
31+
32+
return new ConnectionStub(_ => response);
3333
}
34-
34+
3535
public static class TestData
3636
{
3737
public static readonly List<object[]> ValidConnections

tests/YouTrackSharp.Tests/Integration/Agiles/AgileServiceTest.cs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.IO;
2+
using System.Linq;
23
using System.Reflection;
34

45
namespace YouTrackSharp.Tests.Integration.Agiles
@@ -11,7 +12,16 @@ public partial class AgileServiceTest
1112
private static string DemoSprintId => "109-2";
1213
private static string DemoSprintName => "First sprint";
1314

14-
private static string CompleteAgileJson => GetTextResource("YouTrackSharp.Tests.Resources.CompleteAgile.json");
15+
private static string SingleAgileJson => GetTextResource("YouTrackSharp.Tests.Resources.CompleteAgile.json");
16+
17+
private static string GetAgileJsonArray(int count)
18+
{
19+
string agileJson = SingleAgileJson;
20+
21+
string agilesJson = string.Join(",", Enumerable.Range(0, count).Select(_ => agileJson));
22+
23+
return $"[{agilesJson}]";
24+
}
1525

1626
private static string GetTextResource(string name)
1727
{

tests/YouTrackSharp.Tests/Integration/Agiles/GetAgiles.cs

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public partial class AgileServiceTest
1414
public class GetAgiles
1515
{
1616
[Fact]
17-
public async Task Valid_Connection_Return_Existing_Agile_Verbose()
17+
public async Task Valid_Connection_Return_Existing_Agiles_Verbose()
1818
{
1919
// Arrange
2020
IAgileService agileService = Connections.Demo1Token.CreateAgileService();
@@ -30,35 +30,10 @@ public async Task Valid_Connection_Return_Existing_Agile_Verbose()
3030
Assert.NotNull(demoBoard);
3131
Assert.Equal(DemoBoardId, demoBoard.Id);
3232
Assert.Equal(DemoBoardNamePrefix, demoBoard.Name);
33-
34-
Assert.NotNull(demoBoard.ColumnSettings);
35-
Assert.NotNull(demoBoard.Projects);
36-
Assert.NotNull(demoBoard.Sprints);
37-
Assert.NotNull(demoBoard.Projects);
38-
Assert.NotNull(demoBoard.Sprints);
39-
Assert.NotNull(demoBoard.Status);
40-
41-
Assert.NotNull(demoBoard.ColumnSettings);
42-
Assert.NotNull(demoBoard.CurrentSprint);
43-
Assert.NotNull(demoBoard.EstimationField);
44-
Assert.NotNull(demoBoard.SprintsSettings);
45-
Assert.NotNull(demoBoard.SwimlaneSettings);
46-
47-
48-
// These fields are null in the agile test
49-
Assert.Null(demoBoard.ColorCoding);
50-
Assert.Null(demoBoard.UpdateableBy);
51-
Assert.Null(demoBoard.VisibleFor);
52-
Assert.Null(demoBoard.OriginalEstimationField);
53-
54-
Sprint sprint = demoBoard.Sprints.FirstOrDefault();
55-
Assert.NotNull(sprint);
56-
Assert.Equal(DemoSprintId, sprint.Id);
57-
Assert.Equal(DemoSprintName, sprint.Name);
5833
}
5934

6035
[Fact]
61-
public async Task Verbose_Disabled_Returns_Agile_Minimum_Info()
36+
public async Task Verbose_Disabled_Returns_Agiles_Non_Verbose()
6237
{
6338
// Arrange
6439
IAgileService agileService = Connections.Demo1Token.CreateAgileService();
@@ -72,7 +47,6 @@ public async Task Verbose_Disabled_Returns_Agile_Minimum_Info()
7247

7348
Agile demoBoard = result.FirstOrDefault();
7449
Assert.NotNull(demoBoard);
75-
7650
Assert.Equal(DemoBoardId, demoBoard.Id);
7751
Assert.Equal(DemoBoardNamePrefix, demoBoard.Name);
7852
}
@@ -92,7 +66,7 @@ await Assert.ThrowsAsync<UnauthorizedConnectionException>(
9266
public async Task Full_Agile_Json_Gets_Deserialized_Successfully()
9367
{
9468
// Arrange
95-
IAgileService agileService = Connections.ConnectionStub(CompleteAgileJson).CreateAgileService();
69+
IAgileService agileService = Connections.ConnectionStub(GetAgileJsonArray(1)).CreateAgileService();
9670

9771
// Act
9872
ICollection<Agile> result = await agileService.GetAgileBoards(true);
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Net;
4+
using System.Net.Http;
5+
using System.Text.RegularExpressions;
6+
using System.Threading.Tasks;
7+
using Xunit;
8+
using YouTrackSharp.Agiles;
9+
using YouTrackSharp.Tests.Infrastructure;
10+
11+
namespace YouTrackSharp.Tests.Integration.Agiles
12+
{
13+
public partial class AgileServiceTest
14+
{
15+
public class GetAgilesInMultipleBatches
16+
{
17+
/// <summary>
18+
/// Creates a JSON array of Agile objects, whose size is determined by the "$top" and "$skip" parameters
19+
/// of the request (with a maximum of <see cref="totalAgiles"/> - skipped).<br></br>
20+
/// This allows to simulate returning a total number of agiles, in batches (the size of the batch is
21+
/// determined by the <see cref="AgileService"/> itself.
22+
/// </summary>
23+
/// <param name="request">REST request, with the $top parameter indicating the max number of results</param>
24+
/// <param name="totalAgiles">Total number of agiles to simulate in the server</param>
25+
/// <returns>
26+
/// Json array of agiles, whose size is hose size is determined by the "$top" and "$skip" parameters of the
27+
/// request (with a maximum of <see cref="totalAgiles"/> - skipped)
28+
/// </returns>
29+
private HttpResponseMessage GetAgileBatch(HttpRequestMessage request, int totalAgiles)
30+
{
31+
string requestUri = request.RequestUri.ToString();
32+
33+
Match match = Regex.Match(requestUri, "(&\\$top=(?<top>[0-9]+))?(&\\$skip=(?<skip>[0-9]+))?");
34+
35+
int top = totalAgiles;
36+
if (match.Groups.ContainsKey("top") && match.Groups["top"].Success)
37+
{
38+
top = int.Parse(match.Groups["top"].Value);
39+
}
40+
41+
int skip = 0;
42+
if (match.Groups.ContainsKey("skip") && match.Groups["skip"].Success)
43+
{
44+
skip = int.Parse(match.Groups["skip"].Value);
45+
}
46+
47+
int batchSize = Math.Min(top, totalAgiles - skip);
48+
49+
string agileJsonArray = GetAgileJsonArray(batchSize);
50+
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
51+
response.Content = new StringContent(agileJsonArray);
52+
53+
return response;
54+
}
55+
56+
[Fact]
57+
public async Task Many_Agiles_Are_Fetched_In_Batches()
58+
{
59+
// Arrange
60+
const int totalAgileCount = 53;
61+
Connection connection = new ConnectionStub(request => GetAgileBatch(request, totalAgileCount));
62+
IAgileService agileService = connection.CreateAgileService();
63+
64+
// Act
65+
ICollection<Agile> result = await agileService.GetAgileBoards(true);
66+
67+
// Assert
68+
Assert.NotNull(result);
69+
Assert.NotEmpty(result);
70+
Assert.Equal(totalAgileCount, result.Count);
71+
}
72+
}
73+
}
74+
}

0 commit comments

Comments
 (0)