tests/RestCall.Tests.ps1



# This file tests CMDLets that wrap REST API calls with standard tests.
# WHAT THESE TESTS COVER
# * The correct REST method is called
# * The content type is set correctly
# * The URI is correctly formed
# * A body is only passed when using a Post method
# * When a body is passed, it contains the expected attributes
#
# ADDING TESTS
# To add a CMDLet to test, create a new pscustom object in the TestCases array in RestCall.TestsCases.ps1.
# Make sure to include the Module name, Method, and any Params that should be passed when the CMDLet is run.
#
# OTHER TESTS
# All tests for additional coverage should be placed in the test file associated with the CMDLet's module.

BeforeAll {
  Import-Module '.\NewRelicPS.AlertPolicies.psm1' -Force
  Import-Module '.\NewRelicPS.NotificationChannels.psm1' -Force
  Import-Module '.\NewRelicPS.Dashboards.psm1' -Force
  Import-Module '.\NewRelicPS.NRQLConditions.psm1' -Force
  Import-Module '.\NewRelicPS.SyntheticMonitors.psm1' -Force
  Import-Module '.\NewRelicPS.SyntheticLocationConditions.psm1' -Force
  Import-Module '.\NewRelicPS.SyntheticSecureCredentials.psm1' -Force
}
Describe 'REST API wrapper CMDLets' {
  # Get list of test cases
  $testCases = & ".\tests\testCases\RestCalls.ps1"

  BeforeAll {
    Function Start-CMDLet {
      param(
        $ModuleName,
        $CMDLet
      )

      # Mock is created inside the IT because the module name may change
      Mock Invoke-RestMethod -ModuleName $ModuleName {}
      & $CMDLet @Params
    }
  }

  Context 'All wrapper CMDLets' {

    It '<CMDLET>: Has a valid URI' -TestCases $testCases {
      Start-CMDLet -ModuleName $ModuleName -CMDLet $CMDLet
      Assert-MockCalled Invoke-RestMethod -ModuleName $ModuleName -ParameterFilter {
        $uri -match $ExpectedURL
      }
    }

    # Every call must have API key in headers
    It '<CMDLet>: Has required auth data in headers' -TestCases $testCases {
      Start-CMDLet -ModuleName $ModuleName -CMDLet $CMDLet

      # GraphQL query API has a static URL and requires a different type of API Key
      If ('https://api.newrelic.com/graphql' -match $ExpectedURL ) {
        $KeyType = 'API-Key'
      }
      Else {
        $KeyType = 'X-API-Key'
      }
      Assert-MockCalled Invoke-RestMethod -ModuleName $ModuleName -ParameterFilter {
        $headers.$KeyType -eq $Params.APIKey
      }
    }
  }

  Context 'CMDLets wrapping Get method calls' {

    It '<CMDLet>: Uses Get Method' -TestCases ($testCases | Where-Object { $_.Method -eq 'Get' }) {
      Start-CMDLet -ModuleName $ModuleName -CMDLet $CMDLet
      Assert-MockCalled Invoke-RestMethod -ModuleName $ModuleName -ParameterFilter {
        $method -eq 'Get'
      }
    }

    It '<CMDLet>: Has no body' -TestCases ($TestCases | Where-Object { $_.Method -eq 'Get' }) {
      Start-CMDLet -ModuleName $ModuleName -CMDLet $CMDLet
      Assert-MockCalled Invoke-RestMethod -ModuleName $ModuleName -ParameterFilter {
        $null -eq $body
      }
    }
  }

  Context 'CMDLets wrapping Post method calls' {

    It '<CMDLet>: Has a valid body' -TestCases ($testCases | Where-Object { $_.Method -eq 'Post' -and $null -ne $_.BodyTests }) {

      # Verify each of the items listed in BodyTests is passed into the Invoke-RestMethod call as expected
      foreach ($key in $BodyTests.Keys) {
        Start-CMDLet -ModuleName $ModuleName -CMDLet $CMDLet
        Assert-MockCalled Invoke-RestMethod -ModuleName $ModuleName -ParameterFilter {
          ($body | ConvertFrom-Json).$key -eq $BodyTests[$key] | ConvertTo-Json
        }
      }
    }

    It '<CMDLet>: Is using the correct content type' -TestCases ($testCases | Where-Object { $_.Method -eq 'Post' }) {
      Start-CMDLet -ModuleName $ModuleName -CMDLet $CMDLet
      Assert-MockCalled Invoke-RestMethod -ModuleName $ModuleName -ParameterFilter {
        $contentType -eq 'application/json'
      }
    }

    It '<CMDLet>: Uses Post Method' -TestCases ($testCases | Where-Object { $_.Method -eq 'Post' }) {
      Start-CMDLet -ModuleName $ModuleName -CMDLet $CMDLet
      Assert-MockCalled Invoke-RestMethod -ModuleName $ModuleName -ParameterFilter {
        $method -eq 'Post'
      }
    }
    It '<CMDLet>: Has a body' -TestCases ($testCases | Where-Object { $_.Method -eq 'Post' }) {
      Start-CMDLet -ModuleName $ModuleName -CMDLet $CMDLet
      Assert-MockCalled Invoke-RestMethod -ModuleName $ModuleName -ParameterFilter {
        $null -ne $body
      }
    }
  }

  Context 'CMDLets wrapping Put method calls' {

    It '<CMDLet>: Is using the correct content type' -TestCases ($testCases | Where-Object { $_.Method -eq 'Put' }) {
      Start-CMDLet -ModuleName $ModuleName -CMDLet $CMDLet
      Assert-MockCalled Invoke-RestMethod -ModuleName $ModuleName -ParameterFilter {
        $contentType -eq 'application/json'
      }
    }
    It '<CMDLet>: Uses Post Method' -TestCases ($testCases | Where-Object { $_.Method -eq 'Put' }) {
      Start-CMDLet -ModuleName $ModuleName -CMDLet $CMDLet
      Assert-MockCalled Invoke-RestMethod -ModuleName $ModuleName -ParameterFilter {
        $method -eq 'Put'
      }
    }
  }

  Context 'CMDlets wrapping Delete method calls' {
    It '<CMDLet>: Uses Delete Method' -TestCases ($testCases | Where-Object { $_.Method -eq 'Delete' }) {
      Start-CMDLet -ModuleName $ModuleName -CMDLet $CMDLet
      Assert-MockCalled Invoke-RestMethod -ModuleName $ModuleName -ParameterFilter {
        $Method -eq 'Delete'
      }
    }
    It '<CMDLet>: Has no body' -TestCases ($testCases | Where-Object { $_.Method -eq 'Delete' }) {
      Start-CMDLet -ModuleName $ModuleName -CMDLet $CMDLet
      Assert-MockCalled Invoke-RestMethod -ModuleName $ModuleName -ParameterFilter {
        $null -eq $Body
      }
    }
  }
}