Tests/GitHubAnalytics.tests.ps1
# Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. <# .Synopsis Tests for GitHubAnalytics.ps1 module #> [String] $root = Split-Path -Parent (Split-Path -Parent $Script:MyInvocation.MyCommand.Path) . (Join-Path -Path $root -ChildPath 'Tests\Config\Settings.ps1') Import-Module -Name $root -Force function Initialize-AppVeyor { <# .SYNOPSIS Configures the tests to run with the authentication information stored in AppVeyor (if that information exists in the environment). .DESCRIPTION Configures the tests to run with the authentication information stored in AppVeyor (if that information exists in the environment). The Git repo for this module can be found here: http://aka.ms/PowerShellForGitHub .NOTES Internal-only helper method. The only reason this exists is so that we can leverage CodeAnalysis.SuppressMessageAttribute, which can only be applied to functions. We call this immediately after the declaration so that AppVeyor initialization can heppen (if applicable). #> [CmdletBinding()] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "", Justification="Needed to configure with the stored, encrypted string value in AppVeyor.")] param() if ($env:AppVeyor) { $secureString = $env:avAccessToken | ConvertTo-SecureString -AsPlainText -Force $cred = New-Object System.Management.Automation.PSCredential "<username is ignored>", $secureString Set-GitHubAuthentication -Credential $cred $script:ownerName = $env:avOwnerName $script:organizationName = $env:avOrganizationName $message = @( 'This run is executed in the AppVeyor environment.', 'The GitHub Api Token won''t be decrypted in PR runs causing some tests to fail.', '403 errors possible due to GitHub hourly limit for unauthenticated queries.', 'Use Set-GitHubAuthentication manually. modify the values in Tests\Config\Settings.ps1,', 'and run tests on your machine first.') Write-Warning -Message ($message -join [Environment]::NewLine) } } Initialize-AppVeyor $script:accessTokenConfigured = Test-GitHubAuthenticationConfigured if (-not $script:accessTokenConfigured) { $message = @( 'GitHub API Token not defined, some of the tests will be skipped.', '403 errors possible due to GitHub hourly limit for unauthenticated queries.') Write-Warning -Message ($message -join [Environment]::NewLine) } # Backup the user's configuration before we begin, and ensure we're at a pure state before running # the tests. We'll restore it at the end. $configFile = New-TemporaryFile try { Backup-GitHubConfiguration -Path $configFile Reset-GitHubConfiguration Set-GitHubConfiguration -DisableTelemetry # We don't want UT's to impact telemetry Set-GitHubConfiguration -LogRequestBody # Make it easier to debug UT failures Describe 'Obtaining issues for repository' { $repo = New-GitHubRepository -RepositoryName ([Guid]::NewGuid().Guid) -AutoInit Context 'When initially created, there are no issues' { $issues = Get-GitHubIssue -Uri $repo.svn_url It 'Should return expected number of issues' { @($issues).Count | Should be 0 } } Context 'When there are issues present' { $newIssues = @() for ($i = 0; $i -lt 4; $i++) { $newIssues += New-GitHubIssue -OwnerName $script:ownerName -RepositoryName $repo.name -Title ([guid]::NewGuid().Guid) Start-Sleep -Seconds 5 } $newIssues[0] = Update-GitHubIssue -OwnerName $script:ownerName -RepositoryName $repo.name -Issue $newIssues[0].number -State Closed $newIssues[-1] = Update-GitHubIssue -OwnerName $script:ownerName -RepositoryName $repo.name -Issue $newIssues[-1].number -State Closed $issues = Get-GitHubIssue -Uri $repo.svn_url It 'Should return only open issues' { @($issues).Count | Should be 2 } $issues = Get-GitHubIssue -Uri $repo.svn_url -State All It 'Should return all issues' { @($issues).Count | Should be 4 } $createdOnOrAfterDate = Get-Date -Date $newIssues[0].created_at $createdOnOrBeforeDate = Get-Date -Date $newIssues[2].created_at $issues = (Get-GitHubIssue -Uri $repo.svn_url) | Where-Object { ($_.created_at -ge $createdOnOrAfterDate) -and ($_.created_at -le $createdOnOrBeforeDate) } It 'Smart object date conversion works for comparing dates' { @($issues).Count | Should be 2 } $createdDate = Get-Date -Date $newIssues[1].created_at $issues = Get-GitHubIssue -Uri $repo.svn_url -State All | Where-Object { ($_.created_at -ge $createdDate) -and ($_.state -eq 'closed') } It 'Able to filter based on date and state' { @($issues).Count | Should be 1 } } $null = Remove-GitHubRepository -Uri ($repo.svn_url) } Describe 'Obtaining repository with biggest number of issues' { $repo1 = New-GitHubRepository -RepositoryName ([Guid]::NewGuid().Guid) -AutoInit $repo2 = New-GitHubRepository -RepositoryName ([Guid]::NewGuid().Guid) -AutoInit Context 'When no addional conditions specified' { for ($i = 0; $i -lt 3; $i++) { $null = New-GitHubIssue -OwnerName $script:ownerName -RepositoryName $repo1.name -Title ([guid]::NewGuid().Guid) } $repos = @(($repo1.svn_url), ($repo2.svn_url)) $issueCounts = @() $repos | ForEach-Object { $issueCounts = $issueCounts + ([PSCustomObject]@{ 'Uri' = $_; 'Count' = (Get-GitHubIssue -Uri $_).Count }) } $issueCounts = $issueCounts | Sort-Object -Property Count -Descending It 'Should return expected number of issues for each repository' { @($issueCounts[0].Count) | Should be 3 @($issueCounts[1].Count) | Should be 0 } It 'Should return expected repository names' { @($issueCounts[0].Uri) | Should be ($repo1.svn_url) @($issueCounts[1].Uri) | Should be ($repo2.svn_url) } } $null = Remove-GitHubRepository -Uri ($repo1.svn_url) $null = Remove-GitHubRepository -Uri ($repo2.svn_url) } # TODO: Re-enable these tests once the module has sufficient support getting the repository into the # required state for testing, and to recover back to the original state at the conclusion of the test. # Describe 'Obtaining pull requests for repository' { # Context 'When no addional conditions specified' { # $pullRequests = Get-GitHubPullRequest -Uri $script:repositoryUrl # It 'Should return expected number of PRs' { # @($pullRequests).Count | Should be 2 # } # } # Context 'When state and time range specified' { # $mergedStartDate = Get-Date -Date '2016-04-10' # $mergedEndDate = Get-Date -Date '2016-05-07' # $pullRequests = Get-GitHubPullRequest -Uri $script:repositoryUrl -State Closed | # Where-Object { ($_.merged_at -ge $mergedStartDate) -and ($_.merged_at -le $mergedEndDate) } # It 'Should return expected number of PRs' { # @($pullRequests).Count | Should be 3 # } # } # } # Describe 'Obtaining repository with biggest number of pull requests' { # Context 'When no addional conditions specified' { # @($script:repositoryUrl, $script:repositoryUrl2) | # ForEach-Object { # $pullRequestCounts += ([PSCustomObject]@{ # 'Uri' = $_; # 'Count' = (Get-GitHubPullRequest -Uri $_).Count }) } # $pullRequestCounts = $pullRequestCounts | Sort-Object -Property Count -Descending # It 'Should return expected number of pull requests for each repository' { # @($pullRequestCounts[0].Count) | Should be 2 # @($pullRequestCounts[1].Count) | Should be 0 # } # It 'Should return expected repository names' { # @($pullRequestCounts[0].Uri) | Should be $script:repositoryUrl # @($pullRequestCounts[1].Uri) | Should be $script:repositoryUrl2 # } # } # Context 'When state and time range specified' { # $mergedDate = Get-Date -Date '2015-04-20' # $repos = @($script:repositoryUrl, $script:repositoryUrl2) # $pullRequestCounts = @() # $pullRequestSearchParams = @{ # 'State' = 'closed' # } # $repos | # ForEach-Object { # $pullRequestCounts += ([PSCustomObject]@{ # 'Uri' = $_; # 'Count' = ( # (Get-GitHubPullRequest -Uri $_ @pullRequestSearchParams) | # Where-Object { $_.merged_at -ge $mergedDate } # ).Count # }) } # $pullRequestCounts = $pullRequestCounts | Sort-Object -Property Count -Descending # $pullRequests = Get-GitHubTopPullRequestRepository -Uri @($script:repositoryUrl, $script:repositoryUrl2) -State Closed -MergedOnOrAfter # It 'Should return expected number of pull requests for each repository' { # @($pullRequests[0].Count) | Should be 3 # @($pullRequests[1].Count) | Should be 0 # } # It 'Should return expected repository names' { # @($pullRequests[0].Uri) | Should be $script:repositoryUrl # @($pullRequests[1].Uri) | Should be $script:repositoryUrl2 # } # } # } if ($script:accessTokenConfigured) { Describe 'Obtaining collaborators for repository' { $repositoryName = [guid]::NewGuid().Guid $null = New-GitHubRepository -RepositoryName $repositoryName -AutoInit $repositoryUrl = "https://github.com/$script:ownerName/$repositoryName" $collaborators = Get-GitHubRepositoryCollaborator -Uri $repositoryUrl It 'Should return expected number of collaborators' { @($collaborators).Count | Should be 1 } $null = Remove-GitHubRepository -OwnerName $script:ownerName -RepositoryName $repositoryName } } Describe 'Obtaining contributors for repository' { $repositoryName = [guid]::NewGuid().Guid $null = New-GitHubRepository -RepositoryName $repositoryName -AutoInit $repositoryUrl = "https://github.com/$script:ownerName/$repositoryName" $contributors = Get-GitHubRepositoryContributor -Uri $repositoryUrl -IncludeStatistics It 'Should return expected number of contributors' { @($contributors).Count | Should be 1 } $null = Remove-GitHubRepository -OwnerName $script:ownerName -RepositoryName $repositoryName } if ($script:accessTokenConfigured) { # TODO: Re-enable these tests once the module has sufficient support getting the Organization # and repository into the required state for testing, and to recover back to the original state # at the conclusion of the test. # Describe 'Obtaining organization members' { # $members = Get-GitHubOrganizationMember -OrganizationName $script:organizationName # It 'Should return expected number of organization members' { # @($members).Count | Should be 1 # } # } # Describe 'Obtaining organization teams' { # $teams = Get-GitHubTeam -OrganizationName $script:organizationName # It 'Should return expected number of organization teams' { # @($teams).Count | Should be 2 # } # } # Describe 'Obtaining organization team members' { # $members = Get-GitHubTeamMember -OrganizationName $script:organizationName -TeamName $script:organizationTeamName # It 'Should return expected number of organization team members' { # @($members).Count | Should be 1 # } # } } Describe 'Getting repositories from organization' { $original = Get-GitHubRepository -OrganizationName $script:organizationName $repositoryName = [guid]::NewGuid().Guid $null = New-GitHubRepository -RepositoryName $repositoryName -OrganizationName $script:organizationName $current = Get-GitHubRepository -OrganizationName $script:organizationName It 'Should return expected number of organization repositories' { (@($current).Count - @($original).Count) | Should be 1 } $null = Remove-GitHubRepository -OwnerName $script:organizationName -RepositoryName $repositoryName } Describe 'Getting unique contributors from contributors array' { $repositoryName = [guid]::NewGuid().Guid $null = New-GitHubRepository -RepositoryName $repositoryName -AutoInit $contributors = Get-GitHubRepositoryContributor -OwnerName $script:ownerName -RepositoryName $repositoryName -IncludeStatistics $uniqueContributors = $contributors | Select-Object -ExpandProperty author | Select-Object -ExpandProperty login -Unique Sort-Object It 'Should return expected number of unique contributors' { @($uniqueContributors).Count | Should be 1 } $null = Remove-GitHubRepository -OwnerName $script:ownerName -RepositoryName $repositoryName } Describe 'Getting repository name from url' { $repositoryName = [guid]::NewGuid().Guid $url = "https://github.com/$script:ownerName/$repositoryName" $name = Split-GitHubUri -Uri $url -RepositoryName It 'Should return expected repository name' { $name | Should be $repositoryName } } Describe 'Getting repository owner from url' { $repositoryName = [guid]::NewGuid().Guid $url = "https://github.com/$script:ownerName/$repositoryName" $owner = Split-GitHubUri -Uri $url -OwnerName It 'Should return expected repository owner' { $owner | Should be $script:ownerName } } Describe 'Getting branches for repository' { $repositoryName = [guid]::NewGuid().Guid $null = New-GitHubRepository -RepositoryName $repositoryName -AutoInit $branches = Get-GitHubRepositoryBranch -OwnerName $script:ownerName -RepositoryName $repositoryName It 'Should return expected number of repository branches' { @($branches).Count | Should be 1 } It 'Should return the name of the branches' { @($branches[0].name) | Should be "master" } $null = Remove-GitHubRepository -OwnerName $script:ownerName -RepositoryName $repositoryName } } finally { # Restore the user's configuration to its pre-test state Restore-GitHubConfiguration -Path $configFile } |