/// <inheritdoc /> public async Task <IEnumerable <WorkItem> > GetWorkItemsAsync(WorkItemsQuery query, bool expand = false, CancellationToken cancellationToken = default(CancellationToken)) { var queryResult = await ExecuteQueryAsync(query, cancellationToken); int[] ids; switch (queryResult) { case FlatWorkItemsQueryResult flat: ids = GetWorkitemIdsFromQuery(flat); break; case HierarchicalWorkItemsQueryResult tree: ids = GetWorkitemIdsFromQuery(tree); break; default: throw new NotSupportedException($"Query result is of not supported type."); } if (!ids.Any()) { return(Enumerable.Empty <WorkItem>()); } if (!expand) { var columns = queryResult.Columns.Select(c => c.ReferenceName).ToArray(); return(await GetWorkItemsAsync(ids, fields : columns, cancellationToken : cancellationToken)); } else { return(await GetWorkItemsAsync(ids, cancellationToken : cancellationToken)); } }
public async Task GetWorkItemsShouldComposeCorrectUrlForFlatQueries() { var query = WorkItemsQuery.Get("Dummy query"); var queryResult = new FlatWorkItemsQueryResult { Columns = new[] { new ColumnReference("Id", "System.Id"), new ColumnReference("Title", "System.Title") }, WorkItems = new[] { new WorkItemReference(2), new WorkItemReference(34), new WorkItemReference(56) } }; var fields = queryResult.Columns.Select(c => c.ReferenceName); var ids = queryResult.WorkItems.Select(w => w.Id); var workItems = ids.Select(i => new WorkItem { Id = i }); HttpClientMock.Setup(c => c.ExecutePost <FlatWorkItemsQueryResult>(It.IsAny <string>(), It.Is <WorkItemsQuery>(q => !q.IsHierarchical), CancellationToken)) .ReturnsAsync(queryResult) .Verifiable(); HttpClientMock.Setup(c => c.ExecuteGet <CollectionResponse <WorkItem> >(It.Is <string>(u => VerifyWorkItemsUrl(u, fields, ids)), CancellationToken)) .ReturnsAsync(new CollectionResponse <WorkItem> { Value = workItems }) .Verifiable(); var result = await Client.GetWorkItemsAsync(query, false, CancellationToken); result.Should().HaveCount(workItems.Count()); result.Should().BeEquivalentTo(workItems); HttpClientMock.Verify(); }
/// <inheritdoc /> public async Task<IEnumerable<WorkItem>> GetWorkItemsAsync(string project, WorkItemsQuery query, CancellationToken cancellationToken = default(CancellationToken)) { var queryResult = await ExecuteQueryAsync(project, query, cancellationToken); int[] ids; switch (queryResult) { case FlatWorkItemsQueryResult flat: ids = GetWorkitemIdsFromQuery(flat); break; case HierarchicalWorkItemsQueryResult tree: ids = GetWorkitemIdsFromQuery(tree); break; default: throw new NotSupportedException($"Query result is of not supported type."); } if (!ids.Any()) return Enumerable.Empty<WorkItem>(); var fieldsString = string.Join(",", queryResult.Columns.Select(c => c.ReferenceName)); var idsString = string.Join(",", ids); var url = VstsUrlBuilder.Create(_instanceName) .ForWorkItemsBatch(idsString, project) .WithQueryParameter("fields", fieldsString) .Build(); var workitemsResponse = await _httpClient.ExecuteGet<CollectionResponse<WorkItem>>(url, cancellationToken); if (workitemsResponse == null) return Enumerable.Empty<WorkItem>(); return workitemsResponse.Value; }
public void ExecuteQueryShouldThrowArgumentExceptionIfQueryIsEmpty() { var query = WorkItemsQuery.Get(string.Empty); Client.Awaiting(async c => await c.ExecuteQueryAsync(query)) .Should() .Throw <ArgumentException>(); }
public void ExecuteQueryShouldThrowArgumentExceptionIfQueryIsEmpty() { var query = new WorkItemsQuery(string.Empty); _client.Awaiting(async c => await c.ExecuteQueryAsync(ProjectName, query)) .Should() .Throw <ArgumentException>(); }
private async Task <T> ExecuteQueryInternalAsync <T>(WorkItemsQuery query, CancellationToken cancellationToken) { ThrowIfArgumentNull(query, nameof(query)); var url = _urlBuilderFactory.Create() .ForWIQL() .Build(Constants.CurrentWorkItemsApiVersion); return(await _httpClient.ExecutePost <T>(url, query, cancellationToken)); }
public void GetWorkItemsShouldThrowExceptionIfNullQuery() { var query = WorkItemsQuery.Get("Dummy query"); HttpClientMock.Setup(c => c.ExecutePost <FlatWorkItemsQueryResult>(It.IsAny <string>(), It.Is <WorkItemsQuery>(q => !q.IsHierarchical), CancellationToken.None)) .ReturnsAsync((FlatWorkItemsQueryResult)null); Client.Awaiting(c => c.GetWorkItemsAsync(query)) .Should().Throw <NotSupportedException>(); }
public async Task GetWorkItemsShouldReturnEmptyListOfWorkItemsIfResponseIsNull() { var query = WorkItemsQuery.Get("Dummy query"); HttpClientMock.Setup(c => c.ExecutePost <FlatWorkItemsQueryResult>(It.IsAny <string>(), It.Is <WorkItemsQuery>(q => !q.IsHierarchical), CancellationToken.None)) .ReturnsAsync(new FlatWorkItemsQueryResult { Columns = Enumerable.Empty <ColumnReference>(), WorkItems = Enumerable.Empty <WorkItemReference>() }); HttpClientMock.Setup(c => c.ExecuteGet <CollectionResponse <WorkItem> >(It.IsAny <string>(), CancellationToken.None)) .ReturnsAsync((CollectionResponse <WorkItem>)null); var result = await Client.GetWorkItemsAsync(query); result.Should().HaveCount(0); }
public async Task ExecuteQueryShouldReturnCorrectResultType(bool isHierarchical, Type expectedReturnType) { var query = new WorkItemsQuery("Dummy query", isHierarchical); _httpClientMock.Setup(c => c.ExecutePost <HierarchicalWorkItemsQueryResult>(It.Is <string>(u => VerifyWiqlQueryUrl(u)), It.Is <WorkItemsQuery>(q => q.IsHierarchical), _cancellationToken)) .ReturnsAsync(new HierarchicalWorkItemsQueryResult()); _httpClientMock.Setup(c => c.ExecutePost <FlatWorkItemsQueryResult>(It.Is <string>(u => VerifyWiqlQueryUrl(u)), It.Is <WorkItemsQuery>(q => !q.IsHierarchical), _cancellationToken)) .ReturnsAsync(new FlatWorkItemsQueryResult()); var result = await _client.ExecuteQueryAsync(ProjectName, query, _cancellationToken); result.Should().BeOfType(expectedReturnType); _httpClientMock.Verify(c => c.ExecutePost <HierarchicalWorkItemsQueryResult>(It.Is <string>(u => VerifyWiqlQueryUrl(u)), It.Is <WorkItemsQuery>(q => q.IsHierarchical), _cancellationToken), Times.Exactly(isHierarchical ? 1 : 0)); _httpClientMock.Verify(c => c.ExecutePost <FlatWorkItemsQueryResult>(It.Is <string>(u => VerifyWiqlQueryUrl(u)), It.Is <WorkItemsQuery>(q => !q.IsHierarchical), _cancellationToken), Times.Exactly(!isHierarchical ? 1 : 0)); }
/// <inheritdoc /> public async Task <WorkItemsQueryResult> ExecuteQueryAsync(WorkItemsQuery query, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfArgumentNull(query, nameof(query)); ThrowIfArgumentNullOrEmpty(query.Query, "Query cannot be empty."); var url = _urlBuilderFactory.Create() .ForWIQL() .Build(Constants.CurrentWorkItemsApiVersion); _logger.LogDebug("Requesting {0}", url); if (query.IsHierarchical) { return(await _httpClient.ExecutePost <HierarchicalWorkItemsQueryResult>(url, query, cancellationToken)); } return(await _httpClient.ExecutePost <FlatWorkItemsQueryResult>(url, query, cancellationToken)); }
public async Task <HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) { var config = await _mediator.Request <GetFirstOrganization, OrganizationViewModel>(); if (config == null || config.Identity.Equals(Guid.Empty)) { return(HealthCheckResult.Unhealthy("ADO default identity is not set.")); } if (string.IsNullOrEmpty(config.Name)) { return(HealthCheckResult.Unhealthy("ADO instance name is not set.")); } var identity = await _mediator.Request <GetIdentityById, IdentityViewModel>(new GetIdentityById { Id = config.Identity }); if (identity == null || string.IsNullOrEmpty(identity.Token)) { return(HealthCheckResult.Unhealthy("Token is empty.")); } if (identity.ExpirationDate < DateTime.UtcNow.AddDays(15)) { return(HealthCheckResult.Degraded($"Default token will expire on {identity.ExpirationDate.ToString("MM/dd/yyyy")}")); } if (identity.ExpirationDate < DateTime.UtcNow) { return(HealthCheckResult.Unhealthy("Default token has expired.")); } try { var client = VstsClient.Get(new OnlineUrlBuilderFactory(config.Name), identity.Token); await client.ExecuteQueryAsync(WorkItemsQuery.Get(@"SELECT [System.Id] FROM WorkItems WHERE (ID < 1)")); } catch (Exception ex) { return(HealthCheckResult.Unhealthy("Exception while fetching from ADO", ex)); } return(HealthCheckResult.Healthy("AzureDevOps is OK")); }
public async Task GetWorkItemsShouldReturnEmptyIfNoItemsFound() { var query = WorkItemsQuery.Get("Dummy query"); var queryResult = new FlatWorkItemsQueryResult { Columns = new ColumnReference[0], WorkItems = new WorkItemReference[0] }; HttpClientMock.Setup(c => c.ExecutePost <FlatWorkItemsQueryResult>(It.IsAny <string>(), It.Is <WorkItemsQuery>(q => !q.IsHierarchical), CancellationToken)) .ReturnsAsync(queryResult) .Verifiable(); var result = await Client.GetWorkItemsAsync(query, false, CancellationToken); result.Should().BeEmpty(); HttpClientMock.Verify(); HttpClientMock.Verify(c => c.ExecuteGet <CollectionResponse <WorkItem> >(It.IsAny <string>(), CancellationToken), Times.Never()); }
public async Task GetWorkItemsShouldComposeCorrectUrlForTreeQueries() { var query = new WorkItemsQuery("Dummy query", isHierarchical: true); var queryResult = new HierarchicalWorkItemsQueryResult { Columns = new[] { new ColumnReference("Id", "System.Id"), new ColumnReference("Title", "System.Title") }, WorkItemRelations = new[] { new WorkItemLink(new WorkItemReference(2), new WorkItemReference(34), "foo"), new WorkItemLink(new WorkItemReference(2), new WorkItemReference(2), "foo"), new WorkItemLink(new WorkItemReference(2), new WorkItemReference(56), "foo") } }; var fields = queryResult.Columns.Select(c => c.ReferenceName); var ids = queryResult.WorkItemRelations.Select(w => w.Source.Id) .Union(queryResult.WorkItemRelations.Select(w => w.Target.Id)) .Distinct() .ToArray(); var workItems = ids.Select(i => new WorkItem { Id = i }); _httpClientMock.Setup(c => c.ExecutePost <HierarchicalWorkItemsQueryResult>(It.IsAny <string>(), It.Is <WorkItemsQuery>(q => q.IsHierarchical), _cancellationToken)) .ReturnsAsync(queryResult) .Verifiable(); _httpClientMock.Setup(c => c.ExecuteGet <CollectionResponse <WorkItem> >(It.Is <string>(u => VerifyWorkItemsUrl(u, fields, ids)), _cancellationToken)) .ReturnsAsync(new CollectionResponse <WorkItem> { Value = workItems }) .Verifiable(); var result = await _client.GetWorkItemsAsync(ProjectName, query, _cancellationToken); result.Should().HaveCount(workItems.Count()); result.Should().BeEquivalentTo(workItems); _httpClientMock.Verify(); }
public void GetWorkItemsShouldNotCatchExceptions() { var query = WorkItemsQuery.Get("Dummy query"); // Test 1 HttpClientMock.Setup(c => c.ExecutePost <FlatWorkItemsQueryResult>(It.IsAny <string>(), It.Is <WorkItemsQuery>(q => !q.IsHierarchical), CancellationToken.None)) .Throws <Exception>(); Client.Awaiting(c => c.GetWorkItemsAsync(query)) .Should().Throw <Exception>(); // Test 2 HttpClientMock.Setup(c => c.ExecutePost <FlatWorkItemsQueryResult>(It.IsAny <string>(), It.Is <WorkItemsQuery>(q => !q.IsHierarchical), CancellationToken.None)) .ReturnsAsync(new FlatWorkItemsQueryResult { Columns = new[] { new ColumnReference("Title", "System.Title") }, WorkItems = new[] { new WorkItemReference(1) } }); HttpClientMock.Setup(c => c.ExecuteGet <CollectionResponse <WorkItem> >(It.IsAny <string>(), CancellationToken.None)) .Throws(new Exception()); Client.Awaiting(c => c.GetWorkItemsAsync(query)) .Should().Throw <Exception>(); }
/// <inheritdoc /> public async Task <HierarchicalWorkItemsQueryResult> ExecuteHierarchicalQueryAsync(string query, CancellationToken cancellationToken = default(CancellationToken)) { var result = await ExecuteQueryAsync(WorkItemsQuery.Get(query, isHierarchical: true), cancellationToken); return(result as HierarchicalWorkItemsQueryResult); }
/// <inheritdoc /> public async Task <WorkItemsQueryResult> ExecuteQueryAndExpandAsync(string query, bool expandFields, CancellationToken cancellationToken = default(CancellationToken)) { ThrowIfArgumentNullOrEmpty(query, nameof(query)); return(await ExecuteQueryAndExpandInternal(async() => await ExecuteQueryInternalAsync <JObject>(WorkItemsQuery.Get(query), cancellationToken), expandFields, cancellationToken)); }