diff --git a/VstsService.Tests/Builds.cs b/VstsService.Tests/Builds.cs index c2b7111c..9920b215 100644 --- a/VstsService.Tests/Builds.cs +++ b/VstsService.Tests/Builds.cs @@ -17,43 +17,7 @@ public Builds(TestConfig config) _config = config; _client = new VstsRestClient(_config.Organization, _config.Token); } - - [Fact] - [Trait("category", "integration")] - public void QueryArtifacts() - { - var artifacts = _client.Get(Requests.Builds.Artifacts(_config.Project, _config.BuildId)).ToList(); - artifacts.ShouldNotBeEmpty(); - - var artifact = artifacts.First(); - artifact.Id.ShouldNotBe(0); - - artifact.Resource.ShouldNotBeNull(); - artifact.Resource.Type.ShouldBe("Container"); - } - - [Fact] - [Trait("category", "integration")] - public async Task QueryBuild() - { - var build = await _client.GetAsync(Requests.Builds.Build(_config.Project, _config.BuildId)); - build.ShouldNotBeNull(); - build.Id.ShouldNotBe(0); - build.Definition.ShouldNotBeNull(); - build.Project.ShouldNotBeNull(); - build.Result.ShouldNotBeNull(); - } - - [Fact] - [Trait("category", "integration")] - public void QueryLongRunningBuilds() - { - var queryOrder = "startTimeAscending"; - var minTime = DateTime.UtcNow.AddHours(-6).ToString("O"); - var build = _client.Get(Requests.Builds.LongRunningBuilds(_config.Project, queryOrder, minTime)).ToList(); - build.ShouldNotBeNull(); - } - + [Fact] [Trait("category", "integration")] public async Task QueryBuildDefinition() @@ -93,20 +57,7 @@ public async Task QueryBuildDefinitionsReturnsBuildDefinitionsWithExtendedProper buildDefinitions.ShouldNotBeNull(); buildDefinitions.SelectTokens("value[*].process").Count().ShouldBeGreaterThan(0); } - - [Fact] - [Trait("category", "integration")] - public async Task CanQueryBuildDefinitionsByProcessType() - { - var projectId = (await _client.GetAsync(Project.Properties(_config.Project))).Id; - - var buildDefinitions = _client.Get(Requests.Builds.BuildDefinitions(projectId, 2)).ToList(); - - buildDefinitions.ShouldNotBeNull(); - buildDefinitions.First().Id.ShouldNotBeNull(); - buildDefinitions.First().Project.Id.ShouldNotBeNull(); - } - + [Fact] [Trait("category", "integration")] public async Task GetProjectRetentionSetting() diff --git a/VstsService.Tests/HttpRequestMessageExtensionsTests.cs b/VstsService.Tests/HttpRequestMessageExtensionsTests.cs deleted file mode 100644 index 7a35a244..00000000 --- a/VstsService.Tests/HttpRequestMessageExtensionsTests.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Net.Http; -using AutoFixture; -using AutoFixture.AutoNSubstitute; -using Shouldly; -using Xunit; - -namespace SecurePipelineScan.VstsService.Tests -{ - public class HttpRequestMessageExtensionsTests - { - private readonly Fixture _fixture = new Fixture(); - - [Fact] - public void ExtMgtRequestShouldReturnTrue() - { - _fixture.Customize(new AutoNSubstituteCustomization()); - - var org = "asdfasdfasdf-test"; - var request = _fixture.Create(); - request.RequestUri = new Uri($"https://{org}.extmgmt.visualstudio.com/blablabla"); - request.IsExtMgtRequest(org).ShouldBeTrue(); - } - - [Fact] - public void OtherRequestShouldReturnFalse() - { - _fixture.Customize(new AutoNSubstituteCustomization()); - - var org = "asdfasdfasdf-test"; - var request = _fixture.Create(); - request.RequestUri = new Uri($"https://dev.azure.com/{org}/blabla"); - request.IsExtMgtRequest(org).ShouldBeFalse(); - } - } -} \ No newline at end of file diff --git a/VstsService.Tests/Processors/QueryBatchProcessorIntegrationTests.cs b/VstsService.Tests/Processors/QueryBatchProcessorIntegrationTests.cs deleted file mode 100644 index dd1fae89..00000000 --- a/VstsService.Tests/Processors/QueryBatchProcessorIntegrationTests.cs +++ /dev/null @@ -1,41 +0,0 @@ -using SecurePipelineScan.VstsService.Processors; -using Shouldly; -using System.Linq; -using Xunit; - -namespace SecurePipelineScan.VstsService.Tests.Processors -{ - /// - /// Tests work item retrieval in batches. - /// - /// - /// As we don't have enough work items in our default organisation (asdfasdfasdf-test), we run this on asdfasdfasdf with the - /// project hard coded. When running this test, make sure your token in appsettings.user.json or an environment - /// variable is valid for asdfasdfasdf. - /// - /// - public class QueryBatchProcessorIntegrationTests : IClassFixture - { - private const string Project = "Investments"; - - private readonly IQueryBatchProcessor _processor; - - public QueryBatchProcessorIntegrationTests(TestConfig config) - { - var client = new VstsRestClient("asdfasdfasdf", config.Token); - _processor = new QueryBatchProcessor(client); - } - - [Fact(Skip = "integration")] - public void ShouldBeAbleToReceiveMoreThan20KWorkItems() - { - // Arrange - - // Act - var resultCount = _processor.QueryByWiql(Project).Count(); - - // Assert - resultCount.ShouldBeGreaterThan(20_000); - } - } -} \ No newline at end of file diff --git a/VstsService.Tests/Processors/QueryBatchProcessorTests.cs b/VstsService.Tests/Processors/QueryBatchProcessorTests.cs deleted file mode 100644 index bd28dbbc..00000000 --- a/VstsService.Tests/Processors/QueryBatchProcessorTests.cs +++ /dev/null @@ -1,94 +0,0 @@ -using AutoFixture; -using NSubstitute; -using SecurePipelineScan.VstsService.Processors; -using SecurePipelineScan.VstsService.Response; -using Shouldly; -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using Xunit; - -namespace SecurePipelineScan.VstsService.Tests.Processors -{ - public class QueryBatchProcessorTests - { - private readonly IVstsRestClient _client = Substitute.For(); - private readonly Fixture _fixture = new Fixture(); - - [Fact] - public void QueryByWiql_WithoutWhereClause_ShouldBeRunInBatchesOfSpecifiedSize() - { - // Arrange - var projectName = _fixture.Create(); - var workItemReferences = new[] {new WorkItemReference {Id = 42}, new WorkItemReference {Id = 96}}; - var processor = new QueryBatchProcessor(_client); - - MockQueryResultsByOne(workItemReferences); - - // Act - var results = processor.QueryByWiql(projectName, batchSize: 1).ToImmutableList(); - - // Assert - results.ShouldBe(workItemReferences); - _client - .Received(workItemReferences.Length + 1) - .PostAsync( - Arg.Is>(r => - r.QueryParams.Any(p => p.Key == "$top" && 1.Equals(p.Value))), - Arg.Any()); - AssertQueriesReceivedContain(workItemReferences, "SELECT [System.Id]"); - } - - [Fact] - public void QueryByWiql_WithWhereClause_ShouldBeRunInBatchesOfSpecifiedSize() - { - // Arrange - const string whereClause = "[System.ChangedDate] < @startOfDay"; - - var projectName = _fixture.Create(); - var workItemReferences = _fixture.CreateMany().ToImmutableList(); - var processor = new QueryBatchProcessor(_client); - - MockQueryResultsByOne(workItemReferences); - - // Act - var results = processor.QueryByWiql(projectName, whereClause, 1).ToImmutableList(); - - // Assert - results.ShouldBe(workItemReferences); - AssertQueriesReceivedContain(workItemReferences, whereClause); - } - - private void MockQueryResultsByOne(IEnumerable workItemReferences) - { - var results = workItemReferences - .Select(r => CreateWorkItemQueryResult(r)) - .Append(CreateWorkItemQueryResult()) - .ToImmutableList(); - - _client - .PostAsync(Arg.Any>(), Arg.Any()) - .Returns(results.First(), results.Skip(1).ToArray()); - } - - private WorkItemQueryResult CreateWorkItemQueryResult(params WorkItemReference[] workItems) => - new WorkItemQueryResult - { - WorkItems = workItems.ToImmutableList(), - AsOf = _fixture.Create() - }; - - private void AssertQueriesReceivedContain(ICollection workItemReferences, string query) - { - _client - .Received(workItemReferences.Count + 1) - .PostAsync( - Arg.Any>(), - Arg.Is(q => QueryContains(q, query))); - } - - private static bool QueryContains(QueryByWiql queryByWiql, string expectedPart) => - queryByWiql.Query.Contains(expectedPart, StringComparison.InvariantCultureIgnoreCase); - } -} \ No newline at end of file diff --git a/VstsService.Tests/TaskGroup.cs b/VstsService.Tests/TaskGroup.cs deleted file mode 100644 index f22c1b34..00000000 --- a/VstsService.Tests/TaskGroup.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Shouldly; -using System.Linq; -using System.Threading.Tasks; -using Xunit; - -namespace SecurePipelineScan.VstsService.Tests -{ - public class TaskGroup : IClassFixture - { - private readonly TestConfig _config; - private readonly IVstsRestClient _client; - - public TaskGroup(TestConfig config) - { - _config = config; - _client = new VstsRestClient(_config.Organization, _config.Token); - } - - [Fact] - [Trait("category", "integration")] - public async Task GetTaskGroupById() - { - var response = await _client.GetAsync(Requests.TaskGroup.TaskGroupById(_config.Project, "df6aa8e5-82dc-468c-a794-a7990523363d")); - response.ShouldNotBeNull(); - response.Value.FirstOrDefault().Tasks.ShouldNotBeNull(); - response.Value.FirstOrDefault().Tasks.FirstOrDefault().Task.Id.ShouldNotBeNull(); - } - } -} \ No newline at end of file diff --git a/VstsService.Tests/TestManagement.cs b/VstsService.Tests/TestManagement.cs deleted file mode 100644 index bb9d2700..00000000 --- a/VstsService.Tests/TestManagement.cs +++ /dev/null @@ -1,39 +0,0 @@ -using AutoFixture; -using SecurePipelineScan.VstsService.Requests; -using Shouldly; -using System; -using System.Collections.Generic; -using System.Text; -using Xunit; - -namespace SecurePipelineScan.VstsService.Tests -{ - public class TestManagement : IClassFixture - { - private readonly TestConfig _config; - private readonly IVstsRestClient _client; - - public TestManagement(TestConfig config) - { - _config = config; - _client = new VstsRestClient(config.Organization, config.Token); - } - - [Fact] - public void GetManualTestRuns_ShouldReturnResults() - { - // Arrange - var maxdate = DateTime.UtcNow; - var mindate = maxdate.AddDays(-1); - - // Act - var result = _client.Get(Requests.TestManagement.QueryTestRuns(_config.Project, mindate, maxdate, false)); - - // Assert - result.ShouldNotBeNull(); - result.ShouldBeEmpty(); - } - - - } -} diff --git a/VstsService.Tests/Timeline.cs b/VstsService.Tests/Timeline.cs deleted file mode 100644 index 2d0f9b6e..00000000 --- a/VstsService.Tests/Timeline.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Shouldly; -using System.Threading.Tasks; -using Xunit; - -namespace SecurePipelineScan.VstsService.Tests -{ - public class Timeline : IClassFixture - { - private readonly TestConfig _config; - private readonly IVstsRestClient _client; - - public Timeline(TestConfig config) - { - _config = config; - _client = new VstsRestClient(_config.Organization, _config.Token); - } - - [Fact] - [Trait("category", "integration")] - public async Task QueryTimeline() - { - var timeline = await _client.GetAsync(Requests.Builds.Timeline(_config.Project, _config.BuildId)); - timeline.ShouldNotBeNull(); - } - } -} \ No newline at end of file diff --git a/VstsService.Tests/VstsRestClientTests.cs b/VstsService.Tests/VstsRestClientTests.cs index e9dda1c2..31251c2a 100644 --- a/VstsService.Tests/VstsRestClientTests.cs +++ b/VstsService.Tests/VstsRestClientTests.cs @@ -105,7 +105,7 @@ public async Task RestRequestResultAsJsonObject() [Fact] public async Task NotFoundIsNull() { - var result = await _vsts.GetAsync(Requests.Builds.Build(_config.Project, "2342423")); + var result = await _vsts.GetAsync(Requests.Builds.BuildDefinition(_config.Project, "2342423")); result.ShouldBeNull(); } } diff --git a/VstsService.Tests/Wiql.cs b/VstsService.Tests/Wiql.cs deleted file mode 100644 index 6cea5e1c..00000000 --- a/VstsService.Tests/Wiql.cs +++ /dev/null @@ -1,36 +0,0 @@ -using SecurePipelineScan.VstsService.Requests; -using SecurePipelineScan.VstsService.Response; -using Shouldly; -using System.Linq; -using Xunit; -using Task = System.Threading.Tasks.Task; - -namespace SecurePipelineScan.VstsService.Tests -{ - public class Wiql : IClassFixture - { - private readonly TestConfig _config; - private readonly IVstsRestClient _client; - - public Wiql(TestConfig config) - { - _config = config; - _client = new VstsRestClient(config.Organization, config.Token); - } - - [Fact] - public async Task QueryByWiql_ShouldReturnResults() - { - // Arrange - - // Act - var result = await _client.PostAsync(WorkItemTracking.QueryByWiql(_config.Project, 1), - new QueryByWiql("select [System.Id] from WorkItems")); - - // Assert - result.ShouldNotBeNull(); - result.WorkItems.ShouldNotBeEmpty(); - result.WorkItems.First().Id.ShouldNotBe(default); - } - } -} \ No newline at end of file diff --git a/VstsService.Tests/WorkItemTests.cs b/VstsService.Tests/WorkItemTests.cs deleted file mode 100644 index b021d723..00000000 --- a/VstsService.Tests/WorkItemTests.cs +++ /dev/null @@ -1,44 +0,0 @@ -using SecurePipelineScan.VstsService.Requests; -using SecurePipelineScan.VstsService.Response; -using Shouldly; -using System; -using System.Linq; -using Xunit; -using Task = System.Threading.Tasks.Task; - -namespace SecurePipelineScan.VstsService.Tests -{ - public class WorkItemTests : IClassFixture - { - private readonly TestConfig _config; - private readonly IVstsRestClient _client; - - public WorkItemTests(TestConfig config) - { - _config = config ?? throw new ArgumentNullException(nameof(config)); - _client = new VstsRestClient(config.Organization, config.Token); - } - - [Fact] - public async Task GetSingle_ShouldReturnWorkItem() - { - // Arrange - var queryResult = await _client.PostAsync(WorkItemTracking.QueryByWiql(_config.Project, 1), - new QueryByWiql($"select [System.Id] from WorkItems")); - var workItem = queryResult.WorkItems.First(); - var fields = new[] {FieldNames.TeamProject}; - - // Act - var result = - await _client.GetAsync(WorkItemTracking.GetWorkItem(_config.Project, workItem.Id, fields, - queryResult.AsOf)); - - // Assert - result.ShouldNotBeNull(); - result.Id.ShouldBe(workItem.Id); - result.Fields.ShouldNotBeNull(); - result.Fields.ShouldContainKey(FieldNames.TeamProject); - result.Fields[FieldNames.TeamProject].ShouldNotBeNull(); - } - } -} \ No newline at end of file diff --git a/VstsService/HttpRequestMessageExtensions.cs b/VstsService/HttpRequestMessageExtensions.cs deleted file mode 100644 index 2d1aa8a4..00000000 --- a/VstsService/HttpRequestMessageExtensions.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Net.Http; - -namespace SecurePipelineScan.VstsService -{ - public static class HttpRequestMessageExtensions - { - public static bool IsExtMgtRequest(this HttpRequestMessage request, string organization) - { - if (request == null) - throw new ArgumentNullException(nameof(request)); - - return new ExtmgmtRequest(string.Empty).BaseUri(organization).IsBaseOf(request.RequestUri); - } - } -} \ No newline at end of file diff --git a/VstsService/Processors/QueryBatchProcessor.cs b/VstsService/Processors/QueryBatchProcessor.cs deleted file mode 100644 index d7b99b23..00000000 --- a/VstsService/Processors/QueryBatchProcessor.cs +++ /dev/null @@ -1,76 +0,0 @@ -using SecurePipelineScan.VstsService.Requests; -using SecurePipelineScan.VstsService.Response; -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace SecurePipelineScan.VstsService.Processors -{ - public class QueryBatchProcessor : IQueryBatchProcessor - { - private const int DefaultBatchSize = 20_000 - 1; - - private readonly IVstsRestClient _client; - - public QueryBatchProcessor(IVstsRestClient client) - { - _client = client ?? throw new ArgumentNullException(nameof(client)); - } - - public IEnumerable QueryByWiql(string project, string whereClause = null, - int batchSize = DefaultBatchSize) => - new BatchedQueryByWiql(_client, project, whereClause, batchSize); - - private class BatchedQueryByWiql : IEnumerable - { - private readonly IVstsRestClient _client; - private readonly string _project; - private readonly int _batchSize; - private readonly string _extraWhereClause; - - public BatchedQueryByWiql(IVstsRestClient client, string project, string whereClause, int batchSize) - { - _client = client ?? throw new ArgumentNullException(nameof(client)); - _project = project ?? throw new ArgumentNullException(nameof(project)); - _batchSize = batchSize; - - _extraWhereClause = string.IsNullOrEmpty(whereClause) ? string.Empty : $"AND ({whereClause})"; - } - - public IEnumerator GetEnumerator() - { - var id = 0; - WorkItemQueryResult result; - do - { - result = QuerySingleBatchAsync(id) - .ConfigureAwait(false) - .GetAwaiter().GetResult(); - - if (result.WorkItems.Any()) - { - foreach (var workItem in result.WorkItems) - { - yield return workItem; - } - id = result.WorkItems.Last().Id; - } - } while (result.WorkItems.Any()); - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - private Task QuerySingleBatchAsync(int id) - { - var fullWhereClause = $@"[{FieldNames.TeamProject}] = @Project AND [{FieldNames.Id}] > { - id - } {_extraWhereClause} ORDER BY [{FieldNames.Id}]"; - var query = $"SELECT [{FieldNames.Id}] FROM WorkItems WHERE {fullWhereClause}"; - - return _client.PostAsync(WorkItemTracking.QueryByWiql(_project, _batchSize), new QueryByWiql(query)); - } - } - } -} \ No newline at end of file diff --git a/VstsService/Requests/BuildArtifact.cs b/VstsService/Requests/BuildArtifact.cs deleted file mode 100644 index a9db812c..00000000 --- a/VstsService/Requests/BuildArtifact.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace SecurePipelineScan.VstsService.Requests -{ - public class BuildArtifact - { - public int Id { get; set; } - public ArtifactResource Resource { get; set; } - } -} \ No newline at end of file diff --git a/VstsService/Requests/Builds.cs b/VstsService/Requests/Builds.cs index c266b4da..85322505 100644 --- a/VstsService/Requests/Builds.cs +++ b/VstsService/Requests/Builds.cs @@ -14,40 +14,12 @@ public static IEnumerableRequest BuildDefinitions(string projec {"api-version", "5.0-preview.7"} }).AsEnumerable(); - public static IEnumerableRequest BuildDefinitions(string projectId, int processType) => - new VstsRequest( - $"{projectId}/_apis/build/definitions", new Dictionary - { - {"processType", $"{processType}"}, - {"api-version", "5.0-preview.7"} - }).AsEnumerable(); - public static IEnumerableRequest BuildDefinitions(string projectId) => BuildDefinitions(projectId, false); public static IVstsRequest BuildDefinition(string projectId, string id) => new VstsRequest($"{projectId}/_apis/build/definitions/{id}"); - public static IEnumerableRequest Artifacts(string project, string id) => - new VstsRequest($"{project}/_apis/build/builds/{id}/artifacts").AsEnumerable(); - - public static IVstsRequest Timeline(string project, string id) => - new VstsRequest($"{project}/_apis/build/builds/{id}/timeline"); - - public static IVstsRequest Build(string project, string id) => - new VstsRequest($"{project}/_apis/build/builds/{id}"); - - public static IEnumerableRequest LongRunningBuilds(string project, string queryOrder, string minTime) => - new VstsRequest($"{project}/_apis/build/builds/", new Dictionary - { - {"queryOrder", queryOrder}, - { "minTime", minTime}, - {"api-version", "5.1"} - }).AsEnumerable(); - - public static IEnumerableRequest All(string project) => - new VstsRequest($"{project}/_apis/build/builds").AsEnumerable(); - public static IVstsRequest Retention(string project) => new VstsRequest($"{project}/_apis/build/retention"); } diff --git a/VstsService/Requests/TaskGroup.cs b/VstsService/Requests/TaskGroup.cs deleted file mode 100644 index 7dad88df..00000000 --- a/VstsService/Requests/TaskGroup.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Collections.Generic; - -namespace SecurePipelineScan.VstsService.Requests -{ - public static class TaskGroup - { - public static IVstsRequest TaskGroupById(string project, string id) => - new VstsRequest($"{project}/_apis/distributedtask/taskgroups/{id}", new Dictionary - { - { "api-version", "6.0-preview.1" } - }); - } -} \ No newline at end of file diff --git a/VstsService/Requests/TestManagement.cs b/VstsService/Requests/TestManagement.cs deleted file mode 100644 index 21dd39e4..00000000 --- a/VstsService/Requests/TestManagement.cs +++ /dev/null @@ -1,20 +0,0 @@ -using SecurePipelineScan.VstsService.Response; -using System; -using System.Collections.Generic; -using System.Text; - -namespace SecurePipelineScan.VstsService.Requests -{ - public static class TestManagement - { - public static IEnumerableRequest QueryTestRuns(string project, DateTime mindate, DateTime maxdate, bool isAutomated) => - new VstsRequest($"{project}/_apis/test/runs", - new Dictionary - { - ["api-version"] = "5.0", - ["isAutomated"] = isAutomated, - ["minLastUpdatedDate"] = mindate, - ["maxLastUpdatedDate"] = maxdate - }).AsEnumerable(); - } -} diff --git a/VstsService/Requests/WorkItemTracking.cs b/VstsService/Requests/WorkItemTracking.cs deleted file mode 100644 index 18b79389..00000000 --- a/VstsService/Requests/WorkItemTracking.cs +++ /dev/null @@ -1,26 +0,0 @@ -using SecurePipelineScan.VstsService.Response; -using System; -using System.Collections.Generic; - -namespace SecurePipelineScan.VstsService.Requests -{ - public static class WorkItemTracking - { - public static IVstsRequest QueryByWiql(string project, int? top = null) => - new VstsRequest( - $"{project}/_apis/wit/wiql", new Dictionary - { - ["api-version"] = "5.1", - ["$top"] = top - }); - - public static IVstsRequest GetWorkItem(string project, int id, IEnumerable fields = null, - DateTime? asOf = null) => new VstsRequest( - $"{project}/_apis/wit/workitems/{id}", new Dictionary - { - ["api-version"] = "5.1", - ["asOf"] = asOf, - ["fields"] = fields == null ? null : string.Join(",", fields) - }); - } -} \ No newline at end of file diff --git a/VstsService/Response/QueryByWiql.cs b/VstsService/Response/QueryByWiql.cs deleted file mode 100644 index 6e00cd4e..00000000 --- a/VstsService/Response/QueryByWiql.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace SecurePipelineScan.VstsService.Response -{ - public class QueryByWiql - { - public string Query { get; } - - public QueryByWiql(string query) - { - Query = query ?? throw new ArgumentNullException(nameof(query)); - } - } -} \ No newline at end of file diff --git a/VstsService/Response/WorkItemQueryResult.cs b/VstsService/Response/WorkItemQueryResult.cs deleted file mode 100644 index 4db4a4e3..00000000 --- a/VstsService/Response/WorkItemQueryResult.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace SecurePipelineScan.VstsService.Response -{ - public class WorkItemQueryResult - { - public DateTime AsOf { get; set; } - public IList WorkItems { get; set; } - } -} \ No newline at end of file