diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f3ae7a..518d4c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 `Required` or `Write`. - `Get-CompositeResourceParameterValidateSet` - Returns the array of values contained in the ValidateSet parameter attributes if it exists. +- Added QA test to do some quality checks on the module code and change log. ### Changed @@ -43,6 +44,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 use with composite DSC resources. - Enabled the function to extract the comment block if it is not at the top of the script file to support composite resources. +- Updated code to pass newly added quality checks. ### Fixed diff --git a/build.yaml b/build.yaml index 1097968..dd75b96 100644 --- a/build.yaml +++ b/build.yaml @@ -65,7 +65,8 @@ Pester: ExcludeFromCodeCoverage: - Modules/DscResource.Common Script: - - tests/unit + - tests/QA + - tests/unit ExcludeTag: Tag: CodeCoverageThreshold: 80 diff --git a/source/Private/Copy-WikiFolder.ps1 b/source/Private/Copy-WikiFolder.ps1 index 860c2fc..b3aa618 100644 --- a/source/Private/Copy-WikiFolder.ps1 +++ b/source/Private/Copy-WikiFolder.ps1 @@ -3,6 +3,10 @@ Copies any Wiki files from the module into the Wiki and optionally overwrite any existing files. + .DESCRIPTION + Copies any Wiki files from the module into the Wiki and optionally overwrite + any existing files. + .PARAMETER Path The path to the output that was generated by New-DscResourceWikiPage. @@ -12,6 +16,9 @@ .PARAMETER WikiSourcePath The name of the folder that contains the source Wiki files. + .PARAMETER Force + If present, copies files forcefully, overwriting any existing files. + .EXAMPLE Copy-WikiFolder -Path '.\output\WikiContent' -DestinationPath 'c:\repoName.wiki.git' -WikiSourcePath '.\source\WikiSource' diff --git a/source/Private/Format-Text.ps1 b/source/Private/Format-Text.ps1 index 78007e8..0c2e643 100644 --- a/source/Private/Format-Text.ps1 +++ b/source/Private/Format-Text.ps1 @@ -2,8 +2,11 @@ .SYNOPSIS Formats a string using predefined format options. + .DESCRIPTION + Formats a string using predefined format options. + .PARAMETER Text - The string to format. + Specifies the string to format. .PARAMETER Format One or more predefined format options. The formatting is done in the diff --git a/source/Private/Get-ClassAst.ps1 b/source/Private/Get-ClassAst.ps1 index 2ce91ad..d79ffc5 100644 --- a/source/Private/Get-ClassAst.ps1 +++ b/source/Private/Get-ClassAst.ps1 @@ -2,6 +2,9 @@ .SYNOPSIS Returns the AST for a single or all classes. + .DESCRIPTION + Returns the AST for a single or all classes. + .PARAMETER ScriptFile The path to the source file that contain the class. @@ -21,6 +24,7 @@ function Get-ClassAst { [CmdletBinding()] + [OutputType([System.Collections.Generic.IEnumerable`1[System.Management.Automation.Language.Ast]])] param ( [Parameter(Mandatory = $true)] diff --git a/source/Private/Get-ClassResourceAst.ps1 b/source/Private/Get-ClassResourceAst.ps1 index b98facf..cc9c25e 100644 --- a/source/Private/Get-ClassResourceAst.ps1 +++ b/source/Private/Get-ClassResourceAst.ps1 @@ -2,6 +2,9 @@ .SYNOPSIS Returns the AST for a single or all DSC class resources. + .DESCRIPTION + Returns the AST for a single or all DSC class resources. + .PARAMETER ScriptFile The path to the source file that contain the DSC class resource. diff --git a/source/Private/Get-ClassResourceProperty.ps1 b/source/Private/Get-ClassResourceProperty.ps1 index dd2fcb0..ecad583 100644 --- a/source/Private/Get-ClassResourceProperty.ps1 +++ b/source/Private/Get-ClassResourceProperty.ps1 @@ -2,6 +2,9 @@ .SYNOPSIS Returns DSC class resource properties from the provided class or classes. + .DESCRIPTION + Returns DSC class resource properties from the provided class or classes. + .PARAMETER SourcePath The path to the source folder (in which the child folder 'Classes' exist). diff --git a/source/Private/Get-ConfigurationAst.ps1 b/source/Private/Get-ConfigurationAst.ps1 index 97c28fa..f6d85ff 100644 --- a/source/Private/Get-ConfigurationAst.ps1 +++ b/source/Private/Get-ConfigurationAst.ps1 @@ -2,6 +2,9 @@ .SYNOPSIS Returns the AST for a single or all configurations. + .DESCRIPTION + Returns the AST for a single or all configurations. + .PARAMETER ScriptFile The path to the source file that contain the configuration. @@ -25,6 +28,7 @@ function Get-ConfigurationAst { [CmdletBinding()] + [OutputType([System.Collections.Generic.IEnumerable`1[System.Management.Automation.Language.Ast]])] param ( [Parameter(Mandatory = $true)] diff --git a/source/Private/Get-DscResourceHelpExampleContent.ps1 b/source/Private/Get-DscResourceHelpExampleContent.ps1 index fb42ad5..8ada3ac 100644 --- a/source/Private/Get-DscResourceHelpExampleContent.ps1 +++ b/source/Private/Get-DscResourceHelpExampleContent.ps1 @@ -10,8 +10,8 @@ .PARAMETER ExamplePath The path to the example file. - .PARAMETER ModulePath - The number of the example. + .PARAMETER ExampleNumber + The (order) number of the example. .EXAMPLE Get-DscResourceHelpExampleContent -ExamplePath 'C:\repos\NetworkingDsc\Examples\Resources\DhcpClient\1-DhcpClient_EnableDHCP.ps1' -ExampleNumber 1 diff --git a/source/Private/Get-DscResourceSchemaPropertyContent.ps1 b/source/Private/Get-DscResourceSchemaPropertyContent.ps1 index cd5a867..ac194d0 100644 --- a/source/Private/Get-DscResourceSchemaPropertyContent.ps1 +++ b/source/Private/Get-DscResourceSchemaPropertyContent.ps1 @@ -7,10 +7,14 @@ Get-DscResourceSchemaPropertyContent is used to generate the parameter content for the wiki page. - .PARAMETER Attribute + .PARAMETER Property A hash table with properties that is returned by Get-MofSchemaObject in the property Attributes. + .PARAMETER UseMarkdown + If certain text should be output as markdown, for example values of the + hashtable property ValueMap. + .EXAMPLE $content = Get-DscResourceSchemaPropertyContent -Property @( @{ diff --git a/source/Private/Get-DscResourceWikiExampleContent.ps1 b/source/Private/Get-DscResourceWikiExampleContent.ps1 index 1a4674e..2015745 100644 --- a/source/Private/Get-DscResourceWikiExampleContent.ps1 +++ b/source/Private/Get-DscResourceWikiExampleContent.ps1 @@ -12,8 +12,8 @@ .PARAMETER ExamplePath The path to the example file. - .PARAMETER ModulePath - The number of the example. + .PARAMETER ExampleNumber + The (order) number of the example. .EXAMPLE Get-DscResourceWikiExampleContent -ExamplePath 'C:\repos\NetworkingDsc\Examples\Resources\DhcpClient\1-DhcpClient_EnableDHCP.ps1' -ExampleNumber 1 diff --git a/source/Private/Get-TemporaryPath.ps1 b/source/Private/Get-TemporaryPath.ps1 index c35c59e..d1a1af3 100644 --- a/source/Private/Get-TemporaryPath.ps1 +++ b/source/Private/Get-TemporaryPath.ps1 @@ -8,6 +8,11 @@ on Windows OS, '/tmp' when run in Linux and $ENV:TMPDIR when run on MacOS. + .EXAMPLE + Get-TemporaryPath + + Get the temporary path (which will differ between operating system). + .NOTES We use Get-Variable to determine if the OS specific variables are defined so that we can mock these during testing. We also use Get-Item diff --git a/source/Private/Invoke-Git.ps1 b/source/Private/Invoke-Git.ps1 index a55ef51..883d314 100644 --- a/source/Private/Invoke-Git.ps1 +++ b/source/Private/Invoke-Git.ps1 @@ -1,6 +1,9 @@ <# .SYNOPSIS - Invokes the git command. + Invokes a git command. + + .DESCRIPTION + Invokes a git command with command line arguments. .PARAMETER WorkingDirectory The path to the git working directory. diff --git a/source/Private/New-DscClassResourceWikiPage.ps1 b/source/Private/New-DscClassResourceWikiPage.ps1 index 830c957..920ee8d 100644 --- a/source/Private/New-DscClassResourceWikiPage.ps1 +++ b/source/Private/New-DscClassResourceWikiPage.ps1 @@ -20,6 +20,9 @@ The path to the root of the built DSC resource module, e.g. 'output/MyResource/1.0.0'. + .PARAMETER Force + Overwrites any existing file when outputting the generated content. + .EXAMPLE New-DscClassResourceWikiPage ` -SourcePath C:\repos\MyResource\source ` @@ -30,6 +33,7 @@ #> function New-DscClassResourceWikiPage { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] param ( diff --git a/source/Private/New-DscMofResourceWikiPage.ps1 b/source/Private/New-DscMofResourceWikiPage.ps1 index 39d14ae..59a9bda 100644 --- a/source/Private/New-DscMofResourceWikiPage.ps1 +++ b/source/Private/New-DscMofResourceWikiPage.ps1 @@ -20,6 +20,9 @@ The path to the root of the built DSC resource module, e.g. 'output/MyResource/1.0.0'. + .PARAMETER Force + Overwrites any existing file when outputting the generated content. + .EXAMPLE New-DscMofResourceWikiPage ` -SourcePath C:\repos\MyResource\source ` @@ -30,6 +33,8 @@ #> function New-DscMofResourceWikiPage { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', '')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] param ( diff --git a/source/Private/New-TempFolder.ps1 b/source/Private/New-TempFolder.ps1 index e16ccb2..e77c153 100644 --- a/source/Private/New-TempFolder.ps1 +++ b/source/Private/New-TempFolder.ps1 @@ -2,6 +2,9 @@ .SYNOPSIS Creates a new temporary folder with a random name. + .DESCRIPTION + Creates a new temporary folder with a random name. + .EXAMPLE New-TempFolder @@ -15,6 +18,7 @@ #> function New-TempFolder { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] [OutputType([System.IO.DirectoryInfo])] param diff --git a/source/Private/New-WikiFooter.ps1 b/source/Private/New-WikiFooter.ps1 index a8ff8c3..c86fcd0 100644 --- a/source/Private/New-WikiFooter.ps1 +++ b/source/Private/New-WikiFooter.ps1 @@ -2,6 +2,9 @@ .SYNOPSIS Creates the Wiki footer file if one does not already exist. + .DESCRIPTION + Creates the Wiki footer file if one does not already exist. + .PARAMETER Path The path for the Wiki footer file. @@ -15,6 +18,7 @@ #> function New-WikiFooter { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] param ( diff --git a/source/Private/New-WikiSidebar.ps1 b/source/Private/New-WikiSidebar.ps1 index 9ba69a9..8e10cba 100644 --- a/source/Private/New-WikiSidebar.ps1 +++ b/source/Private/New-WikiSidebar.ps1 @@ -2,6 +2,9 @@ .SYNOPSIS Creates the Wiki side bar file from the list of markdown files in the path. + .DESCRIPTION + Creates the Wiki side bar file from the list of markdown files in the path. + .PARAMETER ModuleName The name of the module to generate a new Wiki Sidebar file for. @@ -20,6 +23,7 @@ #> function New-WikiSidebar { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] param ( diff --git a/source/Private/Test-PropertyMemberAst.ps1 b/source/Private/Test-PropertyMemberAst.ps1 index 744a964..2a193bf 100644 --- a/source/Private/Test-PropertyMemberAst.ps1 +++ b/source/Private/Test-PropertyMemberAst.ps1 @@ -11,6 +11,18 @@ The Abstract Syntax Tree (AST) for class-based DSC resource property. The passed value must be an AST of the type 'PropertyMemberAst'. + .PARAMETER IsKey + Specifies if the parameter is expected to have the type qualifier Key. + + .PARAMETER IsMandatory + Specifies if the parameter is expected to have the type qualifier Mandatory. + + .PARAMETER IsWrite + Specifies if the parameter is expected to have the type qualifier Write. + + .PARAMETER IsRead + Specifies if the parameter is expected to have the type qualifier Read. + .EXAMPLE Test-PropertyMemberAst -IsKey -Ast { [DscResource()] diff --git a/source/Public/New-DscResourcePowerShellHelp.ps1 b/source/Public/New-DscResourcePowerShellHelp.ps1 index d8dfdcf..ce0ba85 100644 --- a/source/Public/New-DscResourcePowerShellHelp.ps1 +++ b/source/Public/New-DscResourcePowerShellHelp.ps1 @@ -99,6 +99,7 @@ #> function New-DscResourcePowerShellHelp { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] param ( diff --git a/source/Public/New-DscResourceWikiPage.ps1 b/source/Public/New-DscResourceWikiPage.ps1 index fe35726..368b933 100644 --- a/source/Public/New-DscResourceWikiPage.ps1 +++ b/source/Public/New-DscResourceWikiPage.ps1 @@ -21,6 +21,9 @@ The path to the root of the built DSC resource module, e.g. 'output/MyResource/1.0.0'. + .PARAMETER Force + Overwrites any existing file when outputting the generated content. + .EXAMPLE New-DscResourceWikiPage ` -SourcePath C:\repos\MyResource\source ` @@ -31,6 +34,7 @@ #> function New-DscResourceWikiPage { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] param ( diff --git a/source/Public/Publish-WikiContent.ps1 b/source/Public/Publish-WikiContent.ps1 index 67cd68f..bb6dd4b 100644 --- a/source/Public/Publish-WikiContent.ps1 +++ b/source/Public/Publish-WikiContent.ps1 @@ -33,6 +33,11 @@ .PARAMETER GitUserName The user name to use for the Git commit. + .PARAMETER GlobalCoreAutoCrLf + Specifies how line breaks should be handled when cloning the + GitHub wiki repository. Valid values are 'true', 'false', or + 'input'. + .EXAMPLE Publish-WikiContent ` -Path '.\output\WikiContent' ` diff --git a/source/Public/Set-WikiModuleVersion.ps1 b/source/Public/Set-WikiModuleVersion.ps1 index ce36bdb..23891c0 100644 --- a/source/Public/Set-WikiModuleVersion.ps1 +++ b/source/Public/Set-WikiModuleVersion.ps1 @@ -19,6 +19,7 @@ #> function Set-WikiModuleVersion { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '')] [CmdletBinding()] param ( diff --git a/source/Public/Split-ModuleVersion.ps1 b/source/Public/Split-ModuleVersion.ps1 index b1e727b..87cccd4 100644 --- a/source/Public/Split-ModuleVersion.ps1 +++ b/source/Public/Split-ModuleVersion.ps1 @@ -3,8 +3,12 @@ This function parses a module version string as returns a PSCustomObject which each of the module version's parts. + .DESCRIPTION + This function parses a module version string as returns a PSCustomObject + which each of the module version's parts. + .PARAMETER ModuleVersion - The module to parse. + The module version for which to return the module version's parts. .EXAMPLE Split-ModuleVersion -ModuleVersion '1.15.0-pr0224-0022+Sha.47ae45eb' diff --git a/tests/QA/module.tests.ps1 b/tests/QA/module.tests.ps1 new file mode 100644 index 0000000..04713d4 --- /dev/null +++ b/tests/QA/module.tests.ps1 @@ -0,0 +1,233 @@ + +$script:moduleName = 'DscResource.DocGenerator' + +# Convert-Path required for PS7 or Join-Path fails +$projectPath = "$($PSScriptRoot)\..\.." | Convert-Path + +$sourcePath = ( + Get-ChildItem -Path $projectPath\*\*.psd1 | + Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) ` + -and $( + try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction 'Stop' + } + catch + { + $false + } + ) + } +).Directory.FullName + +Describe 'Changelog Management' -Tag 'Changelog' { + It 'Should have updated the Changelog' -skip:( + -not ( + [System.Boolean] (Get-Command -Name git -ErrorAction 'SilentlyContinue') -and + [System.Boolean] (& (Get-Process -Id $PID).Path -NoProfile -Command 'git rev-parse --is-inside-work-tree 2>$null') + ) + ) { + # Get the list of changed files compared with master + $headCommit = & git rev-parse HEAD + $defaultBranchCommit = & git rev-parse origin/main + $filesChanged = & git @('diff', "$defaultBranchCommit...$headCommit", '--name-only') + + if ($headCommit -ne $defaultBranchCommit) + { + # If we're not testing same commit (i.e. main..main) + $filesChanged.Where{ (Split-Path $_ -Leaf) -match '^changelog' } | Should -Not -BeNullOrEmpty + } + } + + It 'Should have the Changelog compliant with the Keepachangelog format' -skip:(-not [System.Boolean] (Get-Command git -ErrorAction 'SilentlyContinue')) { + { + Get-ChangelogData -Path (Join-Path -Path $ProjectPath -ChildPath 'CHANGELOG.md') -ErrorAction 'Stop' + } | Should -Not -Throw + } +} + +Describe 'General module control' -Tags 'FunctionalQuality' { + It 'Should import without errors' { + { Import-Module -Name $script:moduleName -Force -ErrorAction Stop } | Should -Not -Throw + + Get-Module -Name $script:moduleName | Should -Not -BeNullOrEmpty + } + + It 'Should remove without error' { + { Remove-Module -Name $script:moduleName -ErrorAction Stop } | Should -Not -Throw + + Get-Module -Name $script:moduleName | Should -BeNullOrEmpty + } +} + +#region Build test cases +$script:moduleName = 'DscResource.DocGenerator' + +Remove-Module -Name $script:moduleName -Force -ErrorAction 'SilentlyContinue' + +$mut = Get-Module -Name $script:moduleName -ListAvailable | + Select-Object -First 1 | + Import-Module -Force -ErrorAction 'Stop' -PassThru + +# Must use the imported module to build test cases. +$allModuleFunctions = & $mut { Get-Command -Module $args[0] -CommandType Function } $script:moduleName + +# Build test cases. +$testCases = @() + +foreach ($function in $allModuleFunctions) +{ + $testCases += @{ + Name = $function.Name + } + +} +#endregion Build test cases + +Describe 'Quality for module' -Tags 'TestQuality' { + if (Get-Command -Name Invoke-ScriptAnalyzer -ErrorAction SilentlyContinue) + { + $scriptAnalyzerRules = Get-ScriptAnalyzerRule + } + else + { + if ($ErrorActionPreference -ne 'Stop') + { + Write-Warning -Message 'ScriptAnalyzer not found!' + } + else + { + throw 'ScriptAnalyzer not found!' + } + } + + It 'Should have a unit test for ' -TestCases $testCases { + param + ( + $Name + ) + + Get-ChildItem -Path 'tests\' -Recurse -Include "$Name.Tests.ps1" | Should -Not -BeNullOrEmpty + } + + It 'Should pass Script Analyzer for ' -TestCases $testCases -Skip:(-not $scriptAnalyzerRules) { + param + ( + $Name + ) + + $functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1" + + $pssaResult = (Invoke-ScriptAnalyzer -Path $functionFile.FullName) + $report = $pssaResult | Format-Table -AutoSize | Out-String -Width 110 + $pssaResult | Should -BeNullOrEmpty -Because ` + "some rule triggered.`r`n`r`n $report" + } +} + +Describe 'Help for module' -Tags 'helpQuality' { + It 'Should have .SYNOPSIS for ' -TestCases $testCases { + param + ( + $Name + ) + + $functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1" + + $scriptFileRawContent = Get-Content -Raw -Path $functionFile.FullName + + $abstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($scriptFileRawContent, [ref] $null, [ref] $null) + + $astSearchDelegate = { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] } + + $parsedFunction = $abstractSyntaxTree.FindAll( $astSearchDelegate, $true ) | + Where-Object -FilterScript { + $_.Name -eq $Name + } + + $functionHelp = $parsedFunction.GetHelpContent() + + $functionHelp.Synopsis | Should -Not -BeNullOrEmpty + } + + It 'Should have a .DESCRIPTION with length greater than 40 characters for ' -TestCases $testCases { + param + ( + $Name + ) + + $functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1" + + $scriptFileRawContent = Get-Content -Raw -Path $functionFile.FullName + + $abstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($scriptFileRawContent, [ref] $null, [ref] $null) + + $astSearchDelegate = { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] } + + $parsedFunction = $abstractSyntaxTree.FindAll( $astSearchDelegate, $true ) | + Where-Object -FilterScript { + $_.Name -eq $Name + } + + $functionHelp = $parsedFunction.GetHelpContent() + + $functionHelp.Description.Length | Should -BeGreaterThan 40 + } + + It 'Should have at least one (1) example for ' -TestCases $testCases { + param + ( + $Name + ) + + $functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1" + + $scriptFileRawContent = Get-Content -Raw -Path $functionFile.FullName + + $abstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($scriptFileRawContent, [ref] $null, [ref] $null) + + $astSearchDelegate = { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] } + + $parsedFunction = $abstractSyntaxTree.FindAll( $astSearchDelegate, $true ) | + Where-Object -FilterScript { + $_.Name -eq $Name + } + + $functionHelp = $parsedFunction.GetHelpContent() + + $functionHelp.Examples.Count | Should -BeGreaterThan 0 + $functionHelp.Examples[0] | Should -Match ([regex]::Escape($Name)) + $functionHelp.Examples[0].Length | Should -BeGreaterThan ($Name.Length + 10) + } + + It 'Should have described all parameters for ' -TestCases $testCases { + param + ( + $Name + ) + + $functionFile = Get-ChildItem -Path $sourcePath -Recurse -Include "$Name.ps1" + + $scriptFileRawContent = Get-Content -Raw -Path $functionFile.FullName + + $abstractSyntaxTree = [System.Management.Automation.Language.Parser]::ParseInput($scriptFileRawContent, [ref] $null, [ref] $null) + + $astSearchDelegate = { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] } + + $parsedFunction = $abstractSyntaxTree.FindAll( $astSearchDelegate, $true ) | + Where-Object -FilterScript { + $_.Name -eq $Name + } + + $functionHelp = $parsedFunction.GetHelpContent() + + $parameters = $parsedFunction.Body.ParamBlock.Parameters.Name.VariablePath.ForEach({ $_.ToString() }) + + foreach ($parameter in $parameters) + { + $functionHelp.Parameters.($parameter.ToUpper()) | Should -Not -BeNullOrEmpty -Because ('the parameter {0} must have a description' -f $parameter) + $functionHelp.Parameters.($parameter.ToUpper()).Length | Should -BeGreaterThan 25 -Because ('the parameter {0} must have descriptive description' -f $parameter) + } + } +} diff --git a/tests/unit/public/Split-ModuleVersion.Tests.ps1 b/tests/unit/public/Split-ModuleVersion.Tests.ps1 new file mode 100644 index 0000000..8042f47 --- /dev/null +++ b/tests/unit/public/Split-ModuleVersion.Tests.ps1 @@ -0,0 +1,32 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:moduleName = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +Remove-Module -Name $script:moduleName -Force -ErrorAction 'SilentlyContinue' + +Import-Module $script:moduleName -Force -ErrorAction 'Stop' +#endregion HEADER + +Describe 'Split-ModuleVersion' { + Context 'When module version have prerelease string' { + It 'Should return the correct version' { + $result = Split-ModuleVersion -ModuleVersion '1.2.3-preview0001' + + $result | Should -BeOfType [PSCustomObject] + $result.Version | Should -Be '1.2.3' + $result.PreReleaseString | Should -Be 'preview0001' + $result.ModuleVersion | Should -Be '1.2.3-preview0001' + } + } +}