1010 ' PSUseDeclaredVarsMoreThanAssignments' , ' functionBearingFiles' ,
1111 Justification = ' Variables are used in the test.'
1212)]
13+ [Diagnostics.CodeAnalysis.SuppressMessageAttribute (
14+ ' PSUseDeclaredVarsMoreThanAssignments' , ' publicHelpLinkTestCases' ,
15+ Justification = ' Variable is used during Pester test discovery.'
16+ )]
1317[Diagnostics.CodeAnalysis.SuppressMessageAttribute (
1418 ' PSAvoidUsingWriteHost' , ' ' ,
1519 Justification = ' Logging to Github Actions.'
2024)]
2125[CmdLetBinding ()]
2226param (
27+ # The name of the module.
28+ [Parameter (Mandatory )]
29+ [string ] $ModuleName ,
30+
2331 # The path to the 'src' folder of the repo.
2432 [Parameter (Mandatory )]
2533 [string ] $Path ,
@@ -29,6 +37,37 @@ param(
2937 [string ] $TestsPath
3038)
3139
40+ BeforeDiscovery {
41+ $publicFunctionsPath = Join-Path - Path $Path - ChildPath ' functions/public'
42+ $publicHelpLinkTestCases = if (Test-Path - Path $publicFunctionsPath ) {
43+ Get-ChildItem - Path $publicFunctionsPath - Filter ' *.ps1' - Recurse - File |
44+ Sort-Object - Property FullName |
45+ ForEach-Object {
46+ $ast = [System.Management.Automation.Language.Parser ]::ParseFile($_.FullName , [ref ]$null , [ref ]$null )
47+ $functionTokens = $ast.FindAll ({ $args [0 ] -is [System.Management.Automation.Language.FunctionDefinitionAst ] }, $true )
48+ if ($functionTokens.Count -eq 0 ) {
49+ return
50+ }
51+
52+ $relativePath = [IO.Path ]::GetRelativePath($publicFunctionsPath , $_.FullName )
53+ $relativeDirectory = Split-Path - Path $relativePath - Parent
54+ $documentationPath = if ($relativeDirectory ) {
55+ ' {0}/{1}' -f ($relativeDirectory -replace ' [\\/]' , ' /' ), $_.BaseName
56+ } else {
57+ $_.BaseName
58+ }
59+
60+ @ {
61+ DocumentationPath = $documentationPath
62+ ExpectedLink = " https://psmodule.io/$ModuleName /Functions/$documentationPath /"
63+ FilePath = $_.FullName
64+ }
65+ }
66+ } else {
67+ @ ()
68+ }
69+ }
70+
3271BeforeAll {
3372 $scriptFiles = Get-ChildItem - Path $Path - Include * .psm1, * .ps1 - Recurse - File
3473 Write-Host " ::group:: - Script files [$ ( $scriptFiles.Count ) ]"
@@ -163,24 +202,6 @@ Describe 'PSModule - SourceCode tests' {
163202 $issues -join [Environment ]::NewLine |
164203 Should - BeNullOrEmpty - Because " the script should use '`$ null = ...' instead of '... | Out-Null'"
165204 }
166- It ' Should not use ternary operations for compatibility reasons (ID: NoTernary)' - Skip {
167- $issues = @ (' ' )
168- $scriptFiles | ForEach-Object {
169- $filePath = $_.FullName
170- $relativePath = $filePath.Replace ($Path , ' ' ).Trim(' \' ).Trim(' /' )
171- $skipTest = Select-String - Path $filePath - Pattern ' #SkipTest:NoTernary:(?<Reason>.+)' - AllMatches
172- if ($skipTest.Matches.Count -gt 0 ) {
173- $skipReason = $skipTest.Matches.Groups | Where-Object { $_.Name -eq ' Reason' } | Select-Object - ExpandProperty Value
174- Write-Host " ::warning title=Skipping NoTernary test:: - $relativePath - $skipReason "
175- } else {
176- Select-String - Path $filePath - Pattern ' (?<!\|)\s+\?\s' - AllMatches | ForEach-Object {
177- $issues += " - $relativePath `:L$ ( $_.LineNumber ) - $ ( $_.Line ) "
178- }
179- }
180- }
181- $issues -join [Environment ]::NewLine |
182- Should - BeNullOrEmpty - Because ' the script should not use ternary operations for compatibility with PS 5.1 and below'
183- }
184205 It ' all powershell keywords are lowercase (ID: LowercaseKeywords)' {
185206 $issues = @ (' ' )
186207 $scriptFiles | ForEach-Object {
@@ -339,6 +360,16 @@ Describe 'PSModule - SourceCode tests' {
339360 $tokens.count -ne 0
340361 }
341362 }
363+ It ' Should put the canonical documentation link first for <DocumentationPath> (ID: PublicHelpLink)' - ForEach $publicHelpLinkTestCases {
364+ param ($DocumentationPath , $ExpectedLink , $FilePath )
365+
366+ $content = Get-Content - Path $FilePath - Raw
367+ $links = [regex ]::Matches($content , ' (?ms)^\s*\.LINK\s*\r?\n\s*(?<Uri>\S+)' )
368+
369+ $links.Count | Should - BeGreaterThan 0 - Because " $DocumentationPath should have a documentation link"
370+ $links [0 ].Groups[' Uri' ].Value |
371+ Should - BeExactly $ExpectedLink - Because " $DocumentationPath should put its canonical documentation link first"
372+ }
342373 It ' All public functions/filters have tests (ID: FunctionTest)' {
343374 $issues = @ (' ' )
344375
0 commit comments