diff --git a/.vscode/launch.json b/.vscode/launch.json
index c1b568a..b0e497f 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -4,6 +4,30 @@
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
+ {
+ "name": "Run Build and Debug (Temp Console)",
+ "type": "PowerShell",
+ "request": "launch",
+ "script": "${cwd}/build.ps1",
+ "args": [
+ "-Task Test",
+ "-Verbose"
+ ],
+ "cwd": "${workspaceFolder}",
+ "createTemporaryIntegratedConsole": true
+ },
+ {
+ "name": "Run Build and Debug",
+ "type": "PowerShell",
+ "request": "launch",
+ "script": "${cwd}/build.ps1",
+ "args": [
+ "-Task Test",
+ "-Verbose"
+ ],
+ "cwd": "${workspaceFolder}",
+ "createTemporaryIntegratedConsole": true
+ },
{
"name": "PowerShell: Interactive Session",
"type": "PowerShell",
@@ -11,4 +35,4 @@
"cwd": ""
}
]
-}
\ No newline at end of file
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index bce2856..b8375aa 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -7,6 +7,7 @@
"powershell.codeFormatting.useCorrectCasing": true,
"powershell.codeFormatting.newLineAfterOpenBrace": true,
"powershell.codeFormatting.alignPropertyValuePairs": true,
+ "powershell.scriptAnalysis.settingsPath": "tests/ScriptAnalyzerSettings.psd1",
"search.useIgnoreFiles": true,
"search.exclude": {
"**/node_modules": true,
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index ca72255..69ccd58 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -6,7 +6,7 @@
"windows": {
"options": {
"shell": {
- "executable": "powershell.exe",
+ "executable": "pwsh.exe",
"args": [
"-NoProfile",
"-ExecutionPolicy",
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 53a93ba..1793fb0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,10 +7,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Unreleased
+### Added
+
- Add new dependencies variables to allow end user to modify which tasks are
run.
- Add localization support.
+### Fixed
+
+- Remove extra item from `New-MarkdownHelp` splat that would result in a failure
+ when using `$PSBPreference.Docs.Overwrite = $true`
+- Clean up some failing Script Analyzer settings, including moving the file.
+
## [0.7.2] 2025-05-21
### Added
diff --git a/PowerShellBuild/Public/Publish-PSBuildModule.ps1 b/PowerShellBuild/Public/Publish-PSBuildModule.ps1
index dd4708d..5345687 100644
--- a/PowerShellBuild/Public/Publish-PSBuildModule.ps1
+++ b/PowerShellBuild/Public/Publish-PSBuildModule.ps1
@@ -27,6 +27,12 @@ function Publish-PSBuildModule {
Publish version 0.1.0 of the module at path .\Output\0.1.0\MyModule to the PSGallery repository using an API key and a PowerShell credential.
#>
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(
+ 'PSReviewUnusedParameter',
+ '',
+ Justification = 'Both Credential and NuGetApiKey are used just not via explicit variable call.'
+ )]
+ [CmdletBinding(DefaultParameterSetName = 'ApiKey')]
[CmdletBinding(DefaultParameterSetName = 'ApiKey')]
param(
[parameter(Mandatory)]
diff --git a/PowerShellBuild/Public/Test-PSBuildPester.ps1 b/PowerShellBuild/Public/Test-PSBuildPester.ps1
index 3dbd4a9..b6d0f20 100644
--- a/PowerShellBuild/Public/Test-PSBuildPester.ps1
+++ b/PowerShellBuild/Public/Test-PSBuildPester.ps1
@@ -36,6 +36,11 @@ function Test-PSBuildPester {
Run Pester tests in ./tests and save results to ./out/testResults.xml
#>
[CmdletBinding()]
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute(
+ 'PSReviewUnusedParameter',
+ 'CodeCoverageThreshold',
+ Justification = 'Used inside a foreach method call.'
+ )]
param(
[parameter(Mandatory)]
[string]$Path,
diff --git a/PowerShellBuild/ScriptAnalyzerSettings.psd1 b/PowerShellBuild/ScriptAnalyzerSettings.psd1
deleted file mode 100644
index f794cdb..0000000
--- a/PowerShellBuild/ScriptAnalyzerSettings.psd1
+++ /dev/null
@@ -1,13 +0,0 @@
-@{
- ExcludeRules = @(
- 'PSAvoidUsingWriteHost',
- 'PSUseToExportFieldsInManifest'
- 'PSUseDeclaredVarsMoreThanAssignments'
- )
- Rules = @{
- # Don't trip on the task alias. It's by design
- PSAvoidUsingCmdletAliases = @{
- Whitelist = @('task')
- }
- }
-}
diff --git a/README.md b/README.md
index 8725468..526f1dc 100644
--- a/README.md
+++ b/README.md
@@ -25,9 +25,11 @@ Install-Module -Name psake -RequiredVersion 4.8.0 -Repository PSGallery
> [how to dot source tasks using PowerShell aliases](https://github.com/nightroman/Invoke-Build/blob/master/Tasks/Import/README.md#example-2-import-from-a-module-with-tasks)
> example.
+
+
## Status - Work in progress
@@ -209,3 +211,5 @@ $PSBPreference.Test.CodeCoverage.Enabled = $false
[psgallery]: https://www.powershellgallery.com/packages/PowerShellBuild
[license-badge]: https://img.shields.io/github/license/psake/PowerShellBuild.svg
[license]: https://raw.githubusercontent.com/psake/PowerShellBuild/main/LICENSE
+
+
diff --git a/cspell.json b/cspell.json
index a8959d9..23d56cb 100644
--- a/cspell.json
+++ b/cspell.json
@@ -11,7 +11,9 @@
],
"words": [],
"ignoreWords": [
+ "BHPS",
"psake",
+ "pscredential",
"MAML"
],
"import": []
diff --git a/psakeFile.ps1 b/psakeFile.ps1
index 22a24c4..4fd5b41 100644
--- a/psakeFile.ps1
+++ b/psakeFile.ps1
@@ -1,24 +1,24 @@
-properties {
+Properties {
$settings = . ([IO.Path]::Combine($PSScriptRoot, 'build.settings.ps1'))
if ($galleryApiKey) {
$settings.PSGalleryApiKey = $galleryApiKey.GetNetworkCredential().password
}
}
-task default -depends Test
+Task default -depends Test
-task Init {
+Task Init {
"STATUS: Testing with PowerShell $($settings.PSVersion)"
'Build System Details:'
Get-Item ENV:BH*
} -description 'Initialize build environment'
-task Test -Depends Init, Analyze, Pester -description 'Run test suite'
+Task Test -depends Init, Analyze, Pester -description 'Run test suite'
-task Analyze -depends Build {
- $analysis = Invoke-ScriptAnalyzer -Path $settings.ModuleOutDir -Recurse -Verbose:$false -Settings ([IO.Path]::Combine($env:BHModulePath, 'ScriptAnalyzerSettings.psd1'))
- $errors = $analysis | Where-Object {$_.Severity -eq 'Error'}
- $warnings = $analysis | Where-Object {$_.Severity -eq 'Warning'}
+Task Analyze -depends Build {
+ $analysis = Invoke-ScriptAnalyzer -Path $settings.ModuleOutDir -Recurse -Verbose:$false -Settings './tests/ScriptAnalyzerSettings.psd1'
+ $errors = $analysis | Where-Object { $_.Severity -eq 'Error' }
+ $warnings = $analysis | Where-Object { $_.Severity -eq 'Warning' }
if (@($errors).Count -gt 0) {
Write-Error -Message 'One or more Script Analyzer errors were found. Build cannot continue!'
$errors | Format-Table -AutoSize
@@ -30,11 +30,11 @@ task Analyze -depends Build {
}
} -description 'Run PSScriptAnalyzer'
-task Pester -depends Build {
+Task Pester -depends Build {
Remove-Module $settings.ProjectName -ErrorAction SilentlyContinue -Verbose:$false
$testResultsXml = [IO.Path]::Combine($settings.OutputDir, 'testResults.xml')
- $testResults = Invoke-Pester -Path $settings.Tests -Output Detailed -PassThru
+ $testResults = Invoke-Pester -Path $settings.Tests -Output Detailed -PassThru
if ($testResults.FailedCount -gt 0) {
$testResults | Format-List
@@ -42,13 +42,13 @@ task Pester -depends Build {
}
} -description 'Run Pester tests'
-task Clean -depends Init {
+Task Clean -depends Init {
if (Test-Path -Path $settings.ModuleOutDir) {
Remove-Item -Path $settings.ModuleOutDir -Recurse -Force -Verbose:$false
}
}
-task Build -depends Init, Clean {
+Task Build -depends Init, Clean {
New-Item -Path $settings.ModuleOutDir -ItemType Directory -Force > $null
Copy-Item -Path "$($settings.SUT)/*" -Destination $settings.ModuleOutDir -Recurse
@@ -59,7 +59,7 @@ task Build -depends Init, Clean {
# & .\Build\Convert-PSAke.ps1 $psakePath | Out-File -Encoding UTF8 $ibPath
}
-task Publish -depends Test {
+Task Publish -depends Test {
" Publishing version [$($settings.Manifest.ModuleVersion)] to PSGallery..."
if ($settings.PSGalleryApiKey) {
Publish-Module -Path $settings.ModuleOutDir -NuGetApiKey $settings.PSGalleryApiKey
diff --git a/requirements.psd1 b/requirements.psd1
index 5e22bd3..190478b 100755
--- a/requirements.psd1
+++ b/requirements.psd1
@@ -4,7 +4,7 @@
}
BuildHelpers = '2.0.16'
Pester = @{
- MinimumVersion = '5.6.1'
+ MinimumVersion = '5.7.1'
Parameters = @{
SkipPublisherCheck = $true
}
diff --git a/tests/Help.tests.ps1 b/tests/Help.tests.ps1
index 974e60a..2719468 100755
--- a/tests/Help.tests.ps1
+++ b/tests/Help.tests.ps1
@@ -1,17 +1,17 @@
# Taken with love from @juneb_get_help (https://raw.githubusercontent.com/juneb/PesterTDD/master/Module.Help.Tests.ps1)
BeforeDiscovery {
+
function global:FilterOutCommonParams {
param ($Params)
- $commonParams = [System.Management.Automation.PSCmdlet]::OptionalCommonParameters +
- [System.Management.Automation.PSCmdlet]::CommonParameters
- $params | Where-Object { $_.Name -notin $commonParams } | Sort-Object -Property Name -Unique
+ $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
+ $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
@@ -25,36 +25,32 @@ BeforeDiscovery {
if ($PSVersionTable.PSVersion.Major -lt 6) {
$params.CommandType[0] += 'Workflow'
}
- $commands = Get-Command @params
+ $script:commands = Get-Command @params
## When testing help, remember that help is cached at the beginning of each session.
## To test, restart session.
}
-AfterAll {
- Remove-Item Function:/FilterOutCommonParams
-}
-
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
+ $command = $_
+ $commandHelp = Get-Help $command.Name -ErrorAction SilentlyContinue
+ $commandParameters = global:FilterOutCommonParams -Params $command.ParameterSets.Parameters
+ $script:commandParameterNames = $commandParameters.Name
+ $script:helpLinks = $commandHelp.relatedLinks.navigationLink.uri
}
BeforeAll {
# These vars are needed in both discovery and test phases so we need to duplicate them here
- $command = $_
- $commandName = $_.Name
- $commandHelp = Get-Help $command.Name -ErrorAction SilentlyContinue
- $commandParameters = global:FilterOutCommonParams -Params $command.ParameterSets.Parameters
- $commandParameterNames = $commandParameters.Name
- $helpParameters = global:FilterOutCommonParams -Params $commandHelp.Parameters.Parameter
- $helpParameterNames = $helpParameters.Name
+ $command = $_
+ $script:commandName = $_.Name
+ $commandHelp = Get-Help $command.Name -ErrorAction SilentlyContinue
+ $commandParameters = global:FilterOutCommonParams -Params $command.ParameterSets.Parameters
+ $script:commandParameterNames = $commandParameters.Name
+ $helpParameters = global:FilterOutCommonParams -Params $commandHelp.Parameters.Parameter
+ $script:helpParameterNames = $helpParameters.Name
}
# If help is not found, synopsis in auto-generated help is the syntax diagram
@@ -81,13 +77,13 @@ Describe "Test help for <_.Name>" -ForEach $commands {
(Invoke-WebRequest -Uri $_ -UseBasicParsing).StatusCode | Should -Be '200'
}
- Context "Parameter <_.Name>" -Foreach $commandParameters {
+ Context "Parameter <_.Name>" -ForEach $commandParameters {
BeforeAll {
- $parameter = $_
- $parameterName = $parameter.Name
- $parameterHelp = $commandHelp.parameters.parameter | Where-Object Name -eq $parameterName
- $parameterHelpType = if ($parameterHelp.ParameterValue) { $parameterHelp.ParameterValue.Trim() }
+ $parameter = $_
+ $parameterName = $parameter.Name
+ $parameterHelp = $commandHelp.parameters.parameter | Where-Object Name -EQ $parameterName
+ $script:parameterHelpType = if ($parameterHelp.ParameterValue) { $parameterHelp.ParameterValue.Trim() }
}
# Should be a description for every parameter
@@ -107,7 +103,7 @@ Describe "Test help for <_.Name>" -ForEach $commands {
}
}
- Context "Test <_> help parameter help for " -Foreach $helpParameterNames {
+ Context "Test <_> help parameter help for " -ForEach $helpParameterNames {
# Shouldn't find extra parameters in help.
It "finds help parameter in code: <_>" {
diff --git a/tests/Manifest.tests.ps1 b/tests/Manifest.tests.ps1
index b659654..4dcc18d 100644
--- a/tests/Manifest.tests.ps1
+++ b/tests/Manifest.tests.ps1
@@ -1,14 +1,15 @@
BeforeAll {
+ Set-Location "$PSScriptRoot/.."
Set-BuildEnvironment -Force
- $moduleName = $env:BHProjectName
- $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
+ $moduleName = $env:BHProjectName
+ $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
$outputManifestPath = Join-Path -Path $outputModVerDir -Child "$($moduleName).psd1"
- $manifestData = Test-ModuleManifest -Path $outputManifestPath -Verbose:$false -ErrorAction Stop -WarningAction SilentlyContinue
+ $manifestData = Test-ModuleManifest -Path $outputManifestPath -Verbose:$false -ErrorAction Stop -WarningAction SilentlyContinue
- $changelogPath = Join-Path -Path $env:BHProjectPath -Child 'CHANGELOG.md'
+ $changelogPath = Join-Path -Path $env:BHProjectPath -Child 'CHANGELOG.md'
$changelogVersion = Get-Content $changelogPath | ForEach-Object {
if ($_ -match "^##\s\[(?(\d+\.){1,3}\d+)\]") {
$changelogVersion = $matches.Version
@@ -16,7 +17,7 @@ BeforeAll {
}
}
- $script:manifest = $null
+ $script:manifest = $null
}
Describe 'Module manifest' {
@@ -47,7 +48,7 @@ Describe 'Module manifest' {
}
It 'Has a valid guid' {
- {[guid]::Parse($manifestData.Guid)} | Should -Not -Throw
+ { [guid]::Parse($manifestData.Guid) } | Should -Not -Throw
}
It 'Has a valid copyright' {
@@ -55,7 +56,7 @@ Describe 'Module manifest' {
}
It 'Has a valid version in the changelog' {
- $changelogVersion | Should -Not -BeNullOrEmpty
+ $changelogVersion | Should -Not -BeNullOrEmpty
$changelogVersion -as [Version] | Should -Not -BeNullOrEmpty
}
@@ -76,7 +77,7 @@ Describe 'Git tagging' -Skip {
}
It 'Is tagged with a valid version' {
- $gitTagVersion | Should -Not -BeNullOrEmpty
+ $gitTagVersion | Should -Not -BeNullOrEmpty
$gitTagVersion -as [Version] | Should -Not -BeNullOrEmpty
}
diff --git a/tests/ScriptAnalyzerSettings.psd1 b/tests/ScriptAnalyzerSettings.psd1
index 8fe45b9..2c11de5 100644
--- a/tests/ScriptAnalyzerSettings.psd1
+++ b/tests/ScriptAnalyzerSettings.psd1
@@ -1,3 +1,15 @@
@{
-
+ ExcludeRules = @(
+ 'PSAvoidUsingWriteHost',
+ 'PSUseToExportFieldsInManifest',
+ 'PSUseDeclaredVarsMoreThanAssignments',
+ # This throws a warning on Build verb, which is valid as of PSv6
+ 'PSUseApprovedVerbs'
+ )
+ Rules = @{
+ # Don't trip on the task alias. It's by design
+ PSAvoidUsingCmdletAliases = @{
+ Whitelist = @('task')
+ }
+ }
}
diff --git a/tests/TestModule/Tests/Help.tests.ps1 b/tests/TestModule/Tests/Help.tests.ps1
deleted file mode 100644
index 7467ad8..0000000
--- a/tests/TestModule/Tests/Help.tests.ps1
+++ /dev/null
@@ -1,93 +0,0 @@
-# Taken with love from @juneb_get_help (https://raw.githubusercontent.com/juneb/PesterTDD/master/Module.Help.Tests.ps1)
-
-Describe 'Help' {
- $testCases = Get-Command -Module $env:BHProjectName -CommandType Cmdlet, Function | ForEach-Object {
- @{
- Name = $_.Name
- Command = $_
- }
- }
-
- BeforeAll {
- $commonParameters = 'Debug', 'ErrorAction', 'ErrorVariable', 'InformationAction', 'InformationVariable', 'OutBuffer',
- 'OutVariable', 'PipelineVariable', 'Verbose', 'WarningAction', 'WarningVariable', 'Confirm', 'Whatif'
- }
-
- # No auto-generated help
- Context 'Auto-generation' {
- it 'Help for [] should not be auto-generated' -TestCases $testCases {
- param($Name, $Command)
-
- $help = Get-Help $Name -ErrorAction SilentlyContinue
- $help.Synopsis | Should -Not -BeLike '*`[``]*'
- }
- }
-
-
- # Should have a description for every function
- Context 'Help description' {
- It 'Help for [] has a description' -TestCases $testCases {
- param($Name, $Command)
-
- $help = Get-Help $Name -ErrorAction SilentlyContinue
- $help.Description | Should -Not -BeNullOrEmpty
- }
- }
-
- # Should be at least one example per command
- Context 'Examples' {
- It 'Help for [] has example code' -TestCases $testCases {
- param($Name, $Command)
-
- $help = Get-Help $Name -ErrorAction SilentlyContinue
- ($help.Examples.Example | Select-Object -First 1).Code | Should -Not -BeNullOrEmpty
- }
- }
-
- # Parameter help
- Context 'Parameter help' {
- It '[] has help for every parameter' -TestCases $testCases {
- param($Name, $Command)
-
- $help = Get-Help $Name -ErrorAction SilentlyContinue
- $parameters = $Command.ParameterSets.Parameters |
- Sort-Object -Property Name -Unique |
- Where-Object { $_.Name -notin $commonParameters }
- $parameterNames = $parameters.Name
-
- # Without the filter, WhatIf and Confirm parameters are still flagged in "finds help parameter in code" test
- $helpParameters = $help.Parameters.Parameter |
- Where-Object { $_.Name -notin $commonParameters } |
- Sort-Object -Property Name -Unique
- $helpParameterNames = $helpParameters.Name
-
- foreach ($parameter in $parameters) {
- $parameterName = $parameter.Name
- $parameterHelp = $help.parameters.parameter | Where-Object Name -eq $parameterName
- $parameterHelp.Description.Text | Should -Not -BeNullOrEmpty
-
- $codeMandatory = $parameter.IsMandatory.toString()
- $parameterHelp.Required | Should -Be $codeMandatory
-
- $codeType = $parameter.ParameterType.Name
- # To avoid calling Trim method on a null object.
- $helpType = if ($parameterHelp.parameterValue) { $parameterHelp.parameterValue.Trim() }
- $helpType | Should -Be $codeType
- }
- }
- }
-
- # Links are valid
- Context 'Links' {
- It 'Help for [] has valid links' -TestCases $testCases {
- param($Name, $Command)
-
- $help = Get-Help $Name -ErrorAction SilentlyContinue
- $link = $help.relatedLinks.navigationLink.uri
- foreach ($link in $links) {
- $Results = Invoke-WebRequest -Uri $link -UseBasicParsing
- $Results.StatusCode | Should -Be '200'
- }
- }
- }
-}
diff --git a/tests/build.tests.ps1 b/tests/build.tests.ps1
index 6022d47..331cbc3 100644
--- a/tests/build.tests.ps1
+++ b/tests/build.tests.ps1
@@ -1,37 +1,56 @@
# spell-checker:ignore excludeme
Describe 'Build' {
+ BeforeDiscovery {
+ if ($null -eq $env:BHProjectPath) {
+ $path = Join-Path -Path $PSScriptRoot -ChildPath '..\build.ps1'
+ . $path -Task Build
+ }
+ $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
+ $global: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
+ }
BeforeAll {
- # Hack for GH Actions
+ $script:testModuleSource = Join-Path $TestDrive 'TestModule'
+ New-Item -Path $script:testModuleSource -ItemType Directory -Force | Out-Null
+ Copy-Item $PSScriptRoot/fixtures/TestModule/* $script:testModuleSource -Recurse
+ $script:testModuleOutputPath = [IO.Path]::Combine($script:testModuleSource, 'Output', 'TestModule', '0.1.0')
+
+ <# Hack for GH Actions
# For some reason, the TestModule build process create the output in the project root
# and not relative to it's own build file.
if ($env:GITHUB_ACTION) {
- $script:testModuleSource = [IO.Path]::Combine($PSScriptRoot, 'TestModule')
+ $script:testModuleSource = [IO.Path]::Combine($PSScriptRoot, 'Fixtures', 'TestModule')
$script:testModuleOutputPath = [IO.Path]::Combine($env:BHProjectPath, 'Output', 'TestModule', '0.1.0')
} else {
- $script:testModuleSource = [IO.Path]::Combine($PSScriptRoot, 'TestModule')
+ $script:testModuleSource = [IO.Path]::Combine($PSScriptRoot, 'Fixtures', 'TestModule')
$script:testModuleOutputPath = [IO.Path]::Combine($script:testModuleSource, 'Output', 'TestModule', '0.1.0')
- }
+ }#>
}
Context 'Compile module' {
BeforeAll {
-
Write-Host "PSScriptRoot: $PSScriptRoot"
Write-Host "OutputPath: $script:testModuleOutputPath"
# build is PS job so psake doesn't freak out because it's nested
Start-Job -Scriptblock {
Set-Location -Path $using:testModuleSource
+ # We want to load the current build of PowerShellBuild so we use a
+ # global variable to store the output path.
+ $global:PSBOutput = $using:outputModVerManifest
$global:PSBuildCompile = $true
./build.ps1 -Task Build
} -WorkingDirectory $script:testModuleSource | Wait-Job
}
- AfterAll {
- Remove-Item $script:testModuleOutputPath -Recurse -Force
- }
-
It 'Creates module' {
$script:testModuleOutputPath | Should -Exist
}
@@ -72,22 +91,22 @@ Describe 'Build' {
Context 'Dot-sourced module' {
BeforeAll {
+ $copyItemSplat = @{
+ Path = "$PSScriptRoot/fixtures/DotSource.psm1"
+ Destination = "$script:testModuleSource/TestModule/TestModule.psm1"
+ Force = $true
+ }
+ # Overwrite the existing PSM1 with the dot-sourced version
+ Copy-Item @copyItemSplat
# build is PS job so psake doesn't freak out because it's nested
Start-Job -Scriptblock {
Set-Location -Path $using:testModuleSource
+ # We want to load the current build of PowerShellBuild so we use a
+ # global variable to store the output path.
+ $global:PSBOutput = $using:outputModVerManifest
$global:PSBuildCompile = $false
./build.ps1 -Task Build
} -WorkingDirectory $script:testModuleSource | Wait-Job
- Write-Debug "TestModule output path: $script:testModuleSource"
- $items = Get-ChildItem -Path $script:testModuleSource -Recurse -File
- Write-Debug ($items | Format-Table FullName | Out-String)
- Write-Debug "TestModule output path: $script:testModuleOutputPath"
- $items = Get-ChildItem -Path $script:testModuleOutputPath -Recurse -File
- Write-Debug ($items | Format-Table FullName | Out-String)
- }
-
- AfterAll {
- Remove-Item $script:testModuleOutputPath -Recurse -Force
}
It 'Creates module' {
@@ -111,4 +130,55 @@ Describe 'Build' {
"$script:testModuleOutputPath/en-US/TestModule-help.xml" | Should -Exist
}
}
+ Context 'Overwrite Docs' {
+ BeforeAll {
+
+ Write-Host "PSScriptRoot: $script:testModuleSource"
+ Write-Host "OutputPath: $script:testModuleOutputPath"
+
+ $copyItemSplat = @{
+ Path = "$PSScriptRoot/fixtures/DotSource.psm1"
+ Destination = "$script:testModuleSource/TestModule/TestModule.psm1"
+ Force = $true
+ }
+ # Overwrite the existing PSM1 with the dot-sourced version
+ Copy-Item @copyItemSplat
+ # build is PS job so psake doesn't freak out because it's nested
+ Start-Job -Scriptblock {
+ Set-Location -Path $using:testModuleSource
+ # We want to load the current build of PowerShellBuild so we use a
+ # global variable to store the output path.
+ $global:PSBOutput = $using:outputModVerManifest
+ $global:PSBuildCompile = $false
+ ./build.ps1 -Task Build
+ } -WorkingDirectory $script:testModuleSource | Wait-Job
+
+ # Replace with a different string to test the overwrite
+ $script:docPath = [IO.Path]::Combine($script:testModuleSource, "docs", "en-US", "Get-HelloWorld.md")
+ $script:original = Get-Content $docPath -Raw
+ $new = $original -replace 'Hello World', 'Hello Universe'
+ Set-Content $docPath -Value $new -Force
+
+ # Update the psake file
+ $psakeFile = [IO.Path]::Combine($script:testModuleSource, "psakeFile.ps1")
+ $psakeFileContent = Get-Content $psakeFile -Raw
+ $psakeFileContent = $psakeFileContent -replace '\$PSBPreference.Docs.Overwrite = \$false', '$PSBPreference.Docs.Overwrite = $true'
+ Set-Content $psakeFile -Value $psakeFileContent -Force
+
+ # build is PS job so psake doesn't freak out because it's nested
+ Start-Job -Scriptblock {
+ Set-Location -Path $using:testModuleSource
+ # We want to load the current build of PowerShellBuild so we use a
+ # global variable to store the output path.
+ $global:PSBOutput = $using:outputModVerManifest
+ $global:PSBuildCompile = $false
+ ./build.ps1 -Task Build
+ } -WorkingDirectory $script:testModuleSource | Wait-Job
+ }
+
+ It 'Can Overwrite the Docs' {
+ # Test that the file reset as expected
+ Get-Content $script:docPath -Raw | Should -Not -Contain 'Hello Universe'
+ }
+ }
}
diff --git a/tests/fixtures/DotSource.psm1 b/tests/fixtures/DotSource.psm1
new file mode 100644
index 0000000..c8e9459
--- /dev/null
+++ b/tests/fixtures/DotSource.psm1
@@ -0,0 +1,12 @@
+# This is what a non compiled psm1 would look like. We use this for some of the tests
+# Dot source public functions
+$private = @(Get-ChildItem -Path ([IO.Path]::Combine($PSScriptRoot, 'Private/*.ps1')) -Recurse)
+$public = @(Get-ChildItem -Path ([IO.Path]::Combine($PSScriptRoot, 'Public/*.ps1')) -Recurse)
+foreach ($import in $public + $private) {
+ try {
+ . $import.FullName
+ } catch {
+ throw "Unable to dot source [$($import.FullName)]"
+ }
+}
+Export-ModuleMember -Function $public.Basename
diff --git a/tests/TestModule/.build.ps1 b/tests/fixtures/TestModule/.build.ps1
similarity index 100%
rename from tests/TestModule/.build.ps1
rename to tests/fixtures/TestModule/.build.ps1
diff --git a/tests/TestModule/.gitattributes b/tests/fixtures/TestModule/.gitattributes
similarity index 100%
rename from tests/TestModule/.gitattributes
rename to tests/fixtures/TestModule/.gitattributes
diff --git a/tests/TestModule/.github/CONTRIBUTING.md b/tests/fixtures/TestModule/.github/CONTRIBUTING.md
similarity index 100%
rename from tests/TestModule/.github/CONTRIBUTING.md
rename to tests/fixtures/TestModule/.github/CONTRIBUTING.md
diff --git a/tests/TestModule/.github/ISSUE_TEMPLATE.md b/tests/fixtures/TestModule/.github/ISSUE_TEMPLATE.md
similarity index 100%
rename from tests/TestModule/.github/ISSUE_TEMPLATE.md
rename to tests/fixtures/TestModule/.github/ISSUE_TEMPLATE.md
diff --git a/tests/TestModule/.github/PULL_REQUEST_TEMPLATE.md b/tests/fixtures/TestModule/.github/PULL_REQUEST_TEMPLATE.md
similarity index 100%
rename from tests/TestModule/.github/PULL_REQUEST_TEMPLATE.md
rename to tests/fixtures/TestModule/.github/PULL_REQUEST_TEMPLATE.md
diff --git a/tests/TestModule/.gitignore b/tests/fixtures/TestModule/.gitignore
similarity index 100%
rename from tests/TestModule/.gitignore
rename to tests/fixtures/TestModule/.gitignore
diff --git a/tests/TestModule/.vscode/extensions.json b/tests/fixtures/TestModule/.vscode/extensions.json
similarity index 100%
rename from tests/TestModule/.vscode/extensions.json
rename to tests/fixtures/TestModule/.vscode/extensions.json
diff --git a/tests/TestModule/.vscode/settings.json b/tests/fixtures/TestModule/.vscode/settings.json
similarity index 100%
rename from tests/TestModule/.vscode/settings.json
rename to tests/fixtures/TestModule/.vscode/settings.json
diff --git a/tests/TestModule/.vscode/tasks.json b/tests/fixtures/TestModule/.vscode/tasks.json
similarity index 100%
rename from tests/TestModule/.vscode/tasks.json
rename to tests/fixtures/TestModule/.vscode/tasks.json
diff --git a/tests/TestModule/CHANGELOG.md b/tests/fixtures/TestModule/CHANGELOG.md
similarity index 100%
rename from tests/TestModule/CHANGELOG.md
rename to tests/fixtures/TestModule/CHANGELOG.md
diff --git a/tests/TestModule/CODE_OF_CONDUCT.md b/tests/fixtures/TestModule/CODE_OF_CONDUCT.md
similarity index 100%
rename from tests/TestModule/CODE_OF_CONDUCT.md
rename to tests/fixtures/TestModule/CODE_OF_CONDUCT.md
diff --git a/tests/TestModule/LICENSE b/tests/fixtures/TestModule/LICENSE
similarity index 100%
rename from tests/TestModule/LICENSE
rename to tests/fixtures/TestModule/LICENSE
diff --git a/tests/TestModule/README.md b/tests/fixtures/TestModule/README.md
similarity index 100%
rename from tests/TestModule/README.md
rename to tests/fixtures/TestModule/README.md
diff --git a/tests/TestModule/TestModule/Private/GetHelloWorld.ps1 b/tests/fixtures/TestModule/TestModule/Private/GetHelloWorld.ps1
similarity index 100%
rename from tests/TestModule/TestModule/Private/GetHelloWorld.ps1
rename to tests/fixtures/TestModule/TestModule/Private/GetHelloWorld.ps1
diff --git a/tests/TestModule/TestModule/Private/excludemealso.ps1 b/tests/fixtures/TestModule/TestModule/Private/excludemealso.ps1
similarity index 100%
rename from tests/TestModule/TestModule/Private/excludemealso.ps1
rename to tests/fixtures/TestModule/TestModule/Private/excludemealso.ps1
diff --git a/tests/TestModule/TestModule/Public/Get-HelloWorld.ps1 b/tests/fixtures/TestModule/TestModule/Public/Get-HelloWorld.ps1
similarity index 88%
rename from tests/TestModule/TestModule/Public/Get-HelloWorld.ps1
rename to tests/fixtures/TestModule/TestModule/Public/Get-HelloWorld.ps1
index b25ae79..0f76c5c 100644
--- a/tests/TestModule/TestModule/Public/Get-HelloWorld.ps1
+++ b/tests/fixtures/TestModule/TestModule/Public/Get-HelloWorld.ps1
@@ -1,4 +1,4 @@
-Function Get-HelloWorld {
+function Get-HelloWorld {
<#
.SYNOPSIS
Returns Hello world
diff --git a/tests/TestModule/TestModule/TestModule.psd1 b/tests/fixtures/TestModule/TestModule/TestModule.psd1
similarity index 100%
rename from tests/TestModule/TestModule/TestModule.psd1
rename to tests/fixtures/TestModule/TestModule/TestModule.psd1
diff --git a/tests/TestModule/TestModule/TestModule.psm1 b/tests/fixtures/TestModule/TestModule/TestModule.psm1
similarity index 100%
rename from tests/TestModule/TestModule/TestModule.psm1
rename to tests/fixtures/TestModule/TestModule/TestModule.psm1
diff --git a/tests/TestModule/TestModule/dontcopy/garbage.txt b/tests/fixtures/TestModule/TestModule/dontcopy/garbage.txt
similarity index 100%
rename from tests/TestModule/TestModule/dontcopy/garbage.txt
rename to tests/fixtures/TestModule/TestModule/dontcopy/garbage.txt
diff --git a/tests/TestModule/TestModule/excludeme.txt b/tests/fixtures/TestModule/TestModule/excludeme.txt
similarity index 100%
rename from tests/TestModule/TestModule/excludeme.txt
rename to tests/fixtures/TestModule/TestModule/excludeme.txt
diff --git a/tests/TestModule/TestModule/stuff/copymealways.txt b/tests/fixtures/TestModule/TestModule/stuff/copymealways.txt
similarity index 100%
rename from tests/TestModule/TestModule/stuff/copymealways.txt
rename to tests/fixtures/TestModule/TestModule/stuff/copymealways.txt
diff --git a/tests/fixtures/TestModule/Tests/Help.tests.ps1 b/tests/fixtures/TestModule/Tests/Help.tests.ps1
new file mode 100644
index 0000000..857eb63
--- /dev/null
+++ b/tests/fixtures/TestModule/Tests/Help.tests.ps1
@@ -0,0 +1,117 @@
+# Taken with love from @juneb_get_help (https://raw.githubusercontent.com/juneb/PesterTDD/master/Module.Help.Tests.ps1)
+
+BeforeDiscovery {
+ function global:FilterOutCommonParams {
+ param ($Params)
+ $commonParams = [System.Management.Automation.PSCmdlet]::OptionalCommonParameters +
+ [System.Management.Automation.PSCmdlet]::CommonParameters
+ $params | Where-Object { $_.Name -notin $commonParams } | 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.
+}
+
+AfterAll {
+ Remove-Item Function:/FilterOutCommonParams
+}
+
+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
+ }
+
+ BeforeAll {
+ # These vars are needed in both discovery and test phases so we need to duplicate them here
+ $command = $_
+ $commandName = $_.Name
+ $commandHelp = Get-Help $command.Name -ErrorAction SilentlyContinue
+ $commandParameters = global:FilterOutCommonParams -Params $command.ParameterSets.Parameters
+ $commandParameterNames = $commandParameters.Name
+ $helpParameters = global:FilterOutCommonParams -Params $commandHelp.Parameters.Parameter
+ $helpParameterNames = $helpParameters.Name
+ }
+
+ # If help is not found, synopsis in auto-generated help is the syntax diagram
+ It 'Help is not auto-generated' {
+ $commandHelp.Synopsis | Should -Not -BeLike '*`[``]*'
+ }
+
+ # Should be a description for every function
+ It "Has description" {
+ $commandHelp.Description | Should -Not -BeNullOrEmpty
+ }
+
+ # Should be at least one example
+ It "Has example code" {
+ ($commandHelp.Examples.Example | Select-Object -First 1).Code | Should -Not -BeNullOrEmpty
+ }
+
+ # Should be at least one example description
+ It "Has example help" {
+ ($commandHelp.Examples.Example.Remarks | Select-Object -First 1).Text | Should -Not -BeNullOrEmpty
+ }
+
+ It "Help link <_> is valid" -ForEach $helpLinks {
+ (Invoke-WebRequest -Uri $_ -UseBasicParsing).StatusCode | Should -Be '200'
+ }
+
+ Context "Parameter <_.Name>" -ForEach $commandParameters {
+
+ BeforeAll {
+ $parameter = $_
+ $parameterName = $parameter.Name
+ $parameterHelp = $commandHelp.parameters.parameter | Where-Object Name -EQ $parameterName
+ $parameterHelpType = if ($parameterHelp.ParameterValue) { $parameterHelp.ParameterValue.Trim() }
+ }
+
+ # Should be a description for every parameter
+ It "Has description" {
+ $parameterHelp.Description.Text | Should -Not -BeNullOrEmpty
+ }
+
+ # Required value in Help should match IsMandatory property of parameter
+ It "Has correct [mandatory] value" {
+ $codeMandatory = $_.IsMandatory.toString()
+ $parameterHelp.Required | Should -Be $codeMandatory
+ }
+
+ # Parameter type in help should match code
+ It "Has correct parameter type" {
+ $parameterHelpType | Should -Be $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 $parameterNames | Should -Be $true
+ }
+ }
+}
diff --git a/tests/TestModule/Tests/Manifest.tests.ps1 b/tests/fixtures/TestModule/Tests/Manifest.tests.ps1
similarity index 100%
rename from tests/TestModule/Tests/Manifest.tests.ps1
rename to tests/fixtures/TestModule/Tests/Manifest.tests.ps1
diff --git a/tests/TestModule/Tests/Meta.tests.ps1 b/tests/fixtures/TestModule/Tests/Meta.tests.ps1
similarity index 100%
rename from tests/TestModule/Tests/Meta.tests.ps1
rename to tests/fixtures/TestModule/Tests/Meta.tests.ps1
diff --git a/tests/TestModule/Tests/MetaFixers.psm1 b/tests/fixtures/TestModule/Tests/MetaFixers.psm1
similarity index 100%
rename from tests/TestModule/Tests/MetaFixers.psm1
rename to tests/fixtures/TestModule/Tests/MetaFixers.psm1
diff --git a/tests/TestModule/Tests/ScriptAnalyzerSettings.psd1 b/tests/fixtures/TestModule/Tests/ScriptAnalyzerSettings.psd1
similarity index 100%
rename from tests/TestModule/Tests/ScriptAnalyzerSettings.psd1
rename to tests/fixtures/TestModule/Tests/ScriptAnalyzerSettings.psd1
diff --git a/tests/TestModule/Tests/a_InModuleScope.tests.ps1 b/tests/fixtures/TestModule/Tests/a_InModuleScope.tests.ps1
similarity index 100%
rename from tests/TestModule/Tests/a_InModuleScope.tests.ps1
rename to tests/fixtures/TestModule/Tests/a_InModuleScope.tests.ps1
diff --git a/tests/TestModule/azure-pipelines.yml b/tests/fixtures/TestModule/azure-pipelines.yml
similarity index 100%
rename from tests/TestModule/azure-pipelines.yml
rename to tests/fixtures/TestModule/azure-pipelines.yml
diff --git a/tests/TestModule/build.ps1 b/tests/fixtures/TestModule/build.ps1
similarity index 100%
rename from tests/TestModule/build.ps1
rename to tests/fixtures/TestModule/build.ps1
diff --git a/tests/TestModule/mkdocs.yml b/tests/fixtures/TestModule/mkdocs.yml
similarity index 100%
rename from tests/TestModule/mkdocs.yml
rename to tests/fixtures/TestModule/mkdocs.yml
diff --git a/tests/TestModule/psakeFile.ps1 b/tests/fixtures/TestModule/psakeFile.ps1
similarity index 67%
rename from tests/TestModule/psakeFile.ps1
rename to tests/fixtures/TestModule/psakeFile.ps1
index 68e4dbb..d2dd73e 100644
--- a/tests/TestModule/psakeFile.ps1
+++ b/tests/fixtures/TestModule/psakeFile.ps1
@@ -1,6 +1,6 @@
-Import-Module ../../Output/PowerShellBuild -Force
+Import-Module $global:PSBOutput -Force
-properties {
+Properties {
# Pester can build the module using both scenarios
if (Test-Path -Path 'Variable:\PSBuildCompile') {
$PSBPreference.Build.CompileModule = $global:PSBuildCompile
@@ -15,21 +15,24 @@ properties {
$PSBPreference.Build.Exclude = ('excludeme.txt', 'excludemealso*', 'dontcopy')
# If compiling, insert headers/footers for entire PSM1 and for each inserted function
- $PSBPreference.Build.CompileHeader = '# Module Header' + [Environment]::NewLine
- $PSBPreference.Build.CompileFooter = '# Module Footer'
+ $PSBPreference.Build.CompileHeader = '# Module Header' + [Environment]::NewLine
+ $PSBPreference.Build.CompileFooter = '# Module Footer'
$PSBPreference.Build.CompileScriptHeader = '# Function header'
$PSBPreference.Build.CompileScriptFooter = '# Function footer' + [Environment]::NewLine
# So Pester InModuleScope works
- $PSBPreference.Test.ImportModule = $true
- $PSBPreference.Test.CodeCoverage.Enabled = $true
+ $PSBPreference.Test.ImportModule = $true
+ $PSBPreference.Test.CodeCoverage.Enabled = $true
$PSBPreference.Test.CodeCoverage.Threshold = 0.0
$PSBPreference.Test.CodeCoverage.OutputFile = 'cc.xml'
# Override the default output directory
$PSBPreference.Build.OutDir = 'Output'
+
+ # Don't overwrite the docs
+ $PSBPreference.Docs.Overwrite = $false
}
-task default -depends Build
+Task default -Depends Build
-task Build -FromModule PowerShellBuild -minimumVersion 0.5.0
+Task Build -FromModule PowerShellBuild -MinimumVersion 0.5.0
diff --git a/tests/TestModule/requirements.psd1 b/tests/fixtures/TestModule/requirements.psd1
similarity index 100%
rename from tests/TestModule/requirements.psd1
rename to tests/fixtures/TestModule/requirements.psd1