tests/Client/CustomApi.Tests.ps1
|
<# Integration Test: custom APIs (brief W11, W12) Registers an echo custom API backed by a plug-in compiled on the fly, then tests Invoke-XrmCustomApi and Invoke-XrmCustomApiLoop. #> . "$PSScriptRoot\..\_TestConfig.ps1"; # ============================================================ # Any SDK message # ============================================================ Write-Section "Invoke-XrmCustomApi on a platform message"; $whoAmI = Invoke-XrmCustomApi -XrmClient $Global:XrmClient -Name "WhoAmI"; Assert-Test "WhoAmI: response returned" { $null -ne $whoAmI -and $whoAmI.Results["UserId"] -ne [Guid]::Empty }; $outputError = $null; try { Invoke-XrmCustomApi -XrmClient $Global:XrmClient -Name "WhoAmI" -JsonOutput "Missing" | Out-Null; } catch { $outputError = $_.Exception.Message; } Assert-Test "-JsonOutput on a missing output: error listing the outputs" { $outputError -like "*Missing*UserId*" }; # ============================================================ # Setup: echo custom API # ============================================================ Write-Section "Setup - echo custom API"; $suffix = Get-Random -Minimum 10000 -Maximum 99999; $assemblyName = "PdoTest.CustomApi$suffix"; $apiName = "new_PdoEcho$suffix"; $source = @" using System; using Microsoft.Xrm.Sdk; namespace PdoTest { public class EchoApi : IPlugin { public void Execute(IServiceProvider serviceProvider) { var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext)); var input = context.InputParameters.Contains("Input") ? (string)context.InputParameters["Input"] : ""; context.OutputParameters["Result"] = "{\"Echo\":\"" + input + "\",\"Length\":" + input.Length + "}"; } } } "@; $assemblyPath = New-TestPluginAssembly -AssemblyName $assemblyName -Source $source; if (-not $assemblyPath) { Write-Host " [SKIP] .NET Framework compiler not available: custom API tests skipped" -ForegroundColor Yellow; Write-TestSummary; return; } $Global:XrmClient | Upsert-XrmAssembly -AssemblyPath $assemblyPath; $assembly = $Global:XrmClient | Get-XrmRecord -LogicalName "pluginassembly" -AttributeName "name" -Value $assemblyName -Columns "name"; $typeId = $Global:XrmClient | Add-XrmRecord -Record (New-XrmEntity -LogicalName "plugintype" -Attributes @{ typename = "PdoTest.EchoApi"; name = "PdoTest.EchoApi"; friendlyname = "EchoApi"; pluginassemblyid = $assembly.Reference }); $apiId = $Global:XrmClient | Add-XrmRecord -Record (New-XrmEntity -LogicalName "customapi" -Attributes @{ uniquename = $apiName; name = $apiName; displayname = "PDO Echo"; description = "PowerDataOps integration test"; bindingtype = (New-XrmOptionSetValue -Value 0); isfunction = $false; allowedcustomprocessingsteptype = (New-XrmOptionSetValue -Value 0); plugintypeid = (New-XrmEntityReference -LogicalName "plugintype" -Id $typeId) }); $apiRef = New-XrmEntityReference -LogicalName "customapi" -Id $apiId; $Global:XrmClient | Add-XrmRecord -Record (New-XrmEntity -LogicalName "customapirequestparameter" -Attributes @{ customapiid = $apiRef; uniquename = "Input"; name = "$apiName.Input"; displayname = "Input"; description = "Text to echo"; type = (New-XrmOptionSetValue -Value 10); isoptional = $true }) | Out-Null; $Global:XrmClient | Add-XrmRecord -Record (New-XrmEntity -LogicalName "customapiresponseproperty" -Attributes @{ customapiid = $apiRef; uniquename = "Result"; name = "$apiName.Result"; displayname = "Result"; description = "JSON result"; type = (New-XrmOptionSetValue -Value 10) }) | Out-Null; Assert-Test "Custom API registered" { $apiId -ne [Guid]::Empty }; # ============================================================ # Invoke-XrmCustomApi # ============================================================ Write-Section "Invoke-XrmCustomApi"; $response = Invoke-XrmCustomApi -XrmClient $Global:XrmClient -Name $apiName -Parameters @{ Input = "hello" }; Assert-Test "Response: raw JSON output" { $response.Results["Result"] -eq '{"Echo":"hello","Length":5}' }; $result = Invoke-XrmCustomApi -XrmClient $Global:XrmClient -Name $apiName -Parameters @{ Input = "hello" } -JsonOutput "Result"; Assert-Test "-JsonOutput: deserialized object" { $result.Echo -eq "hello" -and $result.Length -eq 5 }; $skipped = Invoke-XrmCustomApi -XrmClient $Global:XrmClient -Name $apiName -Parameters @{ Input = "hello" } -WhatIf; Assert-Test "-WhatIf: not executed, nothing returned" { $null -eq $skipped }; # ============================================================ # Invoke-XrmCustomApiLoop # ============================================================ Write-Section "Invoke-XrmCustomApiLoop"; $counter = @{ Calls = 0 }; $seen = [System.Collections.Generic.List[int]]::new(); $loop = Invoke-XrmCustomApiLoop -XrmClient $Global:XrmClient -Name $apiName -Parameters @{ Input = "abc" } -JsonOutput "Result" ` -OnIteration { param($output, $iteration) $counter.Calls++; $seen.Add($iteration); } -While { $counter.Calls -lt 3 } -MaxIterations 10; Assert-Test "Stops when -While is false: 3 iterations, no ceiling, last output" { $loop.Iterations -eq 3 -and -not $loop.CeilingReached -and $loop.LastOutput.Echo -eq "abc" }; Assert-Test "-OnIteration receives the iteration number" { ($seen -join ",") -eq "1,2,3" }; $byOutput = Invoke-XrmCustomApiLoop -XrmClient $Global:XrmClient -Name $apiName -Parameters @{ Input = "abc" } -JsonOutput "Result" -While { $_.Length -gt 100 }; Assert-Test "-While reads the output in `$_: 1 iteration" { $byOutput.Iterations -eq 1 -and -not $byOutput.CeilingReached }; $ceiling = Invoke-XrmCustomApiLoop -XrmClient $Global:XrmClient -Name $apiName -Parameters @{ Input = "abc" } -While { $true } -MaxIterations 2; Assert-Test "Ceiling: 2 iterations, CeilingReached, response as LastOutput" { $ceiling.Iterations -eq 2 -and $ceiling.CeilingReached -and $ceiling.LastOutput.Results["Result"] -like "*abc*" }; $whatIfLoop = Invoke-XrmCustomApiLoop -XrmClient $Global:XrmClient -Name $apiName -While { $true } -MaxIterations 5 -WhatIf; Assert-Test "-WhatIf: stops after the skipped call" { $whatIfLoop.Iterations -eq 1 -and $null -eq $whatIfLoop.LastOutput -and -not $whatIfLoop.CeilingReached }; $failure = $null; try { Invoke-XrmCustomApiLoop -XrmClient $Global:XrmClient -Name "new_PdoNoSuchApi$suffix" -While { $true } -MaxIterations 3 | Out-Null; } catch { $failure = $_.Exception.Message; } Assert-Test "A failed call stops the loop with an error" { $null -ne $failure }; # ============================================================ # Cleanup # ============================================================ Write-Section "Cleanup"; try { $Global:XrmClient | Remove-XrmRecord -LogicalName "customapi" -Id $apiId; } catch { } try { Remove-XrmPluginAssembly -XrmClient $Global:XrmClient -Name $assemblyName -Force | Out-Null; } catch { Write-Host " Cleanup failed: $($_.Exception.Message)" -ForegroundColor Red; } Remove-Item -Path (Split-Path $assemblyPath -Parent) -Recurse -Force -ErrorAction SilentlyContinue; Assert-Test "Custom API and assembly removed" { $null -eq ($Global:XrmClient | Get-XrmRecord -LogicalName "customapi" -Id $apiId -IfExists) -and $null -eq ($Global:XrmClient | Get-XrmRecord -LogicalName "pluginassembly" -Id $assembly.Id -IfExists); }; Write-TestSummary; |