From a8ece86aeb2d7f6e2cacfd74c2b97f714f5df068 Mon Sep 17 00:00:00 2001 From: zelodyc Date: Sun, 14 Mar 2021 22:37:17 -0700 Subject: [PATCH] Refactor tests. Add JsonArrayHandler / JsonHandler to simplify tests using ConnectionStub. Added check of requests number for multiple fetches in batches. Correct handling of and paramaters (support any order). Add multiple flavors of agile boards to tests. --- .../Infrastructure/ConnectionStub.cs | 51 +--- .../Infrastructure/Connections.cs | 8 - .../Infrastructure/JsonArrayHandler.cs | 91 +++++++ .../Infrastructure/JsonHandler.cs | 33 +++ .../Integration/Agiles/AgileServiceTest.cs | 14 +- .../Integration/Agiles/GetAgiles.cs | 82 ++++-- .../Agiles/GetAgilesInMultipleBatches.cs | 52 +--- .../Resources/FullAgile01.json | 232 ++++++++++++++++ .../Resources/FullAgile02.json | 251 ++++++++++++++++++ .../YouTrackSharp.Tests.csproj | 4 +- 10 files changed, 683 insertions(+), 135 deletions(-) create mode 100644 tests/YouTrackSharp.Tests/Infrastructure/JsonArrayHandler.cs create mode 100644 tests/YouTrackSharp.Tests/Infrastructure/JsonHandler.cs create mode 100644 tests/YouTrackSharp.Tests/Resources/FullAgile01.json create mode 100644 tests/YouTrackSharp.Tests/Resources/FullAgile02.json diff --git a/tests/YouTrackSharp.Tests/Infrastructure/ConnectionStub.cs b/tests/YouTrackSharp.Tests/Infrastructure/ConnectionStub.cs index d231c97..22696a1 100644 --- a/tests/YouTrackSharp.Tests/Infrastructure/ConnectionStub.cs +++ b/tests/YouTrackSharp.Tests/Infrastructure/ConnectionStub.cs @@ -1,6 +1,5 @@ using System; using System.Net.Http; -using System.Threading; using System.Threading.Tasks; namespace YouTrackSharp.Tests.Infrastructure @@ -10,18 +9,19 @@ namespace YouTrackSharp.Tests.Infrastructure /// public class ConnectionStub : Connection { - private Func ExecuteRequest { get; } - + private readonly HttpClientHandler _handler; private TimeSpan TimeOut => TimeSpan.FromSeconds(100); /// /// Creates an instance of with give response delegate /// - /// Request delegate - public ConnectionStub(Func executeRequest) : base( - "http://fake.connection.com/") + /// + /// to associate to this connection. + /// This can be used to pass a stub handler for testing purposes. + /// + public ConnectionStub(HttpClientHandler handler) : base("http://fake.connection.com/") { - ExecuteRequest = executeRequest; + _handler = handler; } /// @@ -31,42 +31,11 @@ public ConnectionStub(Func executeReque /// configured to return a predefined message and HTTP status public override Task GetAuthenticatedHttpClient() { - return Task.FromResult(CreateClient()); - } - - private HttpClient CreateClient() - { - HttpClient httpClient = new HttpClient(new HttpClientHandlerStub(ExecuteRequest)); + HttpClient httpClient = new HttpClient(_handler); httpClient.BaseAddress = ServerUri; httpClient.Timeout = TimeOut; - - return httpClient; - } - } - - /// - /// mock, that returns a predefined reply and HTTP status code. - /// - public class HttpClientHandlerStub : HttpClientHandler - { - private Func ExecuteRequest { get; } - - /// - /// Creates an instance that delegates HttpRequestMessages - /// - /// Request delegate - public HttpClientHandlerStub(Func executeRequest) - { - ExecuteRequest = executeRequest; - } - - /// - protected override Task SendAsync(HttpRequestMessage request, - CancellationToken cancellationToken) - { - HttpResponseMessage reply = ExecuteRequest?.Invoke(request); - - return Task.FromResult(reply); + + return Task.FromResult(httpClient); } } } \ No newline at end of file diff --git a/tests/YouTrackSharp.Tests/Infrastructure/Connections.cs b/tests/YouTrackSharp.Tests/Infrastructure/Connections.cs index e672294..94d5a0a 100644 --- a/tests/YouTrackSharp.Tests/Infrastructure/Connections.cs +++ b/tests/YouTrackSharp.Tests/Infrastructure/Connections.cs @@ -23,14 +23,6 @@ public static string ServerUrl public static Connection Demo3Token => new BearerTokenConnection(ServerUrl, "perm:ZGVtbzM=.WW91VHJhY2tTaGFycA==.L04RdcCnjyW2UPCVg1qyb6dQflpzFy", ConfigureTestsHandler); - - public static Connection ConnectionStub(string content, HttpStatusCode status = HttpStatusCode.OK) - { - HttpResponseMessage response = new HttpResponseMessage(status); - response.Content = new StringContent(content); - - return new ConnectionStub(_ => response); - } public static class TestData { diff --git a/tests/YouTrackSharp.Tests/Infrastructure/JsonArrayHandler.cs b/tests/YouTrackSharp.Tests/Infrastructure/JsonArrayHandler.cs new file mode 100644 index 0000000..83765e1 --- /dev/null +++ b/tests/YouTrackSharp.Tests/Infrastructure/JsonArrayHandler.cs @@ -0,0 +1,91 @@ +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading; +using System.Threading.Tasks; + +namespace YouTrackSharp.Tests.Infrastructure +{ + /// + /// This handler is used to return a json array from a range of give json strings, created from the $top and $skip + /// parameters of the HTTP request. + /// This handler can be used to simulate a server returning json arrays in batches. + /// + public class JsonArrayHandler : HttpClientHandler + { + private readonly ICollection _jsonObjects; + public int RequestsReceived { get; private set; } + + /// + /// Creates an instance of + /// + /// List of json objects that this instance will pick from + public JsonArrayHandler(params string[] jsonObjects) + { + _jsonObjects = jsonObjects; + RequestsReceived = 0; + } + + /// + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + RequestsReceived++; + + GetRequestedRange(request, _jsonObjects.Count, out int skip, out int count); + string json = GetJsonArray(_jsonObjects, skip, count); + + HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = new StringContent(json); + + return Task.FromResult(response); + } + + /// + /// Creates a JSON array from a range of the given json strings. + /// This allows to simulate returning a total number of elements, in batches. + /// + /// JSON objects from which the JSON array will be created + /// Number of items to skip + /// Number of items to return + /// + /// Json array + /// + private string GetJsonArray(ICollection jsonObjects, int skip, int count) + { + IEnumerable jsonObjectRange = jsonObjects.Skip(skip).Take(count); + string json = $"[{string.Join(",", jsonObjectRange)}]"; + + return json; + } + + /// + /// Parses the $skip and $top parameters from a Youtrack REST request URI, and computes the requested range + /// of objects to return (capped by ). + /// + /// HTTP request + /// Max index (range will not go beyond that index, even if $skip + $top is greater + /// Number of items to skip + /// Number of items to return + /// Range computed from request's $skip and $top + private void GetRequestedRange(HttpRequestMessage request, int maxIndex, out int skip, out int count) + { + string requestUri = request.RequestUri.ToString(); + + Match match = Regex.Match(requestUri, "&\\$top=(?[0-9]+)(&\\$skip=(?[0-9]+))?|&\\$skip=(?[0-9]+)(&\\$top=(?[0-9]+))?"); + + count = maxIndex; + if (match.Groups.ContainsKey("top") && match.Groups["top"].Success) + { + count = int.Parse(match.Groups["top"].Value); + } + + skip = 0; + if (match.Groups.ContainsKey("skip") && match.Groups["skip"].Success) + { + skip = int.Parse(match.Groups["skip"].Value); + } + } + } +} \ No newline at end of file diff --git a/tests/YouTrackSharp.Tests/Infrastructure/JsonHandler.cs b/tests/YouTrackSharp.Tests/Infrastructure/JsonHandler.cs new file mode 100644 index 0000000..bfb5360 --- /dev/null +++ b/tests/YouTrackSharp.Tests/Infrastructure/JsonHandler.cs @@ -0,0 +1,33 @@ +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace YouTrackSharp.Tests.Infrastructure +{ + /// + /// This handler returns a predefined json string on every request. + /// + public class JsonHandler : HttpClientHandler + { + private readonly string _json; + + /// + /// Creates an instance of + /// + /// Json string that will be returned upon each request + public JsonHandler(string json) + { + _json = json; + } + + /// + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = new StringContent(_json); + + return Task.FromResult(response); + } + } +} \ No newline at end of file diff --git a/tests/YouTrackSharp.Tests/Integration/Agiles/AgileServiceTest.cs b/tests/YouTrackSharp.Tests/Integration/Agiles/AgileServiceTest.cs index b0c04b4..ee1b894 100644 --- a/tests/YouTrackSharp.Tests/Integration/Agiles/AgileServiceTest.cs +++ b/tests/YouTrackSharp.Tests/Integration/Agiles/AgileServiceTest.cs @@ -8,20 +8,12 @@ public partial class AgileServiceTest { private static string DemoBoardId => "108-2"; private static string DemoBoardNamePrefix => "Test Board597fb561-ea1f-4095-9636-859ae4439605"; - + private static string DemoSprintId => "109-2"; private static string DemoSprintName => "First sprint"; - private static string SingleAgileJson => GetTextResource("YouTrackSharp.Tests.Resources.CompleteAgile.json"); - - private static string GetAgileJsonArray(int count) - { - string agileJson = SingleAgileJson; - - string agilesJson = string.Join(",", Enumerable.Range(0, count).Select(_ => agileJson)); - - return $"[{agilesJson}]"; - } + private static string FullAgile01 => GetTextResource("YouTrackSharp.Tests.Resources.FullAgile01.json"); + private static string FullAgile02 => GetTextResource("YouTrackSharp.Tests.Resources.FullAgile02.json"); private static string GetTextResource(string name) { diff --git a/tests/YouTrackSharp.Tests/Integration/Agiles/GetAgiles.cs b/tests/YouTrackSharp.Tests/Integration/Agiles/GetAgiles.cs index 4a2ad3a..3d313e8 100644 --- a/tests/YouTrackSharp.Tests/Integration/Agiles/GetAgiles.cs +++ b/tests/YouTrackSharp.Tests/Integration/Agiles/GetAgiles.cs @@ -63,43 +63,67 @@ await Assert.ThrowsAsync( } [Fact] - public async Task Full_Agile_Json_Gets_Deserialized_Successfully() + public async Task Mock_Connection_Returns_Full_Agile_01() { // Arrange - IAgileService agileService = Connections.ConnectionStub(GetAgileJsonArray(1)).CreateAgileService(); + string[] strings = { FullAgile01, FullAgile02 }; + + JsonArrayHandler handler = new JsonArrayHandler(strings); + ConnectionStub connection = new ConnectionStub(handler); + + IAgileService agileService = connection.CreateAgileService(); // Act ICollection result = await agileService.GetAgileBoards(true); // Assert Assert.NotNull(result); - Assert.NotEmpty(result); - - Agile demoBoard = result.FirstOrDefault(); - Assert.NotNull(demoBoard); - Assert.Equal(DemoBoardId, demoBoard.Id); - Assert.Equal(DemoBoardNamePrefix, demoBoard.Name); - - Assert.NotNull(demoBoard.ColumnSettings); - Assert.NotNull(demoBoard.Projects); - Assert.NotNull(demoBoard.Sprints); - Assert.NotNull(demoBoard.Projects); - Assert.NotNull(demoBoard.Sprints); - Assert.NotNull(demoBoard.Status); - Assert.NotNull(demoBoard.ColumnSettings); - Assert.NotNull(demoBoard.CurrentSprint); - Assert.NotNull(demoBoard.EstimationField); - Assert.NotNull(demoBoard.SprintsSettings); - Assert.NotNull(demoBoard.SwimlaneSettings); - Assert.NotNull(demoBoard.ColorCoding); - Assert.NotNull(demoBoard.UpdateableBy); - Assert.NotNull(demoBoard.VisibleFor); - Assert.NotNull(demoBoard.OriginalEstimationField); - - Sprint sprint = demoBoard.Sprints.FirstOrDefault(); - Assert.NotNull(sprint); - Assert.Equal(DemoSprintId, sprint.Id); - Assert.Equal(DemoSprintName, sprint.Name); + Assert.Equal(2, result.Count); + + foreach (Agile agile in result) + { + Assert.NotNull(agile); + + Assert.True("109-1".Equals(agile.Id) || "109-2".Equals(agile.Id)); + + + + Assert.NotNull(agile.ColumnSettings); + Assert.NotNull(agile.Projects); + Assert.NotNull(agile.Sprints); + Assert.NotNull(agile.Projects); + Assert.NotNull(agile.Sprints); + Assert.NotNull(agile.Status); + Assert.NotNull(agile.ColumnSettings); + Assert.NotNull(agile.CurrentSprint); + Assert.NotNull(agile.EstimationField); + Assert.NotNull(agile.SprintsSettings); + Assert.NotNull(agile.SwimlaneSettings); + Assert.NotNull(agile.ColorCoding); + Assert.NotNull(agile.UpdateableBy); + Assert.NotNull(agile.VisibleFor); + Assert.NotNull(agile.OriginalEstimationField); + + Sprint sprint = agile.Sprints.FirstOrDefault(); + Assert.NotNull(sprint); + Assert.Equal(DemoSprintId, sprint.Id); + Assert.Equal(DemoSprintName, sprint.Name); + + if ("109-1".Equals(agile.Id)) + { + Assert.Equal("Full Board 01", agile.Name); + Assert.IsType(agile.ColorCoding); + Assert.IsType(agile.SwimlaneSettings); + Assert.IsType(((IssueBasedSwimlaneSettings)agile.SwimlaneSettings).Field); + } + else + { + Assert.Equal("Full Board 02", agile.Name); + Assert.IsType(agile.ColorCoding); + Assert.IsType(agile.SwimlaneSettings); + Assert.IsType(((AttributeBasedSwimlaneSettings)agile.SwimlaneSettings).Field); + } + } } } } diff --git a/tests/YouTrackSharp.Tests/Integration/Agiles/GetAgilesInMultipleBatches.cs b/tests/YouTrackSharp.Tests/Integration/Agiles/GetAgilesInMultipleBatches.cs index b6cbf11..ae3b640 100644 --- a/tests/YouTrackSharp.Tests/Integration/Agiles/GetAgilesInMultipleBatches.cs +++ b/tests/YouTrackSharp.Tests/Integration/Agiles/GetAgilesInMultipleBatches.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Net; -using System.Net.Http; -using System.Text.RegularExpressions; +using System.Linq; using System.Threading.Tasks; using Xunit; using YouTrackSharp.Agiles; @@ -14,51 +12,16 @@ public partial class AgileServiceTest { public class GetAgilesInMultipleBatches { - /// - /// Creates a JSON array of Agile objects, whose size is determined by the "$top" and "$skip" parameters - /// of the request (with a maximum of - skipped).

