public async Task CreateWorkItemAsync_OnDuplicateWorkItem_SetsDuplicateLabel(bool isIssueDuplicate) { // Arrange var issuesMock = new GitHubIssueMock(); var ctorArgs = new CtorArgs { Issues = issuesMock.Issues }; GitHubRepoIssueReaderWriter target = CreateTarget(ctorArgs); WorkItemDetails workItemDetails = CreateSampleWorkItemDetails(isDuplicate: isIssueDuplicate); // Act await target.WriteWorkItemAsync(workItemDetails); // Assert if (isIssueDuplicate) { Assert.Equal(2, issuesMock.UpdateIssueArgs.IssueUpdate.Labels.Count); Assert.Contains(GitHubLabels.Duplicate, issuesMock.UpdateIssueArgs.IssueUpdate.Labels); } else { Assert.Single(issuesMock.UpdateIssueArgs.IssueUpdate.Labels); } Assert.Contains(GitHubLabels.CodePlexMigrated, issuesMock.UpdateIssueArgs.IssueUpdate.Labels); }
public async Task CreateWorkItemAsync_OnWorkItemWithFeatureIssueAndTextTypes_SetsIssueTypeLabel(string codePlexWorkItemType, string gitHubLabel) { // Arrange var issuesMock = new GitHubIssueMock(); var ctorArgs = new CtorArgs { Issues = issuesMock.Issues }; GitHubRepoIssueReaderWriter target = CreateTarget(ctorArgs); WorkItemDetails workItemDetails = CreateSampleWorkItemDetails(type: codePlexWorkItemType); // Act await target.WriteWorkItemAsync(workItemDetails); // Assert if (gitHubLabel != null) { Assert.Equal(2, issuesMock.UpdateIssueArgs.IssueUpdate.Labels.Count); Assert.Contains(gitHubLabel, issuesMock.UpdateIssueArgs.IssueUpdate.Labels); } else { Assert.Single(issuesMock.UpdateIssueArgs.IssueUpdate.Labels); } Assert.Contains(GitHubLabels.CodePlexMigrated, issuesMock.UpdateIssueArgs.IssueUpdate.Labels); }
public DynamicController(string name, string nameSpace, string route, string controllerComments) { _name = name; _namespace = nameSpace; _route = route; _controllerComments = controllerComments; Namespaces.Add(@"Microsoft.Extensions.Logging"); CtorArgs.Add(@"ILoggerFactory loggerFactory"); Fields.Add($@"private readonly ILogger<{_name}> _log;"); }
public async Task GetMigratedWorkItems_IfMultipleWorkItemsExist_ReturnsWorkItems() { // Arrange int migratedIssueCount = 2; int partiallyMigratedIssueCount = 3; // 2 calls for migrated issues + 2 calls for partially migrated issues since Search mock paginates any // search result set passed to it via SetSearchResults(). int expectedSearchCallCount = 4; TestIssue[] migratedIssues = Enumerable.Range(0, migratedIssueCount).Select(i => CreateSampleIssue(GitHubLabels.CodePlexMigrated)).ToArray(); TestIssue[] partiallyMigratedIssues = Enumerable.Range(0, partiallyMigratedIssueCount).Select(i => CreateSampleIssue(GitHubLabels.CodePlexMigrationInitiated)).ToArray(); var searchMock = new GitHubSearchByLabelMock() .SetSearchResults(GitHubLabels.CodePlexMigrated, migratedIssues) .SetSearchResults(GitHubLabels.CodePlexMigrationInitiated, partiallyMigratedIssues); var ctorArgs = new CtorArgs { Search = searchMock.Search }; GitHubRepoIssueReaderWriter target = CreateTarget(ctorArgs); // Act IReadOnlyList <MigratedWorkItem> migratedWorkItems = await target.GetMigratedWorkItemsAsync(); // Assert Assert.Equal(migratedIssueCount + partiallyMigratedIssueCount, migratedWorkItems.Count); foreach (MigratedWorkItem migratedWorkItem in migratedWorkItems) { switch (migratedWorkItem.MigrationState) { case MigrationState.Migrated: Assert.Contains(migratedIssues, issue => issue.WorkItemId == migratedWorkItem.CodePlexWorkItemId); break; case MigrationState.PartiallyMigrated: Assert.Contains(partiallyMigratedIssues, issue => issue.WorkItemId == migratedWorkItem.CodePlexWorkItemId); break; default: Assert.True(false, "Unexpected work item migration state"); break; } } Assert.Equal(IssueTypeQualifier.Issue, searchMock.SearchIssuesRequest.Type); Assert.Single(searchMock.SearchIssuesRequest.Repos); Assert.Equal(ctorArgs.FullRepoName, searchMock.SearchIssuesRequest.Repos[0]); searchMock.VerifySearchCallCount(callCount: expectedSearchCallCount); }
public async Task UpdateWorkItemAsync_IfWorkItemExists_Succeeds(bool hasAttachments) { // Arrange Issue issue = CreateSampleIssue(label: "AnyLabel"); WorkItemDetails workItemDetails = CreateSampleWorkItemDetails(hasAttachments: hasAttachments); var issuesMock = new GitHubIssueMock(); var searchMock = new GitHubSearchInBodyMock(searchResults: new[] { issue }); CtorArgs ctorArgs = new CtorArgs { Search = searchMock.Search, Issues = issuesMock.Issues }; GitHubRepoIssueReaderWriter target = CreateTarget(ctorArgs); // Act await target.UpdateWorkItemAsync(workItemDetails); // Assert: Search Assert.Contains(workItemDetails.WorkItem.Id.ToString(), searchMock.SearchIssuesRequest.Term); Assert.Equal(IssueTypeQualifier.Issue, searchMock.SearchIssuesRequest.Type); Assert.Single(searchMock.SearchIssuesRequest.Repos); Assert.Equal(ctorArgs.FullRepoName, searchMock.SearchIssuesRequest.Repos[0]); Assert.Contains(searchMock.SearchIssuesRequest.In, q => q == IssueInQualifier.Body); searchMock.VerifySearchCallCount(callCount: 1); // Assert: Update -- Owner + Repo + Issue number Assert.Equal(ctorArgs.RepoOwner, issuesMock.UpdateIssueArgs.Owner); Assert.Equal(ctorArgs.Repo, issuesMock.UpdateIssueArgs.Name); Assert.Equal(issue.Number, issuesMock.UpdateIssueArgs.Number); // Assert: Update -- Title + Body Assert.Equal(workItemDetails.WorkItem.Summary, issuesMock.UpdateIssueArgs.IssueUpdate.Title); Assert.Contains(TextUtilities.GetFormattedWorkItemBody(workItemDetails.WorkItem, workItemDetails.FileAttachments), issuesMock.UpdateIssueArgs.IssueUpdate.Body); // Assert: Update -- Labels Assert.Single(issuesMock.UpdateIssueArgs.IssueUpdate.Labels); Assert.Contains(issuesMock.UpdateIssueArgs.IssueUpdate.Labels, label => label == GitHubLabels.CodePlexMigrated); // Assert: Update -- Attachments if (hasAttachments) { Assert.Contains(Resources.Attachments, issuesMock.UpdateIssueArgs.IssueUpdate.Body); } else { Assert.DoesNotContain(Resources.Attachments, issuesMock.UpdateIssueArgs.IssueUpdate.Body); } issuesMock.VerifyIssuesCallCount(methodName: nameof(IIssuesClient.Update), callCount: 2); }
public async Task CreateWorkItemAsync_OnNonNullWorkItemDetailsAndWorkItem_CreatesIssue(bool isIssueClosed, bool hasAttachments) { // Arrange var issuesMock = new GitHubIssueMock(); var ctorArgs = new CtorArgs { Issues = issuesMock.Issues }; GitHubRepoIssueReaderWriter target = CreateTarget(ctorArgs); WorkItemDetails workItemDetails = CreateSampleWorkItemDetails(hasAttachments: hasAttachments, isClosed: isIssueClosed); // Act await target.WriteWorkItemAsync(workItemDetails); // Assert: Owner + Repo Assert.NotNull(issuesMock.CreateIssueArgs.NewIssue); Assert.Equal(ctorArgs.RepoOwner, issuesMock.CreateIssueArgs.Owner); Assert.Equal(ctorArgs.Repo, issuesMock.CreateIssueArgs.Name); // Assert: Title + Body Assert.Equal(workItemDetails.WorkItem.Summary, issuesMock.CreateIssueArgs.NewIssue.Title); Assert.Contains(TextUtilities.GetFormattedWorkItemBody(workItemDetails.WorkItem, workItemDetails.FileAttachments), issuesMock.CreateIssueArgs.NewIssue.Body); // Assert: Labels Assert.Single(issuesMock.CreateIssueArgs.NewIssue.Labels); Assert.Contains(issuesMock.CreateIssueArgs.NewIssue.Labels, label => label == GitHubLabels.CodePlexMigrationInitiated); Assert.Single(issuesMock.UpdateIssueArgs.IssueUpdate.Labels); Assert.Contains(issuesMock.UpdateIssueArgs.IssueUpdate.Labels, label => label == GitHubLabels.CodePlexMigrated); // Assert: Attachments if (hasAttachments) { Assert.Contains(Resources.Attachments, issuesMock.CreateIssueArgs.NewIssue.Body); } else { Assert.DoesNotContain(Resources.Attachments, issuesMock.CreateIssueArgs.NewIssue.Body); } // Assert: Issue state: closed/open Assert.Equal(isIssueClosed ? ItemState.Closed : (ItemState?)null, issuesMock.UpdateIssueArgs.IssueUpdate.State); issuesMock.VerifyIssuesCallCount(methodName: nameof(IIssuesClient.Create), callCount: 1); issuesMock.VerifyIssuesCallCount(methodName: nameof(IIssuesClient.Update), callCount: 1); issuesMock.VerifyCommentCallCount(methodName: nameof(IIssueCommentsClient.Create), callCount: 0); issuesMock.VerifyCommentCallCount(methodName: nameof(IIssueCommentsClient.Delete), callCount: 0); }
public async Task UpdateWorkItemAsync_IfWorkItemHasComments_DropsAndRecreatesComments() { // Arrange int issueCommentCount = 10; Issue issue = CreateSampleIssue(label: "AnyLabel"); IssueComment[] issueComments = Enumerable.Range(0, issueCommentCount).Select(i => CreateSampleComment(issue.Number)).ToArray(); WorkItemDetails workItemDetails = CreateSampleWorkItemDetails(hasComments: true); var issuesMock = new GitHubIssueMock(); issuesMock.SetCommentsForIssue(issue.Number, issueComments); var searchMock = new GitHubSearchInBodyMock(searchResults: new[] { issue }); CtorArgs ctorArgs = new CtorArgs { Search = searchMock.Search, Issues = issuesMock.Issues }; GitHubRepoIssueReaderWriter target = CreateTarget(ctorArgs); // Act await target.UpdateWorkItemAsync(workItemDetails); // Assert: Search searchMock.VerifySearchCallCount(callCount: 1); // Assert: Delete comments Assert.True(issuesMock.DeleteCommentArgs.All(args => args.Owner == ctorArgs.RepoOwner)); Assert.True(issuesMock.DeleteCommentArgs.All(args => args.Name == ctorArgs.Repo)); Assert.Equal(issueComments.Select(c => c.Id), issuesMock.DeleteCommentArgs.Select(args => args.Id)); issuesMock.VerifyCommentCallCount(nameof(IIssueCommentsClient.Delete), callCount: issueCommentCount); // Assert: Create comments Assert.True(issuesMock.CreateCommentArgs.All(args => args.Owner == ctorArgs.RepoOwner)); Assert.True(issuesMock.CreateCommentArgs.All(args => args.Name == ctorArgs.Repo)); Assert.True(issuesMock.CreateCommentArgs.All(args => args.Number == issue.Number)); string[] createdComments = issuesMock.CreateCommentArgs.Select(c => c.NewComment).ToArray(); foreach (WorkItemComment comment in workItemDetails.Comments) { Assert.Contains(createdComments, c => c.Contains(comment.Message)); } issuesMock.VerifyCommentCallCount(nameof(IIssueCommentsClient.Create), callCount: workItemDetails.Comments.Count()); }
public async Task CreateWorkItemAsync_OnWorkItemWithReleaseComponentAndPriority_SetsTextLabels() { // Arrange var issuesMock = new GitHubIssueMock(); var ctorArgs = new CtorArgs { Issues = issuesMock.Issues }; GitHubRepoIssueReaderWriter target = CreateTarget(ctorArgs); WorkItemDetails workItemDetails = CreateSampleWorkItemDetails(hasSpecialProperties: true); // Act await target.WriteWorkItemAsync(workItemDetails); // Assert Assert.Equal(4, issuesMock.UpdateIssueArgs.IssueUpdate.Labels.Count); Assert.Contains(workItemDetails.WorkItem.PlannedForRelease, issuesMock.UpdateIssueArgs.IssueUpdate.Labels); Assert.Contains(workItemDetails.WorkItem.AffectedComponent.DisplayName, issuesMock.UpdateIssueArgs.IssueUpdate.Labels); Assert.Contains(issuesMock.UpdateIssueArgs.IssueUpdate.Labels, label => label.Contains(GitHubLabels.Impact) && label.Contains(workItemDetails.WorkItem.Priority.Name)); Assert.Contains(GitHubLabels.CodePlexMigrated, issuesMock.UpdateIssueArgs.IssueUpdate.Labels); }
public async Task CreateWorkItemAsync_OnWorkItemWithComments_CreatesCommentsOnIssue() { // Arrange var issuesMock = new GitHubIssueMock(); var ctorArgs = new CtorArgs { Issues = issuesMock.Issues }; GitHubRepoIssueReaderWriter target = CreateTarget(ctorArgs); WorkItemDetails workItemDetails = CreateSampleWorkItemDetails(hasComments: true); // Act await target.WriteWorkItemAsync(workItemDetails); // Assert Assert.True(issuesMock.CreateCommentArgs.All(argSet => argSet.Name == ctorArgs.Repo && argSet.Owner == ctorArgs.RepoOwner)); issuesMock.VerifyCommentCallCount(methodName: nameof(IIssueCommentsClient.Create), callCount: workItemDetails.Comments.Count()); foreach (WorkItemComment comment in workItemDetails.Comments) { Assert.Contains(issuesMock.CreateCommentArgs, argSet => argSet.NewComment.Contains(comment.Message)); } }
public async Task Send_IfValidMaxRequestsPerTimeInterval_LimitsSentRequests() { // Arrange IResponse response = new Mock <IResponse>().Object; IRequest request = new Mock <IRequest>().Object; var httpClientMock = new Mock <Octokit.Internal.IHttpClient>(); httpClientMock .Setup(httpClient => httpClient.Send(It.IsAny <IRequest>(), It.IsAny <CancellationToken>())) .ReturnsAsync <IRequest, CancellationToken, Octokit.Internal.IHttpClient, IResponse>( (r, t) => { Task.Delay(TimeSpan.FromMilliseconds(10)).Wait(); return(response); }); var ctorArgs = new CtorArgs { HttpClient = httpClientMock.Object, MaxRequestsPerTimeInterval = 5 }; RateLimitingHttpClientAdapter target = CreateTarget(ctorArgs); DateTimeOffset startTime = DateTimeOffset.UtcNow; // Act var tasks = new List <Task>(); int requestCount = ctorArgs.MaxRequestsPerTimeInterval + 1; for (int i = 0; i < requestCount; ++i) { tasks.Add(Task.Run(() => target.Send(request))); } // Assert await Task.WhenAll(tasks); Assert.True(DateTimeOffset.Now - startTime > ctorArgs.TimeInterval); httpClientMock.Verify(httpClient => httpClient.Send(It.IsAny <IRequest>(), It.IsAny <CancellationToken>()), Times.Exactly(requestCount)); }
public Wheel(IRim rim, ITire tire, CtorArgs args) { Label = args.Label; _rim = rim; _tire = tire; }
private static GitHubRepoIssueReaderWriter CreateTarget(CtorArgs ctorArgs = null) { CtorArgs args = ctorArgs ?? new CtorArgs(); return(new GitHubRepoIssueReaderWriter(args.RepoOwner, args.Repo, args.Issues, args.Search)); }
private static RateLimitingHttpClientAdapter CreateTarget(CtorArgs ctorArgs = null) { CtorArgs args = ctorArgs ?? new CtorArgs(); return(new RateLimitingHttpClientAdapter(args.HttpClient, args.TimeInterval, args.MaxRequestsPerTimeInterval)); }