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));
            }
        }
Exemple #10
0
        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));
        }
Exemple #11
0
 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));
        }
Exemple #13
0
        private static RateLimitingHttpClientAdapter CreateTarget(CtorArgs ctorArgs = null)
        {
            CtorArgs args = ctorArgs ?? new CtorArgs();

            return(new RateLimitingHttpClientAdapter(args.HttpClient, args.TimeInterval, args.MaxRequestsPerTimeInterval));
        }