- /// This allows to simulate returning a total number of agiles, in batches (the size of the batch is - /// determined by the itself. - ///
- /// REST request, with the $top parameter indicating the max number of results - /// Total number of agiles to simulate in the server - /// - /// Json array of agiles, whose size is hose size is determined by the "$top" and "$skip" parameters of the - /// request (with a maximum of - skipped) - /// - private HttpResponseMessage GetAgileBatch(HttpRequestMessage request, int totalAgiles) - { - string requestUri = request.RequestUri.ToString(); - - Match match = Regex.Match(requestUri, "(&\\$top=(?[0-9]+))?(&\\$skip=(?[0-9]+))?"); - - int top = totalAgiles; - if (match.Groups.ContainsKey("top") && match.Groups["top"].Success) - { - top = int.Parse(match.Groups["top"].Value); - } - - int skip = 0; - if (match.Groups.ContainsKey("skip") && match.Groups["skip"].Success) - { - skip = int.Parse(match.Groups["skip"].Value); - } - - int batchSize = Math.Min(top, totalAgiles - skip); - - string agileJsonArray = GetAgileJsonArray(batchSize); - HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK); - response.Content = new StringContent(agileJsonArray); - - return response; - } - [Fact] - public async Task Many_Agiles_Are_Fetched_In_Batches() + public async Task Mock_Connection_Return_Many_Agiles_In_Batches() { // Arrange const int totalAgileCount = 53; - Connection connection = new ConnectionStub(request => GetAgileBatch(request, totalAgileCount)); + int expectedRequests = (int)Math.Ceiling(totalAgileCount / 10.0); + + string[] jsonStrings = Enumerable.Range(0, totalAgileCount).Select(i => FullAgile01).ToArray(); + JsonArrayHandler handler = new JsonArrayHandler(jsonStrings); + ConnectionStub connection = new ConnectionStub(handler); IAgileService agileService = connection.CreateAgileService(); // Act @@ -68,6 +31,7 @@ public async Task Many_Agiles_Are_Fetched_In_Batches() Assert.NotNull(result); Assert.NotEmpty(result); Assert.Equal(totalAgileCount, result.Count); + Assert.Equal(expectedRequests, handler.RequestsReceived); } } } diff --git a/tests/YouTrackSharp.Tests/Resources/FullAgile01.json b/tests/YouTrackSharp.Tests/Resources/FullAgile01.json new file mode 100644 index 0000000..e12e627 --- /dev/null +++ b/tests/YouTrackSharp.Tests/Resources/FullAgile01.json @@ -0,0 +1,232 @@ +{ + "_comment": "Represents a full agile board (no fields are null), with FieldBasedColorCoding, IssueBasedSwimlaneSettings (and CustomFilterField)", + "projects": [ + { + "shortName": "DP1", + "name": "DemoProject1", + "id": "0-1", + "$type": "Project" + } + ], + "swimlaneSettings": { + "field": { + "customField": { + "name": "Type", + "$type": "CustomField" + }, + "presentation": "Type", + "id": "51-2", + "name": "Type", + "$type": "CustomFilterField" + }, + "values": [ + { + "name": "Feature", + "id": "Feature", + "$type": "SwimlaneValue" + } + ], + "defaultCardType": { + "name": "Task", + "id": "Task", + "$type": "SwimlaneValue" + }, + "id": "105-3", + "$type": "IssueBasedSwimlaneSettings" + }, + "estimationField": { + "name": "Estimation", + "$type": "CustomField" + }, + "sprints": [ + { + "name": "First sprint", + "id": "109-2", + "$type": "Sprint" + } + ], + "hideOrphansSwimlane": false, + "orphansAtTheTop": false, + "visibleForProjectBased": true, + "updateableByProjectBased": true, + "columnSettings": { + "field": { + "name": "State", + "$type": "CustomField" + }, + "columns": [ + { + "fieldValues": [ + { + "name": "Open", + "isResolved": true, + "id": "111-12", + "$type": "AgileColumnFieldValue" + } + ], + "ordinal": 0, + "presentation": "Open", + "wipLimit": { + "id": "205-0", + "max": "10", + "min": "3", + "column": "3", + "$type": "WIPLimit" + }, + "isResolved": true, + "id": "110-8", + "$type": "AgileColumn" + }, + { + "fieldValues": [ + { + "name": "In Progress", + "isResolved": true, + "id": "111-13", + "$type": "AgileColumnFieldValue" + } + ], + "ordinal": 1, + "presentation": "In Progress", + "wipLimit": { + "id": "205-1", + "max": "10", + "min": "3", + "column": "3", + "$type": "WIPLimit" + }, + "isResolved": true, + "id": "110-9", + "$type": "AgileColumn" + }, + { + "fieldValues": [ + { + "name": "Fixed", + "isResolved": true, + "id": "111-14", + "$type": "AgileColumnFieldValue" + } + ], + "ordinal": 2, + "presentation": "Fixed", + "wipLimit": { + "id": "205-2", + "max": "10", + "min": "3", + "column": "3", + "$type": "WIPLimit" + }, + "isResolved": true, + "id": "110-10", + "$type": "AgileColumn" + }, + { + "fieldValues": [ + { + "name": "Verified", + "isResolved": true, + "id": "111-15", + "$type": "AgileColumnFieldValue" + } + ], + "ordinal": 3, + "presentation": "Verified", + "wipLimit": { + "id": "205-3", + "max": "10", + "min": "3", + "column": "3", + "$type": "WIPLimit" + }, + "isResolved": true, + "id": "110-11", + "$type": "AgileColumn" + } + ], + "id": "108-2", + "$type": "ColumnSettings" + }, + "colorCoding": { + "prototype": { + "name": "Type", + "$type": "CustomField" + }, + "id": "108-5", + "$type": "FieldBasedColorCoding" + }, + "currentSprint": { + "name": "First sprint", + "id": "109-2", + "$type": "Sprint" + }, + "originalEstimationField": { + "name": "OriginalEstimationField", + "$type": "CustomField" + }, + "sprintsSettings": { + "explicitQuery": "project: DemoProject1", + "isExplicit": false, + "disableSprints": false, + "hideSubtasksOfCards": false, + "cardOnSeveralSprints": false, + "defaultSprint": { + "name": "First sprint", + "id": "109-2", + "$type": "Sprint" + }, + "sprintSyncField": { + "name": "State", + "$type": "CustomField" + }, + "id": "108-2", + "$type": "SprintsSettings" + }, + "visibleFor": { + "allUsersGroup" : false, + "icon" : "String", + "name" : "String", + "ringId" : "String", + "teamForProject" : { + "shortName": "DP1", + "name": "DemoProject1", + "id": "0-1", + "$type": "Project" + }, + "usersCount" : 2, + "id" : "String", + "$type" : "UserGroup" + }, + "updateableBy": { + "allUsersGroup" : false, + "icon" : "String", + "name" : "String", + "ringId" : "String", + "teamForProject" : { + "shortName": "DP1", + "name": "DemoProject1", + "id": "0-1", + "$type": "Project" + }, + "usersCount" : 2, + "id" : "String", + "$type" : "UserGroup" + }, + "status": { + "errors": [], + "valid": true, + "hasJobs": false, + "warnings": [], + "id": "boardStatus", + "$type": "AgileStatus" + }, + "owner": { + "fullName": "Demo User 1", + "ringId": "0692a47b-3670-452e-8e73-8b166a774705", + "id": "1-2", + "$type": "User" + }, + "name": "Full Board 01", + "id": "109-1", + "$type": "Agile" +} \ No newline at end of file diff --git a/tests/YouTrackSharp.Tests/Resources/FullAgile02.json b/tests/YouTrackSharp.Tests/Resources/FullAgile02.json new file mode 100644 index 0000000..6531da2 --- /dev/null +++ b/tests/YouTrackSharp.Tests/Resources/FullAgile02.json @@ -0,0 +1,251 @@ +{ + "_comment": "Represents a full agile board (no fields are null), with ProjectBasedColorCoding, AttributeBasedSwimlaneSettings (and PredefinedFilterField)", + "projects": [ + { + "shortName": "DP1", + "name": "DemoProject1", + "id": "0-1", + "$type": "Project" + } + ], + "swimlaneSettings": { + "field": { + "presentation": "Type", + "id": "51-3", + "name": "Type", + "$type": "PredefinedFilterField" + }, + "values": [ + { + "name": "Feature 01", + "isResolved": true, + "id": "61-3", + "$type": "SwimlaneEntityAttributeValue" + }, + { + "name": "Feature 02", + "isResolved": true, + "id": "61-4", + "$type": "SwimlaneEntityAttributeValue" + }, + { + "name": "Feature 03", + "isResolved": false, + "id": "61-5", + "$type": "SwimlaneEntityAttributeValue" + } + ], + "id": "105-3", + "name": "Swimlane Settings 01", + "$type": "AttributeBasedSwimlaneSettings" + }, + "estimationField": { + "name": "Estimation", + "$type": "CustomField" + }, + "sprints": [ + { + "name": "First sprint", + "id": "109-2", + "$type": "Sprint" + } + ], + "hideOrphansSwimlane": true, + "orphansAtTheTop": true, + "visibleForProjectBased": true, + "updateableByProjectBased": true, + "columnSettings": { + "field": { + "name": "State", + "$type": "CustomField" + }, + "columns": [ + { + "fieldValues": [ + { + "name": "Open", + "isResolved": true, + "id": "111-12", + "$type": "AgileColumnFieldValue" + } + ], + "ordinal": 0, + "presentation": "Open", + "wipLimit": { + "id": "205-0", + "max": "10", + "min": "3", + "column": "3", + "$type": "WIPLimit" + }, + "isResolved": true, + "id": "110-8", + "$type": "AgileColumn" + }, + { + "fieldValues": [ + { + "name": "In Progress", + "isResolved": true, + "id": "111-13", + "$type": "AgileColumnFieldValue" + } + ], + "ordinal": 1, + "presentation": "In Progress", + "wipLimit": { + "id": "205-1", + "max": "10", + "min": "3", + "column": "3", + "$type": "WIPLimit" + }, + "isResolved": true, + "id": "110-9", + "$type": "AgileColumn" + }, + { + "fieldValues": [ + { + "name": "Fixed", + "isResolved": true, + "id": "111-14", + "$type": "AgileColumnFieldValue" + } + ], + "ordinal": 2, + "presentation": "Fixed", + "wipLimit": { + "id": "205-2", + "max": "10", + "min": "3", + "column": "3", + "$type": "WIPLimit" + }, + "isResolved": true, + "id": "110-10", + "$type": "AgileColumn" + }, + { + "fieldValues": [ + { + "name": "Verified", + "isResolved": true, + "id": "111-15", + "$type": "AgileColumnFieldValue" + } + ], + "ordinal": 3, + "presentation": "Verified", + "wipLimit": { + "id": "205-3", + "max": "10", + "min": "3", + "column": "3", + "$type": "WIPLimit" + }, + "isResolved": true, + "id": "110-11", + "$type": "AgileColumn" + } + ], + "id": "108-2", + "$type": "ColumnSettings" + }, + "colorCoding": { + "id": "108-5", + "projectColors": [ + { + "id": "120-1", + "project": { + "shortName": "DP1", + "name": "DemoProject1", + "id": "0-1", + "$type": "Project" + }, + "color": { + "id": "130-1", + "background": "White", + "foreground": "Black", + "$type": "FieldStyle" + }, + "$type": "ProjectColor" + } + ], + "$type": "ProjectBasedColorCoding" + }, + "currentSprint": { + "name": "First sprint", + "id": "109-2", + "$type": "Sprint" + }, + "originalEstimationField": { + "name": "OriginalEstimationField", + "$type": "CustomField" + }, + "sprintsSettings": { + "explicitQuery": "project: DemoProject1", + "isExplicit": false, + "disableSprints": false, + "hideSubtasksOfCards": false, + "cardOnSeveralSprints": false, + "defaultSprint": { + "name": "First sprint", + "id": "109-2", + "$type": "Sprint" + }, + "sprintSyncField": { + "name": "State", + "$type": "CustomField" + }, + "id": "108-2", + "$type": "SprintsSettings" + }, + "visibleFor": { + "allUsersGroup" : false, + "icon" : "String", + "name" : "String", + "ringId" : "String", + "teamForProject" : { + "shortName": "DP1", + "name": "DemoProject1", + "id": "0-1", + "$type": "Project" + }, + "usersCount" : 2, + "id" : "String", + "$type" : "UserGroup" + }, + "updateableBy": { + "allUsersGroup" : false, + "icon" : "String", + "name" : "String", + "ringId" : "String", + "teamForProject" : { + "shortName": "DP1", + "name": "DemoProject1", + "id": "0-1", + "$type": "Project" + }, + "usersCount" : 2, + "id" : "String", + "$type" : "UserGroup" + }, + "status": { + "errors": [], + "valid": true, + "hasJobs": false, + "warnings": [], + "id": "boardStatus", + "$type": "AgileStatus" + }, + "owner": { + "fullName": "Demo User 1", + "ringId": "0692a47b-3670-452e-8e73-8b166a774705", + "id": "1-2", + "$type": "User" + }, + "name": "Full Board 02", + "id": "109-2", + "$type": "Agile" +} \ No newline at end of file diff --git a/tests/YouTrackSharp.Tests/YouTrackSharp.Tests.csproj b/tests/YouTrackSharp.Tests/YouTrackSharp.Tests.csproj index 26b6aff..3802e6f 100644 --- a/tests/YouTrackSharp.Tests/YouTrackSharp.Tests.csproj +++ b/tests/YouTrackSharp.Tests/YouTrackSharp.Tests.csproj @@ -19,7 +19,7 @@ - - + + \ No newline at end of file