Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added GitHub Codespaces and DevContainerSupport (Non Functional Change)
- Added function `Update-FabricCapacity`
- Added Error Detailed Info in `Test-FabricApiResponse` (Debug mode) when `response.error` exists
- Enhanced Pester unit tests with coverage for many public functions including:
- Domain workspace assignment functions (`Add-FabricDomainWorkspaceAssignmentByCapacity`, `Add-FabricDomainWorkspaceAssignmentById`, `Add-FabricDomainWorkspaceAssignmentByPrincipal`, `Add-FabricDomainWorkspaceRoleAssignment`)
- Workspace functions (`Add-FabricWorkspaceCapacityAssignment`, `Add-FabricWorkspaceIdentity`, `Add-FabricWorkspaceRoleAssignment`, `Add-FabricWorkspaceToStage`, `Update-FabricWorkspace`, `Update-FabricWorkspaceRoleAssignment`)
- Utility functions (`Convert-FromBase64`, `Convert-ToBase64`, `Connect-FabricAccount`, `Export-FabricItem`)
- Update functions for various Fabric items (Notebooks, Reports, Semantic Models, Warehouses, ML models, etc.)
- Tests now include scenarios for successful API calls, long-running operations, error handling, and exception handling
- Increased code coverage threshold from 0.1% to 50%

### Changed

