ReportPortal.psm1

<# ----------------- DEBUGGING ONLY -- REMOVED DURING BUILD ----------------- #>

# Get and dot source all helper functions (internal)
Split-Path -Path $PSCommandPath |
    Get-ChildItem -Filter 'Helpers' -Directory |
        Get-ChildItem -Include '*.ps1' -Exclude '*.Tests.*' -File -Recurse |
            ForEach-Object { . $_.FullName }

# Get and dot source all external functions (public)
Split-Path -Path $PSCommandPath |
    Get-ChildItem -Filter 'Functions' -Directory |
        Get-ChildItem -Include '*.ps1' -Exclude '*.Tests.*' -File -Recurse |
<#
    .SYNOPSIS
        Connect to the report portal service. It will return the service object.
 
    .DESCRIPTION
        .
#>

function Connect-RPService
{
    [CmdletBinding()]
    [OutputType([ReportPortal.Client.Service])]
    param
    (
        # Report portal computer name.
        [Parameter(Mandatory = $true)]
        [System.String]
        $ComputerName,

        # Report portal port.
        [Parameter(Mandatory = $true)]
        [System.Int32]
        $Port,

        # Option to switch SSL.
        [Parameter(Mandatory = $false)]
        [switch]
        $UseSSL,

        # Project name.
        [Parameter(Mandatory = $true)]
        [System.String]
        $ProjectName,

        # Unique identifier.
        [Parameter(Mandatory = $true)]
        [System.String]
        $UserId
    )

    if ($UseSSL.IsPresent)
    {
        $uri = 'https://{0}:{1}/api/v1' -f $ComputerName, $Port
    }
    else
    {
        $uri = 'http://{0}:{1}/api/v1' -f $ComputerName, $Port
    }

    $service = [ReportPortal.Client.Service]::new($uri, $ProjectName, $UserId)

    Write-Output $service
}

<#
    .SYNOPSIS
        Get all report portal launches.
 
    .DESCRIPTION
        Call the GetLaunchAsync() or GetLaunchesAsync() methods on the service
        object to get all existing launches. The method will be invoked
        synchronously.
#>

function Get-RPLaunch
{
    [CmdletBinding(DefaultParameterSetName = 'None')]
    [OutputType([ReportPortal.Client.Models.Launch])]
    param
    (
        # The report portal service.
        [Parameter(Mandatory = $true)]
        [ReportPortal.Client.Service]
        $Service,

        # Optional launch id.
        [Parameter(Mandatory = $false, ParameterSetName = 'Id')]
        [System.String]
        $Id,

        # Optional launch name.
        [Parameter(Mandatory = $false, ParameterSetName = 'Name')]
        [SupportsWildcards()]
        [System.String]
        $Name
    )

    try
    {
        if ($PSCmdlet.ParameterSetName -eq 'Id')
        {
            $Service.GetLaunchAsync($Id).GetAwaiter().GetResult()
        }
        else
        {
            $launches = @()

            $filterOption = [ReportPortal.Client.Filtering.FilterOption]::new()
            $filterOption.Paging = [ReportPortal.Client.Filtering.Paging]::new(1, 300)

            do
            {
                $result = $Service.GetLaunchesAsync($filterOption, $false).GetAwaiter().GetResult()
                $filterOption.Paging.Number++

                $launches += $result.Launches
            }
            while ($result.Page.Number -lt $result.Page.TotalPages)

            # Filter all launches by name
            if ($PSBoundParameters.ContainsKey('Name'))
            {
                $launches = $launches | Where-Object { $_.Name -like $Name }
            }

            Write-Output $launches
        }
    }
    catch
    {
        ConvertFrom-RPException -ErrorRecord $_ | Write-Error
    }
}

<#
    .SYNOPSIS
        Get all test items.
 
    .DESCRIPTION
        Call the GetTestItemAsync() or GetTestItemsAsync() methods on the
        service object to get all test items. The method will be invoked
        synchronously.
#>

