diff --git a/Team.psd1 b/Team.psd1 index f951b8899..485207de1 100644 --- a/Team.psd1 +++ b/Team.psd1 @@ -13,7 +13,7 @@ RootModule = '' # Version number of this module. - ModuleVersion = '0.1.29' + ModuleVersion = '0.1.30' # Supported PSEditions # CompatiblePSEditions = @() @@ -78,7 +78,9 @@ 'src\queues.psm1', 'src\releaseDefinitions.psm1', 'src\releases.psm1', - 'src\serviceendpoints.psm1') + 'src\serviceendpoints.psm1', + 'src\teams.psm1', + 'src\teammembers.psm1') # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. FunctionsToExport = @('Add-AzureRMServiceEndpoint', @@ -90,6 +92,7 @@ 'Add-ReleaseEnvironment', 'Add-ReleaseDefinition', 'Add-TeamAccount', + 'Add-Team', 'Clear-DefaultProject', 'Get-Approval', 'Get-Build', @@ -102,6 +105,8 @@ 'Get-ReleaseDefinition', 'Get-ServiceEndpoint', 'Get-TeamInfo', + 'Get-Team', + 'Get-TeamMember', 'Remove-Build', 'Remove-BuildDefinition', 'Remove-Project', @@ -109,10 +114,12 @@ 'Remove-ReleaseDefinition', 'Remove-ServiceEndpoint', 'Remove-TeamAccount', + 'Remove-Team', 'Set-Approval', 'Set-DefaultProject', 'Set-ReleaseStatus', 'Update-Project', + 'Update-Team', 'Get-GitRepository', 'Add-GitRepository', 'Remove-GitRepository', diff --git a/src/teammembers.psm1 b/src/teammembers.psm1 new file mode 100644 index 000000000..29deda476 --- /dev/null +++ b/src/teammembers.psm1 @@ -0,0 +1,88 @@ +Set-StrictMode -Version Latest + +# Load common code +$here = Split-Path -Parent $MyInvocation.MyCommand.Path +. "$here\common.ps1" + +function _buildURL { + param( + [parameter(Mandatory = $true)] + [string] $ProjectName, + [parameter(Mandatory = $true)] + [string] $TeamId + ) + + if(-not $env:TEAM_ACCT) { + throw 'You must call Add-TeamAccount before calling any other functions in this module.' + } + + $version = '1.0' + $resource = "/projects/$ProjectName/teams/$TeamId/members" + $instance = $env:TEAM_ACCT + + # Build the url to list the projects + return $instance + '/_apis' + $resource + '?api-version=' + $version +} + +# Apply types to the returned objects so format and type files can +# identify the object and act on it. +function _applyTypes { + param( + [Parameter(Mandatory = $true)] + $item, + [Parameter(Mandatory = $true)] + $team + ) + + # Add the team name as a NoteProperty so we can use it further down the pipeline (it's not returned from the REST call) + $item | Add-Member -MemberType NoteProperty -Name Team -Value $team + $item.PSObject.TypeNames.Insert(0, 'Team.TeamMember') +} + +function Get-TeamMember { + [CmdletBinding()] + param ( + [Parameter()] + [int] $Top, + + [Parameter()] + [int] $Skip, + + [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true)] + [Alias('name')] + [string] $TeamId + ) + + DynamicParam { + _buildProjectNameDynamicParam + } + + process { + # Bind the parameter to a friendly variable + $ProjectName = $PSBoundParameters["ProjectName"] + + + # Build the url to list the builds + $listurl = _buildURL -projectName $ProjectName -teamId $TeamId + + $listurl += _appendQueryString -name "`$top" -value $top + $listurl += _appendQueryString -name "`$skip" -value $skip + + # Call the REST API + if (_useWindowsAuthenticationOnPremise) { + $resp = Invoke-RestMethod -UserAgent (_getUserAgent) -Uri $listurl -UseDefaultCredentials + } + else { + $resp = Invoke-RestMethod -UserAgent (_getUserAgent) -Uri $listurl -Headers @{Authorization = "Basic $env:TEAM_PAT"} + } + + # Apply a Type Name so we can use custom format view and custom type extensions + foreach ($item in $resp.value) { + _applyTypes -item $item -team $TeamId + } + + Write-Output $resp.value + } +} + +Export-ModuleMember -Alias * -Function Get-TeamMember \ No newline at end of file diff --git a/src/teams.psm1 b/src/teams.psm1 new file mode 100644 index 000000000..9a2ddb557 --- /dev/null +++ b/src/teams.psm1 @@ -0,0 +1,222 @@ +Set-StrictMode -Version Latest + +# Load common code +$here = Split-Path -Parent $MyInvocation.MyCommand.Path +. "$here\common.ps1" + +function _buildURL { + param( + [parameter(Mandatory = $true)] + [string] $ProjectName, + [string] $TeamId + ) + + if(-not $env:TEAM_ACCT) { + throw 'You must call Add-TeamAccount before calling any other functions in this module.' + } + + $version = '1.0' + $resource = "/projects/$ProjectName/teams" + $instance = $env:TEAM_ACCT + + if ($TeamId) { + $resource += "/$TeamId" + } + + # Build the url to list the projects + return $instance + '/_apis' + $resource + '?api-version=' + $version +} + +# Apply types to the returned objects so format and type files can +# identify the object and act on it. +function _applyTypes { + param( + [Parameter(Mandatory = $true)] + $item, + [Parameter(Mandatory = $true)] + $ProjectName + ) + + # Add the ProjectName as a NoteProperty so we can use it further down the pipeline (it's not returned from the REST call) + $item | Add-Member -MemberType NoteProperty -Name ProjectName -Value $ProjectName + $item.PSObject.TypeNames.Insert(0, 'Team.Team') +} + +function Get-Team { + [CmdletBinding(DefaultParameterSetName = 'List')] + param ( + [Parameter(ParameterSetName = 'List')] + [int] $Top, + + [Parameter(ParameterSetName = 'List')] + [int] $Skip, + + [Parameter(ParameterSetName = 'ByID')] + [string[]] $TeamId + ) + + DynamicParam { + _buildProjectNameDynamicParam + } + + process { + # Bind the parameter to a friendly variable + $ProjectName = $PSBoundParameters["ProjectName"] + + if($TeamId) { + foreach ($item in $TeamId) { + # Build the url to return the single build + $listurl = _buildURL -projectName $ProjectName -teamId $item + + # Call the REST API + if (_useWindowsAuthenticationOnPremise) { + $resp = Invoke-RestMethod -UserAgent (_getUserAgent) -Uri $listurl -UseDefaultCredentials + } + else { + $resp = Invoke-RestMethod -UserAgent (_getUserAgent) -Uri $listurl -Headers @{Authorization = "Basic $env:TEAM_PAT"} + } + + _applyTypes -item $resp -ProjectName $ProjectName + + Write-Output $resp + } + } else { + # Build the url to list the teams + $listurl = _buildURL -projectName $ProjectName + + $listurl += _appendQueryString -name "`$top" -value $top + $listurl += _appendQueryString -name "`$skip" -value $skip + + # Call the REST API + if (_useWindowsAuthenticationOnPremise) { + $resp = Invoke-RestMethod -UserAgent (_getUserAgent) -Uri $listurl -UseDefaultCredentials + } + else { + $resp = Invoke-RestMethod -UserAgent (_getUserAgent) -Uri $listurl -Headers @{Authorization = "Basic $env:TEAM_PAT"} + } + + # Apply a Type Name so we can use custom format view and custom type extensions + foreach ($item in $resp.value) { + _applyTypes -item $item -ProjectName $ProjectName + } + + Write-Output $resp.value + } + } +} + +function Add-Team { + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [string]$TeamName, + [string]$Description = "" + ) + DynamicParam { + _buildProjectNameDynamicParam + } + + process { + # Bind the parameter to a friendly variable + $ProjectName = $PSBoundParameters["ProjectName"] + + $listurl = _buildURL -ProjectName $ProjectName + $body = '{ "name": "' + $TeamName + '", "description": "' + $Description + '" }' + + # Call the REST API + if (_useWindowsAuthenticationOnPremise) { + $resp = Invoke-RestMethod -UserAgent (_getUserAgent) -Method Post -ContentType "application/json" -Body $body -Uri $listurl -UseDefaultCredentials + } + else { + $resp = Invoke-RestMethod -UserAgent (_getUserAgent) -Method Post -ContentType "application/json" -Body $body -Uri $listurl -Headers @{Authorization = "Basic $env:TEAM_PAT"} + } + + _applyTypes -item $resp -ProjectName $ProjectName + + return $resp + } +} + +function Update-Team { + [CmdletBinding()] + param( + [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $true)] + [Alias('name')] + [string]$TeamToUpdate, + [string]$NewTeamName, + [string]$Description + ) + DynamicParam { + _buildProjectNameDynamicParam + } + + process { + # Bind the parameter to a friendly variable + $ProjectName = $PSBoundParameters["ProjectName"] + + $listurl = _buildURL -ProjectName $ProjectName -TeamId $TeamToUpdate + if(-not $NewTeamName -and -not $Description) { + throw 'You must provide a new team name or description, or both.' + } + + if(-not $NewTeamName) + { + $body = '{"description": "' + $Description + '" }' + } + if(-not $Description) + { + $body = '{ "name": "' + $NewTeamName + '" }' + } + if($NewTeamName -and $Description) + { + $body = '{ "name": "' + $NewTeamName + '", "description": "' + $Description + '" }' + } + + # Call the REST API + if (_useWindowsAuthenticationOnPremise) { + $resp = Invoke-RestMethod -UserAgent (_getUserAgent) -Method Patch -ContentType "application/json" -Body $body -Uri $listurl -UseDefaultCredentials + } + else { + $resp = Invoke-RestMethod -UserAgent (_getUserAgent) -Method Patch -ContentType "application/json" -Body $body -Uri $listurl -Headers @{Authorization = "Basic $env:TEAM_PAT"} + } + + _applyTypes -item $resp -ProjectName $ProjectName + + return $resp + } +} + +function Remove-Team { + [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact="High")] + param( + [Parameter(Mandatory = $True, ValueFromPipelineByPropertyName = $true)] + [Alias('name')] + [string]$TeamId, + + [switch]$Force + ) + DynamicParam { + _buildProjectNameDynamicParam + } + + process { + # Bind the parameter to a friendly variable + $ProjectName = $PSBoundParameters["ProjectName"] + + $listurl = _buildURL -ProjectName $ProjectName -TeamId $TeamId + + if ($Force -or $PSCmdlet.ShouldProcess($TeamId, "Delete team")) { + # Call the REST API + if (_useWindowsAuthenticationOnPremise) { + $resp = Invoke-RestMethod -UserAgent (_getUserAgent) -Method Delete -Uri $listurl -UseDefaultCredentials + } + else { + $resp = Invoke-RestMethod -UserAgent (_getUserAgent) -Method Delete -Uri $listurl -Headers @{Authorization = "Basic $env:TEAM_PAT"} + } + + Write-Output "Deleted team $TeamId" + } + } +} + +Export-ModuleMember -Alias * -Function Get-Team, Add-Team, Update-Team, Remove-Team \ No newline at end of file diff --git a/src/types.ps1xml b/src/types.ps1xml index 263783977..2e1be4650 100644 --- a/src/types.ps1xml +++ b/src/types.ps1xml @@ -1,324 +1,368 @@ - - - - - - Team.Environment - - - PSStandardMembers - - - DefaultDisplayPropertySet - - id - name - status - - - - - - - - - Team.Project - - - PSStandardMembers - - - DefaultDisplayPropertySet - - name - id - description - - - - - - - - - Team.Build - - - name - buildNumber - - - queueName - $this.queue.name - - - queueID - $this.queue.id - - - definitionName - $this.definition.name - - - projectName - $this.project.name - - - repositoryType - $this.repository.type - - - requestedForUser - $this.requestedFor.displayName - - - requestedByUser - $this.requestedBy.displayName - - - lastChangedByUser - $this.lastChangedBy.displayName - - - - - - Team.Release - - - definitionName - $this.releaseDefinition.name - - - definitionId - $this.releaseDefinition.id - - - projectId - $this.projectReference.id - - - requestedForUser - $this.requestedFor.displayName - - - modifiedByUser - $this.modifiedBy.displayName - - - createdByUser - $this.createdBy.displayName - - - PSStandardMembers - - - DefaultDisplayPropertySet - - id - name - status - definitionName - - - - - - - - - Team.Queue - - - poolName - $this.pool.name - - - - - - Team.ServiceEndpoint - - - createdByUser - $this.createdBy.displayName - - - - - - Team.AzureSubscription - - - PSStandardMembers - - - DefaultDisplayPropertySet - - displayName - subscriptionId - subscriptionTenantId - - - - - - - - - Team.BuildDefinition - - - authoredByUser - $this.authoredBy.displayName - - - queueName - $this.queue.name - - - PSStandardMembers - - - DefaultDisplayPropertySet - - id - name - queueName - authoredByUser - - - - - - - - - Team.Pool - - - createdByUser - $this.createdBy.displayName - - - queueName - $this.queue.name - - - PSStandardMembers - - - DefaultDisplayPropertySet - - name - createdByUser - - - - - - - - - Team.ReleaseDefinition - - - createdByUser - $this.createdBy.displayName - - - PSStandardMembers - - - DefaultDisplayPropertySet - - id - name - createdByUser - - - - - - - - - Team.Approval - - - approverName - $this.approver.displayName - - - releaseName - $this.release.name - - - releaseDefinitionName - $this.releaseDefinition.name - - - releaseEnvironmentName - $this.releaseEnvironment.name - - - shortApprovalType - $this.approvalType.Replace('Deploy', '').Replace('p', 'P') - - - PSStandardMembers - - - DefaultDisplayPropertySet - - id - approverName - status - comments - releaseDefinitionName - releaseEnvironmentName - - - - - - - - - Team.GitRepository - - - projectName - $this.project.name - - - PSStandardMembers - - - DefaultDisplayPropertySet - - name - remoteUrl - defaultBranch - projectName - - - - - - + + + + + + Team.Environment + + + PSStandardMembers + + + DefaultDisplayPropertySet + + id + name + status + + + + + + + + + Team.Project + + + PSStandardMembers + + + DefaultDisplayPropertySet + + name + id + description + + + + + + projectname + name + + + + + + Team.Team + + + PSStandardMembers + + + DefaultDisplayPropertySet + + projectname + name + id + description + + + + + + + + + Team.TeamMember + + + PSStandardMembers + + + DefaultDisplayPropertySet + + team + displayName + id + uniqueName + + + + + + + + + Team.Build + + + name + buildNumber + + + queueName + $this.queue.name + + + queueID + $this.queue.id + + + definitionName + $this.definition.name + + + projectName + $this.project.name + + + repositoryType + $this.repository.type + + + requestedForUser + $this.requestedFor.displayName + + + requestedByUser + $this.requestedBy.displayName + + + lastChangedByUser + $this.lastChangedBy.displayName + + + + + + Team.Release + + + definitionName + $this.releaseDefinition.name + + + definitionId + $this.releaseDefinition.id + + + projectId + $this.projectReference.id + + + requestedForUser + $this.requestedFor.displayName + + + modifiedByUser + $this.modifiedBy.displayName + + + createdByUser + $this.createdBy.displayName + + + PSStandardMembers + + + DefaultDisplayPropertySet + + id + name + status + definitionName + + + + + + + + + Team.Queue + + + poolName + $this.pool.name + + + + + + Team.ServiceEndpoint + + + createdByUser + $this.createdBy.displayName + + + + + + Team.AzureSubscription + + + PSStandardMembers + + + DefaultDisplayPropertySet + + displayName + subscriptionId + subscriptionTenantId + + + + + + + + + Team.BuildDefinition + + + authoredByUser + $this.authoredBy.displayName + + + queueName + $this.queue.name + + + PSStandardMembers + + + DefaultDisplayPropertySet + + id + name + queueName + authoredByUser + + + + + + + + + Team.Pool + + + createdByUser + $this.createdBy.displayName + + + queueName + $this.queue.name + + + PSStandardMembers + + + DefaultDisplayPropertySet + + name + createdByUser + + + + + + + + + Team.ReleaseDefinition + + + createdByUser + $this.createdBy.displayName + + + PSStandardMembers + + + DefaultDisplayPropertySet + + id + name + createdByUser + + + + + + + + + Team.Approval + + + approverName + $this.approver.displayName + + + releaseName + $this.release.name + + + releaseDefinitionName + $this.releaseDefinition.name + + + releaseEnvironmentName + $this.releaseEnvironment.name + + + shortApprovalType + $this.approvalType.Replace('Deploy', '').Replace('p', 'P') + + + PSStandardMembers + + + DefaultDisplayPropertySet + + id + approverName + status + comments + releaseDefinitionName + releaseEnvironmentName + + + + + + + + + Team.GitRepository + + + projectName + $this.project.name + + + PSStandardMembers + + + DefaultDisplayPropertySet + + name + remoteUrl + defaultBranch + projectName + + + + + + \ No newline at end of file diff --git a/test/teammembers.Tests.ps1 b/test/teammembers.Tests.ps1 new file mode 100644 index 000000000..78492d47d --- /dev/null +++ b/test/teammembers.Tests.ps1 @@ -0,0 +1,75 @@ +Set-StrictMode -Version Latest + +Get-Module team | Remove-Module -Force +Import-Module $PSScriptRoot\..\src\teammembers.psm1 -Force +Import-Module $PSScriptRoot\..\src\teams.psm1 -Force + +InModuleScope teammembers { + $env:TEAM_ACCT = 'https://test.visualstudio.com' + + Describe "TeamMembers" { + . "$PSScriptRoot\mockProjectNameDynamicParam.ps1" + + Context 'Get-Teammember for specific project and team' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should return teammembers' { + Get-Teammember -ProjectName TestProject -TeamId TestTeam + # Make sure it was called with the correct URI + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/TestProject/teams/TestTeam/members?api-version=1.0' + } + } + } + + Context 'Get-Teammember for specific project and team, with top' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should return teammembers' { + Get-Teammember -ProjectName TestProject -TeamId TestTeam -Top 10 + # Make sure it was called with the correct URI + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/TestProject/teams/TestTeam/members?api-version=1.0&$top=10' + } + } + } + + Context 'Get-Teammember for specific project and team, with skip' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should return teammembers' { + Get-Teammember -ProjectName TestProject -TeamId TestTeam -Skip 5 + # Make sure it was called with the correct URI + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/TestProject/teams/TestTeam/members?api-version=1.0&$skip=5' + } + } + } + + Context 'Get-Teammember for specific project and team, with top and skip' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should return teammembers' { + Get-Teammember -ProjectName TestProject -TeamId TestTeam -Top 10 -Skip 5 + # Make sure it was called with the correct URI + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/TestProject/teams/TestTeam/members?api-version=1.0&$top=10&$skip=5' + } + } + } + + Context 'Get-Teammember for specific team, fed through pipeline' { + Mock Get-Team { return New-Object -TypeName PSObject -Prop @{projectname="TestProject"; name="TestTeam"} } + Mock Invoke-RestMethod { return @{value='teammembers'}} + + It 'Should return teammembers' { + Get-Team -ProjectName TestProject -TeamId "TestTeam" | Get-TeamMember + + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/TestProject/teams/TestTeam/members?api-version=1.0' + } + } + } + } + +} \ No newline at end of file diff --git a/test/teams.Tests.ps1 b/test/teams.Tests.ps1 new file mode 100644 index 000000000..9944893fe --- /dev/null +++ b/test/teams.Tests.ps1 @@ -0,0 +1,202 @@ +Set-StrictMode -Version Latest + +Get-Module team | Remove-Module -Force +Import-Module $PSScriptRoot\..\src\teams.psm1 -Force + +InModuleScope teams { + $env:TEAM_ACCT = 'https://test.visualstudio.com' + + Describe "Teams" { + . "$PSScriptRoot\mockProjectNameDynamicParam.ps1" + + Context 'Get-Team with project name' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should return teams' { + Get-Team -ProjectName Test + + # Make sure it was called with the correct URI + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/Test/teams?api-version=1.0' + } + } + } + + Context 'Get-Team with project name, with top' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should return teams' { + Get-Team -ProjectName Test -Top 10 + + # Make sure it was called with the correct URI + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/Test/teams?api-version=1.0&$top=10' + } + } + } + + Context 'Get-Team with project name, with skip' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should return teams' { + Get-Team -ProjectName Test -Skip 10 + + # Make sure it was called with the correct URI + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/Test/teams?api-version=1.0&$skip=10' + } + } + } + + Context 'Get-Team with project name, with top and skip' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should return teams' { + Get-Team -ProjectName Test -Top 10 -Skip 5 + + # Make sure it was called with the correct URI + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/Test/teams?api-version=1.0&$top=10&$skip=5' + } + } + } + + Context 'Get-Team with specific project and specific team' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should return teams' { + Get-Team -ProjectName Test -TeamId TestTeam + + # Make sure it was called with the correct URI + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/Test/teams/TestTeam?api-version=1.0' + } + } + } + + Context 'Add-Team with team name only' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should create a team' { + Add-Team -ProjectName Test -TeamName "TestTeam" + + $expectedBody = '{ "name": "TestTeam", "description": "" }' + + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/Test/teams?api-version=1.0' -and + $Method -eq "Post" -and + $Body -eq $expectedBody + } + } + } + + Context 'Add-Team with team name and description' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should create a team' { + Add-Team -ProjectName Test -TeamName "TestTeam" -Description "Test Description" + + $expectedBody = '{ "name": "TestTeam", "description": "Test Description" }' + + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/Test/teams?api-version=1.0' -and + $Method -eq "Post" -and + $Body -eq $expectedBody + } + } + } + + Context 'Update-Team with new team name' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should update the team' { + Update-Team -ProjectName Test -TeamToUpdate "OldTeamName" -NewTeamName "NewTeamName" + + $expectedBody = '{ "name": "NewTeamName" }' + + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/Test/teams/OldTeamName?api-version=1.0' -and + $Method -eq "Patch" -and + $Body -eq $expectedBody + } + } + } + + Context 'Update-Team with new description' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should update the team' { + Update-Team -ProjectName Test -TeamToUpdate "OldTeamName" -Description "New Description" + + $expectedBody = '{"description": "New Description" }' + + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/Test/teams/OldTeamName?api-version=1.0' -and + $Method -eq "Patch" -and + $Body -eq $expectedBody + } + } + } + + Context 'Update-Team with new team name and description' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should update the team' { + Update-Team -ProjectName Test -TeamToUpdate "OldTeamName" -NewTeamName "NewTeamName" -Description "New Description" + + $expectedBody = '{ "name": "NewTeamName", "description": "New Description" }' + + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/Test/teams/OldTeamName?api-version=1.0' -and + $Method -eq "Patch" -and + $Body -eq $expectedBody + } + } + } + + Context 'Update-Team, fed through pipeline' { + Mock Get-Team { return New-Object -TypeName PSObject -Prop @{projectname="TestProject"; name="OldTeamName"} } + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should update the team' { + Get-Team -ProjectName TestProject -TeamId "OldTeamName" | Update-Team -NewTeamName "NewTeamName" -Description "New Description" + + $expectedBody = '{ "name": "NewTeamName", "description": "New Description" }' + + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/TestProject/teams/OldTeamName?api-version=1.0' -and + $Method -eq "Patch" -and + $Body -eq $expectedBody + } + } + } + + Context 'Remove-Team' { + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should remove the team' { + Remove-Team -ProjectName Test -TeamId "TestTeam" -Force + + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/Test/teams/TestTeam?api-version=1.0' -and + $Method -eq "Delete" + } + } + } + + Context 'Remove-Team, fed through pipeline' { + Mock Get-Team { return New-Object -TypeName PSObject -Prop @{projectname="TestProject"; name="TestTeam"} } + Mock Invoke-RestMethod { return @{value='teams'}} + + It 'Should remove the team' { + Get-Team -ProjectName TestProject -TeamId "TestTeam" | Remove-Team -Force + + Assert-MockCalled Invoke-RestMethod -Exactly 1 -ParameterFilter { + $Uri -eq 'https://test.visualstudio.com/_apis/projects/TestProject/teams/TestTeam?api-version=1.0' -and + $Method -eq "Delete" + } + } + } + } + +} \ No newline at end of file