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 GetMigratedWorkItems_IfNoMigratedWorkItems_ReturnsEmptyList()
        {
            // Arrange
            var searchMock = new GitHubSearchByLabelMock();
            GitHubRepoIssueReaderWriter target = CreateTarget(new CtorArgs {
                Search = searchMock.Search
            });

            // Act
            IReadOnlyList <MigratedWorkItem> migratedWorkItems = await target.GetMigratedWorkItemsAsync();

            Assert.Equal(0, migratedWorkItems.Count);
            searchMock.VerifySearchCallCount(callCount: 2);
        }
        public async Task GetMigratedWorkItems_OnInvalidWorkItemId_Throws(string issueLabel, string workItemStringValue)
        {
            // Arrange
            var searchMock =
                new GitHubSearchByLabelMock()
                .SetSearchResults(
                    issueLabel, new[] { CreateSampleIssue(issueLabel, body: string.Format(TextUtilities.CodePlexWorkItemFormat, workItemStringValue)) });

            // Act
            GitHubRepoIssueReaderWriter target = CreateTarget(new CtorArgs {
                Search = searchMock.Search
            });

            // Assert
            await Assert.ThrowsAsync <WorkItemIdentificationException>(() => target.GetMigratedWorkItemsAsync());
        }
        public async Task GetMigratedWorkItems_IfOneWorkItemExists_ReturnsWorkItem(string issueLabel, string expectedMigrationState)
        {
            // Arrange
            var searchMock =
                new GitHubSearchByLabelMock()
                .SetSearchResults(issueLabel, new[] { CreateSampleIssue(issueLabel) });

            GitHubRepoIssueReaderWriter target = CreateTarget(new CtorArgs {
                Search = searchMock.Search
            });

            // Act
            IReadOnlyList <MigratedWorkItem> migratedWorkItems = await target.GetMigratedWorkItemsAsync();

            // Assert
            Assert.Single(migratedWorkItems);
            Assert.True(migratedWorkItems.All(item => item.MigrationState == (MigrationState)Enum.Parse(typeof(MigrationState), expectedMigrationState)));
            searchMock.VerifySearchCallCount(callCount: 2);
        }