function Get-RPTestItem
{
    [CmdletBinding(DefaultParameterSetName = 'None')]
    [OutputType([ReportPortal.Client.Models.TestItem])]
    param
    (
        # The report portal service.
        [Parameter(Mandatory = $true)]
        [ReportPortal.Client.Service]
        $Service,

        # Optional test item id.
        [Parameter(Mandatory = $false, ParameterSetName = 'Id')]
        [System.String]
        $Id,

        # Optional test item name.
        [Parameter(Mandatory = $false, ParameterSetName = 'Name')]
        [SupportsWildcards()]
        [System.String]
        $Name
    )

    try
    {
        if ($PSCmdlet.ParameterSetName -eq 'Id')
        {
            $Service.GetTestItemAsync($Id).GetAwaiter().GetResult()
        }
        else
        {
            $testItems = @()

            $filterOption = [ReportPortal.Client.Filtering.FilterOption]::new()
            $filterOption.Paging = [ReportPortal.Client.Filtering.Paging]::new(1, 300)

            do
            {
                $result = $Service.GetTestItemsAsync($filterOption).GetAwaiter().GetResult()
                $filterOption.Paging.Number++

                $testItems += $result.TestItems
            }
            while ($result.Page.Number -lt $result.Page.TotalPages)

            # Filter all test items by name
            if ($PSBoundParameters.ContainsKey('Name'))
            {
                $testItems = $testItems | Where-Object { $_.Name -like $Name }
            }

            Write-Output $testItems
        }
    }
    catch
    {
        ConvertFrom-RPException -ErrorRecord $_ | Write-Error
    }
}

<#
    .SYNOPSIS
        Remove an existing report portal launch.
 
    .DESCRIPTION
        Call the DeleteLaunchAsync() method on the service object to remove the
        existing launch from the report portal. The method will be invoked
        synchronously.
#>

function Remove-RPLaunch
{
    [CmdletBinding(SupportsShouldProcess = $true)]
    param
    (
        # The report portal service.
        [Parameter(Mandatory = $true)]
        [ReportPortal.Client.Service]
        $Service,

        # The launch id to remove.
        [Parameter(Mandatory = $true, ParameterSetName = 'Id')]
        [System.String]
        $Id,

        # The launch to remove.
        [Parameter(Mandatory = $true, ParameterSetName = 'Launch')]
        [ReportPortal.Client.Models.Launch]
        $Launch,

        # Force the removal.
        [Parameter(Mandatory = $false)]
        [switch]
        $Force
    )

    try
    {
        if ($PSCmdlet.ParameterSetName -eq 'Launch')
        {
            $Id = $Launch.Id
        }

        if ($Force.IsPresent)
        {
            Stop-RPLaunch -Service $service -Id $Id -Force
        }

        if ($PSCmdlet.ShouldProcess($Id, 'Remove Launch'))
        {
            $Service.DeleteLaunchAsync($Id).GetAwaiter().GetResult() | Out-Null
        }
    }
    catch
    {
        ConvertFrom-RPException -ErrorRecord $_ | Write-Error
    }
}

<#
    .SYNOPSIS
        Start a new report portal launch.
 
    .DESCRIPTION
        Call the StartLaunchAsync() method on the service object to start a new
        launch in the report portal. The method will be invoked synchronously.
#>

function Start-RPLaunch
{
    [CmdletBinding(SupportsShouldProcess = $true)]
    [OutputType([ReportPortal.Client.Models.Launch])]
    param
    (
        # The report portal service.
        [Parameter(Mandatory = $true)]
        [ReportPortal.Client.Service]
        $Service,

        # Launch name.
        [Parameter(Mandatory = $true)]
        [System.String]
        $Name,

        # Launch description.
        [Parameter(Mandatory = $false)]
        [System.String]
        $Description,

        # Launch start time.
        [Parameter(Mandatory = $false)]
        [System.DateTime]
        $StartTime = (Get-Date),

        # Test item tags.
        [Parameter(Mandatory = $false)]
        [System.String[]]
        $Tags
    )

    try
    {
        $model = [ReportPortal.Client.Requests.StartLaunchRequest]::new()
        $model.Name        = $Name
        $model.Description = $Description
        $model.StartTime   = $StartTime.ToUniversalTime()
        $model.Tags        = $Tags

        if ($PSCmdlet.ShouldProcess($null, 'Start Launch'))
        {
            $launch = $Service.StartLaunchAsync($model).GetAwaiter().GetResult()

            Get-RPLaunch -Service $Service -Id $launch.Id
        }
    }
    catch
    {
        ConvertFrom-RPException -ErrorRecord $_ | Write-Error
    }
}

