diff --git a/CHANGELOG.md b/CHANGELOG.md index 65f9d6bbc6..eb97558e47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,9 +7,13 @@ * AADServicePrincipal * Fixes comparison of assigned roles for null values. FIXES [#5717](https://github.com/microsoft/Microsoft365DSC/issues/5717) +* CommerceSelfServicePurchase + * Initial release. * MISC * Changed the CIMInstance logic of various resources to us common logic. * Added support for specifying a proxy in Update-M365DSCModule. +* DEPENDENCIES + * Updated MSCloudLoginAssistant to version 1.1.36. # 1.25.129.3 diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_CommerceSelfServicePurchase/MSFT_CommerceSelfServicePurchase.psm1 b/Modules/Microsoft365DSC/DSCResources/MSFT_CommerceSelfServicePurchase/MSFT_CommerceSelfServicePurchase.psm1 new file mode 100644 index 0000000000..4e3bde1a8d --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_CommerceSelfServicePurchase/MSFT_CommerceSelfServicePurchase.psm1 @@ -0,0 +1,381 @@ +function Get-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $ProductId, + + [Parameter(Mandatory = $true)] + [System.String] + $ProductName, + + [Parameter()] + [ValidateSet('Enabled', 'Disabled', 'OnlyTrialsWithoutPaymentMethod')] + [System.String] + $PolicyValue, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + New-M365DSCConnection -Workload 'Licensing' ` + -InboundParameters $PSBoundParameters | Out-Null + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $nullResult = $PSBoundParameters + $nullResult.Ensure = 'Absent' + try + { + if ($null -ne $Script:exportedInstances -and $Script:ExportMode) + { + $instance = $Script:exportedInstances.items | Where-Object -FilterScript {$_.ProductId -eq $ProductId} + } + else + { + $uri = (Get-MSCloudLoginConnectionProfile -Workload 'Licensing').HostUrl + "/v1/policies/AllowSelfServicePurchase/products/$($ProductId)" + $instance = Invoke-M365DSCLicensingWebRequest -Uri $uri -Method 'GET' + } + + if ($null -eq $instance) + { + return $nullResult + } + + $results = @{ + ProductId = $instance.ProductId + ProductName = $instance.ProductName + PolicyValue = $instance.PolicyValue + Ensure = 'Present' + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + return [System.Collections.Hashtable] $results + } + catch + { + Write-Verbose -Message $_ + New-M365DSCLogEntry -Message 'Error retrieving data:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return $nullResult + } +} + +function Set-TargetResource +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $ProductId, + + [Parameter(Mandatory = $true)] + [System.String] + $ProductName, + + [Parameter()] + [System.String] + [ValidateSet('Enabled', 'Disabled', 'OnlyTrialsWithoutPaymentMethod')] + $PolicyValue, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $currentInstance = Get-TargetResource @PSBoundParameters + $setParameters = Remove-M365DSCAuthenticationParameter -BoundParameters $PSBoundParameters + + if ($Ensure -eq 'Absent') + { + throw "Ensure cannot be absent. This resource can only update existing Self Service Purchase Policies." + } + + $uri = (Get-MSCloudLoginConnectionProfile -Workload 'Licensing').HostUrl + "/v1/policies/AllowSelfServicePurchase/products/$($ProductId)" + $body = @{ + policyValue = $PolicyValue + } + Write-Verbose -Message "Updating Policy for {$ProductName} to value {$PolicyValue}" + Invoke-M365DSCLicensingWebRequest -Uri $uri -Method 'PUT' -Body $body | Out-Null +} + +function Test-TargetResource +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $ProductId, + + [Parameter(Mandatory = $true)] + [System.String] + $ProductName, + + [Parameter()] + [System.String] + [ValidateSet('Enabled', 'Disabled', 'OnlyTrialsWithoutPaymentMethod')] + $PolicyValue, + + [Parameter()] + [ValidateSet('Present', 'Absent')] + [System.String] + $Ensure = 'Present', + + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + $CurrentValues = Get-TargetResource @PSBoundParameters + $ValuesToCheck = ([Hashtable]$PSBoundParameters).Clone() + + Write-Verbose -Message "Current Values: $(Convert-M365DscHashtableToString -Hashtable $CurrentValues)" + Write-Verbose -Message "Target Values: $(Convert-M365DscHashtableToString -Hashtable $ValuesToCheck)" + + $testResult = Test-M365DSCParameterState -CurrentValues $CurrentValues ` + -Source $($MyInvocation.MyCommand.Source) ` + -DesiredValues $PSBoundParameters ` + -ValuesToCheck $ValuesToCheck.Keys + + Write-Verbose -Message "Test-TargetResource returned $testResult" + + return $testResult +} + +function Export-TargetResource +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter()] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.Management.Automation.PSCredential] + $ApplicationSecret, + + [Parameter()] + [System.String] + $CertificateThumbprint, + + [Parameter()] + [Switch] + $ManagedIdentity, + + [Parameter()] + [System.String[]] + $AccessTokens + ) + + $ConnectionMode = New-M365DSCConnection -Workload 'Licensing' ` + -InboundParameters $PSBoundParameters + + #Ensure the proper dependencies are installed in the current environment. + Confirm-M365DSCDependencies + + #region Telemetry + $ResourceName = $MyInvocation.MyCommand.ModuleName.Replace('MSFT_', '') + $CommandName = $MyInvocation.MyCommand + $data = Format-M365DSCTelemetryParameters -ResourceName $ResourceName ` + -CommandName $CommandName ` + -Parameters $PSBoundParameters + Add-M365DSCTelemetryEvent -Data $data + #endregion + + try + { + $Script:ExportMode = $true + $uri = (Get-MSCloudLoginConnectionProfile -Workload 'Licensing').HostUrl + '/v1/policies/AllowSelfServicePurchase/products' + [array] $Script:exportedInstances = Invoke-M365DSCLicensingWebRequest -Uri $uri -Method 'GET' + + $i = 1 + $dscContent = '' + if ($Script:exportedInstances.Length -eq 0) + { + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + else + { + Write-Host "`r`n" -NoNewline + } + foreach ($config in $Script:exportedInstances.items) + { + if ($null -ne $Global:M365DSCExportResourceInstancesCount) + { + $Global:M365DSCExportResourceInstancesCount++ + } + + $displayedKey = $config.ProductName + Write-Host " |---[$i/$($Script:exportedInstances.items.Count)] $displayedKey" -NoNewline + $params = @{ + ProductId = $config.productId + ProductName = $config.productName + Credential = $Credential + ApplicationId = $ApplicationId + TenantId = $TenantId + CertificateThumbprint = $CertificateThumbprint + ManagedIdentity = $ManagedIdentity.IsPresent + AccessTokens = $AccessTokens + } + + $Results = Get-TargetResource @Params + $Results = Update-M365DSCExportAuthenticationResults -ConnectionMode $ConnectionMode ` + -Results $Results + + $currentDSCBlock = Get-M365DSCExportContentForResource -ResourceName $ResourceName ` + -ConnectionMode $ConnectionMode ` + -ModulePath $PSScriptRoot ` + -Results $Results ` + -Credential $Credential + $dscContent += $currentDSCBlock + Save-M365DSCPartialExport -Content $currentDSCBlock ` + -FileName $Global:PartialExportFileName + $i++ + Write-Host $Global:M365DSCEmojiGreenCheckMark + } + return $dscContent + } + catch + { + Write-Host $Global:M365DSCEmojiRedX + + New-M365DSCLogEntry -Message 'Error during Export:' ` + -Exception $_ ` + -Source $($MyInvocation.MyCommand.Source) ` + -TenantId $TenantId ` + -Credential $Credential + + return '' + } +} + +Export-ModuleMember -Function *-TargetResource diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_CommerceSelfServicePurchase/MSFT_CommerceSelfServicePurchase.schema.mof b/Modules/Microsoft365DSC/DSCResources/MSFT_CommerceSelfServicePurchase/MSFT_CommerceSelfServicePurchase.schema.mof new file mode 100644 index 0000000000..ff3351516e --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_CommerceSelfServicePurchase/MSFT_CommerceSelfServicePurchase.schema.mof @@ -0,0 +1,15 @@ +[ClassVersion("1.0.0.0"), FriendlyName("CommerceSelfServicePurchase")] +class MSFT_CommerceSelfServicePurchase : OMI_BaseResource +{ + [Key, Description("Unique ID of the product.")] String ProductId; + [Write, Description("Name of the product")] String ProductName; + [Write, Description("Can be Enabled or Disabled."), ValueMap{"Enabled","Disabled", "OnlyTrialsWithoutPaymentMethod"}, Values{"Enabled","Disabled", "OnlyTrialsWithoutPaymentMethod"}] String PolicyValue; + + [Write, Description("Present ensures the instance exists, absent ensures it is removed."), ValueMap{"Absent","Present"}, Values{"Absent","Present"}] string Ensure; + [Write, Description("Credentials of the workload's Admin"), EmbeddedInstance("MSFT_Credential")] string Credential; + [Write, Description("Id of the Azure Active Directory application to authenticate with.")] String ApplicationId; + [Write, Description("Id of the Azure Active Directory tenant used for authentication.")] String TenantId; + [Write, Description("Thumbprint of the Azure Active Directory application's authentication certificate to use for authentication.")] String CertificateThumbprint; + [Write, Description("Managed ID being used for authentication.")] Boolean ManagedIdentity; + [Write, Description("Access token used for authentication.")] String AccessTokens[]; +}; diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_CommerceSelfServicePurchase/readme.md b/Modules/Microsoft365DSC/DSCResources/MSFT_CommerceSelfServicePurchase/readme.md new file mode 100644 index 0000000000..d5244037e0 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_CommerceSelfServicePurchase/readme.md @@ -0,0 +1,6 @@ + +# CommerceSelfServicePurchase + +## Description + +Manages the Self Purchase policies in commerce. diff --git a/Modules/Microsoft365DSC/DSCResources/MSFT_CommerceSelfServicePurchase/settings.json b/Modules/Microsoft365DSC/DSCResources/MSFT_CommerceSelfServicePurchase/settings.json new file mode 100644 index 0000000000..e79b4e3f34 --- /dev/null +++ b/Modules/Microsoft365DSC/DSCResources/MSFT_CommerceSelfServicePurchase/settings.json @@ -0,0 +1,25 @@ +{ + "resourceName": "CommerceSelfServicePurchase", + "description": "Manages the Self Purchase policies in commerce.", + "roles": {}, + "permissions": { + "aeb86249-8ea3-49e2-900b-54cc8e308f85": { + "delegated": { + "read": [], + "update": [] + }, + "application": { + "read": [ + { + "name": "Policy.Read.AllowSelfServicePurchase" + } + ], + "update": [ + { + "name": "Policy.ReadWrite.AllowSelfServicePurchase" + } + ] + } + } + } +} diff --git a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 index b8b8009b49..75ba341060 100644 --- a/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 +++ b/Modules/Microsoft365DSC/Dependencies/Manifest.psd1 @@ -122,7 +122,7 @@ }, @{ ModuleName = "MSCloudLoginAssistant" - RequiredVersion = "1.1.35" + RequiredVersion = "1.1.36" }, @{ ModuleName = 'PnP.PowerShell' diff --git a/Modules/Microsoft365DSC/Examples/Resources/CommerceSelfServicePurchase/2-Update.ps1 b/Modules/Microsoft365DSC/Examples/Resources/CommerceSelfServicePurchase/2-Update.ps1 new file mode 100644 index 0000000000..527caf2fd9 --- /dev/null +++ b/Modules/Microsoft365DSC/Examples/Resources/CommerceSelfServicePurchase/2-Update.ps1 @@ -0,0 +1,35 @@ +<# +This example is used to test new resources and showcase the usage of new resources being worked on. +It is not meant to use as a production baseline. +#> + +Configuration Example +{ + param( + [Parameter()] + [System.String] + $ApplicationId, + + [Parameter()] + [System.String] + $TenantId, + + [Parameter()] + [System.String] + $CertificateThumbprint + ) + Import-DscResource -ModuleName Microsoft365DSC + node localhost + { + CommerceSelfServicePurchase "Power Apps per user" + { + ApplicationId = $ApplicationId; + CertificateThumbprint = $CertificateThumbprint; + Ensure = "Present"; + PolicyValue = "Enabled"; + ProductId = "CFQ7TTC0LH2H"; + ProductName = "Power Apps per user"; + TenantId = $TenantId; + } + } +} diff --git a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 index 2ca6216f5a..e6cf6d519d 100644 --- a/Modules/Microsoft365DSC/Microsoft365DSC.psd1 +++ b/Modules/Microsoft365DSC/Microsoft365DSC.psd1 @@ -84,6 +84,7 @@ 'Modules/WorkloadHelpers/M365DSCAzureDevOPSHelper.psm1', 'Modules/WorkloadHelpers/M365DSCDefenderHelper.psm1', 'Modules/WorkloadHelpers/M365DSCFabricHelper.psm1', + 'Modules/WorkloadHelpers/M365DSCLicensingHelper.psm1', 'Modules/M365DSCConfigurationHelper.psm1' ) diff --git a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 index c1bb6c1add..a1e21f45cc 100644 --- a/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 +++ b/Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1 @@ -1881,7 +1881,7 @@ function New-M365DSCConnection param ( [Parameter(Mandatory = $true)] - [ValidateSet('AdminAPI', 'Azure', 'AzureDevOPS', 'DefenderForEndPoint', 'ExchangeOnline', 'Fabric', 'Intune', ` + [ValidateSet('AdminAPI', 'Azure', 'AzureDevOPS', 'DefenderForEndPoint', 'ExchangeOnline', 'Fabric', 'Intune', 'Licensing', ` 'SecurityComplianceCenter', 'PnP', 'PowerPlatforms', ` 'MicrosoftTeams', 'MicrosoftGraph', 'SharePointOnlineREST', 'Tasks', 'AdminAPI')] [System.String] diff --git a/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCLicensingHelper.psm1 b/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCLicensingHelper.psm1 new file mode 100644 index 0000000000..0f3d582353 --- /dev/null +++ b/Modules/Microsoft365DSC/Modules/WorkloadHelpers/M365DSCLicensingHelper.psm1 @@ -0,0 +1,37 @@ +function Invoke-M365DSCLicensingWebRequest +{ + [OutputType([PSCustomObject])] + [CmdletBinding()] + param( + [Parameter(Mandatory = $true)] + [System.String] + $Uri, + + [Parameter()] + [System.String] + $Method = 'GET', + + [Parameter()] + [System.Collections.Hashtable] + $Body + ) + + $headers = @{ + Authorization = (Get-MSCloudLoginConnectionProfile -Workload 'Licensing').AccessToken + } + + $bodyValue = $null + if (-not [System.String]::IsNullOrEmpty($Body)) + { + $bodyValue = ConvertTo-Json $Body -Depth 10 -Compress + } + + $response = Invoke-WebRequest -Method $Method ` + -Uri $Uri ` + -Headers $headers ` + -Body $bodyValue ` + -ContentType 'application/json' ` + -UseBasicParsing + $result = ConvertFrom-Json $response.Content + return $result +} diff --git a/Tests/Unit/Microsoft365DSC/Microsoft365DSC.CommerceSelfServicePurchase.Tests.ps1 b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.CommerceSelfServicePurchase.Tests.ps1 new file mode 100644 index 0000000000..4ed6ad62f0 --- /dev/null +++ b/Tests/Unit/Microsoft365DSC/Microsoft365DSC.CommerceSelfServicePurchase.Tests.ps1 @@ -0,0 +1,152 @@ +[CmdletBinding()] +param( +) +$M365DSCTestFolder = Join-Path -Path $PSScriptRoot ` + -ChildPath '..\..\Unit' ` + -Resolve +$CmdletModule = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Microsoft365.psm1' ` + -Resolve) +$GenericStubPath = (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\Stubs\Generic.psm1' ` + -Resolve) +Import-Module -Name (Join-Path -Path $M365DSCTestFolder ` + -ChildPath '\UnitTestHelper.psm1' ` + -Resolve) + +$CurrentScriptPath = $PSCommandPath.Split('\') +$CurrentScriptName = $CurrentScriptPath[$CurrentScriptPath.Length -1] +$ResourceName = $CurrentScriptName.Split('.')[1] +$Global:DscHelper = New-M365DscUnitTestHelper -StubModule $CmdletModule ` + -DscResource $ResourceName -GenericStubModule $GenericStubPath + +Describe -Name $Global:DscHelper.DescribeHeader -Fixture { + InModuleScope -ModuleName $Global:DscHelper.ModuleName -ScriptBlock { + Invoke-Command -ScriptBlock $Global:DscHelper.InitializeScript -NoNewScope + BeforeAll { + + $secpasswd = ConvertTo-SecureString (New-Guid | Out-String) -AsPlainText -Force + $Credential = New-Object System.Management.Automation.PSCredential ('tenantadmin@mydomain.com', $secpasswd) + + Mock -CommandName Confirm-M365DSCDependencies -MockWith { + } + + Mock -CommandName New-M365DSCConnection -MockWith { + return "Credentials" + } + + # Mock Write-Host to hide output during the tests + Mock -CommandName Write-Host -MockWith { + } + $Script:exportedInstances =$null + $Script:ExportMode = $false + } + # Test contexts + Context -Name "The instance should exist but it DOES NOT" -Fixture { + BeforeAll { + $testParams = @{ + PolicyValue = "Enabled"; + ProductId = "CFQ7TTC0LH2H"; + ProductName = "Power Apps per user"; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Invoke-M365DSCLicensingWebRequest -MockWith { + return $null + } + } + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Absent' + } + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + } + + Context -Name "The instance exists and values are already in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + PolicyValue = "Enabled"; + ProductId = "CFQ7TTC0LH2H"; + ProductName = "Power Apps per user"; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Invoke-M365DSCLicensingWebRequest -MockWith { + return @{ + policyValue = "Enabled" + productId = "CFQ7TTC0LH2H"; + productName = "Power Apps per user"; + } + } + } + + It 'Should return true from the Test method' { + Test-TargetResource @testParams | Should -Be $true + } + } + + Context -Name "The instance exists and values are NOT in the desired state" -Fixture { + BeforeAll { + $testParams = @{ + PolicyValue = "Enabled"; + ProductId = "CFQ7TTC0LH2H"; + ProductName = "Power Apps per user"; + Ensure = 'Present' + Credential = $Credential; + } + + Mock -CommandName Invoke-M365DSCLicensingWebRequest -MockWith { + return @{ + policyValue = "Disabled" # Drift + productId = "CFQ7TTC0LH2H"; + productName = "Power Apps per user"; + } + } + } + + It 'Should return Values from the Get method' { + (Get-TargetResource @testParams).Ensure | Should -Be 'Present' + } + + It 'Should return false from the Test method' { + Test-TargetResource @testParams | Should -Be $false + } + + It 'Should call the Set method' { + Set-TargetResource @testParams + Should -Invoke -CommandName Invoke-M365DSCLicensingWebRequest -Exactly 2 + } + } + + Context -Name 'ReverseDSC Tests' -Fixture { + BeforeAll { + $Global:CurrentModeIsExport = $true + $Global:PartialExportFileName = "$(New-Guid).partial.ps1" + $testParams = @{ + Credential = $Credential; + } + + Mock -CommandName Invoke-M365DSCLicensingWebRequest -MockWith { + return @{ + items = @( + @{ + policyValue = "Enabled" + productId = "CFQ7TTC0LH2H"; + productName = "Power Apps per user"; + } + ) + } + } + } + It 'Should Reverse Engineer resource from the Export method' { + $result = Export-TargetResource @testParams + $result | Should -Not -BeNullOrEmpty + } + } + } +} + +Invoke-Command -ScriptBlock $Global:DscHelper.CleanupScript -NoNewScope