tests/Metadata/MetadataSettings.Tests.ps1
|
<# Integration Test: table, column and relationship settings (brief lot 5: M01 to M07) Add-XrmTable / Set-XrmTable flags and -LogicalName, activity table creation, Set-XrmColumn -LogicalName -RequiredLevel -MinValue -MaxValue, New-XrmBooleanColumn -TrueLabels -FalseLabels, New-XrmCascadeConfiguration, New-XrmAssociatedMenuConfiguration, Set-XrmRelationship, Get-XrmRelationship -IfExists, Get-XrmAlternateKey -IfExists, New-XrmLabel (empty text), ConvertFrom-XrmLabel. Known issues 2.0.0.65: Add-XrmTable -SchemaName (K15), Set-XrmTable -IsBusinessProcessEnabled (K09), Set-XrmColumnVisualization (K11), menu properties kept (K16). #> . "$PSScriptRoot\..\_TestConfig.ps1"; $prefix = "new"; $suffix = Get-Random -Minimum 10000 -Maximum 99999; $tableName = "${prefix}_pdoset$suffix"; $activityName = "${prefix}_pdoact$suffix"; $relationshipName = "${prefix}_account_${tableName}"; # ============================================================ # Labels (local) # ============================================================ Write-Section "New-XrmLabel / ConvertFrom-XrmLabel"; $emptyLabel = New-XrmLabel -Text ""; Assert-Test "New-XrmLabel -Text '': accepted" { $emptyLabel.LocalizedLabels.Count -eq 1 -and $emptyLabel.LocalizedLabels[0].Label -eq "" }; $converted = ConvertFrom-XrmLabel -Label (New-XrmLabel -Labels @{ 1033 = "Project"; 1036 = "Projet" }); Assert-Test "ConvertFrom-XrmLabel: every language, int keys" { $converted.Count -eq 2 -and $converted[1036] -eq "Projet" -and $converted[1033] -eq "Project" }; $french = ConvertFrom-XrmLabel -Label (New-XrmLabel -Labels @{ 1033 = "Project"; 1036 = "Projet" }) -LanguageCodes 1036; Assert-Test "-LanguageCodes: filtered" { $french.Count -eq 1 -and $french[1036] -eq "Projet" }; Assert-Test "`$null label: empty hashtable" { (ConvertFrom-XrmLabel -Label $null).Count -eq 0 }; # ============================================================ # Tables # ============================================================ Write-Section "Add-XrmTable / Set-XrmTable flags"; $Global:XrmClient | Add-XrmTable -LogicalName $tableName -DisplayNameLabels @{ 1033 = "PDO settings $suffix"; 1036 = "Reglages PDO $suffix" } -PluralName "PDO settings" ` -PrimaryAttributeSchemaName "${prefix}_name" -PrimaryAttributeDisplayName "Name" -IsQuickCreateEnabled $true -ChangeTrackingEnabled $true -SchemaName "${prefix}_PdoSet$suffix" | Out-Null; $table = Get-XrmEntityMetadata -XrmClient $Global:XrmClient -LogicalName $tableName -Filter Entity; Assert-Test "Created with IsQuickCreateEnabled and ChangeTrackingEnabled" { $table.IsQuickCreateEnabled -eq $true -and $table.ChangeTrackingEnabled -eq $true }; Assert-Test "-SchemaName: schema name kept with its casing (K15)" { $table.SchemaName -ceq "${prefix}_PdoSet$suffix" -and $table.LogicalName -ceq $tableName }; $schemaNameError = $null; try { New-XrmTable -LogicalName $tableName -SchemaName "${prefix}_Other$suffix" | Out-Null; } catch { $schemaNameError = $_.Exception.Message; } Assert-Test "SchemaName that is not LogicalName in another casing: error" { $schemaNameError -like "*does not match LogicalName*" }; Assert-Test "SchemaName alone: logical name derived in lower case" { (New-XrmTable -SchemaName "${prefix}_BankAccount").LogicalName -ceq "${prefix}_bankaccount" }; Assert-Test "ConvertFrom-XrmLabel on table metadata" { (ConvertFrom-XrmLabel -Label $table.DisplayName)[1036] -eq "Reglages PDO $suffix" }; $Global:XrmClient | Set-XrmTable -LogicalName $tableName -IsConnectionsEnabled $true -IsDocumentManagementEnabled $true -SyncToExternalSearchIndex $true -IsQuickCreateEnabled $false | Out-Null; $table = Get-XrmEntityMetadata -XrmClient $Global:XrmClient -LogicalName $tableName -Filter Entity; Assert-Test "Set-XrmTable -LogicalName: flags applied" { $table.IsConnectionsEnabled.Value -eq $true -and $table.IsDocumentManagementEnabled -eq $true -and $table.SyncToExternalSearchIndex -eq $true -and $table.IsQuickCreateEnabled -eq $false; }; Assert-Test "Untouched flags kept (ChangeTrackingEnabled)" { $table.ChangeTrackingEnabled -eq $true }; $Global:XrmClient | Set-XrmTable -MetadataId $table.MetadataId -IsMailMergeEnabled $false | Out-Null; $table = Get-XrmEntityMetadata -XrmClient $Global:XrmClient -LogicalName $tableName -Filter Entity; Assert-Test "Set-XrmTable -MetadataId -IsMailMergeEnabled `$false" { $table.IsMailMergeEnabled.Value -eq $false }; $missingIdError = $null; try { $Global:XrmClient | Set-XrmTable -IsQuickCreateEnabled $true | Out-Null; } catch { $missingIdError = $_.Exception.Message; } Assert-Test "Neither MetadataId nor LogicalName: error" { $missingIdError -like "*MetadataId or LogicalName*" }; # K09: IsBPFEntity is ignored by UpdateEntity (it marks the tables generated for a business process flow); IsBusinessProcessEnabled is the table setting $Global:XrmClient | Set-XrmTable -LogicalName $tableName -IsBusinessProcessEnabled $true | Out-Null; $table = Get-XrmEntityMetadata -XrmClient $Global:XrmClient -LogicalName $tableName -Filter Entity; Assert-Test "Set-XrmTable -IsBusinessProcessEnabled `$true: applied" { $table.IsBusinessProcessEnabled -eq $true }; Write-Section "Activity table"; $rulesError = $null; try { $Global:XrmClient | Add-XrmTable -LogicalName $activityName -DisplayName "PDO activity $suffix" -PluralName "PDO activities" -IsActivity $true -PrimaryAttributeSchemaName "Subject" -PrimaryAttributeDisplayName "Subject" | Out-Null; } catch { $rulesError = $_.Exception.Message; } Assert-Test "Activity without -HasNotes / -IsAvailableOffline: actionable error before sending" { $rulesError -like "*HasNotes*IsAvailableOffline*" }; $activityError = $null; try { $Global:XrmClient | Add-XrmTable -LogicalName $activityName -DisplayName "PDO activity $suffix" -PluralName "PDO activities" -IsActivity $true -HasNotes $true ` -PrimaryAttributeSchemaName "Subject" -PrimaryAttributeDisplayName "Subject" -IsAvailableOffline $true -IsQuickCreateEnabled $true -ErrorAction Stop | Out-Null; } catch { $activityError = $_.Exception.Message; } $activity = Get-XrmEntityMetadata -XrmClient $Global:XrmClient -LogicalName $activityName -Filter Entity -IfExists; Assert-Test "Activity table created with -HasNotes -IsAvailableOffline -IsQuickCreateEnabled $(if ($activityError) { "($activityError)" })" { $null -ne $activity -and $activity.IsActivity -eq $true -and $activity.IsQuickCreateEnabled -eq $true }; # ============================================================ # Columns # ============================================================ Write-Section "Set-XrmColumn -LogicalName -RequiredLevel -MinValue -MaxValue"; $integer = New-XrmIntegerColumn -LogicalName "${prefix}_score" -SchemaName "${prefix}_Score" -DisplayName "Score" -MinValue 0 -MaxValue 100; $Global:XrmClient | Add-XrmColumn -EntityLogicalName $tableName -Attribute $integer | Out-Null; $money = New-XrmMoneyColumn -LogicalName "${prefix}_budget" -SchemaName "${prefix}_Budget" -DisplayName "Budget" -Precision 2 -MinValue 0 -MaxValue 1000; $Global:XrmClient | Add-XrmColumn -EntityLogicalName $tableName -Attribute $money | Out-Null; # The test instance accepts UpdateAttribute but keeps the requirement level (SDK .NET and .NET Framework alike): # the cmdlet must then say so instead of returning as if it worked $levelError = $null; try { $Global:XrmClient | Set-XrmColumn -EntityLogicalName $tableName -LogicalName "${prefix}_score" -RequiredLevel ApplicationRequired | Out-Null; } catch { $levelError = $_.Exception.Message; } $score = Get-XrmColumn -XrmClient $Global:XrmClient -EntityLogicalName $tableName -LogicalName "${prefix}_score"; $levelApplied = $score.RequiredLevel.Value -eq [Microsoft.Xrm.Sdk.Metadata.AttributeRequiredLevel]::ApplicationRequired; Assert-Test "RequiredLevel: applied, or an explicit error when the platform kept the old level (applied: $levelApplied)" { ($levelApplied -and $null -eq $levelError) -or (-not $levelApplied -and $levelError -like "*kept its requirement level*") }; Assert-Test "Range kept by the RequiredLevel update" { $score.MinValue -eq 0 -and $score.MaxValue -eq 100 }; $Global:XrmClient | Set-XrmColumn -EntityLogicalName $tableName -LogicalName "${prefix}_score" -MinValue 200 -MaxValue 300 | Out-Null; $score = Get-XrmColumn -XrmClient $Global:XrmClient -EntityLogicalName $tableName -LogicalName "${prefix}_score"; Assert-Test "Range moved above the old one in one call (200..300)" { $score.MinValue -eq 200 -and $score.MaxValue -eq 300 }; $Global:XrmClient | Set-XrmColumn -EntityLogicalName $tableName -LogicalName "${prefix}_score" -MaxValue 250 | Out-Null; $score = Get-XrmColumn -XrmClient $Global:XrmClient -EntityLogicalName $tableName -LogicalName "${prefix}_score"; Assert-Test "-MaxValue alone: minimum kept" { $score.MinValue -eq 200 -and $score.MaxValue -eq 250 }; $Global:XrmClient | Set-XrmColumn -EntityLogicalName $tableName -LogicalName "${prefix}_budget" -MinValue -500 -MaxValue 5000.5 | Out-Null; $budget = Get-XrmColumn -XrmClient $Global:XrmClient -EntityLogicalName $tableName -LogicalName "${prefix}_budget"; Assert-Test "Currency range (-500..5000.5)" { $budget.MinValue -eq -500 -and $budget.MaxValue -eq 5000.5 }; $rangeError = $null; try { $Global:XrmClient | Set-XrmColumn -EntityLogicalName $tableName -LogicalName "${prefix}_score" -MinValue 400 | Out-Null; } catch { $rangeError = $_.Exception.Message; } Assert-Test "MinValue above the kept MaxValue: error before sending" { $rangeError -like "*greater than MaxValue*" }; $typeError = $null; try { $Global:XrmClient | Set-XrmColumn -EntityLogicalName $tableName -LogicalName "${prefix}_name" -MaxValue 10 | Out-Null; } catch { $typeError = $_.Exception.Message; } Assert-Test "Range on a text column: error" { $typeError -like "*has no MinValue*" }; $locked = (Get-XrmEntityMetadata -XrmClient $Global:XrmClient -LogicalName "account" -Filter Attributes).Attributes | Where-Object { $null -ne $_.RequiredLevel -and -not $_.RequiredLevel.CanBeChanged } | Select-Object -First 1; if ($locked) { $otherLevel = $(if ($locked.RequiredLevel.Value -eq [Microsoft.Xrm.Sdk.Metadata.AttributeRequiredLevel]::None) { "ApplicationRequired" } else { "None" }); $lockedError = $null; try { $Global:XrmClient | Set-XrmColumn -EntityLogicalName "account" -LogicalName $locked.LogicalName -RequiredLevel $otherLevel -WhatIf | Out-Null; } catch { $lockedError = $_.Exception.Message; } Assert-Test "RequiredLevel.CanBeChanged false ('account.$($locked.LogicalName)'): error before sending" { $lockedError -like "*cannot be changed*" }; } Write-Section "Set-XrmColumnVisualization"; # Renderer ids read from the maker portal by the consumer repository (heat map, radial dial) $heatMapId = [Guid]"e7f8a9b0-c1d2-4e3f-5a6b-7c8d9e0f1a2b"; $radialDialId = [Guid]"c3d4e5f6-a7b8-9012-cdef-345678901234"; $visualizationPublisherRef = $Global:XrmClient | Add-XrmPublisher -UniqueName "pdoviz$suffix" -DisplayName "PDO Viz $suffix" -Prefix "pdz" -OptionValuePrefix (10000 + ($suffix % 89999)) -Description "Integration test publisher"; $visualizationSolution = "pdovizsol$suffix"; $visualizationSolutionRef = $Global:XrmClient | Add-XrmSolution -UniqueName $visualizationSolution -DisplayName "PDO Viz $suffix" -PublisherReference $visualizationPublisherRef -Version "1.0.0.0"; $componentTypeCache = @{}; $visualizationRef = $null; if (-not (Get-XrmEntityMetadata -XrmClient $Global:XrmClient -LogicalName "controlconfiguration" -Filter Entity -IfExists)) { Write-Host " [SKIP] No controlconfiguration table on this instance" -ForegroundColor Yellow; } else { $visualizationRef = Set-XrmColumnVisualization -XrmClient $Global:XrmClient -EntityLogicalName $tableName -LogicalName "${prefix}_score" -RendererId $heatMapId -SolutionUniqueName $visualizationSolution -Cache $componentTypeCache; $configuration = $Global:XrmClient | Get-XrmRecord -LogicalName "controlconfiguration" -Id $visualizationRef.Id -Columns "uniquename", "name", "entitylogicalname", "attribute", "metadatajson" -AsEntity; Assert-Test "Created: controlconfiguration as the maker portal writes it" { $configuration["uniquename"] -eq "msdyn_$($tableName)_${prefix}_score_customrenderers" -and $configuration["name"] -eq "CustomRenderersConfiguration" -and $configuration["entitylogicalname"] -eq $tableName -and $configuration["attribute"].Id -eq $score.MetadataId -and $configuration["metadatajson"] -eq "{`"type`":`"$heatMapId`"}"; }; $componentType = Get-XrmSolutionComponentType -XrmClient $Global:XrmClient -LogicalName "controlconfiguration" -Cache $componentTypeCache; Assert-Test "Added to the solution under the organization's component type ($componentType)" { Test-XrmSolutionComponent -XrmClient $Global:XrmClient -SolutionUniqueName $visualizationSolution -ComponentId $visualizationRef.Id -ComponentType $componentType }; $updatedRef = Set-XrmColumnVisualization -XrmClient $Global:XrmClient -EntityLogicalName $tableName -LogicalName "${prefix}_score" -RendererId $radialDialId; $configuration = $Global:XrmClient | Get-XrmRecord -LogicalName "controlconfiguration" -Id $visualizationRef.Id -Columns "metadatajson" -AsEntity; Assert-Test "Second call: same row, renderer updated" { $updatedRef.Id -eq $visualizationRef.Id -and $configuration["metadatajson"] -eq "{`"type`":`"$radialDialId`"}" }; $removed = Set-XrmColumnVisualization -XrmClient $Global:XrmClient -EntityLogicalName $tableName -LogicalName "${prefix}_score" -Remove; Assert-Test "-Remove: row deleted, nothing returned" { $null -eq $removed -and $null -eq ($Global:XrmClient | Get-XrmRecord -LogicalName "controlconfiguration" -Id $visualizationRef.Id -IfExists) }; $removeAgainError = $null; try { Set-XrmColumnVisualization -XrmClient $Global:XrmClient -EntityLogicalName $tableName -LogicalName "${prefix}_score" -Remove -ErrorAction Stop; } catch { $removeAgainError = $_.Exception.Message; } Assert-Test "-Remove without visualization: nothing, no error" { $null -eq $removeAgainError }; } Write-Section "New-XrmBooleanColumn -TrueLabels -FalseLabels"; $boolean = New-XrmBooleanColumn -LogicalName "${prefix}_enabled" -SchemaName "${prefix}_Enabled" -DisplayName "Enabled" -TrueLabels @{ 1033 = "On"; 1036 = "Marche" } -FalseLabels @{ 1033 = "Off"; 1036 = "Arret" }; $Global:XrmClient | Add-XrmColumn -EntityLogicalName $tableName -Attribute $boolean | Out-Null; $enabled = Get-XrmColumn -XrmClient $Global:XrmClient -EntityLogicalName $tableName -LogicalName "${prefix}_enabled"; Assert-Test "Option labels in both languages" { (ConvertFrom-XrmLabel -Label $enabled.OptionSet.TrueOption.Label)[1036] -eq "Marche" -and (ConvertFrom-XrmLabel -Label $enabled.OptionSet.FalseOption.Label)[1033] -eq "Off"; }; # ============================================================ # Relationships # ============================================================ Write-Section "Set-XrmRelationship / New-XrmCascadeConfiguration / New-XrmAssociatedMenuConfiguration"; Assert-Test "Get-XrmRelationship -IfExists before creation: `$null" { $null -eq (Get-XrmRelationship -XrmClient $Global:XrmClient -Name $relationshipName -IfExists) }; $oneToMany = New-Object Microsoft.Xrm.Sdk.Metadata.OneToManyRelationshipMetadata; $oneToMany.SchemaName = $relationshipName; $oneToMany.ReferencedEntity = "account"; $oneToMany.ReferencingEntity = $tableName; $oneToMany.ReferencedAttribute = "accountid"; $oneToMany.CascadeConfiguration = New-XrmCascadeConfiguration -Assign NoCascade -Delete RemoveLink -Merge NoCascade -Reparent NoCascade -Share NoCascade -Unshare NoCascade; $lookup = New-Object Microsoft.Xrm.Sdk.Metadata.LookupAttributeMetadata; $lookup.SchemaName = "${prefix}_AccountId"; $lookup.DisplayName = New-XrmLabel -Text "Account"; $lookup.RequiredLevel = New-Object Microsoft.Xrm.Sdk.Metadata.AttributeRequiredLevelManagedProperty([Microsoft.Xrm.Sdk.Metadata.AttributeRequiredLevel]::None); $Global:XrmClient | Add-XrmOneToManyRelationship -OneToManyRelationship $oneToMany -Lookup $lookup | Out-Null; $menuBefore = (Get-XrmRelationship -XrmClient $Global:XrmClient -Name $relationshipName).AssociatedMenuConfiguration; $menu = New-XrmAssociatedMenuConfiguration -Behavior UseLabel -Group Details -Labels @{ 1033 = "PDO rows"; 1036 = "Lignes PDO" } -Order 10500; $Global:XrmClient | Set-XrmRelationship -Name $relationshipName -CascadeConfiguration (New-XrmCascadeConfiguration -Delete Restrict) -AssociatedMenuConfiguration $menu | Out-Null; $relationship = Get-XrmRelationship -XrmClient $Global:XrmClient -Name $relationshipName; # K16: the value-type properties of a new menu object (false, empty Guid) are not copied Assert-Test "Menu: IsCustomizable, AvailableOffline and ViewId kept" { $relationship.AssociatedMenuConfiguration.IsCustomizable -eq $menuBefore.IsCustomizable -and $relationship.AssociatedMenuConfiguration.AvailableOffline -eq $menuBefore.AvailableOffline -and $relationship.AssociatedMenuConfiguration.ViewId -eq $menuBefore.ViewId; }; Assert-Test "Cascade: Delete Restrict applied, Assign kept (NoCascade)" { $relationship.CascadeConfiguration.Delete -eq [Microsoft.Xrm.Sdk.Metadata.CascadeType]::Restrict -and $relationship.CascadeConfiguration.Assign -eq [Microsoft.Xrm.Sdk.Metadata.CascadeType]::NoCascade; }; Assert-Test "Menu: UseLabel, group, order, French label" { $relationship.AssociatedMenuConfiguration.Behavior -eq [Microsoft.Xrm.Sdk.Metadata.AssociatedMenuBehavior]::UseLabel -and $relationship.AssociatedMenuConfiguration.Order -eq 10500 -and (ConvertFrom-XrmLabel -Label $relationship.AssociatedMenuConfiguration.Label)[1036] -eq "Lignes PDO"; }; $kindError = $null; try { $Global:XrmClient | Set-XrmRelationship -Name $relationshipName -Entity1AssociatedMenuConfiguration $menu | Out-Null; } catch { $kindError = $_.Exception.Message; } Assert-Test "N:N settings on a 1:N relationship: error" { $kindError -like "*one-to-many*" }; $missingError = $null; try { $Global:XrmClient | Set-XrmRelationship -Name "${prefix}_pdo_missing_$suffix" -CascadeConfiguration (New-XrmCascadeConfiguration -Delete Restrict) | Out-Null; } catch { $missingError = $_.Exception.Message; } Assert-Test "Missing relationship: error" { $missingError -like "*not found*" }; Assert-Test "Get-XrmAlternateKey -IfExists on a missing key: `$null" { $null -eq (Get-XrmAlternateKey -XrmClient $Global:XrmClient -EntityLogicalName $tableName -LogicalName "${prefix}_pdo_missing_key" -IfExists) }; # ============================================================ # Cleanup # ============================================================ Write-Section "Cleanup"; if ($visualizationRef) { $Global:XrmClient | Remove-XrmRecord -LogicalName "controlconfiguration" -Id $visualizationRef.Id -IfExists; } try { $Global:XrmClient | Remove-XrmRecord -LogicalName "solution" -Id $visualizationSolutionRef.Id -IfExists; } catch { Write-Host " Cleanup failed: $($_.Exception.Message)" -ForegroundColor Red; } try { $Global:XrmClient | Remove-XrmRecord -LogicalName "publisher" -Id $visualizationPublisherRef.Id -IfExists; } catch { Write-Host " Cleanup failed: $($_.Exception.Message)" -ForegroundColor Red; } try { $Global:XrmClient | Remove-XrmRelationship -Name $relationshipName | Out-Null; } catch { } try { $Global:XrmClient | Remove-XrmTable -LogicalName $tableName | Out-Null; } catch { Write-Host " Cleanup failed: $($_.Exception.Message)" -ForegroundColor Red; } if ($activity) { try { $Global:XrmClient | Remove-XrmTable -LogicalName $activityName | Out-Null; } catch { Write-Host " Cleanup failed: $($_.Exception.Message)" -ForegroundColor Red; } } Assert-Test "Test tables removed" { -not (Test-XrmTable -XrmClient $Global:XrmClient -LogicalName $tableName) -and -not (Test-XrmTable -XrmClient $Global:XrmClient -LogicalName $activityName) }; Write-TestSummary; |