<#
    .SYNOPSIS
        Start a new report portal test item.
 
    .DESCRIPTION
        Call the StartTestItemAsync() method on the service object to start a
        new test item in the report portal. The method will be invoked
        synchronously.
#>

function Start-RPTestItem
{
    [CmdletBinding(SupportsShouldProcess = $true)]
    [OutputType([ReportPortal.Client.Models.TestItem])]
    param
    (
        # The report portal service.
        [Parameter(Mandatory = $true)]
        [ReportPortal.Client.Service]
        $Service,

        # The report portal launch.
        [Parameter(Mandatory = $true)]
        [ReportPortal.Client.Models.Launch]
        $Launch,

        # The parent test item, can be null.
        [Parameter(Mandatory = $false)]
        [AllowNull()]
        [ReportPortal.Client.Models.TestItem]
        $Parent,

        # Test item name.
        [Parameter(Mandatory = $true)]
        [System.String]
        $Name,

        # Test item type.
        [Parameter(Mandatory = $true)]
        [ValidateSet('Suite', 'Test', 'Step')]
        [System.String]
        $Type,

        # Test item description.
        [Parameter(Mandatory = $false)]
        [System.String]
        $Description,

        # Test item start time.
        [Parameter(Mandatory = $false)]
        [System.DateTime]
        $StartTime = (Get-Date),

        # Test item tags.
        [Parameter(Mandatory = $false)]
        [System.String[]]
        $Tags
    )

    try
    {
        $model = [ReportPortal.Client.Requests.StartTestItemRequest]::new()
        $model.LaunchId    = $Launch.Id
        $model.Name        = $Name
        $model.Type        = $Type
        $model.Description = $Description
        $model.StartTime   = $StartTime.ToUniversalTime()
        $model.Tags        = $Tags

        if ($PSCmdlet.ShouldProcess($null, 'Start Test Item'))
        {
            if ($null -eq $Parent)
            {
                $testItem = $Service.StartTestItemAsync($model).GetAwaiter().GetResult()
            }
            else
            {
                $testItem = $Service.StartTestItemAsync($Parent.Id, $model).GetAwaiter().GetResult()
            }

            Get-RPTestItem -Service $Service -Id $testItem.Id
        }
    }
    catch
    {
        ConvertFrom-RPException -ErrorRecord $_ | Write-Error
    }
}

<#
    .SYNOPSIS
        Finish a previously started report portal launch.
 
    .DESCRIPTION
        Call the FinishLaunchAsync() method on the service object to finish the
        existing launch in the report portal. The method will be invoked
        synchronously.
#>