Expand Down
2 changes: 1 addition & 1 deletion build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ Pester:
# - FunctionalQuality
# - TestQuality
Tag:
CodeCoverageThreshold: 0.10 # 85 # Set to 0 to bypass
CodeCoverageThreshold: 50 # 85 # Set to 0 to bypass
#CodeCoverageOutputFile: JaCoCo_$OsShortName.xml
#CodeCoverageOutputFileEncoding: ascii
# Use this if code coverage should be merged from several pipeline test jobs.
Expand Down
2 changes: 1 addition & 1 deletion source/Public/Domain/Get-FabricDomainWorkspace.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Author: Tiago Balabuch

} catch {
# Step 7: Capture and log error details
$errorDetails = Get-ErrorResponse($_.Exception)
$errorDetails = $_.Exception.Message
Write-Message -Message "Failed to retrieve domain workspaces. Error: $errorDetails" -Level Error
}
}
8 changes: 5 additions & 3 deletions source/Public/Item/Export-FabricItem.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,13 @@ https://github.com/microsoft/Analysis-Services/tree/master/pbidevmode/fabricps-p
param
(
[string]$path = '.\pbipOutput',
[guid]$WorkspaceId = '',
[Parameter(Mandatory = $false)]
[guid]$WorkspaceId,
[scriptblock]$filter = { $_.type -in @("Report", "SemanticModel", "Notebook", "SparkJobDefinitionV1") },
[guid]$itemID = $null
[Parameter(Mandatory = $false)]
[guid]$itemID
)
if (-not $itemID) {
if ($PSBoundParameters.ContainsKey('itemID')) {
# Invoke the Fabric API to get the specific item in the workspace

$item = Invoke-FabricRestMethod -Uri "workspaces/$workspaceId/items/$itemID/getDefinition" -Method POST
Expand Down
243 changes: 207 additions & 36 deletions tests/Unit/Add-FabricDomainWorkspaceAssignmentByCapacity.Tests.ps1
Original file line number Diff line number Diff line change
@@ -1,46 +1,217 @@
#Requires -Module @{ ModuleName="Pester"; ModuleVersion="5.0"}
param(
$ModuleName = "FabricTools",
$expectedParams = @(
"DomainId"
"CapacitiesIds"
"Verbose"
"Debug"
"ErrorAction"
"WarningAction"
"InformationAction"
"ProgressAction"
"ErrorVariable"
"WarningVariable"
"InformationVariable"
"OutVariable"
"OutBuffer"
"PipelineVariable"

)
)

Describe "Add-FabricDomainWorkspaceAssignmentByCapacity" -Tag "UnitTests" {

BeforeDiscovery {
$command = Get-Command -Name Add-FabricDomainWorkspaceAssignmentByCapacity
$expected = $expectedParams
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '')]
param ()

BeforeAll {
$script:moduleName = 'FabricTools'

# If the module is not found, run the build task 'noop'.
if (-not (Get-Module -Name $script:moduleName -ListAvailable)) {
# Redirect all streams to $null, except the error stream (stream 2)
& "$PSScriptRoot/../../build.ps1" -Tasks 'noop' 3>&1 4>&1 5>&1 6>&1 > $null
}

# Re-import the module using force to get any code changes between runs.
Import-Module -Name $script:moduleName -Force -ErrorAction 'Stop'

$PSDefaultParameterValues['InModuleScope:ModuleName'] = $script:moduleName
$PSDefaultParameterValues['Mock:ModuleName'] = $script:moduleName
$PSDefaultParameterValues['Should:ModuleName'] = $script:moduleName
}

AfterAll {
$PSDefaultParameterValues.Remove('InModuleScope:ModuleName')
$PSDefaultParameterValues.Remove('Mock:ModuleName')
$PSDefaultParameterValues.Remove('Should:ModuleName')

# Unload the module being tested so that it doesn't impact any other tests.
Get-Module -Name $script:moduleName -All | Remove-Module -Force
}

Describe 'Add-FabricDomainWorkspaceAssignmentByCapacity' -Tag 'Public' {
It 'Should have the correct parameters in parameter set <MockParameterSetName>' -ForEach @(
@{
MockParameterSetName = '__AllParameterSets'
MockExpectedParameters = '[-DomainId] <guid> [-CapacitiesIds] <guid[]> [<CommonParameters>]'
}
) {
$result = (Get-Command -Name 'Add-FabricDomainWorkspaceAssignmentByCapacity').ParameterSets |
Where-Object -FilterScript {
$_.Name -eq $MockParameterSetName
} |
Select-Object -Property @(
@{
Name = 'ParameterSetName'
Expression = { $_.Name }
},
@{
Name = 'ParameterListAsString'
Expression = { $_.ToString() }
}
)

$result.ParameterSetName | Should -Be $MockParameterSetName
$result.ParameterListAsString | Should -Be $MockExpectedParameters
}

Context 'When assigning workspaces by capacity successfully (201)' {
BeforeAll {
Mock -CommandName Confirm-TokenState -MockWith { }
Mock -CommandName Write-Message -MockWith { }
Mock -CommandName Invoke-FabricRestMethod -MockWith {
InModuleScope -ModuleName 'FabricTools' {
$script:statusCode = 201
}
return [pscustomobject]@{
status = 'Succeeded'
}
}
}

It 'Should call Invoke-FabricRestMethod with the correct parameters' {
$mockDomainId = [guid]::NewGuid()
$mockCapacityIds = @([guid]::NewGuid(), [guid]::NewGuid())

Add-FabricDomainWorkspaceAssignmentByCapacity -DomainId $mockDomainId -CapacitiesIds $mockCapacityIds

Should -Invoke -CommandName Invoke-FabricRestMethod -Times 1 -ParameterFilter {
$Uri -like "*admin/domains/*/assignWorkspacesByCapacities" -and
$Method -eq 'Post'
}
}

It 'Should return the response on success' {
$mockDomainId = [guid]::NewGuid()
$mockCapacityIds = @([guid]::NewGuid())

$result = Add-FabricDomainWorkspaceAssignmentByCapacity -DomainId $mockDomainId -CapacitiesIds $mockCapacityIds

$result.status | Should -Be 'Succeeded'
}
}

Context 'When assigning workspaces by capacity is in progress (202)' {
BeforeAll {
Mock -CommandName Confirm-TokenState -MockWith { }
Mock -CommandName Write-Message -MockWith { }
Mock -CommandName Invoke-FabricRestMethod -MockWith {
InModuleScope -ModuleName 'FabricTools' {
$script:statusCode = 202
$script:responseHeader = @{
'x-ms-operation-id' = 'op-12345'
'Location' = 'https://api.fabric.microsoft.com/v1/operations/op-12345'
'Retry-After' = '30'
}
}
return [pscustomobject]@{}
}
Mock -CommandName Get-FabricLongRunningOperation -MockWith {
return [pscustomobject]@{
status = 'Succeeded'
operationId = 'op-12345'
}
}
}

It 'Should call Get-FabricLongRunningOperation when status is 202' {
$mockDomainId = [guid]::NewGuid()
$mockCapacityIds = @([guid]::NewGuid())

Add-FabricDomainWorkspaceAssignmentByCapacity -DomainId $mockDomainId -CapacitiesIds $mockCapacityIds

Should -Invoke -CommandName Get-FabricLongRunningOperation -Times 1
}

It 'Should return the operation status when long running operation succeeds' {
$mockDomainId = [guid]::NewGuid()
$mockCapacityIds = @([guid]::NewGuid())

$result = Add-FabricDomainWorkspaceAssignmentByCapacity -DomainId $mockDomainId -CapacitiesIds $mockCapacityIds

$result.status | Should -Be 'Succeeded'
}
}

Context 'When long running operation fails' {
BeforeAll {
Mock -CommandName Confirm-TokenState -MockWith { }
Mock -CommandName Write-Message -MockWith { }
Mock -CommandName Invoke-FabricRestMethod -MockWith {
InModuleScope -ModuleName 'FabricTools' {
$script:statusCode = 202
$script:responseHeader = @{
'x-ms-operation-id' = 'op-failed'
'Location' = 'https://api.fabric.microsoft.com/v1/operations/op-failed'
'Retry-After' = '30'
}
}
return [pscustomobject]@{}
}
Mock -CommandName Get-FabricLongRunningOperation -MockWith {
return [pscustomobject]@{
status = 'Failed'
operationId = 'op-failed'
error = @{
message = 'Operation failed'
}
}
}
}

It 'Should return the failed operation status' {
$mockDomainId = [guid]::NewGuid()
$mockCapacityIds = @([guid]::NewGuid())

$result = Add-FabricDomainWorkspaceAssignmentByCapacity -DomainId $mockDomainId -CapacitiesIds $mockCapacityIds

$result.status | Should -Be 'Failed'
}
}

Context "Parameter validation" {
Context 'When an unexpected status code is returned' {
BeforeAll {
$command = Get-Command -Name Add-FabricDomainWorkspaceAssignmentByCapacity
$expected = $expectedParams
Mock -CommandName Confirm-TokenState -MockWith { }
Mock -CommandName Write-Message -MockWith { }
Mock -CommandName Invoke-FabricRestMethod -MockWith {
InModuleScope -ModuleName 'FabricTools' {
$script:statusCode = 400
}
return [pscustomobject]@{
message = 'Bad Request'
errorCode = 'InvalidRequest'
}
}
}

It "Has parameter: <_>" -ForEach $expected {
$command | Should -HaveParameter $PSItem
It 'Should write an error message for unexpected status codes' {
$mockDomainId = [guid]::NewGuid()
$mockCapacityIds = @([guid]::NewGuid())

Add-FabricDomainWorkspaceAssignmentByCapacity -DomainId $mockDomainId -CapacitiesIds $mockCapacityIds

Should -Invoke -CommandName Write-Message -ParameterFilter {
$Level -eq 'Error'
}
}
}

Context 'When an exception is thrown' {
BeforeAll {
Mock -CommandName Confirm-TokenState -MockWith { }
Mock -CommandName Write-Message -MockWith { }
Mock -CommandName Invoke-FabricRestMethod -MockWith {
throw 'API connection failed'
}
}

It 'Should handle exceptions gracefully' {
$mockDomainId = [guid]::NewGuid()
$mockCapacityIds = @([guid]::NewGuid())

{ Add-FabricDomainWorkspaceAssignmentByCapacity -DomainId $mockDomainId -CapacitiesIds $mockCapacityIds } | Should -Not -Throw

It "Should have exactly the number of expected parameters $($expected.Count)" {
$hasparms = $command.Parameters.Values.Name
#$hasparms.Count | Should -BeExactly $expected.Count
Compare-Object -ReferenceObject $expected -DifferenceObject $hasparms | Should -BeNullOrEmpty
Should -Invoke -CommandName Write-Message -ParameterFilter {
$Level -eq 'Error' -and $Message -like "*Error occurred while assigning workspaces*"
}
}
}
}
Loading
Loading