tests/Customization/Customization.Tests.ps1

<#
    Integration Test: Customization
    Tests views, forms, charts, dashboards, commands cmdlets.
    Cmdlets: Add-XrmView, Get-XrmViews, Remove-XrmView,
             Get-XrmForms, Get-XrmCharts, Get-XrmDashboards,
             Add-XrmDashboard, Upsert-XrmDashboard, Remove-XrmDashboard (dashboard type, known issue K18),
             Add-XrmCommand, Get-XrmCommands, Remove-XrmCommand
#>

. "$PSScriptRoot\..\_TestConfig.ps1";

# ============================================================
# Get-XrmViews
# ============================================================
Write-Section "Get-XrmViews";

$views = $Global:XrmClient | Get-XrmViews -EntityLogicalName "account" -Columns "name", "savedqueryid", "querytype";
Assert-Test "Get-XrmViews (account) - returns views (actual: $($views.Count))" {
    $views.Count -ge 1;
};

$activeAccountsView = $views | Where-Object { $_.name -eq "Active Accounts" } | Select-Object -First 1;
Assert-Test "Get-XrmViews - 'Active Accounts' view exists" {
    $activeAccountsView -ne $null;
};

# ============================================================
# Add-XrmView + Remove-XrmView
# ============================================================
Write-Section "Add-XrmView + Remove-XrmView";

$viewName = Get-TestName -Prefix "View";
$fetchXml = @"
<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
  <entity name="account">
    <attribute name="name" />
    <attribute name="accountid" />
    <order attribute="name" descending="false" />
    <filter type="and">
      <condition attribute="statecode" operator="eq" value="0" />
    </filter>
  </entity>
</fetch>
"@
;

$layoutXml = @"
<grid name="resultset" object="1" jump="name" select="1" icon="1" preview="1">
  <row name="result" id="accountid">
    <cell name="name" width="300" />
  </row>
</grid>
"@
;