function Stop-RPLaunch
{
    [CmdletBinding(SupportsShouldProcess = $true)]
    [OutputType([ReportPortal.Client.Models.Launch])]
    param
    (
        # The report portal service.
        [Parameter(Mandatory = $true)]
        [ReportPortal.Client.Service]
        $Service,

        # The launch id to finish.
        [Parameter(Mandatory = $true, ParameterSetName = 'Id')]
        [System.String]
        $Id,

        # The launch to finish.
        [Parameter(Mandatory = $true, ParameterSetName = 'Launch')]
        [ReportPortal.Client.Models.Launch]
        $Launch,

        # Launch end time.
        [Parameter(Mandatory = $false)]
        [System.DateTime]
        $EndTime = (Get-Date),

        # Force the finish action.
        [Parameter(Mandatory = $false)]
        [switch]
        $Force,

        # Return the updated launch object.
        [Parameter(Mandatory = $false)]
        [switch]
        $PassThru
    )

    try
    {
        $model = [ReportPortal.Client.Requests.FinishLaunchRequest]::new()
        $model.EndTime = $EndTime.ToUniversalTime()

        if ($PSCmdlet.ParameterSetName -eq 'Launch')
        {
            $Id = $Launch.Id
        }

        if ($PSCmdlet.ShouldProcess($Id, 'Finish Launch'))
        {
            $Service.FinishLaunchAsync($Id, $model, $Force.IsPresent).GetAwaiter().GetResult() | Out-Null

            if ($PassThru.IsPresent)
            {
                Get-RPLaunch -Service $Service -Id $Id
            }
        }
    }
    catch
    {
        ConvertFrom-RPException -ErrorRecord $_ | Write-Error
    }
}

<#
    .SYNOPSIS
        Finish an existing report portal test item.
 
    .DESCRIPTION
        Call the FinishTestItemAsync() method on the service object to finish
        the existing launch in the report portal. The method will be invoked
        synchronously.
#>

function Stop-RPTestItem
{
    [CmdletBinding(SupportsShouldProcess = $true)]
    [OutputType([ReportPortal.Client.Models.TestItem])]
    param
    (
        # The report portal service.
        [Parameter(Mandatory = $true)]
        [ReportPortal.Client.Service]
        $Service,

        # The test item id to finish.
        [Parameter(Mandatory = $true, ParameterSetName = 'Id')]
        [System.String]
        $Id,

        # The test item to finish.
        [Parameter(Mandatory = $true, ParameterSetName = 'TestItem')]
        [ReportPortal.Client.Models.TestItem]
        $TestItem,

        # Test item end time.
        [Parameter(Mandatory = $false)]
        [System.DateTime]
        $EndTime = (Get-Date),

        # The test result.
        [Parameter(Mandatory = $false)]
        [ValidateSet('InProgress', 'Passed', 'Failed', 'Skipped', 'Interrupted')]
        [System.String]
        $Status = 'Passed',

        [Parameter(Mandatory = $false)]
        [System.String]
        $Description,

        # Return the updated test item object.
        [Parameter(Mandatory = $false)]
        [switch]
        $PassThru
    )

    try
    {
        $model = [ReportPortal.Client.Requests.FinishTestItemRequest]::new()
        $model.EndTime     = $EndTime.ToUniversalTime()
        $model.Status      = $Status
        $model.Description = $Description

        if ($PSCmdlet.ParameterSetName -eq 'TestItem')
        {
            $Id = $TestItem.Id
        }

        if ($PSCmdlet.ShouldProcess($Id, 'Finish Test Item'))
        {
            $Service.FinishTestItemAsync($Id, $model).GetAwaiter().GetResult() | Out-Null

            if ($PassThru.IsPresent)
            {
                Get-RPTestItem -Service $Service -Id $Id
            }
        }
    }
    catch
    {
        ConvertFrom-RPException -ErrorRecord $_ | Write-Error
    }
}

function ConvertFrom-RPException
{
    param
    (
        # Error record.
        [Parameter(Mandatory = $true, Position = 0)]
        [System.Management.Automation.ErrorRecord]
        $ErrorRecord
    )

    $message = $ErrorRecord.Exception.InnerException.Message
    $message = ([System.String] $message).Split("`n")[1]

    if ($message -match '^Response Body: (?<Error>.*)$')
    {
        $rpError = $Matches['Error'] | Convertfrom-Json

        $exception     = [System.Exception]::new($rpError.message)
        $errorCategory = [System.Management.Automation.ErrorCategory]::NotSpecified

        [System.Management.Automation.ErrorRecord]::new($exception, $rpError.error_code, $errorCategory, $ErrorRecord.TargetObject)
    }
    else
    {
        Write-Output $ErrorRecord
    }
}