Modules/businessdev.ALbuild.Apps/Private/ConvertTo-BcTestCodeunitFilter.ps1

function ConvertTo-BcTestCodeunitFilter {
    <#
    .SYNOPSIS
        Normalises a test codeunit selection into the AL filter the test page expects.
 
    .DESCRIPTION
        Accepts ids, ranges and alternatives: '50100', '50100..50150', '50100-50150', '50100|50200',
        '50100,50200'. Anything else throws, because a filter the page cannot read selects nothing and the
        run would end with no test at all.
    #>

    [CmdletBinding()]
    [OutputType([string])]
    param([Parameter(Mandatory)] [string] $Filter)

    $parts = foreach ($term in ($Filter -split '[|,]')) {
        $t = $term.Trim()
        if (-not $t) { continue }
        if ($t -match '^(\d+)\s*(?:\.\.|-)\s*(\d+)$') { '{0}..{1}' -f $Matches[1], $Matches[2] }
        elseif ($t -match '^\d+$') { $t }
        else { throw "Test codeunit filter '$Filter': '$t' is not an id or a range (use 50100, 50100..50150 or 50100|50200)." }
    }
    if (@($parts).Count -eq 0) { throw "Test codeunit filter '$Filter' selects nothing." }
    return (@($parts) -join '|')
}

function Test-BcTestCodeunitFilter {
    <#
    .SYNOPSIS
        Whether a codeunit id matches a normalised codeunit filter ('50100..50150|50200').
    #>

    [CmdletBinding()]
    [OutputType([bool])]
    param([Parameter(Mandatory)] [int] $Id, [Parameter(Mandatory)] [string] $Filter)
    foreach ($t in ($Filter -split '\|')) {
        if ($t -match '^(\d+)\.\.(\d+)$') { if ($Id -ge [int]$Matches[1] -and $Id -le [int]$Matches[2]) { return $true } }
        elseif ([int]$t -eq $Id) { return $true }
    }
    return $false
}

function Test-BcTestProcedureFilter {
    <#
    .SYNOPSIS
        Whether a test procedure name matches an AL name filter ('Post*|Release?', '@post*' ignores case).
    .DESCRIPTION
        Mirrors how the test page applies the filter (SetFilter on the method name): '*' and '?' are
        wildcards, '|' separates alternatives, and the match is case-sensitive unless the term starts with '@'.
    #>

    [CmdletBinding()]
    [OutputType([bool])]
    param([Parameter(Mandatory)] [string] $Name, [Parameter(Mandatory)] [string] $Filter)
    foreach ($term in ($Filter -split '\|')) {
        $t = $term.Trim()
        if (-not $t) { continue }
        $ignoreCase = $t.StartsWith('@')
        if ($ignoreCase) { $t = $t.Substring(1) }
        $pattern = '^' + ([regex]::Escape($t) -replace '\\\*', '.*' -replace '\\\?', '.') + '$'
        $options = if ($ignoreCase) { [System.Text.RegularExpressions.RegexOptions]::IgnoreCase } else { [System.Text.RegularExpressions.RegexOptions]::None }
        if ([regex]::IsMatch($Name, $pattern, $options)) { return $true }
    }
    return $false
}