$viewRef = $Global:XrmClient | Add-XrmView `
    -EntityLogicalName "account" `
    -Name $viewName `
    -FetchXml $fetchXml `
    -LayoutXml $layoutXml `
    -Description "Integration test view";

Assert-Test "Add-XrmView - created '$viewName' (Id: $($viewRef.Id))" {
    $viewRef -ne $null -and $viewRef.Id -ne [Guid]::Empty;
};

# Verify the view appears
$viewsAfter = $Global:XrmClient | Get-XrmViews -EntityLogicalName "account" -Columns "name", "savedqueryid";
$createdView = $viewsAfter | Where-Object { $_.name -eq $viewName } | Select-Object -First 1;
Assert-Test "Add-XrmView - view appears in Get-XrmViews" {
    $createdView -ne $null;
};

# Remove the view
$Global:XrmClient | Remove-XrmView -ViewReference $viewRef;
Assert-Test "Remove-XrmView - view removed" { $true };

# ============================================================
# Get-XrmForms
# ============================================================
Write-Section "Get-XrmForms";

$forms = $Global:XrmClient | Get-XrmForms -EntityLogicalName "account" -Columns "name", "formid", "type";
Assert-Test "Get-XrmForms (account) - returns forms (actual: $($forms.Count))" {
    $forms.Count -ge 1;
};

# FormType 2 = Main form
$mainForms = $Global:XrmClient | Get-XrmForms -EntityLogicalName "account" -FormType 2 -Columns "name", "formid";
Assert-Test "Get-XrmForms (Main forms) - returns main forms (actual: $($mainForms.Count))" {
    $mainForms.Count -ge 1;
};

# ============================================================
# Get-XrmCharts
# ============================================================
Write-Section "Get-XrmCharts";

$charts = $Global:XrmClient | Get-XrmCharts -EntityLogicalName "account" -Columns "name", "savedqueryvisualizationid";
Assert-Test "Get-XrmCharts (account) - returns charts (actual: $($charts.Count))" {
    $charts.Count -ge 0;
};

# ============================================================
# Get-XrmDashboards
# ============================================================
Write-Section "Get-XrmDashboards";

$dashboards = $Global:XrmClient | Get-XrmDashboards -Columns "name", "formid";
$classicDashboards = @($Global:XrmClient | Get-XrmDashboards -Columns "name", "type" -Type 0);
$interactiveDashboards = @($Global:XrmClient | Get-XrmDashboards -Columns "name", "type" -Type 10);
Assert-Test "Get-XrmDashboards - default returns classic ($($classicDashboards.Count)) and interactive ($($interactiveDashboards.Count)) dashboards" {
    @($dashboards).Count -eq ($classicDashboards.Count + $interactiveDashboards.Count);
};
if ($interactiveDashboards.Count -eq 0) {
    Write-Host " [SKIP] No interactive experience dashboard on this instance: type 10 not exercised" -ForegroundColor Yellow;
}
Assert-Test "Get-XrmDashboards -Type 10 - only interactive experience dashboards" {
    @($interactiveDashboards | Where-Object { $_.type_Value.Value -ne 10 }).Count -eq 0;
};
Assert-Test "Get-XrmDashboards - returns dashboards (actual: $($dashboards.Count))" {
    $dashboards.Count -ge 0;
};

# ============================================================
# Add-XrmDashboard / Upsert-XrmDashboard -FormType (K18)
# ============================================================
Write-Section "Dashboard type: Add-XrmDashboard / Upsert-XrmDashboard -FormType";

# FormXml copied from the dashboards of the instance, one of each type
$sourceDashboards = @($Global:XrmClient | Get-XrmDashboards -Columns "name", "type", "formxml");
$classicXml = ($sourceDashboards | Where-Object { ($_ | Get-XrmAttributeValue -Name "type" -Raw) -eq 0 } | Sort-Object { $_.formxml.Length } | Select-Object -First 1).formxml;
$interactiveXml = ($sourceDashboards | Where-Object { ($_ | Get-XrmAttributeValue -Name "type" -Raw) -eq 10 } | Sort-Object { $_.formxml.Length } | Select-Object -First 1).formxml;
if (-not $classicXml -or -not $interactiveXml) {
    Write-Host " [SKIP] A classic and an interactive dashboard are needed to copy their FormXml" -ForegroundColor Yellow;
}
else {
    function Get-TestDashboard {
        param([Guid]$Id)
        # The update of a form stays unpublished: Retrieve answers the previous name
        $dashboard = @($Global:XrmClient | Get-XrmDashboards -Columns "name", "type", "formid" -Unpublished) | Where-Object { $_.formid -eq $Id } | Select-Object -First 1;
        if ($dashboard) {
            [PSCustomObject]@{ Name = $dashboard.name; Type = ($dashboard | Get-XrmAttributeValue -Name "type" -Raw) };
        }
    }

    $dashboardId = [Guid]::NewGuid();
    $dashboardName = Get-TestName -Prefix "Dashboard";
    $Global:XrmClient | Upsert-XrmDashboard -Id $dashboardId -Name $dashboardName -FormXml $interactiveXml -FormType 10 | Out-Null;
    Assert-Test "Upsert-XrmDashboard -FormType 10: created interactive" { (Get-TestDashboard -Id $dashboardId).Type -eq 10 };

    $Global:XrmClient | Upsert-XrmDashboard -Id $dashboardId -Name "$dashboardName v2" -FormXml $interactiveXml -FormType 10 | Out-Null;
    Assert-Test "Upsert-XrmDashboard -FormType 10 on an interactive dashboard: updated" { (Get-TestDashboard -Id $dashboardId).Name -eq "$dashboardName v2" };

    $typeError = $null;
    try { $Global:XrmClient | Upsert-XrmDashboard -Id $dashboardId -Name "$dashboardName v3" -FormXml $classicXml -FormType 0 | Out-Null; } catch { $typeError = $_.Exception.Message; }
    $afterError = Get-TestDashboard -Id $dashboardId;
    Assert-Test "Upsert-XrmDashboard -FormType 0 on an interactive dashboard: error, nothing written" { $typeError -like "*exists with form type 10, not 0*" -and $afterError.Name -eq "$dashboardName v2" -and $afterError.Type -eq 10 };

    $Global:XrmClient | Upsert-XrmDashboard -Id $dashboardId -Name "$dashboardName v4" -FormXml $interactiveXml | Out-Null;
    $withoutType = Get-TestDashboard -Id $dashboardId;
    Assert-Test "Upsert-XrmDashboard without -FormType: existing dashboard updated, type kept (as before)" { $withoutType.Name -eq "$dashboardName v4" -and $withoutType.Type -eq 10 };
    $Global:XrmClient | Remove-XrmDashboard -DashboardReference (New-XrmEntityReference -LogicalName "systemform" -Id $dashboardId);

    $classicId = [Guid]::NewGuid();
    $Global:XrmClient | Upsert-XrmDashboard -Id $classicId -Name (Get-TestName -Prefix "Dashboard") -FormXml $classicXml | Out-Null;
    Assert-Test "Upsert-XrmDashboard without -FormType: created classic (as before)" { (Get-TestDashboard -Id $classicId).Type -eq 0 };
    $Global:XrmClient | Remove-XrmDashboard -DashboardReference (New-XrmEntityReference -LogicalName "systemform" -Id $classicId);

    $addedRef = $Global:XrmClient | Add-XrmDashboard -Name (Get-TestName -Prefix "Dashboard") -FormXml $interactiveXml -FormType 10;
    Assert-Test "Add-XrmDashboard -FormType 10: created interactive" { (Get-TestDashboard -Id $addedRef.Id).Type -eq 10 };
    $Global:XrmClient | Remove-XrmDashboard -DashboardReference $addedRef;

    Assert-Test "Test dashboards removed" { $null -eq (Get-TestDashboard -Id $dashboardId) -and $null -eq (Get-TestDashboard -Id $classicId) -and $null -eq (Get-TestDashboard -Id $addedRef.Id) };
}

# ============================================================
# Add-XrmCommand + Get-XrmCommands + Remove-XrmCommand
# ============================================================
Write-Section "Commands CRUD";

$cmdName = Get-TestName -Prefix "Cmd";
$cmdUniqueName = "pdo_testcmd_$(Get-Random -Minimum 10000 -Maximum 99999)";
$cmdRef = $Global:XrmClient | Add-XrmCommand `
    -Name $cmdName `
    -UniqueName $cmdUniqueName `
    -Type 2 `
    -Context 0 `
    -ButtonLabelText "Test Button" `
    -Location 0;

Assert-Test "Add-XrmCommand - created '$cmdName'" {
    $cmdRef -ne $null -and $cmdRef.Id -ne [Guid]::Empty;
};

# Get commands and check ours exists
$commands = $Global:XrmClient | Get-XrmCommands -Columns "name", "uniquename";
Assert-Test "Get-XrmCommands - returns commands (actual: $($commands.Count))" {
    $commands.Count -ge 1;
};

$ourCmd = $commands | Where-Object { $_.uniquename -eq $cmdUniqueName } | Select-Object -First 1;
Assert-Test "Get-XrmCommands - test command found" {
    $ourCmd -ne $null;
};

# Remove command
$Global:XrmClient | Remove-XrmCommand -CommandReference $cmdRef;
Assert-Test "Remove-XrmCommand - command removed" { $true };

Write-TestSummary;