diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9139ba9..61c03d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,50 +1,54 @@ name: CI -permissions: - checks: write - pull-requests: write - contents: read on: push: - branches: [master] + branches: [ master ] paths: - - 'PSDepend/**' - - 'Tests/**' - - 'build.ps1' - - 'psakeFile.ps1' - - 'requirements.psd1' + - "PSDepend/**" + - "Tests/**" + - "build.ps1" + - "psakeFile.ps1" + - "requirements.psd1" pull_request: paths: - - 'PSDepend/**' - - 'Tests/**' - - 'build.ps1' - - 'psakeFile.ps1' - - 'requirements.psd1' + - "PSDepend/**" + - "Tests/**" + - "build.ps1" + - "psakeFile.ps1" + - "requirements.psd1" workflow_dispatch: jobs: test: name: Test (${{ matrix.os }}) runs-on: ${{ matrix.os }} + permissions: + contents: read strategy: fail-fast: false matrix: - os: [ubuntu-latest, windows-latest, macOS-latest] + os: [ ubuntu-latest, windows-latest, macOS-latest ] steps: - uses: actions/checkout@v4 - - name: Bootstrap and Test + - name: Bootstrap shell: pwsh - run: ./build.ps1 -Bootstrap -Task Test + run: ./build.ps1 -Bootstrap -Task Init + - name: Test + shell: pwsh + run: ./build.ps1 -Task Test - name: Upload Test Results if: always() uses: actions/upload-artifact@v4 with: name: testResults-${{ matrix.os }} - path: ./Output/testResults.xml + path: ./Tests/out/testResults.xml publish-test-results: name: Publish Test Results needs: test runs-on: ubuntu-latest + permissions: + checks: write + pull-requests: write if: ${{ !cancelled() }} steps: - uses: actions/download-artifact@v4 diff --git a/.gitignore b/.gitignore index 6f437ab..6e28a6d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ -nuget.exe \ No newline at end of file +nuget.exe +Output/** +Tests/Output/** +Tests/out/** \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json index 54c8569..67d2203 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,5 +3,7 @@ "powershell.codeFormatting.ignoreOneLineBlock": false, "powershell.codeFormatting.whitespaceAfterSeparator": false, "powershell.codeFormatting.whitespaceAroundOperator": false, - "powershell.codeFormatting.whitespaceBeforeOpenParen": false -} + "powershell.codeFormatting.whitespaceBeforeOpenParen": false, + "powershell.codeFormatting.preset": "OTBS", + "powershell.codeFormatting.trimWhitespaceAroundPipe": true +} \ No newline at end of file diff --git a/PSDepend/PSDepend.psd1 b/PSDepend/PSDepend.psd1 index 51e044d..6e1f918 100644 --- a/PSDepend/PSDepend.psd1 +++ b/PSDepend/PSDepend.psd1 @@ -1,111 +1,111 @@ @{ -# Script module or binary module file associated with this manifest. -RootModule = 'PSDepend.psm1' + # Script module or binary module file associated with this manifest. + RootModule = 'PSDepend.psm1' -# Version number of this module. -ModuleVersion = '0.3.0' + # Version number of this module. + ModuleVersion = '0.3.0' -# ID used to uniquely identify this module -GUID = '63ea9e2a-320d-43ff-a11a-4930ca03cce6' + # ID used to uniquely identify this module + GUID = '63ea9e2a-320d-43ff-a11a-4930ca03cce6' -# Author of this module -Author = 'Warren Frame' + # Author of this module + Author = 'Warren Frame' -# Company or vendor of this module -#CompanyName = 'Unknown' + # Company or vendor of this module + #CompanyName = 'Unknown' -# Copyright statement for this module -Copyright = '(c) 2016 Warren F. All rights reserved.' + # Copyright statement for this module + Copyright = '(c) 2016 Warren F. All rights reserved.' -# Description of the functionality provided by this module -Description = 'PowerShell Dependency Handler' + # Description of the functionality provided by this module + Description = 'PowerShell Dependency Handler' -# Minimum version of the Windows PowerShell engine required by this module -PowerShellVersion = '3.0' + # Minimum version of the Windows PowerShell engine required by this module + PowerShellVersion = '3.0' -# Name of the Windows PowerShell host required by this module -# PowerShellHostName = '' + # Name of the Windows PowerShell host required by this module + # PowerShellHostName = '' -# Minimum version of the Windows PowerShell host required by this module -# PowerShellHostVersion = '' + # Minimum version of the Windows PowerShell host required by this module + # PowerShellHostVersion = '' -# Minimum version of Microsoft .NET Framework required by this module -# DotNetFrameworkVersion = '' + # Minimum version of Microsoft .NET Framework required by this module + # DotNetFrameworkVersion = '' -# Minimum version of the common language runtime (CLR) required by this module -# CLRVersion = '' + # Minimum version of the common language runtime (CLR) required by this module + # CLRVersion = '' -# Processor architecture (None, X86, Amd64) required by this module -# ProcessorArchitecture = '' + # Processor architecture (None, X86, Amd64) required by this module + # ProcessorArchitecture = '' -# Modules that must be imported into the global environment prior to importing this module -# RequiredModules = @() + # Modules that must be imported into the global environment prior to importing this module + # RequiredModules = @() -# Assemblies that must be loaded prior to importing this module -# RequiredAssemblies = @() + # Assemblies that must be loaded prior to importing this module + # RequiredAssemblies = @() -# Script files (.ps1) that are run in the caller's environment prior to importing this module. -# ScriptsToProcess = @() + # Script files (.ps1) that are run in the caller's environment prior to importing this module. + # ScriptsToProcess = @() -# Type files (.ps1xml) to be loaded when importing this module -# TypesToProcess = @() + # Type files (.ps1xml) to be loaded when importing this module + # TypesToProcess = @() -# Format files (.ps1xml) to be loaded when importing this module -FormatsToProcess = 'PSDepend.Format.ps1xml' + # Format files (.ps1xml) to be loaded when importing this module + FormatsToProcess = 'PSDepend.Format.ps1xml' -# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess -# NestedModules = @() + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + # NestedModules = @() -# Functions to export from this module -FunctionsToExport = @('Get-Dependency','Get-PSDependScript','Get-PSDependType','Import-Dependency','Install-Dependency','Invoke-DependencyScript','Invoke-PSDepend','Test-Dependency') + # Functions to export from this module + FunctionsToExport = @('Get-Dependency','Get-PSDependScript','Get-PSDependType','Import-Dependency','Install-Dependency','Invoke-DependencyScript','Invoke-PSDepend','Test-Dependency') -# Cmdlets to export from this module -CmdletsToExport = '*' + # Cmdlets to export from this module + CmdletsToExport = '*' -# Variables to export from this module -# VariablesToExport = '*' + # Variables to export from this module + # VariablesToExport = '*' -# Aliases to export from this module -AliasesToExport = '*' + # Aliases to export from this module + AliasesToExport = '*' -# DSC resources to export from this module -# DscResourcesToExport = @() + # DSC resources to export from this module + # DscResourcesToExport = @() -# List of all modules packaged with this module -# ModuleList = @() + # List of all modules packaged with this module + # ModuleList = @() -# List of all files packaged with this module -# FileList = @() + # List of all files packaged with this module + # FileList = @() -# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. -PrivateData = @{ + # Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. + PrivateData = @{ - PSData = @{ + PSData = @{ - # Tags applied to this module. These help with module discovery in online galleries. - Tags = @('requirements', 'dependencies', 'dependency', 'manager', 'bundle', 'package') + # Tags applied to this module. These help with module discovery in online galleries. + Tags = @('requirements', 'dependencies', 'dependency', 'manager', 'bundle', 'package') - # A URL to the license for this module. - LicenseUri = 'https://github.com/RamblingCookieMonster/PSDepend/blob/master/LICENSE' + # A URL to the license for this module. + LicenseUri = 'https://github.com/PowerShellOrg/PSDepend/blob/master/LICENSE' - # A URL to the main website for this project. - ProjectUri = 'https://github.com/RamblingCookieMonster/PSDepend/' + # A URL to the main website for this project. + ProjectUri = 'https://github.com/PowerShellOrg/PSDepend/' - # A URL to an icon representing this module. - # IconUri = '' + # A URL to an icon representing this module. + # IconUri = '' - # ReleaseNotes of this module - ReleaseNotes = 'Added various PowerShell Core fixes thanks to @lipkau!' + # ReleaseNotes of this module + ReleaseNotes = 'Added various PowerShell Core fixes thanks to @lipkau!' - } # End of PSData hashtable + } # End of PSData hashtable -} # End of PrivateData hashtable + } # End of PrivateData hashtable -# HelpInfo URI of this module -# HelpInfoURI = '' + # HelpInfo URI of this module + # HelpInfoURI = '' -# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. -# DefaultCommandPrefix = '' + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + # DefaultCommandPrefix = '' } diff --git a/PSDepend/Private/Get-ClonedObject.ps1 b/PSDepend/Private/Get-ClonedObject.ps1 index 77ba56c..502cd2b 100644 --- a/PSDepend/Private/Get-ClonedObject.ps1 +++ b/PSDepend/Private/Get-ClonedObject.ps1 @@ -1,10 +1,41 @@ -# Idea from http://stackoverflow.com/questions/7468707/deep-copy-a-dictionary-hashtable-in-powershell -# borrowed from http://stackoverflow.com/questions/8982782/does-anyone-have-a-dependency-graph-and-topological-sorting-code-snippet-for-pow function Get-ClonedObject { + <# + .SYNOPSIS + Clones + + .DESCRIPTION + Creates a deep copy of the provided object. This is useful for cloning + dependency objects before passing them to dependency scripts, allowing + modifications to the clone without affecting the original object. + + .PARAMETER DeepCopyObject + The source object to copy from. + + .EXAMPLE + Get-ClonedObject $MyObject + + Get a deep copy of $MyObject. This is used to clone dependency objects + before passing them to dependency scripts, so that we can modify the object + without affecting the original. + + .NOTES + Idea from https://stackoverflow.com/a/7475744 + borrowed from https://stackoverflow.com/q/8982782 + + BinaryFormatter was removed in .NET 7; use a recursive hashtable clone + instead + #> param($DeepCopyObject) - $memStream = new-object IO.MemoryStream - $formatter = new-object Runtime.Serialization.Formatters.Binary.BinaryFormatter - $formatter.Serialize($memStream,$DeepCopyObject) - $memStream.Position=0 - $formatter.Deserialize($memStream) + $clone = @{} + foreach ($key in $DeepCopyObject.Keys) { + $val = $DeepCopyObject[$key] + if ($val -is [hashtable]) { + $clone[$key] = Get-ClonedObject $val + } elseif ($val -is [array]) { + $clone[$key] = $val.Clone() + } else { + $clone[$key] = $val + } + } + $clone } \ No newline at end of file diff --git a/PSDepend/Private/Test-PlatformSupport.ps1 b/PSDepend/Private/Test-PlatformSupport.ps1 index a88370a..34eec5e 100644 --- a/PSDepend/Private/Test-PlatformSupport.ps1 +++ b/PSDepend/Private/Test-PlatformSupport.ps1 @@ -1,18 +1,22 @@ function Test-PlatformSupport { - [cmdletbinding()] + [CmdletBinding()] param( $Type, - [string[]]$Support + [string[]] + $Support ) # test core/full if('Core' -eq $PSVersionTable.PSEdition) { - if($Support -notcontains 'core') { + # On Windows with PS Core, 'windows' in Support is sufficient (backwards compat with types + # declared before PS Core on Windows was common) + $windowsCoreOk = $IsWindows -and ($Support -contains 'windows') + if(-not $windowsCoreOk -and $Support -notcontains 'core') { Write-Verbose "Supported platforms [$Support] for type [$Type] does not contain [core]. Pull requests welcome!" return $false } - } - else { # full windows powershell + } else { + # full windows powershell if($Support -notcontains 'windows') { Write-Verbose "Supported platforms [$Support] for type [$Type] does not contain [windows]. Pull requests welcome!" return $false diff --git a/PSDepend/Public/Get-Dependency.ps1 b/PSDepend/Public/Get-Dependency.ps1 index 3372f5a..f9784db 100644 --- a/PSDepend/Public/Get-Dependency.ps1 +++ b/PSDepend/Public/Get-Dependency.ps1 @@ -120,26 +120,13 @@ function Get-Dependency { AnotherPrivatePackage = $morePrivateCredenials } - .LINK - about_PSDepend + .EXAMPLE + Get-Dependency -Path C:\requirements.psd1 - .LINK - about_PSDepend_Definitions + Get dependencies defined in C:\requirements.psd1 .LINK - Get-PSDependScript - - .LINK - Get-PSDependType - - .LINK - Install-Dependency - - .LINK - Invoke-PSDepend - - .LINK - https://github.com/RamblingCookieMonster/PSDepend + https://github.com/PowerShellOrg/PSDepend #> [cmdletbinding(DefaultParameterSetName = 'File')] param( @@ -154,33 +141,27 @@ function Get-Dependency { [parameter(ParameterSetName='Hashtable')] [hashtable[]]$InputObject, - [parameter(ParameterSetName='File')] - [parameter(ParameterSetName='Hashtable')] - [hashtable]$Credentials + [parameter(ParameterSetName='File')] + [parameter(ParameterSetName='Hashtable')] + [hashtable]$Credentials ) # Helper to pick from global psdependoptions, or return a default function Get-GlobalOption { param( - $Options = $PSDependOptions, + $Options = $PSDependOptions, $Name, $Prefer, $Default = $null ) # Check for preferred value, otherwise try to get value from key, otherwise use default.... $Output = $Default - if($Prefer) - { + if($Prefer) { $Output = $Prefer - } - else - { - try - { + } else { + try { $Output = $Options[$Name] - } - catch - { + } catch { $Output = $Default } } @@ -189,8 +170,7 @@ function Get-Dependency { if( $Name -eq 'Target' -or $Name -eq 'Source' -or $Name -eq 'PreScripts' -or - $Name -eq 'PostScripts') - { + $Name -eq 'PostScripts') { $Output = Inject-Variable $Output } $Output @@ -200,30 +180,29 @@ function Get-Dependency { [cmdletbinding()] param( $Value ) $Output = $Value - switch($Value) - { - {$_ -match '^\.$|^\.\\|^\./'}{ + switch($Value) { + { $_ -match '^\.$|^\.\\|^\./' } { $Output = $Output -replace '^\.', $PWD.Path } - {$_ -Match '\$PWD'} { + { $_ -match '\$PWD' } { $Output = $Output -replace '\$PWD', $PWD.Path } - {$_ -Match '\$ENV:ProgramData'} { + { $_ -match '\$ENV:ProgramData' } { $Output = $Output -replace '\$ENV:ProgramData', $ENV:ProgramData } - {$_ -Match '\$ENV:USERPROFILE'} { + { $_ -match '\$ENV:USERPROFILE' } { $Output = $Output -replace '\$ENV:USERPROFILE', $ENV:USERPROFILE } - {$_ -Match '\$ENV:APPDATA'} { + { $_ -match '\$ENV:APPDATA' } { $Output = $Output -replace '\$ENV:APPDATA', $ENV:APPDATA } - {$_ -Match '\$ENV:TEMP'} { + { $_ -match '\$ENV:TEMP' } { $Output = $Output -replace '\$ENV:TEMP', $ENV:TEMP } - {$_ -Match '\$DependencyFolder|\$DependencyPath'} { + { $_ -match '\$DependencyFolder|\$DependencyPath' } { $DependencyFolder = Split-Path $DependencyFile -Parent $Output = $Output -replace '\$DependencyFolder|\$DependencyPath', $DependencyFolder } @@ -240,25 +219,22 @@ function Get-Dependency { # Global settings.... $PSDependOptions = $null - if($Dependencies.Containskey('PSDependOptions')) - { + if($Dependencies.Containskey('PSDependOptions')) { $PSDependOptions = $Dependencies.PSDependOptions $Dependencies.Remove('PSDependOptions') } - foreach($Dependency in $Dependencies.keys) - { + foreach($Dependency in $Dependencies.keys) { $DependencyHash = $Dependencies.$Dependency $DependencyType = Get-GlobalOption -Name DependencyType - $CredentialName = Get-GlobalOption -Name Credential + $CredentialName = Get-GlobalOption -Name Credential # Look simple syntax with helpers in the key first - If( $DependencyHash -is [string] -and + if( $DependencyHash -is [string] -and $Dependency -match '::' -and ($Dependency -split '::').count -eq 2 - ) - { + ) { [pscustomobject]@{ PSTypeName = 'PSDepend.Dependency' DependencyFile = $DependencyFile @@ -273,8 +249,8 @@ function Get-Dependency { Tags = Get-GlobalOption -Name Tags DependsOn = Get-GlobalOption -Name DependsOn PreScripts = Get-GlobalOption -Name PreScripts - PostScripts = Get-GlobalOption -Name PostScripts - PSDependOptions = $PSDependOptions + PostScripts = Get-GlobalOption -Name PostScripts + PSDependOptions = $PSDependOptions Raw = $null } } @@ -283,8 +259,7 @@ function Get-Dependency { elseif( $DependencyHash -is [string] -and $Dependency -notmatch '/' -and -not $DependencyType -or - $DependencyType -eq 'PSGalleryModule') - { + $DependencyType -eq 'PSGalleryModule') { [pscustomobject]@{ PSTypeName = 'PSDepend.Dependency' DependencyFile = $DependencyFile @@ -300,18 +275,17 @@ function Get-Dependency { DependsOn = Get-GlobalOption -Name DependsOn PreScripts = Get-GlobalOption -Name PreScripts PostScripts = Get-GlobalOption -Name PostScripts - Credential = Resolve-Credential -Name $CredentialName + Credential = Resolve-Credential -Name $CredentialName PSDependOptions = $PSDependOptions Raw = $null } } # It looks like a git repo, simple syntax, and not a full URI elseif($DependencyHash -is [string] -and - $Dependency -match '/' -and - $Dependency.split('/').count -eq 2 -and - -not $DependencyType -or - $DependencyType -eq 'GitHub') - { + $Dependency -match '/' -and + $Dependency.split('/').count -eq 2 -and + -not $DependencyType -or + $DependencyType -eq 'GitHub') { [pscustomobject]@{ PSTypeName = 'PSDepend.Dependency' DependencyFile = $DependencyFile @@ -333,10 +307,9 @@ function Get-Dependency { } # It looks like a git repo, and simple syntax: Git elseif($DependencyHash -is [string] -and - $Dependency -match '/' -and - -not $DependencyType -or - $DependencyType -eq 'Git' ) - { + $Dependency -match '/' -and + -not $DependencyType -or + $DependencyType -eq 'Git' ) { [pscustomobject]@{ PSTypeName = 'PSDepend.Dependency' DependencyFile = $DependencyFile @@ -355,47 +328,40 @@ function Get-Dependency { PSDependOptions = $PSDependOptions Raw = $null } - } - else - { + } else { # Parse dependency hash format # Default type is module, unless it's in a git-style format - if(-not $DependencyHash.DependencyType) - { + if(-not $DependencyHash.DependencyType) { # Is it a global option? - if($DependencyType) {} + if($DependencyType) { + } # GitHub first elseif( # Ugly right? Watch out for split called on hashtable... ($Dependency -match '/' -and -not $Dependency.Name -and - ($Dependency -is [string] -and $Dependency.split('/').count -eq 2) + ($Dependency -is [string] -and $Dependency.split('/').count -eq 2) ) -or ($DependencyHash.Name -match '/' -and - ($DependencyHash -is [string] -and $DependencyHash.split('/').count -eq 2) + ($DependencyHash -is [string] -and $DependencyHash.split('/').count -eq 2) ) - ) - { + ) { $DependencyType = 'GitHub' } # Now git... elseif( ($Dependency -match '/' -and -not $Dependency.Name) -or $DependencyHash.Name -match '/' - ) - { + ) { $DependencyType = 'Git' - } - else # finally, psgallerymodule - { + } else { + # finally, psgallerymodule $DependencyType = 'PSGalleryModule' } - } - else - { + } else { $DependencyType = $DependencyHash.DependencyType } - $CredentialName = Get-GlobalOption -Name Credential -Prefer $DependencyHash.Credential + $CredentialName = Get-GlobalOption -Name Credential -Prefer $DependencyHash.Credential [pscustomobject]@{ PSTypeName = 'PSDepend.Dependency' DependencyFile = $DependencyFile @@ -411,53 +377,47 @@ function Get-Dependency { DependsOn = Get-GlobalOption -Name DependsOn -Prefer $DependencyHash.DependsOn PreScripts = Get-GlobalOption -Name PreScripts -Prefer $DependencyHash.PreScripts PostScripts = Get-GlobalOption -Name PostScripts -Prefer $DependencyHash.PostScripts - Credential = Resolve-Credential -Name $CredentialName - PSDependOptions = $PSDependOptions + Credential = Resolve-Credential -Name $CredentialName + PSDependOptions = $PSDependOptions Raw = $DependencyHash } } } - } - - # Heleper to retrieve the credential for a dependency - function Resolve-Credential { - [CmdletBinding()] - param ( - [string]$Name - ) - - $credential = $null - if (($null -ne $Name) -and ($null -ne $Credentials)) { - - if ($Credentials.ContainsKey($Name)) { - $credential = $Credentials[$Name] - } else { - Write-Warning "No credential found for the specified name $Name. Was the dependency misconfigured?" - } - } + } - return $credential - } + # Helper to retrieve the credential for a dependency + function Resolve-Credential { + [CmdletBinding()] + param ( + [string]$Name + ) - if($PSCmdlet.ParameterSetName -eq 'File') - { - $ParsedDependencies = foreach($DependencyPath in $Path) - { + $credential = $null + if (($null -ne $Name) -and ($null -ne $Credentials)) { + + if ($Credentials.ContainsKey($Name)) { + $credential = $Credentials[$Name] + } else { + Write-Warning "No credential found for the specified name $Name. Was the dependency misconfigured?" + } + } + + return $credential + } + + if($PSCmdlet.ParameterSetName -eq 'File') { + $ParsedDependencies = foreach($DependencyPath in $Path) { #Resolve relative paths... Thanks Oisin! http://stackoverflow.com/a/3040982/3067642 $DependencyPath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($DependencyPath) - if(Test-Path $DependencyPath -PathType Container) - { + if(Test-Path $DependencyPath -PathType Container) { $DependencyFiles = @( Resolve-DependScripts -Path $DependencyPath -Recurse $Recurse ) - } - else - { + } else { $DependencyFiles = @( $DependencyPath ) } $DependencyFiles = $DependencyFiles | Select-Object -Unique - foreach($DependencyFile in $DependencyFiles) - { + foreach($DependencyFile in $DependencyFiles) { # Read the file $Base = Split-Path $DependencyFile -Parent $File = Split-Path $DependencyFile -Leaf @@ -466,23 +426,18 @@ function Get-Dependency { Parse-Dependency -ParamSet $PSCmdlet.ParameterSetName } } - } - elseif($PSCmdlet.ParameterSetName -eq 'Hashtable') - { + } elseif($PSCmdlet.ParameterSetName -eq 'Hashtable') { $DependencyFile = 'Hashtable' - $ParsedDependencies = foreach($InputDependency in $InputObject) - { + $ParsedDependencies = foreach($InputDependency in $InputObject) { $Dependencies = $InputDependency Parse-Dependency -ParamSet $PSCmdlet.ParameterSetName } } - If($PSBoundParameters.ContainsKey('Tags')) - { + if($PSBoundParameters.ContainsKey('Tags')) { $ParsedDependencies = Get-TaggedDependency -Dependency $ParsedDependencies -Tags $Tags - if(-not $ParsedDependencies) - { + if(-not $ParsedDependencies) { Write-Warning "No dependencies found with tags '$tags'" return } diff --git a/PSDepend/Public/Get-PSDependScript.ps1 b/PSDepend/Public/Get-PSDependScript.ps1 index fba005e..d104858 100644 --- a/PSDepend/Public/Get-PSDependScript.ps1 +++ b/PSDepend/Public/Get-PSDependScript.ps1 @@ -1,4 +1,4 @@ -Function Get-PSDependScript { +function Get-PSDependScript { <# .SYNOPSIS Get dependency types and associated scripts @@ -26,29 +26,11 @@ Function Get-PSDependScript { # List dependency types defined in a centralized dependency map .LINK - about_PSDepend - - .LINK - about_PSDepend_Definitions - - .LINK - Get-Dependency - - .LINK - Get-PSDependType - - .LINK - Install-Dependency - - .LINK - Invoke-PSDepend - - .LINK - https://github.com/RamblingCookieMonster/PSDepend + https://github.com/PowerShellOrg/PSDepend #> [cmdletbinding()] param( - [validatescript({Test-Path $_ -PathType Leaf -ErrorAction Stop})] + [validatescript({ Test-Path $_ -PathType Leaf -ErrorAction Stop })] [string]$Path = $(Join-Path $ModuleRoot PSDependMap.psd1) ) @@ -58,26 +40,19 @@ Function Get-PSDependScript { $DependencyDefinitions = Import-LocalizedData -BaseDirectory $Base -FileName $File $DependHash = @{} - foreach($DependencyType in $DependencyDefinitions.Keys) - { + foreach($DependencyType in $DependencyDefinitions.Keys) { #Determine the path to this script $Script = $DependencyDefinitions.$DependencyType.Script - if(Test-Path $Script -ErrorAction SilentlyContinue) - { + if(Test-Path $Script -ErrorAction SilentlyContinue) { $ScriptPath = $Script - } - else - { + } else { # account for missing ps1 $ScriptPath = Join-Path $ModuleRoot "PSDependScripts\$($Script -replace ".ps1$").ps1" } - if(test-path $ScriptPath) - { + if(Test-Path $ScriptPath) { $DependHash.$DependencyType = $ScriptPath - } - else - { + } else { Write-Error "Could not find path '$ScriptPath' for dependency $DependencyType. Origin: $($DependencyDefinitions.$DependencyType.Script)" } } diff --git a/PSDepend/Public/Get-PSDependType.ps1 b/PSDepend/Public/Get-PSDependType.ps1 index efa6aab..e356d24 100644 --- a/PSDepend/Public/Get-PSDependType.ps1 +++ b/PSDepend/Public/Get-PSDependType.ps1 @@ -43,25 +43,7 @@ Function Get-PSDependType { # List dependency types defined in a centralized dependency map .LINK - about_PSDepend - - .LINK - about_PSDepend_Definitions - - .LINK - Get-Dependency - - .LINK - Get-PSDependScript - - .LINK - Install-Dependency - - .LINK - Invoke-PSDepend - - .LINK - https://github.com/RamblingCookieMonster/PSDepend + https://github.com/PowerShellOrg/PSDepend #> [cmdletbinding()] param( diff --git a/PSDepend/Public/Import-Dependency.ps1 b/PSDepend/Public/Import-Dependency.ps1 index 622550b..25d9488 100644 --- a/PSDepend/Public/Import-Dependency.ps1 +++ b/PSDepend/Public/Import-Dependency.ps1 @@ -30,22 +30,7 @@ Function Import-Dependency { Get dependencies from C:\requirements.psd1 and import them .LINK - about_PSDepend - - .LINK - about_PSDepend_Definitions - - .LINK - Get-Dependency - - .LINK - Get-PSDependType - - .LINK - Invoke-PSDepend - - .LINK - https://github.com/RamblingCookieMonster/PSDepend + https://github.com/PowerShellOrg/PSDepend #> [cmdletbinding()] Param( diff --git a/PSDepend/Public/Install-Dependency.ps1 b/PSDepend/Public/Install-Dependency.ps1 index e091914..35fcdb9 100644 --- a/PSDepend/Public/Install-Dependency.ps1 +++ b/PSDepend/Public/Install-Dependency.ps1 @@ -33,22 +33,7 @@ Function Install-Dependency { Get dependencies from C:\requirements.psd1 and install them .LINK - about_PSDepend - - .LINK - about_PSDepend_Definitions - - .LINK - Get-Dependency - - .LINK - Get-PSDependType - - .LINK - Invoke-PSDepend - - .LINK - https://github.com/RamblingCookieMonster/PSDepend + https://github.com/PowerShellOrg/PSDepend #> [cmdletbinding( SupportsShouldProcess = $True, ConfirmImpact='High' )] @@ -67,6 +52,8 @@ Function Install-Dependency { ) Process { - Invoke-DependencyScript @PSBoundParameters -PSDependAction Install + $InvokeParams = @{} + $PSBoundParameters + $null = $InvokeParams.Remove('Force') + Invoke-DependencyScript @InvokeParams -PSDependAction Install } } diff --git a/PSDepend/Public/Invoke-DependencyScript.ps1 b/PSDepend/Public/Invoke-DependencyScript.ps1 index 3e492e5..1a52710 100644 --- a/PSDepend/Public/Invoke-DependencyScript.ps1 +++ b/PSDepend/Public/Invoke-DependencyScript.ps1 @@ -1,4 +1,4 @@ -Function Invoke-DependencyScript { +function Invoke-DependencyScript { <# .SYNOPSIS Invoke a dependency script @@ -33,32 +33,17 @@ Function Invoke-DependencyScript { Get dependencies from C:\requirements.psd1 and import them .LINK - about_PSDepend - - .LINK - about_PSDepend_Definitions - - .LINK - Get-Dependency - - .LINK - Get-PSDependType - - .LINK - Invoke-PSDepend - - .LINK - https://github.com/RamblingCookieMonster/PSDepend + https://github.com/PowerShellOrg/PSDepend #> [cmdletbinding()] - Param( + param( [parameter( ValueFromPipeline = $True, - ParameterSetName='Map', - Mandatory = $True)] + ParameterSetName='Map', + Mandatory = $True)] [PSTypeName('PSDepend.Dependency')] [psobject]$Dependency, - [validatescript({Test-Path -Path $_ -PathType Leaf -ErrorAction Stop})] + [validatescript({ Test-Path -Path $_ -PathType Leaf -ErrorAction Stop })] [string]$PSDependTypePath = $(Join-Path $ModuleRoot PSDependMap.psd1), [string[]]$PSDependAction, @@ -67,14 +52,12 @@ Function Invoke-DependencyScript { [switch]$Quiet ) - Begin - { + begin { # This script reads a depend.psd1, installs dependencies as defined Write-Verbose "Running Invoke-DependencyScript with ParameterSetName '$($PSCmdlet.ParameterSetName)' and params: $($PSBoundParameters | Out-String)" $PSDependTypes = Get-PSDependType -SkipHelp } - Process - { + process { Write-Verbose "Dependencies:`n$($Dependency | Select-Object -Property * | Out-String)" #Get definitions, and dependencies in this particular psd1 @@ -82,21 +65,18 @@ Function Invoke-DependencyScript { $TheseDependencyTypes = @( $Dependency.DependencyType | Sort-Object -Unique ) #Build up hash, we call each dependencytype script for applicable dependencies - foreach($DependencyType in $TheseDependencyTypes) - { - $PSDependType = ($PSDependTypes | Where-Object {$_.DependencyType -eq $DependencyType}) - if(-not $PSDependType.Supported) - { + foreach($DependencyType in $TheseDependencyTypes) { + $PSDependType = ($PSDependTypes | Where-Object { $_.DependencyType -eq $DependencyType }) + if(-not $PSDependType.Supported) { Write-Warning "Skipping dependency type [$DependencyType]`nThis dependency does not support your platform`nSupported platforms: [$($PSDependType.Supports)]" continue } $DependencyScript = $DependencyDefs.$DependencyType - if(-not $DependencyScript) - { + if(-not $DependencyScript) { Write-Error "DependencyType $DependencyType is not defined in PSDependMap.psd1" continue } - $TheseDependencies = @( $Dependency | Where-Object {$_.DependencyType -eq $DependencyType}) + $TheseDependencies = @( $Dependency | Where-Object { $_.DependencyType -eq $DependencyType }) #Define params for the script #Each dependency type can have a hashtable to splat. @@ -104,101 +84,75 @@ Function Invoke-DependencyScript { $ValidParamNames = $RawParameters.Name Write-Verbose "Found parameters [$ValidParamNames]" - if($ValidParamNames -notcontains 'PSDependAction') - { + if($ValidParamNames -notcontains 'PSDependAction') { Write-Error "No PSDependAction found on PSDependScript [$DependencyScript]. Skipping [$($Dependency.DependencyName)]" continue } [string[]]$ValidPSDependActions = $RawParameters | - Where-Object {$_.Name -like 'PSDependAction'} | + Where-Object { $_.Name -like 'PSDependAction' } | Select-Object -ExpandProperty ValidateSetValues -ErrorAction SilentlyContinue - [string[]]$PSDependActions = foreach($Action in $PSDependAction) - { - if($ValidPSDependActions -contains $Action) {$Action} - else - { + [string[]]$PSDependActions = foreach($Action in $PSDependAction) { + if($ValidPSDependActions -contains $Action) { + $Action + } else { Write-Warning "Skipping PSDependAction [$Action] for dependency [$($Dependency.DependencyName)]. Valid actions: [$ValidPSDependActions]" } } - if($PSDependActions.count -like 0) - { + if($PSDependActions.count -like 0) { Write-Verbose "Skipped dependency [$($Dependency.DependencyName)] due to filtered PSDependAction. See Warnings above." continue } - if($PSDependActions -contains 'Test' -and ( $PSDependActions -contains 'Import' -or $PSDependActions -contains 'Install')) - { + if($PSDependActions -contains 'Test' -and ( $PSDependActions -contains 'Import' -or $PSDependActions -contains 'Install')) { Write-Error "Removing [Test] from PSDependActions. The Test action must run on its own." - $PSDependActions = $PSDependActions | Where-Object {$_ -ne 'Test'} + $PSDependActions = $PSDependActions | Where-Object { $_ -ne 'Test' } } - foreach($ThisDependency in $TheseDependencies) - { + foreach($ThisDependency in $TheseDependencies) { #Parameters for dependency types. Only accept valid params... - if($ThisDependency.Parameters.keys.count -gt 0) - { + if($ThisDependency.Parameters.keys.count -gt 0) { $splat = @{} - foreach($key in $ThisDependency.Parameters.keys) - { - if($ValidParamNames -contains $key) - { + foreach($key in $ThisDependency.Parameters.keys) { + if($ValidParamNames -contains $key) { $splat.Add($key, $ThisDependency.Parameters.$key) - } - else - { + } else { Write-Warning "Parameter [$Key] with value [$($ThisDependency.Parameters.$Key)] is not a valid parameter for [$DependencyType], ignoring. Valid params:`n[$ValidParamNames]" } } - if($ThisDependency.Parameters.Import -and $PSDependActions -notcontains 'Test') - { + if($ThisDependency.Parameters.Import -and $PSDependActions -notcontains 'Test') { $PSDependActions += 'Import' $PSDependActions = $PSDependActions | Sort-Object -Unique } - if($splat.ContainsKey('PSDependAction')) - { + if($splat.ContainsKey('PSDependAction')) { $Splat['PSDependAction'] = $PSDependActions - } - else - { + } else { $Splat.add('PSDependAction', $PSDependActions) } - } - else - { - $splat = @{PSDependAction = $PSDependActions} + } else { + $splat = @{PSDependAction = $PSDependActions } } #Define params for the script $splat.add('Dependency', $ThisDependency) # PITA, but tasks can run two ways, each different than typical dependency scripts - if($PSDependActions -contains 'Install' -and $DependencyType -eq 'Task') - { - foreach($TaskScript in $ThisDependency.Target) - { - if( Test-Path $TaskScript -PathType Leaf) - { + if($PSDependActions -contains 'Install' -and $DependencyType -eq 'Task') { + foreach($TaskScript in $ThisDependency.Target) { + if( Test-Path $TaskScript -PathType Leaf) { . $TaskScript @splat - } - else - { + } else { Write-Error "Could not process task [$TaskScript].`nAre connectivity, privileges, and other needs met to access it?" } } - } - else - { + } else { Write-Verbose "Invoking '$DependencyScript' with parameters $($Splat | Out-String)" $Output = . $DependencyScript @splat - if($PSDependActions -contains 'Test' -and -not $Quiet) - { + if($PSDependActions -contains 'Test' -and -not $Quiet) { Add-Member -InputObject $ThisDependency -MemberType NoteProperty -Name DependencyExists -Value $Output -Force -PassThru - } - else - { + } else { $Output } } diff --git a/PSDepend/Public/Invoke-PSDepend.ps1 b/PSDepend/Public/Invoke-PSDepend.ps1 index d46d329..b1b51b3 100644 --- a/PSDepend/Public/Invoke-PSDepend.ps1 +++ b/PSDepend/Public/Invoke-PSDepend.ps1 @@ -96,19 +96,7 @@ Function Invoke-PSDepend { # Find and run *.depend.psd1 and requirements.psd1 files under C\Requirements (but not subfolders) .LINK - about_PSDepend - - .LINK - about_PSDepend_Definitions - - .LINK - Get-Dependency - - .LINK - Install-Dependency - - .LINK - https://github.com/RamblingCookieMonster/PSDepend + https://github.com/PowerShellOrg/PSDepend #> [cmdletbinding( DefaultParameterSetName = 'installimport-file', SupportsShouldProcess = $True, diff --git a/PSDepend/Public/Test-Dependency.ps1 b/PSDepend/Public/Test-Dependency.ps1 index b49dfe6..fb433d5 100644 --- a/PSDepend/Public/Test-Dependency.ps1 +++ b/PSDepend/Public/Test-Dependency.ps1 @@ -1,4 +1,4 @@ -Function Test-Dependency { +function Test-Dependency { <# .SYNOPSIS Test a specific dependency @@ -34,40 +34,24 @@ Function Test-Dependency { Get dependencies from C:\requirements.psd1 and test whether they exist .LINK - about_PSDepend - - .LINK - about_PSDepend_Definitions - - .LINK - Get-Dependency - - .LINK - Get-PSDependType - - .LINK - Invoke-PSDepend - - .LINK - https://github.com/RamblingCookieMonster/PSDepend + https://github.com/PowerShellOrg/PSDepend #> [cmdletbinding()] - Param( + param( [parameter( ValueFromPipeline = $True, - ParameterSetName='Map', - Mandatory = $True)] + ParameterSetName='Map', + Mandatory = $True)] [PSTypeName('PSDepend.Dependency')] [psobject[]]$Dependency, - [validatescript({Test-Path -Path $_ -PathType Leaf -ErrorAction Stop})] + [validatescript({ Test-Path -Path $_ -PathType Leaf -ErrorAction Stop })] [string]$PSDependTypePath = $(Join-Path $ModuleRoot PSDependMap.psd1), [string[]]$Tags, [switch]$Quiet ) - process - { + process { Invoke-DependencyScript @PSBoundParameters -PSDependAction Test } } diff --git a/PSDepend/en-US/about_PSDepend.help.txt b/PSDepend/en-US/about_PSDepend.help.txt index b5fdc13..3a493b4 100644 --- a/PSDepend/en-US/about_PSDepend.help.txt +++ b/PSDepend/en-US/about_PSDepend.help.txt @@ -159,4 +159,4 @@ DETAILED DESCRIPTION SEE ALSO about_PSDepend_Definitions - https://github.com/RamblingCookieMonster/PSDepend \ No newline at end of file + https://github.com/PowerShellOrg/PSDepend \ No newline at end of file diff --git a/Tests/Help.tests.ps1 b/Tests/Help.tests.ps1 new file mode 100644 index 0000000..8eca696 --- /dev/null +++ b/Tests/Help.tests.ps1 @@ -0,0 +1,120 @@ +# Taken with love from @juneb_get_help (https://raw.githubusercontent.com/juneb/PesterTDD/master/Module.Help.Tests.ps1) + +BeforeDiscovery { + if ($null -eq $env:BHPSModuleManifest) { + & "$PSScriptRoot/../Build.ps1" -Task Init + } + function global:FilterOutCommonParams { + param ($Params) + $commonParameters = [System.Management.Automation.PSCmdlet]::CommonParameters + + [System.Management.Automation.PSCmdlet]::OptionalCommonParameters + $params | Where-Object { $_.Name -notin $commonParameters } | Sort-Object -Property Name -Unique + } + + $manifest = Import-PowerShellDataFile -Path $env:BHPSModuleManifest + $outputDir = Join-Path -Path $env:BHProjectPath -ChildPath 'Output' + $outputModDir = Join-Path -Path $outputDir -ChildPath $env:BHProjectName + $outputModVerDir = Join-Path -Path $outputModDir -ChildPath $manifest.ModuleVersion + $outputModVerManifest = Join-Path -Path $outputModVerDir -ChildPath "$($env:BHProjectName).psd1" + + # Get module commands + # Remove all versions of the module from the session. Pester can't handle multiple versions. + Get-Module $env:BHProjectName | Remove-Module -Force -ErrorAction Ignore + Import-Module -Name $outputModVerManifest -Verbose:$false -ErrorAction Stop + $params = @{ + Module = (Get-Module $env:BHProjectName) + CommandType = [System.Management.Automation.CommandTypes[]]'Cmdlet, Function' # Not alias + } + if ($PSVersionTable.PSVersion.Major -lt 6) { + $params.CommandType[0] += 'Workflow' + } + $commands = Get-Command @params + + ## When testing help, remember that help is cached at the beginning of each session. + ## To test, restart session. +} + +Describe "Test help for <_.Name>" -ForEach $commands { + + BeforeDiscovery { + # Get command help, parameters, and links + $command = $_ + $commandHelp = Get-Help $command.Name -ErrorAction SilentlyContinue + $commandParameters = global:FilterOutCommonParams -Params $command.ParameterSets.Parameters + $commandParameterNames = $commandParameters.Name + $helpLinks = @($commandHelp.relatedLinks.navigationLink.uri | Where-Object { $_ }) + $helpParameters = global:FilterOutCommonParams -Params $commandHelp.Parameters.Parameter + $helpParameterNames = $helpParameters.Name + } + + BeforeAll { + # These vars are needed in both discovery and test phases so we need to duplicate them here + $script:command = $_ + $script:commandName = $_.Name + $script:commandHelp = Get-Help $script:command.Name -ErrorAction SilentlyContinue + $script:commandParameters = global:FilterOutCommonParams -Params $script:command.ParameterSets.Parameters + $script:commandParameterNames = $script:commandParameters.Name + $script:helpParameters = global:FilterOutCommonParams -Params $script:commandHelp.Parameters.Parameter + $script:helpParameterNames = $script:helpParameters.Name + } + + # If help is not found, synopsis in auto-generated help is the syntax diagram + It 'Help is not auto-generated' { + $script:commandHelp.Synopsis | Should -Not -BeLike '*`[``]*' + } + + # Should be a description for every function + It "Has description" { + $script:commandHelp.Description | Should -Not -BeNullOrEmpty + } + + # Should be at least one example + It "Has example code" { + ($script:commandHelp.Examples.Example | Select-Object -First 1).Code | Should -Not -BeNullOrEmpty + } + + # Should be at least one example description + It "Has example help" { + ($script:commandHelp.Examples.Example.Remarks | Select-Object -First 1).Text | Should -Not -BeNullOrEmpty + } + + It "Help link <_> is valid" -Tag 'Acceptance' -ForEach $helpLinks { + (Invoke-WebRequest -Uri $_ -UseBasicParsing -TimeoutSec 10).StatusCode | Should -Be '200' + } + + Context "Parameter <_.Name>" -ForEach $commandParameters { + + BeforeAll { + $script:parameter = $_ + $script:parameterName = $script:parameter.Name + $script:parameterHelp = $script:commandHelp.parameters.parameter | Where-Object Name -EQ $script:parameterName + $script:parameterHelpType = if ($script:parameterHelp.ParameterValue) { + $script:parameterHelp.ParameterValue.Trim() + } + } + + # Should be a description for every parameter + It "Has description" { + $script:parameterHelp.Description.Text | Should -Not -BeNullOrEmpty + } + + # Required value in Help should match IsMandatory property of parameter + It "Has correct [mandatory] value" { + $codeMandatory = $_.IsMandatory.toString() + $script:parameterHelp.Required | Should -Be $codeMandatory + } + + # Parameter type in help should match code + It "Has correct parameter type" { + $script:parameterHelpType | Should -Be $script:parameter.ParameterType.Name + } + } + + Context "Test <_> help parameter help for " -ForEach $helpParameterNames { + + # Shouldn't find extra parameters in help. + It "finds help parameter in code: <_>" { + $_ -in $script:commandParameterNames | Should -Be $true + } + } +} diff --git a/Tests/PSDepend.Tests.ps1 b/Tests/PSDepend.Tests.ps1 index c8b82eb..cbdb7fb 100644 --- a/Tests/PSDepend.Tests.ps1 +++ b/Tests/PSDepend.Tests.ps1 @@ -1,100 +1,230 @@ -if(-not $ENV:BHProjectPath) -{ - Set-BuildEnvironment -Path $PSScriptRoot\.. -} -Remove-Module $ENV:BHProjectName -ErrorAction SilentlyContinue -Import-Module (Join-Path $ENV:BHProjectPath $ENV:BHProjectName) -Force - -$PSVersion = $PSVersionTable.PSVersion.Major - -# Verbose output for non-master builds on appveyor -# Handy for troubleshooting. -# Splat @Verbose against commands as needed (here or in pester tests) - $Verbose = @{} - if($ENV:BHBranchName -notlike "master" -or $env:BHCommitMessage -match "!verbose") - { - $Verbose.add("Verbose",$True) +BeforeDiscovery { + if ($null -eq $env:BHPSModuleManifest) { + & "$PSScriptRoot/../Build.ps1" -Task Init } + $manifest = Import-PowerShellDataFile -Path $env:BHPSModuleManifest + $outputDir = Join-Path -Path $env:BHProjectPath -ChildPath 'Output' + $outputModDir = Join-Path -Path $outputDir -ChildPath $env:BHProjectName + $outputModVerDir = Join-Path -Path $outputModDir -ChildPath $manifest.ModuleVersion + $outputModVerManifest = Join-Path -Path $outputModVerDir -ChildPath "$($env:BHProjectName).psd1" -$TestDepends = Join-Path $ENV:BHProjectPath Tests\DependFiles + Get-Module $env:BHProjectName | Remove-Module -Force -ErrorAction Ignore + Import-Module -Name $outputModVerManifest -Verbose:$false -ErrorAction Stop -Describe "$ENV:BHProjectName PS$PSVersion" { - Context 'Strict mode' { + $PSVersion = $PSVersionTable.PSVersion.Major # discovery-scope for Describe names +} + + +BeforeAll { + $script:TestDepends = Join-Path $ENV:BHProjectPath Tests\DependFiles + $script:Verbose = @{} + if($ENV:BHBranchName -notlike "master" -or $env:BHCommitMessage -match "!verbose") { + $script:Verbose.add("Verbose",$True) + } +} - Set-StrictMode -Version latest +Describe "$ENV:BHProjectName PS$PSVersion" -Tag 'Unit' { + Context 'Strict mode' { + BeforeAll { Set-StrictMode -Version latest } + AfterAll { Set-StrictMode -Off } It 'Should load' { $Module = Get-Module $ENV:BHProjectName - $Module.Name | Should be $ENV:BHProjectName - $Module.ExportedFunctions.Keys -contains 'Get-Dependency' | Should be $True + $Module.Name | Should -Be $ENV:BHProjectName + $Module.ExportedFunctions.Keys -contains 'Get-Dependency' | Should -Be $True } } } -Describe "Get-Dependency PS$PSVersion" { +Describe "Get-Dependency PS$PSVersion" -Tag 'Unit' { Context 'Strict mode' { - Set-StrictMode -Version latest + BeforeAll { Set-StrictMode -Version latest } + AfterAll { Set-StrictMode -Off } It 'Should read ModuleName=Version syntax' { $Dependencies = Get-Dependency -Path $TestDepends\simple.depend.psd1 - $Dependencies.Count | Should be 4 - @( $Dependencies.DependencyType -like 'PSGalleryModule' ).count | Should be 4 - @( $Dependencies | Where {$_.Name -like $_.DependencyName} ).count | Should be 4 + $Dependencies.Count | Should -Be 4 + @( $Dependencies.DependencyType -like 'PSGalleryModule' ).count | Should -Be 4 + @( $Dependencies | Where-Object { $_.Name -like $_.DependencyName } ).count | Should -Be 4 } It 'Should read DependencyType::DependencyName=Version syntax' { $Dependencies = Get-Dependency -Path $TestDepends\simple.helpers.depend.psd1 - $Dependencies.Count | Should be 2 - @( $Dependencies.DependencyType -like 'PSGalleryModule' ).count | Should be 1 - @( $Dependencies.DependencyType -like 'GitHub' ).count | Should be 1 - @( $Dependencies | Where {$_.Name -like $_.DependencyName} ).count | Should be 2 + $Dependencies.Count | Should -Be 2 + @( $Dependencies.DependencyType -like 'PSGalleryModule' ).count | Should -Be 1 + @( $Dependencies.DependencyType -like 'GitHub' ).count | Should -Be 1 + @( $Dependencies | Where-Object { $_.Name -like $_.DependencyName } ).count | Should -Be 2 } It 'Should read each property correctly' { $Dependencies = Get-Dependency -Path $TestDepends\allprops.depend.psd1 - @( $Dependencies ).count | Should Be 1 - $Dependencies.DependencyName | Should be 'DependencyName' - $Dependencies.Name | Should be 'Name' - $Dependencies.Version | Should be 'Version' - $Dependencies.DependencyType | Should be 'noop' - $Dependencies.Parameters.ContainsKey('Random') | Should Be $True - $Dependencies.Parameters['Random'] | Should be 'Value' - $Dependencies.Source | Should be 'Source' - $Dependencies.Target | Should be 'Target' - $Dependencies.AddToPath | Should be $True - $Dependencies.Tags.Count | SHould Be 2 - $Dependencies.Tags -contains 'tags' | Should be $True - $Dependencies.DependsOn | Should be 'DependsOn' - $Dependencies.PreScripts | Should be 'C:\PreScripts.ps1' - $Dependencies.PostScripts | Should be 'C:\PostScripts.ps1' - $Dependencies.Raw.ContainsKey('ExtendedSchema') | Should be $True - $Dependencies.Raw.ExtendedSchema['IsTotally'] | Should Be 'Captured' + @( $Dependencies ).count | Should -Be 1 + $Dependencies.DependencyName | Should -Be 'DependencyName' + $Dependencies.Name | Should -Be 'Name' + $Dependencies.Version | Should -Be 'Version' + $Dependencies.DependencyType | Should -Be 'noop' + $Dependencies.Parameters.ContainsKey('Random') | Should -Be $True + $Dependencies.Parameters['Random'] | Should -Be 'Value' + $Dependencies.Source | Should -Be 'Source' + $Dependencies.Target | Should -Be 'Target' + $Dependencies.AddToPath | Should -Be $True + $Dependencies.Tags.Count | Should -Be 2 + $Dependencies.Tags -contains 'tags' | Should -Be $True + $Dependencies.DependsOn | Should -Be 'DependsOn' + $Dependencies.PreScripts | Should -Be 'C:\PreScripts.ps1' + $Dependencies.PostScripts | Should -Be 'C:\PostScripts.ps1' + $Dependencies.Raw.ContainsKey('ExtendedSchema') | Should -Be $True + $Dependencies.Raw.ExtendedSchema['IsTotally'] | Should -Be 'Captured' } It 'Should handle DependsOn' { $Dependencies = Get-Dependency -Path $TestDepends\dependson.depend.psd1 - @( $Dependencies ).count | Should Be 3 - $Dependencies[0].DependencyName | Should be 'One' - $Dependencies[1].DependencyName | Should be 'Two' - $Dependencies[2].DependencyName | Should be 'THree' + @( $Dependencies ).count | Should -Be 3 + $Dependencies[0].DependencyName | Should -Be 'One' + $Dependencies[1].DependencyName | Should -Be 'Two' + $Dependencies[2].DependencyName | Should -Be 'THree' } It 'Should inject variables' { $Dependencies = Get-Dependency -Path $TestDepends\inject.variables.depend.psd1 $DependencyFolder = Split-Path $Dependencies.DependencyFile -Parent - $Dependencies.Source | Should Be "PWD=$($PWD.Path)" - $Dependencies.Target | Should Be "$($PWD.Path)\Dependencies;$DependencyFolder" + $Dependencies.Source | Should -Be "PWD=$($PWD.Path)" + $Dependencies.Target | Should -Be "$($PWD.Path)\Dependencies;$DependencyFolder" } It 'Should not mangle dependencies if multiple PSGallery modules specified' { $Dependencies = Get-Dependency -Path $TestDepends\multiplepsgallerymodule.depend.psd1 - $Dependencies.Count | Should be 3 - $Dependencies[0].Version | Should BeNullOrEmpty - $Dependencies[1].Version | Should BeNullOrEmpty - $Dependencies[2].Version | Should BeNullOrEmpty - @($Dependencies[0].Tags) -contains 'prd' | Should Be $True - @($Dependencies[1].Tags) -contains 'prd' | Should Be $True - @($Dependencies[2].Tags) -contains 'prd' | Should Be $True + $Dependencies.Count | Should -Be 3 + $Dependencies[0].Version | Should -BeNullOrEmpty + $Dependencies[1].Version | Should -BeNullOrEmpty + $Dependencies[2].Version | Should -BeNullOrEmpty + @($Dependencies[0].Tags) -contains 'prd' | Should -Be $True + @($Dependencies[1].Tags) -contains 'prd' | Should -Be $True + @($Dependencies[2].Tags) -contains 'prd' | Should -Be $True + } + } + + Context 'Error and edge cases' { + BeforeAll { Set-StrictMode -Version latest } + AfterAll { Set-StrictMode -Off } + + It 'Filters results to matching tags when -Tags is specified' { + $Dependencies = Get-Dependency -Path $TestDepends\allprops.depend.psd1 -Tags 'tags' + $Dependencies | Should -Not -BeNullOrEmpty + $Dependencies.DependencyName | Should -Be 'DependencyName' + } + + It 'Returns nothing when -Tags matches no dependency' { + $Dependencies = Get-Dependency -Path $TestDepends\allprops.depend.psd1 -Tags 'nonexistenttag' -WarningAction SilentlyContinue + $Dependencies | Should -BeNullOrEmpty + } + + It 'Parses -InputObject hashtable as PSGalleryModule by default' { + $Dependencies = Get-Dependency -InputObject @{ Pester = 'latest' } + $Dependencies.DependencyName | Should -Be 'Pester' + $Dependencies.DependencyType | Should -Be 'PSGalleryModule' + $Dependencies.Version | Should -Be 'latest' + } + } +} + +Describe "Get-PSDependType PS$PSVersion" -Tag 'Unit' { + Context 'Strict mode' { + BeforeAll { Set-StrictMode -Version latest } + AfterAll { Set-StrictMode -Off } + + It 'Returns objects for all types in the default map' { + $Types = Get-PSDependType -SkipHelp + $Types | Should -Not -BeNullOrEmpty + $Types[0].DependencyType | Should -Not -BeNullOrEmpty + } + + It 'Returns a bool Supported flag for every type' { + $Types = Get-PSDependType -SkipHelp + foreach ($Type in $Types) { + $Type.Supported | Should -BeOfType [bool] + } + } + + It 'Filters by DependencyType wildcard' { + $Types = Get-PSDependType -DependencyType 'PSGallery*' -SkipHelp + $Types | Should -Not -BeNullOrEmpty + $Types | ForEach-Object { $_.DependencyType | Should -BeLike 'PSGallery*' } + } + + It 'Throws on an invalid Path' { + { Get-PSDependType -Path 'C:\DoesNotExist\map.psd1' -SkipHelp } | Should -Throw + } + } +} + +Describe "Get-PSDependScript PS$PSVersion" -Tag 'Unit' { + Context 'Strict mode' { + BeforeAll { Set-StrictMode -Version latest } + AfterAll { Set-StrictMode -Off } + + It 'Returns a hashtable keyed by dependency type name' { + $Scripts = Get-PSDependScript + $Scripts | Should -BeOfType [hashtable] + $Scripts.ContainsKey('PSGalleryModule') | Should -Be $True + } + + It 'Maps each type to an existing .ps1 file' { + $Scripts = Get-PSDependScript + foreach ($Key in $Scripts.Keys) { + Test-Path $Scripts[$Key] | Should -Be $True -Because "$Key must point to an existing script" + } + } + + It 'Throws on an invalid Path' { + { Get-PSDependScript -Path 'C:\DoesNotExist\map.psd1' } | Should -Throw + } + } +} + +Describe "Install-Dependency PS$PSVersion" -Tag 'Unit' { + Context 'PSGalleryModule install' { + BeforeAll { + Set-StrictMode -Version latest + Mock Install-Module {} -ModuleName PSDepend + } + AfterAll { Set-StrictMode -Off } + + It 'Calls Install-Module when given a PSGalleryModule dependency via pipeline' { + Get-Dependency -Path $TestDepends\psgallerymodule.depend.psd1 | + Install-Dependency -Force + Should -Invoke Install-Module -Times 1 -Exactly -ModuleName PSDepend + } + } +} + +Describe "Invoke-DependencyScript PS$PSVersion" -Tag 'Unit' { + Context 'Command type' { + BeforeAll { Set-StrictMode -Version latest } + AfterAll { Set-StrictMode -Off } + + It 'Returns the script output for a Command dependency' { + $Dep = Get-Dependency -Path $TestDepends\command.depend.psd1 | Select-Object -First 1 + $Dep | Invoke-DependencyScript -PSDependAction Install | Should -Be 'hello world' + } + + It 'Does not throw when PSDependAction is not valid for the dependency type' { + $Dep = Get-Dependency -Path $TestDepends\psgallerymodule.depend.psd1 | Select-Object -First 1 + { $Dep | Invoke-DependencyScript -PSDependAction 'NonExistentAction' -WarningAction SilentlyContinue } | + Should -Not -Throw + } + } + + Context 'Test action' { + BeforeAll { + Set-StrictMode -Version latest + Mock Get-Module { [pscustomobject]@{ Version = '1.2.5' } } -ModuleName PSDepend + } + AfterAll { Set-StrictMode -Off } + + It 'Returns $true when the module is installed at the required version with -Quiet' { + $Dep = Get-Dependency -Path $TestDepends\psgallerymodule.sameversion.depend.psd1 + $Dep | Invoke-DependencyScript -PSDependAction Test -Quiet | Should -Be $True } } } \ No newline at end of file diff --git a/Tests/PSModuleGallery.Type.Tests.ps1 b/Tests/PSModuleGallery.Type.Tests.ps1 index a2477d4..8f9cc67 100644 --- a/Tests/PSModuleGallery.Type.Tests.ps1 +++ b/Tests/PSModuleGallery.Type.Tests.ps1 @@ -1,204 +1,229 @@ -if(-not $ENV:BHProjectPath) -{ - Set-BuildEnvironment -Path "$PSScriptRoot/.." +BeforeDiscovery { + if ($null -eq $env:BHPSModuleManifest) { + & "$PSScriptRoot/../Build.ps1" -Task Init + } + $manifest = Import-PowerShellDataFile -Path $env:BHPSModuleManifest + $outputDir = Join-Path -Path $env:BHProjectPath -ChildPath 'Output' + $outputModDir = Join-Path -Path $outputDir -ChildPath $env:BHProjectName + $outputModVerDir = Join-Path -Path $outputModDir -ChildPath $manifest.ModuleVersion + $outputModVerManifest = Join-Path -Path $outputModVerDir -ChildPath "$($env:BHProjectName).psd1" + + Get-Module $env:BHProjectName | Remove-Module -Force -ErrorAction Ignore + Import-Module -Name $outputModVerManifest -Verbose:$false -ErrorAction Stop + + if($IsLinux -or $IsMacOS) { + # Skip tests tagged WindowsOnly on non-Windows platforms + $nonWindows = $true + } + $PSVersion = $PSVersionTable.PSVersion.Major } -Remove-Module $ENV:BHProjectName -ErrorAction SilentlyContinue -Import-Module (Join-Path $ENV:BHProjectPath $ENV:BHProjectName) -Force - -# Maybe use a convention for describe/context/it... these are all over the place... -# Pull requests welcome! - -InModuleScope 'PSDepend' { - $TestDepends = Join-Path $ENV:BHProjectPath "Tests/DependFiles" - $PSVersion = $PSVersionTable.PSVersion.Major - $ProjectRoot = $ENV:BHProjectPath - $ExistingPSModulePath = $env:PSModulePath.PSObject.Copy() - $ExistingPath = $env:PATH.PSObject.Copy() - - $Password = 'testPassword' | ConvertTo-SecureString -AsPlainText -Force - $TestCredential = New-Object System.Management.Automation.PSCredential('testUser', $Password) - $OtherCredential = New-Object System.Management.Automation.PSCredential('otherUser', $Password) - $Credentials = @{ - 'imaginaryCreds' = $TestCredential - 'otherCreds' = $OtherCredential - } +Describe "PSModuleGallery Type" -Tag 'Integration' { + BeforeAll { + $script:TestDepends = Join-Path $ENV:BHProjectPath "Tests/DependFiles" + $script:ProjectRoot = $ENV:BHProjectPath + $script:ExistingPSModulePath = $env:PSModulePath.PSObject.Copy() + $script:ExistingPath = $env:PATH.PSObject.Copy() + + $script:Password = 'testPassword' | ConvertTo-SecureString -AsPlainText -Force + $script:TestCredential = New-Object System.Management.Automation.PSCredential('testUser', $script:Password) + $script:OtherCredential = New-Object System.Management.Automation.PSCredential('otherUser', $script:Password) + $script:Credentials = @{ + 'imaginaryCreds' = $script:TestCredential + 'otherCreds' = $script:OtherCredential + } - $Verbose = @{} - if($ENV:BHBranchName -notlike "master" -or $env:BHCommitMessage -match "!verbose") - { - $Verbose.add("Verbose",$True) + $script:Verbose = @{} + if($ENV:BHBranchName -notlike "master" -or $env:BHCommitMessage -match "!verbose") { + $script:Verbose.add("Verbose",$True) + } } Describe "PSGalleryModule Type PS$PSVersion" { - - $SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + BeforeAll { + $script:SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + } Context 'Installs Modules' { - Mock Install-Module { Return $true } - - $Results = Invoke-PSDepend @Verbose -Path "$TestDepends/psgallerymodule.depend.psd1" -Force + BeforeAll { + Mock Install-Module { return $true } -ModuleName PSDepend + $script:Results = Invoke-PSDepend @Verbose -Path "$TestDepends/psgallerymodule.depend.psd1" -Force + } It 'Should execute Install-Module' { - Assert-MockCalled Install-Module -Times 1 -Exactly + Should -Invoke Install-Module -Times 1 -Exactly -Scope Context -ModuleName PSDepend } It 'Should Return Mocked output' { - $Results | Should be $True + $script:Results | Should -Be $True } - } - - Context 'Installs Modules with credentials' { - Mock Install-Module { Return $true } - - $Results = Invoke-PSDepend @Verbose -Path "$TestDepends/psgallerymodule.withcredentials.depend.psd1" -Force -Credentials $Credentials + } - It 'Should execute Install-Module' { - Assert-MockCalled Install-Module -Times 1 -Exactly -ParameterFilter { $Credential -ne $null -and $Credential.Username -eq 'testUser' } - } + Context 'Installs Modules with credentials' { + BeforeAll { + Mock Install-Module { return $true } -ModuleName PSDepend + $script:Results = Invoke-PSDepend @Verbose -Path "$TestDepends/psgallerymodule.withcredentials.depend.psd1" -Force -Credentials $Credentials + } - It 'Should Return Mocked output' { - $Results | Should be $True - } - } + It 'Should execute Install-Module' { + Should -Invoke Install-Module -Times 1 -Exactly -ParameterFilter { $Credential -ne $null -and $Credential.Username -eq 'testUser' } -Scope Context -ModuleName PSDepend + } - Context 'Installs Modules with multiple credentials' { - Mock Install-Module { Return $true } + It 'Should Return Mocked output' { + $script:Results | Should -Be $True + } + } - $Results = Invoke-PSDepend @Verbose -Path "$TestDepends/psgallerymodule.multiplecredentials.depend.psd1" -Force -Credentials $Credentials + Context 'Installs Modules with multiple credentials' { + BeforeAll { + Mock Install-Module { return $true } -ModuleName PSDepend + $script:Results = Invoke-PSDepend @Verbose -Path "$TestDepends/psgallerymodule.multiplecredentials.depend.psd1" -Force -Credentials $Credentials + } - It 'Should execute Install-Module with the correct credentials' { - Assert-MockCalled Install-Module -Times 1 -Exactly -ParameterFilter { $Name -eq 'imaginary' -and $Credential -ne $null -and $Credential.Username -eq 'testUser' } - Assert-MockCalled Install-Module -Times 1 -Exactly -ParameterFilter { $Name -eq 'other' -and $Credential -ne $null -and $Credential.Username -eq 'otherUser' } - } + It 'Should execute Install-Module with the correct credentials' { + Should -Invoke Install-Module -Times 1 -Exactly -ParameterFilter { $Name -eq 'imaginary' -and $Credential -ne $null -and $Credential.Username -eq 'testUser' } -Scope Context -ModuleName PSDepend + Should -Invoke Install-Module -Times 1 -Exactly -ParameterFilter { $Name -eq 'other' -and $Credential -ne $null -and $Credential.Username -eq 'otherUser' } -Scope Context -ModuleName PSDepend + } - It 'Should Return Mocked output' { - $Results | Should be @($True, $True) - } - } + It 'Should Return Mocked output' { + $script:Results | Should -Be @($True, $True) + } + } Context 'Saves Modules' { - Mock Save-Module { Return $true } - - $Results = Invoke-PSDepend @Verbose -Path "$TestDepends/savemodule.depend.psd1" -Force + BeforeAll { + Mock Save-Module { return $true } -ModuleName PSDepend + $script:Results = Invoke-PSDepend @Verbose -Path "$TestDepends/savemodule.depend.psd1" -Force + } It 'Should execute Save-Module' { - Assert-MockCalled Save-Module -Times 1 -Exactly + Should -Invoke Save-Module -Times 1 -Exactly -Scope Context -ModuleName PSDepend } It 'Should Return Mocked output' { - $Results | Should be $True + $script:Results | Should -Be $True } } - Context 'Saves Modules with credentials' { - Mock Save-Module { Return $true } - - $Results = Invoke-PSDepend @Verbose -Path "$TestDepends/savemodule.withcredentials.depend.psd1" -Force -Credentials $Credentials + Context 'Saves Modules with credentials' { + BeforeAll { + Mock Save-Module { return $true } -ModuleName PSDepend + $script:Results = Invoke-PSDepend @Verbose -Path "$TestDepends/savemodule.withcredentials.depend.psd1" -Force -Credentials $Credentials + } - It 'Should execute Save-Module' { - Assert-MockCalled Save-Module -Times 1 -Exactly -ParameterFilter { $Credential -ne $null -and $Credential.Username -eq 'testUser' } - } + It 'Should execute Save-Module' { + Should -Invoke Save-Module -Times 1 -Exactly -ParameterFilter { $Credential -ne $null -and $Credential.Username -eq 'testUser' } -Scope Context -ModuleName PSDepend + } - It 'Should Return Mocked output' { - $Results | Should be $True - } - } + It 'Should Return Mocked output' { + $script:Results | Should -Be $True + } + } Context 'Repository does not Exist' { - Mock Install-Module { throw "Unable to find repository 'Blah'" } -ParameterFilter { $Repository -eq 'Blah'} + BeforeAll { + Mock Install-Module { throw "Unable to find repository 'Blah'" } -ParameterFilter { $Repository -eq 'Blah' } -ModuleName PSDepend + } It 'Throws because Repository could not be found' { $Results = { Invoke-PSDepend @Verbose -Path "$TestDepends/psgallerymodule.missingrepo.depend.psd1" -Force -ErrorAction Stop } - $Results | Should Throw + $Results | Should -Throw } } Context 'Same module version exists (Version)' { - Mock Install-Module {} - Mock Get-Module { - [pscustomobject]@{ - Version = '1.2.5' - } + BeforeAll { + Mock Install-Module {} -ModuleName PSDepend + Mock Get-Module { + [pscustomobject]@{ + Version = '1.2.5' + } + } -ModuleName PSDepend + Mock Find-Module -ModuleName PSDepend } - Mock Find-Module It 'Skips Install-Module' { Invoke-PSDepend @Verbose -Path "$TestDepends/psgallerymodule.sameversion.depend.psd1" -Force -ErrorAction Stop - Assert-MockCalled Get-Module -Times 1 -Exactly - Assert-MockCalled Find-Module -Times 0 -Exactly - Assert-MockCalled Install-Module -Times 0 -Exactly + Should -Invoke Get-Module -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Find-Module -Times 0 -Exactly -ModuleName PSDepend + Should -Invoke Install-Module -Times 0 -Exactly -ModuleName PSDepend } } Context 'Same module version exists (SemVersion)' { - Mock Install-Module {} - Mock Get-Module { - [pscustomobject]@{ - Version = '1.2.5-preview0002' - } + BeforeAll { + Mock Install-Module {} -ModuleName PSDepend + Mock Get-Module { + [pscustomobject]@{ + Version = '1.2.5-preview0002' + } + } -ModuleName PSDepend + Mock Find-Module -ModuleName PSDepend } - Mock Find-Module It 'Skips Install-Module' { Invoke-PSDepend @Verbose -Path "$TestDepends/psgallerymodule.SameSemanticVersion.depend.psd1" -Force -ErrorAction Stop - Assert-MockCalled Get-Module -Times 1 -Exactly - Assert-MockCalled Find-Module -Times 0 -Exactly - Assert-MockCalled Install-Module -Times 0 -Exactly + Should -Invoke Get-Module -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Find-Module -Times 0 -Exactly -ModuleName PSDepend + Should -Invoke Install-Module -Times 0 -Exactly -ModuleName PSDepend } } Context 'Latest module required, and already installed (version)' { - Mock Install-Module {} - Mock Get-Module { - [pscustomobject]@{ - Version = '1.2.5' - } - } - Mock Find-Module { - [pscustomobject]@{ - Version = '1.2.5' - } + BeforeAll { + Mock Install-Module {} -ModuleName PSDepend + Mock Get-Module { + [pscustomobject]@{ + Version = '1.2.5' + } + } -ModuleName PSDepend + Mock Find-Module { + [pscustomobject]@{ + Version = '1.2.5' + } + } -ModuleName PSDepend } It 'Skips Install-Module' { Invoke-PSDepend @Verbose -Path "$TestDepends/psgallerymodule.latestversion.depend.psd1" -Force -ErrorAction Stop - Assert-MockCalled Get-Module -Times 1 -Exactly - Assert-MockCalled Find-Module -Times 1 -Exactly - Assert-MockCalled Install-Module -Times 0 -Exactly + Should -Invoke Get-Module -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Find-Module -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Install-Module -Times 0 -Exactly -ModuleName PSDepend } } Context 'Latest module required, and already installed (SemVersion)' { - Mock Install-Module {} - Mock Get-Module { - [pscustomobject]@{ - Version = '1.2.5-preview0002' - } - } - Mock Find-Module { - [pscustomobject]@{ - Version = '1.2.5-preview0002' - } + BeforeAll { + Mock Install-Module {} -ModuleName PSDepend + Mock Get-Module { + [pscustomobject]@{ + Version = '1.2.5-preview0002' + } + } -ModuleName PSDepend + Mock Find-Module { + [pscustomobject]@{ + Version = '1.2.5-preview0002' + } + } -ModuleName PSDepend } It 'Skips Install-Module' { Invoke-PSDepend @Verbose -Path "$TestDepends/psgallerymodule.latestversion.depend.psd1" -Force -ErrorAction Stop - Assert-MockCalled Get-Module -Times 1 -Exactly - Assert-MockCalled Find-Module -Times 1 -Exactly - Assert-MockCalled Install-Module -Times 0 -Exactly + Should -Invoke Get-Module -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Find-Module -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Install-Module -Times 0 -Exactly -ModuleName PSDepend } } Context 'Test-Dependency' { BeforeEach { - Mock Install-Module {} - Mock Find-Module {} + Mock Install-Module {} -ModuleName PSDepend + Mock Find-Module {} -ModuleName PSDepend } It 'Returns $true when it finds an existing module (Version)' { @@ -206,11 +231,11 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ Version = '1.2.5' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends/psgallerymodule.sameversion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $True + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $True } It 'Returns $true when it finds an existing module (SemVersion)' { @@ -218,11 +243,11 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ Version = '1.2.5-preview0002' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends/psgallerymodule.SameSemanticVersion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $True + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $True } It 'Returns $true when it finds an existing latest module (Version)' { @@ -230,16 +255,16 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ Version = '1.2.5' } - } + } -ModuleName PSDepend Mock Find-Module { [pscustomobject]@{ Version = '1.2.5' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends/psgallerymodule.latestversion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $True + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $True } It 'Returns $true when it finds an existing latest module (SemVersion)' { @@ -247,32 +272,32 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ Version = '1.2.5-preview0002' } - } + } -ModuleName PSDepend Mock Find-Module { [pscustomobject]@{ Version = '1.2.5-preview0002' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends/psgallerymodule.latestversion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $True + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $True } It "Returns `$false when it doesn't find an existing module (Version)" { - Mock Get-Module { $null } + Mock Get-Module { $null } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends/psgallerymodule.sameversion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $False + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $False } It "Returns `$false when it doesn't find an existing module (SemVersion)" { - Mock Get-Module { $null } + Mock Get-Module { $null } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends/psgallerymodule.SameSemanticVersion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $False + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $False } It "Returns `$false when it finds an existing module with a lower version (Version)" { @@ -280,11 +305,11 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ Version = '1.2.4' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends/psgallerymodule.sameversion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $False + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $False } It 'Returns $false when it finds an existing module with a lower version (SemVersion)' { @@ -292,11 +317,11 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ Version = '1.2.5-preview0001' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends/psgallerymodule.SameSemanticVersion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $False + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $False } It 'Returns $false when it finds an existing module with a lower version (SemVersion-Version)' { @@ -304,11 +329,11 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ Version = '1.2.4' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends/psgallerymodule.SameSemanticVersion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $False + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $False } It 'Returns $false when it finds an existing module with a lower version than latest (Version)' { @@ -316,16 +341,16 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ Version = '1.2.4' } - } + } -ModuleName PSDepend Mock Find-Module { [pscustomobject]@{ Version = '1.2.5' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends/psgallerymodule.latestversion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $False + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $False } It 'Returns $false when it finds an existing module with a lower version than latest (SemVersion)' { @@ -333,35 +358,44 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ Version = '1.2.5-preview0001' } - } + } -ModuleName PSDepend Mock Find-Module { [pscustomobject]@{ Version = '1.2.5-preview0002' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends/psgallerymodule.latestversion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $False + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $False } } Context 'Imports dependencies' { + BeforeAll { + Mock Install-Module {} -ModuleName PSDepend + Mock Import-Module -ModuleName PSDepend + } + It 'Runs Import-Module when import is specified' { - Mock Install-Module {} - Mock Import-Module $Results = Get-Dependency @Verbose -Path "$TestDepends/psgallerymodule.depend.psd1" | Import-Dependency @Verbose - Assert-MockCalled -CommandName Import-Module -Times 1 -Exactly - Assert-MockCalled -CommandName Install-Module -Times 0 -Exactly + Should -Invoke Import-Module -Times 1 -Exactly -Scope Context -ModuleName PSDepend + Should -Invoke Install-Module -Times 0 -Exactly -Scope Context -ModuleName PSDepend } } Context 'AddToPath on install of module to target folder' { + BeforeAll { + Mock Save-Module { $True } -ModuleName PSDepend + } + + AfterEach { + $ENV:PSModulePath = $script:ExistingPSModulePath + } + It 'Adds folder to path' { - Mock Save-Module {$True} Invoke-PSDepend @Verbose -Path "$TestDepends\psgallerymodule.addtopath.depend.psd1" -Force -ErrorAction Stop - ($env:PSModulePath -split ([IO.Path]::PathSeparator)) -contains $SavePath | Should Be $True - $ENV:PSModulePath = $ExistingPSModulePath + ($env:PSModulePath -split ([IO.Path]::PathSeparator)) -contains $script:SavePath | Should -Be $True } } @@ -378,17 +412,19 @@ InModuleScope 'PSDepend' { } ) - Mock Install-Module - Mock Import-Module - Mock Get-Module { - [pscustomobject]@{ - Version = '1.2.5' - } - } - Mock Find-Module { - [pscustomobject]@{ - Version = '1.2.5' - } + BeforeAll { + Mock Install-Module -ModuleName PSDepend + Mock Import-Module -ModuleName PSDepend + Mock Get-Module { + [pscustomobject]@{ + Version = '1.2.5' + } + } -ModuleName PSDepend + Mock Find-Module { + [pscustomobject]@{ + Version = '1.2.5' + } + } -ModuleName PSDepend } AfterEach { @@ -402,220 +438,238 @@ InModuleScope 'PSDepend' { Invoke-PSDepend @Verbose -Path "$TestDepends\$DependPsd1File" -Import -Force -ErrorAction Stop # check assumption that expected code path was followed... - Assert-MockCalled Install-Module -Times 0 -Exactly -Scope It - Assert-MockCalled Import-Module -Times 1 -Exactly -Scope It + Should -Invoke Install-Module -Times 0 -Exactly -ModuleName PSDepend + Should -Invoke Import-Module -Times 1 -Exactly -ModuleName PSDepend # then - ($env:PSModulePath -split ([IO.Path]::PathSeparator)) -contains $SavePath | Should Be $True + ($env:PSModulePath -split ([IO.Path]::PathSeparator)) -contains $script:SavePath | Should -Be $True } } -#> + Context 'SkipPublisherCheck' { + BeforeAll { + Mock Get-PSRepository { return $true } -ModuleName PSDepend + Mock Install-Module {} -ModuleName PSDepend + } + It 'Supplies SkipPublisherCheck switch to Install-Module' { - Mock Get-PSRepository { Return $true } - Mock Install-Module {} Invoke-PSDepend @Verbose -Path "$TestDepends\psgallerymodule.skippubcheck.depend.psd1" -Force -ErrorAction Stop - Assert-MockCalled -CommandName Install-Module -Times 1 -Exactly -ExclusiveFilter { + Should -Invoke Install-Module -Times 1 -Exactly -Scope Context -ModuleName PSDepend + Should -Invoke Install-Module -Times 1 -Exactly -Scope Context -ModuleName PSDepend -ParameterFilter { $SkipPublisherCheck -eq $true } } } Context 'AllowPrerelease' { + BeforeAll { + Mock Get-PSRepository { return $true } -ModuleName PSDepend + Mock Install-Module {} -ModuleName PSDepend + } + It 'Supplies AllowPrerelease switch to Install-Module' { - Mock Get-PSRepository { Return $true } - Mock Install-Module {} Invoke-PSDepend @Verbose -Path "$TestDepends\psgallerymodule.AllowPrerelease.depend.psd1" -Force -ErrorAction Stop - Assert-MockCalled -CommandName Install-Module -Times 1 -Exactly -ExclusiveFilter { + Should -Invoke Install-Module -Times 1 -Exactly -Scope Context -ModuleName PSDepend + Should -Invoke Install-Module -Times 1 -Exactly -Scope Context -ModuleName PSDepend -ParameterFilter { $AllowPrerelease -eq $true } } } } - Describe "Git Type PS$PSVersion" -Tag "WindowsOnly" { - - $SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + Describe "Git Type PS$PSVersion" -Skip:$nonWindows { + BeforeAll { + $script:SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + } Context 'Installs Module' { - Mock Invoke-ExternalCommand { - [pscustomobject]@{ - PSB = $PSBoundParameters - Arg = $Args - } - } -ParameterFilter {$Arguments -contains 'checkout' -or $Arguments -contains 'clone'} - Mock New-Item { return $true } - Mock Push-Location {} - Mock Pop-Location {} - Mock Set-Location {} - Mock Test-Path { return $False } -ParameterFilter {$Path -match "Invoke-Build$|PSDeploy$"} + BeforeAll { + Mock Invoke-ExternalCommand { + [pscustomobject]@{ + PSB = $PSBoundParameters + Arg = $Args + } + } -ModuleName PSDepend -ParameterFilter { $Arguments -contains 'checkout' -or $Arguments -contains 'clone' } + Mock New-Item { return $true } -ModuleName PSDepend + Mock Push-Location {} -ModuleName PSDepend + Mock Pop-Location {} -ModuleName PSDepend + Mock Set-Location {} -ModuleName PSDepend + Mock Test-Path { return $False } -ModuleName PSDepend -ParameterFilter { $Path -match "Invoke-Build$|PSDeploy$" } - $Dependencies = Get-Dependency @Verbose -Path "$TestDepends\git.depend.psd1" + $script:Dependencies = Get-Dependency @Verbose -Path "$TestDepends\git.depend.psd1" + $script:Results = Invoke-PSDepend @Verbose -Path "$TestDepends\git.depend.psd1" -Force + } It 'Parses the Git dependency type' { - $Dependencies.count | Should be 3 - ( $Dependencies | Where {$_.DependencyType -eq 'Git'} ).Count | Should Be 3 - ( $Dependencies | Where {$_.DependencyName -like '*nightroman/Invoke-Build'}).Version | Should be 'ac54571010d8ca5107fc8fa1a69278102c9aa077' - ( $Dependencies | Where {$_.DependencyName -like '*ramblingcookiemonster/PSDeploy'}).Version | Should be 'master' + $script:Dependencies.count | Should -Be 3 + ( $script:Dependencies | Where-Object { $_.DependencyType -eq 'Git' } ).Count | Should -Be 3 + ( $script:Dependencies | Where-Object { $_.DependencyName -like '*nightroman/Invoke-Build' }).Version | Should -Be 'ac54571010d8ca5107fc8fa1a69278102c9aa077' + ( $script:Dependencies | Where-Object { $_.DependencyName -like '*ramblingcookiemonster/PSDeploy' }).Version | Should -Be 'master' } - $Results = Invoke-PSDepend @Verbose -Path "$TestDepends\git.depend.psd1" -Force - It 'Invokes the Git dependency type' { - Assert-MockCalled -CommandName Invoke-ExternalCommand -Times 6 -Exactly + Should -Invoke Invoke-ExternalCommand -Times 6 -Exactly -Scope Context -ModuleName PSDepend } - } Context 'Tests dependency' { - Mock New-Item { return $true } - Mock Push-Location {} - Mock Pop-Location {} - Mock Set-Location {} - Mock Invoke-ExternalCommand -ParameterFilter {$Arguments -contains 'checkout' -or $Arguments -contains 'clone'} - + BeforeAll { + Mock New-Item { return $true } -ModuleName PSDepend + Mock Push-Location {} -ModuleName PSDepend + Mock Pop-Location {} -ModuleName PSDepend + Mock Set-Location {} -ModuleName PSDepend + Mock Invoke-ExternalCommand -ModuleName PSDepend -ParameterFilter { $Arguments -contains 'checkout' -or $Arguments -contains 'clone' } + } It 'Returns $false if git repo does not exist' { - Mock Test-Path { return $False } -ParameterFilter {$Path -match "PSDeploy$"} + Mock Test-Path { return $False } -ModuleName PSDepend -ParameterFilter { $Path -match "PSDeploy$" } $Results = @( Get-Dependency @Verbose -Path "$TestDepends\git.test.depend.psd1" | Test-Dependency @Verbose -Quiet ) - $Results.count | Should be 1 - $Results[0] | Should be $False + $Results.count | Should -Be 1 + $Results[0] | Should -Be $False } It 'Returns $true if git repo does exist' { - Mock Test-Path { return $true } -ParameterFilter {$Path -match "PSDeploy$"} - Mock Invoke-ExternalCommand { return 'imaginary_branch' } -ParameterFilter {$Arguments -contains 'rev-parse'} + Mock Test-Path { return $true } -ModuleName PSDepend -ParameterFilter { $Path -match "PSDeploy$" } + Mock Invoke-ExternalCommand { return 'imaginary_branch' } -ModuleName PSDepend -ParameterFilter { $Arguments -contains 'rev-parse' } $Results = @( Get-Dependency @Verbose -Path "$TestDepends\git.test.depend.psd1" | Test-Dependency @Verbose -Quiet ) - $Results.count | Should be 1 - $Results[0] | Should be $true + $Results.count | Should -Be 1 + $Results[0] | Should -Be $true } } } - Describe "FileDownload Type PS$PSVersion" -Tag "WindowsOnly" { - - $SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + Describe "FileDownload Type PS$PSVersion" -Skip:$nonWindows { + BeforeAll { + $script:SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + } Context 'Installs dependency' { - Mock Get-WebFile { - [pscustomobject]@{ - PSB = $PSBoundParameters - Arg = $Args - } + BeforeAll { + Mock Get-WebFile { + [pscustomobject]@{ + PSB = $PSBoundParameters + Arg = $Args + } + } -ModuleName PSDepend + $script:Dependencies = @(Get-Dependency @Verbose -Path "$TestDepends\filedownload.depend.psd1") } - $Dependencies = @(Get-Dependency @Verbose -Path "$TestDepends\filedownload.depend.psd1") - It 'Parses the FileDownload dependency type' { - $Dependencies.count | Should be 1 - $Dependencies[0].DependencyType | Should be 'FileDownload' + $script:Dependencies.count | Should -Be 1 + $script:Dependencies[0].DependencyType | Should -Be 'FileDownload' } - $Results = Invoke-PSDepend @Verbose -Path "$TestDepends\filedownload.depend.psd1" -Force - It 'Invokes the FileDownload dependency type' { - Assert-MockCalled Get-WebFile -Times 1 -Exactly + Invoke-PSDepend @Verbose -Path "$TestDepends\filedownload.depend.psd1" -Force + Should -Invoke Get-WebFile -Times 1 -Exactly -ModuleName PSDepend } - New-Item -ItemType File -Path (Join-Path $SavePath 'System.Data.SQLite.dll') - $Results = Invoke-PSDepend @Verbose -Path "$TestDepends\filedownload.depend.psd1" -Force - It 'Parses URL file name and skips on existing' { - Assert-MockCalled Get-WebFile -Times 1 -Exactly # already called, so still 1, not 2... + New-Item -ItemType File -Path (Join-Path $script:SavePath 'System.Data.SQLite.dll') -Force + Invoke-PSDepend @Verbose -Path "$TestDepends\filedownload.depend.psd1" -Force + Should -Invoke Get-WebFile -Times 0 -Exactly -ModuleName PSDepend } } - Remove-Item $SavePath -Force -Recurse - $null = New-Item $SavePath -ItemType Directory -Force - Context 'Tests dependency' { + BeforeAll { + Remove-Item $script:SavePath -Force -Recurse -ErrorAction SilentlyContinue + $null = New-Item $script:SavePath -ItemType Directory -Force + } + It 'Returns $false if file does not exist' { - Mock Get-WebFile {} + Mock Get-WebFile {} -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends\filedownload.depend.psd1" | Test-Dependency @Verbose -Quiet) - $Results.count | Should be 1 - $Results[0] | Should be $False - Assert-MockCalled -CommandName Get-WebFile -Times 0 -Exactly + $Results.count | Should -Be 1 + $Results[0] | Should -Be $False + Should -Invoke Get-WebFile -Times 0 -Exactly -ModuleName PSDepend } - New-Item -ItemType File -Path (Join-Path $SavePath 'System.Data.SQLite.dll') -Force It 'Returns $true if file does exist' { - Mock Get-WebFile {} + New-Item -ItemType File -Path (Join-Path $script:SavePath 'System.Data.SQLite.dll') -Force + Mock Get-WebFile {} -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends\filedownload.depend.psd1" | Test-Dependency @Verbose -Quiet) - $Results.count | Should be 1 - $Results[0] | Should be $true - Assert-MockCalled -CommandName Get-WebFile -Times 0 -Exactly + $Results.count | Should -Be 1 + $Results[0] | Should -Be $true + Should -Invoke Get-WebFile -Times 0 -Exactly -ModuleName PSDepend } } } - Describe "PSGalleryNuget Type PS$PSVersion" -Tag "WindowsOnly" { - - $SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + Describe "PSGalleryNuget Type PS$PSVersion" -Skip:$nonWindows { + BeforeAll { + $script:SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + } Context 'Installs Modules' { - Mock Test-Path { Return $true } -ParameterFilter { $PathType -eq 'Container' } - Mock Invoke-ExternalCommand { Return $true } - Mock Find-NugetPackage { Return $true } - - $Results = Invoke-PSDepend @Verbose -Path "$TestDepends\psgallerynuget.depend.psd1" -Force + BeforeAll { + Mock Test-Path { return $true } -ModuleName PSDepend -ParameterFilter { $PathType -eq 'Container' } + Mock Invoke-ExternalCommand { return $true } -ModuleName PSDepend + Mock Find-NugetPackage { return $true } -ModuleName PSDepend + $script:Results = Invoke-PSDepend @Verbose -Path "$TestDepends\psgallerynuget.depend.psd1" -Force + } It 'Should execute Invoke-ExternalCommand' { - Assert-MockCalled Invoke-ExternalCommand -Times 1 -Exactly + Should -Invoke Invoke-ExternalCommand -Times 1 -Exactly -Scope Context -ModuleName PSDepend } It 'Should Return Mocked output' { - $Results | Should be $True + $script:Results | Should -Be $True } } Context 'Same module version exists' { - Mock Test-Path {return $True} -ParameterFilter {$Path -match 'jenkins'} - Mock Invoke-ExternalCommand {} - Mock Import-LocalizedData { - [pscustomobject]@{ - ModuleVersion = '1.2.5' - } - } -ParameterFilter {$FileName -eq 'jenkins.psd1'} - Mock Find-NugetPackage + BeforeAll { + Mock Test-Path { return $True } -ModuleName PSDepend -ParameterFilter { $Path -match 'jenkins' } + Mock Invoke-ExternalCommand {} -ModuleName PSDepend + Mock Import-LocalizedData { + [pscustomobject]@{ + ModuleVersion = '1.2.5' + } + } -ModuleName PSDepend -ParameterFilter { $FileName -eq 'jenkins.psd1' } + Mock Find-NugetPackage -ModuleName PSDepend + } It 'Skips Invoke-ExternalCommand' { Invoke-PSDepend @Verbose -Path "$TestDepends\psgallerynuget.sameversion.depend.psd1" -Force -ErrorAction Stop - Assert-MockCalled Import-LocalizedData -Times 1 -Exactly - Assert-MockCalled Find-NugetPackage -Times 0 -Exactly - Assert-MockCalled Invoke-ExternalCommand -Times 0 -Exactly + Should -Invoke Import-LocalizedData -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Find-NugetPackage -Times 0 -Exactly -ModuleName PSDepend + Should -Invoke Invoke-ExternalCommand -Times 0 -Exactly -ModuleName PSDepend } } Context 'Latest module required, and already installed' { - Mock Test-Path {return $True} -ParameterFilter {$Path -match 'jenkins'} - Mock Invoke-ExternalCommand {} - Mock Import-LocalizedData { - [pscustomobject]@{ - ModuleVersion = '1.2.5' - } - } -ParameterFilter {$FileName -eq 'jenkins.psd1'} - Mock Find-NugetPackage { - [pscustomobject]@{ - Version = '1.2.5' - } + BeforeAll { + Mock Test-Path { return $True } -ModuleName PSDepend -ParameterFilter { $Path -match 'jenkins' } + Mock Invoke-ExternalCommand {} -ModuleName PSDepend + Mock Import-LocalizedData { + [pscustomobject]@{ + ModuleVersion = '1.2.5' + } + } -ModuleName PSDepend -ParameterFilter { $FileName -eq 'jenkins.psd1' } + Mock Find-NugetPackage { + [pscustomobject]@{ + Version = '1.2.5' + } + } -ModuleName PSDepend } It 'Skips Invoke-ExternalCommand' { Invoke-PSDepend @Verbose -Path "$TestDepends\psgallerynuget.latestversion.depend.psd1" -Force -ErrorAction Stop - Assert-MockCalled Import-LocalizedData -Times 1 -Exactly - Assert-MockCalled Find-NugetPackage -Times 1 -Exactly - Assert-MockCalled Invoke-ExternalCommand -Times 0 -Exactly + Should -Invoke Import-LocalizedData -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Find-NugetPackage -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Invoke-ExternalCommand -Times 0 -Exactly -ModuleName PSDepend } } Context 'Tests dependencies' { BeforeEach { - Mock Invoke-ExternalCommand {} - Mock Test-Path {return $True} -ParameterFilter {$Path -match 'jenkins'} - Mock Find-NugetPackage {} + Mock Invoke-ExternalCommand {} -ModuleName PSDepend + Mock Test-Path { return $True } -ModuleName PSDepend -ParameterFilter { $Path -match 'jenkins' } + Mock Find-NugetPackage {} -ModuleName PSDepend } It 'Returns $true when it finds an existing module' { @@ -623,11 +677,11 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ ModuleVersion = '1.2.5' } - } -ParameterFilter {$FileName -eq 'jenkins.psd1'} + } -ModuleName PSDepend -ParameterFilter { $FileName -eq 'jenkins.psd1' } $Results = @( Get-Dependency @Verbose -Path "$TestDepends\psgallerynuget.sameversion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $True + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $True } It 'Returns $true when it finds an existing latest module' { @@ -635,24 +689,24 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ ModuleVersion = '1.2.5' } - } -ParameterFilter {$FileName -eq 'jenkins.psd1'} + } -ModuleName PSDepend -ParameterFilter { $FileName -eq 'jenkins.psd1' } Mock Find-NugetPackage { [pscustomobject]@{ Version = '1.2.5' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends\psgallerynuget.latestversion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $True + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $True } It "Returns `$false when it doesn't find an existing module" { - Mock Import-LocalizedData -ParameterFilter {$FileName -eq 'jenkins.psd1'} + Mock Import-LocalizedData -ModuleName PSDepend -ParameterFilter { $FileName -eq 'jenkins.psd1' } $Results = @( Get-Dependency @Verbose -Path "$TestDepends\psgallerynuget.sameversion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $False + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $False } It "Returns `$false when it finds an existing module with a lower version" { @@ -660,12 +714,12 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ ModuleVersion = '1.2.4' } - } -ParameterFilter {$FileName -eq 'jenkins.psd1'} + } -ModuleName PSDepend -ParameterFilter { $FileName -eq 'jenkins.psd1' } $Results = @( Get-Dependency @Verbose -Path "$TestDepends\psgallerynuget.sameversion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $False + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $False } It "Returns `$false when it finds an existing module with a lower version than latest" { @@ -673,41 +727,49 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ ModuleVersion = '1.2.4' } - } -ParameterFilter {$FileName -eq 'jenkins.psd1'} + } -ModuleName PSDepend -ParameterFilter { $FileName -eq 'jenkins.psd1' } Mock Find-NugetPackage { [pscustomobject]@{ Version = '1.2.5' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends\psgallerynuget.latestversion.depend.psd1" | Test-Dependency -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $False + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $False } } Context 'Imports dependencies' { + BeforeAll { + Mock Invoke-ExternalCommand { $True } -ModuleName PSDepend + Mock Import-Module -ModuleName PSDepend + } + It 'Runs Import-Module when import is specified' { - Mock Invoke-ExternalCommand {$True} - Mock Import-Module $Results = Get-Dependency @Verbose -Path "$TestDepends\psgallerynuget.depend.psd1" | Import-Dependency @Verbose - Assert-MockCalled -CommandName Import-Module -Times 1 -Exactly - Assert-MockCalled -CommandName Invoke-ExternalCommand -Times 0 -Exactly + Should -Invoke Import-Module -Times 1 -Exactly -Scope Context -ModuleName PSDepend + Should -Invoke Invoke-ExternalCommand -Times 0 -Exactly -Scope Context -ModuleName PSDepend } } Context 'AddToPath on install of module to target folder' { + BeforeAll { + Mock Invoke-ExternalCommand { $True } -ModuleName PSDepend + Mock Import-Module -ModuleName PSDepend + } + + AfterEach { + $ENV:PSModulePath = $script:ExistingPSModulePath + } + It 'Adds folder to path' { - Mock Invoke-ExternalCommand {$True} - Mock Import-Module $Results = Invoke-PSDepend @Verbose -Path "$TestDepends\psgallerynuget.addtopath.depend.psd1" -Force -ErrorAction Stop - $env:PSModulePath -split ([IO.Path]::PathSeparator) -contains $SavePath | Should Be $True - $ENV:PSModulePath = $ExistingPSModulePath + $env:PSModulePath -split ([IO.Path]::PathSeparator) -contains $script:SavePath | Should -Be $True } } - Context 'AddToPath on import of module in target folder' { $addToPathTestCases = @( @@ -721,18 +783,20 @@ InModuleScope 'PSDepend' { } ) - Mock Test-Path {return $True} -ParameterFilter {$Path -match 'imaginary'} - Mock Invoke-ExternalCommand {} - Mock Import-Module - Mock Import-LocalizedData { - [pscustomobject]@{ - ModuleVersion = '1.2.5' - } - } -ParameterFilter {$FileName -eq 'imaginary.psd1'} - Mock Find-NugetPackage { - [pscustomobject]@{ - Version = '1.2.5' - } + BeforeAll { + Mock Test-Path { return $True } -ModuleName PSDepend -ParameterFilter { $Path -match 'imaginary' } + Mock Invoke-ExternalCommand {} -ModuleName PSDepend + Mock Import-Module -ModuleName PSDepend + Mock Import-LocalizedData { + [pscustomobject]@{ + ModuleVersion = '1.2.5' + } + } -ModuleName PSDepend -ParameterFilter { $FileName -eq 'imaginary.psd1' } + Mock Find-NugetPackage { + [pscustomobject]@{ + Version = '1.2.5' + } + } -ModuleName PSDepend } AfterEach { @@ -746,181 +810,171 @@ InModuleScope 'PSDepend' { Invoke-PSDepend @Verbose -Path "$TestDepends\$DependPsd1File" -Import -Force -ErrorAction Stop # check assumption that expected code path was followed... - Assert-MockCalled Invoke-ExternalCommand -Times 0 -Exactly -Scope It - Assert-MockCalled Import-Module -Times 1 -Exactly -Scope It + Should -Invoke Invoke-ExternalCommand -Times 0 -Exactly -ModuleName PSDepend + Should -Invoke Import-Module -Times 1 -Exactly -ModuleName PSDepend # then - (($env:PSModulePath -split ([IO.Path]::PathSeparator))) -contains $SavePath | Should Be $True + (($env:PSModulePath -split ([IO.Path]::PathSeparator))) -contains $script:SavePath | Should -Be $True } } } - Describe "FileSystem Type PS$PSVersion" -Tag "WindowsOnly" { - - $SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + Describe "FileSystem Type PS$PSVersion" -Skip:$nonWindows { + BeforeAll { + $script:SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + } Context 'Installs dependency' { - Mock Copy-Item - - $Dependencies = @(Get-Dependency @Verbose -Path "$TestDepends\filesystem.depend.psd1") + BeforeAll { + Mock Copy-Item -ModuleName PSDepend + $script:Dependencies = @(Get-Dependency @Verbose -Path "$TestDepends\filesystem.depend.psd1") + } It 'Parses the FileDownload dependency type' { - $Dependencies.count | Should be 1 - $Dependencies[0].DependencyType | Should be 'FileSystem' + $script:Dependencies.count | Should -Be 1 + $script:Dependencies[0].DependencyType | Should -Be 'FileSystem' } - $Results = Invoke-PSDepend @Verbose -Path "$TestDepends\filesystem.depend.psd1" -Force - It 'Invokes the FileSystem dependency type' { - Assert-MockCalled Copy-Item -Times 1 -Exactly + Invoke-PSDepend @Verbose -Path "$TestDepends\filesystem.depend.psd1" -Force + Should -Invoke Copy-Item -Times 1 -Exactly -ModuleName PSDepend } - New-Item -ItemType File -Path (Join-Path $SavePath 'notepad.exe') - $Results = Invoke-PSDepend @Verbose -Path "$TestDepends\filesystem.depend.psd1" -Force - It 'Still copies if file hashes do not match' { - Assert-MockCalled Copy-Item -Times 2 -Exactly # already called, so 2... + New-Item -ItemType File -Path (Join-Path $script:SavePath 'notepad.exe') -Force + Invoke-PSDepend @Verbose -Path "$TestDepends\filesystem.depend.psd1" -Force + Should -Invoke Copy-Item -Times 1 -Exactly -ModuleName PSDepend } } - Remove-Item $SavePath -Force -Recurse - $null = New-Item $SavePath -ItemType Directory -Force - Context 'Tests dependency' { + BeforeAll { + Remove-Item $script:SavePath -Force -Recurse -ErrorAction SilentlyContinue + $null = New-Item $script:SavePath -ItemType Directory -Force + } + It 'Returns $false if file does not exist' { - Mock Copy-Item + Mock Copy-Item -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends\filesystem.depend.psd1" | Test-Dependency @Verbose -Quiet) - $Results.count | Should be 1 - $Results[0] | Should be $False - Assert-MockCalled -CommandName Copy-Item -Times 0 -Exactly + $Results.count | Should -Be 1 + $Results[0] | Should -Be $False + Should -Invoke Copy-Item -Times 0 -Exactly -ModuleName PSDepend } - xcopy C:\Windows\notepad.exe $(Join-Path $SavePath '*') /Y - It 'Returns $true if file does exist' { - Mock Copy-Item + xcopy C:\Windows\notepad.exe $(Join-Path $script:SavePath '*') /Y + Mock Copy-Item -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends\filesystem.depend.psd1" | Test-Dependency @Verbose -Quiet) - $Results.count | Should be 1 - $Results[0] | Should be $true - Assert-MockCalled -CommandName Copy-Item -Times 0 -Exactly + $Results.count | Should -Be 1 + $Results[0] | Should -Be $true + Should -Invoke Copy-Item -Times 0 -Exactly -ModuleName PSDepend } } } - Describe "Package Type PS$PSVersion" -tag pkg { - - $SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + Describe "Package Type PS$PSVersion" -Tag pkg { + BeforeAll { + $script:SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + + # Inject stub functions into PSDepend's module scope so Pester generates + # mock proxies from these simple param signatures instead of the real + # PackageManagement/AnyPackage cmdlets (whose multi-parameter-set definitions + # cause ParameterBindingException when called with our test splats). + # NOTE: 'script:' qualifier is required — without it, the function is created + # in a temporary scope that vanishes when the scriptblock returns. + & (Get-Module PSDepend) { + function script:Get-Package { [cmdletbinding()]param($ProviderName, $Name, $RequiredVersion) } + function script:Install-Package { [cmdletbinding()]param($Source, $Name, $RequiredVersion, $Force) } + function script:Find-Package { [cmdletbinding()]param($Name, $Source) } + function script:Get-PackageSource { [cmdletbinding()]param() } + } + } - # So... these didn't work with mocking. Create function, define alias to override any function call, mock that. - function Get-Package {[cmdletbinding()]param( $ProviderName, $Name, $RequiredVersion)} - function Install-Package {[cmdletbinding()]param( $Source, $Name, $RequiredVersion)} + AfterAll { + & (Get-Module PSDepend) { + Remove-Item Function:\Get-Package, Function:\Install-Package, Function:\Find-Package, Function:\Get-PackageSource -ErrorAction SilentlyContinue + } + } - <# Works, but waiting on https://github.com/pester/Pester/issues/604... - # Got past Get-Package, but Install-Package is still giving the parameter error Context 'Installs Packages' { - Mock Get-PackageSource { @([pscustomobject]@{Name = 'chocolatey'; ProviderName = 'chocolatey'}) } - Mock Get-Package - Mock Install-Package { $True } - - $Results = Invoke-PSDepend @Verbose -Path "$TestDepends\package.depend.psd1" -Force + BeforeAll { + Mock Get-PackageSource { @([pscustomobject]@{Name = 'chocolatey'; ProviderName = 'chocolatey'}) } -ModuleName PSDepend + Mock Get-Package -ModuleName PSDepend + Mock Install-Package { $True } -ModuleName PSDepend + $script:Results = Invoke-PSDepend @Verbose -Path "$TestDepends\package.depend.psd1" -Force + } It 'Should execute Install-Package' { - Assert-MockCalled Install-Package -Times 1 -Exactly + Should -Invoke Install-Package -Times 1 -Exactly -Scope Context -ModuleName PSDepend } It 'Should Return Mocked output' { - $Results | Should be $True + $script:Results | Should -Be $True } } - #> Context 'PackageSource does not Exist' { - Mock Install-Package - Mock Get-PackageSource + BeforeAll { + Mock Install-Package -ModuleName PSDepend + Mock Get-PackageSource -ModuleName PSDepend + } It 'Throws because Repository could not be found' { $Results = { Invoke-PSDepend @Verbose -Path "$TestDepends\package.depend.psd1" -Force -ErrorAction Stop } - $Results | Should Throw + $Results | Should -Throw } } Context 'Same package version exists' { - - function Install-Package {[cmdletbinding()]param( $Source, $Name, $RequiredVersion, $Force)} - function Get-PackageSource { @([pscustomobject]@{Name = 'chocolatey'; ProviderName = 'chocolatey'}) } - - It 'Skips Install-Package' { - - Mock Install-Package + BeforeAll { + Mock Get-PackageSource { @([pscustomobject]@{Name = 'chocolatey'; ProviderName = 'chocolatey'}) } -ModuleName PSDepend + Mock Install-Package -ModuleName PSDepend Mock Get-Package { [pscustomobject]@{ Version = '1.1' } - } - Mock Find-Package + } -ModuleName PSDepend + Mock Find-Package -ModuleName PSDepend + } + It 'Skips Install-Package' { Invoke-PSDepend @Verbose -Path "$TestDepends\package.sameversion.depend.psd1" -Force -ErrorAction Stop - Assert-MockCalled Get-Package -Times 1 -Exactly - Assert-MockCalled Find-Package -Times 0 -Exactly - Assert-MockCalled Install-Package -Times 0 -Exactly + Should -Invoke Get-Package -Times 1 -Exactly -Scope Context -ModuleName PSDepend + Should -Invoke Find-Package -Times 0 -Exactly -Scope Context -ModuleName PSDepend + Should -Invoke Install-Package -Times 0 -Exactly -Scope Context -ModuleName PSDepend } } Context 'Latest package required, and already installed' { - - <# - This test works on my machine but not in AppVeyor (!) - The test DOES work in AppVeyor but only if the previous test above is skipped (!!) - - I think this is a problem can be isolated to something to do with Pester Mocks. - - AppVeyor failure: - - "Parameter set cannot be resolved using the specified named parameters. - at line: 188 in C:\projects\psdepend\psdepend\Public\Invoke-DependencyScript.ps1" - - See build logs: https://ci.appveyor.com/project/RamblingCookieMonster/psdepend/build/1.0.124 - - #> - - function Install-Package {[cmdletbinding()]param( $Source, $Name, $RequiredVersion, $Force)} - function Get-PackageSource { @([pscustomobject]@{Name = 'chocolatey'; ProviderName = 'chocolatey'}) } - - It 'Runs Get-Package and Find-Package, skips Install-Package' -Skip { - - Mock Install-Package + BeforeAll { + Mock Get-PackageSource { @([pscustomobject]@{Name = 'chocolatey'; ProviderName = 'chocolatey'}) } -ModuleName PSDepend + Mock Install-Package -ModuleName PSDepend Mock Get-Package { [pscustomobject]@{ Version = '1.1' } - } + } -ModuleName PSDepend Mock Find-Package { [pscustomobject]@{ Version = '1.1' } - } + } -ModuleName PSDepend + } + It 'Runs Get-Package and Find-Package, skips Install-Package' { Invoke-PSDepend @Verbose -Path "$TestDepends\package.latestversion.depend.psd1" -Force -ErrorAction Stop - Assert-MockCalled Get-Package -Times 1 -Exactly - Assert-MockCalled Find-Package -Times 1 -Exactly - Assert-MockCalled Install-Package -Times 0 -Exactly + Should -Invoke Get-Package -Times 1 -Exactly -Scope Context -ModuleName PSDepend + Should -Invoke Find-Package -Times 1 -Exactly -Scope Context -ModuleName PSDepend + Should -Invoke Install-Package -Times 0 -Exactly -Scope Context -ModuleName PSDepend } } Context 'Test-Dependency' { - - if (-not (Get-Command Get-Package -Module PackageManagement)) { - function Get-Package {[cmdletbinding()]param( $ProviderName, $Name, $RequiredVersion) write-verbose "WTF NOW"} - } - if (-not (Get-Command Install-Package -Module PackageManagement)) { - function Install-Package {[cmdletbinding()]param( $Source, $Name, $RequiredVersion, $Force)} - } - function Get-PackageSource { @([pscustomobject]@{Name = 'chocolatey'; ProviderName = 'chocolatey'}) } - BeforeEach { - Mock Install-Package {} - Mock Find-Package {} + Mock Get-PackageSource { @([pscustomobject]@{Name = 'chocolatey'; ProviderName = 'chocolatey'}) } -ModuleName PSDepend + Mock Install-Package {} -ModuleName PSDepend + Mock Find-Package {} -ModuleName PSDepend } It 'Returns $true when it finds an existing module' { @@ -928,11 +982,11 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ Version = '1.1' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends\package.sameversion.depend.psd1" | Test-Dependency @Verbose -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $True + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $True } It 'Returns $true when it finds an existing latest module' { @@ -940,24 +994,24 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ Version = '1.1' } - } + } -ModuleName PSDepend Mock Find-Package { [pscustomobject]@{ Version = '1.1' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends\package.latestversion.depend.psd1" | Test-Dependency @Verbose -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $True + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $True } It "Returns `$false when it doesn't find an existing module" { - Mock Get-Package { $null } + Mock Get-Package { $null } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends\package.sameversion.depend.psd1" | Test-Dependency @Verbose -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $False + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $False } It "Returns `$false when it finds an existing module with a lower version" { @@ -965,11 +1019,11 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ Version = '1.0' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends\package.sameversion.depend.psd1" | Test-Dependency @Verbose -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $False + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $False } It "Returns `$false when it finds an existing module with a lower version than latest" { @@ -977,137 +1031,158 @@ InModuleScope 'PSDepend' { [pscustomobject]@{ Version = '1.0' } - } + } -ModuleName PSDepend Mock Find-Package { [pscustomobject]@{ Version = '1.1' } - } + } -ModuleName PSDepend $Results = @( Get-Dependency @Verbose -Path "$TestDepends\package.latestversion.depend.psd1" | Test-Dependency @Verbose -Quiet ) - $Results.Count | Should be 1 - $Results[0] | Should be $False + $Results.Count | Should -Be 1 + $Results[0] | Should -Be $False } } } Describe "Command Type PS$PSVersion" { - - $SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + BeforeAll { + $script:SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + } Context 'Invokes a command' { - - $Dependencies = @(Get-Dependency @Verbose -Path "$TestDepends\command.depend.psd1") + BeforeAll { + $script:Dependencies = @(Get-Dependency @Verbose -Path "$TestDepends\command.depend.psd1") + } It 'Parses the command dependency type' { - $Dependencies.count | Should be 1 - $Dependencies[0].DependencyType | Should be 'Command' + $script:Dependencies.count | Should -Be 1 + $script:Dependencies[0].DependencyType | Should -Be 'Command' } It 'Invokes a command' { $Output = Invoke-PSDepend @Verbose -Path "$TestDepends\command.depend.psd1" -Force - $Output | Should be 'hello world' + $Output | Should -Be 'hello world' } } } Describe "Npm Type PS$PSVersion" { - - $SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + BeforeAll { + $script:SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName + } Context 'Installs Dependency' { - Mock Get-NodeModule {return $null} - Mock Install-NodeModule {} - Mock New-Item {return true} - Mock Push-Location - Mock Pop-Location + BeforeAll { + Mock Get-NodeModule { return $null } -ModuleName PSDepend + Mock Install-NodeModule {} -ModuleName PSDepend + Mock New-Item { return $true } -ModuleName PSDepend + Mock Push-Location -ModuleName PSDepend + Mock Pop-Location -ModuleName PSDepend - $Dependencies = Get-Dependency @Verbose -Path "$TestDepends\npm.depend.psd1" - $Results = Invoke-PSDepend @Verbose -Path "$TestDepends\npm.depend.psd1" -Force + $script:Dependencies = Get-Dependency @Verbose -Path "$TestDepends\npm.depend.psd1" + $script:Results = Invoke-PSDepend @Verbose -Path "$TestDepends\npm.depend.psd1" -Force + } It 'Parses the Npm dependency type' { - $Dependencies.count | Should be 2 - ( $Dependencies | Where-Object {$_.DependencyType -eq 'Npm'} ).Count | Should Be 2 - ( $Dependencies | Where-Object {$_.DependencyName -like 'gitbook-cli'}).Version | Should be '2.3.0' - ( $Dependencies | Where-Object {$_.DependencyName -like 'gitbook-cli'}).Target | Should be 'Global' - ( $Dependencies | Where-Object {$_.DependencyName -like 'gitbook-summary'}).Version | Should BeNullOrEmpty + $script:Dependencies.count | Should -Be 2 + ( $script:Dependencies | Where-Object { $_.DependencyType -eq 'Npm' } ).Count | Should -Be 2 + ( $script:Dependencies | Where-Object { $_.DependencyName -like 'gitbook-cli' }).Version | Should -Be '2.3.0' + ( $script:Dependencies | Where-Object { $_.DependencyName -like 'gitbook-cli' }).Target | Should -Be 'Global' + ( $script:Dependencies | Where-Object { $_.DependencyName -like 'gitbook-summary' }).Version | Should -BeNullOrEmpty } - It 'Invokes the Nppm dependency type' { - Assert-MockCalled -CommandName Install-NodeModule -Times 2 -Exactly + It 'Invokes the Npm dependency type' { + Should -Invoke Install-NodeModule -Times 2 -Exactly -Scope Context -ModuleName PSDepend } } Context 'Tests Dependency' { - Mock Install-NodeModule {} - Mock New-Item {return true} - Mock Push-Location - Mock Pop-Location + BeforeAll { + Mock Install-NodeModule {} -ModuleName PSDepend + Mock New-Item { return $true } -ModuleName PSDepend + Mock Push-Location -ModuleName PSDepend + Mock Pop-Location -ModuleName PSDepend - $Dependencies = Get-Dependency @Verbose -Path "$TestDepends\npm.depend.psd1" + $script:Dependencies = Get-Dependency @Verbose -Path "$TestDepends\npm.depend.psd1" + } It 'Returns $false if the module is not installed' { - Mock Get-NodeModule {return $null} - Invoke-PSDepend @Verbose -Path "$TestDepends\npm.depend.psd1" -Test -Quiet | Should Be $false + Mock Get-NodeModule { return $null } -ModuleName PSDepend + Invoke-PSDepend @Verbose -Path "$TestDepends\npm.depend.psd1" -Test -Quiet | Should -Be $false } It 'Returns $true if the module is installed' { - Mock Get-NodeModule {return [pscustomobject]@{ - 'gitbook-cli' = @{ - version = '2.3.0' - } - }} -ParameterFilter {$Target -eq 'Global'} - Mock Get-NodeModule {return [pscustomobject]@{ - 'gitbook-summary' = @{ - version = '1.2.3' - } - }} - Invoke-PSDepend @Verbose -Path "$TestDepends\npm.depend.psd1" -Test -Quiet | Should Be $true + Mock Get-NodeModule { return [pscustomobject]@{ + 'gitbook-cli' = @{ + version = '2.3.0' + } + } } -ParameterFilter { $Global -eq $true } -ModuleName PSDepend + Mock Get-NodeModule { return [pscustomobject]@{ + 'gitbook-summary' = @{ + version = '1.2.3' + } + } } -ModuleName PSDepend + Invoke-PSDepend @Verbose -Path "$TestDepends\npm.depend.psd1" -Test -Quiet | Should -Be $true } } } Describe "DotnetSdk Type PS$PSVersion" { - $IsWindowsEnv = !$PSVersionTable.Platform -or $PSVersionTable.Platform -eq "Win32NT" - $GlobalDotnetSdkLocation = if ($IsWindowsEnv) { "$env:LocalAppData\Microsoft\dotnet" } else { "$env:HOME/.dotnet" } - $DotnetFile = if ($IsWindowsEnv) { "dotnet.exe" } else { "dotnet" } - $SavePath = '.dotnet' + BeforeAll { + $script:IsWindowsEnv = !$PSVersionTable.Platform -or $PSVersionTable.Platform -eq "Win32NT" + $script:GlobalDotnetSdkLocation = if ($script:IsWindowsEnv) { + "$env:LocalAppData\Microsoft\dotnet" + } else { + "$env:HOME/.dotnet" + } + $script:DotnetFile = if ($script:IsWindowsEnv) { + "dotnet.exe" + } else { + "dotnet" + } + $script:SavePath = '.dotnet' + } Context 'Installs Dependency' { - $Dependency = Get-Dependency @Verbose -Path "$TestDepends\dotnetsdk.complex.depend.psd1" + BeforeAll { + $script:Dependency = Get-Dependency @Verbose -Path "$TestDepends\dotnetsdk.complex.depend.psd1" + } + It 'Parses the DotnetSdk dependency type' { - $Dependency | Should -Not -BeNullOrEmpty - $Dependency.DependencyType | Should -Be 'DotnetSdk' - $Dependency.Version | Should -Be '2.1.300' - $Dependency.DependencyName | Should -Be 'release' - $Dependency.Target | Should -Be $SavePath + $script:Dependency | Should -Not -BeNullOrEmpty + $script:Dependency.DependencyType | Should -Be 'DotnetSdk' + $script:Dependency.Version | Should -Be '2.1.300' + $script:Dependency.DependencyName | Should -Be 'release' + $script:Dependency.Target | Should -Be $script:SavePath } It 'Installs the .NET Core SDK to the specified directory' { - Mock Test-Dotnet { return $false } + Mock Test-Dotnet { return $false } -ModuleName PSDepend Invoke-PSDepend @Verbose -Path "$TestDepends\dotnetsdk.complex.depend.psd1" -Force - Test-Path $SavePath | Should -BeTrue + Test-Path $script:SavePath | Should -BeTrue } It 'Does nothing if the .NET Core SDK is found' { - Mock Test-Dotnet { return $true } - Mock Install-Dotnet + Mock Test-Dotnet { return $true } -ModuleName PSDepend + Mock Install-Dotnet -ModuleName PSDepend Invoke-PSDepend @Verbose -Path "$TestDepends\dotnetsdk.complex.depend.psd1" -Force - Assert-MockCalled -CommandName Install-Dotnet -Times 0 -Exactly + Should -Invoke Install-Dotnet -Times 0 -Exactly -ModuleName PSDepend } AfterAll { - Remove-Item -Force -Recurse $SavePath -ErrorAction SilentlyContinue + Remove-Item -Force -Recurse $script:SavePath -ErrorAction SilentlyContinue } } Context 'Tests Dependency' { - # used to see if 'dotnet' is already on the PATH - we need this to return false - Mock Get-Command { return $false } -ParameterFilter { $Name -eq 'dotnet' } - Mock Test-Path { return $true } -ParameterFilter { $Path -eq (Join-Path $GlobalDotnetSdkLocation $DotnetFile) } - Mock Get-DotnetVersion { return '2.1.330-rc1' } + BeforeAll { + Mock Get-Command { return $false } -ParameterFilter { $Name -eq 'dotnet' } -ModuleName PSDepend + Mock Test-Path { return $true } -ParameterFilter { $Path -eq (Join-Path $script:GlobalDotnetSdkLocation $script:DotnetFile) } -ModuleName PSDepend + Mock Get-DotnetVersion { return '2.1.330-rc1' } -ModuleName PSDepend + } It 'Can propertly compare semantic versions' { # '2.1.330-rc1' >= '2.1.330-preview1' @@ -1118,66 +1193,56 @@ InModuleScope 'PSDepend' { } Context 'Imports Dependency' { - # used to see if 'dotnet' is already on the PATH - we need this to return false - Mock Get-Command { return $false } -ParameterFilter { $Name -eq 'dotnet' } - BeforeAll { - $originalPath = $env:PATH + Mock Get-Command { return $false } -ParameterFilter { $Name -eq 'dotnet' } -ModuleName PSDepend + $script:originalPath = $env:PATH + } + + AfterEach { + $env:PATH = $script:originalPath } It 'Can add the Target of the .NET Core SDK to the PATH' { - Mock Test-Dotnet { return $true } + Mock Test-Dotnet { return $true } -ModuleName PSDepend Invoke-PSDepend @Verbose -Path "$TestDepends\dotnetsdk.complex.depend.psd1" -Force -Import -ErrorAction Stop - ($env:PATH -split [IO.Path]::PathSeparator)[0] | Should -Be $SavePath + ($env:PATH -split [IO.Path]::PathSeparator)[0] | Should -Be $script:SavePath } It 'Can add the global path of the .NET Core SDK to the PATH' { - Mock Test-Dotnet { return $true } + Mock Test-Dotnet { return $true } -ModuleName PSDepend Invoke-PSDepend @Verbose -Path "$TestDepends\dotnetsdk.simple.depend.psd1" -Force -Import -ErrorAction Stop - ($env:PATH -split [IO.Path]::PathSeparator)[0] | Should -Be $GlobalDotnetSdkLocation + ($env:PATH -split [IO.Path]::PathSeparator)[0] | Should -Be $script:GlobalDotnetSdkLocation } It 'Throws if the path cannot be found' { - Mock Test-Dotnet { return $false } + Mock Test-Dotnet { return $false } -ModuleName PSDepend { Invoke-PSDepend @Verbose -Path "$TestDepends\dotnetsdk.simple.depend.psd1" -Force -Import -ErrorAction Stop } | Should -Throw -ExpectedMessage ".NET SDK cannot be located. Try installing using PSDepend." } - AfterEach { - $env:PATH = $originalPath - } } } - Describe "Chocolatey Type PS$PSVersion" -Tag 'Chocolatey', "WindowsOnly" { + Describe "Chocolatey Type PS$PSVersion" -Tag 'Chocolatey', 'WindowsOnly' -Skip:$nonWindows { + BeforeAll { + $script:SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName - $SavePath = (New-Item 'TestDrive:/PSDependPesterTest' -ItemType Directory -Force).FullName - - # So... these didn't work with mocking. Create function, define alias to override any function call, mock that. - function Invoke-ChocoInstallPackage - { - [cmdletbinding()]param($Name, $Version, $Source, $Force, $Credential) - } - function Get-ChocoLatestPackage - { - [cmdletbinding()]param( $Source, $Name, $RequiredVersion) - } - - function Get-ChocoInstalledPackage - { - [cmdletbinding()]param($Name) + # Simulate choco.exe being present so tests don't hit the install-chocolatey branch by default + Mock Get-Command -ParameterFilter { $Name -eq 'choco.exe' } -MockWith { [pscustomobject]@{Name = 'choco.exe'} } -ModuleName PSDepend + # Default catch-all for Invoke-ExternalCommand; individual tests register specific ParameterFilter mocks + Mock Invoke-ExternalCommand -ModuleName PSDepend } Context 'Chocolatey is not installed' { It 'installs Chocolatey' { - Mock Get-Command -ParameterFilter { $Name -eq 'choco.exe' } -MockWith { return $false } - Mock Invoke-WebRequest + Mock Get-Command -ParameterFilter { $Name -eq 'choco.exe' } -MockWith { return $false } -ModuleName PSDepend + Mock Invoke-WebRequest -ModuleName PSDepend # this will throw as the source is invalid - lets catch that { Invoke-PSDepend @Verbose -Path "$TestDepends\chocolatey.specificversionrequested.depend.psd1" -Force -ErrorAction Stop } | Should -Throw - Assert-MockCalled Get-Command -Times 1 -Exactly - Assert-MockCalled Invoke-WebRequest -Times 1 -Exactly + Should -Invoke Get-Command -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Invoke-WebRequest -Times 1 -Exactly -ModuleName PSDepend } } @@ -1191,64 +1256,55 @@ InModuleScope 'PSDepend' { Context 'Package version installed is what is requested' { It 'skips installing the package' { - - Mock Get-ChocoInstalledPackage { @{ Name = $Name; Version = '1.0' } } - Mock Get-ChocoLatestPackage - Mock Invoke-ChocoInstallPackage + Mock Invoke-ExternalCommand { "7zip|1.0" } -ParameterFilter { $Arguments -contains '--local-only' } -ModuleName PSDepend Invoke-PSDepend @Verbose -Path "$TestDepends\chocolatey.specificversionrequested.depend.psd1" -Force -ErrorAction Stop - Assert-MockCalled Get-ChocoInstalledPackage -Times 1 -Exactly - Assert-MockCalled Get-ChocoLatestPackage -Times 0 -Exactly - Assert-MockCalled Invoke-ChocoInstallPackage -Times 0 -Exactly + Should -Invoke Invoke-ExternalCommand -ParameterFilter { $Arguments -contains '--local-only' } -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Invoke-ExternalCommand -ParameterFilter { $Arguments[0] -eq 'list' -and $Arguments -notcontains '--local-only' } -Times 0 -Exactly -ModuleName PSDepend + Should -Invoke Invoke-ExternalCommand -ParameterFilter { $Arguments[0] -eq 'upgrade' } -Times 0 -Exactly -ModuleName PSDepend } } Context 'Package version installed is latest' { It 'skips installing the package' { - - Mock Get-ChocoInstalledPackage { @{ Name = $Name; Version = '2.0' } } - Mock Get-ChocoLatestPackage { @{ Name = $Name; Version = '2.0' } } - Mock Invoke-ChocoInstallPackage + Mock Invoke-ExternalCommand { "7zip|2.0" } -ParameterFilter { $Arguments -contains '--local-only' } -ModuleName PSDepend + Mock Invoke-ExternalCommand { "7zip|2.0" } -ParameterFilter { $Arguments[0] -eq 'list' -and $Arguments -notcontains '--local-only' } -ModuleName PSDepend Invoke-PSDepend @Verbose -Path "$TestDepends\chocolatey.latestversionrequested.depend.psd1" -Force -ErrorAction Stop - Assert-MockCalled Get-ChocoInstalledPackage -Times 1 -Exactly - Assert-MockCalled Get-ChocoLatestPackage -Times 1 -Exactly - Assert-MockCalled Invoke-ChocoInstallPackage -Times 0 -Exactly + Should -Invoke Invoke-ExternalCommand -ParameterFilter { $Arguments -contains '--local-only' } -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Invoke-ExternalCommand -ParameterFilter { $Arguments[0] -eq 'list' -and $Arguments -notcontains '--local-only' } -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Invoke-ExternalCommand -ParameterFilter { $Arguments[0] -eq 'upgrade' } -Times 0 -Exactly -ModuleName PSDepend } } Context 'Package requested is latest and version installed is newer than available in source' { It 'skips installing the package' { - - Mock Get-ChocoInstalledPackage { @{ Name = $Name; Version = '2.0' } } - Mock Get-ChocoLatestPackage { @{ Name = $Name; Version = '1.0' } } - Mock Invoke-ChocoInstallPackage + Mock Invoke-ExternalCommand { "7zip|2.0" } -ParameterFilter { $Arguments -contains '--local-only' } -ModuleName PSDepend + Mock Invoke-ExternalCommand { "7zip|1.0" } -ParameterFilter { $Arguments[0] -eq 'list' -and $Arguments -notcontains '--local-only' } -ModuleName PSDepend Invoke-PSDepend @Verbose -Path "$TestDepends\chocolatey.latestversionrequested.depend.psd1" -Force -ErrorAction Stop - Assert-MockCalled Get-ChocoInstalledPackage -Times 1 -Exactly - Assert-MockCalled Get-ChocoLatestPackage -Times 1 -Exactly - Assert-MockCalled Invoke-ChocoInstallPackage -Times 0 -Exactly + Should -Invoke Invoke-ExternalCommand -ParameterFilter { $Arguments -contains '--local-only' } -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Invoke-ExternalCommand -ParameterFilter { $Arguments[0] -eq 'list' -and $Arguments -notcontains '--local-only' } -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Invoke-ExternalCommand -ParameterFilter { $Arguments[0] -eq 'upgrade' } -Times 0 -Exactly -ModuleName PSDepend } } Context 'Package requested is latest and version installed is older than available in source' { It 'installs the package' { - - Mock Get-ChocoInstalledPackage { @{ Name = $Name; Version = '1.0' } } - Mock Get-ChocoLatestPackage { @{ Name = $Name; Version = '2.0' } } - Mock Invoke-ChocoInstallPackage + Mock Invoke-ExternalCommand { "7zip|1.0" } -ParameterFilter { $Arguments -contains '--local-only' } -ModuleName PSDepend + Mock Invoke-ExternalCommand { "7zip|2.0" } -ParameterFilter { $Arguments[0] -eq 'list' -and $Arguments -notcontains '--local-only' } -ModuleName PSDepend Invoke-PSDepend @Verbose -Path "$TestDepends\chocolatey.latestversionrequested.depend.psd1" -Force -ErrorAction Stop - Assert-MockCalled Get-ChocoInstalledPackage -Times 1 -Exactly - Assert-MockCalled Get-ChocoLatestPackage -Times 1 -Exactly - Assert-MockCalled Invoke-ChocoInstallPackage -Times 1 -Exactly + Should -Invoke Invoke-ExternalCommand -ParameterFilter { $Arguments -contains '--local-only' } -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Invoke-ExternalCommand -ParameterFilter { $Arguments[0] -eq 'list' -and $Arguments -notcontains '--local-only' } -Times 1 -Exactly -ModuleName PSDepend + Should -Invoke Invoke-ExternalCommand -ParameterFilter { $Arguments[0] -eq 'upgrade' } -Times 1 -Exactly -ModuleName PSDepend } } } diff --git a/build.ps1 b/build.ps1 index 6e14267..eb9034e 100644 --- a/build.ps1 +++ b/build.ps1 @@ -50,6 +50,8 @@ if ($Bootstrap) { } Import-Module -Name PSDepend -Verbose:$false Invoke-PSDepend -Path './requirements.psd1' -Install -Import -Force -WarningAction SilentlyContinue +} else { + Invoke-PSDepend -Path './requirements.psd1' -Import -Force -WarningAction SilentlyContinue } if ($PSCmdlet.ParameterSetName -eq 'Help') { diff --git a/docs/en-US/Get-Dependency.md b/docs/en-US/Get-Dependency.md index 6a06fa6..4354e7f 100644 --- a/docs/en-US/Get-Dependency.md +++ b/docs/en-US/Get-Dependency.md @@ -14,12 +14,14 @@ Read a dependency psd1 file. ## SYNTAX ### File (Default) + ``` Get-Dependency [-Path ] [-Tags ] [-Recurse] [-Credentials ] [-ProgressAction ] [] ``` ### Hashtable + ``` Get-Dependency [-Tags ] [-InputObject ] [-Credentials ] [-ProgressAction ] [] @@ -130,6 +132,7 @@ Accept wildcard characters: False ``` ### -ProgressAction + {{ Fill ProgressAction Description }} ```yaml @@ -145,6 +148,7 @@ Accept wildcard characters: False ``` ### CommonParameters + This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). ## INPUTS @@ -158,5 +162,3 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES ## RELATED LINKS - -[Invoke-PSDepend](Invoke-PSDepend.md) diff --git a/docs/en-US/Get-PSDependScript.md b/docs/en-US/Get-PSDependScript.md index cc25e32..aa8a8b7 100644 --- a/docs/en-US/Get-PSDependScript.md +++ b/docs/en-US/Get-PSDependScript.md @@ -50,6 +50,7 @@ Accept wildcard characters: False ``` ### -ProgressAction + {{ Fill ProgressAction Description }} ```yaml @@ -65,6 +66,7 @@ Accept wildcard characters: False ``` ### CommonParameters + This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). ## INPUTS @@ -74,5 +76,3 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES ## RELATED LINKS - -[Get-PSDependType](Get-PSDependType.md) diff --git a/docs/en-US/Get-PSDependType.md b/docs/en-US/Get-PSDependType.md index d2395df..8cb6db8 100644 --- a/docs/en-US/Get-PSDependType.md +++ b/docs/en-US/Get-PSDependType.md @@ -108,6 +108,7 @@ Accept wildcard characters: False ``` ### -ProgressAction + {{ Fill ProgressAction Description }} ```yaml @@ -123,6 +124,7 @@ Accept wildcard characters: False ``` ### CommonParameters + This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). ## INPUTS @@ -132,5 +134,3 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES ## RELATED LINKS - -[Get-PSDependScript](Get-PSDependScript.md) diff --git a/docs/en-US/Import-Dependency.md b/docs/en-US/Import-Dependency.md index 63a8552..d7d766b 100644 --- a/docs/en-US/Import-Dependency.md +++ b/docs/en-US/Import-Dependency.md @@ -84,6 +84,7 @@ Accept wildcard characters: False ``` ### -ProgressAction + {{ Fill ProgressAction Description }} ```yaml @@ -99,6 +100,7 @@ Accept wildcard characters: False ``` ### CommonParameters + This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). ## INPUTS @@ -110,7 +112,3 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES ## RELATED LINKS - -[Get-Dependency](Get-Dependency.md) -[Install-Dependency](Install-Dependency.md) -[Invoke-PSDepend](Invoke-PSDepend.md) diff --git a/docs/en-US/Install-Dependency.md b/docs/en-US/Install-Dependency.md index 188b60c..1c41f03 100644 --- a/docs/en-US/Install-Dependency.md +++ b/docs/en-US/Install-Dependency.md @@ -108,6 +108,7 @@ Accept wildcard characters: False ``` ### -WhatIf + Shows what would happen if the cmdlet runs. The cmdlet is not run. ```yaml @@ -123,6 +124,7 @@ Accept wildcard characters: False ``` ### -Confirm + Prompts you for confirmation before running the cmdlet. ```yaml @@ -138,6 +140,7 @@ Accept wildcard characters: False ``` ### -ProgressAction + {{ Fill ProgressAction Description }} ```yaml @@ -153,6 +156,7 @@ Accept wildcard characters: False ``` ### CommonParameters + This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). ## INPUTS @@ -164,7 +168,3 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES ## RELATED LINKS - -[Get-Dependency](Get-Dependency.md) -[Import-Dependency](Import-Dependency.md) -[Invoke-PSDepend](Invoke-PSDepend.md) diff --git a/docs/en-US/Invoke-DependencyScript.md b/docs/en-US/Invoke-DependencyScript.md index 00d8c2a..7f2c23a 100644 --- a/docs/en-US/Invoke-DependencyScript.md +++ b/docs/en-US/Invoke-DependencyScript.md @@ -116,6 +116,7 @@ Accept wildcard characters: False ``` ### -ProgressAction + {{ Fill ProgressAction Description }} ```yaml @@ -131,6 +132,7 @@ Accept wildcard characters: False ``` ### CommonParameters + This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). ## INPUTS @@ -142,6 +144,3 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES ## RELATED LINKS - -[Get-Dependency](Get-Dependency.md) -[Invoke-PSDepend](Invoke-PSDepend.md) diff --git a/docs/en-US/Invoke-PSDepend.md b/docs/en-US/Invoke-PSDepend.md index 9569f52..f64b019 100644 --- a/docs/en-US/Invoke-PSDepend.md +++ b/docs/en-US/Invoke-PSDepend.md @@ -14,6 +14,7 @@ Install, import, or test dependencies defined in a PSDepend file. ## SYNTAX ### installimport-file (Default) + ``` Invoke-PSDepend [[-Path] ] [-PSDependTypePath ] [-Tags ] [-Recurse ] [-Import] [-Install] [-Force] [-Target ] [-Credentials ] @@ -21,6 +22,7 @@ Invoke-PSDepend [[-Path] ] [-PSDependTypePath ] [-Tags ] [-PSDependTypePath ] [-Tags ] [-Recurse ] [-Test] [-Quiet] [-Force] [-Target ] [-ProgressAction ] [-WhatIf] [-Confirm] @@ -28,12 +30,14 @@ Invoke-PSDepend [[-Path] ] [-PSDependTypePath ] [-Tags ] [-PSDependTypePath ] [-Tags ] [-Test] [-Quiet] [-Force] [-Target ] [-ProgressAction ] [-WhatIf] [-Confirm] [] ``` ### installimport-hashtable + ``` Invoke-PSDepend [[-InputObject] ] [-PSDependTypePath ] [-Tags ] [-Import] [-Install] [-Force] [-Target ] [-Credentials ] [-ProgressAction ] @@ -277,6 +281,7 @@ Accept wildcard characters: False ``` ### -WhatIf + Shows what would happen if the cmdlet runs. The cmdlet is not run. ```yaml @@ -292,6 +297,7 @@ Accept wildcard characters: False ``` ### -Confirm + Prompts you for confirmation before running the cmdlet. ```yaml @@ -307,6 +313,7 @@ Accept wildcard characters: False ``` ### -ProgressAction + {{ Fill ProgressAction Description }} ```yaml @@ -322,6 +329,7 @@ Accept wildcard characters: False ``` ### CommonParameters + This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). ## INPUTS @@ -333,8 +341,3 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES ## RELATED LINKS - -[Get-Dependency](Get-Dependency.md) -[Install-Dependency](Install-Dependency.md) -[Import-Dependency](Import-Dependency.md) -[Test-Dependency](Test-Dependency.md) diff --git a/docs/en-US/Test-Dependency.md b/docs/en-US/Test-Dependency.md index a0dd9d3..19d62f4 100644 --- a/docs/en-US/Test-Dependency.md +++ b/docs/en-US/Test-Dependency.md @@ -108,6 +108,7 @@ Accept wildcard characters: False ``` ### -ProgressAction + {{ Fill ProgressAction Description }} ```yaml @@ -123,6 +124,7 @@ Accept wildcard characters: False ``` ### CommonParameters + This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). ## INPUTS @@ -134,7 +136,3 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES ## RELATED LINKS - -[Get-Dependency](Get-Dependency.md) -[Install-Dependency](Install-Dependency.md) -[Invoke-PSDepend](Invoke-PSDepend.md) diff --git a/psakeFile.ps1 b/psakeFile.ps1 index 202a4e7..1547744 100644 --- a/psakeFile.ps1 +++ b/psakeFile.ps1 @@ -1,4 +1,4 @@ -properties { +Properties { # PSDepend stages files without compiling to a single PSM1 $PSBPreference.Build.CompileModule = $false @@ -9,28 +9,35 @@ properties { $PSBPreference.Build.CopyDirectories = @('PSDependScripts', 'en-US') # Test configuration - $PSBPreference.Test.OutputFile = './Output/testResults.xml' + $PSBPreference.Help.DefaultLocale = 'en-US' + $PSBPreference.Test.OutputFile = 'out/testResults.xml' $PSBPreference.Test.OutputFormat = 'JUnitXml' $PSBPreference.Test.ScriptAnalysis.Enabled = $true $PSBPreference.Test.ScriptAnalysis.FailBuildOnSeverityLevel = 'Error' $PSBPreference.Test.CodeCoverage.Enabled = $false + # Explicit casing required for Linux (case-sensitive filesystem) + $PSBPreference.Test.RootDir = Join-Path $ENV:BHProjectPath 'Tests' # Exclude Windows-only tests on non-Windows runners if (-not $IsWindows) { $PSBPreference.Test.ExcludeTagFilter = @('WindowsOnly') } - - # Publish configuration — API key injected via environment in CI - $PSBPreference.Publish.PSRepository = 'PSGallery' - $PSBPreference.Publish.PSRepositoryApiKey = $env:PSGALLERY_API_KEY } -task default -depends Test +# Pre-set before -FromModule so PowerShellBuild 0.7.x's null-check doesn't override it. +# Skips BuildHelp (GenerateMarkdown) — doc generation is not needed in the test pipeline +# and Build-PSBuildMarkdown has a Remove-Module scope bug specific to PSDepend. +$PSBBuildDependency = @('StageFiles') + +Task Default -Depends Test -task Init -FromModule PowerShellBuild -minimumVersion '0.6.1' -task Clean -FromModule PowerShellBuild -minimumVersion '0.6.1' -task Build -FromModule PowerShellBuild -minimumVersion '0.6.1' -task Analyze -FromModule PowerShellBuild -minimumVersion '0.6.1' -task Pester -FromModule PowerShellBuild -minimumVersion '0.6.1' -task Test -FromModule PowerShellBuild -minimumVersion '0.6.1' -task Publish -FromModule PowerShellBuild -minimumVersion '0.6.1' +# PowerShellBuild adds the following tasks: +# - Init +# - Clean +# - StageFiles +# - Build +# - Test +# - BuildHelp +# - GenerateMarkdown +# - Publish +Task Test -FromModule PowerShellBuild -MinimumVersion '0.7.3' diff --git a/requirements.psd1 b/requirements.psd1 index 51f85ad..5784be4 100644 --- a/requirements.psd1 +++ b/requirements.psd1 @@ -6,7 +6,7 @@ Version = '4.9.1' } 'PowerShellBuild' = @{ - Version = '0.7.2' + Version = '0.7.3' } 'Pester' = @{ Version = '5.7.1'