From 145c72aea88c8134204efa61b3df574565d52834 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Thu, 4 Feb 2021 12:39:44 +0000 Subject: [PATCH 01/27] Updated check function names --- Build/Build.Properties.json | 4 ++-- Checks/{Function-Extraction.Tests.ps1 => Extraction.ps1} | 0 Checks/{Module.Tests.ps1 => Module.Checks.ps1} | 0 Checks/{Project.Tests.ps1 => Project.Checks.ps1} | 0 Checks/{Script.Tests.ps1 => Script.Checks.ps1} | 0 Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 | 8 ++++---- 6 files changed, 6 insertions(+), 6 deletions(-) rename Checks/{Function-Extraction.Tests.ps1 => Extraction.ps1} (100%) rename Checks/{Module.Tests.ps1 => Module.Checks.ps1} (100%) rename Checks/{Project.Tests.ps1 => Project.Checks.ps1} (100%) rename Checks/{Script.Tests.ps1 => Script.Checks.ps1} (100%) diff --git a/Build/Build.Properties.json b/Build/Build.Properties.json index 60aa121..9119afd 100644 --- a/Build/Build.Properties.json +++ b/Build/Build.Properties.json @@ -46,8 +46,8 @@ "pester-tests" ], "Version": { - "PSQualityCheck": "1.3.1", - "PSQualityCheck.Functions": "1.3.1" + "PSQualityCheck": "1.4.0", + "PSQualityCheck.Functions": "1.4.0" } } } diff --git a/Checks/Function-Extraction.Tests.ps1 b/Checks/Extraction.ps1 similarity index 100% rename from Checks/Function-Extraction.Tests.ps1 rename to Checks/Extraction.ps1 diff --git a/Checks/Module.Tests.ps1 b/Checks/Module.Checks.ps1 similarity index 100% rename from Checks/Module.Tests.ps1 rename to Checks/Module.Checks.ps1 diff --git a/Checks/Project.Tests.ps1 b/Checks/Project.Checks.ps1 similarity index 100% rename from Checks/Project.Tests.ps1 rename to Checks/Project.Checks.ps1 diff --git a/Checks/Script.Tests.ps1 b/Checks/Script.Checks.ps1 similarity index 100% rename from Checks/Script.Tests.ps1 rename to Checks/Script.Checks.ps1 diff --git a/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 b/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 index f986fb5..af1f77e 100644 --- a/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 +++ b/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 @@ -369,12 +369,12 @@ function Invoke-PSQualityCheck { if ($runModuleCheck -eq $true) { # Run the Module tests on all the valid module files found - $container1 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Module.Tests.ps1') -Data @{ Source = $modulesToTest } + $container1 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Module.Checks.ps1') -Data @{ Source = $modulesToTest } $PesterConfiguration.Run.Container = $container1 $moduleResults = Invoke-Pester -Configuration $PesterConfiguration # Extract all the functions from the modules into individual .ps1 files ready for testing - $container2 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Function-Extraction.Tests.ps1') -Data @{ Source = $modulesToTest; ExtractPath = $extractPath } + $container2 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Extraction.ps1') -Data @{ Source = $modulesToTest; ExtractPath = $extractPath } $PesterConfiguration.Run.Container = $container2 $extractionResults = Invoke-Pester -Configuration $PesterConfiguration @@ -386,7 +386,7 @@ function Invoke-PSQualityCheck { $extractedScriptsToTest = Get-ChildItem -Path $extractPath -Include '*.ps1' -Recurse # Run the Script tests against all the extracted functions .ps1 files - $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Script.Tests.ps1') -Data @{ Source = $extractedScriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath; HelpRulesPath = $HelpRulesPath } + $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Script.Checks.ps1') -Data @{ Source = $extractedScriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath; HelpRulesPath = $HelpRulesPath } $PesterConfiguration.Run.Container = $container3 $extractedScriptResults = Invoke-Pester -Configuration $PesterConfiguration } @@ -403,7 +403,7 @@ function Invoke-PSQualityCheck { if ($scriptsToTest.Count -ge 1 -and $runScriptCheck -eq $true) { # Run the Script tests against all the valid script files found - $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Script.Tests.ps1') -Data @{ Source = $scriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath } + $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Script.Checks.ps1') -Data @{ Source = $scriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath } $PesterConfiguration.Run.Container = $container3 $scriptResults = Invoke-Pester -Configuration $PesterConfiguration From 7b978dc1e72d193b81689d4ef15d59c091a7ad79 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Thu, 4 Feb 2021 17:43:42 +0000 Subject: [PATCH 02/27] Fix invalid unit test check --- Checks/Project.Checks.ps1 | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Checks/Project.Checks.ps1 b/Checks/Project.Checks.ps1 index fb113fb..2df5150 100644 --- a/Checks/Project.Checks.ps1 +++ b/Checks/Project.Checks.ps1 @@ -20,8 +20,8 @@ BeforeDiscovery { $publicFolder = Join-Path -Path $moduleFolder -ChildPath "Public" $unitTestFolder = Join-Path -Path $unitTestPath -ChildPath $module.Name - $privateModules = Get-ChildItem -Path $privateFolder | Select-Object -Property Name, FullName - $publicModules = Get-ChildItem -Path $publicFolder | Select-Object -Property Name, FullName + $privateModules = Get-ChildItem -Path $privateFolder | Select-Object -Property Name, BaseName, FullName + $publicModules = Get-ChildItem -Path $publicFolder | Select-Object -Property Name, BaseName, FullName $moduleData += @{ 'Name' = $module.Name @@ -78,8 +78,9 @@ Describe "Project Test" -Tag "Project" { It "public script has a unit test" { - $TestScript = $_ - $TestScript.FullName | Should -Exist + $testFileName = "{0}{1}" -f $_.BaseName, ".Tests.ps1" + $TestScript = Join-Path -Path $unitTestFolder -ChildPath $testFileName + $TestScript | Should -Exist } From e34cef6779598901b5d88da8c026ef146fc5d06a Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Thu, 4 Feb 2021 17:44:03 +0000 Subject: [PATCH 03/27] Fix build properties file --- Build/Build.Properties.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Build/Build.Properties.json b/Build/Build.Properties.json index 9119afd..7e98564 100644 --- a/Build/Build.Properties.json +++ b/Build/Build.Properties.json @@ -32,7 +32,8 @@ "NestedModules": { "PSQualityCheck": [ "PSQualityCheck.Functions.psd1" - ] + ], + "PSQualityCheck.Functions": null }, "PowerShellVersion": "5.0", "ProjectUri": "https://github.com/andrewrdavidson/PSQualityCheck", From cfe731f766e5936b42ec8d0707a6c3a54c801fc1 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Tue, 20 Apr 2021 15:02:53 +0100 Subject: [PATCH 04/27] updted todo --- TODO | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 TODO diff --git a/TODO b/TODO new file mode 100644 index 0000000..669d2d7 --- /dev/null +++ b/TODO @@ -0,0 +1,8 @@ +Project check - Must contain 1+ Modules with 1+ Functions. Any Function should have 1 unit test. Optional Integration tests. + +Project output should contain list of functions and paths. + +add function that exports list of modules and paths independant of invoke psqualitycheck + + + From 435c1d16b2b6f071d3ac2576d9e6a34d9e27a0a8 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Wed, 21 Apr 2021 18:23:06 +0100 Subject: [PATCH 05/27] Added gitmodules --- .gitmodules | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .gitmodules diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..223d36b --- /dev/null +++ b/.gitmodules @@ -0,0 +1,9 @@ +[submodule "HelpRules/InjectionHunter"] + path = HelpRules/InjectionHunter + url = https://github.com/matt2005/InjectionHunter +[submodule "HelpRules/ScriptAnalyzerRules"] + path = HelpRules/ScriptAnalyzerRules + url = https://github.com/indented-automation/ScriptAnalyzerRules +[submodule "HelpRules/PSScriptAnalyzer"] + path = HelpRules/PSScriptAnalyzer + url = https://github.com/PowerShell/PSScriptAnalyzer From 7958214e584ee3e807192f35adc82b73e0df0c8a Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Sat, 24 Apr 2021 18:22:26 +0100 Subject: [PATCH 06/27] Updated to new project layout --- .editorconfig | 26 ++ Build/Build.Properties.json | 54 ---- Build/Invoke-Build.ps1 | 239 ---------------- Checks/Extraction.ps1 | 57 ---- Checks/HelpRules.psd1 | 73 ----- Checks/Module.Checks.ps1 | 84 ------ Checks/Project.Checks.ps1 | 114 -------- Checks/Script.Checks.ps1 | 269 ------------------ .../Public/Convert-Help.ps1 | 145 ---------- .../Public/Export-FunctionsFromModule.ps1 | 104 ------- .../Public/Get-FileContent.ps1 | 112 -------- .../Public/Get-FileList.ps1 | 56 ---- .../Public/Get-FunctionCount.ps1 | 100 ------- .../Public/Get-ParsedContent.ps1 | 29 -- .../Public/Get-ParsedFile.ps1 | 38 --- .../Public/Get-ScriptParameter.ps1 | 76 ----- .../Public/Get-TagList.ps1 | 71 ----- .../Public/Get-Token.ps1 | 38 --- .../Public/Get-TokenComponent.ps1 | 35 --- .../Public/Get-TokenMarker.ps1 | 41 --- .../Public/Test-HelpTokensCountIsValid.ps1 | 82 ------ .../Public/Test-HelpTokensParamsMatch.ps1 | 92 ------ .../Public/Test-HelpTokensTextIsValid.ps1 | 57 ---- .../Public/Test-ImportModuleIsValid.ps1 | 71 ----- .../Test-ParameterVariablesHaveType.ps1 | 48 ---- .../Public/Test-RequiredToken.ps1 | 62 ---- .../Public/Test-UnspecifiedToken.ps1 | 65 ----- .../Public/Invoke-PSQualityCheck.ps1 | 132 +++++---- build.ps1 | 202 +++++++++++++ docs/about.md | 6 + docs/acknowledgements.md | 0 docs/index.md | 4 + docs/quickstart.md | 5 + install.depend.ps1 | 25 ++ install.depend.psd1 | 20 ++ 35 files changed, 361 insertions(+), 2271 deletions(-) create mode 100644 .editorconfig delete mode 100644 Build/Build.Properties.json delete mode 100644 Build/Invoke-Build.ps1 delete mode 100644 Checks/Extraction.ps1 delete mode 100644 Checks/HelpRules.psd1 delete mode 100644 Checks/Module.Checks.ps1 delete mode 100644 Checks/Project.Checks.ps1 delete mode 100644 Checks/Script.Checks.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Convert-Help.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Export-FunctionsFromModule.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Get-FileContent.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Get-FileList.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Get-FunctionCount.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Get-ParsedContent.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Get-ParsedFile.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Get-ScriptParameter.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Get-TagList.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Get-Token.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Get-TokenComponent.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Get-TokenMarker.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Test-HelpTokensCountIsValid.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Test-HelpTokensParamsMatch.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Test-HelpTokensTextIsValid.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Test-ImportModuleIsValid.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Test-ParameterVariablesHaveType.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Test-RequiredToken.ps1 delete mode 100644 Source/PSQualityCheck.Functions/Public/Test-UnspecifiedToken.ps1 create mode 100644 build.ps1 create mode 100644 docs/about.md create mode 100644 docs/acknowledgements.md create mode 100644 docs/index.md create mode 100644 docs/quickstart.md create mode 100644 install.depend.ps1 create mode 100644 install.depend.psd1 diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..89c1e8a --- /dev/null +++ b/.editorconfig @@ -0,0 +1,26 @@ +# EditorConfig is awesome: http://EditorConfig.org +# +# Copied from https://github.com/PowerShell/PowerShellEditorServices/blob/master/.editorconfig + +# top-most EditorConfig file +root = true + +[*] +charset = utf-8 +indent_style = space +insert_final_newline = true + +[*.{cs}] +indent_size = 4 +trim_trailing_whitespace = true + +[*.{json}] +indent_size = 2 +trim_trailing_whitespace = true + +[*.{ps1,psm1,psd1}] +indent_size = 4 +trim_trailing_whitespace = true + +[*.{ps1xml,props,xml,yaml}] +indent_size = 2 diff --git a/Build/Build.Properties.json b/Build/Build.Properties.json deleted file mode 100644 index 7e98564..0000000 --- a/Build/Build.Properties.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "PreRequisites": { - "PSQualityCheck": "1.1.0", - "Pester": "5.1", - "PSScriptAnalyzer": "1.19.0" - }, - "Support": { - "PSQualityCheck": { - "ScriptAnalyzerRulesPath": "C:\\Source\\ScriptAnalyzerRules\\Indented.CodingConventions" - } - }, - "Module": { - "Author": "Andrew Davidson", - "Company": "Andrew Davidson", - "Copyright": "(c) Andrew Davidson. All rights reserved.", - "Description": { - "PSQualityCheck": "This module interfaces to a set of Pester tests that enable the enforcement of quality controls rules on PowerShell scripts and modules.", - "PSQualityCheck.Functions": "This module contains supporting functions for PSQualityCheck." - }, - "FileList": { - "PSQualityCheck": null, - "PSQualityCheck.Functions": [ - "Checks\\HelpRules.psd1" - ] - }, - "GUID": { - "PSQualityCheck": "9daebff2-9a44-48e4-9d4b-bed18c3c8e4b", - "PSQualityCheck.Functions": "5ddfdef7-3985-476d-92d8-e7db35bf960b" - }, - "HelpInfoURI": "https://github.com/andrewrdavidson/PSQualityCheck/wiki", - "LicenseUri": "https://github.com/andrewrdavidson/PSQualityCheck/blob/main/LICENSE", - "NestedModules": { - "PSQualityCheck": [ - "PSQualityCheck.Functions.psd1" - ], - "PSQualityCheck.Functions": null - }, - "PowerShellVersion": "5.0", - "ProjectUri": "https://github.com/andrewrdavidson/PSQualityCheck", - "Tags": [ - "powershell", - "powershell-module", - "quality", - "quality-check", - "tests", - "pester", - "pester-tests" - ], - "Version": { - "PSQualityCheck": "1.4.0", - "PSQualityCheck.Functions": "1.4.0" - } - } -} diff --git a/Build/Invoke-Build.ps1 b/Build/Invoke-Build.ps1 deleted file mode 100644 index d6481f0..0000000 --- a/Build/Invoke-Build.ps1 +++ /dev/null @@ -1,239 +0,0 @@ -<# - .SYNOPSIS - Build the PSMoxu module and its sub-modules - - .DESCRIPTION - Build the PSMoxu module and its sub-modules - - .PARAMETER Properties - A string containing the name of the build properties file - - .EXAMPLE - Invoke-Build.ps1 -Properties "Build.Properties.json" -#> -[CmdletBinding()] -[OutputType([System.Void])] -param ( - [string]$Properties = "Build.Properties.json" -) - -# Build the Moxu modules -Write-Verbose "Loading Build Properties" -try { - $buildProperties = Get-Content -Path $Properties | ConvertFrom-Json -} -catch { - throw "Error loading the Build Properties file" -} - -# Check that the build pre-requisites are available -Write-Verbose "Verifying pre-requisites are available" - -try { - - foreach ($preReq in $buildProperties.PreRequisites.PSObject.Properties) { - - Import-Module -Name $preReq.Name -MinimumVersion $preReq.Value -Verbose:$false - - if ( -not (Get-Module -Name $preReq.Name -ListAvailable -Verbose:$false) ) { - throw "Module '$($preReq.Name)' version '$($preReq.Value)' is not available" - } - else { - Write-Verbose "Module '$($preReq.Name)' version '$($preReq.Value)' is available" - } - - } - -} -catch { - - throw - -} - -# Generate build location -$builtModuleLocation = Split-Path -Path $PSScriptRoot -Parent -$sourceModuleLocation = Join-Path -Path (Split-Path -Path $PSScriptRoot -Parent) -ChildPath "Source" -Write-Verbose "Build Location: $builtModuleLocation" - -$PSQualityCheckSplat = @{} -if (-not ([string]::IsNullOrEmpty($buildProperties.Support.PSQualityCheck.ScriptAnalyzerRulesPath))) { - $PSQualityCheckSplat.Add("ScriptAnalyzerRulesPath", $buildProperties.Support.PSQualityCheck.ScriptAnalyzerRulesPath) - Write-Verbose "Adding ScriptAnalyzer Rules: $($buildProperties.Support.PSQualityCheck.ScriptAnalyzerRulesPath)" -} - -$PesterConfiguration = [PesterConfiguration]::Default -$PesterConfiguration.Run.Exit = $false -$PesterConfiguration.CodeCoverage.Enabled = $false -$PesterConfiguration.Output.Verbosity = 'None' -$PesterConfiguration.Run.PassThru = $false -$PesterConfiguration.Should.ErrorAction = 'Stop' -$PSQualityCheckSplat.Add("PesterConfiguration", $PesterConfiguration) - -$manifestsToTest = @() - -# Loop through the modules -foreach ($module in $buildProperties.Module.Version.PSObject.Properties) { - - Write-Verbose "Building module : $($module.Name)" - - Write-Verbose "Getting Public modules" - $functionPublicPath = Join-Path -Path (Join-Path -Path $sourceModuleLocation -ChildPath $module.Name) -ChildPath "public" - $sourcePublicFiles = Get-ChildItem -Path $functionPublicPath -Recurse - - Write-Verbose "Getting Private modules" - $functionPrivatePath = Join-Path -Path (Join-Path -Path $sourceModuleLocation -ChildPath $module.Name) -ChildPath "private" - $sourcePrivateFiles = Get-ChildItem -Path $functionPrivatePath -Recurse - - Write-Verbose "Generating module file name" - $moduleName = "{0}{1}" -f $module.Name, '.psm1' - $moduleFileName = Join-Path -Path $builtModuleLocation -ChildPath $moduleName - - # # remove the module if it exists - if (Test-Path -Path $moduleFileName) { - Write-Verbose "Removing existing module file name" - Remove-Item -Path $moduleFileName -Force - } - - Write-Verbose "Generating manifest file name" - $manifestName = "{0}{1}" -f $module.Name, '.psd1' - $manifestFileName = Join-Path -Path $builtModuleLocation -ChildPath $manifestName - $manifestsToTest += $manifestFileName - - # remove the module if it exists - if (Test-Path -Path $manifestFileName) { - Write-Verbose "Removing existing manifest file name" - Remove-Item -Path $manifestFileName -Force - } - - # Run the Quality Checks - Write-Verbose "Invoking PSQualityCheck" - Import-Module -Name PSQualityCheck -MinimumVersion "1.3.0" - - foreach ($function in $sourcePublicFiles) { - - Write-Verbose "Public function $($function.Name)" - Invoke-PSQualityCheck -File $function.FullName @PSQualityCheckSplat - - } - - foreach ($function in $sourcePrivateFiles) { - - Write-Verbose "Private function $($function.Name)" - Invoke-PSQualityCheck -File $function.FullName @PSQualityCheckSplat - - } - - Remove-Module -Name PSQualityCheck - - # Run the Unit Tests - # Write-Verbose "Invoking Unit tests" - - # $configuration = [PesterConfiguration]::Default - # $configuration.Run.Exit = $true - # $configuration.CodeCoverage.Enabled = $false - # $configuration.TestResult.Enabled = $false - # $configuration.Output.Verbosity = "Detailed" - # $configuration.Run.PassThru = $false - # $configuration.Should.ErrorAction = 'Stop' - - # foreach ($function in $sourcePublicFiles) { - - # . $function.FullName - # $script = "..\Tests\Unit\$($module.Name)\$($function.BaseName).Tests.ps1" - # Write-Verbose "Executing test $script" - - # $configuration.Run.Path = $script - # Invoke-Pester -Configuration $configuration - - # } - - # foreach ($function in $sourcePrivateFiles) { - - # . $function.FullName - # $script = "..\Tests\Unit\$($module.Name)\$($function.BaseName).Tests.ps1" - # Write-Verbose "Executing test $script" - - # $configuration.Run.Path = $script - # Invoke-Pester -Configuration $configuration - - # } - - $functionsToExport = @() - - # Build up the module from public and private functions - Write-Verbose "Generating Module" - foreach ($function in $sourcePublicFiles) { - - Write-Verbose "Adding function $($function.Name)" - Get-Content -Path $function.FullName | Add-Content -Path $moduleFileName - - $functionsToExport += $function.BaseName - - "" | Add-Content -Path $moduleFileName - - } - - foreach ($function in $sourcePrivateFiles) { - - Write-Verbose "Adding function $($function.Name)" - Get-Content -Path $function.FullName | Add-Content -Path $moduleFileName - - "" | Add-Content -Path $moduleFileName - - } - - if (-not (Test-Path -Path $moduleFileName)) { - continue - } - - $newModuleManifest = @{ - Path = $manifestFileName - Guid = $buildProperties.Module.Guid.($module.Name) - RootModule = ("{0}{1}" -f $module.Name, '.psm1') - - ModuleVersion = $buildProperties.Module.Version.($module.Name) - PowerShellVersion = $buildProperties.Module.PowerShellVersion - - FunctionsToExport = $functionsToExport - CmdletsToExport = @() - VariablesToExport = @() - AliasesToExport = @() - - Author = $buildProperties.Module.Author - Company = $buildProperties.Module.Company - Copyright = $buildProperties.Module.Copyright - Description = $buildProperties.Module.Description.($module.Name) - FileList = $buildProperties.Module.FileList.($module.Name) - HelpInfoURI = $buildProperties.Module.HelpInfoURI - LicenseUri = $buildProperties.Module.LicenseUri - ProjectUri = $buildProperties.Module.ProjectUri - Tags = $buildProperties.Module.Tags - - NestedModules = $buildProperties.Module.NestedModules.($module.Name) - - } - - try { - Write-Verbose "Generating Manifest" - Write-Verbose ($newModuleManifest | Out-String) - $manifest = New-ModuleManifest @newModuleManifest - } - catch { - Write-Error "Error generating manifest: $_" - } - - $functionsToExport = $null - -} - -foreach ($manifest in $manifestsToTest) { - try { - Write-Verbose "Testing Manifest $manifest" - $null = Test-ModuleManifest -Path $manifest - Write-Verbose "Pass" - } - catch { - Write-Error "Fail" - } -} diff --git a/Checks/Extraction.ps1 b/Checks/Extraction.ps1 deleted file mode 100644 index 7d63590..0000000 --- a/Checks/Extraction.ps1 +++ /dev/null @@ -1,57 +0,0 @@ -param( - [parameter(Mandatory = $true)] - [string[]]$Source, - - [parameter(Mandatory = $true)] - [string]$ExtractPath -) - -BeforeDiscovery { - - $moduleFiles = @() - - $Source | ForEach-Object { - - $fileProperties = (Get-Item -Path $_) - - $moduleFiles += @{ - 'FullName' = $_ - 'Name' = $fileProperties.Name - 'Directory' = $fileProperties.Directory - - } - - } - - if ( Test-Path -Path $ExtractPath ) { - Get-ChildItem -Path $ExtractPath -Recurse -ErrorAction SilentlyContinue | Remove-Item -Force -Recurse - Remove-Item $ExtractPath -Force -ErrorAction SilentlyContinue - } - - New-Item -Path $ExtractPath -ItemType 'Directory' - -} - -Describe "Function Extraction" { - - Context "Script: <_.Name> at <_.Directory>" -ForEach $moduleFiles { - - BeforeEach { - - $moduleFile = $_.FullName - - } - - It "function extraction should complete" { - - { - - Export-FunctionsFromModule -Path $moduleFile -ExtractPath $ExtractPath - - } | Should -Not -Throw - - } - - } - -} diff --git a/Checks/HelpRules.psd1 b/Checks/HelpRules.psd1 deleted file mode 100644 index 40084cb..0000000 --- a/Checks/HelpRules.psd1 +++ /dev/null @@ -1,73 +0,0 @@ -@{ - # HashTable of the keys that you want in your help comments - # If the test finds an element that does not appear in this list then the test will fail - - # Possible key elements - # '.SYNOPSIS' - # '.DESCRIPTION' - # '.PARAMETER' - # '.EXAMPLE' - # '.INPUTS' - # '.OUTPUTS' - # '.NOTES' - # '.LINK' - # '.COMPONENT' - # '.ROLE' - # '.FUNCTIONALITY' - # '.FORWARDHELPTARGETNAME' - # '.FORWARDHELPCATEGORY' - # '.REMOTEHELPRUNSPACE' - # '.EXTERNALHELP' - - # If a key is required then it must exist, and have between MinOccurrences and MaxOccurrences count - # The keys will be matched in the numerical sequence below - '1' = @{ - Key = '.SYNOPSIS' - Required = $true - MinOccurrences = 1 - MaxOccurrences = 1 - } - '2' = @{ - Key = '.DESCRIPTION' - Required = $true - MinOccurrences = 1 - MaxOccurrences = 1 - } - '3' = @{ - Key = '.PARAMETER' - Required = $false - MinOccurrences = 0 - MaxOccurrences = 0 - } - '4' = @{ - Key = '.EXAMPLE' - Required = $true - MinOccurrences = 1 - MaxOccurrences = 100 - # MaxOccurrences = 1 - } - '5' = @{ - Key = '.INPUTS' - Required = $false - MinOccurrences = 0 - MaxOccurrences = 0 - } - '6' = @{ - Key = '.OUTPUTS' - Required = $false - MinOccurrences = 0 - MaxOccurrences = 0 - } - '7' = @{ - Key = '.NOTES' - Required = $false - MinOccurrences = 0 - MaxOccurrences = 0 - } - '8' = @{ - Key = '.LINK' - Required = $false - MinOccurrences = 0 - MaxOccurrences = 0 - } -} diff --git a/Checks/Module.Checks.ps1 b/Checks/Module.Checks.ps1 deleted file mode 100644 index 8b94fd3..0000000 --- a/Checks/Module.Checks.ps1 +++ /dev/null @@ -1,84 +0,0 @@ -param( - [parameter(Mandatory = $true)] - [string[]]$Source -) - -BeforeDiscovery { - - $moduleFiles = @() - - $Source | ForEach-Object { - - $fileProperties = (Get-Item -Path $_) - - $moduleFiles += @{ - 'FullName' = $_ - 'Name' = $fileProperties.Name - 'Directory' = $fileProperties.Directory - - } - - } - -} - -Describe "Module Tests" -Tag "Module" { - - Context "Script: <_.Name> at <_.Directory>" -Foreach $moduleFiles { - - BeforeEach { - - $moduleFile = $_.FullName - $manifestFile = [Io.Path]::ChangeExtension($_.FullName, 'psd1') - - ($ExportedCommandsCount, $CommandFoundInModuleCount, $CommandInModuleCount, $CommandFoundInManifestCount) = Get-FunctionCount -Module $moduleFile -Manifest $manifestFile - - } - - It "Module should exist" -Tag "ModuleShouldExist" { - - $moduleFile | Should -Exist - - } - - It "Manifest should exist" -Tag "ManifestShouldExist" { - - $manifestFile | Should -Exist - - } - - It "Manifest should be valid" -Tag "ValidManifest" { - - $manifest = Test-ModuleManifest -Path $manifestFile -ErrorAction SilentlyContinue - - $manifest | Should -BeOfType [System.Management.Automation.PSModuleInfo] - - } - - It "Manifest should export Functions" -Tag "ModuleShouldExportFunctions" { - - ($ExportedCommandsCount) | Should -BeGreaterOrEqual 1 - - } - - It "Module should have Functions" -Tag "ModuleShouldHaveFunctions" { - - ($CommandInModuleCount) | Should -BeGreaterOrEqual 1 - - } - - It "all exported Functions from Manifest should exist in the Module" -Tag "FunctionsFromManifestExistInModule" { - - ($ExportedCommandsCount -eq $CommandFoundInModuleCount -and $ExportedCommandsCount -ge 1) | Should -BeTrue - - } - - It "all Functions in the Module should exist in Manifest " -Tag "FunctionsFromModuleExistInManifest" { - - ($CommandInModuleCount -eq $CommandFoundInManifestCount -and $CommandFoundInManifestCount -ge 1 ) | Should -BeTrue - - } - - } - -} diff --git a/Checks/Project.Checks.ps1 b/Checks/Project.Checks.ps1 deleted file mode 100644 index 2df5150..0000000 --- a/Checks/Project.Checks.ps1 +++ /dev/null @@ -1,114 +0,0 @@ -param( - [parameter(Mandatory = $true)] - [string]$Path -) - -BeforeDiscovery { - - $sourcePath = Join-Path -Path $Path -ChildPath "Source" - $testPath = Join-Path -Path $Path -ChildPath "Tests" - $unitTestPath = Join-Path -Path $testPath -ChildPath "Unit" - - $moduleList = Get-ChildItem -Path $sourcePath -Directory | Select-Object -Property Name - - $moduleData = @() - - foreach ($module in $moduleList) { - - $moduleFolder = Join-Path -Path $sourcePath -ChildPath $module.Name - $privateFolder = Join-Path -Path $moduleFolder -ChildPath "Private" - $publicFolder = Join-Path -Path $moduleFolder -ChildPath "Public" - $unitTestFolder = Join-Path -Path $unitTestPath -ChildPath $module.Name - - $privateModules = Get-ChildItem -Path $privateFolder | Select-Object -Property Name, BaseName, FullName - $publicModules = Get-ChildItem -Path $publicFolder | Select-Object -Property Name, BaseName, FullName - - $moduleData += @{ - 'Name' = $module.Name - 'Path' = $moduleFolder - 'PublicFolder' = $publicFolder - 'PrivateFolder' = $privateFolder - 'UnitTestFolder' = $unitTestFolder - 'Public' = $publicModules - 'Private' = $privateModules - } - } - -} - -Describe "Project Test" -Tag "Project" { - - Context "Checking fixed folder structure" { - - It "should contain <_> folder" -Foreach @($sourcePath, $TestPath, $unitTestPath) { - - $_ | Should -Exist - - } - - } - - Context "checking module <_.Name>" -Foreach $moduleData { - - BeforeAll { - - $approvedVerbs = Get-Verb | Select-Object -Property Verb - - } - - It "Private folder exists" { - - $_.PrivateFolder | Should -Exist - - } - - It "Public folder exists" { - - $_.PublicFolder | Should -Exist - - } - - It "Unit Test folder exists" { - - $_.UnitTestFolder | Should -Exist - - } - - Context "Checking Public Script <_.Name>" -ForEach $_.Public { - - It "public script has a unit test" { - - $testFileName = "{0}{1}" -f $_.BaseName, ".Tests.ps1" - $TestScript = Join-Path -Path $unitTestFolder -ChildPath $testFileName - $TestScript | Should -Exist - - } - - It "public script has a valid verb-noun format" { - - ($verb, $noun) = $_.Name -Split "-" - - $verb | Should -Not -BeNullOrEmpty - $noun | Should -Not -BeNullOrEmpty - - $approvedVerbs.Verb -contains $verb | Should -BeTrue - - } - - } - - Context "Checking Private Script <_.Name>" -ForEach $_.Private { - - It "private script has a valid format" { - - $Script = $_.Name - - $Script | Should -Not -Match "-" - - } - - } - - } - -} diff --git a/Checks/Script.Checks.ps1 b/Checks/Script.Checks.ps1 deleted file mode 100644 index 5515f4c..0000000 --- a/Checks/Script.Checks.ps1 +++ /dev/null @@ -1,269 +0,0 @@ -param( - [parameter(Mandatory = $true)] - [string[]]$Source, - - [parameter(Mandatory = $false)] - [string[]]$ScriptAnalyzerRulesPath, - - [parameter(Mandatory = $false)] - [string]$HelpRulesPath - -) - -BeforeDiscovery { - - $scriptFiles = @() - - $Source | ForEach-Object { - - $fileProperties = (Get-Item -Path $_) - - $scriptFiles += @{ - 'FullName' = $_ - 'Name' = $fileProperties.Name - 'Directory' = $fileProperties.Directory - } - - } - - if ( -not ($ScriptAnalyzerRulesPath -is [Array])) { - $ScriptAnalyzerRulesPath = @($ScriptAnalyzerRulesPath) - } - - $rulesPath = @() - - $ScriptAnalyzerRulesPath | ForEach-Object { - - $rulesPath += @{ - 'Path' = $_ - } - - } - -} - -Describe "Script Tests" -Tag "Script" { - - Context "Script: at " -ForEach $scriptFiles { - - BeforeAll { - - $file = $_ - - } - - BeforeEach { - - $scriptFile = $file.FullName - $fileContent = Get-FileContent -Path $file.FullName - - if (-not([string]::IsNullOrEmpty($fileContent))) { - ($ParsedFile, $ErrorCount) = Get-ParsedContent -Content $fileContent - } - else { - Write-Warning "File is empty" - $ParsedFile = $null - $ErrorCount = 1 - } - - } - - It "check script has valid PowerShell syntax" -Tag "ValidSyntax" { - - $ErrorCount | Should -Be 0 - - } - - It "check help must contain required elements" -Tag "HelpMustContainRequiredElements" { - - { - - $helpComments = ($ParsedFile | Where-Object { $_.Type -eq "Comment" } | Select-Object -First 1) - if ([string]::IsNullOrEmpty($helpComments)) { - throw "No help block found" - } - $helpTokens = Convert-Help -Help $helpComments.Content - Test-RequiredToken -HelpTokens $helpTokens -HelpRulesPath $HelpRulesPath - - } | - Should -Not -Throw - - } - - It "check help must not contain unspecified elements" -Tag "HelpMustContainUnspecifiedElements" { - - { - - $helpComments = ($ParsedFile | Where-Object { $_.Type -eq "Comment" } | Select-Object -First 1) - if ([string]::IsNullOrEmpty($helpComments)) { - throw "No help block found" - } - $helpTokens = Convert-Help -Help $helpComments.Content - Test-UnspecifiedToken -HelpTokens $helpTokens -HelpRulesPath $HelpRulesPath - - } | - Should -Not -Throw - - } - - It "check help elements text is not empty" -Tag "HelpElementsNotEmpty" { - - { - - $helpComments = ($ParsedFile | Where-Object { $_.Type -eq "Comment" } | Select-Object -First 1) - if ([string]::IsNullOrEmpty($helpComments)) { - throw "No help block found" - } - $helpTokens = Convert-Help -Help $helpComments.Content - Test-HelpTokensTextIsValid -HelpTokens $helpTokens - - } | Should -Not -Throw - - } - - It "check help elements Min/Max counts are valid" -Tag "HelpElementsMinMaxCount" { - - { - - $helpComments = ($ParsedFile | Where-Object { $_.Type -eq "Comment" } | Select-Object -First 1) - if ([string]::IsNullOrEmpty($helpComments)) { - throw "No help block found" - } - $helpTokens = Convert-Help -Help $helpComments.Content - Test-HelpTokensCountIsValid -HelpTokens $helpTokens -HelpRulesPath $HelpRulesPath - - } | Should -Not -Throw - - } - - It "check script contains [CmdletBinding] attribute" -Tag "ContainsCmdletBinding" { - - $cmdletBindingCount = (@(Get-TokenMarker -ParsedContent $ParsedFile -Type "Attribute" -Content "CmdletBinding")).Count - - $cmdletBindingCount | Should -Be 1 - - } - - It "check script contains [OutputType] attribute" -Tag "ContainsOutputType" { - - $outputTypeCount = (@(Get-TokenMarker -ParsedContent $ParsedFile -Type "Attribute" -Content "OutputType")).Count - - $outputTypeCount | Should -Be 1 - - } - - It "check script [OutputType] attribute is not empty" -Tag "OutputTypeNotEmpty" { - - $outputTypeToken = (Get-Token -ParsedContent $ParsedFile -Type "Attribute" -Content "OutputType") - - $outputTypeValue = @($outputTypeToken | Where-Object { $_.Type -eq "Type" }) - - $outputTypeValue | Should -Not -BeNullOrEmpty - - } - - # Note: Disabled because I'm questioning the validity of the rule. So many function haven't got a need for params - # It "check script contains param attribute" -Tag "ContainsParam" { - - # $paramCount = (@(Get-TokenMarker -ParsedContent $ParsedFile -Type "Keyword" -Content "param")).Count - - # $paramCount | Should -Be 1 - - # } - - It "check script param block variables have type" -Tag "ParamVariablesHaveType" { - - $parameterVariables = Get-ScriptParameter -Content $fileContent - - if ($parameterVariables.Count -eq 0) { - - Set-ItResult -Inconclusive -Because "No parameters found" - - } - - { - - Test-ParameterVariablesHaveType -ParameterVariables $parameterVariables - - } | Should -Not -Throw - - } - - It "check .PARAMETER help matches variables in param block" -Tag "HelpMatchesParamVariables" { - - { - - $helpComments = ($ParsedFile | Where-Object { $_.Type -eq "Comment" } | Select-Object -First 1) - if ([string]::IsNullOrEmpty($helpComments)) { - throw "No help block found" - } - $parameterVariables = Get-ScriptParameter -Content $fileContent - $helpTokens = Convert-Help -Help $helpComments.Content - - Test-HelpTokensParamsMatch -HelpTokens $helpTokens -ParameterVariables $parameterVariables - - } | Should -Not -Throw - - } - - It "check script contains no PSScriptAnalyzer suppressions" -Tag "NoScriptAnalyzerSuppressions" { - - $suppressCount = (@(Get-TokenMarker -ParsedContent $ParsedFile -Type "Attribute" -Content "Diagnostics.CodeAnalysis.SuppressMessageAttribute")).Count - $suppressCount | Should -Be 0 - - $suppressCount = (@(Get-TokenMarker -ParsedContent $ParsedFile -Type "Attribute" -Content "Diagnostics.CodeAnalysis.SuppressMessage")).Count - $suppressCount | Should -Be 0 - - } - - It "check script contains no PSScriptAnalyzer failures" -Tag "NoScriptAnalyzerFailures" { - - $AnalyserFailures = @(Invoke-ScriptAnalyzer -Path $scriptFile) - - ($AnalyserFailures | ForEach-Object { $_.Message }) | Should -BeNullOrEmpty - - } - - It "check script contains no PSScriptAnalyser rule failures '<_.Path>" -Tag "NoScriptAnalyzerExtraRulesFailures" -TestCases $rulesPath { - - param($Path) - - if ( [string]::IsNullOrEmpty($Path)) { - - Set-ItResult -Inconclusive -Because "Empty ScriptAnalyzerRulesPath '$Path'" - - } - - if ( -not (Test-Path -Path $Path -ErrorAction SilentlyContinue)) { - - Set-ItResult -Inconclusive -Because "ScriptAnalyzerRulesPath path '$Path' not found" - - } - - $AnalyserFailures = @(Invoke-ScriptAnalyzer -Path $scriptFile -CustomRulePath $Path) - - $AnalyserFailures | ForEach-Object { $_.Message } | Should -BeNullOrEmpty - - } - - It "check Import-Module statements have valid format" -Tag "ValidImportModuleStatements" { - - $importModuleTokens = @($ParsedFile | Where-Object { $_.Type -eq "Command" -and $_.Content -eq "Import-Module" }) - - if ($importModuleTokens.Count -eq 0) { - - Set-ItResult -Inconclusive -Because "No Import-Module statements found" - - } - - { - - Test-ImportModuleIsValid -ParsedContent $ParsedFile -ImportModuleTokens $importModuleTokens - - } | Should -Not -Throw - - } - - } - -} diff --git a/Source/PSQualityCheck.Functions/Public/Convert-Help.ps1 b/Source/PSQualityCheck.Functions/Public/Convert-Help.ps1 deleted file mode 100644 index af52b76..0000000 --- a/Source/PSQualityCheck.Functions/Public/Convert-Help.ps1 +++ /dev/null @@ -1,145 +0,0 @@ -function Convert-Help { - <# - .SYNOPSIS - Convert the help comment into an object - - .DESCRIPTION - Convert the help comment into an object containing all the elements from the help comment - - .PARAMETER Help - A string containing the Help Comment - - .EXAMPLE - $helpObject = Convert-Help -Help $Help - #> - [CmdletBinding()] - [OutputType([HashTable], [System.Exception])] - param ( - [parameter(Mandatory = $true)] - [string]$Help - ) - - # These are the possible Help Comment elements that the script will look for - # .SYNOPSIS - # .DESCRIPTION - # .PARAMETER - # .EXAMPLE - # .INPUTS - # .OUTPUTS - # .NOTES - # .LINK - # .COMPONENT - # .ROLE - # .FUNCTIONALITY - # .FORWARDHELPTARGETNAME - # .FORWARDHELPCATEGORY - # .REMOTEHELPRUNSPACE - # .EXTERNALHELP - - # This function will go through the help and work out which elements are where and what text they contain - - try { - - if (-not( - $Help.StartsWith("<#") -and - $Help.EndsWith("#>") - )) { - throw "Help does not appear to be a comment block" - } - - $helpElementsToFind = - '.SYNOPSIS', - '.DESCRIPTION', - '.PARAMETER', - '.EXAMPLE', - '.INPUTS', - '.OUTPUTS', - '.NOTES', - '.LINK', - '.COMPONENT', - '.ROLE', - '.FUNCTIONALITY', - '.FORWARDHELPTARGETNAME', - '.FORWARDHELPCATEGORY', - '.REMOTEHELPRUNSPACE', - '.EXTERNALHELP' - - $commentArray = ($Help -split '\n').Trim() - - $foundElements = @{} - $numFound = 0 - $lastHelpElement = $null - - for ($line = 0; $line -lt $commentArray.Count; $line++) { - - # get the first 'word' of the help comment. This is required so that we can - # match '.PARAMETER' since it has a parameter name after it - $helpElementName = ($commentArray[$line] -split " ")[0] - - if ($helpElementsToFind -contains $helpElementName) { - - $numFound++ - - if ($numFound -ge 2) { - - # if it's the second element then we must set the help comment text of the - # previous element to the found text so far, then reset it - - $lastElement = @($foundElements[$lastHelpElement]) - $lastElement[$lastElement.Count - 1].Text = $helpData - $foundElements[$lastHelpElement] = $lastElement - - $helpData = $null - } - - # this should be an array of HashTables - # each hash table will contain the properties LineNumber, Name & Text - $currentElement = @($foundElements[$helpElementName]) - - $newElement = @{} - $newElement.LineNumber = $line - $newElement.Name = ($commentArray[$line] -split " ")[1] - $newElement.Text = "" - - if ($null -eq $currentElement[0]) { - - $currentElement = $newElement - - } - else { - $currentElement += $newElement - } - - $foundElements[$helpElementName] = $currentElement - - $lastHelpElement = $helpElementName - - } - else { - - if ($numFound -ge 1 -and $line -lt ($commentArray.Count - 1)) { - - $helpData += $commentArray[$line] - - } - - } - - } - - if ( -not ([string]::IsNullOrEmpty($lastHelpElement))) { - $currentElement = @($foundElements[$lastHelpElement]) - $currentElement[$currentElement.Count - 1].Text = $helpData - $foundElements[$lastHelpElement] = $currentElement - } - - return $foundElements - - } - catch { - - throw $_.Exception.Message - - } - -} diff --git a/Source/PSQualityCheck.Functions/Public/Export-FunctionsFromModule.ps1 b/Source/PSQualityCheck.Functions/Public/Export-FunctionsFromModule.ps1 deleted file mode 100644 index fd5393b..0000000 --- a/Source/PSQualityCheck.Functions/Public/Export-FunctionsFromModule.ps1 +++ /dev/null @@ -1,104 +0,0 @@ -function Export-FunctionsFromModule { - <# - .SYNOPSIS - Export functions from a PowerShell module (.psm1) - - .DESCRIPTION - Takes a PowerShell module and outputs a single file for each function containing the code for that function - - .PARAMETER Path - A string Path containing the full file name and path to the module - - .PARAMETER ExtractPath - A string Path containing the full path to the extraction folder - - .EXAMPLE - Export-FunctionsFromModule -Path 'c:\path.to\module.psm1' -ExtractPath 'c:\extract' - #> - [CmdletBinding()] - [OutputType([System.Void])] - param ( - [parameter(Mandatory = $true)] - [string]$Path, - [parameter(Mandatory = $true)] - [string]$ExtractPath - ) - - try { - - $fileProperties = (Get-Item -LiteralPath $Path) - - if ($fileProperties.Extension -ne ".psm1") { - throw "Passed file does not appear to be a PowerShell module" - } - - $moduleName = $fileProperties.BaseName - - $ModuleFileContent = Get-Content -Path $Path -ErrorAction Stop - - $ParserErrors = $null - $ParsedFileFunctions = [System.Management.Automation.PSParser]::Tokenize($ModuleFileContent, [ref]$ParserErrors) - - $ParsedFunctions = ($ParsedFileFunctions | Where-Object { $_.Type -eq "Keyword" -and $_.Content -like 'function' }) - - $parsedFunction = 0 - - if ($ParsedFunctions.Count -ge 1) { - - $FunctionOutputPath = Join-Path -Path $ExtractPath -ChildPath $moduleName - - if (-not (Test-Path -Path $FunctionOutputPath)) { - New-Item $FunctionOutputPath -ItemType 'Directory' - } - - foreach ($Function in $ParsedFunctions) { - - $parsedFunction++ - - $FunctionProperties = $ParsedFileFunctions | Where-Object { $_.StartLine -eq $Function.StartLine } - $FunctionName = ($FunctionProperties | Where-Object { $_.Type -eq "CommandArgument" }).Content - - if ($parsedFunction -eq $ParsedFunctions.Count) { - - $StartLine = ($Function.StartLine) - for ($line = $ModuleFileContent.Count; $line -gt $Function.StartLine; $line--) { - if ($ModuleFileContent[$line] -like "}") { - $EndLine = $line - break - } - } - - } - else { - - $StartLine = ($Function.StartLine) - - for ($line = $ParsedFunctions[$parsedFunction].StartLine; $line -gt $Function.StartLine; $line--) { - if ($ModuleFileContent[$line] -like "}") { - $EndLine = $line - break - } - } - - } - - $FunctionOutputFileName = "{0}\{1}{2}" -f $FunctionOutputPath, $FunctionName, ".ps1" - - if (-not (Test-Path -Path $FunctionOutputFileName)) { - Out-File -FilePath $FunctionOutputFileName - } - - for ($line = $StartLine; $line -lt $EndLine; $line++) { - Add-Content -Path $FunctionOutputFileName -Value $ModuleFileContent[$line] - } - - } - } - else { - throw "File contains no functions" - } - } - catch { - throw - } -} diff --git a/Source/PSQualityCheck.Functions/Public/Get-FileContent.ps1 b/Source/PSQualityCheck.Functions/Public/Get-FileContent.ps1 deleted file mode 100644 index b0e7b02..0000000 --- a/Source/PSQualityCheck.Functions/Public/Get-FileContent.ps1 +++ /dev/null @@ -1,112 +0,0 @@ -function Get-FileContent { - <# - .SYNOPSIS - Gets the content of a script file - - .DESCRIPTION - Gets the content of the file or the content of the function inside the file - - .PARAMETER Path - A file name to parse - - .EXAMPLE - $fileContent = Get-FileContent -Path 'c:\file.txt' - #> - [CmdletBinding()] - [OutputType([System.String[]])] - param ( - [parameter(Mandatory = $true)] - [string]$Path - ) - - try { - - $fileContent = Get-Content -Path $Path - - $parserErrors = $null - - if ([string]::IsNullOrEmpty($fileContent)) { - $parsedFileFunctions = @() - } - else { - $parsedFileFunctions = [System.Management.Automation.PSParser]::Tokenize($fileContent, [ref]$parserErrors) - } - - $parsedFunctions = ($parsedFileFunctions | Where-Object { $_.Type -eq "Keyword" -and $_.Content -like 'function' }) - - if ($parsedFunctions.Count -gt 1) { - throw "Too many functions in file, file is invalid" - } - - if ($parsedFunctions.Count -eq 1) { - - if ($fileContent.Count -gt 1) { - - foreach ($function in $parsedFunctions) { - - $startLine = ($function.StartLine) - - for ($line = $fileContent.Count; $line -gt $function.StartLine; $line--) { - - if ($fileContent[$line] -like "*}*") { - - $endLine = $line - break - - } - - } - - for ($line = $startLine; $line -lt $endLine; $line++) { - - $parsedFileContent += $fileContent[$line] - - if ($line -ne ($fileContent.Count - 1)) { - $parsedFileContent += "`r`n" - } - - } - - } - - } - else { - - [int]$startBracket = $fileContent.IndexOf('{') - [int]$endBracket = $fileContent.LastIndexOf('}') - - $parsedFileContent = $fileContent.substring($startBracket + 1, $endBracket - 1 - $startBracket) - - } - } - else { - - if ($fileContent.Count -gt 1) { - - for ($line = 0; $line -lt $fileContent.Count; $line++) { - - $parsedFileContent += $fileContent[$line] - - if ($line -ne ($fileContent.Count - 1)) { - $parsedFileContent += "`r`n" - } - - } - - } - else { - - $parsedFileContent = $fileContent - - } - - } - - } - catch { - throw - } - - return $parsedFileContent - -} diff --git a/Source/PSQualityCheck.Functions/Public/Get-FileList.ps1 b/Source/PSQualityCheck.Functions/Public/Get-FileList.ps1 deleted file mode 100644 index 692c7f8..0000000 --- a/Source/PSQualityCheck.Functions/Public/Get-FileList.ps1 +++ /dev/null @@ -1,56 +0,0 @@ -function Get-FileList { - <# - .SYNOPSIS - Return a list of files - - .DESCRIPTION - Return a list of files from the specified path matching the passed extension - - .PARAMETER Path - A string containing the path - - .PARAMETER Extension - A string containing the extension - - .PARAMETER Recurse - A switch specifying whether or not to recursively search the path specified - - .EXAMPLE - $files = Get-FileList -Path 'c:\folder' -Extension ".ps1" - - .EXAMPLE - $files = Get-FileList -Path 'c:\folder' -Extension ".ps1" -Recurse - #> - [CmdletBinding()] - [OutputType([System.Object[]])] - param ( - [parameter(Mandatory = $true)] - [string]$Path, - [parameter(Mandatory = $true)] - [string]$Extension, - [parameter(Mandatory = $false)] - [switch]$Recurse - ) - - $Extension = $Extension - - $FileNameArray = @() - - if (Test-Path -Path $Path) { - - $gciSplat = @{ - 'Path' = $Path - 'Exclude' = "*.Tests.*" - } - if ($PSBoundParameters.ContainsKey('Recurse')) { - $gciSplat.Add('Recurse', $true) - } - - $SelectedFilesArray = Get-ChildItem @gciSplat | Where-Object { $_.Extension -eq $Extension } | Select-Object -Property FullName - $SelectedFilesArray | ForEach-Object { $FileNameArray += [string]$_.FullName } - - } - - return $FileNameArray - -} diff --git a/Source/PSQualityCheck.Functions/Public/Get-FunctionCount.ps1 b/Source/PSQualityCheck.Functions/Public/Get-FunctionCount.ps1 deleted file mode 100644 index 921a0df..0000000 --- a/Source/PSQualityCheck.Functions/Public/Get-FunctionCount.ps1 +++ /dev/null @@ -1,100 +0,0 @@ -function Get-FunctionCount { - <# - .SYNOPSIS - Return the count of functions within Module and its Manifest - - .DESCRIPTION - Return the count of functions in the Module and Manifest and whether they appear in their counterpart. - e.g. Whether the functions in the manifest appear in the module and vice versa - - .PARAMETER ModulePath - A string containing the Module filename - - .PARAMETER ManifestPath - A string containing the Manifest filename - - .EXAMPLE - ($ExportedCommandsCount, $CommandFoundInModuleCount, $CommandInModuleCount, $CommandFoundInManifestCount) = Get-FunctionCount -ModulePath $ModulePath -ManifestPath $ManifestPath - - #> - [CmdletBinding()] - [OutputType([Int[]])] - param ( - [parameter(Mandatory = $true)] - [string]$ModulePath, - [parameter(Mandatory = $true)] - [string]$ManifestPath - ) - - try { - if (Test-Path -Path $ManifestPath) { - $ExportedCommands = (Test-ModuleManifest -Path $ManifestPath -ErrorAction Stop).ExportedCommands - $ExportedCommandsCount = $ExportedCommands.Count - } - else { - throw "Manifest file doesn't exist" - } - } - catch { - $ExportedCommands = @() - $ExportedCommandsCount = 0 - } - - try { - if (Test-Path -Path $ModulePath) { - ($ParsedModule, $ParserErrors) = Get-ParsedFile -Path $ModulePath - } - else { - throw "Module file doesn't exist" - } - } - catch { - $ParsedModule = @() - $ParserErrors = 1 - } - - $CommandFoundInModuleCount = 0 - $CommandFoundInManifestCount = 0 - $CommandInModuleCount = 0 - - if ( -not ([string]::IsNullOrEmpty($ParsedModule))) { - - foreach ($ExportedCommand in $ExportedCommands.Keys) { - - if ( ($ParsedModule | Where-Object { $_.Type -eq "CommandArgument" -and $_.Content -eq $ExportedCommand })) { - - $CommandFoundInModuleCount++ - - } - - } - - $functionNames = @() - - $functionKeywords = ($ParsedModule | Where-Object { $_.Type -eq "Keyword" -and $_.Content -eq "function" }) - $functionKeywords | ForEach-Object { - - $functionLineNo = $_.StartLine - $functionNames += ($ParsedModule | Where-Object { $_.Type -eq "CommandArgument" -and $_.StartLine -eq $functionLineNo }) - - } - } - - if ($ExportedCommandsCount -ge 1) { - - foreach ($function in $functionNames) { - - $CommandInModuleCount++ - if ($ExportedCommands.ContainsKey($function.Content)) { - - $CommandFoundInManifestCount++ - - } - - } - - } - - return ($ExportedCommandsCount, $CommandFoundInModuleCount, $CommandInModuleCount, $CommandFoundInManifestCount) - -} diff --git a/Source/PSQualityCheck.Functions/Public/Get-ParsedContent.ps1 b/Source/PSQualityCheck.Functions/Public/Get-ParsedContent.ps1 deleted file mode 100644 index 1751820..0000000 --- a/Source/PSQualityCheck.Functions/Public/Get-ParsedContent.ps1 +++ /dev/null @@ -1,29 +0,0 @@ -function Get-ParsedContent { - <# - .SYNOPSIS - Get the tokenized content of the passed data - - .DESCRIPTION - Get and return the tokenized content of the passed PowerShell script content - - .PARAMETER Content - A string containing PowerShell script content - - .EXAMPLE - ($ParsedModule, $ParserErrorCount) = Get-ParsedContent -Content $fileContent - #> - [CmdletBinding()] - [OutputType([System.Object[]], [System.Void])] - param ( - [parameter(Mandatory = $true)] - [string]$Content - ) - - if (-not ([string]::IsNullOrEmpty($Content))) { - $ParserErrors = $null - $ParsedModule = [System.Management.Automation.PSParser]::Tokenize($Content, [ref]$ParserErrors) - - return $ParsedModule, ($ParserErrors.Count) - } - -} diff --git a/Source/PSQualityCheck.Functions/Public/Get-ParsedFile.ps1 b/Source/PSQualityCheck.Functions/Public/Get-ParsedFile.ps1 deleted file mode 100644 index 3e53144..0000000 --- a/Source/PSQualityCheck.Functions/Public/Get-ParsedFile.ps1 +++ /dev/null @@ -1,38 +0,0 @@ -function Get-ParsedFile { - <# - .SYNOPSIS - Get the tokenized content of the passed file - - .DESCRIPTION - Get and return the tokenized content of the passed PowerShell file - - .PARAMETER Path - A string containing PowerShell filename - - .EXAMPLE - ($ParsedModule, $ParserErrors) = Get-ParsedFile -Path $ModuleFile - - #> - [CmdletBinding()] - [OutputType([System.Object[]])] - param ( - [parameter(Mandatory = $true)] - [string]$Path - ) - - try { - if (-not(Test-Path -Path $Path)) { - throw "$Path doesn't exist" - } - } - catch { - throw $_ - } - - $fileContent = Get-Content -Path $Path -Raw - - ($ParsedModule, $ParserErrorCount) = Get-ParsedContent -Content $fileContent - - return $ParsedModule, $ParserErrorCount - -} diff --git a/Source/PSQualityCheck.Functions/Public/Get-ScriptParameter.ps1 b/Source/PSQualityCheck.Functions/Public/Get-ScriptParameter.ps1 deleted file mode 100644 index 357c3fb..0000000 --- a/Source/PSQualityCheck.Functions/Public/Get-ScriptParameter.ps1 +++ /dev/null @@ -1,76 +0,0 @@ -function Get-ScriptParameter { - <# - .SYNOPSIS - Get a list of the parameters in the param block - - .DESCRIPTION - Create a list of the parameters, and their type (if available) from the param block - - .PARAMETER Content - A string containing the text of the script - - .EXAMPLE - $parameterVariables = Get-ScriptParameter -Content $Content - #> - [CmdletBinding()] - [OutputType([System.Exception], [HashTable])] - param ( - [parameter(Mandatory = $true)] - [String]$Content - ) - - try { - - $parsedScript = [System.Management.Automation.Language.Parser]::ParseInput($Content, [ref]$null, [ref]$null) - - if ([string]::IsNullOrEmpty($parsedScript.ParamBlock)) { - throw "No parameters found" - } - - [string]$paramBlock = $parsedScript.ParamBlock - - ($ParsedContent, $ParserErrorCount) = Get-ParsedContent -Content $paramBlock - - $paramBlockArray = ($paramBlock -split '\n').Trim() - - $parametersFound = @{} - - for ($line = 0; $line -le $paramBlockArray.Count; $line++) { - - $paramToken = @($ParsedContent | Where-Object { $_.StartLine -eq $line }) - - foreach ($token in $paramToken) { - - if ($token.Type -eq 'Attribute' -and $token.Content -eq "Parameter") { - - break - } - - if ($token.Type -eq 'Type') { - - $foundType = $token.Content - - } - - if ($token.Type -eq 'Variable') { - - $parametersFound[$token.Content] = $foundType - $foundType = $null - break - - } - - } - - } - - return $parametersFound - - } - catch { - - throw $_.Exception.Message - - } - -} diff --git a/Source/PSQualityCheck.Functions/Public/Get-TagList.ps1 b/Source/PSQualityCheck.Functions/Public/Get-TagList.ps1 deleted file mode 100644 index 76db235..0000000 --- a/Source/PSQualityCheck.Functions/Public/Get-TagList.ps1 +++ /dev/null @@ -1,71 +0,0 @@ -function Get-TagList { - <# - .SYNOPSIS - Return a list of test tags - - .DESCRIPTION - Return a list of test tags from the module and script checks file - - .EXAMPLE - ($moduleTags, $scriptTags) = Get-TagList - - #> - [CmdletBinding()] - [OutputType([System.Object[]])] - param ( - ) - - $moduleTags = @() - $scriptTags = @() - - $modulePath = (Get-Module -Name 'PSQualityCheck').ModuleBase - - $checksPath = (Join-Path -Path $modulePath -ChildPath "Checks") - - Get-Content -Path (Join-Path -Path $checksPath -ChildPath "Module.Tests.ps1") -Raw | ForEach-Object { - $ast = [Management.Automation.Language.Parser]::ParseInput($_, [ref]$null, [ref]$null) - $ast.FindAll( { - param($node) - $node -is [System.Management.Automation.Language.CommandAst] -and - $node.CommandElements[0].Value -eq "Describe" -and - $node.CommandElements[2] -is [System.Management.Automation.Language.CommandParameterAst] -and - $node.CommandElements[2].ParameterName -eq "Tag" - }, $true) | ForEach-Object { - $moduleTags += $_.CommandElements[3].Value - } - $ast.FindAll( { - param($node) - $node -is [System.Management.Automation.Language.CommandAst] -and - $node.CommandElements[0].Value -eq "It" -and - $node.CommandElements[2] -is [System.Management.Automation.Language.CommandParameterAst] -and - $node.CommandElements[2].ParameterName -eq "Tag" - }, $true) | ForEach-Object { - $moduleTags += $_.CommandElements[3].Value - } - } - - Get-Content -Path (Join-Path -Path $checksPath -ChildPath "Script.Tests.ps1") -Raw | ForEach-Object { - $ast = [Management.Automation.Language.Parser]::ParseInput($_, [ref]$null, [ref]$null) - $ast.FindAll( { - param($node) - $node -is [System.Management.Automation.Language.CommandAst] -and - $node.CommandElements[0].Value -eq "Describe" -and - $node.CommandElements[2] -is [System.Management.Automation.Language.CommandParameterAst] -and - $node.CommandElements[2].ParameterName -eq "Tag" - }, $true) | ForEach-Object { - $scriptTags += $_.CommandElements[3].Value - } - $ast.FindAll( { - param($node) - $node -is [System.Management.Automation.Language.CommandAst] -and - $node.CommandElements[0].Value -eq "It" -and - $node.CommandElements[2] -is [System.Management.Automation.Language.CommandParameterAst] -and - $node.CommandElements[2].ParameterName -eq "Tag" - }, $true) | ForEach-Object { - $scriptTags += $_.CommandElements[3].Value - } - } - - return $moduleTags, $scriptTags - -} diff --git a/Source/PSQualityCheck.Functions/Public/Get-Token.ps1 b/Source/PSQualityCheck.Functions/Public/Get-Token.ps1 deleted file mode 100644 index 4182e47..0000000 --- a/Source/PSQualityCheck.Functions/Public/Get-Token.ps1 +++ /dev/null @@ -1,38 +0,0 @@ -function Get-Token { - <# - .SYNOPSIS - Get token(s) from the tokenized output - - .DESCRIPTION - Get token(s) from the tokenized output matching the passed Type and Content - - .PARAMETER ParsedContent - A string array containing the Tokenized data - - .PARAMETER Type - The token type to be found - - .PARAMETER Content - The token content (or value) to be found - - .EXAMPLE - $outputTypeToken = (Get-Token -ParsedContent $ParsedFile -Type "Attribute" -Content "OutputType") - #> - [CmdletBinding()] - [OutputType([System.Object[]])] - param ( - [parameter(Mandatory = $true)] - [System.Object[]]$ParsedContent, - [parameter(Mandatory = $true)] - [string]$Type, - [parameter(Mandatory = $true)] - [string]$Content - ) - - $token = Get-TokenMarker -ParsedContent $ParsedContent -Type $Type -Content $Content - - $tokens = Get-TokenComponent -ParsedContent $ParsedContent -StartLine $token.StartLine - - return $tokens - -} diff --git a/Source/PSQualityCheck.Functions/Public/Get-TokenComponent.ps1 b/Source/PSQualityCheck.Functions/Public/Get-TokenComponent.ps1 deleted file mode 100644 index 5e60985..0000000 --- a/Source/PSQualityCheck.Functions/Public/Get-TokenComponent.ps1 +++ /dev/null @@ -1,35 +0,0 @@ -function Get-TokenComponent { - <# - .SYNOPSIS - Get all the tokens components from a single line - - .DESCRIPTION - Get all the tokens components from a single line in the tokenized content - - .PARAMETER ParsedContent - A string array containing the tokenized content - - .PARAMETER StartLine - A integer of the starting line to parse - - .EXAMPLE - $tokens = Get-TokenComponent -ParsedContent $ParsedContent -StartLine 10 - #> - [CmdletBinding()] - [OutputType([System.Object[]])] - param ( - [parameter(Mandatory = $true)] - [System.Object[]]$ParsedContent, - [parameter(Mandatory = $true)] - [int]$StartLine - ) - - #* This is just to satisfy the PSScriptAnalyzer - #* which can't find the variables in the 'Where-Object' clause (even though it's valid) - $StartLine = $StartLine - - $tokenComponents = @($ParsedContent | Where-Object { $_.StartLine -eq $StartLine }) - - return $tokenComponents - -} diff --git a/Source/PSQualityCheck.Functions/Public/Get-TokenMarker.ps1 b/Source/PSQualityCheck.Functions/Public/Get-TokenMarker.ps1 deleted file mode 100644 index 58a5814..0000000 --- a/Source/PSQualityCheck.Functions/Public/Get-TokenMarker.ps1 +++ /dev/null @@ -1,41 +0,0 @@ -function Get-TokenMarker { - <# - .SYNOPSIS - Gets token from the tokenized output - - .DESCRIPTION - Gets single token from the tokenized output matching the passed Type and Content - - .PARAMETER ParsedContent - A string array containing the Tokenized data - - .PARAMETER Type - The token type to be found - - .PARAMETER Content - The token content (or value) to be found - - .EXAMPLE - $token = Get-TokenMarker -ParsedContent $ParsedContent -Type $Type -Content $Content - #> - [CmdletBinding()] - [OutputType([System.Object[]])] - param ( - [parameter(Mandatory = $true)] - [System.Object[]]$ParsedContent, - [parameter(Mandatory = $true)] - [string]$Type, - [parameter(Mandatory = $true)] - [string]$Content - ) - - #* This is just to satisfy the PSScriptAnalyzer - #* which can't find the variables in the 'Where-Object' clause (even though it's valid) - $Type = $Type - $Content = $Content - - $token = @($ParsedContent | Where-Object { $_.Type -eq $Type -and $_.Content -eq $Content }) - - return $token - -} diff --git a/Source/PSQualityCheck.Functions/Public/Test-HelpTokensCountIsValid.ps1 b/Source/PSQualityCheck.Functions/Public/Test-HelpTokensCountIsValid.ps1 deleted file mode 100644 index a9bdab7..0000000 --- a/Source/PSQualityCheck.Functions/Public/Test-HelpTokensCountIsValid.ps1 +++ /dev/null @@ -1,82 +0,0 @@ -function Test-HelpTokensCountIsValid { - <# - .SYNOPSIS - Check that help tokens count is valid - - .DESCRIPTION - Check that the help tokens count is valid by making sure that they appear between Min and Max times - - .PARAMETER HelpTokens - A array of tokens containing the tokens of the Help Comment - - .PARAMETER HelpRulesPath - Path to the HelpRules file - - .EXAMPLE - Test-HelpTokensCountIsValid -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" - - .NOTES - This function will only check the Min/Max counts of required help tokens - #> - [CmdletBinding()] - [OutputType([System.Exception], [System.Void])] - param ( - [parameter(Mandatory = $true)] - [HashTable]$HelpTokens, - - [parameter(Mandatory = $true)] - [string]$HelpRulesPath - ) - - try { - - $helpRules = Import-PowerShellDataFile -Path $HelpRulesPath - - $tokenFound = @{} - for ($order = 1; $order -le $HelpRules.Count; $order++) { - $helpRuleIndex = [string]$order - $token = $HelpRules.$helpRuleIndex.Key - $tokenFound[$token] = $false - } - - $tokenErrors = @() - - foreach ($key in $HelpTokens.Keys) { - - for ($order = 1; $order -le $HelpRules.Count; $order++) { - - $helpRuleIndex = [string]$order - $token = $HelpRules.$helpRuleIndex - - if ( $token.Key -eq $key ) { - - $tokenFound[$key] = $true - - if ($HelpTokens.$key.Count -lt $token.MinOccurrences -or - $HelpTokens.$key.Count -gt $token.MaxOccurrences -and - $token.Required -eq $true) { - - $tokenErrors += "Found $(($HelpTokens.$key).Count) occurrences of '$key' which is not between $($token.MinOccurrences) and $($token.MaxOccurrences). " - - } - - } - - } - - } - - if ($tokenErrors.Count -ge 1) { - - throw $tokenErrors - - } - - } - catch { - - throw $_.Exception.Message - - } - -} diff --git a/Source/PSQualityCheck.Functions/Public/Test-HelpTokensParamsMatch.ps1 b/Source/PSQualityCheck.Functions/Public/Test-HelpTokensParamsMatch.ps1 deleted file mode 100644 index 892784f..0000000 --- a/Source/PSQualityCheck.Functions/Public/Test-HelpTokensParamsMatch.ps1 +++ /dev/null @@ -1,92 +0,0 @@ -function Test-HelpTokensParamsMatch { - <# - .SYNOPSIS - Checks to see whether the parameters and help PARAMETER statements match - - .DESCRIPTION - Checks to see whether the parameters in the param block and in the help PARAMETER statements exist in both locations - - .PARAMETER HelpTokens - A array of tokens containing the tokens of the Help Comment - - .PARAMETER ParameterVariables - A object containing the parameters from the param block - - .EXAMPLE - Test-HelpTokensParamsMatch -HelpTokens $HelpTokens -ParameterVariables $ParameterVariables - #> - [CmdletBinding()] - [OutputType([System.Exception], [System.String[]])] - param ( - [parameter(Mandatory = $true)] - [HashTable]$HelpTokens, - [parameter(Mandatory = $true)] - [PSCustomObject]$ParameterVariables - ) - - try { - - $foundInHelpErrors = @() - $foundInParamErrors = @() - - foreach ($key in $ParameterVariables.Keys) { - - $foundInHelp = $false - - foreach ($token in $HelpTokens.".PARAMETER") { - - if ($key -eq $token.Name) { - - $foundInHelp = $true - break - - } - - } - - if ($foundInHelp -eq $false) { - - $foundInHelpErrors += "Parameter block variable '$key' was not found in help. " - - } - - } - - foreach ($token in $HelpTokens.".PARAMETER") { - - $foundInParams = $false - - foreach ($key in $ParameterVariables.Keys) { - - if ($key -eq $token.Name) { - - $foundInParams = $true - break - - } - - } - - if ($foundInParams -eq $false) { - - $foundInParamErrors += "Help defined variable '$($token.Name)' was not found in parameter block definition. " - - } - - } - - if ($foundInHelpErrors.Count -ge 1 -or $foundInParamErrors.Count -ge 1) { - - $allErrors = $foundInHelpErrors + $foundInParamErrors - throw $allErrors - - } - - } - catch { - - throw $_.Exception.Message - - } - -} diff --git a/Source/PSQualityCheck.Functions/Public/Test-HelpTokensTextIsValid.ps1 b/Source/PSQualityCheck.Functions/Public/Test-HelpTokensTextIsValid.ps1 deleted file mode 100644 index ed841a0..0000000 --- a/Source/PSQualityCheck.Functions/Public/Test-HelpTokensTextIsValid.ps1 +++ /dev/null @@ -1,57 +0,0 @@ -function Test-HelpTokensTextIsValid { - <# - .SYNOPSIS - Check that Help Tokens text is valid - - .DESCRIPTION - Check that the Help Tokens text is valid by making sure that they its not empty - - .PARAMETER HelpTokens - A array of tokens containing the tokens of the Help Comment - - .EXAMPLE - Test-HelpTokensTextIsValid -HelpTokens $HelpTokens - #> - [CmdletBinding()] - [OutputType([System.Exception], [System.Void])] - param ( - [parameter(Mandatory = $true)] - [HashTable]$HelpTokens - ) - - try { - - $tokenErrors = @() - - foreach ($key in $HelpTokens.Keys) { - - $tokenCount = @($HelpTokens.$key) - - for ($loop = 0; $loop -lt $tokenCount.Count; $loop++) { - - $token = $HelpTokens.$key[$loop] - - if ([string]::IsNullOrWhitespace($token.Text)) { - - $tokenErrors += "Found '$key' does not have any text. " - - } - - } - - } - - if ($tokenErrors.Count -ge 1) { - - throw $tokenErrors - - } - - } - catch { - - throw $_.Exception.Message - - } - -} diff --git a/Source/PSQualityCheck.Functions/Public/Test-ImportModuleIsValid.ps1 b/Source/PSQualityCheck.Functions/Public/Test-ImportModuleIsValid.ps1 deleted file mode 100644 index 1e750d5..0000000 --- a/Source/PSQualityCheck.Functions/Public/Test-ImportModuleIsValid.ps1 +++ /dev/null @@ -1,71 +0,0 @@ -function Test-ImportModuleIsValid { - <# - .SYNOPSIS - Test that the Import-Module commands are valid - - .DESCRIPTION - Test that the Import-Module commands contain a -Name parameter, and one of RequiredVersion, MinimumVersion or MaximumVersion - - .PARAMETER ParsedContent - An object containing the source file parsed into its Tokenizer components - - .PARAMETER ImportModuleTokens - An object containing the Import-Module tokens found - - .EXAMPLE - TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens - #> - [CmdletBinding()] - [OutputType([System.Exception], [System.Void])] - param ( - [parameter(Mandatory = $true)] - [System.Object[]]$ParsedContent, - [parameter(Mandatory = $true)] - [System.Object[]]$ImportModuleTokens - ) - - try { - - $errString = "" - - foreach ($token in $importModuleTokens) { - - $importModuleStatement = Get-TokenComponent -ParsedContent $ParsedContent -StartLine $token.StartLine - - $name = ($importModuleStatement | Where-Object { $_.Type -eq "CommandArgument" } | Select-Object -First 1).Content - if ($null -eq $name) { - - $name = ($importModuleStatement | Where-Object { $_.Type -eq "String" } | Select-Object -First 1).Content - - } - - if (-not($importModuleStatement | Where-Object { $_.Type -eq "CommandParameter" -and $_.Content -eq "-Name" })) { - - $errString += "Import-Module for '$name' : Missing -Name parameter keyword. " - - } - - if (-not($importModuleStatement | Where-Object { $_.Type -eq "CommandParameter" -and - ( $_.Content -eq "-RequiredVersion" -or $_.Content -eq "-MinimumVersion" -or $_.Content -eq "-MaximumVersion" ) - })) { - - $errString += "Import-Module for '$name' : Missing -RequiredVersion, -MinimumVersion or -MaximumVersion parameter keyword. " - - } - - } - - if (-not ([string]::IsNullOrEmpty($errString))) { - - throw $errString - - } - - } - catch { - - throw $_.Exception.Message - - } - -} diff --git a/Source/PSQualityCheck.Functions/Public/Test-ParameterVariablesHaveType.ps1 b/Source/PSQualityCheck.Functions/Public/Test-ParameterVariablesHaveType.ps1 deleted file mode 100644 index 79ea9f7..0000000 --- a/Source/PSQualityCheck.Functions/Public/Test-ParameterVariablesHaveType.ps1 +++ /dev/null @@ -1,48 +0,0 @@ -function Test-ParameterVariablesHaveType { - <# - .SYNOPSIS - Check that all the passed parameters have a type variable set. - - .DESCRIPTION - Check that all the passed parameters have a type variable set. - - .PARAMETER ParameterVariables - A HashTable containing the parameters from the param block - - .EXAMPLE - Test-ParameterVariablesHaveType -ParameterVariables $ParameterVariables - #> - [CmdletBinding()] - [OutputType([System.Exception], [System.Void])] - param ( - [parameter(Mandatory = $true)] - [HashTable]$ParameterVariables - ) - - $variableErrors = @() - - try { - - foreach ($key in $ParameterVariables.Keys) { - - if ([string]::IsNullOrEmpty($ParameterVariables.$key)) { - - $variableErrors += "Parameter '$key' does not have a type defined." - - } - - } - - if ($variableErrors.Count -ge 1) { - - throw $variableErrors - } - - } - catch { - - throw $_.Exception.Message - - } - -} diff --git a/Source/PSQualityCheck.Functions/Public/Test-RequiredToken.ps1 b/Source/PSQualityCheck.Functions/Public/Test-RequiredToken.ps1 deleted file mode 100644 index 4b3e3a6..0000000 --- a/Source/PSQualityCheck.Functions/Public/Test-RequiredToken.ps1 +++ /dev/null @@ -1,62 +0,0 @@ -function Test-RequiredToken { - <# - .SYNOPSIS - Check that help tokens contain required tokens - - .DESCRIPTION - Check that the help comments contain tokens that are specified in the external verification data file - - .PARAMETER HelpTokens - A array of tokens containing the tokens of the Help Comment - - .PARAMETER HelpRulesPath - Path to the HelpRules file - - .EXAMPLE - Test-RequiredToken -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" - #> - [CmdletBinding()] - [OutputType([System.Exception], [System.Void])] - param ( - [parameter(Mandatory = $true)] - [HashTable]$HelpTokens, - - [parameter(Mandatory = $true)] - [string]$HelpRulesPath - ) - - try { - - $helpRules = Import-PowerShellDataFile -Path $HelpRulesPath - - $tokenErrors = @() - - for ($order = 1; $order -le $HelpRules.Count; $order++) { - - $helpRuleIndex = [string]$order - $token = $HelpRules.$helpRuleIndex - - if ($token.Key -notin $HelpTokens.Keys ) { - - if ($token.Required -eq $true) { - - $tokenErrors += $token.Key - - } - - } - - } - - if ($tokenErrors.Count -ge 1) { - throw "Missing required token(s): $tokenErrors" - } - - } - catch { - - throw $_.Exception.Message - - } - -} diff --git a/Source/PSQualityCheck.Functions/Public/Test-UnspecifiedToken.ps1 b/Source/PSQualityCheck.Functions/Public/Test-UnspecifiedToken.ps1 deleted file mode 100644 index 76d589a..0000000 --- a/Source/PSQualityCheck.Functions/Public/Test-UnspecifiedToken.ps1 +++ /dev/null @@ -1,65 +0,0 @@ -function Test-UnspecifiedToken { - <# - .SYNOPSIS - Check that help tokens do not contain unspecified tokens - - .DESCRIPTION - Check that the help comments do not contain tokens that are not specified in the external verification data file - - .PARAMETER HelpTokens - A array of tokens containing the tokens of the Help Comment - - .PARAMETER HelpRulesPath - Path to the HelpRules file - - .EXAMPLE - Test-UnspecifiedToken -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" - #> - [CmdletBinding()] - [OutputType([System.Exception], [System.Void])] - param ( - [parameter(Mandatory = $true)] - [HashTable]$HelpTokens, - - [parameter(Mandatory = $true)] - [string]$HelpRulesPath - ) - - try { - - $helpRules = Import-PowerShellDataFile -Path $HelpRulesPath - - $tokenErrors = @() - $helpTokensKeys = @() - - for ($order = 1; $order -le $helpRules.Count; $order++) { - - $helpRuleIndex = [string]$order - $token = $helpRules.$helpRuleIndex - - $helpTokensKeys += $token.key - - } - - foreach ($key in $helpTokens.Keys) { - - if ( $key -notin $helpTokensKeys ) { - - $tokenErrors += $key - - } - - } - - if ($tokenErrors.Count -ge 1) { - throw "Found extra, non-specified, token(s): $tokenErrors" - } - - } - catch { - - throw $_.Exception.Message - - } - -} diff --git a/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 b/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 index af1f77e..394cac1 100644 --- a/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 +++ b/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 @@ -47,48 +47,48 @@ function Invoke-PSQualityCheck { .EXAMPLE Invoke-PSQualityCheck -Path 'C:\Scripts' - This will call the quality checks on single path + This will call the quality Data on single path .EXAMPLE Invoke-PSQualityCheck -Path 'C:\Scripts' -Recurse - This will call the quality checks on single path and sub folders + This will call the quality Data on single path and sub folders .EXAMPLE Invoke-PSQualityCheck -Path @('C:\Scripts', 'C:\MoreScripts') - This will call the quality checks with multiple paths + This will call the quality Data with multiple paths .EXAMPLE Invoke-PSQualityCheck -File 'C:\Scripts\Script.ps1' - This will call the quality checks with single script file + This will call the quality Data with single script file .EXAMPLE Invoke-PSQualityCheck -File 'C:\Scripts\Script.psm1' - This will call the quality checks with single module file + This will call the quality Data with single module file .EXAMPLE Invoke-PSQualityCheck -File 'C:\Scripts\Script.psd1' - This will call the quality checks with single datafile file + This will call the quality Data with single datafile file Note: The datafile test will fail as it is not a file that is accepted for testing .EXAMPLE Invoke-PSQualityCheck -File @('C:\Scripts\Script.ps1','C:\Scripts\Script2.ps1') - This will call the quality checks with multiple files. Files can be either scripts or modules + This will call the quality Data with multiple files. Files can be either scripts or modules .EXAMPLE Invoke-PSQualityCheck -File 'C:\Scripts\Script.ps1' -ScriptAnalyzerRulesPath 'C:\ScriptAnalyzerRulesPath' - This will call the quality checks with single file and the extra PSScriptAnalyzer rules + This will call the quality Data with single file and the extra PSScriptAnalyzer rules .EXAMPLE Invoke-PSQualityCheck -Path 'C:\Scripts' -ShowCheckResults - This will display a summary of the checks performed (example below uses sample data): + This will display a summary of the Data performed (example below uses sample data): Name Files Tested Total Passed Failed Skipped ---- ------------ ----- ------ ------ ------- @@ -177,7 +177,7 @@ function Invoke-PSQualityCheck { } else { - $helpRulesPath = (Join-Path -Path $modulePath -ChildPath "Checks\HelpRules.psd1") + $helpRulesPath = (Join-Path -Path $modulePath -ChildPath "Data\HelpRules.psd1") } @@ -203,12 +203,26 @@ function Invoke-PSQualityCheck { if (Test-Path -Path $ProjectPath) { - $container1 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Project.Tests.ps1') -Data @{ Path = $ProjectPath } + $container1 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Project.Checks.ps1') -Data @{ Path = $ProjectPath } $PesterConfiguration.Run.Container = $container1 $projectResults = Invoke-Pester -Configuration $PesterConfiguration # setup the rest of the Path based tests - $Path = Join-Path -Path $ProjectPath -ChildPath "Source" + # this needs to include the module/public module/private and scripts folder only, not the data or any other folders + $ProjectPath = (Resolve-Path -Path $ProjectPath) + $sourceRootPath = (Join-Path -Path $ProjectPath -ChildPath "Source") + $scriptPath = (Join-Path -Path $ProjectPath -ChildPath "Scripts") + $Path = @($scriptPath) + + # Get the list of Modules + $modules = Get-ChildItem -Path $sourceRootPath -Directory + + foreach ($module in $modules) { + + $Path += (Join-Path -Path $module -ChildPath "Public") + $Path += (Join-Path -Path $module -ChildPath "Private") + + } } else { @@ -234,8 +248,8 @@ function Invoke-PSQualityCheck { $getFileListSplat.Add('Recurse', $true) } - $scriptsToTest += Get-FileList @getFileListSplat -Extension '.ps1' - $modulesToTest += Get-FileList @getFileListSplat -Extension '.psm1' + $scriptsToTest += GetFileList @getFileListSplat -Extension '.ps1' + $modulesToTest += GetFileList @getFileListSplat -Extension '.psm1' } else { @@ -284,12 +298,12 @@ function Invoke-PSQualityCheck { } - # Get the list of test tags from the checks files + # Get the list of test tags from the Data files if ($PSBoundParameters.ContainsKey('Include') -or $PSBoundParameters.ContainsKey('Exclude')) { - ($moduleTags, $scriptTags) = Get-TagList + ($moduleTags, $scriptTags) = GetTagList $moduleTagsToInclude = @() $moduleTagsToExclude = @() $scriptTagsToInclude = @() @@ -369,12 +383,12 @@ function Invoke-PSQualityCheck { if ($runModuleCheck -eq $true) { # Run the Module tests on all the valid module files found - $container1 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Module.Checks.ps1') -Data @{ Source = $modulesToTest } + $container1 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Module.Checks.ps1') -Data @{ Source = $modulesToTest } $PesterConfiguration.Run.Container = $container1 $moduleResults = Invoke-Pester -Configuration $PesterConfiguration # Extract all the functions from the modules into individual .ps1 files ready for testing - $container2 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Extraction.ps1') -Data @{ Source = $modulesToTest; ExtractPath = $extractPath } + $container2 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Extraction.ps1') -Data @{ Source = $modulesToTest; ExtractPath = $extractPath } $PesterConfiguration.Run.Container = $container2 $extractionResults = Invoke-Pester -Configuration $PesterConfiguration @@ -386,7 +400,7 @@ function Invoke-PSQualityCheck { $extractedScriptsToTest = Get-ChildItem -Path $extractPath -Include '*.ps1' -Recurse # Run the Script tests against all the extracted functions .ps1 files - $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Script.Checks.ps1') -Data @{ Source = $extractedScriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath; HelpRulesPath = $HelpRulesPath } + $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Script.Checks.ps1') -Data @{ Source = $extractedScriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath; HelpRulesPath = $HelpRulesPath } $PesterConfiguration.Run.Container = $container3 $extractedScriptResults = Invoke-Pester -Configuration $PesterConfiguration } @@ -403,7 +417,7 @@ function Invoke-PSQualityCheck { if ($scriptsToTest.Count -ge 1 -and $runScriptCheck -eq $true) { # Run the Script tests against all the valid script files found - $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Script.Checks.ps1') -Data @{ Source = $scriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath } + $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Data\Script.Checks.ps1') -Data @{ Source = $scriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath } $PesterConfiguration.Run.Container = $container3 $scriptResults = Invoke-Pester -Configuration $PesterConfiguration @@ -419,12 +433,12 @@ function Invoke-PSQualityCheck { if ($null -ne $projectResults) { $qualityCheckResults += @{ - 'Test' = 'Project Tests' + 'Test' = 'Project Tests' 'Files Tested' = 0 - 'Total' = ($projectResults.TotalCount - $projectResults.NotRunCount) - 'Passed' = $projectResults.PassedCount - 'Failed' = $projectResults.FailedCount - 'Skipped' = $projectResults.SkippedCount + 'Total' = ($projectResults.TotalCount - $projectResults.NotRunCount) + 'Passed' = $projectResults.PassedCount + 'Failed' = $projectResults.FailedCount + 'Skipped' = $projectResults.SkippedCount } $filesTested += 0 $total += ($projectResults.TotalCount - $projectResults.NotRunCount) @@ -436,12 +450,12 @@ function Invoke-PSQualityCheck { if ($null -ne $moduleResults) { $qualityCheckResults += @{ - 'Test' = 'Module Tests' + 'Test' = 'Module Tests' 'Files Tested' = $ModulesToTest.Count - 'Total' = ($moduleResults.TotalCount - $moduleResults.NotRunCount) - 'Passed' = $moduleResults.PassedCount - 'Failed' = $moduleResults.FailedCount - 'Skipped' = $moduleResults.SkippedCount + 'Total' = ($moduleResults.TotalCount - $moduleResults.NotRunCount) + 'Passed' = $moduleResults.PassedCount + 'Failed' = $moduleResults.FailedCount + 'Skipped' = $moduleResults.SkippedCount } $filesTested += $ModulesToTest.Count $total += ($moduleResults.TotalCount - $moduleResults.NotRunCount) @@ -453,12 +467,12 @@ function Invoke-PSQualityCheck { if ($null -ne $extractionResults) { $qualityCheckResults += @{ - 'Test' = 'Extracting functions' + 'Test' = 'Extracting functions' 'Files Tested' = $ModulesToTest.Count - 'Total' = ($extractionResults.TotalCount - $extractionResults.NotRunCount) - 'Passed' = $extractionResults.PassedCount - 'Failed' = $extractionResults.FailedCount - 'Skipped' = $extractionResults.SkippedCount + 'Total' = ($extractionResults.TotalCount - $extractionResults.NotRunCount) + 'Passed' = $extractionResults.PassedCount + 'Failed' = $extractionResults.FailedCount + 'Skipped' = $extractionResults.SkippedCount } $total += ($extractionResults.TotalCount - $extractionResults.NotRunCount) $passed += $extractionResults.PassedCount @@ -469,12 +483,12 @@ function Invoke-PSQualityCheck { if ($null -ne $extractedScriptResults) { $qualityCheckResults += @{ - 'Test' = 'Extracted function script tests' + 'Test' = 'Extracted function script tests' 'Files Tested' = $extractedScriptsToTest.Count - 'Total' = ($extractedScriptResults.TotalCount - $extractedScriptResults.NotRunCount) - 'Passed' = $extractedScriptResults.PassedCount - 'Failed' = $extractedScriptResults.FailedCount - 'Skipped' = $extractedScriptResults.SkippedCount + 'Total' = ($extractedScriptResults.TotalCount - $extractedScriptResults.NotRunCount) + 'Passed' = $extractedScriptResults.PassedCount + 'Failed' = $extractedScriptResults.FailedCount + 'Skipped' = $extractedScriptResults.SkippedCount } $filesTested += $extractedScriptsToTest.Count $total += ($extractedScriptResults.TotalCount - $extractedScriptResults.NotRunCount) @@ -486,12 +500,12 @@ function Invoke-PSQualityCheck { if ($null -ne $scriptResults) { $qualityCheckResults += @{ - 'Test' = "Script Tests" + 'Test' = "Script Tests" 'Files Tested' = $scriptsToTest.Count - 'Total' = ($scriptResults.TotalCount - $scriptResults.NotRunCount) - 'Passed' = $scriptResults.PassedCount - 'Failed' = $scriptResults.FailedCount - 'Skipped' = $scriptResults.SkippedCount + 'Total' = ($scriptResults.TotalCount - $scriptResults.NotRunCount) + 'Passed' = $scriptResults.PassedCount + 'Failed' = $scriptResults.FailedCount + 'Skipped' = $scriptResults.SkippedCount } $filesTested += $scriptsToTest.Count $total += ($scriptResults.TotalCount - $scriptResults.NotRunCount) @@ -502,23 +516,23 @@ function Invoke-PSQualityCheck { $qualityCheckResults += @{ - 'Test' = "Total" + 'Test' = "Total" 'Files Tested' = $filesTested - 'Total' = $total - 'Passed' = $passed - 'Failed' = $failed - 'Skipped' = $skipped + 'Total' = $total + 'Passed' = $passed + 'Failed' = $failed + 'Skipped' = $skipped } # This works on PS5 and PS7 $qualityCheckResults | ForEach-Object { [PSCustomObject]@{ - 'Test' = $_.Test + 'Test' = $_.Test 'Files Tested' = $_.'Files Tested' - 'Total' = $_.total - 'Passed' = $_.passed - 'Failed' = $_.failed - 'Skipped' = $_.skipped + 'Total' = $_.total + 'Passed' = $_.passed + 'Failed' = $_.failed + 'Skipped' = $_.skipped } } | Format-Table -AutoSize @@ -542,10 +556,10 @@ function Invoke-PSQualityCheck { if ($PesterConfiguration.Run.PassThru.Value -eq $true) { $resultObject = @{ - 'project' = $projectResults - 'module' = $moduleResults - 'extraction' = $extractionResults - 'script' = $scriptResults + 'project' = $projectResults + 'module' = $moduleResults + 'extraction' = $extractionResults + 'script' = $scriptResults 'extractedscript' = $extractedScriptResults } diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..4dbc89f --- /dev/null +++ b/build.ps1 @@ -0,0 +1,202 @@ +Import-Module -Name Pester -MinimumVersion 5.1.0 +Import-Module -Name PSQualityCheck -MinimumVersion 1.3.0 + +$InformationPreference = 'Continue' + +# PesterConfiguration +$PesterConfiguration = [PesterConfiguration]::Default +$PesterConfiguration.Run.Exit = $false +$PesterConfiguration.CodeCoverage.Enabled = $false +$PesterConfiguration.Output.Verbosity = 'Detailed' +$PesterConfiguration.Run.PassThru = $true +$PesterConfiguration.Should.ErrorAction = 'Stop' + +$ScriptRules = @( + '../ScriptAnalyzerRules/Indented.CodingConventions/' + #, './Analyzer/PSScriptAnalyzer/Tests/Engine/CommunityAnalyzerRules/' + #, './Analyzer/InjectionHunter/' +) + +function Get-FunctionFileContent { + [CmdletBinding()] + [OutputType([System.String[]])] + param ( + [parameter(Mandatory = $true)] + [string]$Path + ) + + try { + $fileContent = Get-Content -Path $Path + $parserErrors = $null + if ([string]::IsNullOrEmpty($fileContent)) { + $parsedFileFunctions = @() + } + else { + $parsedFileFunctions = [System.Management.Automation.PSParser]::Tokenize($fileContent, [ref]$parserErrors) + } + $parsedFunctions = ($parsedFileFunctions | Where-Object { $_.Type -eq "Keyword" -and $_.Content -like 'function' }) + if ($parsedFunctions.Count -gt 1) { + throw "Too many functions in file, file is invalid" + } + if ($parsedFunctions.Count -eq 1) { + if ($fileContent.Count -gt 1) { + foreach ($function in $parsedFunctions) { + $startLine = ($function.StartLine) + for ($line = $fileContent.Count; $line -gt $function.StartLine; $line--) { + if ($fileContent[$line] -like "*}*") { + $endLine = $line + break + } + } + for ($line = $startLine; $line -lt $endLine; $line++) { + $parsedFileContent += $fileContent[$line] + if ($line -ne ($fileContent.Count - 1)) { + $parsedFileContent += "`r`n" + } + } + } + } + else { + [int]$startBracket = $fileContent.IndexOf('{') + [int]$endBracket = $fileContent.LastIndexOf('}') + $parsedFileContent = $fileContent.substring($startBracket + 1, $endBracket - 1 - $startBracket) + } + } + else { + if ($fileContent.Count -gt 1) { + for ($line = 0; $line -lt $fileContent.Count; $line++) { + $parsedFileContent += $fileContent[$line] + if ($line -ne ($fileContent.Count - 1)) { + $parsedFileContent += "`r`n" + } + } + } + else { + $parsedFileContent = $fileContent + } + } + } + catch { + throw + } + return $parsedFileContent +} + +# Project Based +# $qualityResult = Invoke-PSQualityCheck -ProjectPath '.\' -ScriptAnalyzerRulesPath $ScriptRules -HelpRulesPath '.\HelpRules.psd1' -Passthru -PesterConfiguration $PesterConfiguration + +# if ($qualityResult.Script.FailedCount -eq 0 -and $qualityResult.Project.FailedCount -eq 0) { +if ($true) { + + $Modules = Get-ChildItem -Path ".\Source" -Directory + + $functionResults = @() + + foreach ($module in $Modules) { + + $functionFiles = @() + # $privateFunctionFiles = @() + + $functionFiles += Get-ChildItem -Path (Join-Path -Path $Module.FullName -ChildPath "public") + + # If there are any scripts in the private folder with corresponding tests then run those too + # $privateFunctionFiles += Get-ChildItem -Path (Join-Path -Path $Module.FullName -ChildPath "private") + # Write-Host $privateFunctionFiles.Count -ForegroundColor Yellow + # foreach ($function in $privateFunctionFiles) { + # Write-Host $function.FullName -ForegroundColor Yellow + # if (Test-Path -Path ".\tests\unit\$($module.BaseName)\$($function.BaseName).Tests.ps1") { + # $functionFiles += (Get-ChildItem -Path ".\tests\unit\$($module.BaseName)\$($function.BaseName).Tests.ps1") + # } + # } + + foreach ($function in $functionFiles) { + + # Write-Host ".\tests\unit\$($module.BaseName)\$($function.BaseName).Tests.psd1" -ForegroundColor Yellow + # Write-Host $function.FullName -ForegroundColor Yellow + + $fileContent = Get-FunctionFileContent -Path $function.FullName + . "$($function.FullName)" + + $container = New-PesterContainer -Path ".\tests\unit\$($module.BaseName)\$($function.BaseName).Tests.ps1" -Data @{FileContent = $fileContent } + $PesterConfiguration.Run.Container = $container + + $functionResults += Invoke-Pester -Configuration $PesterConfiguration + + } + } +} +else { + + # Write-Information 'Functions not tested - there were project quality check errors' + # Write-Warning -Message "Project Quality Check fails" + Write-Error -Message "Project Quality Check fails" + break + +} + +$failedCount = 0 + +foreach ($result in $functionResults) { + $failedCount += $result.FailedCount +} + +if ($failedCount -eq 0 ) { + + foreach ($module in $Modules) { + + $buildFile = ".\source\$($module.BaseName)\build.psd1" + Write-Host $buildFile -ForegroundColor Yellow + + Build-Module -SourcePath $buildFile + + } +} +else { + + Write-Information 'Modules not build - there were errors' + throw + +} + +# End of module build + +# Script checks +$scriptFiles = Get-ChildItem -Path ".\Scripts" -Filter "*.ps1" -Recurse + +$scriptResults = @() + +foreach ($script in $scriptFiles) { + + $Result = Invoke-PSQualityCheck -File $script.FullName -ScriptAnalyzerRulesPath $ScriptRules -HelpRulesPath '.\HelpRules.psd1' -Passthru -PesterConfiguration $PesterConfiguration + + $folder = Split-Path -Path $script.DirectoryName -Leaf + + Write-Host ".\tests\scripts\$folder\$($script.BaseName).Tests.ps1" + if ((Test-Path -Path ".\tests\scripts\$folder\$($script.BaseName).Tests.ps1") -and $result.Script.FailedCount -eq 0) { + + $fileContent = Get-FunctionFileContent -Path $script.FullName + + $container = New-PesterContainer -Path ".\tests\scripts\$folder\$($script.BaseName).Tests.ps1" -Data @{FileContent = $fileContent } + $PesterConfiguration.Run.Container = $container + + $scriptResults += Invoke-Pester -Configuration $PesterConfiguration + + } + +} + + + + +# $Result = Invoke-PSQualityCheck -Path @('.\Scripts') -recurse -ScriptAnalyzerRulesPath $ScriptRules -HelpRulesPath '.\HelpRules.psd1' -Passthru -PesterConfiguration $PesterConfiguration + +# if ($Result.Script.FailedCount -eq 0) { + +# $Dest = ".\artifacts" +# # Copy Script files to release folder +# New-Item -ItemType Directory -Force -Path $Dest +# Copy-Item ".\Scripts\*.*" -Destination $Dest -Recurse -Force +# } +# else { +# Write-Information 'Scripts not exported - there were errors' +# } diff --git a/docs/about.md b/docs/about.md new file mode 100644 index 0000000..7ca5e1a --- /dev/null +++ b/docs/about.md @@ -0,0 +1,6 @@ +# What is + + + +Authored by + diff --git a/docs/acknowledgements.md b/docs/acknowledgements.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..a3c45b1 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,4 @@ +# Docs + + uses ReadTheDocs to host our documentation. This allows us to keep our docs in the repository, without the various limitations that come with the built in GitHub repo wiki. + diff --git a/docs/quickstart.md b/docs/quickstart.md new file mode 100644 index 0000000..9cb5cd1 --- /dev/null +++ b/docs/quickstart.md @@ -0,0 +1,5 @@ +# Installing + + # Install from the Powershell Gallery + Find-Module | Install-Module + diff --git a/install.depend.ps1 b/install.depend.ps1 new file mode 100644 index 0000000..bab344c --- /dev/null +++ b/install.depend.ps1 @@ -0,0 +1,25 @@ + +# Bootstrap environment +Get-PackageProvider -Name 'NuGet' -ForceBootstrap | Out-Null + +# Install PSDepend module if it is not already installed +if (-not (Get-Module -Name 'PSDepend' -ListAvailable)) { + Write-Output "`nPSDepend is not yet installed...installing PSDepend now..." + Install-Module -Name 'PSDepend' -Scope 'CurrentUser' -Force +} +else { + Write-Output "`nPSDepend already installed...skipping." +} + +# Install build dependencies +$psdependencyConfigPath = Join-Path -Path $PSScriptRoot -ChildPath 'install.depend.psd1' +Write-Output "Checking / resolving module dependencies from [$psdependencyConfigPath]..." +Import-Module -Name 'PSDepend' +$invokePSDependParams = @{ + Path = $psdependencyConfigPath + Import = $true + Confirm = $false + Install = $true + Verbose = $true +} +Invoke-PSDepend @invokePSDependParams diff --git a/install.depend.psd1 b/install.depend.psd1 new file mode 100644 index 0000000..e7ffa37 --- /dev/null +++ b/install.depend.psd1 @@ -0,0 +1,20 @@ +# NOTE: follow nuget syntax for versions: https://docs.microsoft.com/en-us/nuget/reference/package-versioning#version-ranges-and-wildcards +@{ + PSDependOptions = @{ + Target = 'CurrentUser' + } + Configuration = 'Latest' + Pester = @{ + Name = 'Pester' + Version = '5.1.1' + Parameters = @{ + SkipPublisherCheck = $true + } + } + ModuleBuilder = 'Latest' + PowerShellGet = 'Latest' + PSScriptAnalyzer = 'Latest' + PSQualityCheck = 'Latest' + InvokeBuild = 'Latest' + "Cofl.Util" = 'Latest' +} From 5464fec2ed7a6893528c4f9406b4667df1690d35 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Sat, 24 Apr 2021 18:22:57 +0100 Subject: [PATCH 07/27] Further updates --- PSQualityCheck.Functions.psd1 | 140 -- PSQualityCheck.Functions.psm1 | 1343 ----------------- PSQualityCheck.psd1 | 133 -- PSQualityCheck.psm1 | 562 ------- Source/PSQualityCheck/PSQualityCheck.psd1 | 133 ++ Source/PSQualityCheck/build.psd1 | 10 + Source/PSQualityCheck/data/Extraction.ps1 | 52 + Source/PSQualityCheck/data/HelpRules.psd1 | 73 + Source/PSQualityCheck/data/Module.Checks.ps1 | 84 ++ Source/PSQualityCheck/data/Project.Checks.ps1 | 118 ++ Source/PSQualityCheck/data/Script.Checks.ps1 | 250 +++ .../en-US/aboutPSQualityCheck.help.txt | 28 + Source/PSQualityCheck/private/ConvertHelp.ps1 | 149 ++ .../private/ExportFunctionsFromModule.ps1 | 104 ++ .../PSQualityCheck/private/GetFileContent.ps1 | 95 ++ Source/PSQualityCheck/private/GetFileList.ps1 | 56 + .../private/GetFunctionCount.ps1 | 100 ++ .../private/GetParsedContent.ps1 | 39 + .../PSQualityCheck/private/GetParsedFile.ps1 | 38 + .../private/GetScriptParameter.ps1 | 76 + Source/PSQualityCheck/private/GetTagList.ps1 | 71 + Source/PSQualityCheck/private/GetToken.ps1 | 38 + .../private/GetTokenComponent.ps1 | 35 + .../PSQualityCheck/private/GetTokenMarker.ps1 | 41 + .../private/TestHelpTokensCountisValid.ps1 | 82 + .../private/TestHelpTokensParamsMatch.ps1 | 92 ++ .../private/TestHelpTokensTextIsValid.ps1 | 57 + .../private/TestImportModuleIsValid.ps1 | 76 + .../TestParameterVariablesHaveType.ps1 | 48 + .../private/TestRequiredToken.ps1 | 62 + .../private/TestUnspecifiedToken.ps1 | 65 + .../Convert-Help.Tests.ps1 | 40 +- .../Export-FunctionsFromModule.Tests.ps1 | 0 .../Get-FileContent.Tests.ps1 | 0 .../Get-FileList.Tests.ps1 | 0 .../Get-FunctionCount.Tests.ps1 | 0 .../Get-ParsedContent.Tests.ps1 | 0 .../Get-ParsedFile.Tests.ps1 | 0 .../Get-ScriptParameter.Tests.ps1 | 0 .../Get-TagList.Tests.ps1 | 0 .../Get-Token.Tests.ps1 | 0 .../Get-TokenComponent.Tests.ps1 | 0 .../Get-TokenMarker.Tests.ps1 | 86 +- .../Test-HelpTokensCountisValid.Tests.ps1} | 54 +- .../Test-HelpTokensParamsMatch.Tests.ps1 | 0 .../Test-HelpTokensTextIsValid.Tests.ps1 | 0 .../Test-ImportModuleIsValid.Tests.ps1 | 0 .../Test-ParameterVariablesHaveType.Tests.ps1 | 0 .../Test-RequiredToken.Tests.ps1 | 72 +- .../Test-UnspecifiedToken.Tests.ps1 | 60 +- 50 files changed, 2228 insertions(+), 2334 deletions(-) delete mode 100644 PSQualityCheck.Functions.psd1 delete mode 100644 PSQualityCheck.Functions.psm1 delete mode 100644 PSQualityCheck.psd1 delete mode 100644 PSQualityCheck.psm1 create mode 100644 Source/PSQualityCheck/PSQualityCheck.psd1 create mode 100644 Source/PSQualityCheck/build.psd1 create mode 100644 Source/PSQualityCheck/data/Extraction.ps1 create mode 100644 Source/PSQualityCheck/data/HelpRules.psd1 create mode 100644 Source/PSQualityCheck/data/Module.Checks.ps1 create mode 100644 Source/PSQualityCheck/data/Project.Checks.ps1 create mode 100644 Source/PSQualityCheck/data/Script.Checks.ps1 create mode 100644 Source/PSQualityCheck/en-US/aboutPSQualityCheck.help.txt create mode 100644 Source/PSQualityCheck/private/ConvertHelp.ps1 create mode 100644 Source/PSQualityCheck/private/ExportFunctionsFromModule.ps1 create mode 100644 Source/PSQualityCheck/private/GetFileContent.ps1 create mode 100644 Source/PSQualityCheck/private/GetFileList.ps1 create mode 100644 Source/PSQualityCheck/private/GetFunctionCount.ps1 create mode 100644 Source/PSQualityCheck/private/GetParsedContent.ps1 create mode 100644 Source/PSQualityCheck/private/GetParsedFile.ps1 create mode 100644 Source/PSQualityCheck/private/GetScriptParameter.ps1 create mode 100644 Source/PSQualityCheck/private/GetTagList.ps1 create mode 100644 Source/PSQualityCheck/private/GetToken.ps1 create mode 100644 Source/PSQualityCheck/private/GetTokenComponent.ps1 create mode 100644 Source/PSQualityCheck/private/GetTokenMarker.ps1 create mode 100644 Source/PSQualityCheck/private/TestHelpTokensCountisValid.ps1 create mode 100644 Source/PSQualityCheck/private/TestHelpTokensParamsMatch.ps1 create mode 100644 Source/PSQualityCheck/private/TestHelpTokensTextIsValid.ps1 create mode 100644 Source/PSQualityCheck/private/TestImportModuleIsValid.ps1 create mode 100644 Source/PSQualityCheck/private/TestParameterVariablesHaveType.ps1 create mode 100644 Source/PSQualityCheck/private/TestRequiredToken.ps1 create mode 100644 Source/PSQualityCheck/private/TestUnspecifiedToken.ps1 rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Convert-Help.Tests.ps1 (88%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Export-FunctionsFromModule.Tests.ps1 (100%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Get-FileContent.Tests.ps1 (100%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Get-FileList.Tests.ps1 (100%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Get-FunctionCount.Tests.ps1 (100%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Get-ParsedContent.Tests.ps1 (100%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Get-ParsedFile.Tests.ps1 (100%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Get-ScriptParameter.Tests.ps1 (100%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Get-TagList.Tests.ps1 (100%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Get-Token.Tests.ps1 (100%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Get-TokenComponent.Tests.ps1 (100%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Get-TokenMarker.Tests.ps1 (50%) rename Tests/Unit/{PSQualityCheck.Functions/Test-HelpTokensCountIsValid.Tests.ps1 => PSQualityCheck/Test-HelpTokensCountisValid.Tests.ps1} (81%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Test-HelpTokensParamsMatch.Tests.ps1 (100%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Test-HelpTokensTextIsValid.Tests.ps1 (100%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Test-ImportModuleIsValid.Tests.ps1 (100%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Test-ParameterVariablesHaveType.Tests.ps1 (100%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Test-RequiredToken.Tests.ps1 (77%) rename Tests/Unit/{PSQualityCheck.Functions => PSQualityCheck}/Test-UnspecifiedToken.Tests.ps1 (79%) diff --git a/PSQualityCheck.Functions.psd1 b/PSQualityCheck.Functions.psd1 deleted file mode 100644 index 5d6dfef..0000000 --- a/PSQualityCheck.Functions.psd1 +++ /dev/null @@ -1,140 +0,0 @@ -# -# Module manifest for module 'PSQualityCheck.Functions' -# -# Generated by: Andrew Davidson -# -# Generated on: 03/02/2021 -# - -@{ - -# Script module or binary module file associated with this manifest. -RootModule = 'PSQualityCheck.Functions.psm1' - -# Version number of this module. -ModuleVersion = '1.3.1' - -# Supported PSEditions -# CompatiblePSEditions = @() - -# ID used to uniquely identify this module -GUID = '5ddfdef7-3985-476d-92d8-e7db35bf960b' - -# Author of this module -Author = 'Andrew Davidson' - -# Company or vendor of this module -CompanyName = 'Andrew Davidson' - -# Copyright statement for this module -Copyright = '(c) Andrew Davidson. All rights reserved.' - -# Description of the functionality provided by this module -Description = 'This module contains supporting functions for PSQualityCheck.' - -# Minimum version of the PowerShell engine required by this module -PowerShellVersion = '5.0' - -# Name of the PowerShell host required by this module -# PowerShellHostName = '' - -# Minimum version of the PowerShell host required by this module -# PowerShellHostVersion = '' - -# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. -# DotNetFrameworkVersion = '' - -# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. -# ClrVersion = '' - -# 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 = @() - -# 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 = @() - -# Type files (.ps1xml) to be loaded when importing this module -# TypesToProcess = @() - -# Format files (.ps1xml) to be loaded when importing this module -# FormatsToProcess = @() - -# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess -# NestedModules = @() - -# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. -FunctionsToExport = 'Convert-Help', 'Export-FunctionsFromModule', 'Get-FileContent', - 'Get-FileList', 'Get-FunctionCount', 'Get-ParsedContent', - 'Get-ParsedFile', 'Get-ScriptParameter', 'Get-TagList', 'Get-Token', - 'Get-TokenComponent', 'Get-TokenMarker', - 'Test-HelpTokensCountIsValid', 'Test-HelpTokensParamsMatch', - 'Test-HelpTokensTextIsValid', 'Test-ImportModuleIsValid', - 'Test-ParameterVariablesHaveType', 'Test-RequiredToken', - 'Test-UnspecifiedToken' - -# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. -CmdletsToExport = @() - -# Variables to export from this module -# VariablesToExport = @() - -# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. -AliasesToExport = @() - -# DSC resources to export from this module -# DscResourcesToExport = @() - -# List of all modules packaged with this module -# ModuleList = @() - -# List of all files packaged with this module -FileList = 'Checks\HelpRules.psd1' - -# 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 = @{ - - # Tags applied to this module. These help with module discovery in online galleries. - Tags = 'powershell', 'powershell-module', 'quality', 'quality-check', 'tests', - 'pester', 'pester-tests' - - # A URL to the license for this module. - LicenseUri = 'https://github.com/andrewrdavidson/PSQualityCheck/blob/main/LICENSE' - - # A URL to the main website for this project. - ProjectUri = 'https://github.com/andrewrdavidson/PSQualityCheck' - - # A URL to an icon representing this module. - # IconUri = '' - - # ReleaseNotes of this module - # ReleaseNotes = '' - - # Prerelease string of this module - # Prerelease = '' - - # Flag to indicate whether the module requires explicit user acceptance for install/update/save - # RequireLicenseAcceptance = $false - - # External dependent modules of this module - # ExternalModuleDependencies = @() - - } # End of PSData hashtable - -} # End of PrivateData hashtable - -# HelpInfo URI of this module -HelpInfoURI = 'https://github.com/andrewrdavidson/PSQualityCheck/wiki' - -# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. -# DefaultCommandPrefix = '' - -} - diff --git a/PSQualityCheck.Functions.psm1 b/PSQualityCheck.Functions.psm1 deleted file mode 100644 index 0bc5f7a..0000000 --- a/PSQualityCheck.Functions.psm1 +++ /dev/null @@ -1,1343 +0,0 @@ -function Convert-Help { - <# - .SYNOPSIS - Convert the help comment into an object - - .DESCRIPTION - Convert the help comment into an object containing all the elements from the help comment - - .PARAMETER Help - A string containing the Help Comment - - .EXAMPLE - $helpObject = Convert-Help -Help $Help - #> - [CmdletBinding()] - [OutputType([HashTable], [System.Exception])] - param ( - [parameter(Mandatory = $true)] - [string]$Help - ) - - # These are the possible Help Comment elements that the script will look for - # .SYNOPSIS - # .DESCRIPTION - # .PARAMETER - # .EXAMPLE - # .INPUTS - # .OUTPUTS - # .NOTES - # .LINK - # .COMPONENT - # .ROLE - # .FUNCTIONALITY - # .FORWARDHELPTARGETNAME - # .FORWARDHELPCATEGORY - # .REMOTEHELPRUNSPACE - # .EXTERNALHELP - - # This function will go through the help and work out which elements are where and what text they contain - - try { - - if (-not( - $Help.StartsWith("<#") -and - $Help.EndsWith("#>") - )) { - throw "Help does not appear to be a comment block" - } - - $helpElementsToFind = - '.SYNOPSIS', - '.DESCRIPTION', - '.PARAMETER', - '.EXAMPLE', - '.INPUTS', - '.OUTPUTS', - '.NOTES', - '.LINK', - '.COMPONENT', - '.ROLE', - '.FUNCTIONALITY', - '.FORWARDHELPTARGETNAME', - '.FORWARDHELPCATEGORY', - '.REMOTEHELPRUNSPACE', - '.EXTERNALHELP' - - $commentArray = ($Help -split '\n').Trim() - - $foundElements = @{} - $numFound = 0 - $lastHelpElement = $null - - for ($line = 0; $line -lt $commentArray.Count; $line++) { - - # get the first 'word' of the help comment. This is required so that we can - # match '.PARAMETER' since it has a parameter name after it - $helpElementName = ($commentArray[$line] -split " ")[0] - - if ($helpElementsToFind -contains $helpElementName) { - - $numFound++ - - if ($numFound -ge 2) { - - # if it's the second element then we must set the help comment text of the - # previous element to the found text so far, then reset it - - $lastElement = @($foundElements[$lastHelpElement]) - $lastElement[$lastElement.Count - 1].Text = $helpData - $foundElements[$lastHelpElement] = $lastElement - - $helpData = $null - } - - # this should be an array of HashTables - # each hash table will contain the properties LineNumber, Name & Text - $currentElement = @($foundElements[$helpElementName]) - - $newElement = @{} - $newElement.LineNumber = $line - $newElement.Name = ($commentArray[$line] -split " ")[1] - $newElement.Text = "" - - if ($null -eq $currentElement[0]) { - - $currentElement = $newElement - - } - else { - $currentElement += $newElement - } - - $foundElements[$helpElementName] = $currentElement - - $lastHelpElement = $helpElementName - - } - else { - - if ($numFound -ge 1 -and $line -lt ($commentArray.Count - 1)) { - - $helpData += $commentArray[$line] - - } - - } - - } - - if ( -not ([string]::IsNullOrEmpty($lastHelpElement))) { - $currentElement = @($foundElements[$lastHelpElement]) - $currentElement[$currentElement.Count - 1].Text = $helpData - $foundElements[$lastHelpElement] = $currentElement - } - - return $foundElements - - } - catch { - - throw $_.Exception.Message - - } - -} - -function Export-FunctionsFromModule { - <# - .SYNOPSIS - Export functions from a PowerShell module (.psm1) - - .DESCRIPTION - Takes a PowerShell module and outputs a single file for each function containing the code for that function - - .PARAMETER Path - A string Path containing the full file name and path to the module - - .PARAMETER ExtractPath - A string Path containing the full path to the extraction folder - - .EXAMPLE - Export-FunctionsFromModule -Path 'c:\path.to\module.psm1' -ExtractPath 'c:\extract' - #> - [CmdletBinding()] - [OutputType([System.Void])] - param ( - [parameter(Mandatory = $true)] - [string]$Path, - [parameter(Mandatory = $true)] - [string]$ExtractPath - ) - - try { - - $fileProperties = (Get-Item -LiteralPath $Path) - - if ($fileProperties.Extension -ne ".psm1") { - throw "Passed file does not appear to be a PowerShell module" - } - - $moduleName = $fileProperties.BaseName - - $ModuleFileContent = Get-Content -Path $Path -ErrorAction Stop - - $ParserErrors = $null - $ParsedFileFunctions = [System.Management.Automation.PSParser]::Tokenize($ModuleFileContent, [ref]$ParserErrors) - - $ParsedFunctions = ($ParsedFileFunctions | Where-Object { $_.Type -eq "Keyword" -and $_.Content -like 'function' }) - - $parsedFunction = 0 - - if ($ParsedFunctions.Count -ge 1) { - - $FunctionOutputPath = Join-Path -Path $ExtractPath -ChildPath $moduleName - - if (-not (Test-Path -Path $FunctionOutputPath)) { - New-Item $FunctionOutputPath -ItemType 'Directory' - } - - foreach ($Function in $ParsedFunctions) { - - $parsedFunction++ - - $FunctionProperties = $ParsedFileFunctions | Where-Object { $_.StartLine -eq $Function.StartLine } - $FunctionName = ($FunctionProperties | Where-Object { $_.Type -eq "CommandArgument" }).Content - - if ($parsedFunction -eq $ParsedFunctions.Count) { - - $StartLine = ($Function.StartLine) - for ($line = $ModuleFileContent.Count; $line -gt $Function.StartLine; $line--) { - if ($ModuleFileContent[$line] -like "}") { - $EndLine = $line - break - } - } - - } - else { - - $StartLine = ($Function.StartLine) - - for ($line = $ParsedFunctions[$parsedFunction].StartLine; $line -gt $Function.StartLine; $line--) { - if ($ModuleFileContent[$line] -like "}") { - $EndLine = $line - break - } - } - - } - - $FunctionOutputFileName = "{0}\{1}{2}" -f $FunctionOutputPath, $FunctionName, ".ps1" - - if (-not (Test-Path -Path $FunctionOutputFileName)) { - Out-File -FilePath $FunctionOutputFileName - } - - for ($line = $StartLine; $line -lt $EndLine; $line++) { - Add-Content -Path $FunctionOutputFileName -Value $ModuleFileContent[$line] - } - - } - } - else { - throw "File contains no functions" - } - } - catch { - throw - } -} - -function Get-FileContent { - <# - .SYNOPSIS - Gets the content of a script file - - .DESCRIPTION - Gets the content of the file or the content of the function inside the file - - .PARAMETER Path - A file name to parse - - .EXAMPLE - $fileContent = Get-FileContent -Path 'c:\file.txt' - #> - [CmdletBinding()] - [OutputType([System.String[]])] - param ( - [parameter(Mandatory = $true)] - [string]$Path - ) - - try { - - $fileContent = Get-Content -Path $Path - - $parserErrors = $null - - if ([string]::IsNullOrEmpty($fileContent)) { - $parsedFileFunctions = @() - } - else { - $parsedFileFunctions = [System.Management.Automation.PSParser]::Tokenize($fileContent, [ref]$parserErrors) - } - - $parsedFunctions = ($parsedFileFunctions | Where-Object { $_.Type -eq "Keyword" -and $_.Content -like 'function' }) - - if ($parsedFunctions.Count -gt 1) { - throw "Too many functions in file, file is invalid" - } - - if ($parsedFunctions.Count -eq 1) { - - if ($fileContent.Count -gt 1) { - - foreach ($function in $parsedFunctions) { - - $startLine = ($function.StartLine) - - for ($line = $fileContent.Count; $line -gt $function.StartLine; $line--) { - - if ($fileContent[$line] -like "*}*") { - - $endLine = $line - break - - } - - } - - for ($line = $startLine; $line -lt $endLine; $line++) { - - $parsedFileContent += $fileContent[$line] - - if ($line -ne ($fileContent.Count - 1)) { - $parsedFileContent += "`r`n" - } - - } - - } - - } - else { - - [int]$startBracket = $fileContent.IndexOf('{') - [int]$endBracket = $fileContent.LastIndexOf('}') - - $parsedFileContent = $fileContent.substring($startBracket + 1, $endBracket - 1 - $startBracket) - - } - } - else { - - if ($fileContent.Count -gt 1) { - - for ($line = 0; $line -lt $fileContent.Count; $line++) { - - $parsedFileContent += $fileContent[$line] - - if ($line -ne ($fileContent.Count - 1)) { - $parsedFileContent += "`r`n" - } - - } - - } - else { - - $parsedFileContent = $fileContent - - } - - } - - } - catch { - throw - } - - return $parsedFileContent - -} - -function Get-FileList { - <# - .SYNOPSIS - Return a list of files - - .DESCRIPTION - Return a list of files from the specified path matching the passed extension - - .PARAMETER Path - A string containing the path - - .PARAMETER Extension - A string containing the extension - - .PARAMETER Recurse - A switch specifying whether or not to recursively search the path specified - - .EXAMPLE - $files = Get-FileList -Path 'c:\folder' -Extension ".ps1" - - .EXAMPLE - $files = Get-FileList -Path 'c:\folder' -Extension ".ps1" -Recurse - #> - [CmdletBinding()] - [OutputType([System.Object[]])] - param ( - [parameter(Mandatory = $true)] - [string]$Path, - [parameter(Mandatory = $true)] - [string]$Extension, - [parameter(Mandatory = $false)] - [switch]$Recurse - ) - - $Extension = $Extension - - $FileNameArray = @() - - if (Test-Path -Path $Path) { - - $gciSplat = @{ - 'Path' = $Path - 'Exclude' = "*.Tests.*" - } - if ($PSBoundParameters.ContainsKey('Recurse')) { - $gciSplat.Add('Recurse', $true) - } - - $SelectedFilesArray = Get-ChildItem @gciSplat | Where-Object { $_.Extension -eq $Extension } | Select-Object -Property FullName - $SelectedFilesArray | ForEach-Object { $FileNameArray += [string]$_.FullName } - - } - - return $FileNameArray - -} - -function Get-FunctionCount { - <# - .SYNOPSIS - Return the count of functions within Module and its Manifest - - .DESCRIPTION - Return the count of functions in the Module and Manifest and whether they appear in their counterpart. - e.g. Whether the functions in the manifest appear in the module and vice versa - - .PARAMETER ModulePath - A string containing the Module filename - - .PARAMETER ManifestPath - A string containing the Manifest filename - - .EXAMPLE - ($ExportedCommandsCount, $CommandFoundInModuleCount, $CommandInModuleCount, $CommandFoundInManifestCount) = Get-FunctionCount -ModulePath $ModulePath -ManifestPath $ManifestPath - - #> - [CmdletBinding()] - [OutputType([Int[]])] - param ( - [parameter(Mandatory = $true)] - [string]$ModulePath, - [parameter(Mandatory = $true)] - [string]$ManifestPath - ) - - try { - if (Test-Path -Path $ManifestPath) { - $ExportedCommands = (Test-ModuleManifest -Path $ManifestPath -ErrorAction Stop).ExportedCommands - $ExportedCommandsCount = $ExportedCommands.Count - } - else { - throw "Manifest file doesn't exist" - } - } - catch { - $ExportedCommands = @() - $ExportedCommandsCount = 0 - } - - try { - if (Test-Path -Path $ModulePath) { - ($ParsedModule, $ParserErrors) = Get-ParsedFile -Path $ModulePath - } - else { - throw "Module file doesn't exist" - } - } - catch { - $ParsedModule = @() - $ParserErrors = 1 - } - - $CommandFoundInModuleCount = 0 - $CommandFoundInManifestCount = 0 - $CommandInModuleCount = 0 - - if ( -not ([string]::IsNullOrEmpty($ParsedModule))) { - - foreach ($ExportedCommand in $ExportedCommands.Keys) { - - if ( ($ParsedModule | Where-Object { $_.Type -eq "CommandArgument" -and $_.Content -eq $ExportedCommand })) { - - $CommandFoundInModuleCount++ - - } - - } - - $functionNames = @() - - $functionKeywords = ($ParsedModule | Where-Object { $_.Type -eq "Keyword" -and $_.Content -eq "function" }) - $functionKeywords | ForEach-Object { - - $functionLineNo = $_.StartLine - $functionNames += ($ParsedModule | Where-Object { $_.Type -eq "CommandArgument" -and $_.StartLine -eq $functionLineNo }) - - } - } - - if ($ExportedCommandsCount -ge 1) { - - foreach ($function in $functionNames) { - - $CommandInModuleCount++ - if ($ExportedCommands.ContainsKey($function.Content)) { - - $CommandFoundInManifestCount++ - - } - - } - - } - - return ($ExportedCommandsCount, $CommandFoundInModuleCount, $CommandInModuleCount, $CommandFoundInManifestCount) - -} - -function Get-ParsedContent { - <# - .SYNOPSIS - Get the tokenized content of the passed data - - .DESCRIPTION - Get and return the tokenized content of the passed PowerShell script content - - .PARAMETER Content - A string containing PowerShell script content - - .EXAMPLE - ($ParsedModule, $ParserErrorCount) = Get-ParsedContent -Content $fileContent - #> - [CmdletBinding()] - [OutputType([System.Object[]], [System.Void])] - param ( - [parameter(Mandatory = $true)] - [string]$Content - ) - - if (-not ([string]::IsNullOrEmpty($Content))) { - $ParserErrors = $null - $ParsedModule = [System.Management.Automation.PSParser]::Tokenize($Content, [ref]$ParserErrors) - - return $ParsedModule, ($ParserErrors.Count) - } - -} - -function Get-ParsedFile { - <# - .SYNOPSIS - Get the tokenized content of the passed file - - .DESCRIPTION - Get and return the tokenized content of the passed PowerShell file - - .PARAMETER Path - A string containing PowerShell filename - - .EXAMPLE - ($ParsedModule, $ParserErrors) = Get-ParsedFile -Path $ModuleFile - - #> - [CmdletBinding()] - [OutputType([System.Object[]])] - param ( - [parameter(Mandatory = $true)] - [string]$Path - ) - - try { - if (-not(Test-Path -Path $Path)) { - throw "$Path doesn't exist" - } - } - catch { - throw $_ - } - - $fileContent = Get-Content -Path $Path -Raw - - ($ParsedModule, $ParserErrorCount) = Get-ParsedContent -Content $fileContent - - return $ParsedModule, $ParserErrorCount - -} - -function Get-ScriptParameter { - <# - .SYNOPSIS - Get a list of the parameters in the param block - - .DESCRIPTION - Create a list of the parameters, and their type (if available) from the param block - - .PARAMETER Content - A string containing the text of the script - - .EXAMPLE - $parameterVariables = Get-ScriptParameter -Content $Content - #> - [CmdletBinding()] - [OutputType([System.Exception], [HashTable])] - param ( - [parameter(Mandatory = $true)] - [String]$Content - ) - - try { - - $parsedScript = [System.Management.Automation.Language.Parser]::ParseInput($Content, [ref]$null, [ref]$null) - - if ([string]::IsNullOrEmpty($parsedScript.ParamBlock)) { - throw "No parameters found" - } - - [string]$paramBlock = $parsedScript.ParamBlock - - ($ParsedContent, $ParserErrorCount) = Get-ParsedContent -Content $paramBlock - - $paramBlockArray = ($paramBlock -split '\n').Trim() - - $parametersFound = @{} - - for ($line = 0; $line -le $paramBlockArray.Count; $line++) { - - $paramToken = @($ParsedContent | Where-Object { $_.StartLine -eq $line }) - - foreach ($token in $paramToken) { - - if ($token.Type -eq 'Attribute' -and $token.Content -eq "Parameter") { - - break - } - - if ($token.Type -eq 'Type') { - - $foundType = $token.Content - - } - - if ($token.Type -eq 'Variable') { - - $parametersFound[$token.Content] = $foundType - $foundType = $null - break - - } - - } - - } - - return $parametersFound - - } - catch { - - throw $_.Exception.Message - - } - -} - -function Get-TagList { - <# - .SYNOPSIS - Return a list of test tags - - .DESCRIPTION - Return a list of test tags from the module and script checks file - - .EXAMPLE - ($moduleTags, $scriptTags) = Get-TagList - - #> - [CmdletBinding()] - [OutputType([System.Object[]])] - param ( - ) - - $moduleTags = @() - $scriptTags = @() - - $modulePath = (Get-Module -Name 'PSQualityCheck').ModuleBase - - $checksPath = (Join-Path -Path $modulePath -ChildPath "Checks") - - Get-Content -Path (Join-Path -Path $checksPath -ChildPath "Module.Tests.ps1") -Raw | ForEach-Object { - $ast = [Management.Automation.Language.Parser]::ParseInput($_, [ref]$null, [ref]$null) - $ast.FindAll( { - param($node) - $node -is [System.Management.Automation.Language.CommandAst] -and - $node.CommandElements[0].Value -eq "Describe" -and - $node.CommandElements[2] -is [System.Management.Automation.Language.CommandParameterAst] -and - $node.CommandElements[2].ParameterName -eq "Tag" - }, $true) | ForEach-Object { - $moduleTags += $_.CommandElements[3].Value - } - $ast.FindAll( { - param($node) - $node -is [System.Management.Automation.Language.CommandAst] -and - $node.CommandElements[0].Value -eq "It" -and - $node.CommandElements[2] -is [System.Management.Automation.Language.CommandParameterAst] -and - $node.CommandElements[2].ParameterName -eq "Tag" - }, $true) | ForEach-Object { - $moduleTags += $_.CommandElements[3].Value - } - } - - Get-Content -Path (Join-Path -Path $checksPath -ChildPath "Script.Tests.ps1") -Raw | ForEach-Object { - $ast = [Management.Automation.Language.Parser]::ParseInput($_, [ref]$null, [ref]$null) - $ast.FindAll( { - param($node) - $node -is [System.Management.Automation.Language.CommandAst] -and - $node.CommandElements[0].Value -eq "Describe" -and - $node.CommandElements[2] -is [System.Management.Automation.Language.CommandParameterAst] -and - $node.CommandElements[2].ParameterName -eq "Tag" - }, $true) | ForEach-Object { - $scriptTags += $_.CommandElements[3].Value - } - $ast.FindAll( { - param($node) - $node -is [System.Management.Automation.Language.CommandAst] -and - $node.CommandElements[0].Value -eq "It" -and - $node.CommandElements[2] -is [System.Management.Automation.Language.CommandParameterAst] -and - $node.CommandElements[2].ParameterName -eq "Tag" - }, $true) | ForEach-Object { - $scriptTags += $_.CommandElements[3].Value - } - } - - return $moduleTags, $scriptTags - -} - -function Get-Token { - <# - .SYNOPSIS - Get token(s) from the tokenized output - - .DESCRIPTION - Get token(s) from the tokenized output matching the passed Type and Content - - .PARAMETER ParsedContent - A string array containing the Tokenized data - - .PARAMETER Type - The token type to be found - - .PARAMETER Content - The token content (or value) to be found - - .EXAMPLE - $outputTypeToken = (Get-Token -ParsedContent $ParsedFile -Type "Attribute" -Content "OutputType") - #> - [CmdletBinding()] - [OutputType([System.Object[]])] - param ( - [parameter(Mandatory = $true)] - [System.Object[]]$ParsedContent, - [parameter(Mandatory = $true)] - [string]$Type, - [parameter(Mandatory = $true)] - [string]$Content - ) - - $token = Get-TokenMarker -ParsedContent $ParsedContent -Type $Type -Content $Content - - $tokens = Get-TokenComponent -ParsedContent $ParsedContent -StartLine $token.StartLine - - return $tokens - -} - -function Get-TokenComponent { - <# - .SYNOPSIS - Get all the tokens components from a single line - - .DESCRIPTION - Get all the tokens components from a single line in the tokenized content - - .PARAMETER ParsedContent - A string array containing the tokenized content - - .PARAMETER StartLine - A integer of the starting line to parse - - .EXAMPLE - $tokens = Get-TokenComponent -ParsedContent $ParsedContent -StartLine 10 - #> - [CmdletBinding()] - [OutputType([System.Object[]])] - param ( - [parameter(Mandatory = $true)] - [System.Object[]]$ParsedContent, - [parameter(Mandatory = $true)] - [int]$StartLine - ) - - #* This is just to satisfy the PSScriptAnalyzer - #* which can't find the variables in the 'Where-Object' clause (even though it's valid) - $StartLine = $StartLine - - $tokenComponents = @($ParsedContent | Where-Object { $_.StartLine -eq $StartLine }) - - return $tokenComponents - -} - -function Get-TokenMarker { - <# - .SYNOPSIS - Gets token from the tokenized output - - .DESCRIPTION - Gets single token from the tokenized output matching the passed Type and Content - - .PARAMETER ParsedContent - A string array containing the Tokenized data - - .PARAMETER Type - The token type to be found - - .PARAMETER Content - The token content (or value) to be found - - .EXAMPLE - $token = Get-TokenMarker -ParsedContent $ParsedContent -Type $Type -Content $Content - #> - [CmdletBinding()] - [OutputType([System.Object[]])] - param ( - [parameter(Mandatory = $true)] - [System.Object[]]$ParsedContent, - [parameter(Mandatory = $true)] - [string]$Type, - [parameter(Mandatory = $true)] - [string]$Content - ) - - #* This is just to satisfy the PSScriptAnalyzer - #* which can't find the variables in the 'Where-Object' clause (even though it's valid) - $Type = $Type - $Content = $Content - - $token = @($ParsedContent | Where-Object { $_.Type -eq $Type -and $_.Content -eq $Content }) - - return $token - -} - -function Test-HelpTokensCountIsValid { - <# - .SYNOPSIS - Check that help tokens count is valid - - .DESCRIPTION - Check that the help tokens count is valid by making sure that they appear between Min and Max times - - .PARAMETER HelpTokens - A array of tokens containing the tokens of the Help Comment - - .PARAMETER HelpRulesPath - Path to the HelpRules file - - .EXAMPLE - Test-HelpTokensCountIsValid -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" - - .NOTES - This function will only check the Min/Max counts of required help tokens - #> - [CmdletBinding()] - [OutputType([System.Exception], [System.Void])] - param ( - [parameter(Mandatory = $true)] - [HashTable]$HelpTokens, - - [parameter(Mandatory = $true)] - [string]$HelpRulesPath - ) - - try { - - $helpRules = Import-PowerShellDataFile -Path $HelpRulesPath - - $tokenFound = @{} - for ($order = 1; $order -le $HelpRules.Count; $order++) { - $helpRuleIndex = [string]$order - $token = $HelpRules.$helpRuleIndex.Key - $tokenFound[$token] = $false - } - - $tokenErrors = @() - - foreach ($key in $HelpTokens.Keys) { - - for ($order = 1; $order -le $HelpRules.Count; $order++) { - - $helpRuleIndex = [string]$order - $token = $HelpRules.$helpRuleIndex - - if ( $token.Key -eq $key ) { - - $tokenFound[$key] = $true - - if ($HelpTokens.$key.Count -lt $token.MinOccurrences -or - $HelpTokens.$key.Count -gt $token.MaxOccurrences -and - $token.Required -eq $true) { - - $tokenErrors += "Found $(($HelpTokens.$key).Count) occurrences of '$key' which is not between $($token.MinOccurrences) and $($token.MaxOccurrences). " - - } - - } - - } - - } - - if ($tokenErrors.Count -ge 1) { - - throw $tokenErrors - - } - - } - catch { - - throw $_.Exception.Message - - } - -} - -function Test-HelpTokensParamsMatch { - <# - .SYNOPSIS - Checks to see whether the parameters and help PARAMETER statements match - - .DESCRIPTION - Checks to see whether the parameters in the param block and in the help PARAMETER statements exist in both locations - - .PARAMETER HelpTokens - A array of tokens containing the tokens of the Help Comment - - .PARAMETER ParameterVariables - A object containing the parameters from the param block - - .EXAMPLE - Test-HelpTokensParamsMatch -HelpTokens $HelpTokens -ParameterVariables $ParameterVariables - #> - [CmdletBinding()] - [OutputType([System.Exception], [System.String[]])] - param ( - [parameter(Mandatory = $true)] - [HashTable]$HelpTokens, - [parameter(Mandatory = $true)] - [PSCustomObject]$ParameterVariables - ) - - try { - - $foundInHelpErrors = @() - $foundInParamErrors = @() - - foreach ($key in $ParameterVariables.Keys) { - - $foundInHelp = $false - - foreach ($token in $HelpTokens.".PARAMETER") { - - if ($key -eq $token.Name) { - - $foundInHelp = $true - break - - } - - } - - if ($foundInHelp -eq $false) { - - $foundInHelpErrors += "Parameter block variable '$key' was not found in help. " - - } - - } - - foreach ($token in $HelpTokens.".PARAMETER") { - - $foundInParams = $false - - foreach ($key in $ParameterVariables.Keys) { - - if ($key -eq $token.Name) { - - $foundInParams = $true - break - - } - - } - - if ($foundInParams -eq $false) { - - $foundInParamErrors += "Help defined variable '$($token.Name)' was not found in parameter block definition. " - - } - - } - - if ($foundInHelpErrors.Count -ge 1 -or $foundInParamErrors.Count -ge 1) { - - $allErrors = $foundInHelpErrors + $foundInParamErrors - throw $allErrors - - } - - } - catch { - - throw $_.Exception.Message - - } - -} - -function Test-HelpTokensTextIsValid { - <# - .SYNOPSIS - Check that Help Tokens text is valid - - .DESCRIPTION - Check that the Help Tokens text is valid by making sure that they its not empty - - .PARAMETER HelpTokens - A array of tokens containing the tokens of the Help Comment - - .EXAMPLE - Test-HelpTokensTextIsValid -HelpTokens $HelpTokens - #> - [CmdletBinding()] - [OutputType([System.Exception], [System.Void])] - param ( - [parameter(Mandatory = $true)] - [HashTable]$HelpTokens - ) - - try { - - $tokenErrors = @() - - foreach ($key in $HelpTokens.Keys) { - - $tokenCount = @($HelpTokens.$key) - - for ($loop = 0; $loop -lt $tokenCount.Count; $loop++) { - - $token = $HelpTokens.$key[$loop] - - if ([string]::IsNullOrWhitespace($token.Text)) { - - $tokenErrors += "Found '$key' does not have any text. " - - } - - } - - } - - if ($tokenErrors.Count -ge 1) { - - throw $tokenErrors - - } - - } - catch { - - throw $_.Exception.Message - - } - -} - -function Test-ImportModuleIsValid { - <# - .SYNOPSIS - Test that the Import-Module commands are valid - - .DESCRIPTION - Test that the Import-Module commands contain a -Name parameter, and one of RequiredVersion, MinimumVersion or MaximumVersion - - .PARAMETER ParsedContent - An object containing the source file parsed into its Tokenizer components - - .PARAMETER ImportModuleTokens - An object containing the Import-Module tokens found - - .EXAMPLE - TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens - #> - [CmdletBinding()] - [OutputType([System.Exception], [System.Void])] - param ( - [parameter(Mandatory = $true)] - [System.Object[]]$ParsedContent, - [parameter(Mandatory = $true)] - [System.Object[]]$ImportModuleTokens - ) - - try { - - $errString = "" - - foreach ($token in $importModuleTokens) { - - $importModuleStatement = Get-TokenComponent -ParsedContent $ParsedContent -StartLine $token.StartLine - - $name = ($importModuleStatement | Where-Object { $_.Type -eq "CommandArgument" } | Select-Object -First 1).Content - if ($null -eq $name) { - - $name = ($importModuleStatement | Where-Object { $_.Type -eq "String" } | Select-Object -First 1).Content - - } - - if (-not($importModuleStatement | Where-Object { $_.Type -eq "CommandParameter" -and $_.Content -eq "-Name" })) { - - $errString += "Import-Module for '$name' : Missing -Name parameter keyword. " - - } - - if (-not($importModuleStatement | Where-Object { $_.Type -eq "CommandParameter" -and - ( $_.Content -eq "-RequiredVersion" -or $_.Content -eq "-MinimumVersion" -or $_.Content -eq "-MaximumVersion" ) - })) { - - $errString += "Import-Module for '$name' : Missing -RequiredVersion, -MinimumVersion or -MaximumVersion parameter keyword. " - - } - - } - - if (-not ([string]::IsNullOrEmpty($errString))) { - - throw $errString - - } - - } - catch { - - throw $_.Exception.Message - - } - -} - -function Test-ParameterVariablesHaveType { - <# - .SYNOPSIS - Check that all the passed parameters have a type variable set. - - .DESCRIPTION - Check that all the passed parameters have a type variable set. - - .PARAMETER ParameterVariables - A HashTable containing the parameters from the param block - - .EXAMPLE - Test-ParameterVariablesHaveType -ParameterVariables $ParameterVariables - #> - [CmdletBinding()] - [OutputType([System.Exception], [System.Void])] - param ( - [parameter(Mandatory = $true)] - [HashTable]$ParameterVariables - ) - - $variableErrors = @() - - try { - - foreach ($key in $ParameterVariables.Keys) { - - if ([string]::IsNullOrEmpty($ParameterVariables.$key)) { - - $variableErrors += "Parameter '$key' does not have a type defined." - - } - - } - - if ($variableErrors.Count -ge 1) { - - throw $variableErrors - } - - } - catch { - - throw $_.Exception.Message - - } - -} - -function Test-RequiredToken { - <# - .SYNOPSIS - Check that help tokens contain required tokens - - .DESCRIPTION - Check that the help comments contain tokens that are specified in the external verification data file - - .PARAMETER HelpTokens - A array of tokens containing the tokens of the Help Comment - - .PARAMETER HelpRulesPath - Path to the HelpRules file - - .EXAMPLE - Test-RequiredToken -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" - #> - [CmdletBinding()] - [OutputType([System.Exception], [System.Void])] - param ( - [parameter(Mandatory = $true)] - [HashTable]$HelpTokens, - - [parameter(Mandatory = $true)] - [string]$HelpRulesPath - ) - - try { - - $helpRules = Import-PowerShellDataFile -Path $HelpRulesPath - - $tokenErrors = @() - - for ($order = 1; $order -le $HelpRules.Count; $order++) { - - $helpRuleIndex = [string]$order - $token = $HelpRules.$helpRuleIndex - - if ($token.Key -notin $HelpTokens.Keys ) { - - if ($token.Required -eq $true) { - - $tokenErrors += $token.Key - - } - - } - - } - - if ($tokenErrors.Count -ge 1) { - throw "Missing required token(s): $tokenErrors" - } - - } - catch { - - throw $_.Exception.Message - - } - -} - -function Test-UnspecifiedToken { - <# - .SYNOPSIS - Check that help tokens do not contain unspecified tokens - - .DESCRIPTION - Check that the help comments do not contain tokens that are not specified in the external verification data file - - .PARAMETER HelpTokens - A array of tokens containing the tokens of the Help Comment - - .PARAMETER HelpRulesPath - Path to the HelpRules file - - .EXAMPLE - Test-UnspecifiedToken -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" - #> - [CmdletBinding()] - [OutputType([System.Exception], [System.Void])] - param ( - [parameter(Mandatory = $true)] - [HashTable]$HelpTokens, - - [parameter(Mandatory = $true)] - [string]$HelpRulesPath - ) - - try { - - $helpRules = Import-PowerShellDataFile -Path $HelpRulesPath - - $tokenErrors = @() - $helpTokensKeys = @() - - # Create an array of the help element rules elements - for ($order = 1; $order -le $helpRules.Count; $order++) { - - $helpRuleIndex = [string]$order - $token = $helpRules.$helpRuleIndex - - $helpTokensKeys += $token.key - - } - - # search through the found tokens and match them against the rules - foreach ($key in $helpTokens.Keys) { - - if ( $key -notin $helpTokensKeys ) { - - $tokenErrors += $key - - } - - } - - if ($tokenErrors.Count -ge 1) { - throw "Found extra, non-specified, token(s): $tokenErrors" - } - - } - catch { - - throw $_.Exception.Message - - } - -} - diff --git a/PSQualityCheck.psd1 b/PSQualityCheck.psd1 deleted file mode 100644 index b2a6592..0000000 --- a/PSQualityCheck.psd1 +++ /dev/null @@ -1,133 +0,0 @@ -# -# Module manifest for module 'PSQualityCheck' -# -# Generated by: Andrew Davidson -# -# Generated on: 03/02/2021 -# - -@{ - -# Script module or binary module file associated with this manifest. -RootModule = 'PSQualityCheck.psm1' - -# Version number of this module. -ModuleVersion = '1.3.1' - -# Supported PSEditions -# CompatiblePSEditions = @() - -# ID used to uniquely identify this module -GUID = '9daebff2-9a44-48e4-9d4b-bed18c3c8e4b' - -# Author of this module -Author = 'Andrew Davidson' - -# Company or vendor of this module -CompanyName = 'Andrew Davidson' - -# Copyright statement for this module -Copyright = '(c) Andrew Davidson. All rights reserved.' - -# Description of the functionality provided by this module -Description = 'This module interfaces to a set of Pester tests that enable the enforcement of quality controls rules on PowerShell scripts and modules.' - -# Minimum version of the PowerShell engine required by this module -PowerShellVersion = '5.0' - -# Name of the PowerShell host required by this module -# PowerShellHostName = '' - -# Minimum version of the PowerShell host required by this module -# PowerShellHostVersion = '' - -# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. -# DotNetFrameworkVersion = '' - -# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. -# ClrVersion = '' - -# 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 = @() - -# 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 = @() - -# Type files (.ps1xml) to be loaded when importing this module -# TypesToProcess = @() - -# Format files (.ps1xml) to be loaded when importing this module -# FormatsToProcess = @() - -# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess -NestedModules = @('PSQualityCheck.Functions.psd1') - -# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. -FunctionsToExport = 'Invoke-PSQualityCheck' - -# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. -CmdletsToExport = @() - -# Variables to export from this module -# VariablesToExport = @() - -# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. -AliasesToExport = @() - -# DSC resources to export from this module -# DscResourcesToExport = @() - -# List of all modules packaged with this module -# ModuleList = @() - -# 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 = @{ - - PSData = @{ - - # Tags applied to this module. These help with module discovery in online galleries. - Tags = 'powershell', 'powershell-module', 'quality', 'quality-check', 'tests', - 'pester', 'pester-tests' - - # A URL to the license for this module. - LicenseUri = 'https://github.com/andrewrdavidson/PSQualityCheck/blob/main/LICENSE' - - # A URL to the main website for this project. - ProjectUri = 'https://github.com/andrewrdavidson/PSQualityCheck' - - # A URL to an icon representing this module. - # IconUri = '' - - # ReleaseNotes of this module - # ReleaseNotes = '' - - # Prerelease string of this module - # Prerelease = '' - - # Flag to indicate whether the module requires explicit user acceptance for install/update/save - # RequireLicenseAcceptance = $false - - # External dependent modules of this module - # ExternalModuleDependencies = @() - - } # End of PSData hashtable - -} # End of PrivateData hashtable - -# HelpInfo URI of this module -HelpInfoURI = 'https://github.com/andrewrdavidson/PSQualityCheck/wiki' - -# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. -# DefaultCommandPrefix = '' - -} - diff --git a/PSQualityCheck.psm1 b/PSQualityCheck.psm1 deleted file mode 100644 index ac25e35..0000000 --- a/PSQualityCheck.psm1 +++ /dev/null @@ -1,562 +0,0 @@ -function Invoke-PSQualityCheck { - <# - .SYNOPSIS - Invoke the PSQualityCheck tests - - .DESCRIPTION - Invoke a series of Pester-based quality tests on the passed files - - .PARAMETER Path - A string array containing paths to check for testable files - - .PARAMETER File - A string array containing testable files - - .PARAMETER Recurse - A switch specifying whether or not to recursively search the path specified - - .PARAMETER ScriptAnalyzerRulesPath - A path the the external PSScriptAnalyzer rules - - .PARAMETER ShowCheckResults - Show a summary of the Check results at the end of processing - Note: this cannot be used with -Passthru - - .PARAMETER ExportCheckResults - Exports the Check results at the end of processing to file - - .PARAMETER Passthru - Returns the Check results objects back to the caller - Note: this cannot be used with -ShowCheckResults - - .PARAMETER PesterConfiguration - A Pester configuration object to allow configuration of Pester - - .PARAMETER Include - An array of test tags to run - - .PARAMETER Exclude - An array of test tags to not run - - .PARAMETER ProjectPath - A path to the root of a Project - - .PARAMETER HelpRulesPath - A path to the HelpRules parameter file - - .EXAMPLE - Invoke-PSQualityCheck -Path 'C:\Scripts' - - This will call the quality checks on single path - - .EXAMPLE - Invoke-PSQualityCheck -Path 'C:\Scripts' -Recurse - - This will call the quality checks on single path and sub folders - - .EXAMPLE - Invoke-PSQualityCheck -Path @('C:\Scripts', 'C:\MoreScripts') - - This will call the quality checks with multiple paths - - .EXAMPLE - Invoke-PSQualityCheck -File 'C:\Scripts\Script.ps1' - - This will call the quality checks with single script file - - .EXAMPLE - Invoke-PSQualityCheck -File 'C:\Scripts\Script.psm1' - - This will call the quality checks with single module file - - .EXAMPLE - Invoke-PSQualityCheck -File 'C:\Scripts\Script.psd1' - - This will call the quality checks with single datafile file - Note: The datafile test will fail as it is not a file that is accepted for testing - - .EXAMPLE - Invoke-PSQualityCheck -File @('C:\Scripts\Script.ps1','C:\Scripts\Script2.ps1') - - This will call the quality checks with multiple files. Files can be either scripts or modules - - .EXAMPLE - Invoke-PSQualityCheck -File 'C:\Scripts\Script.ps1' -ScriptAnalyzerRulesPath 'C:\ScriptAnalyzerRulesPath' - - This will call the quality checks with single file and the extra PSScriptAnalyzer rules - - .EXAMPLE - Invoke-PSQualityCheck -Path 'C:\Scripts' -ShowCheckResults - - This will display a summary of the checks performed (example below uses sample data): - - Name Files Tested Total Passed Failed Skipped - ---- ------------ ----- ------ ------ ------- - Module Tests 2 14 14 0 0 - Extracting functions 2 2 2 0 0 - Extracted function script tests 22 330 309 0 21 - Total 24 346 325 0 21 - - For those who have spotted that the Total files tested isn't a total of the rows above, this is because the Module Tests and Extracting function Tests operate on the same file and are then not counted twice - - .LINK - Website: https://github.com/andrewrdavidson/PSQualityCheck - SonarQube rules are available here: https://github.com/indented-automation/ScriptAnalyzerRules - - #> - [CmdletBinding()] - [OutputType([System.Void], [HashTable], [System.Object[]])] - param ( - [Parameter(Mandatory = $true, ParameterSetName = "Path")] - [String[]]$Path, - [Parameter(Mandatory = $true, ParameterSetName = "File")] - [String[]]$File, - [Parameter(Mandatory = $true, ParameterSetName = "ProjectPath")] - [String]$ProjectPath, - - [Parameter(Mandatory = $false, ParameterSetName = "Path")] - [switch]$Recurse, - - [Parameter(Mandatory = $false)] - [String[]]$ScriptAnalyzerRulesPath, - - [switch]$ShowCheckResults, - - [switch]$ExportCheckResults, - - [switch]$Passthru, - - [Parameter(Mandatory = $false)] - [System.Object]$PesterConfiguration, - - [Parameter(Mandatory = $false)] - [String[]]$Include, - - [Parameter(Mandatory = $false)] - [String[]]$Exclude, - - [Parameter(Mandatory = $false)] - [String]$HelpRulesPath - - ) - - Set-StrictMode -Version Latest - - # External Modules - Import-Module -Name 'Pester' -MinimumVersion '5.1.0' -Force - Import-Module -Name 'PSScriptAnalyzer' -MinimumVersion '1.19.1' -Force - - $modulePath = (Get-Module -Name 'PSQualityCheck').ModuleBase - - # Validate any incoming parameters for clashes - if ($PSBoundParameters.ContainsKey('ShowCheckResults') -and $PSBoundParameters.ContainsKey('Passthru')) { - - Write-Error "-ShowCheckResults and -Passthru cannot be used at the same time" - break - - } - - $scriptsToTest = @() - $modulesToTest = @() - - $projectResults = $null - $moduleResults = $null - $extractionResults = $null - $extractedScriptResults = $null - $scriptResults = $null - - if ($PSBoundParameters.ContainsKey('HelpRulesPath')) { - - if ( -not (Test-Path -Path $HelpRulesPath)) { - - Write-Error "-HelpRulesPath does not exist" - break - - } - - } - else { - - $helpRulesPath = (Join-Path -Path $modulePath -ChildPath "Checks\HelpRules.psd1") - - } - - if ($PSBoundParameters.ContainsKey('PesterConfiguration') -and $PesterConfiguration -is [PesterConfiguration]) { - - # left here so that we can over-ride passed in object with values we require - - } - else { - # Default Pester Parameters - $PesterConfiguration = [PesterConfiguration]::Default - $PesterConfiguration.Run.Exit = $false - $PesterConfiguration.CodeCoverage.Enabled = $false - $PesterConfiguration.Output.Verbosity = 'Detailed' - $PesterConfiguration.Run.PassThru = $true - $PesterConfiguration.Should.ErrorAction = 'Stop' - } - - # Analyse the incoming Path and File parameters and produce a list of Modules and Scripts - if ($PSBoundParameters.ContainsKey('Path') -or $PSBoundParameters.ContainsKey('ProjectPath')) { - - if ($PSBoundParameters.ContainsKey('ProjectPath')) { - - if (Test-Path -Path $ProjectPath) { - - $container1 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Project.Tests.ps1') -Data @{ Path = $ProjectPath } - $PesterConfiguration.Run.Container = $container1 - $projectResults = Invoke-Pester -Configuration $PesterConfiguration - - # setup the rest of the Path based tests - $Path = Join-Path -Path $ProjectPath -ChildPath "Source" - - } - else { - Write-Error "Project Path $ProjectPath does not exist" - } - - } - - if ($Path -isnot [string[]]) { - $Path = @($Path) - } - - foreach ($item in $Path) { - - # Test whether the item is a directory (also tells us if it exists) - if (Test-Path -Path $item -PathType Container) { - - $getFileListSplat = @{ - 'Path' = $item - } - if ($PSBoundParameters.ContainsKey('Recurse') -or - $PSBoundParameters.ContainsKey('ProjectPath')) { - $getFileListSplat.Add('Recurse', $true) - } - - $scriptsToTest += Get-FileList @getFileListSplat -Extension '.ps1' - $modulesToTest += Get-FileList @getFileListSplat -Extension '.psm1' - - } - else { - - Write-Warning -Message "$item is not a directory, skipping" - - } - - } - - } - - if ($PSBoundParameters.ContainsKey('File')) { - - if ($File -isnot [string[]]) { - $File = @($File) - } - - foreach ($item in $File) { - - # Test whether the item is a file (also tells us if it exists) - if (Test-Path -Path $item -PathType Leaf) { - - $itemProperties = Get-ChildItem -Path $item - - switch ($itemProperties.Extension) { - - '.psm1' { - $modulesToTest += $itemProperties - } - - '.ps1' { - $scriptsToTest += $itemProperties - } - - } - - } - else { - - Write-Warning -Message "$item is not a file, skipping" - - } - - } - - } - - # Get the list of test tags from the checks files - if ($PSBoundParameters.ContainsKey('Include') -or - $PSBoundParameters.ContainsKey('Exclude')) { - - - ($moduleTags, $scriptTags) = Get-TagList - $moduleTagsToInclude = @() - $moduleTagsToExclude = @() - $scriptTagsToInclude = @() - $scriptTagsToExclude = @() - $runModuleCheck = $false - $runScriptCheck = $false - - } - else { - $runModuleCheck = $true - $runScriptCheck = $true - } - - if ($PSBoundParameters.ContainsKey('Include')) { - - if ($Include -eq 'All') { - $moduleTagsToInclude = $moduleTags - $scriptTagsToInclude = $scriptTags - $runModuleCheck = $true - $runScriptCheck = $true - } - else { - # Validate tests to include from $Include - $Include | ForEach-Object { - if ($_ -in $moduleTags) { - $moduleTagsToInclude += $_ - $runModuleCheck = $true - #* To satisfy PSScriptAnalyzer - $runModuleCheck = $runModuleCheck - $runScriptCheck = $runScriptCheck - } - } - $Include | ForEach-Object { - if ($_ -in $scriptTags) { - $scriptTagsToInclude += $_ - $runScriptCheck = $true - #* To satisfy PSScriptAnalyzer - $runModuleCheck = $runModuleCheck - $runScriptCheck = $runScriptCheck - } - } - } - $PesterConfiguration.Filter.Tag = $moduleTagsToInclude + $scriptTagsToInclude - - } - - if ($PSBoundParameters.ContainsKey('Exclude')) { - - # Validate tests to exclude from $Exclude - $Exclude | ForEach-Object { - if ($_ -in $moduleTags) { - $moduleTagsToExclude += $_ - $runModuleCheck = $true - #* To satisfy PSScriptAnalyzer - $runModuleCheck = $runModuleCheck - $runScriptCheck = $runScriptCheck - } - } - $Exclude | ForEach-Object { - if ($_ -in $scriptTags) { - $scriptTagsToExclude += $_ - $runScriptCheck = $true - #* To satisfy PSScriptAnalyzer - $runModuleCheck = $runModuleCheck - $runScriptCheck = $runScriptCheck - } - } - $PesterConfiguration.Filter.ExcludeTag = $moduleTagsToExclude + $scriptTagsToExclude - - } - - if ($modulesToTest.Count -ge 1) { - - # Location of files extracted from any passed modules - $extractPath = Join-Path -Path ([IO.Path]::GetTempPath()) -ChildPath (New-Guid).Guid - - if ($runModuleCheck -eq $true) { - - # Run the Module tests on all the valid module files found - $container1 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Module.Tests.ps1') -Data @{ Source = $modulesToTest } - $PesterConfiguration.Run.Container = $container1 - $moduleResults = Invoke-Pester -Configuration $PesterConfiguration - - # Extract all the functions from the modules into individual .ps1 files ready for testing - $container2 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Function-Extraction.Tests.ps1') -Data @{ Source = $modulesToTest; ExtractPath = $extractPath } - $PesterConfiguration.Run.Container = $container2 - $extractionResults = Invoke-Pester -Configuration $PesterConfiguration - - } - - if ($runScriptCheck -eq $true -and (Test-Path -Path $extractPath -ErrorAction SilentlyContinue)) { - - # Get a list of the 'extracted' function scripts .ps1 files - $extractedScriptsToTest = Get-ChildItem -Path $extractPath -Include '*.ps1' -Recurse - - # Run the Script tests against all the extracted functions .ps1 files - $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Script.Tests.ps1') -Data @{ Source = $extractedScriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath; HelpRulesPath = $HelpRulesPath } - $PesterConfiguration.Run.Container = $container3 - $extractedScriptResults = Invoke-Pester -Configuration $PesterConfiguration - } - - # Tidy up and temporary paths that have been used - - if ( Test-Path -Path $ExtractPath -ErrorAction SilentlyContinue) { - Get-ChildItem -Path $ExtractPath -Recurse -ErrorAction SilentlyContinue | Remove-Item -Force -Recurse - Remove-Item $ExtractPath -Force -ErrorAction SilentlyContinue - } - - } - - if ($scriptsToTest.Count -ge 1 -and $runScriptCheck -eq $true) { - - # Run the Script tests against all the valid script files found - $container3 = New-PesterContainer -Path (Join-Path -Path $modulePath -ChildPath 'Checks\Script.Tests.ps1') -Data @{ Source = $scriptsToTest; ScriptAnalyzerRulesPath = $ScriptAnalyzerRulesPath } - $PesterConfiguration.Run.Container = $container3 - $scriptResults = Invoke-Pester -Configuration $PesterConfiguration - - } - - # Show/Export results in the various formats - - if ($PSBoundParameters.ContainsKey('ShowCheckResults')) { - - $qualityCheckResults = @() - $filesTested = $total = $passed = $failed = $skipped = 0 - - if ($null -ne $projectResults) { - $qualityCheckResults += - @{ - 'Test' = 'Project Tests' - 'Files Tested' = 0 - 'Total' = ($projectResults.TotalCount - $projectResults.NotRunCount) - 'Passed' = $projectResults.PassedCount - 'Failed' = $projectResults.FailedCount - 'Skipped' = $projectResults.SkippedCount - } - $filesTested += 0 - $total += ($projectResults.TotalCount - $projectResults.NotRunCount) - $passed += $projectResults.PassedCount - $failed += $projectResults.FailedCount - $skipped += $projectResults.SkippedCount - } - - if ($null -ne $moduleResults) { - $qualityCheckResults += - @{ - 'Test' = 'Module Tests' - 'Files Tested' = $ModulesToTest.Count - 'Total' = ($moduleResults.TotalCount - $moduleResults.NotRunCount) - 'Passed' = $moduleResults.PassedCount - 'Failed' = $moduleResults.FailedCount - 'Skipped' = $moduleResults.SkippedCount - } - $filesTested += $ModulesToTest.Count - $total += ($moduleResults.TotalCount - $moduleResults.NotRunCount) - $passed += $moduleResults.PassedCount - $failed += $moduleResults.FailedCount - $skipped += $moduleResults.SkippedCount - } - - if ($null -ne $extractionResults) { - $qualityCheckResults += - @{ - 'Test' = 'Extracting functions' - 'Files Tested' = $ModulesToTest.Count - 'Total' = ($extractionResults.TotalCount - $extractionResults.NotRunCount) - 'Passed' = $extractionResults.PassedCount - 'Failed' = $extractionResults.FailedCount - 'Skipped' = $extractionResults.SkippedCount - } - $total += ($extractionResults.TotalCount - $extractionResults.NotRunCount) - $passed += $extractionResults.PassedCount - $failed += $extractionResults.FailedCount - $skipped += $extractionResults.SkippedCount - } - - if ($null -ne $extractedScriptResults) { - $qualityCheckResults += - @{ - 'Test' = 'Extracted function script tests' - 'Files Tested' = $extractedScriptsToTest.Count - 'Total' = ($extractedScriptResults.TotalCount - $extractedScriptResults.NotRunCount) - 'Passed' = $extractedScriptResults.PassedCount - 'Failed' = $extractedScriptResults.FailedCount - 'Skipped' = $extractedScriptResults.SkippedCount - } - $filesTested += $extractedScriptsToTest.Count - $total += ($extractedScriptResults.TotalCount - $extractedScriptResults.NotRunCount) - $passed += $extractedScriptResults.PassedCount - $failed += $extractedScriptResults.FailedCount - $skipped += $extractedScriptResults.SkippedCount - } - - if ($null -ne $scriptResults) { - $qualityCheckResults += - @{ - 'Test' = "Script Tests" - 'Files Tested' = $scriptsToTest.Count - 'Total' = ($scriptResults.TotalCount - $scriptResults.NotRunCount) - 'Passed' = $scriptResults.PassedCount - 'Failed' = $scriptResults.FailedCount - 'Skipped' = $scriptResults.SkippedCount - } - $filesTested += $scriptsToTest.Count - $total += ($scriptResults.TotalCount - $scriptResults.NotRunCount) - $passed += $scriptResults.PassedCount - $failed += $scriptResults.FailedCount - $skipped += $scriptResults.SkippedCount - } - - $qualityCheckResults += - @{ - 'Test' = "Total" - 'Files Tested' = $filesTested - 'Total' = $total - 'Passed' = $passed - 'Failed' = $failed - 'Skipped' = $skipped - } - - # This works on PS5 and PS7 - $qualityCheckResults | ForEach-Object { - [PSCustomObject]@{ - 'Test' = $_.Test - 'Files Tested' = $_.'Files Tested' - 'Total' = $_.total - 'Passed' = $_.passed - 'Failed' = $_.failed - 'Skipped' = $_.skipped - } - } | Format-Table -AutoSize - - # This works on PS7 not on PS5 - # $qualityCheckResults | Select-Object Name, 'Files Tested', Total, Passed, Failed, Skipped | Format-Table -AutoSize - - } - - if ($PSBoundParameters.ContainsKey('ExportCheckResults')) { - - $projectResults | Export-Clixml -Path "projectResults.xml" - $moduleResults | Export-Clixml -Path "moduleResults.xml" - $extractionResults | Export-Clixml -Path "extractionResults.xml" - $scriptResults | Export-Clixml -Path "scriptsToTest.xml" - $extractedScriptResults | Export-Clixml -Path "extractedScriptResults.xml" - - } - - if ($PSBoundParameters.ContainsKey('Passthru')) { - - if ($PesterConfiguration.Run.PassThru.Value -eq $true) { - - $resultObject = @{ - 'project' = $projectResults - 'module' = $moduleResults - 'extraction' = $extractionResults - 'script' = $scriptResults - 'extractedscript' = $extractedScriptResults - } - - return $resultObject - - } - else { - Write-Error "Unable to pass back result objects. Passthru not enabled in Pester Configuration object" - } - - } - -} - diff --git a/Source/PSQualityCheck/PSQualityCheck.psd1 b/Source/PSQualityCheck/PSQualityCheck.psd1 new file mode 100644 index 0000000..94e2527 --- /dev/null +++ b/Source/PSQualityCheck/PSQualityCheck.psd1 @@ -0,0 +1,133 @@ +# +# Module manifest for module 'PSQualityCheck' +# +# Generated by: Andrew Davidson +# +# Generated on: 21/04/2021 +# + +@{ + + # Script module or binary module file associated with this manifest. + RootModule = 'PSQualityCheck.psm1' + + # Version number of this module. + ModuleVersion = '2.0.0' + + # Supported PSEditions + # CompatiblePSEditions = @() + + # ID used to uniquely identify this module + GUID = '9daebff2-9a44-48e4-9d4b-bed18c3c8e4b' + + # Author of this module + Author = 'Andrew Davidson' + + # Company or vendor of this module + CompanyName = 'kelrys.com' + + # Copyright statement for this module + Copyright = '(c) Andrew Davidson. All rights reserved.' + + # Description of the functionality provided by this module + Description = 'PSQualityCheck' + + # Minimum version of the PowerShell engine required by this module + PowerShellVersion = '7.0.0' + + # Name of the PowerShell host required by this module + # PowerShellHostName = '' + + # Minimum version of the PowerShell host required by this module + # PowerShellHostVersion = '' + + # Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # DotNetFrameworkVersion = '' + + # Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. + # ClrVersion = '' + + # 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 = @() + + # 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 = @() + + # Type files (.ps1xml) to be loaded when importing this module + # TypesToProcess = @() + + # Format files (.ps1xml) to be loaded when importing this module + # FormatsToProcess = @() + + # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess + # NestedModules = @() + + # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. + FunctionsToExport = '*' + + # Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. + CmdletsToExport = '*' + + # Variables to export from this module + VariablesToExport = '*' + + # Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. + AliasesToExport = '*' + + # DSC resources to export from this module + # DscResourcesToExport = @() + + # List of all modules packaged with this module + # ModuleList = @() + + # 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 = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + # Tags = @() + + # A URL to the license for this module. + # LicenseUri = '' + + # A URL to the main website for this project. + # ProjectUri = '' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + # Prerelease string of this module + # Prerelease = '' + + # Flag to indicate whether the module requires explicit user acceptance for install/update/save + # RequireLicenseAcceptance = $false + + # External dependent modules of this module + # ExternalModuleDependencies = @() + + } # End of PSData hashtable + + } # End of PrivateData hashtable + + # HelpInfo URI of this module + # HelpInfoURI = '' + + # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. + # DefaultCommandPrefix = '' + +} + + diff --git a/Source/PSQualityCheck/build.psd1 b/Source/PSQualityCheck/build.psd1 new file mode 100644 index 0000000..bffba1f --- /dev/null +++ b/Source/PSQualityCheck/build.psd1 @@ -0,0 +1,10 @@ +# Use this file to override the default parameter values used by the `Build-Module` +# command when building the module (see `Get-Help Build-Module -Full` for details). +@{ + ModuleManifest = "PSQualityCheck.psd1" + # Subsequent relative paths are to the ModuleManifest + OutputDirectory = "../../artifacts/PSQualityCheck" + VersionedOutputDirectory = $true + CopyDirectories = @('data', 'bin') +} + diff --git a/Source/PSQualityCheck/data/Extraction.ps1 b/Source/PSQualityCheck/data/Extraction.ps1 new file mode 100644 index 0000000..e27e2eb --- /dev/null +++ b/Source/PSQualityCheck/data/Extraction.ps1 @@ -0,0 +1,52 @@ +param( + [parameter(Mandatory = $true)] + [string[]]$Source, + + [parameter(Mandatory = $true)] + [string]$ExtractPath +) + +BeforeDiscovery { + + $moduleFiles = @() + + $Source | ForEach-Object { + + $fileProperties = (Get-Item -Path $_) + + $moduleFiles += @{ + 'FullName' = $_ + 'Name' = $fileProperties.Name + 'Directory' = $fileProperties.Directory + + } + + } + + if ( Test-Path -Path $ExtractPath ) { + Get-ChildItem -Path $ExtractPath -Recurse -ErrorAction SilentlyContinue | Remove-Item -Force -Recurse + Remove-Item $ExtractPath -Force -ErrorAction SilentlyContinue + } + + New-Item -Path $ExtractPath -ItemType 'Directory' + +} + +Describe "Function Extraction" { + + Context "Script: <_.Name> at <_.Directory>" -Foreach $moduleFiles { + + It "function extraction should complete" { + + { + + $moduleFile = $_.FullName + ExportFunctionsFromModule -Path $moduleFile -ExtractPath $ExtractPath + + } | Should -Not -Throw + + } + + } + +} diff --git a/Source/PSQualityCheck/data/HelpRules.psd1 b/Source/PSQualityCheck/data/HelpRules.psd1 new file mode 100644 index 0000000..40084cb --- /dev/null +++ b/Source/PSQualityCheck/data/HelpRules.psd1 @@ -0,0 +1,73 @@ +@{ + # HashTable of the keys that you want in your help comments + # If the test finds an element that does not appear in this list then the test will fail + + # Possible key elements + # '.SYNOPSIS' + # '.DESCRIPTION' + # '.PARAMETER' + # '.EXAMPLE' + # '.INPUTS' + # '.OUTPUTS' + # '.NOTES' + # '.LINK' + # '.COMPONENT' + # '.ROLE' + # '.FUNCTIONALITY' + # '.FORWARDHELPTARGETNAME' + # '.FORWARDHELPCATEGORY' + # '.REMOTEHELPRUNSPACE' + # '.EXTERNALHELP' + + # If a key is required then it must exist, and have between MinOccurrences and MaxOccurrences count + # The keys will be matched in the numerical sequence below + '1' = @{ + Key = '.SYNOPSIS' + Required = $true + MinOccurrences = 1 + MaxOccurrences = 1 + } + '2' = @{ + Key = '.DESCRIPTION' + Required = $true + MinOccurrences = 1 + MaxOccurrences = 1 + } + '3' = @{ + Key = '.PARAMETER' + Required = $false + MinOccurrences = 0 + MaxOccurrences = 0 + } + '4' = @{ + Key = '.EXAMPLE' + Required = $true + MinOccurrences = 1 + MaxOccurrences = 100 + # MaxOccurrences = 1 + } + '5' = @{ + Key = '.INPUTS' + Required = $false + MinOccurrences = 0 + MaxOccurrences = 0 + } + '6' = @{ + Key = '.OUTPUTS' + Required = $false + MinOccurrences = 0 + MaxOccurrences = 0 + } + '7' = @{ + Key = '.NOTES' + Required = $false + MinOccurrences = 0 + MaxOccurrences = 0 + } + '8' = @{ + Key = '.LINK' + Required = $false + MinOccurrences = 0 + MaxOccurrences = 0 + } +} diff --git a/Source/PSQualityCheck/data/Module.Checks.ps1 b/Source/PSQualityCheck/data/Module.Checks.ps1 new file mode 100644 index 0000000..d42b31d --- /dev/null +++ b/Source/PSQualityCheck/data/Module.Checks.ps1 @@ -0,0 +1,84 @@ +param( + [parameter(Mandatory = $true)] + [string[]]$Source +) + +BeforeDiscovery { + + $moduleFiles = @() + + $Source | ForEach-Object { + + $fileProperties = (Get-Item -Path $_) + + $moduleFiles += @{ + 'FullName' = $_ + 'Name' = $fileProperties.Name + 'Directory' = $fileProperties.Directory + + } + + } + +} + +Describe "Module Tests" -Tag "Module" { + + Context "Script: <_.Name> at <_.Directory>" -ForEach $moduleFiles { + + BeforeEach { + + $moduleFile = $_.FullName + $manifestFile = [Io.Path]::ChangeExtension($_.FullName, 'psd1') + + ($ExportedCommandsCount, $CommandFoundInModuleCount, $CommandInModuleCount, $CommandFoundInManifestCount) = GetFunctionCount -Module $moduleFile -Manifest $manifestFile + + } + + It "Module should exist" -Tag "ModuleShouldExist" { + + $moduleFile | Should -Exist + + } + + It "Manifest should exist" -Tag "ManifestShouldExist" { + + $manifestFile | Should -Exist + + } + + It "Manifest should be valid" -Tag "ValidManifest" { + + $manifest = Test-ModuleManifest -Path $manifestFile -ErrorAction SilentlyContinue + + $manifest | Should -BeOfType [System.Management.Automation.PSModuleInfo] + + } + + It "Manifest should export Functions" -Tag "ModuleShouldExportFunctions" { + + ($ExportedCommandsCount) | Should -BeGreaterOrEqual 1 + + } + + It "Module should have Functions" -Tag "ModuleShouldHaveFunctions" { + + ($CommandInModuleCount) | Should -BeGreaterOrEqual 1 + + } + + It "all exported Functions from Manifest should exist in the Module" -Tag "FunctionsFromManifestExistInModule" { + + ($ExportedCommandsCount -eq $CommandFoundInModuleCount -and $ExportedCommandsCount -ge 1) | Should -BeTrue + + } + + It "all Functions in the Module should exist in Manifest " -Tag "FunctionsFromModuleExistInManifest" { + + ($CommandInModuleCount -eq $CommandFoundInManifestCount -and $CommandFoundInManifestCount -ge 1 ) | Should -BeTrue + + } + + } + +} diff --git a/Source/PSQualityCheck/data/Project.Checks.ps1 b/Source/PSQualityCheck/data/Project.Checks.ps1 new file mode 100644 index 0000000..18acd0b --- /dev/null +++ b/Source/PSQualityCheck/data/Project.Checks.ps1 @@ -0,0 +1,118 @@ +param( + [parameter(Mandatory = $true)] + [string]$Path +) + +BeforeDiscovery { + + $scriptsPath = Join-Path -Path $Path -ChildPath "Scripts" + $sourcePath = Join-Path -Path $Path -ChildPath "Source" + $testPath = Join-Path -Path $Path -ChildPath "Tests" + $unitTestPath = Join-Path -Path $testPath -ChildPath "Unit" + $integrationTestPath = Join-Path -Path $testPath -ChildPath "Integration" + + $moduleList = Get-ChildItem -Path $sourcePath -Directory | Select-Object -Property Name + + $moduleData = @() + + foreach ($module in $moduleList) { + + $moduleFolder = Join-Path -Path $sourcePath -ChildPath $module.Name + $privateFolder = Join-Path -Path $moduleFolder -ChildPath "Private" + $publicFolder = Join-Path -Path $moduleFolder -ChildPath "Public" + $unitTestFolder = Join-Path -Path $unitTestPath -ChildPath $module.Name + $integrationTestFolder = Join-Path -Path $integrationTestPath -ChildPath $module.Name + + $privateModules = Get-ChildItem -Path $privateFolder | Select-Object -Property Name, BaseName, FullName + $publicModules = Get-ChildItem -Path $publicFolder | Select-Object -Property Name, BaseName, FullName + + $moduleData += @{ + 'Name' = $module.Name + 'Path' = $moduleFolder + 'PublicFolder' = $publicFolder + 'PrivateFolder' = $privateFolder + 'UnitTestFolder' = $unitTestFolder + 'IntegrationTestFolder' = $integrationTestFolder + 'Public' = $publicModules + 'Private' = $privateModules + } + } + +} + +Describe "Project Test" -Tag "Project" { + + Context "Checking fixed folder structure" { + + It "should contain <_> folder" -Foreach @($sourcePath, $TestPath, $unitTestPath, $scriptsPath, $integrationTestPath) { + + $_ | Should -Exist + + } + + } + + Context "checking module <_.Name>" -Foreach $moduleData { + + BeforeAll { + + $approvedVerbs = Get-Verb | Select-Object -Property Verb + + } + + It "Private folder exists" { + + $_.PrivateFolder | Should -Exist + + } + + It "Public folder exists" { + + $_.PublicFolder | Should -Exist + + } + + It "Unit Test folder exists" { + + $_.UnitTestFolder | Should -Exist + + } + + Context "Checking Public Script <_.Name>" -ForEach $_.Public { + + It "public script has a unit test" { + + $testFileName = "{0}{1}" -f $_.BaseName, ".Tests.ps1" + $TestScript = Join-Path -Path $unitTestFolder -ChildPath $testFileName + $TestScript | Should -Exist + + } + + It "public script has a valid verb-noun format" { + + ($verb, $noun) = $_.Name -Split "-" + + $verb | Should -Not -BeNullOrEmpty + $noun | Should -Not -BeNullOrEmpty + + $approvedVerbs.Verb -contains $verb | Should -BeTrue + + } + + } + + Context "Checking Private Script <_.Name>" -ForEach $_.Private { + + It "private script has a valid format" { + + $Script = $_.Name + + $Script | Should -Not -Match "-" + + } + + } + + } + +} diff --git a/Source/PSQualityCheck/data/Script.Checks.ps1 b/Source/PSQualityCheck/data/Script.Checks.ps1 new file mode 100644 index 0000000..c1a025e --- /dev/null +++ b/Source/PSQualityCheck/data/Script.Checks.ps1 @@ -0,0 +1,250 @@ +param( + [parameter(Mandatory = $true)] + [string[]]$Source, + + [parameter(Mandatory = $false)] + [string[]]$ScriptAnalyzerRulesPath, + + [parameter(Mandatory = $false)] + [string]$HelpRulesPath + +) + +BeforeDiscovery { + + $scriptFiles = @() + + $Source | ForEach-Object { + + $fileProperties = (Get-Item -Path $_) + + $scriptFiles += @{ + 'FullName' = $_ + 'Name' = $fileProperties.Name + 'Directory' = $fileProperties.Directory + } + + } + + if ( -not ($ScriptAnalyzerRulesPath -is [Array])) { + $ScriptAnalyzerRulesPath = @($ScriptAnalyzerRulesPath) + } + + $rulesPath = @() + + $ScriptAnalyzerRulesPath | ForEach-Object { + + $rulesPath += @{ + 'Path' = $_ + } + + } + +} + +Describe "Script Tests" -Tag "Script" { + + Context "Script: <_.Name> at <_.Directory>" -Foreach $scriptFiles { + + BeforeAll { + + $scriptFile = $_.FullName + $fileContent = GetFileContent -Path $scriptFile + + if (-not([string]::IsNullOrEmpty($fileContent))) { + ($ParsedFile, $ErrorCount) = GetParsedContent -Content $fileContent + } + else { + Write-Warning "File is empty" + $ParsedFile = $null + $ErrorCount = 1 + } + + $helpComments = ($ParsedFile | Where-Object { $_.Type -eq "Comment" } | Select-Object -First 1) + if ([string]::IsNullOrEmpty($helpComments)) { + throw "No help block found" + } + $helpTokens = ConvertHelp -Help $helpComments.Content + + } + + It "check script has valid PowerShell syntax" -Tag "ValidSyntax" { + + $ErrorCount | Should -Be 0 + + } + + It "check help must contain required elements" -Tag "HelpMustContainRequiredElements" { + + { + + TestRequiredToken -HelpTokens $helpTokens -HelpRulesPath $HelpRulesPath + + } | + Should -Not -Throw + + } + + It "check help must not contain unspecified elements" -Tag "HelpMustContainUnspecifiedElements" { + + { + + TestUnspecifiedToken -HelpTokens $helpTokens -HelpRulesPath $HelpRulesPath + + } | + Should -Not -Throw + + } + + It "check help elements text is not empty" -Tag "HelpElementsNotEmpty" { + + { + + TestHelpTokensTextIsValid -HelpTokens $helpTokens + + } | Should -Not -Throw + + } + + It "check help elements Min/Max counts are valid" -Tag "HelpElementsMinMaxCount" { + + { + + TestHelpTokensCountIsValid -HelpTokens $helpTokens -HelpRulesPath $HelpRulesPath + + } | Should -Not -Throw + + } + + It "check script contains [CmdletBinding] attribute" -Tag "ContainsCmdletBinding" { + + $cmdletBindingCount = (@(GetTokenMarker -ParsedContent $ParsedFile -Type "Attribute" -Content "CmdletBinding")).Count + + $cmdletBindingCount | Should -Be 1 + + } + + It "check script contains [OutputType] attribute" -Tag "ContainsOutputType" { + + $outputTypeCount = (@(GetTokenMarker -ParsedContent $ParsedFile -Type "Attribute" -Content "OutputType")).Count + + $outputTypeCount | Should -Be 1 + + } + + It "check script [OutputType] attribute is not empty" -Tag "OutputTypeNotEmpty" { + + $outputTypeToken = (GetToken -ParsedContent $ParsedFile -Type "Attribute" -Content "OutputType") + + $outputTypeValue = @($outputTypeToken | Where-Object { $_.Type -eq "Type" }) + + $outputTypeValue | Should -Not -BeNullOrEmpty + + } + + # Note: Disabled because I'm questioning the validity of the rule. So many function haven't got a need for params + # It "check script contains param attribute" -Tag "ContainsParam" { + + # $paramCount = (@(Get-TokenMarker -ParsedContent $ParsedFile -Type "Keyword" -Content "param")).Count + + # $paramCount | Should -Be 1 + + # } + + It "check script param block variables have type" -Tag "ParamVariablesHaveType" { + + $parameterVariables = GetScriptParameter -Content $fileContent + + if ($parameterVariables.Count -eq 0) { + + Set-ItResult -Inconclusive -Because "No parameters found" + + } + + { + + TestParameterVariablesHaveType -ParameterVariables $parameterVariables + + } | Should -Not -Throw + + } + + It "check .PARAMETER help matches variables in param block" -Tag "HelpMatchesParamVariables" { + + $parameterVariables = GetScriptParameter -Content $fileContent + + if ($parameterVariables.Count -eq 0) { + + Set-ItResult -Inconclusive -Because "No parameters found" + + } + + { + + TestHelpTokensParamsMatch -HelpTokens $helpTokens -ParameterVariables $parameterVariables + + } | Should -Not -Throw + + } + + It "check script contains no PSScriptAnalyzer suppressions" -Tag "NoScriptAnalyzerSuppressions" { + + $suppressCount = (@(GetTokenMarker -ParsedContent $ParsedFile -Type "Attribute" -Content "Diagnostics.CodeAnalysis.SuppressMessageAttribute")).Count + $suppressCount | Should -Be 0 + + $suppressCount = (@(GetTokenMarker -ParsedContent $ParsedFile -Type "Attribute" -Content "Diagnostics.CodeAnalysis.SuppressMessage")).Count + $suppressCount | Should -Be 0 + + } + + It "check script contains no PSScriptAnalyzer failures" -Tag "NoScriptAnalyzerFailures" { + + $AnalyserFailures = @(Invoke-ScriptAnalyzer -Path $scriptFile) + + ($AnalyserFailures | ForEach-Object { $_.Message }) | Should -BeNullOrEmpty + + } + + It "check script contains no PSScriptAnalyser rule failures '<_.Path>" -Tag "NoScriptAnalyzerExtraRulesFailures" -TestCases $rulesPath { + + param($Path) + + if ( [string]::IsNullOrEmpty($Path)) { + + Set-ItResult -Inconclusive -Because "Empty ScriptAnalyzerRulesPath '$Path'" + + } + + if ( -not (Test-Path -Path $Path -ErrorAction SilentlyContinue)) { + + Set-ItResult -Inconclusive -Because "ScriptAnalyzerRulesPath path '$Path' not found" + + } + + $AnalyserFailures = @(Invoke-ScriptAnalyzer -Path $scriptFile -CustomRulePath $Path) + + $AnalyserFailures | ForEach-Object { $_.Message } | Should -BeNullOrEmpty + + } + + It "check Import-Module statements have valid format" -Tag "ValidImportModuleStatements" { + + $importModuleTokens = @($ParsedFile | Where-Object { $_.Type -eq "Command" -and $_.Content -eq "Import-Module" }) + + if ($importModuleTokens.Count -eq 0) { + + Set-ItResult -Inconclusive -Because "No Import-Module statements found" + + } + + { + + TestImportModuleIsValid -ParsedContent $ParsedFile -ImportModuleTokens $importModuleTokens + + } | Should -Not -Throw + + } + + } + +} diff --git a/Source/PSQualityCheck/en-US/aboutPSQualityCheck.help.txt b/Source/PSQualityCheck/en-US/aboutPSQualityCheck.help.txt new file mode 100644 index 0000000..fabbc4e --- /dev/null +++ b/Source/PSQualityCheck/en-US/aboutPSQualityCheck.help.txt @@ -0,0 +1,28 @@ +TOPIC + about_PSQualityCheck + +SHORT DESCRIPTION + Common set of tools. + +LONG DESCRIPTION + This project + +EXAMPLES + PS C:\> Build-Module -SourcePath .\ModuleBuilder\Source\build.psd1 + + This will create a versioned folder of the module with ModuleBuilder.psm1 containing all functions + from the Private and Public folder, an updated ModuleBuilder.psd1 module manifest with the FunctionsToExport + correctly populated with all functions from the Public Folder. + +NOTE: + nothing. + +TROUBLESHOOTING NOTE: + Look out on the Github repository for issues and new releases. + +SEE ALSO + - https://github.com/ + +KEYWORDS + Module + diff --git a/Source/PSQualityCheck/private/ConvertHelp.ps1 b/Source/PSQualityCheck/private/ConvertHelp.ps1 new file mode 100644 index 0000000..2426229 --- /dev/null +++ b/Source/PSQualityCheck/private/ConvertHelp.ps1 @@ -0,0 +1,149 @@ +function ConvertHelp { + <# + .SYNOPSIS + Convert the help comment into an object + + .DESCRIPTION + Convert the help comment into an object containing all the elements from the help comment + + .PARAMETER Help + A string containing the Help Comment + + .EXAMPLE + $helpObject = Convert-Help -Help $Help + #> + [CmdletBinding()] + [OutputType([HashTable], [System.Exception])] + param ( + [parameter(Mandatory = $true)] + [string]$Help + ) + + # These are the possible Help Comment elements that the script will look for + # .SYNOPSIS + # .DESCRIPTION + # .PARAMETER + # .EXAMPLE + # .INPUTS + # .OUTPUTS + # .NOTES + # .LINK + # .COMPONENT + # .ROLE + # .FUNCTIONALITY + # .FORWARDHELPTARGETNAME + # .FORWARDHELPCATEGORY + # .REMOTEHELPRUNSPACE + # .EXTERNALHELP + + # This function will go through the help and work out which elements are where and what text they contain + + try { + + if (-not( + $Help.StartsWith("<#") -and + $Help.EndsWith("#>") + )) { + throw "Help does not appear to be a comment block" + } + + $helpElementsToFind = + '.SYNOPSIS', + '.DESCRIPTION', + '.PARAMETER', + '.EXAMPLE', + '.INPUTS', + '.OUTPUTS', + '.NOTES', + '.LINK', + '.COMPONENT', + '.ROLE', + '.FUNCTIONALITY', + '.FORWARDHELPTARGETNAME', + '.FORWARDHELPCATEGORY', + '.REMOTEHELPRUNSPACE', + '.EXTERNALHELP' + + $commentArray = ($Help -split '\n').Trim() + + $foundElements = @{} + $numFound = 0 + $lastHelpElement = $null + + for ($line = 0; $line -lt $commentArray.Count; $line++) { + + # get the first 'word' of the help comment. This is required so that we can + # match '.PARAMETER' since it has a parameter name after it + $helpElementKey = ($commentArray[$line] -split " ")[0] + + # Get the value of the Help Comment (the parameter name) + try { + $helpElementName = ($commentArray[$line] -split " ")[1] + } + catch { + $helpElementName = "" + } + + if ($helpElementsToFind -contains $helpElementKey) { + + $numFound++ + + if ($numFound -ge 2) { + + # if it's the second element then we must set the help comment text of the + # previous element to the found text so far, then reset it + + $lastElement = @($foundElements[$lastHelpElement]) + $lastElement[$lastElement.Count - 1].Text = $helpData + $foundElements[$lastHelpElement] = $lastElement + + $helpData = $null + } + + # this should be an array of HashTables + # each hash table will contain the properties LineNumber, Name & Text + $currentElement = @($foundElements[$helpElementKey]) + + $newElement = @{} + $newElement.LineNumber = $line + $newElement.Name = $helpElementName + $newElement.Text = "" + + if ($null -eq $currentElement[0]) { + $currentElement = $newElement + } + else { + $currentElement += $newElement + } + + $foundElements[$helpElementKey] = $currentElement + + $lastHelpElement = $helpElementKey + + } + else { + + if ($numFound -ge 1 -and $line -lt ($commentArray.Count - 1)) { + $helpData += $commentArray[$line] + } + + } + + } + + if ( -not ([string]::IsNullOrEmpty($lastHelpElement))) { + $currentElement = @($foundElements[$lastHelpElement]) + $currentElement[$currentElement.Count - 1].Text = $helpData + $foundElements[$lastHelpElement] = $currentElement + } + + return $foundElements + + } + catch { + + throw $_.Exception.Message + + } + +} diff --git a/Source/PSQualityCheck/private/ExportFunctionsFromModule.ps1 b/Source/PSQualityCheck/private/ExportFunctionsFromModule.ps1 new file mode 100644 index 0000000..9959c9d --- /dev/null +++ b/Source/PSQualityCheck/private/ExportFunctionsFromModule.ps1 @@ -0,0 +1,104 @@ +function ExportFunctionsFromModule { + <# + .SYNOPSIS + Export functions from a PowerShell module (.psm1) + + .DESCRIPTION + Takes a PowerShell module and outputs a single file for each function containing the code for that function + + .PARAMETER Path + A string Path containing the full file name and path to the module + + .PARAMETER ExtractPath + A string Path containing the full path to the extraction folder + + .EXAMPLE + ExportFunctionsFromModule -Path 'c:\path.to\module.psm1' -ExtractPath 'c:\extract' + #> + [CmdletBinding()] + [OutputType([System.Void])] + param ( + [parameter(Mandatory = $true)] + [string]$Path, + [parameter(Mandatory = $true)] + [string]$ExtractPath + ) + + try { + + $fileProperties = (Get-Item -LiteralPath $Path) + + if ($fileProperties.Extension -ne ".psm1") { + throw "Passed file does not appear to be a PowerShell module" + } + + $moduleName = $fileProperties.BaseName + + $ModuleFileContent = Get-Content -Path $Path -ErrorAction Stop + + $ParserErrors = $null + $ParsedFileFunctions = [System.Management.Automation.PSParser]::Tokenize($ModuleFileContent, [ref]$ParserErrors) + + $ParsedFunctions = ($ParsedFileFunctions | Where-Object { $_.Type -eq "Keyword" -and $_.Content -like 'function' }) + + $parsedFunction = 0 + + if ($ParsedFunctions.Count -ge 1) { + + $FunctionOutputPath = Join-Path -Path $ExtractPath -ChildPath $moduleName + + if (-not (Test-Path -Path $FunctionOutputPath)) { + New-Item $FunctionOutputPath -ItemType 'Directory' + } + + foreach ($Function in $ParsedFunctions) { + + $parsedFunction++ + + $FunctionProperties = $ParsedFileFunctions | Where-Object { $_.StartLine -eq $Function.StartLine } + $FunctionName = ($FunctionProperties | Where-Object { $_.Type -eq "CommandArgument" }).Content + + if ($parsedFunction -eq $ParsedFunctions.Count) { + + $StartLine = ($Function.StartLine) + for ($line = $ModuleFileContent.Count; $line -gt $Function.StartLine; $line--) { + if ($ModuleFileContent[$line] -like "}") { + $EndLine = $line + break + } + } + + } + else { + + $StartLine = ($Function.StartLine) + + for ($line = $ParsedFunctions[$parsedFunction].StartLine; $line -gt $Function.StartLine; $line--) { + if ($ModuleFileContent[$line] -like "}") { + $EndLine = $line + break + } + } + + } + + $FunctionOutputFileName = "{0}\{1}{2}" -f $FunctionOutputPath, $FunctionName, ".ps1" + + if (-not (Test-Path -Path $FunctionOutputFileName)) { + Out-File -FilePath $FunctionOutputFileName + } + + for ($line = $StartLine; $line -lt $EndLine; $line++) { + Add-Content -Path $FunctionOutputFileName -Value $ModuleFileContent[$line] + } + + } + } + else { + throw "File contains no functions" + } + } + catch { + throw + } +} diff --git a/Source/PSQualityCheck/private/GetFileContent.ps1 b/Source/PSQualityCheck/private/GetFileContent.ps1 new file mode 100644 index 0000000..16dadf0 --- /dev/null +++ b/Source/PSQualityCheck/private/GetFileContent.ps1 @@ -0,0 +1,95 @@ +function GetFileContent { + <# + .SYNOPSIS + Gets the content of a script file + + .DESCRIPTION + Gets the content of the file or the content of the function inside the file + + .PARAMETER Path + A file name to parse + + .EXAMPLE + $fileContent = GetFileContent -Path 'c:\file.txt' + #> + [CmdletBinding()] + [OutputType([System.String[]])] + param ( + [parameter(Mandatory = $true)] + [string]$Path + ) + + try { + + $fileContent = Get-Content -Path $Path + + $parserErrors = $null + + if ([string]::IsNullOrEmpty($fileContent)) { + $parsedFileFunctions = @() + } + else { + ($parsedFileFunctions, $parserErrors) = GetParsedContent -Content $fileContent + } + + if ($parserErrors -ge 1) { + throw "Error parsing file" + } + + $parsedFunctions = @($parsedFileFunctions | Where-Object { $_.Type -eq "Keyword" -and $_.Content -like 'function' }) + + if ([string]::IsNullOrEmpty($parsedFunctions) -or $parsedFunctions.Count -eq 0) { + throw "No functions found in file, file is invalid" + } + + if ($parsedFunctions.Count -gt 1) { + throw "Too many functions in file, file is invalid" + } + + if ($fileContent.Count -gt 1) { + + foreach ($function in $parsedFunctions) { + + $startLine = ($function.StartLine) + + for ($line = $fileContent.Count - 1; $line -gt $function.StartLine; $line--) { + + if ($fileContent[$line] -like "*}*") { + + $endLine = $line + break + + } + + } + + for ($line = $startLine; $line -lt $endLine; $line++) { + + $parsedFileContent += $fileContent[$line] + + if ($line -ne ($fileContent.Count - 1)) { + $parsedFileContent += "`r`n" + } + + } + + } + + } + else { + + [int]$startBracket = $fileContent.IndexOf('{') + [int]$endBracket = $fileContent.LastIndexOf('}') + + $parsedFileContent = $fileContent.substring($startBracket + 1, $endBracket - 1 - $startBracket) + + } + + } + catch { + throw + } + + return $parsedFileContent + +} diff --git a/Source/PSQualityCheck/private/GetFileList.ps1 b/Source/PSQualityCheck/private/GetFileList.ps1 new file mode 100644 index 0000000..0232e51 --- /dev/null +++ b/Source/PSQualityCheck/private/GetFileList.ps1 @@ -0,0 +1,56 @@ +function GetFileList { + <# + .SYNOPSIS + Return a list of files + + .DESCRIPTION + Return a list of files from the specified path matching the passed extension + + .PARAMETER Path + A string containing the path + + .PARAMETER Extension + A string containing the extension + + .PARAMETER Recurse + A switch specifying whether or not to recursively search the path specified + + .EXAMPLE + $files = GetFileList -Path 'c:\folder' -Extension ".ps1" + + .EXAMPLE + $files = GetFileList -Path 'c:\folder' -Extension ".ps1" -Recurse + #> + [CmdletBinding()] + [OutputType([System.Object[]])] + param ( + [parameter(Mandatory = $true)] + [string]$Path, + [parameter(Mandatory = $true)] + [string]$Extension, + [parameter(Mandatory = $false)] + [switch]$Recurse + ) + + $Extension = $Extension + + $FileNameArray = @() + + if (Test-Path -Path $Path) { + + $gciSplat = @{ + 'Path' = $Path + 'Exclude' = "*.Tests.*" + } + if ($PSBoundParameters.ContainsKey('Recurse')) { + $gciSplat.Add('Recurse', $true) + } + + $SelectedFilesArray = Get-ChildItem @gciSplat | Where-Object { $_.Extension -eq $Extension } | Select-Object -Property FullName + $SelectedFilesArray | ForEach-Object { $FileNameArray += [string]$_.FullName } + + } + + return $FileNameArray + +} diff --git a/Source/PSQualityCheck/private/GetFunctionCount.ps1 b/Source/PSQualityCheck/private/GetFunctionCount.ps1 new file mode 100644 index 0000000..9ea4fd1 --- /dev/null +++ b/Source/PSQualityCheck/private/GetFunctionCount.ps1 @@ -0,0 +1,100 @@ +function GetFunctionCount { + <# + .SYNOPSIS + Return the count of functions within Module and its Manifest + + .DESCRIPTION + Return the count of functions in the Module and Manifest and whether they appear in their counterpart. + e.g. Whether the functions in the manifest appear in the module and vice versa + + .PARAMETER ModulePath + A string containing the Module filename + + .PARAMETER ManifestPath + A string containing the Manifest filename + + .EXAMPLE + ($ExportedCommandsCount, $CommandFoundInModuleCount, $CommandInModuleCount, $CommandFoundInManifestCount) = GetFunctionCount -ModulePath $ModulePath -ManifestPath $ManifestPath + + #> + [CmdletBinding()] + [OutputType([Int[]])] + param ( + [parameter(Mandatory = $true)] + [string]$ModulePath, + [parameter(Mandatory = $true)] + [string]$ManifestPath + ) + + try { + if (Test-Path -Path $ManifestPath) { + $ExportedCommands = (Test-ModuleManifest -Path $ManifestPath -ErrorAction Stop).ExportedCommands + $ExportedCommandsCount = $ExportedCommands.Count + } + else { + throw "Manifest file doesn't exist" + } + } + catch { + $ExportedCommands = @() + $ExportedCommandsCount = 0 + } + + try { + if (Test-Path -Path $ModulePath) { + ($ParsedModule, $ParserErrors) = GetParsedFile -Path $ModulePath + } + else { + throw "Module file doesn't exist" + } + } + catch { + $ParsedModule = @() + $ParserErrors = 1 + } + + $CommandFoundInModuleCount = 0 + $CommandFoundInManifestCount = 0 + $CommandInModuleCount = 0 + + if ( -not ([string]::IsNullOrEmpty($ParsedModule))) { + + foreach ($ExportedCommand in $ExportedCommands.Keys) { + + if ( ($ParsedModule | Where-Object { $_.Type -eq "CommandArgument" -and $_.Content -eq $ExportedCommand })) { + + $CommandFoundInModuleCount++ + + } + + } + + $functionNames = @() + + $functionKeywords = ($ParsedModule | Where-Object { $_.Type -eq "Keyword" -and $_.Content -eq "function" }) + $functionKeywords | ForEach-Object { + + $functionLineNo = $_.StartLine + $functionNames += ($ParsedModule | Where-Object { $_.Type -eq "CommandArgument" -and $_.StartLine -eq $functionLineNo }) + + } + } + + if ($ExportedCommandsCount -ge 1) { + + foreach ($function in $functionNames) { + + $CommandInModuleCount++ + if ($ExportedCommands.ContainsKey($function.Content)) { + + $CommandFoundInManifestCount++ + + } + + } + + } + + return ($ExportedCommandsCount, $CommandFoundInModuleCount, $CommandInModuleCount, $CommandFoundInManifestCount) + +} diff --git a/Source/PSQualityCheck/private/GetParsedContent.ps1 b/Source/PSQualityCheck/private/GetParsedContent.ps1 new file mode 100644 index 0000000..471d067 --- /dev/null +++ b/Source/PSQualityCheck/private/GetParsedContent.ps1 @@ -0,0 +1,39 @@ +function GetParsedContent { + <# + .SYNOPSIS + Get the tokenized content of the passed data + + .DESCRIPTION + Get and return the tokenized content of the passed PowerShell script content + + .PARAMETER Content + A string containing PowerShell script content + + .EXAMPLE + ($ParsedModule, $ParserErrorCount) = GetParsedContent -Content $fileContent + #> + [CmdletBinding()] + [OutputType([System.Object[]], [System.Int32], [System.Void])] + param ( + [parameter(Mandatory = $true)] + [System.Object[]]$Content + ) + + if (-not ([string]::IsNullOrEmpty($Content))) { + + $ParserErrors = $null + $ParsedModule = [System.Management.Automation.PSParser]::Tokenize($Content, [ref]$ParserErrors) + + $ParserErrorCount = $ParserErrors.Count + + } + else { + + $ParsedModule = $null + $ParserErrorCount = 1 + + } + + return $ParsedModule, $ParserErrorCount + +} diff --git a/Source/PSQualityCheck/private/GetParsedFile.ps1 b/Source/PSQualityCheck/private/GetParsedFile.ps1 new file mode 100644 index 0000000..9b9d4d1 --- /dev/null +++ b/Source/PSQualityCheck/private/GetParsedFile.ps1 @@ -0,0 +1,38 @@ +function GetParsedFile { + <# + .SYNOPSIS + Get the tokenized content of the passed file + + .DESCRIPTION + Get and return the tokenized content of the passed PowerShell file + + .PARAMETER Path + A string containing PowerShell filename + + .EXAMPLE + ($ParsedModule, $ParserErrors) = GetParsedFile -Path $ModuleFile + + #> + [CmdletBinding()] + [OutputType([System.Object[]])] + param ( + [parameter(Mandatory = $true)] + [string]$Path + ) + + try { + if (-not(Test-Path -Path $Path)) { + throw "$Path doesn't exist" + } + } + catch { + throw $_ + } + + $fileContent = Get-Content -Path $Path -Raw + + ($ParsedModule, $ParserErrorCount) = GetParsedContent -Content $fileContent + + return $ParsedModule, $ParserErrorCount + +} diff --git a/Source/PSQualityCheck/private/GetScriptParameter.ps1 b/Source/PSQualityCheck/private/GetScriptParameter.ps1 new file mode 100644 index 0000000..af0face --- /dev/null +++ b/Source/PSQualityCheck/private/GetScriptParameter.ps1 @@ -0,0 +1,76 @@ +function GetScriptParameter { + <# + .SYNOPSIS + Get a list of the parameters in the param block + + .DESCRIPTION + Create a list of the parameters, and their type (if available) from the param block + + .PARAMETER Content + A string containing the text of the script + + .EXAMPLE + $parameterVariables = GetScriptParameter -Content $Content + #> + [CmdletBinding()] + [OutputType([System.Exception], [HashTable])] + param ( + [parameter(Mandatory = $true)] + [String]$Content + ) + + try { + + $parsedScript = [System.Management.Automation.Language.Parser]::ParseInput($Content, [ref]$null, [ref]$null) + + if ([string]::IsNullOrEmpty($parsedScript.ParamBlock)) { + throw "No parameters found" + } + + [string]$paramBlock = $parsedScript.ParamBlock + + ($ParsedContent, $ParserErrorCount) = GetParsedContent -Content $paramBlock + + $paramBlockArray = ($paramBlock -split '\n').Trim() + + $parametersFound = @{} + + for ($line = 0; $line -le $paramBlockArray.Count; $line++) { + + $paramToken = @($ParsedContent | Where-Object { $_.StartLine -eq $line }) + + foreach ($token in $paramToken) { + + if ($token.Type -eq 'Attribute' -and $token.Content -eq "Parameter") { + + break + } + + if ($token.Type -eq 'Type') { + + $foundType = $token.Content + + } + + if ($token.Type -eq 'Variable') { + + $parametersFound[$token.Content] = $foundType + $foundType = $null + break + + } + + } + + } + + return $parametersFound + + } + catch { + + throw $_.Exception.Message + + } + +} diff --git a/Source/PSQualityCheck/private/GetTagList.ps1 b/Source/PSQualityCheck/private/GetTagList.ps1 new file mode 100644 index 0000000..b8ab0ab --- /dev/null +++ b/Source/PSQualityCheck/private/GetTagList.ps1 @@ -0,0 +1,71 @@ +function GetTagList { + <# + .SYNOPSIS + Return a list of test tags + + .DESCRIPTION + Return a list of test tags from the module and script checks file + + .EXAMPLE + ($moduleTags, $scriptTags) = GetTagList + + #> + [CmdletBinding()] + [OutputType([System.Object[]])] + param ( + ) + + $moduleTags = @() + $scriptTags = @() + + $modulePath = (Get-Module -Name 'PSQualityCheck').ModuleBase + + $checksPath = (Join-Path -Path $modulePath -ChildPath "data") + + Get-Content -Path (Join-Path -Path $checksPath -ChildPath "Module.Tests.ps1") -Raw | ForEach-Object { + $ast = [Management.Automation.Language.Parser]::ParseInput($_, [ref]$null, [ref]$null) + $ast.FindAll( { + param($node) + $node -is [System.Management.Automation.Language.CommandAst] -and + $node.CommandElements[0].Value -eq "Describe" -and + $node.CommandElements[2] -is [System.Management.Automation.Language.CommandParameterAst] -and + $node.CommandElements[2].ParameterName -eq "Tag" + }, $true) | ForEach-Object { + $moduleTags += $_.CommandElements[3].Value + } + $ast.FindAll( { + param($node) + $node -is [System.Management.Automation.Language.CommandAst] -and + $node.CommandElements[0].Value -eq "It" -and + $node.CommandElements[2] -is [System.Management.Automation.Language.CommandParameterAst] -and + $node.CommandElements[2].ParameterName -eq "Tag" + }, $true) | ForEach-Object { + $moduleTags += $_.CommandElements[3].Value + } + } + + Get-Content -Path (Join-Path -Path $checksPath -ChildPath "Script.Tests.ps1") -Raw | ForEach-Object { + $ast = [Management.Automation.Language.Parser]::ParseInput($_, [ref]$null, [ref]$null) + $ast.FindAll( { + param($node) + $node -is [System.Management.Automation.Language.CommandAst] -and + $node.CommandElements[0].Value -eq "Describe" -and + $node.CommandElements[2] -is [System.Management.Automation.Language.CommandParameterAst] -and + $node.CommandElements[2].ParameterName -eq "Tag" + }, $true) | ForEach-Object { + $scriptTags += $_.CommandElements[3].Value + } + $ast.FindAll( { + param($node) + $node -is [System.Management.Automation.Language.CommandAst] -and + $node.CommandElements[0].Value -eq "It" -and + $node.CommandElements[2] -is [System.Management.Automation.Language.CommandParameterAst] -and + $node.CommandElements[2].ParameterName -eq "Tag" + }, $true) | ForEach-Object { + $scriptTags += $_.CommandElements[3].Value + } + } + + return $moduleTags, $scriptTags + +} diff --git a/Source/PSQualityCheck/private/GetToken.ps1 b/Source/PSQualityCheck/private/GetToken.ps1 new file mode 100644 index 0000000..87196ec --- /dev/null +++ b/Source/PSQualityCheck/private/GetToken.ps1 @@ -0,0 +1,38 @@ +function GetToken { + <# + .SYNOPSIS + Get token(s) from the tokenized output + + .DESCRIPTION + Get token(s) from the tokenized output matching the passed Type and Content + + .PARAMETER ParsedContent + A string array containing the Tokenized data + + .PARAMETER Type + The token type to be found + + .PARAMETER Content + The token content (or value) to be found + + .EXAMPLE + $outputTypeToken = (GetToken -ParsedContent $ParsedFile -Type "Attribute" -Content "OutputType") + #> + [CmdletBinding()] + [OutputType([System.Object[]])] + param ( + [parameter(Mandatory = $true)] + [System.Object[]]$ParsedContent, + [parameter(Mandatory = $true)] + [string]$Type, + [parameter(Mandatory = $true)] + [string]$Content + ) + + $token = GetTokenMarker -ParsedContent $ParsedContent -Type $Type -Content $Content + + $tokens = GetTokenComponent -ParsedContent $ParsedContent -StartLine $token.StartLine + + return $tokens + +} diff --git a/Source/PSQualityCheck/private/GetTokenComponent.ps1 b/Source/PSQualityCheck/private/GetTokenComponent.ps1 new file mode 100644 index 0000000..30a1d44 --- /dev/null +++ b/Source/PSQualityCheck/private/GetTokenComponent.ps1 @@ -0,0 +1,35 @@ +function GetTokenComponent { + <# + .SYNOPSIS + Get all the tokens components from a single line + + .DESCRIPTION + Get all the tokens components from a single line in the tokenized content + + .PARAMETER ParsedContent + A string array containing the tokenized content + + .PARAMETER StartLine + A integer of the starting line to parse + + .EXAMPLE + $tokens = GetTokenComponent -ParsedContent $ParsedContent -StartLine 10 + #> + [CmdletBinding()] + [OutputType([System.Object[]])] + param ( + [parameter(Mandatory = $true)] + [System.Object[]]$ParsedContent, + [parameter(Mandatory = $true)] + [int]$StartLine + ) + + #* This is just to satisfy the PSScriptAnalyzer + #* which can't find the variables in the 'Where-Object' clause (even though it's valid) + $StartLine = $StartLine + + $tokenComponents = @($ParsedContent | Where-Object { $_.StartLine -eq $StartLine }) + + return $tokenComponents + +} diff --git a/Source/PSQualityCheck/private/GetTokenMarker.ps1 b/Source/PSQualityCheck/private/GetTokenMarker.ps1 new file mode 100644 index 0000000..d3b1e4f --- /dev/null +++ b/Source/PSQualityCheck/private/GetTokenMarker.ps1 @@ -0,0 +1,41 @@ +function GetTokenMarker { + <# + .SYNOPSIS + Gets token from the tokenized output + + .DESCRIPTION + Gets single token from the tokenized output matching the passed Type and Content + + .PARAMETER ParsedContent + A string array containing the Tokenized data + + .PARAMETER Type + The token type to be found + + .PARAMETER Content + The token content (or value) to be found + + .EXAMPLE + $token = GetTokenMarker -ParsedContent $ParsedContent -Type $Type -Content $Content + #> + [CmdletBinding()] + [OutputType([System.Object[]])] + param ( + [parameter(Mandatory = $true)] + [System.Object[]]$ParsedContent, + [parameter(Mandatory = $true)] + [string]$Type, + [parameter(Mandatory = $true)] + [string]$Content + ) + + #* This is just to satisfy the PSScriptAnalyzer + #* which can't find the variables in the 'Where-Object' clause (even though it's valid) + $Type = $Type + $Content = $Content + + $token = @($ParsedContent | Where-Object { $_.Type -eq $Type -and $_.Content -eq $Content }) + + return $token + +} diff --git a/Source/PSQualityCheck/private/TestHelpTokensCountisValid.ps1 b/Source/PSQualityCheck/private/TestHelpTokensCountisValid.ps1 new file mode 100644 index 0000000..b7945e2 --- /dev/null +++ b/Source/PSQualityCheck/private/TestHelpTokensCountisValid.ps1 @@ -0,0 +1,82 @@ +function TestHelpTokensCountIsValid { + <# + .SYNOPSIS + Check that help tokens count is valid + + .DESCRIPTION + Check that the help tokens count is valid by making sure that they appear between Min and Max times + + .PARAMETER HelpTokens + A array of tokens containing the tokens of the Help Comment + + .PARAMETER HelpRulesPath + Path to the HelpRules file + + .EXAMPLE + Test-HelpTokensCountIsValid -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" + + .NOTES + This function will only check the Min/Max counts of required help tokens + #> + [CmdletBinding()] + [OutputType([System.Exception], [System.Void])] + param ( + [parameter(Mandatory = $true)] + [HashTable]$HelpTokens, + + [parameter(Mandatory = $true)] + [string]$HelpRulesPath + ) + + try { + + $helpRules = Import-PowerShellDataFile -Path $HelpRulesPath + + $tokenFound = @{} + for ($order = 1; $order -le $HelpRules.Count; $order++) { + $helpRuleIndex = [string]$order + $token = $HelpRules.$helpRuleIndex.Key + $tokenFound[$token] = $false + } + + $tokenErrors = @() + + foreach ($key in $HelpTokens.Keys) { + + for ($order = 1; $order -le $HelpRules.Count; $order++) { + + $helpRuleIndex = [string]$order + $token = $HelpRules.$helpRuleIndex + + if ( $token.Key -eq $key ) { + + $tokenFound[$key] = $true + + if ($HelpTokens.$key.Count -lt $token.MinOccurrences -or + $HelpTokens.$key.Count -gt $token.MaxOccurrences -and + $token.Required -eq $true) { + + $tokenErrors += "Found $(($HelpTokens.$key).Count) occurrences of '$key' which is not between $($token.MinOccurrences) and $($token.MaxOccurrences). " + + } + + } + + } + + } + + if ($tokenErrors.Count -ge 1) { + + throw $tokenErrors + + } + + } + catch { + + throw $_.Exception.Message + + } + +} diff --git a/Source/PSQualityCheck/private/TestHelpTokensParamsMatch.ps1 b/Source/PSQualityCheck/private/TestHelpTokensParamsMatch.ps1 new file mode 100644 index 0000000..a41dcbf --- /dev/null +++ b/Source/PSQualityCheck/private/TestHelpTokensParamsMatch.ps1 @@ -0,0 +1,92 @@ +function TestHelpTokensParamsMatch { + <# + .SYNOPSIS + Checks to see whether the parameters and help PARAMETER statements match + + .DESCRIPTION + Checks to see whether the parameters in the param block and in the help PARAMETER statements exist in both locations + + .PARAMETER HelpTokens + A array of tokens containing the tokens of the Help Comment + + .PARAMETER ParameterVariables + A object containing the parameters from the param block + + .EXAMPLE + Test-HelpTokensParamsMatch -HelpTokens $HelpTokens -ParameterVariables $ParameterVariables + #> + [CmdletBinding()] + [OutputType([System.Exception], [System.String[]])] + param ( + [parameter(Mandatory = $true)] + [HashTable]$HelpTokens, + [parameter(Mandatory = $true)] + [PSCustomObject]$ParameterVariables + ) + + try { + + $foundInHelpErrors = @() + $foundInParamErrors = @() + + foreach ($key in $ParameterVariables.Keys) { + + $foundInHelp = $false + + foreach ($token in $HelpTokens.".PARAMETER") { + + if ($key -eq $token.Name) { + + $foundInHelp = $true + break + + } + + } + + if ($foundInHelp -eq $false) { + + $foundInHelpErrors += "Parameter block variable '$key' was not found in help. " + + } + + } + + foreach ($token in $HelpTokens.".PARAMETER") { + + $foundInParams = $false + + foreach ($key in $ParameterVariables.Keys) { + + if ($key -eq $token.Name) { + + $foundInParams = $true + break + + } + + } + + if ($foundInParams -eq $false) { + + $foundInParamErrors += "Help defined variable '$($token.Name)' was not found in parameter block definition. " + + } + + } + + if ($foundInHelpErrors.Count -ge 1 -or $foundInParamErrors.Count -ge 1) { + + $allErrors = $foundInHelpErrors + $foundInParamErrors + throw $allErrors + + } + + } + catch { + + throw $_.Exception.Message + + } + +} diff --git a/Source/PSQualityCheck/private/TestHelpTokensTextIsValid.ps1 b/Source/PSQualityCheck/private/TestHelpTokensTextIsValid.ps1 new file mode 100644 index 0000000..14af20f --- /dev/null +++ b/Source/PSQualityCheck/private/TestHelpTokensTextIsValid.ps1 @@ -0,0 +1,57 @@ +function TestHelpTokensTextIsValid { + <# + .SYNOPSIS + Check that Help Tokens text is valid + + .DESCRIPTION + Check that the Help Tokens text is valid by making sure that they its not empty + + .PARAMETER HelpTokens + A array of tokens containing the tokens of the Help Comment + + .EXAMPLE + Test-HelpTokensTextIsValid -HelpTokens $HelpTokens + #> + [CmdletBinding()] + [OutputType([System.Exception], [System.Void])] + param ( + [parameter(Mandatory = $true)] + [HashTable]$HelpTokens + ) + + try { + + $tokenErrors = @() + + foreach ($key in $HelpTokens.Keys) { + + $tokenCount = @($HelpTokens.$key) + + for ($loop = 0; $loop -lt $tokenCount.Count; $loop++) { + + $token = $HelpTokens.$key[$loop] + + if ([string]::IsNullOrWhitespace($token.Text)) { + + $tokenErrors += "Found '$key' does not have any text. " + + } + + } + + } + + if ($tokenErrors.Count -ge 1) { + + throw $tokenErrors + + } + + } + catch { + + throw $_.Exception.Message + + } + +} diff --git a/Source/PSQualityCheck/private/TestImportModuleIsValid.ps1 b/Source/PSQualityCheck/private/TestImportModuleIsValid.ps1 new file mode 100644 index 0000000..e288714 --- /dev/null +++ b/Source/PSQualityCheck/private/TestImportModuleIsValid.ps1 @@ -0,0 +1,76 @@ +function TestImportModuleIsValid { + <# + .SYNOPSIS + Test that the Import-Module commands are valid + + .DESCRIPTION + Test that the Import-Module commands contain a -Name parameter, and one of RequiredVersion, MinimumVersion or MaximumVersion + + .PARAMETER ParsedContent + An object containing the source file parsed into its Tokenizer components + + .PARAMETER ImportModuleTokens + An object containing the Import-Module tokens found + + .EXAMPLE + TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens + #> + [CmdletBinding()] + [OutputType([System.Exception], [System.Void])] + param ( + [parameter(Mandatory = $true)] + [System.Object[]]$ParsedContent, + [parameter(Mandatory = $true)] + [System.Object[]]$ImportModuleTokens + ) + + try { + + $errString = "" + + foreach ($token in $importModuleTokens) { + + $importModuleStatement = GetTokenComponent -ParsedContent $ParsedContent -StartLine $token.StartLine + + try { + $name = ($importModuleStatement | Where-Object { $_.Type -eq "CommandArgument" } | Select-Object -First 1).Content + } + catch { + $name = $null + } + if ($null -eq $name) { + + $name = ($importModuleStatement | Where-Object { $_.Type -eq "String" } | Select-Object -First 1).Content + + } + + if (-not($importModuleStatement | Where-Object { $_.Type -eq "CommandParameter" -and $_.Content -eq "-Name" })) { + + $errString += "Import-Module for '$name' : Missing -Name parameter keyword. " + + } + + if (-not($importModuleStatement | Where-Object { $_.Type -eq "CommandParameter" -and + ( $_.Content -eq "-RequiredVersion" -or $_.Content -eq "-MinimumVersion" -or $_.Content -eq "-MaximumVersion" ) + })) { + + $errString += "Import-Module for '$name' : Missing -RequiredVersion, -MinimumVersion or -MaximumVersion parameter keyword. " + + } + + } + + if (-not ([string]::IsNullOrEmpty($errString))) { + + throw $errString + + } + + } + catch { + + throw $_.Exception.Message + + } + +} diff --git a/Source/PSQualityCheck/private/TestParameterVariablesHaveType.ps1 b/Source/PSQualityCheck/private/TestParameterVariablesHaveType.ps1 new file mode 100644 index 0000000..f4b34ea --- /dev/null +++ b/Source/PSQualityCheck/private/TestParameterVariablesHaveType.ps1 @@ -0,0 +1,48 @@ +function TestParameterVariablesHaveType { + <# + .SYNOPSIS + Check that all the passed parameters have a type variable set. + + .DESCRIPTION + Check that all the passed parameters have a type variable set. + + .PARAMETER ParameterVariables + A HashTable containing the parameters from the param block + + .EXAMPLE + Test-ParameterVariablesHaveType -ParameterVariables $ParameterVariables + #> + [CmdletBinding()] + [OutputType([System.Exception], [System.Void])] + param ( + [parameter(Mandatory = $true)] + [HashTable]$ParameterVariables + ) + + $variableErrors = @() + + try { + + foreach ($key in $ParameterVariables.Keys) { + + if ([string]::IsNullOrEmpty($ParameterVariables.$key)) { + + $variableErrors += "Parameter '$key' does not have a type defined." + + } + + } + + if ($variableErrors.Count -ge 1) { + + throw $variableErrors + } + + } + catch { + + throw $_.Exception.Message + + } + +} diff --git a/Source/PSQualityCheck/private/TestRequiredToken.ps1 b/Source/PSQualityCheck/private/TestRequiredToken.ps1 new file mode 100644 index 0000000..dc447dd --- /dev/null +++ b/Source/PSQualityCheck/private/TestRequiredToken.ps1 @@ -0,0 +1,62 @@ +function TestRequiredToken { + <# + .SYNOPSIS + Check that help tokens contain required tokens + + .DESCRIPTION + Check that the help comments contain tokens that are specified in the external verification data file + + .PARAMETER HelpTokens + A array of tokens containing the tokens of the Help Comment + + .PARAMETER HelpRulesPath + Path to the HelpRules file + + .EXAMPLE + Test-RequiredToken -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" + #> + [CmdletBinding()] + [OutputType([System.Exception], [System.Void])] + param ( + [parameter(Mandatory = $true)] + [HashTable]$HelpTokens, + + [parameter(Mandatory = $true)] + [string]$HelpRulesPath + ) + + try { + + $helpRules = Import-PowerShellDataFile -Path $HelpRulesPath + + $tokenErrors = @() + + for ($order = 1; $order -le $HelpRules.Count; $order++) { + + $helpRuleIndex = [string]$order + $token = $HelpRules.$helpRuleIndex + + if ($token.Key -notin $HelpTokens.Keys ) { + + if ($token.Required -eq $true) { + + $tokenErrors += $token.Key + + } + + } + + } + + if ($tokenErrors.Count -ge 1) { + throw "Missing required token(s): $tokenErrors" + } + + } + catch { + + throw $_.Exception.Message + + } + +} diff --git a/Source/PSQualityCheck/private/TestUnspecifiedToken.ps1 b/Source/PSQualityCheck/private/TestUnspecifiedToken.ps1 new file mode 100644 index 0000000..647a069 --- /dev/null +++ b/Source/PSQualityCheck/private/TestUnspecifiedToken.ps1 @@ -0,0 +1,65 @@ +function TestUnspecifiedToken { + <# + .SYNOPSIS + Check that help tokens do not contain unspecified tokens + + .DESCRIPTION + Check that the help comments do not contain tokens that are not specified in the external verification data file + + .PARAMETER HelpTokens + A array of tokens containing the tokens of the Help Comment + + .PARAMETER HelpRulesPath + Path to the HelpRules file + + .EXAMPLE + Test-UnspecifiedToken -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" + #> + [CmdletBinding()] + [OutputType([System.Exception], [System.Void])] + param ( + [parameter(Mandatory = $true)] + [HashTable]$HelpTokens, + + [parameter(Mandatory = $true)] + [string]$HelpRulesPath + ) + + try { + + $helpRules = Import-PowerShellDataFile -Path $HelpRulesPath + + $tokenErrors = @() + $helpTokensKeys = @() + + for ($order = 1; $order -le $helpRules.Count; $order++) { + + $helpRuleIndex = [string]$order + $token = $helpRules.$helpRuleIndex + + $helpTokensKeys += $token.key + + } + + foreach ($key in $helpTokens.Keys) { + + if ( $key -notin $helpTokensKeys ) { + + $tokenErrors += $key + + } + + } + + if ($tokenErrors.Count -ge 1) { + throw "Found extra, non-specified, token(s): $tokenErrors" + } + + } + catch { + + throw $_.Exception.Message + + } + +} diff --git a/Tests/Unit/PSQualityCheck.Functions/Convert-Help.Tests.ps1 b/Tests/Unit/PSQualityCheck/Convert-Help.Tests.ps1 similarity index 88% rename from Tests/Unit/PSQualityCheck.Functions/Convert-Help.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Convert-Help.Tests.ps1 index 41bda3e..14388cd 100644 --- a/Tests/Unit/PSQualityCheck.Functions/Convert-Help.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/Convert-Help.Tests.ps1 @@ -1,11 +1,11 @@ Describe "Convert-Help.Tests" { - Context "Parameter Tests" -ForEach @( + Context "Parameter Tests" -Foreach @( @{ 'Name' = 'Help'; 'Type' = 'String' } ) { BeforeAll { - $commandletUnderTest = "Convert-Help" + $commandletUnderTest = "ConvertHelp" } It "should have $Name as a mandatory parameter" { @@ -35,7 +35,7 @@ Describe "Convert-Help.Tests" { { - Convert-Help -Help $null + ConvertHelp -Help $null } | Should -Throw @@ -46,7 +46,7 @@ Describe "Convert-Help.Tests" { { $helpComment = '##InvalidHelp##' - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment } | Should -Throw @@ -57,13 +57,13 @@ Describe "Convert-Help.Tests" { { $helpComment = '' - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment } | Should -Throw } - It "should find in help" -Foreach @( + It "should find in help" -ForEach @( @{ 'Token' = '.SYNOPSIS' } @{ 'Token' = '.DESCRIPTION' } @{ 'Token' = '.PARAMETER' } @@ -85,7 +85,7 @@ Describe "Convert-Help.Tests" { $($token) #>" - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment $help.ContainsKey($token) | Should -BeTrue @@ -97,7 +97,7 @@ Describe "Convert-Help.Tests" { .PARAMETER Path #>" - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment $help.ContainsKey(".PARAMETER") | Should -BeTrue @@ -112,7 +112,7 @@ Describe "Convert-Help.Tests" { .PARAMETER Source #>" - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment $help.ContainsKey(".PARAMETER") | Should -BeTrue @@ -129,7 +129,7 @@ Describe "Convert-Help.Tests" { Function -Source #>" - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment $help.ContainsKey(".EXAMPLE") | Should -BeTrue @@ -143,7 +143,7 @@ Describe "Convert-Help.Tests" { .DUMMY #>" - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment $help.ContainsKey(".DUMMY") | Should -BeFalse @@ -156,7 +156,7 @@ Describe "Convert-Help.Tests" { .NOTES #>" - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment $help.ContainsKey(".DUMMY") | Should -BeFalse $help.ContainsKey(".NOTES") | Should -BeTrue @@ -171,7 +171,7 @@ Describe "Convert-Help.Tests" { #>" - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment ([string]::IsNullOrEmpty($help.".SYNOPSIS".Text)) | Should -BeTrue @@ -186,7 +186,7 @@ Describe "Convert-Help.Tests" { .SYNOPSIS #>" - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment ([string]::IsNullOrEmpty($help.".SYNOPSIS".Text)) | Should -BeTrue @@ -206,7 +206,7 @@ Describe "Convert-Help.Tests" { The Path parameter #>" - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment $help.".SYNOPSIS".Text | Should -BeExactly "The SYNOPSIS property" $help.".DESCRIPTION".Text | Should -BeExactly "The DESCRIPTION property" @@ -228,7 +228,7 @@ Describe "Convert-Help.Tests" { The Path parameter #>" - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment $help.".SYNOPSIS".Text | Should -BeExactly "" $help.".DESCRIPTION".Text | Should -BeExactly "The DESCRIPTION property" @@ -249,7 +249,7 @@ Describe "Convert-Help.Tests" { The Path parameter #>" - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment $help.".SYNOPSIS".Text | Should -BeExactly $null $help.".DESCRIPTION".Text | Should -BeExactly "The DESCRIPTION property" @@ -271,7 +271,7 @@ Describe "Convert-Help.Tests" { #>" - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment $help.".SYNOPSIS".Text | Should -BeExactly "" $help.".DESCRIPTION".Text | Should -BeExactly "" @@ -290,7 +290,7 @@ Describe "Convert-Help.Tests" { .PARAMETER Path #>" - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment $help.".SYNOPSIS".Text | Should -BeExactly $null $help.".DESCRIPTION".Text | Should -BeExactly $null @@ -312,7 +312,7 @@ Describe "Convert-Help.Tests" { The Path parameter #>" - $help = Convert-Help -Help $helpComment + $help = ConvertHelp -Help $helpComment $help.".SYNOPSIS".LineNumber | Should -BeExactly 1 $help.".DESCRIPTION".LineNumber | Should -BeExactly 3 diff --git a/Tests/Unit/PSQualityCheck.Functions/Export-FunctionsFromModule.Tests.ps1 b/Tests/Unit/PSQualityCheck/Export-FunctionsFromModule.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck.Functions/Export-FunctionsFromModule.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Export-FunctionsFromModule.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck.Functions/Get-FileContent.Tests.ps1 b/Tests/Unit/PSQualityCheck/Get-FileContent.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck.Functions/Get-FileContent.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Get-FileContent.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck.Functions/Get-FileList.Tests.ps1 b/Tests/Unit/PSQualityCheck/Get-FileList.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck.Functions/Get-FileList.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Get-FileList.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck.Functions/Get-FunctionCount.Tests.ps1 b/Tests/Unit/PSQualityCheck/Get-FunctionCount.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck.Functions/Get-FunctionCount.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Get-FunctionCount.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck.Functions/Get-ParsedContent.Tests.ps1 b/Tests/Unit/PSQualityCheck/Get-ParsedContent.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck.Functions/Get-ParsedContent.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Get-ParsedContent.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck.Functions/Get-ParsedFile.Tests.ps1 b/Tests/Unit/PSQualityCheck/Get-ParsedFile.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck.Functions/Get-ParsedFile.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Get-ParsedFile.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck.Functions/Get-ScriptParameter.Tests.ps1 b/Tests/Unit/PSQualityCheck/Get-ScriptParameter.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck.Functions/Get-ScriptParameter.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Get-ScriptParameter.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck.Functions/Get-TagList.Tests.ps1 b/Tests/Unit/PSQualityCheck/Get-TagList.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck.Functions/Get-TagList.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Get-TagList.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck.Functions/Get-Token.Tests.ps1 b/Tests/Unit/PSQualityCheck/Get-Token.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck.Functions/Get-Token.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Get-Token.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck.Functions/Get-TokenComponent.Tests.ps1 b/Tests/Unit/PSQualityCheck/Get-TokenComponent.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck.Functions/Get-TokenComponent.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Get-TokenComponent.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck.Functions/Get-TokenMarker.Tests.ps1 b/Tests/Unit/PSQualityCheck/Get-TokenMarker.Tests.ps1 similarity index 50% rename from Tests/Unit/PSQualityCheck.Functions/Get-TokenMarker.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Get-TokenMarker.Tests.ps1 index 04d90f6..15c6a83 100644 --- a/Tests/Unit/PSQualityCheck.Functions/Get-TokenMarker.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/Get-TokenMarker.Tests.ps1 @@ -1,13 +1,13 @@ -Describe "Get-TokenMarker.Tests" { +Describe "GetTokenMarker.Tests" { - Context "Parameter Tests" -ForEach @( + Context "Parameter Tests" -Foreach @( @{ 'Name' = 'ParsedContent'; 'Type' = 'Object[]' } @{ 'Name' = 'Type'; 'Type' = 'String' } @{ 'Name' = 'Content'; 'Type' = 'String' } ) { BeforeAll { - $commandletUnderTest = "Get-TokenMarker" + $commandletUnderTest = "GetTokenMarker" } It "should have $Name as a mandatory parameter" { @@ -36,56 +36,56 @@ Describe "Get-TokenMarker.Tests" { BeforeAll { $ParsedContent = @( @{ - "Content" = "function" - "Type" = "Keyword" - "Start" = 0 - "Length" = 8 - "StartLine" = 1 + "Content" = "function" + "Type" = "Keyword" + "Start" = 0 + "Length" = 8 + "StartLine" = 1 "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 9 + "EndLine" = 1 + "EndColumn" = 9 }, @{ - "Content" = "Get-FileContent" - "Type" = "CommandArgument" - "Start" = 9 - "Length" = 15 - "StartLine" = 1 + "Content" = "Get-FileContent" + "Type" = "CommandArgument" + "Start" = 9 + "Length" = 15 + "StartLine" = 1 "StartColumn" = 10 - "EndLine" = 1 - "EndColumn" = 25 + "EndLine" = 1 + "EndColumn" = 25 }, @{ - "Content" = "{" - "Type" = "GroupStart" - "Start" = 25 - "Length" = 1 - "StartLine" = 1 + "Content" = "{" + "Type" = "GroupStart" + "Start" = 25 + "Length" = 1 + "StartLine" = 1 "StartColumn" = 26 - "EndLine" = 1 - "EndColumn" = 27 + "EndLine" = 1 + "EndColumn" = 27 }, @{ - "Content" = "}" - "Type" = "GroupEnd" - "Start" = 26 - "Length" = 1 - "StartLine" = 1 + "Content" = "}" + "Type" = "GroupEnd" + "Start" = 26 + "Length" = 1 + "StartLine" = 1 "StartColumn" = 27 - "EndLine" = 1 - "EndColumn" = 28 + "EndLine" = 1 + "EndColumn" = 28 } ) $tokenMatch = @{ - "Content" = "Get-FileContent" - "Type" = "CommandArgument" - "Start" = 9 - "Length" = 15 - "StartLine" = 1 + "Content" = "Get-FileContent" + "Type" = "CommandArgument" + "Start" = 9 + "Length" = 15 + "StartLine" = 1 "StartColumn" = 10 - "EndLine" = 1 - "EndColumn" = 25 + "EndLine" = 1 + "EndColumn" = 25 } } @@ -94,7 +94,7 @@ Describe "Get-TokenMarker.Tests" { { - Get-TokenMarker -ParsedContent $null -Type $null -Content $null + GetTokenMarker -ParsedContent $null -Type $null -Content $null } | Should -Throw @@ -102,7 +102,7 @@ Describe "Get-TokenMarker.Tests" { It "should find 'CommandArgument' type with 'Get-FileContent' value" { - $token = Get-TokenMarker -ParsedContent $ParsedContent -Type "CommandArgument" -Content "Get-FileContent" + $token = GetTokenMarker -ParsedContent $ParsedContent -Type "CommandArgument" -Content "Get-FileContent" Compare-Object -ReferenceObject $token.Values -DifferenceObject $tokenMatch.values | Should -BeNullOrEmpty @@ -110,7 +110,7 @@ Describe "Get-TokenMarker.Tests" { It "should not find 'Dummy' type with 'Get-FileContent' value" { - $token = Get-TokenMarker -ParsedContent $ParsedContent -Type "Dummy" -Content "Get-FileContent" + $token = GetTokenMarker -ParsedContent $ParsedContent -Type "Dummy" -Content "Get-FileContent" $token | Should -BeNullOrEmpty @@ -118,7 +118,7 @@ Describe "Get-TokenMarker.Tests" { It "should not find 'CommandArgument' type with 'Dummy' value" { - $token = Get-TokenMarker -ParsedContent $ParsedContent -Type "CommandArgument" -Content "Dummy" + $token = GetTokenMarker -ParsedContent $ParsedContent -Type "CommandArgument" -Content "Dummy" $token | Should -BeNullOrEmpty @@ -128,7 +128,7 @@ Describe "Get-TokenMarker.Tests" { { - Get-TokenMarker -ParsedContent $ParsedContent -Type $null -Content $null + GetTokenMarker -ParsedContent $ParsedContent -Type $null -Content $null } | Should -Throw } diff --git a/Tests/Unit/PSQualityCheck.Functions/Test-HelpTokensCountIsValid.Tests.ps1 b/Tests/Unit/PSQualityCheck/Test-HelpTokensCountisValid.Tests.ps1 similarity index 81% rename from Tests/Unit/PSQualityCheck.Functions/Test-HelpTokensCountIsValid.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Test-HelpTokensCountisValid.Tests.ps1 index c8c152c..4bb583a 100644 --- a/Tests/Unit/PSQualityCheck.Functions/Test-HelpTokensCountIsValid.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/Test-HelpTokensCountisValid.Tests.ps1 @@ -33,7 +33,7 @@ Describe "Test-HelpTokensCountIsValid.Tests" { BeforeAll { New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module') -ItemType Directory - New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module\checks') -ItemType Directory + New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data') -ItemType Directory '@{ ''1'' = @{ @@ -84,7 +84,7 @@ Describe "Test-HelpTokensCountIsValid.Tests" { MinOccurrences = 0 MaxOccurrences = 0 } - }' | Set-Content -Path (Join-Path -Path $TestDrive -ChildPath 'module\checks\HelpElementRules.psd1') + }' | Set-Content -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpElementRules.psd1') } BeforeEach { @@ -109,9 +109,9 @@ Describe "Test-HelpTokensCountIsValid.Tests" { $helpTokens = @{ '.SYNOPSIS' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 1 - "Text" = "" + "Text" = "" } ) } @@ -128,30 +128,30 @@ Describe "Test-HelpTokensCountIsValid.Tests" { { $helpTokens = @{ - '.SYNOPSIS' = @( + '.SYNOPSIS' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 1 - "Text" = "" + "Text" = "" }, @{ - "Name" = $null + "Name" = $null "LineNumber" = 2 - "Text" = "" + "Text" = "" } ) '.DESCRIPTION' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 3 - "Text" = "" + "Text" = "" } ) - '.PARAMETER' = @( + '.PARAMETER' = @( @{ - "Name" = "Path" + "Name" = "Path" "LineNumber" = 5 - "Text" = "" + "Text" = "" } ) } @@ -169,37 +169,37 @@ Describe "Test-HelpTokensCountIsValid.Tests" { { $helpTokens = @{ - '.SYNOPSIS' = @( + '.SYNOPSIS' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 1 - "Text" = "" + "Text" = "" } ) '.DESCRIPTION' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 3 - "Text" = "" + "Text" = "" } ) - '.PARAMETER' = @( + '.PARAMETER' = @( @{ - "Name" = "Path" + "Name" = "Path" "LineNumber" = 5 - "Text" = "" + "Text" = "" } ) - '.NOTES' = @( + '.NOTES' = @( @{ - "Name" = "" + "Name" = "" "LineNumber" = 10 - "Text" = "This is a note" + "Text" = "This is a note" }, @{ - "Name" = "" + "Name" = "" "LineNumber" = 10 - "Text" = "This is a note" + "Text" = "This is a note" } ) } diff --git a/Tests/Unit/PSQualityCheck.Functions/Test-HelpTokensParamsMatch.Tests.ps1 b/Tests/Unit/PSQualityCheck/Test-HelpTokensParamsMatch.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck.Functions/Test-HelpTokensParamsMatch.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Test-HelpTokensParamsMatch.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck.Functions/Test-HelpTokensTextIsValid.Tests.ps1 b/Tests/Unit/PSQualityCheck/Test-HelpTokensTextIsValid.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck.Functions/Test-HelpTokensTextIsValid.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Test-HelpTokensTextIsValid.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck.Functions/Test-ImportModuleIsValid.Tests.ps1 b/Tests/Unit/PSQualityCheck/Test-ImportModuleIsValid.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck.Functions/Test-ImportModuleIsValid.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Test-ImportModuleIsValid.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck.Functions/Test-ParameterVariablesHaveType.Tests.ps1 b/Tests/Unit/PSQualityCheck/Test-ParameterVariablesHaveType.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck.Functions/Test-ParameterVariablesHaveType.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Test-ParameterVariablesHaveType.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck.Functions/Test-RequiredToken.Tests.ps1 b/Tests/Unit/PSQualityCheck/Test-RequiredToken.Tests.ps1 similarity index 77% rename from Tests/Unit/PSQualityCheck.Functions/Test-RequiredToken.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Test-RequiredToken.Tests.ps1 index 98a6836..4bc30e8 100644 --- a/Tests/Unit/PSQualityCheck.Functions/Test-RequiredToken.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/Test-RequiredToken.Tests.ps1 @@ -1,6 +1,6 @@ Describe "Test-RequiredToken.Tests" { - Context "Parameter Tests" -Foreach @( + Context "Parameter Tests" -ForEach @( @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } ) { @@ -33,7 +33,7 @@ Describe "Test-RequiredToken.Tests" { BeforeAll { New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module') -ItemType Directory - New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module\checks') -ItemType Directory + New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data') -ItemType Directory '@{ ''1'' = @{ @@ -84,7 +84,7 @@ Describe "Test-RequiredToken.Tests" { MinOccurrences = 0 MaxOccurrences = 0 } - }' | Set-Content -Path (Join-Path -Path $TestDrive -ChildPath 'module\checks\HelpElementRules.psd1') + }' | Set-Content -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpElementRules.psd1') } BeforeEach { @@ -107,32 +107,32 @@ Describe "Test-RequiredToken.Tests" { { $helpTokens = @{ - '.SYNOPSIS' = @( + '.SYNOPSIS' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 1 - "Text" = "" + "Text" = "" } ) '.DESCRIPTION' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 3 - "Text" = "" + "Text" = "" } ) - '.PARAMETER' = @( + '.PARAMETER' = @( @{ - "Name" = "Path" + "Name" = "Path" "LineNumber" = 5 - "Text" = "" + "Text" = "" } ) - '.EXAMPLE' = @( + '.EXAMPLE' = @( @{ - "Name" = "" + "Name" = "" "LineNumber" = 7 - "Text" = "This is example text" + "Text" = "This is example text" } ) } @@ -150,39 +150,39 @@ Describe "Test-RequiredToken.Tests" { { $helpTokens = @{ - '.SYNOPSIS' = @( + '.SYNOPSIS' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 1 - "Text" = "" + "Text" = "" } ) '.DESCRIPTION' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 3 - "Text" = "" + "Text" = "" } ) - '.PARAMETER' = @( + '.PARAMETER' = @( @{ - "Name" = "Path" + "Name" = "Path" "LineNumber" = 5 - "Text" = "" + "Text" = "" } ) - '.EXAMPLE' = @( + '.EXAMPLE' = @( @{ - "Name" = "" + "Name" = "" "LineNumber" = 7 - "Text" = "This is example text" + "Text" = "This is example text" } ) - '.NOTES' = @( + '.NOTES' = @( @{ - "Name" = "" + "Name" = "" "LineNumber" = 10 - "Text" = "This is a note" + "Text" = "This is a note" } ) @@ -200,25 +200,25 @@ Describe "Test-RequiredToken.Tests" { { $helpTokens = @{ - '.SYNOPSIS' = @( + '.SYNOPSIS' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 1 - "Text" = "" + "Text" = "" } ) '.DESCRIPTION' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 3 - "Text" = "" + "Text" = "" } ) - '.PARAMETER' = @( + '.PARAMETER' = @( @{ - "Name" = "Path" + "Name" = "Path" "LineNumber" = 5 - "Text" = "" + "Text" = "" } ) } diff --git a/Tests/Unit/PSQualityCheck.Functions/Test-UnspecifiedToken.Tests.ps1 b/Tests/Unit/PSQualityCheck/Test-UnspecifiedToken.Tests.ps1 similarity index 79% rename from Tests/Unit/PSQualityCheck.Functions/Test-UnspecifiedToken.Tests.ps1 rename to Tests/Unit/PSQualityCheck/Test-UnspecifiedToken.Tests.ps1 index 3191139..6c274a7 100644 --- a/Tests/Unit/PSQualityCheck.Functions/Test-UnspecifiedToken.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/Test-UnspecifiedToken.Tests.ps1 @@ -1,6 +1,6 @@ Describe "Test-UnspecifiedToken.Tests" { - Context "Parameter Tests" -Foreach @( + Context "Parameter Tests" -ForEach @( @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } ) { @@ -33,7 +33,7 @@ Describe "Test-UnspecifiedToken.Tests" { BeforeAll { New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module') -ItemType Directory - New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module\checks') -ItemType Directory + New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data') -ItemType Directory '@{ ''1'' = @{ @@ -84,7 +84,7 @@ Describe "Test-UnspecifiedToken.Tests" { MinOccurrences = 0 MaxOccurrences = 0 } - }' | Set-Content -Path (Join-Path -Path $TestDrive -ChildPath 'module\checks\HelpElementRules.psd1') + }' | Set-Content -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpElementRules.psd1') } BeforeEach { @@ -107,32 +107,32 @@ Describe "Test-UnspecifiedToken.Tests" { { $helpTokens = @{ - '.SYNOPSIS' = @( + '.SYNOPSIS' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 1 - "Text" = "" + "Text" = "" } ) '.DESCRIPTION' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 3 - "Text" = "" + "Text" = "" } ) - '.PARAMETER' = @( + '.PARAMETER' = @( @{ - "Name" = "Path" + "Name" = "Path" "LineNumber" = 5 - "Text" = "" + "Text" = "" } ) - '.EXAMPLE' = @( + '.EXAMPLE' = @( @{ - "Name" = "" + "Name" = "" "LineNumber" = 7 - "Text" = "This is example text" + "Text" = "This is example text" } ) } @@ -150,39 +150,39 @@ Describe "Test-UnspecifiedToken.Tests" { { $helpTokens = @{ - '.SYNOPSIS' = @( + '.SYNOPSIS' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 1 - "Text" = "" + "Text" = "" } ) '.DESCRIPTION' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 3 - "Text" = "" + "Text" = "" } ) - '.PARAMETER' = @( + '.PARAMETER' = @( @{ - "Name" = "Path" + "Name" = "Path" "LineNumber" = 5 - "Text" = "" + "Text" = "" } ) - '.EXAMPLE' = @( + '.EXAMPLE' = @( @{ - "Name" = "" + "Name" = "" "LineNumber" = 7 - "Text" = "This is example text" + "Text" = "This is example text" } ) - '.NOTES' = @( + '.NOTES' = @( @{ - "Name" = "" + "Name" = "" "LineNumber" = 10 - "Text" = "This is a note" + "Text" = "This is a note" } ) @@ -202,9 +202,9 @@ Describe "Test-UnspecifiedToken.Tests" { $helpTokens = @{ '.DUMMY' = @( @{ - "Name" = $null + "Name" = $null "LineNumber" = 1 - "Text" = "" + "Text" = "" } ) } From b152a561ebeec01e09c0d34fa9f6e0a79f28487b Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Sat, 24 Apr 2021 19:56:56 +0100 Subject: [PATCH 08/27] Updated to allow PowerShell 5.1 --- Source/PSQualityCheck/PSQualityCheck.psd1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/PSQualityCheck/PSQualityCheck.psd1 b/Source/PSQualityCheck/PSQualityCheck.psd1 index 94e2527..ee781ea 100644 --- a/Source/PSQualityCheck/PSQualityCheck.psd1 +++ b/Source/PSQualityCheck/PSQualityCheck.psd1 @@ -33,7 +33,7 @@ Description = 'PSQualityCheck' # Minimum version of the PowerShell engine required by this module - PowerShellVersion = '7.0.0' + PowerShellVersion = '5.1' # Name of the PowerShell host required by this module # PowerShellHostName = '' From 53cf09bf6456538ce4452205be6aaa30f070587d Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Sat, 24 Apr 2021 19:57:49 +0100 Subject: [PATCH 09/27] Addition of .psqcignore file and IgnoreFile flag --- .psqcignore | 6 ++++ .../Public/Invoke-PSQualityCheck.ps1 | 20 ++++++++++--- Source/PSQualityCheck/private/GetFileList.ps1 | 30 ++++++++++++------- 3 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 .psqcignore diff --git a/.psqcignore b/.psqcignore new file mode 100644 index 0000000..cef7ac4 --- /dev/null +++ b/.psqcignore @@ -0,0 +1,6 @@ +**/*.Tests.ps1 +**/*.Checks.ps1 +Extraction.ps1 +*.psd1 +**/data/** +**/bin/** diff --git a/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 b/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 index 394cac1..d05aaf7 100644 --- a/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 +++ b/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 @@ -44,6 +44,9 @@ function Invoke-PSQualityCheck { .PARAMETER HelpRulesPath A path to the HelpRules parameter file + .PARAMETER IgnoreFile + A path to the .psqcignore file which excludes files/path from the tests + .EXAMPLE Invoke-PSQualityCheck -Path 'C:\Scripts' @@ -136,7 +139,10 @@ function Invoke-PSQualityCheck { [String[]]$Exclude, [Parameter(Mandatory = $false)] - [String]$HelpRulesPath + [String]$HelpRulesPath, + + [Parameter(Mandatory = $false)] + [String]$IgnoreFile ) @@ -243,9 +249,15 @@ function Invoke-PSQualityCheck { $getFileListSplat = @{ 'Path' = $item } - if ($PSBoundParameters.ContainsKey('Recurse') -or - $PSBoundParameters.ContainsKey('ProjectPath')) { - $getFileListSplat.Add('Recurse', $true) + + if ($PSBoundParameters.ContainsKey('IgnoreFile')) { + $getFileListSplat.Add('IgnoreFile', (Resolve-Path -Path $IgnoreFile)) + } + else { + if ($PSBoundParameters.ContainsKey('Recurse') -or + $PSBoundParameters.ContainsKey('ProjectPath')) { + $getFileListSplat.Add('Recurse', $true) + } } $scriptsToTest += GetFileList @getFileListSplat -Extension '.ps1' diff --git a/Source/PSQualityCheck/private/GetFileList.ps1 b/Source/PSQualityCheck/private/GetFileList.ps1 index 0232e51..0551519 100644 --- a/Source/PSQualityCheck/private/GetFileList.ps1 +++ b/Source/PSQualityCheck/private/GetFileList.ps1 @@ -15,6 +15,9 @@ function GetFileList { .PARAMETER Recurse A switch specifying whether or not to recursively search the path specified + .PARAMETER IgnoreFile + A path to a .psqcignore file (.gitignore file format) for ignoring files + .EXAMPLE $files = GetFileList -Path 'c:\folder' -Extension ".ps1" @@ -29,25 +32,32 @@ function GetFileList { [parameter(Mandatory = $true)] [string]$Extension, [parameter(Mandatory = $false)] - [switch]$Recurse + [switch]$Recurse, + [parameter(Mandatory = $false)] + [string]$IgnoreFile ) $Extension = $Extension - $FileNameArray = @() - if (Test-Path -Path $Path) { - $gciSplat = @{ - 'Path' = $Path - 'Exclude' = "*.Tests.*" + $FileNameArray = @() + + if ($PSBoundParameters.ContainsKey('IgnoreFile')) { + $SelectedFilesArray = Get-FilteredChildItem -Path $Path -IgnoreFileName $IgnoreFile } - if ($PSBoundParameters.ContainsKey('Recurse')) { - $gciSplat.Add('Recurse', $true) + else { + $gciSplat = @{ + 'Path' = $Path + 'Exclude' = "*.Tests.*" + } + if ($PSBoundParameters.ContainsKey('Recurse')) { + $gciSplat.Add('Recurse', $true) + } + $SelectedFilesArray = Get-ChildItem @gciSplat } - $SelectedFilesArray = Get-ChildItem @gciSplat | Where-Object { $_.Extension -eq $Extension } | Select-Object -Property FullName - $SelectedFilesArray | ForEach-Object { $FileNameArray += [string]$_.FullName } + $SelectedFilesArray | Where-Object { $_.Extension -eq $Extension } | Select-Object -Property FullName | ForEach-Object { $FileNameArray += [string]$_.FullName } } From 7d75bf3ef6c7d23a77cce9d10992c79b6813ff13 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Sat, 24 Apr 2021 20:00:47 +0100 Subject: [PATCH 10/27] Added Ignore file example --- Source/PSQualityCheck/private/GetFileList.ps1 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/PSQualityCheck/private/GetFileList.ps1 b/Source/PSQualityCheck/private/GetFileList.ps1 index 0551519..aba8800 100644 --- a/Source/PSQualityCheck/private/GetFileList.ps1 +++ b/Source/PSQualityCheck/private/GetFileList.ps1 @@ -23,6 +23,9 @@ function GetFileList { .EXAMPLE $files = GetFileList -Path 'c:\folder' -Extension ".ps1" -Recurse + + .EXAMPLE + $files = GetFileList -Path 'c:\folder' -IgnoreFile ".psqcignore" #> [CmdletBinding()] [OutputType([System.Object[]])] From 5c847a2e9a88eef29bd3c7009a59cc3722bf82dc Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Sat, 24 Apr 2021 20:03:59 +0100 Subject: [PATCH 11/27] Added example for ProjectPath with IgnoreFile --- .../Public/Invoke-PSQualityCheck.ps1 | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 b/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 index d05aaf7..6dc8fc0 100644 --- a/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 +++ b/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 @@ -45,53 +45,58 @@ function Invoke-PSQualityCheck { A path to the HelpRules parameter file .PARAMETER IgnoreFile - A path to the .psqcignore file which excludes files/path from the tests + A path to the .psqcignore file which excludes files/path from the tests. This is in the .gitignore format .EXAMPLE Invoke-PSQualityCheck -Path 'C:\Scripts' - This will call the quality Data on single path + This will call the quality checks on single path .EXAMPLE Invoke-PSQualityCheck -Path 'C:\Scripts' -Recurse - This will call the quality Data on single path and sub folders + This will call the quality checks on single path and sub folders .EXAMPLE Invoke-PSQualityCheck -Path @('C:\Scripts', 'C:\MoreScripts') - This will call the quality Data with multiple paths + This will call the quality checks with multiple paths + + .EXAMPLE + Invoke-PSQualityCheck -ProjectPath 'C:\Project' -IgnoreFile ".psqcignore" + + This will call the project quality checks on the C:\Project folder with the .psqcignore file .EXAMPLE Invoke-PSQualityCheck -File 'C:\Scripts\Script.ps1' - This will call the quality Data with single script file + This will call the quality checks with single script file .EXAMPLE Invoke-PSQualityCheck -File 'C:\Scripts\Script.psm1' - This will call the quality Data with single module file + This will call the quality checks with single module file .EXAMPLE Invoke-PSQualityCheck -File 'C:\Scripts\Script.psd1' - This will call the quality Data with single datafile file + This will call the quality checks with single datafile file Note: The datafile test will fail as it is not a file that is accepted for testing .EXAMPLE Invoke-PSQualityCheck -File @('C:\Scripts\Script.ps1','C:\Scripts\Script2.ps1') - This will call the quality Data with multiple files. Files can be either scripts or modules + This will call the quality checks with multiple files. Files can be either scripts or modules .EXAMPLE Invoke-PSQualityCheck -File 'C:\Scripts\Script.ps1' -ScriptAnalyzerRulesPath 'C:\ScriptAnalyzerRulesPath' - This will call the quality Data with single file and the extra PSScriptAnalyzer rules + This will call the quality checks with single file and the extra PSScriptAnalyzer rules .EXAMPLE Invoke-PSQualityCheck -Path 'C:\Scripts' -ShowCheckResults - This will display a summary of the Data performed (example below uses sample data): + This will display a summary of the checks performed (example below uses sample data): Name Files Tested Total Passed Failed Skipped ---- ------------ ----- ------ ------ ------- @@ -100,7 +105,7 @@ function Invoke-PSQualityCheck { Extracted function script tests 22 330 309 0 21 Total 24 346 325 0 21 - For those who have spotted that the Total files tested isn't a total of the rows above, this is because the Module Tests and Extracting function Tests operate on the same file and are then not counted twice + For those who have spotted that the Total files tested isn't a total of the rows above, this is because the Module Tests and Extracting function Tests operate on the same file and are not counted twice .LINK Website: https://github.com/andrewrdavidson/PSQualityCheck From c934dbfec80e41a6d370190f37d0ba9180b840d5 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Sun, 25 Apr 2021 16:28:46 +0100 Subject: [PATCH 12/27] Fixes for non-function script files --- Source/PSQualityCheck/data/Script.Checks.ps1 | 3 +- .../PSQualityCheck/private/GetFileContent.ps1 | 45 ++++++++++--------- 2 files changed, 25 insertions(+), 23 deletions(-) diff --git a/Source/PSQualityCheck/data/Script.Checks.ps1 b/Source/PSQualityCheck/data/Script.Checks.ps1 index c1a025e..c42d288 100644 --- a/Source/PSQualityCheck/data/Script.Checks.ps1 +++ b/Source/PSQualityCheck/data/Script.Checks.ps1 @@ -44,11 +44,12 @@ BeforeDiscovery { Describe "Script Tests" -Tag "Script" { - Context "Script: <_.Name> at <_.Directory>" -Foreach $scriptFiles { + Context "Script: <_.Name> at <_.Directory>" -ForEach $scriptFiles { BeforeAll { $scriptFile = $_.FullName + $fileContent = GetFileContent -Path $scriptFile if (-not([string]::IsNullOrEmpty($fileContent))) { diff --git a/Source/PSQualityCheck/private/GetFileContent.ps1 b/Source/PSQualityCheck/private/GetFileContent.ps1 index 16dadf0..0b1b8ab 100644 --- a/Source/PSQualityCheck/private/GetFileContent.ps1 +++ b/Source/PSQualityCheck/private/GetFileContent.ps1 @@ -38,51 +38,52 @@ function GetFileContent { $parsedFunctions = @($parsedFileFunctions | Where-Object { $_.Type -eq "Keyword" -and $_.Content -like 'function' }) - if ([string]::IsNullOrEmpty($parsedFunctions) -or $parsedFunctions.Count -eq 0) { - throw "No functions found in file, file is invalid" - } - if ($parsedFunctions.Count -gt 1) { throw "Too many functions in file, file is invalid" } - if ($fileContent.Count -gt 1) { + if ($parsedFunctions.Count -eq 0) { + $parsedFileContent = $fileContent + } + else { + if ($fileContent.Count -gt 1) { + + foreach ($function in $parsedFunctions) { - foreach ($function in $parsedFunctions) { + $startLine = ($function.StartLine) - $startLine = ($function.StartLine) + for ($line = $fileContent.Count - 1; $line -gt $function.StartLine; $line--) { - for ($line = $fileContent.Count - 1; $line -gt $function.StartLine; $line--) { + if ($fileContent[$line] -like "*}*") { - if ($fileContent[$line] -like "*}*") { + $endLine = $line + break - $endLine = $line - break + } } - } + for ($line = $startLine; $line -lt $endLine; $line++) { - for ($line = $startLine; $line -lt $endLine; $line++) { + $parsedFileContent += $fileContent[$line] - $parsedFileContent += $fileContent[$line] + if ($line -ne ($fileContent.Count - 1)) { + $parsedFileContent += "`r`n" + } - if ($line -ne ($fileContent.Count - 1)) { - $parsedFileContent += "`r`n" } } } + else { - } - else { + [int]$startBracket = $fileContent.IndexOf('{') + [int]$endBracket = $fileContent.LastIndexOf('}') - [int]$startBracket = $fileContent.IndexOf('{') - [int]$endBracket = $fileContent.LastIndexOf('}') - - $parsedFileContent = $fileContent.substring($startBracket + 1, $endBracket - 1 - $startBracket) + $parsedFileContent = $fileContent.substring($startBracket + 1, $endBracket - 1 - $startBracket) + } } } From 290e8935d8cdaea2a57c3fbededc34a09f2f5dda Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Sun, 25 Apr 2021 21:14:51 +0100 Subject: [PATCH 13/27] More fixes for functionless script files --- Source/PSQualityCheck/data/Script.Checks.ps1 | 2 +- Source/PSQualityCheck/private/GetFileContent.ps1 | 9 ++++++++- Source/PSQualityCheck/private/GetScriptParameter.ps1 | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Source/PSQualityCheck/data/Script.Checks.ps1 b/Source/PSQualityCheck/data/Script.Checks.ps1 index c42d288..6c4eb50 100644 --- a/Source/PSQualityCheck/data/Script.Checks.ps1 +++ b/Source/PSQualityCheck/data/Script.Checks.ps1 @@ -44,7 +44,7 @@ BeforeDiscovery { Describe "Script Tests" -Tag "Script" { - Context "Script: <_.Name> at <_.Directory>" -ForEach $scriptFiles { + Context "Script: <_.Name> at <_.Directory>" -Foreach $scriptFiles { BeforeAll { diff --git a/Source/PSQualityCheck/private/GetFileContent.ps1 b/Source/PSQualityCheck/private/GetFileContent.ps1 index 0b1b8ab..115cd08 100644 --- a/Source/PSQualityCheck/private/GetFileContent.ps1 +++ b/Source/PSQualityCheck/private/GetFileContent.ps1 @@ -43,7 +43,14 @@ function GetFileContent { } if ($parsedFunctions.Count -eq 0) { - $parsedFileContent = $fileContent + + for ($line = 0; $line -lt $fileContent.Count; $line++) { + + $parsedFileContent += $fileContent[$line] + $parsedFileContent += "`r`n" + + } + } else { if ($fileContent.Count -gt 1) { diff --git a/Source/PSQualityCheck/private/GetScriptParameter.ps1 b/Source/PSQualityCheck/private/GetScriptParameter.ps1 index af0face..0201b6c 100644 --- a/Source/PSQualityCheck/private/GetScriptParameter.ps1 +++ b/Source/PSQualityCheck/private/GetScriptParameter.ps1 @@ -16,7 +16,7 @@ function GetScriptParameter { [OutputType([System.Exception], [HashTable])] param ( [parameter(Mandatory = $true)] - [String]$Content + [String[]]$Content ) try { From 37293c3dd5500097ab8a83821258b4a8d84929fa Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Mon, 26 Apr 2021 00:20:43 +0100 Subject: [PATCH 14/27] Fix not applying ignore file --- Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 b/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 index 6dc8fc0..edf84b9 100644 --- a/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 +++ b/Source/PSQualityCheck/Public/Invoke-PSQualityCheck.ps1 @@ -290,7 +290,15 @@ function Invoke-PSQualityCheck { # Test whether the item is a file (also tells us if it exists) if (Test-Path -Path $item -PathType Leaf) { - $itemProperties = Get-ChildItem -Path $item + $getFilteredItemSplat = @{ + 'Path' = $item + } + + if ($PSBoundParameters.ContainsKey('IgnoreFile')) { + $getFilteredItemSplat.Add('IgnoreFile', (Resolve-Path -Path $IgnoreFile)) + } + + $itemProperties = Get-FilteredChildItem @getFilteredItemSplat switch ($itemProperties.Extension) { From 511b0fbc8d4621813949f6f1a86aca3d29c69f16 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Mon, 26 Apr 2021 10:32:44 +0100 Subject: [PATCH 15/27] Minor tidy --- .../en-US/aboutPSQualityCheck.help.txt | 28 ------------------- install.depend.ps1 | 6 ++-- 2 files changed, 3 insertions(+), 31 deletions(-) delete mode 100644 Source/PSQualityCheck/en-US/aboutPSQualityCheck.help.txt diff --git a/Source/PSQualityCheck/en-US/aboutPSQualityCheck.help.txt b/Source/PSQualityCheck/en-US/aboutPSQualityCheck.help.txt deleted file mode 100644 index fabbc4e..0000000 --- a/Source/PSQualityCheck/en-US/aboutPSQualityCheck.help.txt +++ /dev/null @@ -1,28 +0,0 @@ -TOPIC - about_PSQualityCheck - -SHORT DESCRIPTION - Common set of tools. - -LONG DESCRIPTION - This project - -EXAMPLES - PS C:\> Build-Module -SourcePath .\ModuleBuilder\Source\build.psd1 - - This will create a versioned folder of the module with ModuleBuilder.psm1 containing all functions - from the Private and Public folder, an updated ModuleBuilder.psd1 module manifest with the FunctionsToExport - correctly populated with all functions from the Public Folder. - -NOTE: - nothing. - -TROUBLESHOOTING NOTE: - Look out on the Github repository for issues and new releases. - -SEE ALSO - - https://github.com/ - -KEYWORDS - Module - diff --git a/install.depend.ps1 b/install.depend.ps1 index bab344c..839a5c5 100644 --- a/install.depend.ps1 +++ b/install.depend.ps1 @@ -12,11 +12,11 @@ else { } # Install build dependencies -$psdependencyConfigPath = Join-Path -Path $PSScriptRoot -ChildPath 'install.depend.psd1' -Write-Output "Checking / resolving module dependencies from [$psdependencyConfigPath]..." +$psDependencyConfigPath = Join-Path -Path $PSScriptRoot -ChildPath 'install.depend.psd1' +Write-Output "Checking / resolving module dependencies from [$psDependencyConfigPath]..." Import-Module -Name 'PSDepend' $invokePSDependParams = @{ - Path = $psdependencyConfigPath + Path = $psDependencyConfigPath Import = $true Confirm = $false Install = $true From f63a05a0defbf715f2ac77d988e1d9486dca9343 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Mon, 26 Apr 2021 10:44:49 +0100 Subject: [PATCH 16/27] Fix build to import Cofl.Util module --- build.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/build.ps1 b/build.ps1 index 4dbc89f..23de97b 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,5 +1,6 @@ Import-Module -Name Pester -MinimumVersion 5.1.0 Import-Module -Name PSQualityCheck -MinimumVersion 1.3.0 +Import-Module -Name Cofl.Util -MinimumVersion 1.2.2 $InformationPreference = 'Continue' From 49b046650f017fa2bc822b5cb05c55634d851613 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Tue, 27 Apr 2021 22:19:35 +0100 Subject: [PATCH 17/27] New build process and fixes to installing dependencies --- Source/PSQualityCheck/build.psd1 | 2 +- build-functions.psm1 | 149 ++++++++++++++++++++ build.ps1 | 226 ++++++++++++++----------------- install.depend.ps1 | 19 ++- install.depend.psd1 | 1 - 5 files changed, 266 insertions(+), 131 deletions(-) create mode 100644 build-functions.psm1 diff --git a/Source/PSQualityCheck/build.psd1 b/Source/PSQualityCheck/build.psd1 index bffba1f..2927f8b 100644 --- a/Source/PSQualityCheck/build.psd1 +++ b/Source/PSQualityCheck/build.psd1 @@ -3,7 +3,7 @@ @{ ModuleManifest = "PSQualityCheck.psd1" # Subsequent relative paths are to the ModuleManifest - OutputDirectory = "../../artifacts/PSQualityCheck" + OutputDirectory = "../../build/PSQualityCheck" VersionedOutputDirectory = $true CopyDirectories = @('data', 'bin') } diff --git a/build-functions.psm1 b/build-functions.psm1 new file mode 100644 index 0000000..528a240 --- /dev/null +++ b/build-functions.psm1 @@ -0,0 +1,149 @@ +function Get-FunctionFileContent { + + [CmdletBinding()] + [OutputType([System.String[]])] + param ( + [parameter(Mandatory = $true)] + [string]$Path + ) + + try { + $fileContent = Get-Content -Path $Path + $parserErrors = $null + if ([string]::IsNullOrEmpty($fileContent)) { + $parsedFileFunctions = @() + } + else { + $parsedFileFunctions = [System.Management.Automation.PSParser]::Tokenize($fileContent, [ref]$parserErrors) + } + $parsedFunctions = ($parsedFileFunctions | Where-Object { $_.Type -eq "Keyword" -and $_.Content -like 'function' }) + if ($parsedFunctions.Count -gt 1) { + throw "Too many functions in file, file is invalid" + } + if ($parsedFunctions.Count -eq 1) { + if ($fileContent.Count -gt 1) { + foreach ($function in $parsedFunctions) { + $startLine = ($function.StartLine) + for ($line = $fileContent.Count; $line -gt $function.StartLine; $line--) { + if ($fileContent[$line] -like "*}*") { + $endLine = $line + break + } + } + for ($line = $startLine; $line -lt $endLine; $line++) { + $parsedFileContent += $fileContent[$line] + if ($line -ne ($fileContent.Count - 1)) { + $parsedFileContent += "`r`n" + } + } + } + } + else { + [int]$startBracket = $fileContent.IndexOf('{') + [int]$endBracket = $fileContent.LastIndexOf('}') + $parsedFileContent = $fileContent.substring($startBracket + 1, $endBracket - 1 - $startBracket) + } + } + else { + if ($fileContent.Count -gt 1) { + for ($line = 0; $line -lt $fileContent.Count; $line++) { + $parsedFileContent += $fileContent[$line] + if ($line -ne ($fileContent.Count - 1)) { + $parsedFileContent += "`r`n" + } + } + } + else { + $parsedFileContent = $fileContent + } + } + } + catch { + throw + } + return $parsedFileContent +} + +function Install-BuiltModule { + + [CmdletBinding()] + [OutputType([System.Void])] + param ( + [parameter(Mandatory = $true)] + [string]$Module + ) + + # $Module = "PSTemplate" + + Install-Module -Name $Module -Repository "$Module-local" + +} + +function Publish-BuiltModule { + + [CmdletBinding()] + [OutputType([System.Void])] + param ( + [parameter(Mandatory = $true)] + [string]$Module, + [parameter(Mandatory = $true)] + [string]$ArtifactsFolder, + [string]$BuildFolder, + [switch]$Clean + ) + + # $Module = "PSTemplate" + $Version = (Import-PowerShellDataFile -Path ".\source\$Module\$Module.psd1").ModuleVersion + + # QUERY: Need this? + # New-Item -ItemType Directory -Path ./artifacts -Force + # $ArtifactsFolder = Resolve-Path -Path "./artifacts" + if ($PSBoundParameters.ContainsKey('Clean')) { + Remove-Item -Path $ArtifactsFolder -Recurse -Force + New-Item -Path $ArtifactsFolder -ItemType Directory + } + + Register-PSRepository -Name "$Module-local" -SourceLocation $ArtifactsFolder -InstallationPolicy Trusted + + Publish-Module -Path "$BuildFolder\$Module\$Version" -Repository "$Module-local" -NuGetApiKey 'use real NuGetApiKey for real nuget server here' + + # Install-Module -Name "$($Module)" -Repository "$($Module)-local" + + # Get-PSRepository + +} + +function Uninstall-BuiltModule { + + [CmdletBinding()] + [OutputType([System.Void])] + param ( + [parameter(Mandatory = $true)] + [string]$Module + ) + + # $Module = "PSTemplate" + + Uninstall-Module -Name $Module + + +} + +function Unpublish-BuiltModule { + + [CmdletBinding()] + [OutputType([System.Void])] + param ( + [parameter(Mandatory = $true)] + [string]$Module + ) + + # $Module = 'PSTemplate' + + Unregister-PSRepository -Name "$Module-local" + + # Remove-Item -Path "./artifacts" -Recurse -Force + + # Get-PSRepository + +} diff --git a/build.ps1 b/build.ps1 index 23de97b..215afbb 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,8 +1,9 @@ Import-Module -Name Pester -MinimumVersion 5.1.0 -Import-Module -Name PSQualityCheck -MinimumVersion 1.3.0 Import-Module -Name Cofl.Util -MinimumVersion 1.2.2 +Import-Module -Name ".\build-functions.psm1" $InformationPreference = 'Continue' +$ErrorActionPreference = 'Stop' # PesterConfiguration $PesterConfiguration = [PesterConfiguration]::Default @@ -18,87 +19,64 @@ $ScriptRules = @( #, './Analyzer/InjectionHunter/' ) -function Get-FunctionFileContent { - [CmdletBinding()] - [OutputType([System.String[]])] - param ( - [parameter(Mandatory = $true)] - [string]$Path - ) - - try { - $fileContent = Get-Content -Path $Path - $parserErrors = $null - if ([string]::IsNullOrEmpty($fileContent)) { - $parsedFileFunctions = @() - } - else { - $parsedFileFunctions = [System.Management.Automation.PSParser]::Tokenize($fileContent, [ref]$parserErrors) - } - $parsedFunctions = ($parsedFileFunctions | Where-Object { $_.Type -eq "Keyword" -and $_.Content -like 'function' }) - if ($parsedFunctions.Count -gt 1) { - throw "Too many functions in file, file is invalid" - } - if ($parsedFunctions.Count -eq 1) { - if ($fileContent.Count -gt 1) { - foreach ($function in $parsedFunctions) { - $startLine = ($function.StartLine) - for ($line = $fileContent.Count; $line -gt $function.StartLine; $line--) { - if ($fileContent[$line] -like "*}*") { - $endLine = $line - break - } - } - for ($line = $startLine; $line -lt $endLine; $line++) { - $parsedFileContent += $fileContent[$line] - if ($line -ne ($fileContent.Count - 1)) { - $parsedFileContent += "`r`n" - } - } - } - } - else { - [int]$startBracket = $fileContent.IndexOf('{') - [int]$endBracket = $fileContent.LastIndexOf('}') - $parsedFileContent = $fileContent.substring($startBracket + 1, $endBracket - 1 - $startBracket) - } - } - else { - if ($fileContent.Count -gt 1) { - for ($line = 0; $line -lt $fileContent.Count; $line++) { - $parsedFileContent += $fileContent[$line] - if ($line -ne ($fileContent.Count - 1)) { - $parsedFileContent += "`r`n" - } - } - } - else { - $parsedFileContent = $fileContent - } - } +$projectPath = Resolve-Path -Path ".\" +$sourcePath = Resolve-Path -Path "$projectPath\source" +$scriptsPath = Resolve-Path -Path "$projectPath\scripts" +$testsPath = Resolve-Path -Path "$projectPath\tests" +$buildFolder = Resolve-Path -Path "$projectPath\build" +$artifactsFolder = Resolve-Path -Path "$projectPath\artifacts" +$ignoreFile = Resolve-Path -Path ".psqcignore" +$moduleName = "PSQualityCheck" + +$modules = Get-ChildItem -Path $sourcePath -Directory + +# Create a built version of the module (pre-testing) +# to allow us to use this module (PSQualityCheck) to test itself whist building +try { + foreach ($module in $modules) { + $buildPropertiesFile = "$sourcePath\$($module.BaseName)\build.psd1" + Write-Host $buildPropertiesFile + Build-Module -SourcePath $buildPropertiesFile } - catch { - throw - } - return $parsedFileContent +} +catch { + throw "Build failed" + break } -# Project Based -# $qualityResult = Invoke-PSQualityCheck -ProjectPath '.\' -ScriptAnalyzerRulesPath $ScriptRules -HelpRulesPath '.\HelpRules.psd1' -Passthru -PesterConfiguration $PesterConfiguration +Publish-BuiltModule -Module $moduleName -ArtifactsFolder $artifactsFolder -BuildFolder $buildFolder -Clean -# if ($qualityResult.Script.FailedCount -eq 0 -and $qualityResult.Project.FailedCount -eq 0) { -if ($true) { +Install-BuiltModule - $Modules = Get-ChildItem -Path ".\Source" -Directory +Import-Module -Name $moduleName -Repository "$moduleName-Local" - $functionResults = @() +# Start of Project Based checks +$qualityCheckSplat = @{ + 'ProjectPath' = $projectPath + 'ScriptAnalyzerRulesPath' = $ScriptRules + 'HelpRulesPath' = (Resolve-Path -Path '.\HelpRules.psd1') + 'Passthru' = $true + 'PesterConfiguration' = $PesterConfiguration + 'IgnoreFile' = $ignoreFile +} +$qualityResult = Invoke-PSQualityCheck @qualityCheckSplat +# End of Project Based checks - foreach ($module in $Modules) { +# Running tests +if ($qualityResult.Script.FailedCount -eq 0 -and $qualityResult.Project.FailedCount -eq 0) { - $functionFiles = @() - # $privateFunctionFiles = @() + $testResults = @() - $functionFiles += Get-ChildItem -Path (Join-Path -Path $Module.FullName -ChildPath "public") + # Run the unit tests for the public functions of any modules in the project + + # Get the modules (the directories in the Source folder) + $modules = Get-ChildItem -Path $sourcePath -Directory + + foreach ($module in $modules) { + + # Get the public functions (minus any excluded by the ignore file) + $functionFiles = @() + $functionFiles += Get-FilteredChildItem -Path (Join-Path -Path $module.FullName -ChildPath "public") -IgnoreFileName $ignoreFile # If there are any scripts in the private folder with corresponding tests then run those too # $privateFunctionFiles += Get-ChildItem -Path (Join-Path -Path $Module.FullName -ChildPath "private") @@ -112,92 +90,90 @@ if ($true) { foreach ($function in $functionFiles) { - # Write-Host ".\tests\unit\$($module.BaseName)\$($function.BaseName).Tests.psd1" -ForegroundColor Yellow - # Write-Host $function.FullName -ForegroundColor Yellow - $fileContent = Get-FunctionFileContent -Path $function.FullName . "$($function.FullName)" - $container = New-PesterContainer -Path ".\tests\unit\$($module.BaseName)\$($function.BaseName).Tests.ps1" -Data @{FileContent = $fileContent } + $container = New-PesterContainer -Path "$testsPath\unit\$($module.BaseName)\$($function.BaseName).Tests.ps1" -Data @{FileContent = $fileContent } $PesterConfiguration.Run.Container = $container - $functionResults += Invoke-Pester -Configuration $PesterConfiguration + $testResults += Invoke-Pester -Configuration $PesterConfiguration } } + + # TODO: Add integration tests here + } else { - # Write-Information 'Functions not tested - there were project quality check errors' # Write-Warning -Message "Project Quality Check fails" - Write-Error -Message "Project Quality Check fails" + Write-Error -Message "Project quality check failed" break - } +# End of running tests -$failedCount = 0 +# Start of module build +# Build the module(s) only if there are no unit/integration test failures +$testFailedCount = 0 -foreach ($result in $functionResults) { - $failedCount += $result.FailedCount +foreach ($result in $testResults) { + $testFailedCount += $result.FailedCount } -if ($failedCount -eq 0 ) { - - foreach ($module in $Modules) { - - $buildFile = ".\source\$($module.BaseName)\build.psd1" - Write-Host $buildFile -ForegroundColor Yellow - - Build-Module -SourcePath $buildFile - - } +if ($testFailedCount -eq 0 ) { + # foreach ($module in $modules) { + # $buildPropertiesFile = ".\source\$($module.BaseName)\build.psd1" + # Build-Module -SourcePath $buildPropertiesFile + # } } else { - - Write-Information 'Modules not build - there were errors' + Write-Error -Message 'One or more module were not built because there were function unit test errors' throw - } - # End of module build -# Script checks -$scriptFiles = Get-ChildItem -Path ".\Scripts" -Filter "*.ps1" -Recurse +# Run any available unit tests for files in Scripts folder +$scriptFiles = @() +$testResults = @() +$scriptFiles += Get-FilteredChildItem -Path $scriptsPath -IgnoreFileName $ignoreFile +foreach ($scriptFile in $scriptFiles) { -$scriptResults = @() + $scriptFolder = $scriptFile.FullName -ireplace [regex]::Escape($scriptsPath.Path), '' + $scriptFolder = $scriptFolder -ireplace [regex]::Escape($scriptFile.Name), '' -foreach ($script in $scriptFiles) { + $fileContent = Get-FunctionFileContent -Path $scriptFile.FullName - $Result = Invoke-PSQualityCheck -File $script.FullName -ScriptAnalyzerRulesPath $ScriptRules -HelpRulesPath '.\HelpRules.psd1' -Passthru -PesterConfiguration $PesterConfiguration + $container = New-PesterContainer -Path "$testsPath\scripts$scriptFolder\$($scriptFile.BaseName).Tests.ps1" -Data @{FileContent = $fileContent } + $PesterConfiguration.Run.Container = $container - $folder = Split-Path -Path $script.DirectoryName -Leaf + $testResults += Invoke-Pester -Configuration $PesterConfiguration - Write-Host ".\tests\scripts\$folder\$($script.BaseName).Tests.ps1" - if ((Test-Path -Path ".\tests\scripts\$folder\$($script.BaseName).Tests.ps1") -and $result.Script.FailedCount -eq 0) { +} - $fileContent = Get-FunctionFileContent -Path $script.FullName +$testFailedCount = 0 - $container = New-PesterContainer -Path ".\tests\scripts\$folder\$($script.BaseName).Tests.ps1" -Data @{FileContent = $fileContent } - $PesterConfiguration.Run.Container = $container +foreach ($result in $testResults) { + $testFailedCount += $result.FailedCount +} - $scriptResults += Invoke-Pester -Configuration $PesterConfiguration +# If there are no script failures then copy the scripts to the Artifacts folder +if ($testFailedCount -eq 0) { + $builtScriptsFolder = Join-Path -Path $buildFolder -ChildPath "scripts" + $compressSplat = @{ + Path = $builtScriptsFolder + CompressionLevel = "Fastest" + DestinationPath = "$artifactsFolder\scripts.zip" } - + Compress-Archive @compressSplat } +else { + Write-Error -Message "Scripts were not copied to artifacts folder because there were failed unit tests" + break +} +# End of script copy +Uninstall-BuiltModule -Module $moduleName +Unpublish-BuiltModule -Module $moduleName - - -# $Result = Invoke-PSQualityCheck -Path @('.\Scripts') -recurse -ScriptAnalyzerRulesPath $ScriptRules -HelpRulesPath '.\HelpRules.psd1' -Passthru -PesterConfiguration $PesterConfiguration - -# if ($Result.Script.FailedCount -eq 0) { - -# $Dest = ".\artifacts" -# # Copy Script files to release folder -# New-Item -ItemType Directory -Force -Path $Dest -# Copy-Item ".\Scripts\*.*" -Destination $Dest -Recurse -Force -# } -# else { -# Write-Information 'Scripts not exported - there were errors' -# } +### END OF SCRIPT diff --git a/install.depend.ps1 b/install.depend.ps1 index 839a5c5..7a30b8e 100644 --- a/install.depend.ps1 +++ b/install.depend.ps1 @@ -1,4 +1,14 @@ +if (-not ($NuGetPath = (Get-Command 'nuget.exe' -ErrorAction SilentlyContinue).Path)) { + if (-not (Test-Path -Path ".\bin" -ErrorAction SilentlyContinue)) { + New-Item -Path "bin" -ItemType Directory + } + + $NuGetPath = Resolve-Path -Path ".\bin" + $NuGetFile = Join-Path -Path $NuGetPath -ChildPath "nuget.exe" + Invoke-WebRequest -Uri 'https://dist.nuget.org/win-x86-commandline/latest/nuget.exe' -OutFile $NuGetFile + $env:Path += "$NuGetPath;" +} # Bootstrap environment Get-PackageProvider -Name 'NuGet' -ForceBootstrap | Out-Null @@ -11,15 +21,16 @@ else { Write-Output "`nPSDepend already installed...skipping." } + # Install build dependencies -$psDependencyConfigPath = Join-Path -Path $PSScriptRoot -ChildPath 'install.depend.psd1' -Write-Output "Checking / resolving module dependencies from [$psDependencyConfigPath]..." +$psdependencyConfigPath = Join-Path -Path $PSScriptRoot -ChildPath 'install.depend.psd1' +Write-Output "Checking / resolving module dependencies from [$psdependencyConfigPath]..." Import-Module -Name 'PSDepend' $invokePSDependParams = @{ - Path = $psDependencyConfigPath + Path = $psdependencyConfigPath Import = $true Confirm = $false Install = $true - Verbose = $true + Verbose = $false } Invoke-PSDepend @invokePSDependParams diff --git a/install.depend.psd1 b/install.depend.psd1 index e7ffa37..b8e3d58 100644 --- a/install.depend.psd1 +++ b/install.depend.psd1 @@ -14,7 +14,6 @@ ModuleBuilder = 'Latest' PowerShellGet = 'Latest' PSScriptAnalyzer = 'Latest' - PSQualityCheck = 'Latest' InvokeBuild = 'Latest' "Cofl.Util" = 'Latest' } From c281094295fe64f3cc2cfbcc996a9245aa6c9008 Mon Sep 17 00:00:00 2001 From: leparduk Date: Wed, 28 Apr 2021 10:12:52 +0100 Subject: [PATCH 18/27] fixed build issues for existing and missing items --- .gitignore | 3 + HelpRules.psd1 | 72 +++++++++++++++++++ Source/PSQualityCheck/private/GetFileList.ps1 | 4 +- build.ps1 | 34 +++++++-- 4 files changed, 105 insertions(+), 8 deletions(-) create mode 100644 HelpRules.psd1 diff --git a/.gitignore b/.gitignore index dfcfd56..3bdf7f8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +/build +/artifacts + ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. ## diff --git a/HelpRules.psd1 b/HelpRules.psd1 new file mode 100644 index 0000000..5c1ee03 --- /dev/null +++ b/HelpRules.psd1 @@ -0,0 +1,72 @@ +@{ + # HashTable of the keys that you want in your help comments + # If the test finds an element that does not appear in this list then the test will fail + + # Possible key elements + # '.SYNOPSIS' + # '.DESCRIPTION' + # '.PARAMETER' + # '.EXAMPLE' + # '.INPUTS' + # '.OUTPUTS' + # '.NOTES' + # '.LINK' + # '.COMPONENT' + # '.ROLE' + # '.FUNCTIONALITY' + # '.FORWARDHELPTARGETNAME' + # '.FORWARDHELPCATEGORY' + # '.REMOTEHELPRUNSPACE' + # '.EXTERNALHELP' + + # If a key is required then it must exist, and have between MinOccurrences and MaxOccurrences count + # The keys will be matched in the numerical sequence below + '1' = @{ + Key = '.SYNOPSIS' + Required = $true + MinOccurrences = 1 + MaxOccurrences = 1 + } + '2' = @{ + Key = '.DESCRIPTION' + Required = $true + MinOccurrences = 1 + MaxOccurrences = 1 + } + '3' = @{ + Key = '.PARAMETER' + Required = $false + MinOccurrences = 0 + MaxOccurrences = 99 + } + '4' = @{ + Key = '.EXAMPLE' + Required = $true + MinOccurrences = 1 + MaxOccurrences = 100 + } + '5' = @{ + Key = '.INPUTS' + Required = $false + MinOccurrences = 0 + MaxOccurrences = 0 + } + '6' = @{ + Key = '.OUTPUTS' + Required = $false + MinOccurrences = 0 + MaxOccurrences = 0 + } + '7' = @{ + Key = '.NOTES' + Required = $false + MinOccurrences = 0 + MaxOccurrences = 0 + } + '8' = @{ + Key = '.LINK' + Required = $false + MinOccurrences = 0 + MaxOccurrences = 99 + } +} diff --git a/Source/PSQualityCheck/private/GetFileList.ps1 b/Source/PSQualityCheck/private/GetFileList.ps1 index aba8800..afe27f8 100644 --- a/Source/PSQualityCheck/private/GetFileList.ps1 +++ b/Source/PSQualityCheck/private/GetFileList.ps1 @@ -24,8 +24,8 @@ function GetFileList { .EXAMPLE $files = GetFileList -Path 'c:\folder' -Extension ".ps1" -Recurse - .EXAMPLE - $files = GetFileList -Path 'c:\folder' -IgnoreFile ".psqcignore" + #.EXAMPLE + #$files = GetFileList -Path 'c:\folder' -IgnoreFile ".psqcignore" #> [CmdletBinding()] [OutputType([System.Object[]])] diff --git a/build.ps1 b/build.ps1 index 215afbb..687fa03 100644 --- a/build.ps1 +++ b/build.ps1 @@ -23,17 +23,30 @@ $projectPath = Resolve-Path -Path ".\" $sourcePath = Resolve-Path -Path "$projectPath\source" $scriptsPath = Resolve-Path -Path "$projectPath\scripts" $testsPath = Resolve-Path -Path "$projectPath\tests" -$buildFolder = Resolve-Path -Path "$projectPath\build" -$artifactsFolder = Resolve-Path -Path "$projectPath\artifacts" $ignoreFile = Resolve-Path -Path ".psqcignore" $moduleName = "PSQualityCheck" +$buildFolder = Join-Path -Path "$projectPath" -ChildPath "build" +$artifactsFolder = Join-Path -Path "$projectPath" -ChildPath "artifacts" + +if (-not (Test-Path -Path $artifactsFolder -ErrorAction SilentlyContinue)) { + New-Item -Path $artifactsFolder -ItemType "directory" -force +} +if (-not (Test-Path -Path $buildFolder -ErrorAction SilentlyContinue)) { + New-Item -Path $buildFolder -ItemType "directory" -force +} + $modules = Get-ChildItem -Path $sourcePath -Directory # Create a built version of the module (pre-testing) # to allow us to use this module (PSQualityCheck) to test itself whist building try { foreach ($module in $modules) { + + if ($module -in ((Get-Module) | Select-Object -Property Name)) { + Remove-Module $module + } + $buildPropertiesFile = "$sourcePath\$($module.BaseName)\build.psd1" Write-Host $buildPropertiesFile Build-Module -SourcePath $buildPropertiesFile @@ -44,11 +57,13 @@ catch { break } -Publish-BuiltModule -Module $moduleName -ArtifactsFolder $artifactsFolder -BuildFolder $buildFolder -Clean +if ("$moduleName-local" -in ((Get-PSRepository) | Select-Object -Property Name)) { + unRegister-PSRepository -Name "$moduleName-local" +} -Install-BuiltModule +Publish-BuiltModule -Module $moduleName -ArtifactsFolder $artifactsFolder -BuildFolder $buildFolder -Clean -Import-Module -Name $moduleName -Repository "$moduleName-Local" +Install-BuiltModule -Module $moduleName # Start of Project Based checks $qualityCheckSplat = @{ @@ -156,10 +171,17 @@ foreach ($result in $testResults) { $testFailedCount += $result.FailedCount } -# If there are no script failures then copy the scripts to the Artifacts folder +# If there are no script failures then copy the scripts to the build folder and archive to the Artifacts folder if ($testFailedCount -eq 0) { + $builtScriptsFolder = Join-Path -Path $buildFolder -ChildPath "scripts" + if (-not (Test-Path -Path $builtScriptsFolder -ErrorAction SilentlyContinue)) { + New-Item -Path $buildFolder -Name "scripts" -ItemType "directory" -force + } + + Copy-Item -Path "Scripts" -Destination $buildFolder -Recurse -Force -Container + $compressSplat = @{ Path = $builtScriptsFolder CompressionLevel = "Fastest" From a9efac7a7106b747f349d448d1b36d4cdf7c29c4 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Wed, 28 Apr 2021 16:34:03 +0100 Subject: [PATCH 19/27] Fix references to private functions --- Source/PSQualityCheck/data/Script.Checks.ps1 | 2 +- Source/PSQualityCheck/private/ConvertHelp.ps1 | 2 +- Source/PSQualityCheck/private/TestHelpTokensCountisValid.ps1 | 2 +- Source/PSQualityCheck/private/TestHelpTokensParamsMatch.ps1 | 2 +- Source/PSQualityCheck/private/TestHelpTokensTextIsValid.ps1 | 2 +- .../PSQualityCheck/private/TestParameterVariablesHaveType.ps1 | 2 +- Source/PSQualityCheck/private/TestRequiredToken.ps1 | 2 +- Source/PSQualityCheck/private/TestUnspecifiedToken.ps1 | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/PSQualityCheck/data/Script.Checks.ps1 b/Source/PSQualityCheck/data/Script.Checks.ps1 index 6c4eb50..02c3631 100644 --- a/Source/PSQualityCheck/data/Script.Checks.ps1 +++ b/Source/PSQualityCheck/data/Script.Checks.ps1 @@ -146,7 +146,7 @@ Describe "Script Tests" -Tag "Script" { # Note: Disabled because I'm questioning the validity of the rule. So many function haven't got a need for params # It "check script contains param attribute" -Tag "ContainsParam" { - # $paramCount = (@(Get-TokenMarker -ParsedContent $ParsedFile -Type "Keyword" -Content "param")).Count + # $paramCount = (@(GetTokenMarker -ParsedContent $ParsedFile -Type "Keyword" -Content "param")).Count # $paramCount | Should -Be 1 diff --git a/Source/PSQualityCheck/private/ConvertHelp.ps1 b/Source/PSQualityCheck/private/ConvertHelp.ps1 index 2426229..0947b7d 100644 --- a/Source/PSQualityCheck/private/ConvertHelp.ps1 +++ b/Source/PSQualityCheck/private/ConvertHelp.ps1 @@ -10,7 +10,7 @@ function ConvertHelp { A string containing the Help Comment .EXAMPLE - $helpObject = Convert-Help -Help $Help + $helpObject = ConvertHelp -Help $Help #> [CmdletBinding()] [OutputType([HashTable], [System.Exception])] diff --git a/Source/PSQualityCheck/private/TestHelpTokensCountisValid.ps1 b/Source/PSQualityCheck/private/TestHelpTokensCountisValid.ps1 index b7945e2..4554688 100644 --- a/Source/PSQualityCheck/private/TestHelpTokensCountisValid.ps1 +++ b/Source/PSQualityCheck/private/TestHelpTokensCountisValid.ps1 @@ -13,7 +13,7 @@ function TestHelpTokensCountIsValid { Path to the HelpRules file .EXAMPLE - Test-HelpTokensCountIsValid -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" + TestHelpTokensCountIsValid -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" .NOTES This function will only check the Min/Max counts of required help tokens diff --git a/Source/PSQualityCheck/private/TestHelpTokensParamsMatch.ps1 b/Source/PSQualityCheck/private/TestHelpTokensParamsMatch.ps1 index a41dcbf..e193295 100644 --- a/Source/PSQualityCheck/private/TestHelpTokensParamsMatch.ps1 +++ b/Source/PSQualityCheck/private/TestHelpTokensParamsMatch.ps1 @@ -13,7 +13,7 @@ function TestHelpTokensParamsMatch { A object containing the parameters from the param block .EXAMPLE - Test-HelpTokensParamsMatch -HelpTokens $HelpTokens -ParameterVariables $ParameterVariables + TestHelpTokensParamsMatch -HelpTokens $HelpTokens -ParameterVariables $ParameterVariables #> [CmdletBinding()] [OutputType([System.Exception], [System.String[]])] diff --git a/Source/PSQualityCheck/private/TestHelpTokensTextIsValid.ps1 b/Source/PSQualityCheck/private/TestHelpTokensTextIsValid.ps1 index 14af20f..642b97c 100644 --- a/Source/PSQualityCheck/private/TestHelpTokensTextIsValid.ps1 +++ b/Source/PSQualityCheck/private/TestHelpTokensTextIsValid.ps1 @@ -10,7 +10,7 @@ function TestHelpTokensTextIsValid { A array of tokens containing the tokens of the Help Comment .EXAMPLE - Test-HelpTokensTextIsValid -HelpTokens $HelpTokens + TestHelpTokensTextIsValid -HelpTokens $HelpTokens #> [CmdletBinding()] [OutputType([System.Exception], [System.Void])] diff --git a/Source/PSQualityCheck/private/TestParameterVariablesHaveType.ps1 b/Source/PSQualityCheck/private/TestParameterVariablesHaveType.ps1 index f4b34ea..c70a482 100644 --- a/Source/PSQualityCheck/private/TestParameterVariablesHaveType.ps1 +++ b/Source/PSQualityCheck/private/TestParameterVariablesHaveType.ps1 @@ -10,7 +10,7 @@ function TestParameterVariablesHaveType { A HashTable containing the parameters from the param block .EXAMPLE - Test-ParameterVariablesHaveType -ParameterVariables $ParameterVariables + TestParameterVariablesHaveType -ParameterVariables $ParameterVariables #> [CmdletBinding()] [OutputType([System.Exception], [System.Void])] diff --git a/Source/PSQualityCheck/private/TestRequiredToken.ps1 b/Source/PSQualityCheck/private/TestRequiredToken.ps1 index dc447dd..f2b76ca 100644 --- a/Source/PSQualityCheck/private/TestRequiredToken.ps1 +++ b/Source/PSQualityCheck/private/TestRequiredToken.ps1 @@ -13,7 +13,7 @@ function TestRequiredToken { Path to the HelpRules file .EXAMPLE - Test-RequiredToken -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" + TestRequiredToken -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" #> [CmdletBinding()] [OutputType([System.Exception], [System.Void])] diff --git a/Source/PSQualityCheck/private/TestUnspecifiedToken.ps1 b/Source/PSQualityCheck/private/TestUnspecifiedToken.ps1 index 647a069..38e91db 100644 --- a/Source/PSQualityCheck/private/TestUnspecifiedToken.ps1 +++ b/Source/PSQualityCheck/private/TestUnspecifiedToken.ps1 @@ -13,7 +13,7 @@ function TestUnspecifiedToken { Path to the HelpRules file .EXAMPLE - Test-UnspecifiedToken -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" + TestUnspecifiedToken -HelpTokens $HelpTokens -HelpRulesPath "C:\HelpRules" #> [CmdletBinding()] [OutputType([System.Exception], [System.Void])] From 4fba56e65f61d1802b26bf00c959e0df0de04faa Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Wed, 28 Apr 2021 16:34:41 +0100 Subject: [PATCH 20/27] Fix unit tests --- ...t-Help.Tests.ps1 => ConvertHelp.Tests.ps1} | 6 +- ...s1 => ExportFunctionsFromModule.Tests.ps1} | 16 +- ...ent.Tests.ps1 => GetFileContent.Tests.ps1} | 38 +-- ...leList.Tests.ps1 => GetFileList.Tests.ps1} | 36 +-- ...t.Tests.ps1 => GetFunctionCount.Tests.ps1} | 48 ++-- ...t.Tests.ps1 => GetParsedContent.Tests.ps1} | 14 +- ...File.Tests.ps1 => GetParsedFile.Tests.ps1} | 14 +- ...Tests.ps1 => GetScriptParameter.Tests.ps1} | 20 +- ...TagList.Tests.ps1 => GetTagList.Tests.ps1} | 0 ...Get-Token.Tests.ps1 => GetToken.Tests.ps1} | 70 ++--- ....Tests.ps1 => GetTokenComponent.Tests.ps1} | 14 +- ...ker.Tests.ps1 => GetTokenMarker.Tests.ps1} | 12 +- .../Test-ImportModuleIsValid.Tests.ps1 | 247 ------------------ ...1 => TestHelpTokensCountisValid.Tests.ps1} | 14 +- ...s1 => TestHelpTokensParamsMatch.Tests.ps1} | 24 +- ...s1 => TestHelpTokensTextIsValid.Tests.ps1} | 22 +- .../TestImportModuleIsValid.Tests.ps1 | 247 ++++++++++++++++++ ... TestParameterVariablesHaveType.Tests.ps1} | 14 +- ....Tests.ps1 => TestRequiredToken.Tests.ps1} | 12 +- ...sts.ps1 => TestUnspecifiedToken.Tests.ps1} | 14 +- 20 files changed, 441 insertions(+), 441 deletions(-) rename Tests/Unit/PSQualityCheck/{Convert-Help.Tests.ps1 => ConvertHelp.Tests.ps1} (98%) rename Tests/Unit/PSQualityCheck/{Export-FunctionsFromModule.Tests.ps1 => ExportFunctionsFromModule.Tests.ps1} (86%) rename Tests/Unit/PSQualityCheck/{Get-FileContent.Tests.ps1 => GetFileContent.Tests.ps1} (79%) rename Tests/Unit/PSQualityCheck/{Get-FileList.Tests.ps1 => GetFileList.Tests.ps1} (79%) rename Tests/Unit/PSQualityCheck/{Get-FunctionCount.Tests.ps1 => GetFunctionCount.Tests.ps1} (67%) rename Tests/Unit/PSQualityCheck/{Get-ParsedContent.Tests.ps1 => GetParsedContent.Tests.ps1} (91%) rename Tests/Unit/PSQualityCheck/{Get-ParsedFile.Tests.ps1 => GetParsedFile.Tests.ps1} (92%) rename Tests/Unit/PSQualityCheck/{Get-ScriptParameter.Tests.ps1 => GetScriptParameter.Tests.ps1} (81%) rename Tests/Unit/PSQualityCheck/{Get-TagList.Tests.ps1 => GetTagList.Tests.ps1} (100%) rename Tests/Unit/PSQualityCheck/{Get-Token.Tests.ps1 => GetToken.Tests.ps1} (59%) rename Tests/Unit/PSQualityCheck/{Get-TokenComponent.Tests.ps1 => GetTokenComponent.Tests.ps1} (85%) rename Tests/Unit/PSQualityCheck/{Get-TokenMarker.Tests.ps1 => GetTokenMarker.Tests.ps1} (91%) delete mode 100644 Tests/Unit/PSQualityCheck/Test-ImportModuleIsValid.Tests.ps1 rename Tests/Unit/PSQualityCheck/{Test-HelpTokensCountisValid.Tests.ps1 => TestHelpTokensCountisValid.Tests.ps1} (93%) rename Tests/Unit/PSQualityCheck/{Test-HelpTokensParamsMatch.Tests.ps1 => TestHelpTokensParamsMatch.Tests.ps1} (87%) rename Tests/Unit/PSQualityCheck/{Test-HelpTokensTextIsValid.Tests.ps1 => TestHelpTokensTextIsValid.Tests.ps1} (91%) create mode 100644 Tests/Unit/PSQualityCheck/TestImportModuleIsValid.Tests.ps1 rename Tests/Unit/PSQualityCheck/{Test-ParameterVariablesHaveType.Tests.ps1 => TestParameterVariablesHaveType.Tests.ps1} (76%) rename Tests/Unit/PSQualityCheck/{Test-RequiredToken.Tests.ps1 => TestRequiredToken.Tests.ps1} (95%) rename Tests/Unit/PSQualityCheck/{Test-UnspecifiedToken.Tests.ps1 => TestUnspecifiedToken.Tests.ps1} (94%) diff --git a/Tests/Unit/PSQualityCheck/Convert-Help.Tests.ps1 b/Tests/Unit/PSQualityCheck/ConvertHelp.Tests.ps1 similarity index 98% rename from Tests/Unit/PSQualityCheck/Convert-Help.Tests.ps1 rename to Tests/Unit/PSQualityCheck/ConvertHelp.Tests.ps1 index 14388cd..667ad19 100644 --- a/Tests/Unit/PSQualityCheck/Convert-Help.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/ConvertHelp.Tests.ps1 @@ -1,6 +1,6 @@ -Describe "Convert-Help.Tests" { +Describe "ConvertHelp.Tests" { - Context "Parameter Tests" -Foreach @( + Context "Parameter Tests" -ForEach @( @{ 'Name' = 'Help'; 'Type' = 'String' } ) { @@ -63,7 +63,7 @@ Describe "Convert-Help.Tests" { } - It "should find in help" -ForEach @( + It "should find in help" -Foreach @( @{ 'Token' = '.SYNOPSIS' } @{ 'Token' = '.DESCRIPTION' } @{ 'Token' = '.PARAMETER' } diff --git a/Tests/Unit/PSQualityCheck/Export-FunctionsFromModule.Tests.ps1 b/Tests/Unit/PSQualityCheck/ExportFunctionsFromModule.Tests.ps1 similarity index 86% rename from Tests/Unit/PSQualityCheck/Export-FunctionsFromModule.Tests.ps1 rename to Tests/Unit/PSQualityCheck/ExportFunctionsFromModule.Tests.ps1 index 34a4167..6850c1b 100644 --- a/Tests/Unit/PSQualityCheck/Export-FunctionsFromModule.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/ExportFunctionsFromModule.Tests.ps1 @@ -1,12 +1,12 @@ -Describe "Export-FunctionsFromModule.Tests" { +Describe "ExportFunctionsFromModule.Tests" { - Context "Parameter Tests" -ForEach @( + Context "Parameter Tests" -Foreach @( @{ 'Name' = 'Path'; 'Type' = 'String' } @{ 'Name' = 'ExtractPath'; 'Type' = 'String' } ) { BeforeAll { - $commandletUnderTest = "Export-FunctionsFromModule" + $commandletUnderTest = "ExportFunctionsFromModule" } It "should have $Name as a mandatory parameter" { @@ -45,7 +45,7 @@ Describe "Export-FunctionsFromModule.Tests" { { - Export-FunctionsFromModule -Path $null -ExtractPath $null + ExportFunctionsFromModule -Path $null -ExtractPath $null } | Should -Throw @@ -58,7 +58,7 @@ Describe "Export-FunctionsFromModule.Tests" { $testPath1 = Join-Path -Path $sourcePath -ChildPath 'test.ps1' Set-Content -Path $testPath1 -Value $fileContent - Export-FunctionsFromModule -Path $testPath1 -ExtractPath $extractPath + ExportFunctionsFromModule -Path $testPath1 -ExtractPath $extractPath } | Should -Throw @@ -71,7 +71,7 @@ Describe "Export-FunctionsFromModule.Tests" { $testPath1 = Join-Path -Path $sourcePath -ChildPath 'test.psm1' Set-Content -Path $testPath1 -Value $fileContent - Export-FunctionsFromModule -Path $testPath1 -ExtractPath $extractPath + ExportFunctionsFromModule -Path $testPath1 -ExtractPath $extractPath } | Should -Throw @@ -89,7 +89,7 @@ Describe "Export-FunctionsFromModule.Tests" { $functionPath = Join-Path $extractPath -ChildPath "test" $functionFile = Join-Path $functionPath -ChildPath "Test-Function.ps1" - Export-FunctionsFromModule -Path $testPath1 -ExtractPath $extractPath + ExportFunctionsFromModule -Path $testPath1 -ExtractPath $extractPath $files = Get-ChildItem -Path $functionPath @@ -116,7 +116,7 @@ Describe "Export-FunctionsFromModule.Tests" { $functionFile1 = Join-Path $functionPath -ChildPath "Test-Function.ps1" $functionFile2 = Join-Path $functionPath -ChildPath "Test-SecondFunction.ps1" - Export-FunctionsFromModule -Path $testPath1 -ExtractPath $extractPath + ExportFunctionsFromModule -Path $testPath1 -ExtractPath $extractPath $files = Get-ChildItem -Path $functionPath diff --git a/Tests/Unit/PSQualityCheck/Get-FileContent.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetFileContent.Tests.ps1 similarity index 79% rename from Tests/Unit/PSQualityCheck/Get-FileContent.Tests.ps1 rename to Tests/Unit/PSQualityCheck/GetFileContent.Tests.ps1 index bf6ece6..edc27b1 100644 --- a/Tests/Unit/PSQualityCheck/Get-FileContent.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetFileContent.Tests.ps1 @@ -1,11 +1,11 @@ -Describe "Get-FileContent.Tests" { +Describe "GetFileContent.Tests" { - Context "Parameter Tests" -ForEach @( + Context "Parameter Tests" -Foreach @( @{ 'Name' = 'Path'; 'Type' = 'String' } ) { BeforeAll { - $commandletUnderTest = "Get-FileContent" + $commandletUnderTest = "GetFileContent" } It "should have $Name as a mandatory parameter" { @@ -35,7 +35,7 @@ Describe "Get-FileContent.Tests" { { - Get-FileContent -Path $null + GetFileContent -Path $null } | Should -Throw @@ -47,7 +47,7 @@ Describe "Get-FileContent.Tests" { $fileContent = "" Set-Content -Path $testPath -Value $fileContent - $parsedFileContent = Get-FileContent -Path $testPath + $parsedFileContent = GetFileContent -Path $testPath ($fileContent -eq $parsedFileContent) | Should -BeTrue @@ -59,7 +59,7 @@ Describe "Get-FileContent.Tests" { $fileContent = "Write-Host" Set-Content -Path $testPath -Value $fileContent - $parsedFileContent = Get-FileContent -Path $testPath + $parsedFileContent = GetFileContent -Path $testPath ($fileContent -eq $parsedFileContent) | Should -BeTrue @@ -73,7 +73,7 @@ Describe "Get-FileContent.Tests" { " Set-Content -Path $testPath -Value $fileContent - $parsedFileContent = Get-FileContent -Path $testPath + $parsedFileContent = GetFileContent -Path $testPath ($fileContent -eq $parsedFileContent) | Should -BeTrue @@ -82,11 +82,11 @@ Describe "Get-FileContent.Tests" { It "should pass when Path is valid with only one empty function in the file" { $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent = "function Get-FileContent {}" + $fileContent = "function GetFileContent {}" $matchContent = "" Set-Content -Path $testPath -Value $fileContent - $parsedFileContent = Get-FileContent -Path $testPath + $parsedFileContent = GetFileContent -Path $testPath ($matchContent -eq $parsedFileContent) | Should -BeTrue @@ -95,11 +95,11 @@ Describe "Get-FileContent.Tests" { It "should pass when Path is valid with only one single-line function in the file" { $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent = "function Get-FileContent { Write-Host }" + $fileContent = "function GetFileContent { Write-Host }" $matchContent = " Write-Host " Set-Content -Path $testPath -Value $fileContent - $parsedFileContent = Get-FileContent -Path $testPath + $parsedFileContent = GetFileContent -Path $testPath ($matchContent -eq $parsedFileContent) | Should -BeTrue @@ -108,11 +108,11 @@ Describe "Get-FileContent.Tests" { It "should pass when Path is valid with only one single-line advanced function in the file" { $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent = "function Get-FileContent { if ($true) { Write-Host } }" + $fileContent = "function GetFileContent { if ($true) { Write-Host } }" $matchContent = " if ($true) { Write-Host } " Set-Content -Path $testPath -Value $fileContent - $parsedFileContent = Get-FileContent -Path $testPath + $parsedFileContent = GetFileContent -Path $testPath ($matchContent -eq $parsedFileContent) | Should -BeTrue @@ -121,16 +121,16 @@ Describe "Get-FileContent.Tests" { It "should pass when Path is valid with only one multi-line function in the file" { $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent1 = "function Get-FileContent { + $fileContent1 = "function GetFileContent { Write-Host }" $matchContent1 = " Write-Host`r`n" Set-Content -Path $testPath -Value $fileContent1 - $parsedFileContent1 = Get-FileContent -Path $testPath + $parsedFileContent1 = GetFileContent -Path $testPath - $fileContent2 = "function Get-FileContent { + $fileContent2 = "function GetFileContent { if ($true) { Write-Host } @@ -141,7 +141,7 @@ Describe "Get-FileContent.Tests" { Set-Content -Path $testPath -Value $fileContent2 - $parsedFileContent2 = Get-FileContent -Path $testPath + $parsedFileContent2 = GetFileContent -Path $testPath ($matchContent1 -eq $parsedFileContent1) | Should -BeTrue ($matchContent2 -eq $parsedFileContent2) | Should -BeTrue @@ -152,7 +152,7 @@ Describe "Get-FileContent.Tests" { { $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent = "function Get-FileContent { + $fileContent = "function GetFileContent { Write-Host } @@ -162,7 +162,7 @@ Describe "Get-FileContent.Tests" { Set-Content -Path $testPath -Value $fileContent - $parsedFileContent = Get-FileContent -Path $testPath + $parsedFileContent = GetFileContent -Path $testPath } | Should -Throw diff --git a/Tests/Unit/PSQualityCheck/Get-FileList.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetFileList.Tests.ps1 similarity index 79% rename from Tests/Unit/PSQualityCheck/Get-FileList.Tests.ps1 rename to Tests/Unit/PSQualityCheck/GetFileList.Tests.ps1 index 96f96bc..d5ebb34 100644 --- a/Tests/Unit/PSQualityCheck/Get-FileList.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetFileList.Tests.ps1 @@ -1,13 +1,13 @@ -Describe "Get-FileList.Tests" { +Describe "GetFileList.Tests" { - Context "Parameter Tests" -ForEach @( + Context "Parameter Tests" -Foreach @( @{ 'Name' = 'Path'; 'Type' = 'String'; 'MandatoryFlag' = $true } @{ 'Name' = 'Extension'; 'Type' = 'String'; 'MandatoryFlag' = $true } @{ 'Name' = 'Recurse'; 'Type' = 'SwitchParameter'; 'MandatoryFlag' = $false } ) { BeforeAll { - $commandletUnderTest = "Get-FileList" + $commandletUnderTest = "GetFileList" } It "should have $Name as a mandatory parameter" { @@ -37,7 +37,7 @@ Describe "Get-FileList.Tests" { { - Get-FileList -Path $null -Extension $null + GetFileList -Path $null -Extension $null } | Should -Throw @@ -45,11 +45,11 @@ Describe "Get-FileList.Tests" { It "should return one file when checking folder with one matching files" { - $fileContent = "function Get-FileContent {}" + $fileContent = "function GetFileContent {}" $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.ps1' Set-Content -Path $testPath1 -Value $fileContent - $fileList = Get-FileList -Path $TestDrive -Extension ".ps1" + $fileList = GetFileList -Path $TestDrive -Extension ".ps1" Remove-Item -Path $testPath1 -Force @@ -59,13 +59,13 @@ Describe "Get-FileList.Tests" { It "should return two files when checking folder with two matching files" { - $fileContent = "function Get-FileContent {}" + $fileContent = "function GetFileContent {}" $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.ps1' Set-Content -Path $testPath1 -Value $fileContent $testPath2 = Join-Path -Path $TestDrive -ChildPath 'test2.ps1' Set-Content -Path $testPath2 -Value $fileContent - $fileList = Get-FileList -Path $TestDrive -Extension ".ps1" + $fileList = GetFileList -Path $TestDrive -Extension ".ps1" Remove-Item -Path $testPath1 -Force Remove-Item -Path $testPath2 -Force @@ -76,11 +76,11 @@ Describe "Get-FileList.Tests" { It "should return no files when checking folder with non-matching files" { - $fileContent = "function Get-FileContent {}" + $fileContent = "function GetFileContent {}" $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.psm1' Set-Content -Path $testPath1 -Value $fileContent - $fileList = Get-FileList -Path $TestDrive -Extension ".ps1" + $fileList = GetFileList -Path $TestDrive -Extension ".ps1" Remove-Item -Path $testPath1 -Force @@ -90,13 +90,13 @@ Describe "Get-FileList.Tests" { It "should return one file when checking folder with some matching files" { - $fileContent = "function Get-FileContent {}" + $fileContent = "function GetFileContent {}" $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.psm1' Set-Content -Path $testPath1 -Value $fileContent $testPath2 = Join-Path -Path $TestDrive -ChildPath 'test2.ps1' Set-Content -Path $testPath2 -Value $fileContent - $fileList = Get-FileList -Path $TestDrive -Extension ".ps1" + $fileList = GetFileList -Path $TestDrive -Extension ".ps1" Remove-Item -Path $testPath1 -Force Remove-Item -Path $testPath2 -Force @@ -107,13 +107,13 @@ Describe "Get-FileList.Tests" { It "should return correct file when checking folder" { - $fileContent = "function Get-FileContent {}" + $fileContent = "function GetFileContent {}" $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.psm1' Set-Content -Path $testPath1 -Value $fileContent $testPath2 = Join-Path -Path $TestDrive -ChildPath 'test2.ps1' Set-Content -Path $testPath2 -Value $fileContent - $fileList = Get-FileList -Path $TestDrive -Extension ".ps1" + $fileList = GetFileList -Path $TestDrive -Extension ".ps1" Remove-Item -Path $testPath1 -Force Remove-Item -Path $testPath2 -Force @@ -124,13 +124,13 @@ Describe "Get-FileList.Tests" { It "should return multiple correct files when checking folder" { - $fileContent = "function Get-FileContent {}" + $fileContent = "function GetFileContent {}" $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.ps1' Set-Content -Path $testPath1 -Value $fileContent $testPath2 = Join-Path -Path $TestDrive -ChildPath 'test2.ps1' Set-Content -Path $testPath2 -Value $fileContent - $fileList = Get-FileList -Path $TestDrive -Extension ".ps1" + $fileList = GetFileList -Path $TestDrive -Extension ".ps1" Remove-Item -Path $testPath1 -Force Remove-Item -Path $testPath2 -Force @@ -141,11 +141,11 @@ Describe "Get-FileList.Tests" { It "should not return Test files when checking folder" { - $fileContent = "function Get-FileContent {}" + $fileContent = "function GetFileContent {}" $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test.Tests.ps1' Set-Content -Path $testPath1 -Value $fileContent - $fileList = Get-FileList -Path $TestDrive -Extension ".ps1" + $fileList = GetFileList -Path $TestDrive -Extension ".ps1" Remove-Item -Path $testPath1 -Force diff --git a/Tests/Unit/PSQualityCheck/Get-FunctionCount.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetFunctionCount.Tests.ps1 similarity index 67% rename from Tests/Unit/PSQualityCheck/Get-FunctionCount.Tests.ps1 rename to Tests/Unit/PSQualityCheck/GetFunctionCount.Tests.ps1 index 823ae37..e70cacf 100644 --- a/Tests/Unit/PSQualityCheck/Get-FunctionCount.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetFunctionCount.Tests.ps1 @@ -1,12 +1,12 @@ -Describe "Get-FunctionCount.Tests" { +Describe "GetFunctionCount.Tests" { - Context "Parameter Tests" -ForEach @( + Context "Parameter Tests" -Foreach @( @{ 'Name' = 'ModulePath'; 'Type' = 'String' } @{ 'Name' = 'ManifestPath'; 'Type' = 'String' } ) { BeforeAll { - $commandletUnderTest = "Get-FunctionCount" + $commandletUnderTest = "GetFunctionCount" } It "should have $Name as a mandatory parameter" { @@ -30,7 +30,7 @@ Describe "Get-FunctionCount.Tests" { } - # TODO Broken Test, requires Get-ParsedFile and Get-ParsedContent mocking out + # TODO Broken Test, requires GetParsedFile and GetParsedContent mocking out Context "Function tests" { @@ -45,7 +45,7 @@ Describe "Get-FunctionCount.Tests" { { - Get-FunctionCount -Module $null -Manifest $null + GetFunctionCount -Module $null -Manifest $null } | Should -Throw @@ -53,14 +53,14 @@ Describe "Get-FunctionCount.Tests" { It "should find one function with matching module and manifest" { - $fileContent = "function Get-FileContent { + $fileContent = "function GetFileContent { Write-Host }" Set-Content -Path $ModulePath -Value $fileContent - New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('Get-FileContent') + New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent') - Get-FunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(1, 1, 1, 1) + GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(1, 1, 1, 1) Remove-Item -Path $ModulePath -Force Remove-Item -Path $ManifestPath -Force @@ -69,13 +69,13 @@ Describe "Get-FunctionCount.Tests" { It "should find two functions in module with matching manifest and module" { - $fileContent = "function Get-FileContent {} - function Get-FileContent2 {}" + $fileContent = "function GetFileContent {} + function GetFileContent2 {}" Set-Content -Path $ModulePath -Value $fileContent - New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('Get-FileContent', 'Get-FileContent2') + New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent', 'GetFileContent2') - Get-FunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(2, 2, 2, 2) + GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(2, 2, 2, 2) Remove-Item -Path $ModulePath -Force Remove-Item -Path $ManifestPath -Force @@ -84,12 +84,12 @@ Describe "Get-FunctionCount.Tests" { It "should not find any function in manifest or module with empty manifest" { - $fileContent = "function Get-FileContent {}" + $fileContent = "function GetFileContent {}" Set-Content -Path $ModulePath -Value $fileContent New-ModuleManifest -Path $ManifestPath - Get-FunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(0, 0, 0, 0) + GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(0, 0, 0, 0) Remove-Item -Path $ModulePath -Force Remove-Item -Path $ManifestPath -Force @@ -98,12 +98,12 @@ Describe "Get-FunctionCount.Tests" { It "should not find function in manifest and module with mismatched functions between manifest and module" { - $fileContent = "function Get-FileContent {}" + $fileContent = "function GetFileContent {}" Set-Content -Path $ModulePath -Value $fileContent - New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('Get-FileContent2') + New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent2') - Get-FunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(1, 0, 1, 0) + GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(1, 0, 1, 0) Remove-Item -Path $ModulePath -Force Remove-Item -Path $ManifestPath -Force @@ -112,12 +112,12 @@ Describe "Get-FunctionCount.Tests" { It "should not find function in module with function in manifest and not in module" { - $fileContent = "function Get-FileContent {}" + $fileContent = "function GetFileContent {}" Set-Content -Path $ModulePath -Value $fileContent - New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('Get-FileContent', 'Get-FileContent2') + New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent', 'GetFileContent2') - Get-FunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(2, 1, 1, 1) + GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(2, 1, 1, 1) Remove-Item -Path $ModulePath -Force Remove-Item -Path $ManifestPath -Force @@ -126,13 +126,13 @@ Describe "Get-FunctionCount.Tests" { It "should not find function in module with function in module and not in manifest" { - $fileContent = "function Get-FileContent {} - function Get-FileContent2 {}" + $fileContent = "function GetFileContent {} + function GetFileContent2 {}" Set-Content -Path $ModulePath -Value $fileContent - New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('Get-FileContent') + New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent') - Get-FunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(1, 1, 2, 1) + GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(1, 1, 2, 1) Remove-Item -Path $ModulePath -Force Remove-Item -Path $ManifestPath -Force diff --git a/Tests/Unit/PSQualityCheck/Get-ParsedContent.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetParsedContent.Tests.ps1 similarity index 91% rename from Tests/Unit/PSQualityCheck/Get-ParsedContent.Tests.ps1 rename to Tests/Unit/PSQualityCheck/GetParsedContent.Tests.ps1 index 36d3400..0c7e17a 100644 --- a/Tests/Unit/PSQualityCheck/Get-ParsedContent.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetParsedContent.Tests.ps1 @@ -1,11 +1,11 @@ -Describe "Get-ParsedContent.Tests" { +Describe "GetParsedContent.Tests" { Context "Parameter Tests" -ForEach @( @{ 'Name' = 'Content'; 'Type' = 'String' } ) { BeforeAll { - $commandletUnderTest = "Get-ParsedContent" + $commandletUnderTest = "GetParsedContent" } It "should have $Name as a mandatory parameter" { @@ -45,7 +45,7 @@ Describe "Get-ParsedContent.Tests" { "EndColumn" = 9 }, @{ - "Content" = "Get-FileContent" + "Content" = "GetFileContent" "Type" = "CommandArgument" "Start" = 9 "Length" = 15 @@ -82,16 +82,16 @@ Describe "Get-ParsedContent.Tests" { { - Get-ParsedContent -Content $null + GetParsedContent -Content $null } | Should -Throw } It "should return correct parse tokens for content" { - $fileContent = "function Get-FileContent {}" + $fileContent = "function GetFileContent {}" - ($parsedModule, $parserErrorCount) = Get-ParsedContent -Content $fileContent + ($parsedModule, $parserErrorCount) = GetParsedContent -Content $fileContent for ($x = 0; $x -lt $parsedModule.Count; $x++) { @@ -116,7 +116,7 @@ Describe "Get-ParsedContent.Tests" { $fileContent = "function Get-Content {}" - ($parsedModule, $parserErrorCount) = Get-ParsedContent -Content $fileContent + ($parsedModule, $parserErrorCount) = GetParsedContent -Content $fileContent $flag = $true diff --git a/Tests/Unit/PSQualityCheck/Get-ParsedFile.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetParsedFile.Tests.ps1 similarity index 92% rename from Tests/Unit/PSQualityCheck/Get-ParsedFile.Tests.ps1 rename to Tests/Unit/PSQualityCheck/GetParsedFile.Tests.ps1 index bb5d750..04c8827 100644 --- a/Tests/Unit/PSQualityCheck/Get-ParsedFile.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetParsedFile.Tests.ps1 @@ -1,11 +1,11 @@ -Describe "Get-ParsedFile.Tests" { +Describe "GetParsedFile.Tests" { Context "Parameter Tests" -ForEach @( @{ 'Name' = 'Path'; 'Type' = 'String' } ) { BeforeAll { - $commandletUnderTest = "Get-ParsedFile" + $commandletUnderTest = "GetParsedFile" } It "should have $Name as a mandatory parameter" { @@ -45,7 +45,7 @@ Describe "Get-ParsedFile.Tests" { "EndColumn" = 9 }, @{ - "Content" = "Get-FileContent" + "Content" = "GetFileContent" "Type" = "CommandArgument" "Start" = 9 "Length" = 15 @@ -92,7 +92,7 @@ Describe "Get-ParsedFile.Tests" { { - Get-ParsedFile -Path $null + GetParsedFile -Path $null } | Should -Throw @@ -101,11 +101,11 @@ Describe "Get-ParsedFile.Tests" { It "should return correct parse tokens for content" { $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent = "function Get-FileContent {}" + $fileContent = "function GetFileContent {}" Set-Content -Path $testPath -Value $fileContent - ($parsedModule, $parserErrorCount) = Get-ParsedFile -Path $testPath + ($parsedModule, $parserErrorCount) = GetParsedFile -Path $testPath for ($x = 0; $x -lt $parsedModule.Count; $x++) { @@ -136,7 +136,7 @@ Describe "Get-ParsedFile.Tests" { Set-Content -Path $testPath -Value $fileContent - ($parsedModule, $parserErrorCount) = Get-ParsedFile -Path $testPath + ($parsedModule, $parserErrorCount) = GetParsedFile -Path $testPath $flag = $true diff --git a/Tests/Unit/PSQualityCheck/Get-ScriptParameter.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetScriptParameter.Tests.ps1 similarity index 81% rename from Tests/Unit/PSQualityCheck/Get-ScriptParameter.Tests.ps1 rename to Tests/Unit/PSQualityCheck/GetScriptParameter.Tests.ps1 index 7e5f93a..500579f 100644 --- a/Tests/Unit/PSQualityCheck/Get-ScriptParameter.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetScriptParameter.Tests.ps1 @@ -1,11 +1,11 @@ -Describe "Get-ScriptParameter.Tests" { +Describe "GetScriptParameter.Tests" { - Context "Parameter Tests" -Foreach @( + Context "Parameter Tests" -ForEach @( @{ 'Name' = 'Content'; 'Type' = 'String' } ) { BeforeAll { - $commandletUnderTest = "Get-ScriptParameter" + $commandletUnderTest = "GetScriptParameter" } It "should have $Name as a mandatory parameter" { @@ -35,7 +35,7 @@ Describe "Get-ScriptParameter.Tests" { { - Get-ScriptParameter -Content $null + GetScriptParameter -Content $null } | Should -Throw @@ -44,9 +44,9 @@ Describe "Get-ScriptParameter.Tests" { It "should throw when passed no parameters" { { - $fileContent = "function Get-FileContent { }" + $fileContent = "function GetFileContent { }" - $parameterVariables = Get-ScriptParameter -Content $fileContent + $parameterVariables = GetScriptParameter -Content $fileContent $parameterVariables | Should -BeNullOrEmpty @@ -58,7 +58,7 @@ Describe "Get-ScriptParameter.Tests" { $fileContent = 'param ( $parameterOne )' - $parameterVariables = Get-ScriptParameter -Content $fileContent + $parameterVariables = GetScriptParameter -Content $fileContent $parameterVariables.ContainsKey('parameterOne') | Should -BeTrue $parameterVariables.('parameterOne') | Should -BeNullOrEmpty @@ -69,7 +69,7 @@ Describe "Get-ScriptParameter.Tests" { $fileContent = 'param ( [int]$parameterOne )' - $parameterVariables = Get-ScriptParameter -Content $fileContent + $parameterVariables = GetScriptParameter -Content $fileContent $parameterVariables.ContainsKey('parameterOne') | Should -BeTrue $parameterVariables.('parameterOne') | Should -BeExactly '[int]' @@ -83,7 +83,7 @@ Describe "Get-ScriptParameter.Tests" { [string]$parameterTwo )' - $parameterVariables = Get-ScriptParameter -Content $fileContent + $parameterVariables = GetScriptParameter -Content $fileContent $parameterVariables.ContainsKey('parameterOne') | Should -BeTrue $parameterVariables.('parameterOne') | Should -BeExactly '[int]' @@ -100,7 +100,7 @@ Describe "Get-ScriptParameter.Tests" { $parameterTwo )' - $parameterVariables = Get-ScriptParameter -Content $fileContent + $parameterVariables = GetScriptParameter -Content $fileContent $parameterVariables.ContainsKey('parameterOne') | Should -BeTrue $parameterVariables.('parameterOne') | Should -BeExactly '[int]' diff --git a/Tests/Unit/PSQualityCheck/Get-TagList.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetTagList.Tests.ps1 similarity index 100% rename from Tests/Unit/PSQualityCheck/Get-TagList.Tests.ps1 rename to Tests/Unit/PSQualityCheck/GetTagList.Tests.ps1 diff --git a/Tests/Unit/PSQualityCheck/Get-Token.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetToken.Tests.ps1 similarity index 59% rename from Tests/Unit/PSQualityCheck/Get-Token.Tests.ps1 rename to Tests/Unit/PSQualityCheck/GetToken.Tests.ps1 index 3d219f3..9aa6982 100644 --- a/Tests/Unit/PSQualityCheck/Get-Token.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetToken.Tests.ps1 @@ -1,13 +1,13 @@ -Describe "Get-Token.Tests" { +Describe "GetToken.Tests" { - Context "Parameter Tests" -ForEach @( + Context "Parameter Tests" -Foreach @( @{ 'Name' = 'ParsedContent'; 'Type' = 'Object[]' } @{ 'Name' = 'Type'; 'Type' = 'String' } @{ 'Name' = 'Content'; 'Type' = 'String' } ) { BeforeAll { - $commandletUnderTest = "Get-Token" + $commandletUnderTest = "GetToken" } It "should have $Name as a mandatory parameter" { @@ -31,51 +31,51 @@ Describe "Get-Token.Tests" { } - # TODO Broken Test, requires Get-TokenMarker and Get-TokenComponent mocking out + # TODO Broken Test, requires GetTokenMarker and GetTokenComponent mocking out Context "Function tests" { BeforeAll { $ParsedContent = @( @{ - "Content" = "function" - "Type" = "Keyword" - "Start" = 0 - "Length" = 8 - "StartLine" = 1 + "Content" = "function" + "Type" = "Keyword" + "Start" = 0 + "Length" = 8 + "StartLine" = 1 "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 9 + "EndLine" = 1 + "EndColumn" = 9 }, @{ - "Content" = "Get-FileContent" - "Type" = "CommandArgument" - "Start" = 9 - "Length" = 15 - "StartLine" = 1 + "Content" = "GetFileContent" + "Type" = "CommandArgument" + "Start" = 9 + "Length" = 15 + "StartLine" = 1 "StartColumn" = 10 - "EndLine" = 1 - "EndColumn" = 25 + "EndLine" = 1 + "EndColumn" = 25 }, @{ - "Content" = "{" - "Type" = "GroupStart" - "Start" = 25 - "Length" = 1 - "StartLine" = 1 + "Content" = "{" + "Type" = "GroupStart" + "Start" = 25 + "Length" = 1 + "StartLine" = 1 "StartColumn" = 26 - "EndLine" = 1 - "EndColumn" = 27 + "EndLine" = 1 + "EndColumn" = 27 }, @{ - "Content" = "}" - "Type" = "GroupEnd" - "Start" = 26 - "Length" = 1 - "StartLine" = 1 + "Content" = "}" + "Type" = "GroupEnd" + "Start" = 26 + "Length" = 1 + "StartLine" = 1 "StartColumn" = 27 - "EndLine" = 1 - "EndColumn" = 28 + "EndLine" = 1 + "EndColumn" = 28 } ) } @@ -84,7 +84,7 @@ Describe "Get-Token.Tests" { { - Get-Token -ParsedContent $null -Type $null -Content $null + GetToken -ParsedContent $null -Type $null -Content $null } | Should -Throw @@ -92,7 +92,7 @@ Describe "Get-Token.Tests" { It "should find token where parameters are valid" { - $token = Get-Token -ParsedContent $ParsedContent -Type "Keyword" -Content "Function" + $token = GetToken -ParsedContent $ParsedContent -Type "Keyword" -Content "Function" for ($x = 0; $x -lt $parsedModule.Count; $x++) { @@ -113,7 +113,7 @@ Describe "Get-Token.Tests" { It "should not find token where parameters are invalid" { - $token = (Get-Token -ParsedContent $ParsedContent -Type "Unknown" -Content "Data") + $token = (GetToken -ParsedContent $ParsedContent -Type "Unknown" -Content "Data") $token | Should -BeNullOrEmpty diff --git a/Tests/Unit/PSQualityCheck/Get-TokenComponent.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetTokenComponent.Tests.ps1 similarity index 85% rename from Tests/Unit/PSQualityCheck/Get-TokenComponent.Tests.ps1 rename to Tests/Unit/PSQualityCheck/GetTokenComponent.Tests.ps1 index 4c5f9a3..8a6ee88 100644 --- a/Tests/Unit/PSQualityCheck/Get-TokenComponent.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetTokenComponent.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "Get-TokenComponent.Tests" { +Describe "GetTokenComponent.Tests" { Context "Parameter Tests" -Foreach @( @{ 'Name' = 'ParsedContent'; 'Type' = 'Object[]' } @@ -6,7 +6,7 @@ Describe "Get-TokenComponent.Tests" { ) { BeforeAll { - $commandletUnderTest = "Get-TokenComponent" + $commandletUnderTest = "GetTokenComponent" } It "should have $Name as a mandatory parameter" { @@ -45,7 +45,7 @@ Describe "Get-TokenComponent.Tests" { "EndColumn" = 9 }, @{ - "Content" = "Get-FileContent" + "Content" = "GetFileContent" "Type" = "CommandArgument" "Start" = 9 "Length" = 15 @@ -81,7 +81,7 @@ Describe "Get-TokenComponent.Tests" { { - Get-TokenComponent -ParsedContent $null -StartLine $null + GetTokenComponent -ParsedContent $null -StartLine $null } | Should -Throw @@ -89,7 +89,7 @@ Describe "Get-TokenComponent.Tests" { It "should find token where 'StartLine' is valid" { - $token = Get-TokenComponent -ParsedContent $ParsedContent -StartLine 1 + $token = GetTokenComponent -ParsedContent $ParsedContent -StartLine 1 Compare-Object -ReferenceObject $token.Values -DifferenceObject $ParsedContent.values | Should -BeNullOrEmpty @@ -97,10 +97,10 @@ Describe "Get-TokenComponent.Tests" { It "should not find token where 'StartLine' is invalid" { - $token = Get-TokenComponent -ParsedContent $ParsedContent -StartLine 3 + $token = GetTokenComponent -ParsedContent $ParsedContent -StartLine 3 $token | Should -BeNullOrEmpty - $token = Get-TokenComponent -ParsedContent $ParsedContent -StartLine $null + $token = GetTokenComponent -ParsedContent $ParsedContent -StartLine $null $token | Should -BeNullOrEmpty } diff --git a/Tests/Unit/PSQualityCheck/Get-TokenMarker.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetTokenMarker.Tests.ps1 similarity index 91% rename from Tests/Unit/PSQualityCheck/Get-TokenMarker.Tests.ps1 rename to Tests/Unit/PSQualityCheck/GetTokenMarker.Tests.ps1 index 15c6a83..8aa999f 100644 --- a/Tests/Unit/PSQualityCheck/Get-TokenMarker.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetTokenMarker.Tests.ps1 @@ -46,7 +46,7 @@ Describe "GetTokenMarker.Tests" { "EndColumn" = 9 }, @{ - "Content" = "Get-FileContent" + "Content" = "GetFileContent" "Type" = "CommandArgument" "Start" = 9 "Length" = 15 @@ -78,7 +78,7 @@ Describe "GetTokenMarker.Tests" { ) $tokenMatch = @{ - "Content" = "Get-FileContent" + "Content" = "GetFileContent" "Type" = "CommandArgument" "Start" = 9 "Length" = 15 @@ -100,17 +100,17 @@ Describe "GetTokenMarker.Tests" { } - It "should find 'CommandArgument' type with 'Get-FileContent' value" { + It "should find 'CommandArgument' type with 'GetFileContent' value" { - $token = GetTokenMarker -ParsedContent $ParsedContent -Type "CommandArgument" -Content "Get-FileContent" + $token = GetTokenMarker -ParsedContent $ParsedContent -Type "CommandArgument" -Content "GetFileContent" Compare-Object -ReferenceObject $token.Values -DifferenceObject $tokenMatch.values | Should -BeNullOrEmpty } - It "should not find 'Dummy' type with 'Get-FileContent' value" { + It "should not find 'Dummy' type with 'GetFileContent' value" { - $token = GetTokenMarker -ParsedContent $ParsedContent -Type "Dummy" -Content "Get-FileContent" + $token = GetTokenMarker -ParsedContent $ParsedContent -Type "Dummy" -Content "GetFileContent" $token | Should -BeNullOrEmpty diff --git a/Tests/Unit/PSQualityCheck/Test-ImportModuleIsValid.Tests.ps1 b/Tests/Unit/PSQualityCheck/Test-ImportModuleIsValid.Tests.ps1 deleted file mode 100644 index 44a9f5a..0000000 --- a/Tests/Unit/PSQualityCheck/Test-ImportModuleIsValid.Tests.ps1 +++ /dev/null @@ -1,247 +0,0 @@ -Describe "Test-ImportModuleIsValid.Tests" { - - Context "Parameter Tests" -ForEach @( - @{ 'Name' = 'ParsedContent'; 'Type' = 'Object[]' } - @{ 'Name' = 'ImportModuleTokens'; 'Type' = 'Object[]' } - ) { - - BeforeAll { - $commandletUnderTest = "Test-ImportModuleIsValid" - } - - It "should have $Name as a mandatory parameter" { - - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - - } - - It "should $Name not belong to a parameter set" { - - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - - } - - It "should $Name type be $Type" { - - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - - } - - } - - Context "Function tests" { - - It "should throw when passing null parameter values" { - - { - - Test-ImportModuleIsValid -ParsedContent $null -ImportModuleTokens $null - - } | Should -Throw - - } - - It "should pass when passed a valid Import-Module command" { - - { - - $ParsedContent = @( - @{ - "Content" = "Import-Module" - "Type" = "Command" - "Start" = 0 - "Length" = 13 - "StartLine" = 1 - "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 14 - }, - @{ - "Content" = "-Name" - "Type" = "CommandParameter" - "Start" = 14 - "Length" = 5 - "StartLine" = 1 - "StartColumn" = 15 - "EndLine" = 1 - "EndColumn" = 20 - }, - @{ - "Content" = "ModuleName" - "Type" = "CommandArgument" - "Start" = 20 - "Length" = 10 - "StartLine" = 1 - "StartColumn" = 21 - "EndLine" = 1 - "EndColumn" = 31 - }, - @{ - "Content" = "-RequiredVersion" - "Type" = "CommandParameter" - "Start" = 31 - "Length" = 16 - "StartLine" = 1 - "StartColumn" = 32 - "EndLine" = 1 - "EndColumn" = 48 - }, - @{ - "Content" = "1.0.0" - "Type" = "String" - "Start" = 48 - "Length" = 7 - "StartLine" = 1 - "StartColumn" = 49 - "EndLine" = 1 - "EndColumn" = 56 - } - ) - - $importModuleTokens = $ParsedContent - - Test-ImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens - - } | Should -Not -Throw - - } - - It "should throw when passed a valid Import-Module command missing all required parameters" { - - { - - $ParsedContent = @( - @{ - "Content" = "Import-Module" - "Type" = "Command" - "Start" = 0 - "Length" = 13 - "StartLine" = 1 - "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 14 - }, - @{ - "Content" = "ModuleName" - "Type" = "CommandArgument" - "Start" = 14 - "Length" = 10 - "StartLine" = 1 - "StartColumn" = 15 - "EndLine" = 1 - "EndColumn" = 25 - } - ) - - $importModuleTokens = $ParsedContent - - Test-ImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens - - } | Should -Throw - - } - - It "should throw when passed a valid Import-Module command missing -Name only" { - - { - - $ParsedContent = @( - @{ - "Content" = "Import-Module" - "Type" = "Command" - "Start" = 0 - "Length" = 13 - "StartLine" = 1 - "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 14 - }, - @{ - "Content" = "ModuleName" - "Type" = "CommandArgument" - "Start" = 14 - "Length" = 10 - "StartLine" = 1 - "StartColumn" = 15 - "EndLine" = 1 - "EndColumn" = 25 - }, - @{ - "Content" = "-RequiredVersion" - "Type" = "CommandParameter" - "Start" = 25 - "Length" = 16 - "StartLine" = 1 - "StartColumn" = 26 - "EndLine" = 1 - "EndColumn" = 42 - }, - @{ - "Content" = "1.0.0" - "Type" = "String" - "Start" = 42 - "Length" = 7 - "StartLine" = 1 - "StartColumn" = 43 - "EndLine" = 1 - "EndColumn" = 50 - } - ) - - $importModuleTokens = $ParsedContent - - Test-ImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens - - } | Should -Throw - - } - - It "should throw when passed a valid Import-Module command missing -RequiredVersion, -MinimumVersion or -MaximumVersion" { - - { - - $ParsedContent = @( - @{ - "Content" = "Import-Module" - "Type" = "Command" - "Start" = 0 - "Length" = 13 - "StartLine" = 1 - "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 14 - }, - @{ - "Content" = "-Name" - "Type" = "CommandParameter" - "Start" = 14 - "Length" = 5 - "StartLine" = 1 - "StartColumn" = 15 - "EndLine" = 1 - "EndColumn" = 20 - }, - @{ - "Content" = "ModuleName" - "Type" = "CommandArgument" - "Start" = 20 - "Length" = 10 - "StartLine" = 1 - "StartColumn" = 21 - "EndLine" = 1 - "EndColumn" = 31 - } - ) - - $importModuleTokens = $ParsedContent - - Test-ImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens - - } | Should -Throw - - } - - } - -} diff --git a/Tests/Unit/PSQualityCheck/Test-HelpTokensCountisValid.Tests.ps1 b/Tests/Unit/PSQualityCheck/TestHelpTokensCountisValid.Tests.ps1 similarity index 93% rename from Tests/Unit/PSQualityCheck/Test-HelpTokensCountisValid.Tests.ps1 rename to Tests/Unit/PSQualityCheck/TestHelpTokensCountisValid.Tests.ps1 index 4bb583a..12f151b 100644 --- a/Tests/Unit/PSQualityCheck/Test-HelpTokensCountisValid.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/TestHelpTokensCountisValid.Tests.ps1 @@ -1,11 +1,11 @@ -Describe "Test-HelpTokensCountIsValid.Tests" { +Describe "TestHelpTokensCountIsValid.Tests" { - Context "Parameter Tests" -ForEach @( + Context "Parameter Tests" -Foreach @( @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } ) { BeforeAll { - $commandletUnderTest = "Test-HelpTokensCountIsValid" + $commandletUnderTest = "TestHelpTokensCountIsValid" } It "should have $Name as a mandatory parameter" { @@ -97,7 +97,7 @@ Describe "Test-HelpTokensCountIsValid.Tests" { { - Test-HelpTokensCountIsValid -HelpTokens $null + TestHelpTokensCountIsValid -HelpTokens $null } | Should -Throw @@ -116,7 +116,7 @@ Describe "Test-HelpTokensCountIsValid.Tests" { ) } - Test-HelpTokensCountIsValid -HelpTokens $helpTokens + TestHelpTokensCountIsValid -HelpTokens $helpTokens Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } @@ -156,7 +156,7 @@ Describe "Test-HelpTokensCountIsValid.Tests" { ) } - Test-HelpTokensCountIsValid -HelpTokens $helpTokens + TestHelpTokensCountIsValid -HelpTokens $helpTokens Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } @@ -204,7 +204,7 @@ Describe "Test-HelpTokensCountIsValid.Tests" { ) } - Test-HelpTokensCountIsValid -HelpTokens $helpTokens + TestHelpTokensCountIsValid -HelpTokens $helpTokens Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } diff --git a/Tests/Unit/PSQualityCheck/Test-HelpTokensParamsMatch.Tests.ps1 b/Tests/Unit/PSQualityCheck/TestHelpTokensParamsMatch.Tests.ps1 similarity index 87% rename from Tests/Unit/PSQualityCheck/Test-HelpTokensParamsMatch.Tests.ps1 rename to Tests/Unit/PSQualityCheck/TestHelpTokensParamsMatch.Tests.ps1 index ee3ae36..128e71b 100644 --- a/Tests/Unit/PSQualityCheck/Test-HelpTokensParamsMatch.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/TestHelpTokensParamsMatch.Tests.ps1 @@ -1,4 +1,4 @@ -Describe "Test-HelpTokensParamsMatch.Tests" { +Describe "TestHelpTokensParamsMatch.Tests" { Context "Parameter Tests" -Foreach @( @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } @@ -6,7 +6,7 @@ Describe "Test-HelpTokensParamsMatch.Tests" { ) { BeforeAll { - $commandletUnderTest = "Test-HelpTokensParamsMatch" + $commandletUnderTest = "TestHelpTokensParamsMatch" } It "should have $Name as a mandatory parameter" { @@ -36,7 +36,7 @@ Describe "Test-HelpTokensParamsMatch.Tests" { { - Test-HelpTokensParamsMatch -HelpTokens $null -ParameterVariables $null + TestHelpTokensParamsMatch -HelpTokens $null -ParameterVariables $null } | Should -Throw @@ -58,7 +58,7 @@ Describe "Test-HelpTokensParamsMatch.Tests" { "ParameterWithType" = '[string]' } - Test-HelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable } | Should -Not -Throw @@ -80,7 +80,7 @@ Describe "Test-HelpTokensParamsMatch.Tests" { "ParameterWithType" = '[string]' } - Test-HelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable } | Should -Throw @@ -108,7 +108,7 @@ Describe "Test-HelpTokensParamsMatch.Tests" { "ParameterTwo" = '[string]' } - Test-HelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable } | Should -Not -Throw @@ -136,7 +136,7 @@ Describe "Test-HelpTokensParamsMatch.Tests" { "ParameterTwo" = '[string]' } - Test-HelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable } | Should -Throw @@ -164,7 +164,7 @@ Describe "Test-HelpTokensParamsMatch.Tests" { "ParameterTwo" = '[string]' } - Test-HelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable } | Should -Throw @@ -187,7 +187,7 @@ Describe "Test-HelpTokensParamsMatch.Tests" { "ParameterTwo" = '[string]' } - Test-HelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable } | Should -Throw @@ -210,7 +210,7 @@ Describe "Test-HelpTokensParamsMatch.Tests" { "ParameterTwo" = '[string]' } - Test-HelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable } | Should -Throw @@ -237,7 +237,7 @@ Describe "Test-HelpTokensParamsMatch.Tests" { "ParameterTwo" = '[string]' } - Test-HelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable } | Should -Throw @@ -263,7 +263,7 @@ Describe "Test-HelpTokensParamsMatch.Tests" { $parameterVariable = @{ } - Test-HelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable } | Should -Throw diff --git a/Tests/Unit/PSQualityCheck/Test-HelpTokensTextIsValid.Tests.ps1 b/Tests/Unit/PSQualityCheck/TestHelpTokensTextIsValid.Tests.ps1 similarity index 91% rename from Tests/Unit/PSQualityCheck/Test-HelpTokensTextIsValid.Tests.ps1 rename to Tests/Unit/PSQualityCheck/TestHelpTokensTextIsValid.Tests.ps1 index 77bdf2e..3249ef0 100644 --- a/Tests/Unit/PSQualityCheck/Test-HelpTokensTextIsValid.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/TestHelpTokensTextIsValid.Tests.ps1 @@ -1,11 +1,11 @@ -Describe "Test-HelpTokensTextIsValid.Tests" { +Describe "TestHelpTokensTextIsValid.Tests" { Context "Parameter Tests" -ForEach @( @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } ) { BeforeAll { - $commandletUnderTest = "Test-HelpTokensTextIsValid" + $commandletUnderTest = "TestHelpTokensTextIsValid" } It "should have $Name as a mandatory parameter" { @@ -35,7 +35,7 @@ Describe "Test-HelpTokensTextIsValid.Tests" { { - Test-HelpTokensTextIsValid -HelpTokens $null + TestHelpTokensTextIsValid -HelpTokens $null } | Should -Throw @@ -54,7 +54,7 @@ Describe "Test-HelpTokensTextIsValid.Tests" { ) } - Test-HelpTokensTextIsValid -HelpTokens $help + TestHelpTokensTextIsValid -HelpTokens $help } | Should -Not -Throw @@ -73,7 +73,7 @@ Describe "Test-HelpTokensTextIsValid.Tests" { ) } - Test-HelpTokensTextIsValid -HelpTokens $help + TestHelpTokensTextIsValid -HelpTokens $help } | Should -Throw @@ -92,7 +92,7 @@ Describe "Test-HelpTokensTextIsValid.Tests" { ) } - Test-HelpTokensTextIsValid -HelpTokens $help + TestHelpTokensTextIsValid -HelpTokens $help } | Should -Throw @@ -125,7 +125,7 @@ Describe "Test-HelpTokensTextIsValid.Tests" { ) } - Test-HelpTokensTextIsValid -HelpTokens $help + TestHelpTokensTextIsValid -HelpTokens $help } | Should -Not -Throw @@ -158,7 +158,7 @@ Describe "Test-HelpTokensTextIsValid.Tests" { ) } - Test-HelpTokensTextIsValid -HelpTokens $help + TestHelpTokensTextIsValid -HelpTokens $help } | Should -Throw @@ -191,7 +191,7 @@ Describe "Test-HelpTokensTextIsValid.Tests" { ) } - Test-HelpTokensTextIsValid -HelpTokens $help + TestHelpTokensTextIsValid -HelpTokens $help } | Should -Throw @@ -224,7 +224,7 @@ Describe "Test-HelpTokensTextIsValid.Tests" { ) } - Test-HelpTokensTextIsValid -HelpTokens $help + TestHelpTokensTextIsValid -HelpTokens $help } | Should -Throw @@ -257,7 +257,7 @@ Describe "Test-HelpTokensTextIsValid.Tests" { ) } - Test-HelpTokensTextIsValid -HelpTokens $help + TestHelpTokensTextIsValid -HelpTokens $help } | Should -Throw diff --git a/Tests/Unit/PSQualityCheck/TestImportModuleIsValid.Tests.ps1 b/Tests/Unit/PSQualityCheck/TestImportModuleIsValid.Tests.ps1 new file mode 100644 index 0000000..74e84f7 --- /dev/null +++ b/Tests/Unit/PSQualityCheck/TestImportModuleIsValid.Tests.ps1 @@ -0,0 +1,247 @@ +Describe "TestImportModuleIsValid.Tests" { + + Context "Parameter Tests" -Foreach @( + @{ 'Name' = 'ParsedContent'; 'Type' = 'Object[]' } + @{ 'Name' = 'ImportModuleTokens'; 'Type' = 'Object[]' } + ) { + + BeforeAll { + $commandletUnderTest = "TestImportModuleIsValid" + } + + It "should have $Name as a mandatory parameter" { + + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + + } + + It "should $Name not belong to a parameter set" { + + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + + } + + It "should $Name type be $Type" { + + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + + } + + } + + Context "Function tests" { + + It "should throw when passing null parameter values" { + + { + + TestImportModuleIsValid -ParsedContent $null -ImportModuleTokens $null + + } | Should -Throw + + } + + It "should pass when passed a valid Import-Module command" { + + { + + $ParsedContent = @( + @{ + "Content" = "Import-Module" + "Type" = "Command" + "Start" = 0 + "Length" = 13 + "StartLine" = 1 + "StartColumn" = 1 + "EndLine" = 1 + "EndColumn" = 14 + }, + @{ + "Content" = "-Name" + "Type" = "CommandParameter" + "Start" = 14 + "Length" = 5 + "StartLine" = 1 + "StartColumn" = 15 + "EndLine" = 1 + "EndColumn" = 20 + }, + @{ + "Content" = "ModuleName" + "Type" = "CommandArgument" + "Start" = 20 + "Length" = 10 + "StartLine" = 1 + "StartColumn" = 21 + "EndLine" = 1 + "EndColumn" = 31 + }, + @{ + "Content" = "-RequiredVersion" + "Type" = "CommandParameter" + "Start" = 31 + "Length" = 16 + "StartLine" = 1 + "StartColumn" = 32 + "EndLine" = 1 + "EndColumn" = 48 + }, + @{ + "Content" = "1.0.0" + "Type" = "String" + "Start" = 48 + "Length" = 7 + "StartLine" = 1 + "StartColumn" = 49 + "EndLine" = 1 + "EndColumn" = 56 + } + ) + + $importModuleTokens = $ParsedContent + + TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens + + } | Should -Not -Throw + + } + + It "should throw when passed a valid Import-Module command missing all required parameters" { + + { + + $ParsedContent = @( + @{ + "Content" = "Import-Module" + "Type" = "Command" + "Start" = 0 + "Length" = 13 + "StartLine" = 1 + "StartColumn" = 1 + "EndLine" = 1 + "EndColumn" = 14 + }, + @{ + "Content" = "ModuleName" + "Type" = "CommandArgument" + "Start" = 14 + "Length" = 10 + "StartLine" = 1 + "StartColumn" = 15 + "EndLine" = 1 + "EndColumn" = 25 + } + ) + + $importModuleTokens = $ParsedContent + + TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens + + } | Should -Throw + + } + + It "should throw when passed a valid Import-Module command missing -Name only" { + + { + + $ParsedContent = @( + @{ + "Content" = "Import-Module" + "Type" = "Command" + "Start" = 0 + "Length" = 13 + "StartLine" = 1 + "StartColumn" = 1 + "EndLine" = 1 + "EndColumn" = 14 + }, + @{ + "Content" = "ModuleName" + "Type" = "CommandArgument" + "Start" = 14 + "Length" = 10 + "StartLine" = 1 + "StartColumn" = 15 + "EndLine" = 1 + "EndColumn" = 25 + }, + @{ + "Content" = "-RequiredVersion" + "Type" = "CommandParameter" + "Start" = 25 + "Length" = 16 + "StartLine" = 1 + "StartColumn" = 26 + "EndLine" = 1 + "EndColumn" = 42 + }, + @{ + "Content" = "1.0.0" + "Type" = "String" + "Start" = 42 + "Length" = 7 + "StartLine" = 1 + "StartColumn" = 43 + "EndLine" = 1 + "EndColumn" = 50 + } + ) + + $importModuleTokens = $ParsedContent + + TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens + + } | Should -Throw + + } + + It "should throw when passed a valid Import-Module command missing -RequiredVersion, -MinimumVersion or -MaximumVersion" { + + { + + $ParsedContent = @( + @{ + "Content" = "Import-Module" + "Type" = "Command" + "Start" = 0 + "Length" = 13 + "StartLine" = 1 + "StartColumn" = 1 + "EndLine" = 1 + "EndColumn" = 14 + }, + @{ + "Content" = "-Name" + "Type" = "CommandParameter" + "Start" = 14 + "Length" = 5 + "StartLine" = 1 + "StartColumn" = 15 + "EndLine" = 1 + "EndColumn" = 20 + }, + @{ + "Content" = "ModuleName" + "Type" = "CommandArgument" + "Start" = 20 + "Length" = 10 + "StartLine" = 1 + "StartColumn" = 21 + "EndLine" = 1 + "EndColumn" = 31 + } + ) + + $importModuleTokens = $ParsedContent + + TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens + + } | Should -Throw + + } + + } + +} diff --git a/Tests/Unit/PSQualityCheck/Test-ParameterVariablesHaveType.Tests.ps1 b/Tests/Unit/PSQualityCheck/TestParameterVariablesHaveType.Tests.ps1 similarity index 76% rename from Tests/Unit/PSQualityCheck/Test-ParameterVariablesHaveType.Tests.ps1 rename to Tests/Unit/PSQualityCheck/TestParameterVariablesHaveType.Tests.ps1 index 37e5690..407784d 100644 --- a/Tests/Unit/PSQualityCheck/Test-ParameterVariablesHaveType.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/TestParameterVariablesHaveType.Tests.ps1 @@ -1,11 +1,11 @@ -Describe "Test-ParameterVariablesHaveType.Tests" { +Describe "TestParameterVariablesHaveType.Tests" { - Context "Parameter Tests" -ForEach @( + Context "Parameter Tests" -Foreach @( @{ 'Name' = 'ParameterVariables'; 'Type' = 'HashTable' } ) { BeforeAll { - $commandletUnderTest = "Test-ParameterVariablesHaveType" + $commandletUnderTest = "TestParameterVariablesHaveType" } It "should have $Name as a mandatory parameter" { @@ -35,7 +35,7 @@ Describe "Test-ParameterVariablesHaveType.Tests" { { - Test-ParameterVariablesHaveType -ParameterVariables $null + TestParameterVariablesHaveType -ParameterVariables $null } | Should -Throw @@ -48,7 +48,7 @@ Describe "Test-ParameterVariablesHaveType.Tests" { 'ParameterWithType' = '[string]' } - Test-ParameterVariablesHaveType -ParameterVariables $parameterVariable + TestParameterVariablesHaveType -ParameterVariables $parameterVariable } | Should -Not -Throw @@ -61,7 +61,7 @@ Describe "Test-ParameterVariablesHaveType.Tests" { 'ParameterWithoutType' = $null } - Test-ParameterVariablesHaveType -ParameterVariables $parameterVariable + TestParameterVariablesHaveType -ParameterVariables $parameterVariable } | Should -Throw @@ -74,7 +74,7 @@ Describe "Test-ParameterVariablesHaveType.Tests" { 'ParameterWithEmptyType' = '' } - Test-ParameterVariablesHaveType -ParameterVariables $parameterVariable + TestParameterVariablesHaveType -ParameterVariables $parameterVariable } | Should -Throw diff --git a/Tests/Unit/PSQualityCheck/Test-RequiredToken.Tests.ps1 b/Tests/Unit/PSQualityCheck/TestRequiredToken.Tests.ps1 similarity index 95% rename from Tests/Unit/PSQualityCheck/Test-RequiredToken.Tests.ps1 rename to Tests/Unit/PSQualityCheck/TestRequiredToken.Tests.ps1 index 4bc30e8..6574dc4 100644 --- a/Tests/Unit/PSQualityCheck/Test-RequiredToken.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/TestRequiredToken.Tests.ps1 @@ -1,11 +1,11 @@ -Describe "Test-RequiredToken.Tests" { +Describe "TestRequiredToken.Tests" { Context "Parameter Tests" -ForEach @( @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } ) { BeforeAll { - $commandletUnderTest = "Test-RequiredToken" + $commandletUnderTest = "TestRequiredToken" } It "should have $Name as a mandatory parameter" { @@ -97,7 +97,7 @@ Describe "Test-RequiredToken.Tests" { { - Test-RequiredToken -HelpTokens $null + TestRequiredToken -HelpTokens $null } | Should -Throw @@ -137,7 +137,7 @@ Describe "Test-RequiredToken.Tests" { ) } - Test-RequiredToken -HelpTokens $helpTokens + TestRequiredToken -HelpTokens $helpTokens Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } @@ -188,7 +188,7 @@ Describe "Test-RequiredToken.Tests" { } - Test-RequiredToken -HelpTokens $helpTokens + TestRequiredToken -HelpTokens $helpTokens Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } @@ -223,7 +223,7 @@ Describe "Test-RequiredToken.Tests" { ) } - Test-RequiredToken -HelpTokens $helpTokens + TestRequiredToken -HelpTokens $helpTokens Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } diff --git a/Tests/Unit/PSQualityCheck/Test-UnspecifiedToken.Tests.ps1 b/Tests/Unit/PSQualityCheck/TestUnspecifiedToken.Tests.ps1 similarity index 94% rename from Tests/Unit/PSQualityCheck/Test-UnspecifiedToken.Tests.ps1 rename to Tests/Unit/PSQualityCheck/TestUnspecifiedToken.Tests.ps1 index 6c274a7..6f6e083 100644 --- a/Tests/Unit/PSQualityCheck/Test-UnspecifiedToken.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/TestUnspecifiedToken.Tests.ps1 @@ -1,11 +1,11 @@ -Describe "Test-UnspecifiedToken.Tests" { +Describe "TestUnspecifiedToken.Tests" { - Context "Parameter Tests" -ForEach @( + Context "Parameter Tests" -Foreach @( @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } ) { BeforeAll { - $commandletUnderTest = "Test-UnspecifiedToken" + $commandletUnderTest = "TestUnspecifiedToken" } It "should have $Name as a mandatory parameter" { @@ -97,7 +97,7 @@ Describe "Test-UnspecifiedToken.Tests" { { - Test-UnspecifiedToken -HelpTokens $null + TestUnspecifiedToken -HelpTokens $null } | Should -Throw @@ -137,7 +137,7 @@ Describe "Test-UnspecifiedToken.Tests" { ) } - Test-UnspecifiedToken -HelpTokens $helpTokens + TestUnspecifiedToken -HelpTokens $helpTokens Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } @@ -188,7 +188,7 @@ Describe "Test-UnspecifiedToken.Tests" { } - Test-UnspecifiedToken -HelpTokens $helpTokens + TestUnspecifiedToken -HelpTokens $helpTokens Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } @@ -209,7 +209,7 @@ Describe "Test-UnspecifiedToken.Tests" { ) } - Test-UnspecifiedToken -HelpTokens $helpTokens + TestUnspecifiedToken -HelpTokens $helpTokens Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } From 1700f1b9235efb8c42199b7b001abf0f1d6ad4c2 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Wed, 28 Apr 2021 16:35:17 +0100 Subject: [PATCH 21/27] Added empty files to keep the folders in git --- Source/PSQualityCheck/classes/readme.md | 0 Tests/scripts/readme.md | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 Source/PSQualityCheck/classes/readme.md create mode 100644 Tests/scripts/readme.md diff --git a/Source/PSQualityCheck/classes/readme.md b/Source/PSQualityCheck/classes/readme.md new file mode 100644 index 0000000..e69de29 diff --git a/Tests/scripts/readme.md b/Tests/scripts/readme.md new file mode 100644 index 0000000..e69de29 From f945dc8868ea6c86db3aed6c0884d1f09416e95c Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Wed, 28 Apr 2021 21:19:54 +0100 Subject: [PATCH 22/27] Fix unit tests --- .../Unit/PSQualityCheck/ConvertHelp.Tests.ps1 | 310 +++++------ .../ExportFunctionsFromModule.Tests.ps1 | 150 +++--- .../PSQualityCheck/GetFileContent.Tests.ps1 | 207 ++++--- .../Unit/PSQualityCheck/GetFileList.Tests.ps1 | 188 +++---- .../PSQualityCheck/GetFunctionCount.Tests.ps1 | 159 +++--- .../PSQualityCheck/GetParsedContent.Tests.ps1 | 214 ++++---- .../PSQualityCheck/GetParsedFile.Tests.ps1 | 246 ++++----- .../GetScriptParameter.Tests.ps1 | 121 +++-- .../Unit/PSQualityCheck/GetTagList.Tests.ps1 | 8 +- Tests/Unit/PSQualityCheck/GetToken.Tests.ps1 | 182 ++++--- .../GetTokenComponent.Tests.ps1 | 182 ++++--- .../PSQualityCheck/GetTokenMarker.Tests.ps1 | 178 +++--- .../TestHelpTokensCountisValid.Tests.ps1 | 264 ++++----- .../TestHelpTokensParamsMatch.Tests.ps1 | 508 +++++++++--------- .../TestHelpTokensTextIsValid.Tests.ps1 | 484 ++++++++--------- .../TestImportModuleIsValid.Tests.ps1 | 456 ++++++++-------- .../TestParameterVariablesHaveType.Tests.ps1 | 96 ++-- .../TestRequiredToken.Tests.ps1 | 310 +++++------ .../TestUnspecifiedToken.Tests.ps1 | 276 +++++----- 19 files changed, 2322 insertions(+), 2217 deletions(-) diff --git a/Tests/Unit/PSQualityCheck/ConvertHelp.Tests.ps1 b/Tests/Unit/PSQualityCheck/ConvertHelp.Tests.ps1 index 667ad19..1fc31e0 100644 --- a/Tests/Unit/PSQualityCheck/ConvertHelp.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/ConvertHelp.Tests.ps1 @@ -1,203 +1,205 @@ -Describe "ConvertHelp.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -ForEach @( - @{ 'Name' = 'Help'; 'Type' = 'String' } - ) { + Describe "ConvertHelp.Tests" { - BeforeAll { - $commandletUnderTest = "ConvertHelp" - } + Context "Parameter Tests" -ForEach @( + @{ 'Name' = 'Help'; 'Type' = 'String' } + ) { - It "should have $Name as a mandatory parameter" { + BeforeAll { + $commandletUnderTest = "ConvertHelp" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + It "should have $Name as a mandatory parameter" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - It "should $Name not belong to a parameter set" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + It "should $Name not belong to a parameter set" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - It "should $Name type be $Type" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + It "should $Name type be $Type" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - } + } + + } - Context "Function tests" { + Context "Function tests" { - It "should throw when passing null parameters" { + It "should throw when passing null parameters" { - { + { - ConvertHelp -Help $null + ConvertHelp -Help $null - } | Should -Throw + } | Should -Throw - } + } - It "should throw on invalid help" { + It "should throw on invalid help" { - { - $helpComment = '##InvalidHelp##' + { + $helpComment = '##InvalidHelp##' - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - } | Should -Throw + } | Should -Throw - } + } - It "should throw on empty help" { + It "should throw on empty help" { - { - $helpComment = '' + { + $helpComment = '' - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - } | Should -Throw + } | Should -Throw - } + } - It "should find in help" -Foreach @( - @{ 'Token' = '.SYNOPSIS' } - @{ 'Token' = '.DESCRIPTION' } - @{ 'Token' = '.PARAMETER' } - @{ 'Token' = '.EXAMPLE' } - @{ 'Token' = '.INPUTS' } - @{ 'Token' = '.OUTPUTS' } - @{ 'Token' = '.NOTES' } - @{ 'Token' = '.LINK' } - @{ 'Token' = '.COMPONENT' } - @{ 'Token' = '.ROLE' } - @{ 'Token' = '.FUNCTIONALITY' } - @{ 'Token' = '.FORWARDHELPTARGETNAME' } - @{ 'Token' = '.FORWARDHELPCATEGORY' } - @{ 'Token' = '.REMOTEHELPRUNSPACE' } - @{ 'Token' = '.EXTERNALHELP' } - ) { + It "should find in help" -Foreach @( + @{ 'Token' = '.SYNOPSIS' } + @{ 'Token' = '.DESCRIPTION' } + @{ 'Token' = '.PARAMETER' } + @{ 'Token' = '.EXAMPLE' } + @{ 'Token' = '.INPUTS' } + @{ 'Token' = '.OUTPUTS' } + @{ 'Token' = '.NOTES' } + @{ 'Token' = '.LINK' } + @{ 'Token' = '.COMPONENT' } + @{ 'Token' = '.ROLE' } + @{ 'Token' = '.FUNCTIONALITY' } + @{ 'Token' = '.FORWARDHELPTARGETNAME' } + @{ 'Token' = '.FORWARDHELPCATEGORY' } + @{ 'Token' = '.REMOTEHELPRUNSPACE' } + @{ 'Token' = '.EXTERNALHELP' } + ) { - $helpComment = "<# + $helpComment = "<# $($token) #>" - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - $help.ContainsKey($token) | Should -BeTrue + $help.ContainsKey($token) | Should -BeTrue - } + } - It "should find .PARAMETER named Path" { + It "should find .PARAMETER named Path" { - $helpComment = "<# + $helpComment = "<# .PARAMETER Path #>" - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - $help.ContainsKey(".PARAMETER") | Should -BeTrue + $help.ContainsKey(".PARAMETER") | Should -BeTrue - $help.".PARAMETER".Name | Should -Be "Path" + $help.".PARAMETER".Name | Should -Be "Path" - } + } - It "should find multiple .PARAMETERs named Path and Source" { + It "should find multiple .PARAMETERs named Path and Source" { - $helpComment = "<# + $helpComment = "<# .PARAMETER Path .PARAMETER Source #>" - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - $help.ContainsKey(".PARAMETER") | Should -BeTrue + $help.ContainsKey(".PARAMETER") | Should -BeTrue - $help.".PARAMETER".Name | Should -Be @('Path', 'Source') + $help.".PARAMETER".Name | Should -Be @('Path', 'Source') - } + } - It "should find multiple .EXAMPLEs" { + It "should find multiple .EXAMPLEs" { - $helpComment = "<# + $helpComment = "<# .EXAMPLE Function -Path .EXAMPLE Function -Source #>" - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - $help.ContainsKey(".EXAMPLE") | Should -BeTrue + $help.ContainsKey(".EXAMPLE") | Should -BeTrue - $help.".EXAMPLE".Count | Should -Be 2 + $help.".EXAMPLE".Count | Should -Be 2 - } + } - It "should not find .DUMMY in help" { + It "should not find .DUMMY in help" { - $helpComment = "<# + $helpComment = "<# .DUMMY #>" - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - $help.ContainsKey(".DUMMY") | Should -BeFalse + $help.ContainsKey(".DUMMY") | Should -BeFalse - } + } - It "should not find .DUMMY but find .NOTES in help" { + It "should not find .DUMMY but find .NOTES in help" { - $helpComment = "<# + $helpComment = "<# .DUMMY .NOTES #>" - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - $help.ContainsKey(".DUMMY") | Should -BeFalse - $help.ContainsKey(".NOTES") | Should -BeTrue + $help.ContainsKey(".DUMMY") | Should -BeFalse + $help.ContainsKey(".NOTES") | Should -BeTrue - } + } - It "should find no help element text when text is empty" { + It "should find no help element text when text is empty" { - { - $helpComment = "<# + { + $helpComment = "<# .SYNOPSIS #>" - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - ([string]::IsNullOrEmpty($help.".SYNOPSIS".Text)) | Should -BeTrue + ([string]::IsNullOrEmpty($help.".SYNOPSIS".Text)) | Should -BeTrue - } | Should -Not -Throw + } | Should -Not -Throw - } + } - It "should find no help element text when text is missing" { + It "should find no help element text when text is missing" { - { - $helpComment = "<# + { + $helpComment = "<# .SYNOPSIS #>" - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - ([string]::IsNullOrEmpty($help.".SYNOPSIS".Text)) | Should -BeTrue + ([string]::IsNullOrEmpty($help.".SYNOPSIS".Text)) | Should -BeTrue - } | Should -Not -Throw + } | Should -Not -Throw - } + } - It "should find multiple help element text values" { + It "should find multiple help element text values" { - { - $helpComment = "<# + { + $helpComment = "<# .SYNOPSIS The SYNOPSIS property .DESCRIPTION @@ -206,20 +208,20 @@ Describe "ConvertHelp.Tests" { The Path parameter #>" - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - $help.".SYNOPSIS".Text | Should -BeExactly "The SYNOPSIS property" - $help.".DESCRIPTION".Text | Should -BeExactly "The DESCRIPTION property" - $help.".PARAMETER".Text | Should -BeExactly "The Path parameter" + $help.".SYNOPSIS".Text | Should -BeExactly "The SYNOPSIS property" + $help.".DESCRIPTION".Text | Should -BeExactly "The DESCRIPTION property" + $help.".PARAMETER".Text | Should -BeExactly "The Path parameter" - } | Should -Not -Throw + } | Should -Not -Throw - } + } - It "should find multiple help element text values where one is empty" { + It "should find multiple help element text values where one is empty" { - { - $helpComment = "<# + { + $helpComment = "<# .SYNOPSIS .DESCRIPTION @@ -228,20 +230,20 @@ Describe "ConvertHelp.Tests" { The Path parameter #>" - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - $help.".SYNOPSIS".Text | Should -BeExactly "" - $help.".DESCRIPTION".Text | Should -BeExactly "The DESCRIPTION property" - $help.".PARAMETER".Text | Should -BeExactly "The Path parameter" + $help.".SYNOPSIS".Text | Should -BeExactly "" + $help.".DESCRIPTION".Text | Should -BeExactly "The DESCRIPTION property" + $help.".PARAMETER".Text | Should -BeExactly "The Path parameter" - } | Should -Not -Throw + } | Should -Not -Throw - } + } - It "should find multiple help element text values where one is missing" { + It "should find multiple help element text values where one is missing" { - { - $helpComment = "<# + { + $helpComment = "<# .SYNOPSIS .DESCRIPTION The DESCRIPTION property @@ -249,20 +251,20 @@ Describe "ConvertHelp.Tests" { The Path parameter #>" - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - $help.".SYNOPSIS".Text | Should -BeExactly $null - $help.".DESCRIPTION".Text | Should -BeExactly "The DESCRIPTION property" - $help.".PARAMETER".Text | Should -BeExactly "The Path parameter" + $help.".SYNOPSIS".Text | Should -BeExactly $null + $help.".DESCRIPTION".Text | Should -BeExactly "The DESCRIPTION property" + $help.".PARAMETER".Text | Should -BeExactly "The Path parameter" - } | Should -Not -Throw + } | Should -Not -Throw - } + } - It "should find no help element text values when all text values are empty" { + It "should find no help element text values when all text values are empty" { - { - $helpComment = "<# + { + $helpComment = "<# .SYNOPSIS .DESCRIPTION @@ -271,39 +273,39 @@ Describe "ConvertHelp.Tests" { #>" - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - $help.".SYNOPSIS".Text | Should -BeExactly "" - $help.".DESCRIPTION".Text | Should -BeExactly "" - $help.".PARAMETER".Text | Should -BeExactly "" + $help.".SYNOPSIS".Text | Should -BeExactly "" + $help.".DESCRIPTION".Text | Should -BeExactly "" + $help.".PARAMETER".Text | Should -BeExactly "" - } | Should -Not -Throw + } | Should -Not -Throw - } + } - It "should find no help element text values when all text values are missing" { + It "should find no help element text values when all text values are missing" { - { - $helpComment = "<# + { + $helpComment = "<# .SYNOPSIS .DESCRIPTION .PARAMETER Path #>" - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment - $help.".SYNOPSIS".Text | Should -BeExactly $null - $help.".DESCRIPTION".Text | Should -BeExactly $null - $help.".PARAMETER".Text | Should -BeExactly $null + $help.".SYNOPSIS".Text | Should -BeExactly $null + $help.".DESCRIPTION".Text | Should -BeExactly $null + $help.".PARAMETER".Text | Should -BeExactly $null - } | Should -Not -Throw + } | Should -Not -Throw - } + } - It "should find correct line numbers" { + It "should find correct line numbers" { - { - $helpComment = "<# + { + $helpComment = "<# .SYNOPSIS The SYNOPSIS property .DESCRIPTION @@ -312,13 +314,15 @@ Describe "ConvertHelp.Tests" { The Path parameter #>" - $help = ConvertHelp -Help $helpComment + $help = ConvertHelp -Help $helpComment + + $help.".SYNOPSIS".LineNumber | Should -BeExactly 1 + $help.".DESCRIPTION".LineNumber | Should -BeExactly 3 + $help.".PARAMETER".LineNumber | Should -BeExactly 5 - $help.".SYNOPSIS".LineNumber | Should -BeExactly 1 - $help.".DESCRIPTION".LineNumber | Should -BeExactly 3 - $help.".PARAMETER".LineNumber | Should -BeExactly 5 + } | Should -Not -Throw - } | Should -Not -Throw + } } diff --git a/Tests/Unit/PSQualityCheck/ExportFunctionsFromModule.Tests.ps1 b/Tests/Unit/PSQualityCheck/ExportFunctionsFromModule.Tests.ps1 index 6850c1b..a2d1bb0 100644 --- a/Tests/Unit/PSQualityCheck/ExportFunctionsFromModule.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/ExportFunctionsFromModule.Tests.ps1 @@ -1,129 +1,133 @@ -Describe "ExportFunctionsFromModule.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -Foreach @( - @{ 'Name' = 'Path'; 'Type' = 'String' } - @{ 'Name' = 'ExtractPath'; 'Type' = 'String' } - ) { + Describe "ExportFunctionsFromModule.Tests" { - BeforeAll { - $commandletUnderTest = "ExportFunctionsFromModule" - } + Context "Parameter Tests" -ForEach @( + @{ 'Name' = 'Path'; 'Type' = 'String' } + @{ 'Name' = 'ExtractPath'; 'Type' = 'String' } + ) { - It "should have $Name as a mandatory parameter" { + BeforeAll { + $commandletUnderTest = "ExportFunctionsFromModule" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + It "should have $Name as a mandatory parameter" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - It "should $Name not belong to a parameter set" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + It "should $Name not belong to a parameter set" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - It "should $Name type be $Type" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + It "should $Name type be $Type" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - } + } - Context "Function tests" { + } - BeforeAll { + Context "Function tests" { - $sourcePath = Join-Path -Path $TestDrive -ChildPath "Source" - New-Item -Path $sourcePath -ItemType Directory - $extractPath = Join-Path -Path $TestDrive -ChildPath "Extract" - New-Item -Path $extractPath -ItemType Directory + BeforeAll { - } + $sourcePath = Join-Path -Path $TestDrive -ChildPath "Source" + New-Item -Path $sourcePath -ItemType Directory + $extractPath = Join-Path -Path $TestDrive -ChildPath "Extract" + New-Item -Path $extractPath -ItemType Directory - It "should throw when passing null parameters" { + } - { + It "should throw when passing null parameters" { - ExportFunctionsFromModule -Path $null -ExtractPath $null + { - } | Should -Throw + ExportFunctionsFromModule -Path $null -ExtractPath $null - } + } | Should -Throw - It "should throw when passing non-module file" { + } - { - $fileContent = "" - $testPath1 = Join-Path -Path $sourcePath -ChildPath 'test.ps1' - Set-Content -Path $testPath1 -Value $fileContent + It "should throw when passing non-module file" { - ExportFunctionsFromModule -Path $testPath1 -ExtractPath $extractPath + { + $fileContent = "" + $testPath1 = Join-Path -Path $sourcePath -ChildPath 'test.ps1' + Set-Content -Path $testPath1 -Value $fileContent - } | Should -Throw + ExportFunctionsFromModule -Path $testPath1 -ExtractPath $extractPath - } + } | Should -Throw - It "should throw when passing functionless module file" { + } - { - $fileContent = "" - $testPath1 = Join-Path -Path $sourcePath -ChildPath 'test.psm1' - Set-Content -Path $testPath1 -Value $fileContent + It "should throw when passing functionless module file" { - ExportFunctionsFromModule -Path $testPath1 -ExtractPath $extractPath + { + $fileContent = "" + $testPath1 = Join-Path -Path $sourcePath -ChildPath 'test.psm1' + Set-Content -Path $testPath1 -Value $fileContent - } | Should -Throw + ExportFunctionsFromModule -Path $testPath1 -ExtractPath $extractPath - } + } | Should -Throw - It "should not throw and create valid extracted file when passing simple, valid module file" { + } - { - $testPath1 = Join-Path -Path $sourcePath -ChildPath 'test.psm1' - $fileContent = "function Test-Function { + It "should not throw and create valid extracted file when passing simple, valid module file" { + + { + $testPath1 = Join-Path -Path $sourcePath -ChildPath 'test.psm1' + $fileContent = "function Test-Function { Write-Host }" - Set-Content -Path $testPath1 -Value $fileContent + Set-Content -Path $testPath1 -Value $fileContent - $functionPath = Join-Path $extractPath -ChildPath "test" - $functionFile = Join-Path $functionPath -ChildPath "Test-Function.ps1" + $functionPath = Join-Path $extractPath -ChildPath "test" + $functionFile = Join-Path $functionPath -ChildPath "Test-Function.ps1" - ExportFunctionsFromModule -Path $testPath1 -ExtractPath $extractPath + ExportFunctionsFromModule -Path $testPath1 -ExtractPath $extractPath - $files = Get-ChildItem -Path $functionPath + $files = Get-ChildItem -Path $functionPath - (Get-ChildItem -Path $functionPath).Count | Should -BeExactly 1 - (Get-ChildItem -Path $functionPath).FullName | Should -BeExactly $functionFile + (Get-ChildItem -Path $functionPath).Count | Should -BeExactly 1 + (Get-ChildItem -Path $functionPath).FullName | Should -BeExactly $functionFile - } | Should -Not -Throw + } | Should -Not -Throw - } + } - It "should not throw and create valid extracted files when passing simple, valid multi-function module file" { + It "should not throw and create valid extracted files when passing simple, valid multi-function module file" { - { - $testPath1 = Join-Path -Path $sourcePath -ChildPath 'test.psm1' - $fileContent = "function Test-Function { + { + $testPath1 = Join-Path -Path $sourcePath -ChildPath 'test.psm1' + $fileContent = "function Test-Function { Write-Host } function Test-SecondFunction { Write-Host }" - Set-Content -Path $testPath1 -Value $fileContent + Set-Content -Path $testPath1 -Value $fileContent + + $functionPath = Join-Path $extractPath -ChildPath "test" + $functionFile1 = Join-Path $functionPath -ChildPath "Test-Function.ps1" + $functionFile2 = Join-Path $functionPath -ChildPath "Test-SecondFunction.ps1" - $functionPath = Join-Path $extractPath -ChildPath "test" - $functionFile1 = Join-Path $functionPath -ChildPath "Test-Function.ps1" - $functionFile2 = Join-Path $functionPath -ChildPath "Test-SecondFunction.ps1" + ExportFunctionsFromModule -Path $testPath1 -ExtractPath $extractPath - ExportFunctionsFromModule -Path $testPath1 -ExtractPath $extractPath + $files = Get-ChildItem -Path $functionPath - $files = Get-ChildItem -Path $functionPath + (Get-ChildItem -Path $functionPath).Count | Should -BeExactly 2 + (Get-ChildItem -Path $functionPath).FullName | Should -BeExactly @($functionFile1, $functionFile2) - (Get-ChildItem -Path $functionPath).Count | Should -BeExactly 2 - (Get-ChildItem -Path $functionPath).FullName | Should -BeExactly @($functionFile1, $functionFile2) + } | Should -Not -Throw - } | Should -Not -Throw + } } diff --git a/Tests/Unit/PSQualityCheck/GetFileContent.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetFileContent.Tests.ps1 index edc27b1..19c002c 100644 --- a/Tests/Unit/PSQualityCheck/GetFileContent.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetFileContent.Tests.ps1 @@ -1,158 +1,187 @@ -Describe "GetFileContent.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -Foreach @( - @{ 'Name' = 'Path'; 'Type' = 'String' } - ) { + Describe "GetFileContent.Tests" { - BeforeAll { - $commandletUnderTest = "GetFileContent" - } + Context "Parameter Tests" -Foreach @( + @{ 'Name' = 'Path'; 'Type' = 'String' } + ) { - It "should have $Name as a mandatory parameter" { + BeforeAll { + $commandletUnderTest = "GetFileContent" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + It "should have $Name as a mandatory parameter" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - It "should $Name not belong to a parameter set" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + It "should $Name not belong to a parameter set" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + + } + + It "should $Name type be $Type" { - It "should $Name type be $Type" { + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + } } - } + Context "Function tests" { - Context "Function tests" { + It "should throw when passing null parameters" { - It "should throw when passing null parameters" { + { - { + GetFileContent -Path $null - GetFileContent -Path $null + } | Should -Throw - } | Should -Throw + } - } + It "should pass when Path is valid with no function, empty content in the file" { + + $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' + $fileContent = "" + Set-Content -Path $testPath -Value $fileContent - It "should pass when Path is valid with no function, empty content in the file" { + $parsedFileContent = GetFileContent -Path $testPath - $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent = "" - Set-Content -Path $testPath -Value $fileContent + Write-Verbose "FC" -Verbose + Write-Verbose $fileContent.GetType() -Verbose + Write-Verbose "PC" -Verbose + Write-Verbose $parsedFileContent.GetType() -Verbose + Write-Verbose "FC" -Verbose + Write-Verbose $fileContent -Verbose + Write-Verbose "PC" -Verbose + Write-Verbose $parsedFileContent -Verbose - $parsedFileContent = GetFileContent -Path $testPath + ($fileContent -eq $parsedFileContent) | Should -BeTrue - ($fileContent -eq $parsedFileContent) | Should -BeTrue + } - } + It "should pass when Path is valid with no function, single-line content in the file" { - It "should pass when Path is valid with no function, single-line content in the file" { + $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' + $fileContent = "Write-Host" + Set-Content -Path $testPath -Value $fileContent - $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent = "Write-Host" - Set-Content -Path $testPath -Value $fileContent + $parsedFileContent = GetFileContent -Path $testPath - $parsedFileContent = GetFileContent -Path $testPath + Write-Verbose "FC" -Verbose + Write-Verbose $fileContent.GetType() -Verbose + Write-Verbose "PC" -Verbose + Write-Verbose $parsedFileContent.GetType() -Verbose + Write-Verbose "FC" -Verbose + Write-Verbose $fileContent -Verbose + Write-Verbose "PC" -Verbose + Write-Verbose $parsedFileContent -Verbose - ($fileContent -eq $parsedFileContent) | Should -BeTrue + ($fileContent -eq $parsedFileContent) | Should -BeTrue - } + } - It "should pass when Path is valid with no function, multi-line content in the file" { + It "should pass when Path is valid with no function, multi-line content in the file" { - $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent = "Write-Host + $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' + $fileContent = "Write-Host Write-Host " - Set-Content -Path $testPath -Value $fileContent + Set-Content -Path $testPath -Value $fileContent - $parsedFileContent = GetFileContent -Path $testPath + $parsedFileContent = GetFileContent -Path $testPath - ($fileContent -eq $parsedFileContent) | Should -BeTrue + Write-Verbose "FC" -Verbose + Write-Verbose $fileContent.GetType() -Verbose + Write-Verbose "PC" -Verbose + Write-Verbose $parsedFileContent.GetType() -Verbose + Write-Verbose "FC" -Verbose + Write-Verbose $fileContent -Verbose + Write-Verbose "PC" -Verbose + Write-Verbose $parsedFileContent -Verbose - } + ($fileContent -eq $parsedFileContent) | Should -BeTrue - It "should pass when Path is valid with only one empty function in the file" { + } - $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent = "function GetFileContent {}" - $matchContent = "" - Set-Content -Path $testPath -Value $fileContent + It "should pass when Path is valid with only one empty function in the file" { - $parsedFileContent = GetFileContent -Path $testPath + $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' + $fileContent = "function GetFileContent {}" + $matchContent = "" + Set-Content -Path $testPath -Value $fileContent - ($matchContent -eq $parsedFileContent) | Should -BeTrue + $parsedFileContent = GetFileContent -Path $testPath - } + ($matchContent -eq $parsedFileContent) | Should -BeTrue - It "should pass when Path is valid with only one single-line function in the file" { + } - $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent = "function GetFileContent { Write-Host }" - $matchContent = " Write-Host " - Set-Content -Path $testPath -Value $fileContent + It "should pass when Path is valid with only one single-line function in the file" { - $parsedFileContent = GetFileContent -Path $testPath + $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' + $fileContent = "function GetFileContent { Write-Host }" + $matchContent = " Write-Host " + Set-Content -Path $testPath -Value $fileContent - ($matchContent -eq $parsedFileContent) | Should -BeTrue + $parsedFileContent = GetFileContent -Path $testPath - } + ($matchContent -eq $parsedFileContent) | Should -BeTrue - It "should pass when Path is valid with only one single-line advanced function in the file" { + } - $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent = "function GetFileContent { if ($true) { Write-Host } }" - $matchContent = " if ($true) { Write-Host } " - Set-Content -Path $testPath -Value $fileContent + It "should pass when Path is valid with only one single-line advanced function in the file" { - $parsedFileContent = GetFileContent -Path $testPath + $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' + $fileContent = "function GetFileContent { if ($true) { Write-Host } }" + $matchContent = " if ($true) { Write-Host } " + Set-Content -Path $testPath -Value $fileContent - ($matchContent -eq $parsedFileContent) | Should -BeTrue + $parsedFileContent = GetFileContent -Path $testPath - } + ($matchContent -eq $parsedFileContent) | Should -BeTrue + + } - It "should pass when Path is valid with only one multi-line function in the file" { + It "should pass when Path is valid with only one multi-line function in the file" { - $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent1 = "function GetFileContent { + $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' + $fileContent1 = "function GetFileContent { Write-Host }" - $matchContent1 = " Write-Host`r`n" + $matchContent1 = " Write-Host`r`n" - Set-Content -Path $testPath -Value $fileContent1 + Set-Content -Path $testPath -Value $fileContent1 - $parsedFileContent1 = GetFileContent -Path $testPath + $parsedFileContent1 = GetFileContent -Path $testPath - $fileContent2 = "function GetFileContent { + $fileContent2 = "function GetFileContent { if ($true) { Write-Host } }" - $matchContent2 = " if ($true) { + $matchContent2 = " if ($true) { Write-Host }`r`n" - Set-Content -Path $testPath -Value $fileContent2 + Set-Content -Path $testPath -Value $fileContent2 - $parsedFileContent2 = GetFileContent -Path $testPath + $parsedFileContent2 = GetFileContent -Path $testPath - ($matchContent1 -eq $parsedFileContent1) | Should -BeTrue - ($matchContent2 -eq $parsedFileContent2) | Should -BeTrue + ($matchContent1 -eq $parsedFileContent1) | Should -BeTrue + ($matchContent2 -eq $parsedFileContent2) | Should -BeTrue - } + } - It "should throw when Path is valid with two functions in the file" { + It "should throw when Path is valid with two functions in the file" { - { - $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent = "function GetFileContent { + { + $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' + $fileContent = "function GetFileContent { Write-Host } @@ -160,11 +189,13 @@ Describe "GetFileContent.Tests" { Write-Host }" - Set-Content -Path $testPath -Value $fileContent + Set-Content -Path $testPath -Value $fileContent - $parsedFileContent = GetFileContent -Path $testPath + $parsedFileContent = GetFileContent -Path $testPath + + } | Should -Throw - } | Should -Throw + } } diff --git a/Tests/Unit/PSQualityCheck/GetFileList.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetFileList.Tests.ps1 index d5ebb34..70ac7e6 100644 --- a/Tests/Unit/PSQualityCheck/GetFileList.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetFileList.Tests.ps1 @@ -1,155 +1,159 @@ -Describe "GetFileList.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -Foreach @( - @{ 'Name' = 'Path'; 'Type' = 'String'; 'MandatoryFlag' = $true } - @{ 'Name' = 'Extension'; 'Type' = 'String'; 'MandatoryFlag' = $true } - @{ 'Name' = 'Recurse'; 'Type' = 'SwitchParameter'; 'MandatoryFlag' = $false } - ) { + Describe "GetFileList.Tests" { - BeforeAll { - $commandletUnderTest = "GetFileList" - } + Context "Parameter Tests" -ForEach @( + @{ 'Name' = 'Path'; 'Type' = 'String'; 'MandatoryFlag' = $true } + @{ 'Name' = 'Extension'; 'Type' = 'String'; 'MandatoryFlag' = $true } + @{ 'Name' = 'Recurse'; 'Type' = 'SwitchParameter'; 'MandatoryFlag' = $false } + ) { - It "should have $Name as a mandatory parameter" { + BeforeAll { + $commandletUnderTest = "GetFileList" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeExactly $MandatoryFlag + It "should have $Name as a mandatory parameter" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeExactly $MandatoryFlag - It "should $Name not belong to a parameter set" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + It "should $Name not belong to a parameter set" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + + } - It "should $Name type be $Type" { + It "should $Name type be $Type" { - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + + } } - } + Context "Function tests" { - Context "Function tests" { + It "should throw when passing null parameters" { - It "should throw when passing null parameters" { + { - { + GetFileList -Path $null -Extension $null - GetFileList -Path $null -Extension $null + } | Should -Throw - } | Should -Throw + } - } + It "should return one file when checking folder with one matching files" { - It "should return one file when checking folder with one matching files" { + $fileContent = "function GetFileContent {}" + $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.ps1' + Set-Content -Path $testPath1 -Value $fileContent - $fileContent = "function GetFileContent {}" - $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.ps1' - Set-Content -Path $testPath1 -Value $fileContent + $fileList = GetFileList -Path $TestDrive -Extension ".ps1" - $fileList = GetFileList -Path $TestDrive -Extension ".ps1" + Remove-Item -Path $testPath1 -Force - Remove-Item -Path $testPath1 -Force + $fileList.Count | Should -BeExactly 1 - $fileList.Count | Should -BeExactly 1 + } - } + It "should return two files when checking folder with two matching files" { - It "should return two files when checking folder with two matching files" { + $fileContent = "function GetFileContent {}" + $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.ps1' + Set-Content -Path $testPath1 -Value $fileContent + $testPath2 = Join-Path -Path $TestDrive -ChildPath 'test2.ps1' + Set-Content -Path $testPath2 -Value $fileContent - $fileContent = "function GetFileContent {}" - $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.ps1' - Set-Content -Path $testPath1 -Value $fileContent - $testPath2 = Join-Path -Path $TestDrive -ChildPath 'test2.ps1' - Set-Content -Path $testPath2 -Value $fileContent + $fileList = GetFileList -Path $TestDrive -Extension ".ps1" - $fileList = GetFileList -Path $TestDrive -Extension ".ps1" + Remove-Item -Path $testPath1 -Force + Remove-Item -Path $testPath2 -Force - Remove-Item -Path $testPath1 -Force - Remove-Item -Path $testPath2 -Force + $fileList.Count | Should -BeExactly 2 - $fileList.Count | Should -BeExactly 2 + } - } + It "should return no files when checking folder with non-matching files" { - It "should return no files when checking folder with non-matching files" { + $fileContent = "function GetFileContent {}" + $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.psm1' + Set-Content -Path $testPath1 -Value $fileContent - $fileContent = "function GetFileContent {}" - $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.psm1' - Set-Content -Path $testPath1 -Value $fileContent + $fileList = GetFileList -Path $TestDrive -Extension ".ps1" - $fileList = GetFileList -Path $TestDrive -Extension ".ps1" + Remove-Item -Path $testPath1 -Force - Remove-Item -Path $testPath1 -Force + $fileList.Count | Should -BeExactly 0 - $fileList.Count | Should -BeExactly 0 + } - } + It "should return one file when checking folder with some matching files" { - It "should return one file when checking folder with some matching files" { + $fileContent = "function GetFileContent {}" + $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.psm1' + Set-Content -Path $testPath1 -Value $fileContent + $testPath2 = Join-Path -Path $TestDrive -ChildPath 'test2.ps1' + Set-Content -Path $testPath2 -Value $fileContent - $fileContent = "function GetFileContent {}" - $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.psm1' - Set-Content -Path $testPath1 -Value $fileContent - $testPath2 = Join-Path -Path $TestDrive -ChildPath 'test2.ps1' - Set-Content -Path $testPath2 -Value $fileContent + $fileList = GetFileList -Path $TestDrive -Extension ".ps1" - $fileList = GetFileList -Path $TestDrive -Extension ".ps1" + Remove-Item -Path $testPath1 -Force + Remove-Item -Path $testPath2 -Force - Remove-Item -Path $testPath1 -Force - Remove-Item -Path $testPath2 -Force + $fileList.Count | Should -BeExactly 1 - $fileList.Count | Should -BeExactly 1 + } - } + It "should return correct file when checking folder" { - It "should return correct file when checking folder" { + $fileContent = "function GetFileContent {}" + $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.psm1' + Set-Content -Path $testPath1 -Value $fileContent + $testPath2 = Join-Path -Path $TestDrive -ChildPath 'test2.ps1' + Set-Content -Path $testPath2 -Value $fileContent - $fileContent = "function GetFileContent {}" - $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.psm1' - Set-Content -Path $testPath1 -Value $fileContent - $testPath2 = Join-Path -Path $TestDrive -ChildPath 'test2.ps1' - Set-Content -Path $testPath2 -Value $fileContent + $fileList = GetFileList -Path $TestDrive -Extension ".ps1" - $fileList = GetFileList -Path $TestDrive -Extension ".ps1" + Remove-Item -Path $testPath1 -Force + Remove-Item -Path $testPath2 -Force - Remove-Item -Path $testPath1 -Force - Remove-Item -Path $testPath2 -Force + $fileList | Should -BeExactly $testPath2 - $fileList | Should -BeExactly $testPath2 + } - } + It "should return multiple correct files when checking folder" { - It "should return multiple correct files when checking folder" { + $fileContent = "function GetFileContent {}" + $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.ps1' + Set-Content -Path $testPath1 -Value $fileContent + $testPath2 = Join-Path -Path $TestDrive -ChildPath 'test2.ps1' + Set-Content -Path $testPath2 -Value $fileContent - $fileContent = "function GetFileContent {}" - $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test1.ps1' - Set-Content -Path $testPath1 -Value $fileContent - $testPath2 = Join-Path -Path $TestDrive -ChildPath 'test2.ps1' - Set-Content -Path $testPath2 -Value $fileContent + $fileList = GetFileList -Path $TestDrive -Extension ".ps1" - $fileList = GetFileList -Path $TestDrive -Extension ".ps1" + Remove-Item -Path $testPath1 -Force + Remove-Item -Path $testPath2 -Force - Remove-Item -Path $testPath1 -Force - Remove-Item -Path $testPath2 -Force + $fileList | Should -BeExactly @($testPath1, $testPath2) - $fileList | Should -BeExactly @($testPath1, $testPath2) + } - } + It "should not return Test files when checking folder" { - It "should not return Test files when checking folder" { + $fileContent = "function GetFileContent {}" + $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test.Tests.ps1' + Set-Content -Path $testPath1 -Value $fileContent - $fileContent = "function GetFileContent {}" - $testPath1 = Join-Path -Path $TestDrive -ChildPath 'test.Tests.ps1' - Set-Content -Path $testPath1 -Value $fileContent + $fileList = GetFileList -Path $TestDrive -Extension ".ps1" - $fileList = GetFileList -Path $TestDrive -Extension ".ps1" + Remove-Item -Path $testPath1 -Force - Remove-Item -Path $testPath1 -Force + $fileList.Count | Should -BeExactly 0 - $fileList.Count | Should -BeExactly 0 + } } diff --git a/Tests/Unit/PSQualityCheck/GetFunctionCount.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetFunctionCount.Tests.ps1 index e70cacf..71d9b0a 100644 --- a/Tests/Unit/PSQualityCheck/GetFunctionCount.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetFunctionCount.Tests.ps1 @@ -1,141 +1,146 @@ -Describe "GetFunctionCount.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -Foreach @( - @{ 'Name' = 'ModulePath'; 'Type' = 'String' } - @{ 'Name' = 'ManifestPath'; 'Type' = 'String' } - ) { - BeforeAll { - $commandletUnderTest = "GetFunctionCount" - } + Describe "GetFunctionCount.Tests" { - It "should have $Name as a mandatory parameter" { + Context "Parameter Tests" -ForEach @( + @{ 'Name' = 'ModulePath'; 'Type' = 'String' } + @{ 'Name' = 'ManifestPath'; 'Type' = 'String' } + ) { - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + BeforeAll { + $commandletUnderTest = "GetFunctionCount" + } - } + It "should have $Name as a mandatory parameter" { - It "should $Name not belong to a parameter set" { + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + } - } + It "should $Name not belong to a parameter set" { - It "should $Name type be $Type" { + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + } - } + It "should $Name type be $Type" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - # TODO Broken Test, requires GetParsedFile and GetParsedContent mocking out + } - Context "Function tests" { + } - BeforeAll { + # TODO Broken Test, requires GetParsedFile and GetParsedContent mocking out - $ModulePath = Join-Path -Path $TestDrive -ChildPath 'test1.psm1' - $ManifestPath = Join-Path -Path $TestDrive -ChildPath 'test1.psd1' + Context "Function tests" { - } + BeforeAll { - It "should throw when passing null parameters" { + $ModulePath = Join-Path -Path $TestDrive -ChildPath 'test1.psm1' + $ManifestPath = Join-Path -Path $TestDrive -ChildPath 'test1.psd1' - { + } - GetFunctionCount -Module $null -Manifest $null + It "should throw when passing null parameters" { - } | Should -Throw + { - } + GetFunctionCount -Module $null -Manifest $null - It "should find one function with matching module and manifest" { + } | Should -Throw - $fileContent = "function GetFileContent { + } + + It "should find one function with matching module and manifest" { + + $fileContent = "function GetFileContent { Write-Host }" - Set-Content -Path $ModulePath -Value $fileContent + Set-Content -Path $ModulePath -Value $fileContent - New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent') + New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent') - GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(1, 1, 1, 1) + GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(1, 1, 1, 1) - Remove-Item -Path $ModulePath -Force - Remove-Item -Path $ManifestPath -Force + Remove-Item -Path $ModulePath -Force + Remove-Item -Path $ManifestPath -Force - } + } - It "should find two functions in module with matching manifest and module" { + It "should find two functions in module with matching manifest and module" { - $fileContent = "function GetFileContent {} + $fileContent = "function GetFileContent {} function GetFileContent2 {}" - Set-Content -Path $ModulePath -Value $fileContent + Set-Content -Path $ModulePath -Value $fileContent - New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent', 'GetFileContent2') + New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent', 'GetFileContent2') - GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(2, 2, 2, 2) + GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(2, 2, 2, 2) - Remove-Item -Path $ModulePath -Force - Remove-Item -Path $ManifestPath -Force + Remove-Item -Path $ModulePath -Force + Remove-Item -Path $ManifestPath -Force - } + } - It "should not find any function in manifest or module with empty manifest" { + It "should not find any function in manifest or module with empty manifest" { - $fileContent = "function GetFileContent {}" - Set-Content -Path $ModulePath -Value $fileContent + $fileContent = "function GetFileContent {}" + Set-Content -Path $ModulePath -Value $fileContent - New-ModuleManifest -Path $ManifestPath + New-ModuleManifest -Path $ManifestPath - GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(0, 0, 0, 0) + GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(0, 0, 0, 0) - Remove-Item -Path $ModulePath -Force - Remove-Item -Path $ManifestPath -Force + Remove-Item -Path $ModulePath -Force + Remove-Item -Path $ManifestPath -Force - } + } - It "should not find function in manifest and module with mismatched functions between manifest and module" { + It "should not find function in manifest and module with mismatched functions between manifest and module" { - $fileContent = "function GetFileContent {}" - Set-Content -Path $ModulePath -Value $fileContent + $fileContent = "function GetFileContent {}" + Set-Content -Path $ModulePath -Value $fileContent - New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent2') + New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent2') - GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(1, 0, 1, 0) + GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(1, 0, 1, 0) - Remove-Item -Path $ModulePath -Force - Remove-Item -Path $ManifestPath -Force + Remove-Item -Path $ModulePath -Force + Remove-Item -Path $ManifestPath -Force - } + } - It "should not find function in module with function in manifest and not in module" { + It "should not find function in module with function in manifest and not in module" { - $fileContent = "function GetFileContent {}" - Set-Content -Path $ModulePath -Value $fileContent + $fileContent = "function GetFileContent {}" + Set-Content -Path $ModulePath -Value $fileContent - New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent', 'GetFileContent2') + New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent', 'GetFileContent2') - GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(2, 1, 1, 1) + GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(2, 1, 1, 1) - Remove-Item -Path $ModulePath -Force - Remove-Item -Path $ManifestPath -Force + Remove-Item -Path $ModulePath -Force + Remove-Item -Path $ManifestPath -Force - } + } - It "should not find function in module with function in module and not in manifest" { + It "should not find function in module with function in module and not in manifest" { - $fileContent = "function GetFileContent {} + $fileContent = "function GetFileContent {} function GetFileContent2 {}" - Set-Content -Path $ModulePath -Value $fileContent + Set-Content -Path $ModulePath -Value $fileContent + + New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent') - New-ModuleManifest -Path $ManifestPath -FunctionsToExport @('GetFileContent') + GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(1, 1, 2, 1) - GetFunctionCount -Module $ModulePath -Manifest $ManifestPath | Should -BeExactly @(1, 1, 2, 1) + Remove-Item -Path $ModulePath -Force + Remove-Item -Path $ManifestPath -Force - Remove-Item -Path $ModulePath -Force - Remove-Item -Path $ManifestPath -Force + } } diff --git a/Tests/Unit/PSQualityCheck/GetParsedContent.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetParsedContent.Tests.ps1 index 0c7e17a..d5acf0c 100644 --- a/Tests/Unit/PSQualityCheck/GetParsedContent.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetParsedContent.Tests.ps1 @@ -1,145 +1,149 @@ -Describe "GetParsedContent.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -ForEach @( - @{ 'Name' = 'Content'; 'Type' = 'String' } - ) { + Describe "GetParsedContent.Tests" { - BeforeAll { - $commandletUnderTest = "GetParsedContent" - } + Context "Parameter Tests" -Foreach @( + @{ 'Name' = 'Content'; 'Type' = 'Object[]' } + ) { - It "should have $Name as a mandatory parameter" { + BeforeAll { + $commandletUnderTest = "GetParsedContent" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + It "should have $Name as a mandatory parameter" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - It "should $Name not belong to a parameter set" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + It "should $Name not belong to a parameter set" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - It "should $Name type be $Type" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + It "should $Name type be $Type" { + + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + + } } - } + Context "Function tests" { + + BeforeAll { + + $parsedFileContent = @( + @{ + "Content" = "function" + "Type" = "Keyword" + "Start" = 0 + "Length" = 8 + "StartLine" = 1 + "StartColumn" = 1 + "EndLine" = 1 + "EndColumn" = 9 + }, + @{ + "Content" = "GetFileContent" + "Type" = "CommandArgument" + "Start" = 9 + "Length" = 15 + "StartLine" = 1 + "StartColumn" = 10 + "EndLine" = 1 + "EndColumn" = 25 + }, + @{ + "Content" = "{" + "Type" = "GroupStart" + "Start" = 25 + "Length" = 1 + "StartLine" = 1 + "StartColumn" = 26 + "EndLine" = 1 + "EndColumn" = 27 + }, + @{ + "Content" = "}" + "Type" = "GroupEnd" + "Start" = 26 + "Length" = 1 + "StartLine" = 1 + "StartColumn" = 27 + "EndLine" = 1 + "EndColumn" = 28 + } + ) - Context "Function tests" { - - BeforeAll { - - $parsedFileContent = @( - @{ - "Content" = "function" - "Type" = "Keyword" - "Start" = 0 - "Length" = 8 - "StartLine" = 1 - "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 9 - }, - @{ - "Content" = "GetFileContent" - "Type" = "CommandArgument" - "Start" = 9 - "Length" = 15 - "StartLine" = 1 - "StartColumn" = 10 - "EndLine" = 1 - "EndColumn" = 25 - }, - @{ - "Content" = "{" - "Type" = "GroupStart" - "Start" = 25 - "Length" = 1 - "StartLine" = 1 - "StartColumn" = 26 - "EndLine" = 1 - "EndColumn" = 27 - }, - @{ - "Content" = "}" - "Type" = "GroupEnd" - "Start" = 26 - "Length" = 1 - "StartLine" = 1 - "StartColumn" = 27 - "EndLine" = 1 - "EndColumn" = 28 - } - ) + } - } + It "should throw when passing null parameters" { - It "should throw when passing null parameters" { + { - { + GetParsedContent -Content $null - GetParsedContent -Content $null + } | Should -Throw - } | Should -Throw + } + It "should return correct parse tokens for content" { - } - It "should return correct parse tokens for content" { + $fileContent = "function GetFileContent {}" + + ($parsedModule, $parserErrorCount) = GetParsedContent -Content $fileContent - $fileContent = "function GetFileContent {}" + for ($x = 0; $x -lt $parsedModule.Count; $x++) { - ($parsedModule, $parserErrorCount) = GetParsedContent -Content $fileContent + ( + ($parsedModule[$x].StartLine -eq $parsedFileContent[$x].StartLine) -and + ($parsedModule[$x].Content -eq $parsedFileContent[$x].Content) -and + ($parsedModule[$x].Type -eq $parsedFileContent[$x].Type) -and + ($parsedModule[$x].Start -eq $parsedFileContent[$x].Start) -and + ($parsedModule[$x].Length -eq $parsedFileContent[$x].Length) -and + ($parsedModule[$x].StartColumn -eq $parsedFileContent[$x].StartColumn) -and + ($parsedModule[$x].EndLine -eq $parsedFileContent[$x].EndLine) -and + ($parsedModule[$x].EndColumn -eq $parsedFileContent[$x].EndColumn) + ) | Should -BeTrue - for ($x = 0; $x -lt $parsedModule.Count; $x++) { + } - ( - ($parsedModule[$x].StartLine -eq $parsedFileContent[$x].StartLine) -and - ($parsedModule[$x].Content -eq $parsedFileContent[$x].Content) -and - ($parsedModule[$x].Type -eq $parsedFileContent[$x].Type) -and - ($parsedModule[$x].Start -eq $parsedFileContent[$x].Start) -and - ($parsedModule[$x].Length -eq $parsedFileContent[$x].Length) -and - ($parsedModule[$x].StartColumn -eq $parsedFileContent[$x].StartColumn) -and - ($parsedModule[$x].EndLine -eq $parsedFileContent[$x].EndLine) -and - ($parsedModule[$x].EndColumn -eq $parsedFileContent[$x].EndColumn) - ) | Should -BeTrue + $parserErrorCount | Should -BeExactly 0 } - $parserErrorCount | Should -BeExactly 0 - - } + It "should not return matching parse tokens for mismatching content" { - It "should not return matching parse tokens for mismatching content" { + $fileContent = "function Get-Content {}" - $fileContent = "function Get-Content {}" + ($parsedModule, $parserErrorCount) = GetParsedContent -Content $fileContent - ($parsedModule, $parserErrorCount) = GetParsedContent -Content $fileContent + $flag = $true - $flag = $true + for ($x = 0; $x -lt $parsedModule.Count; $x++) { - for ($x = 0; $x -lt $parsedModule.Count; $x++) { + if ( + ($parsedModule[$x].StartLine -ne $parsedFileContent[$x].StartLine) -or + ($parsedModule[$x].Content -ne $parsedFileContent[$x].Content) -or + ($parsedModule[$x].Type -ne $parsedFileContent[$x].Type) -or + ($parsedModule[$x].Start -ne $parsedFileContent[$x].Start) -or + ($parsedModule[$x].Length -ne $parsedFileContent[$x].Length) -or + ($parsedModule[$x].StartColumn -ne $parsedFileContent[$x].StartColumn) -or + ($parsedModule[$x].EndLine -ne $parsedFileContent[$x].EndLine) -or + ($parsedModule[$x].EndColumn -ne $parsedFileContent[$x].EndColumn) + ) { + $flag = $false + } - if ( - ($parsedModule[$x].StartLine -ne $parsedFileContent[$x].StartLine) -or - ($parsedModule[$x].Content -ne $parsedFileContent[$x].Content) -or - ($parsedModule[$x].Type -ne $parsedFileContent[$x].Type) -or - ($parsedModule[$x].Start -ne $parsedFileContent[$x].Start) -or - ($parsedModule[$x].Length -ne $parsedFileContent[$x].Length) -or - ($parsedModule[$x].StartColumn -ne $parsedFileContent[$x].StartColumn) -or - ($parsedModule[$x].EndLine -ne $parsedFileContent[$x].EndLine) -or - ($parsedModule[$x].EndColumn -ne $parsedFileContent[$x].EndColumn) - ) { - $flag = $false } - } + $flag | Should -BeFalse - $flag | Should -BeFalse + $parserErrorCount | Should -BeExactly 0 - $parserErrorCount | Should -BeExactly 0 + } } diff --git a/Tests/Unit/PSQualityCheck/GetParsedFile.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetParsedFile.Tests.ps1 index 04c8827..aef15bd 100644 --- a/Tests/Unit/PSQualityCheck/GetParsedFile.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetParsedFile.Tests.ps1 @@ -1,167 +1,171 @@ -Describe "GetParsedFile.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -ForEach @( - @{ 'Name' = 'Path'; 'Type' = 'String' } - ) { + Describe "GetParsedFile.Tests" { - BeforeAll { - $commandletUnderTest = "GetParsedFile" - } + Context "Parameter Tests" -Foreach @( + @{ 'Name' = 'Path'; 'Type' = 'String' } + ) { - It "should have $Name as a mandatory parameter" { + BeforeAll { + $commandletUnderTest = "GetParsedFile" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + It "should have $Name as a mandatory parameter" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - It "should $Name not belong to a parameter set" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + It "should $Name not belong to a parameter set" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - It "should $Name type be $Type" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + It "should $Name type be $Type" { + + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + + } } - } + Context "Function tests" { + + BeforeAll { + + $parsedFileContent = @( + @{ + "Content" = "function" + "Type" = "Keyword" + "Start" = 0 + "Length" = 8 + "StartLine" = 1 + "StartColumn" = 1 + "EndLine" = 1 + "EndColumn" = 9 + }, + @{ + "Content" = "GetFileContent" + "Type" = "CommandArgument" + "Start" = 9 + "Length" = 15 + "StartLine" = 1 + "StartColumn" = 10 + "EndLine" = 1 + "EndColumn" = 25 + }, + @{ + "Content" = "{" + "Type" = "GroupStart" + "Start" = 25 + "Length" = 1 + "StartLine" = 1 + "StartColumn" = 26 + "EndLine" = 1 + "EndColumn" = 27 + }, + @{ + "Content" = "}" + "Type" = "GroupEnd" + "Start" = 26 + "Length" = 1 + "StartLine" = 1 + "StartColumn" = 27 + "EndLine" = 1 + "EndColumn" = 28 + } + @{ + "Content" = "`r`n" + "Type" = "NewLine" + "Start" = 27 + "Length" = 2 + "StartLine" = 1 + "StartColumn" = 28 + "EndLine" = 2 + "EndColumn" = 1 + } + ) - Context "Function tests" { - - BeforeAll { - - $parsedFileContent = @( - @{ - "Content" = "function" - "Type" = "Keyword" - "Start" = 0 - "Length" = 8 - "StartLine" = 1 - "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 9 - }, - @{ - "Content" = "GetFileContent" - "Type" = "CommandArgument" - "Start" = 9 - "Length" = 15 - "StartLine" = 1 - "StartColumn" = 10 - "EndLine" = 1 - "EndColumn" = 25 - }, - @{ - "Content" = "{" - "Type" = "GroupStart" - "Start" = 25 - "Length" = 1 - "StartLine" = 1 - "StartColumn" = 26 - "EndLine" = 1 - "EndColumn" = 27 - }, - @{ - "Content" = "}" - "Type" = "GroupEnd" - "Start" = 26 - "Length" = 1 - "StartLine" = 1 - "StartColumn" = 27 - "EndLine" = 1 - "EndColumn" = 28 - } - @{ - "Content" = "`r`n" - "Type" = "NewLine" - "Start" = 27 - "Length" = 2 - "StartLine" = 1 - "StartColumn" = 28 - "EndLine" = 2 - "EndColumn" = 1 - } - ) + } - } + It "should throw when passing null parameters" { - It "should throw when passing null parameters" { + { - { + GetParsedFile -Path $null - GetParsedFile -Path $null + } | Should -Throw - } | Should -Throw + } - } + It "should return correct parse tokens for content" { - It "should return correct parse tokens for content" { + $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' + $fileContent = "function GetFileContent {}" - $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent = "function GetFileContent {}" + Set-Content -Path $testPath -Value $fileContent - Set-Content -Path $testPath -Value $fileContent + ($parsedModule, $parserErrorCount) = GetParsedFile -Path $testPath - ($parsedModule, $parserErrorCount) = GetParsedFile -Path $testPath + for ($x = 0; $x -lt $parsedModule.Count; $x++) { - for ($x = 0; $x -lt $parsedModule.Count; $x++) { + ( + ($parsedModule[$x].StartLine -eq $parsedFileContent[$x].StartLine) -and + ($parsedModule[$x].Content -eq $parsedFileContent[$x].Content) -and + ($parsedModule[$x].Type -eq $parsedFileContent[$x].Type) -and + ($parsedModule[$x].Start -eq $parsedFileContent[$x].Start) -and + ($parsedModule[$x].Length -eq $parsedFileContent[$x].Length) -and + ($parsedModule[$x].StartColumn -eq $parsedFileContent[$x].StartColumn) -and + ($parsedModule[$x].EndLine -eq $parsedFileContent[$x].EndLine) -and + ($parsedModule[$x].EndColumn -eq $parsedFileContent[$x].EndColumn) + ) | Should -BeTrue - ( - ($parsedModule[$x].StartLine -eq $parsedFileContent[$x].StartLine) -and - ($parsedModule[$x].Content -eq $parsedFileContent[$x].Content) -and - ($parsedModule[$x].Type -eq $parsedFileContent[$x].Type) -and - ($parsedModule[$x].Start -eq $parsedFileContent[$x].Start) -and - ($parsedModule[$x].Length -eq $parsedFileContent[$x].Length) -and - ($parsedModule[$x].StartColumn -eq $parsedFileContent[$x].StartColumn) -and - ($parsedModule[$x].EndLine -eq $parsedFileContent[$x].EndLine) -and - ($parsedModule[$x].EndColumn -eq $parsedFileContent[$x].EndColumn) - ) | Should -BeTrue + } - } + Remove-Item -Path $testPath -Force - Remove-Item -Path $testPath -Force + $parserErrorCount | Should -BeExactly 0 - $parserErrorCount | Should -BeExactly 0 + } - } + It "should not return matching parse tokens for mismatching content" { - It "should not return matching parse tokens for mismatching content" { + $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' + $fileContent = "function Get-Content {}" - $testPath = Join-Path -Path $TestDrive -ChildPath 'test.ps1' - $fileContent = "function Get-Content {}" + Set-Content -Path $testPath -Value $fileContent - Set-Content -Path $testPath -Value $fileContent + ($parsedModule, $parserErrorCount) = GetParsedFile -Path $testPath - ($parsedModule, $parserErrorCount) = GetParsedFile -Path $testPath + $flag = $true - $flag = $true + for ($x = 0; $x -lt $parsedModule.Count; $x++) { - for ($x = 0; $x -lt $parsedModule.Count; $x++) { + if ( + ($parsedModule[$x].StartLine -ne $parsedFileContent[$x].StartLine) -or + ($parsedModule[$x].Content -ne $parsedFileContent[$x].Content) -or + ($parsedModule[$x].Type -ne $parsedFileContent[$x].Type) -or + ($parsedModule[$x].Start -ne $parsedFileContent[$x].Start) -or + ($parsedModule[$x].Length -ne $parsedFileContent[$x].Length) -or + ($parsedModule[$x].StartColumn -ne $parsedFileContent[$x].StartColumn) -or + ($parsedModule[$x].EndLine -ne $parsedFileContent[$x].EndLine) -or + ($parsedModule[$x].EndColumn -ne $parsedFileContent[$x].EndColumn) + ) { + $flag = $false + } - if ( - ($parsedModule[$x].StartLine -ne $parsedFileContent[$x].StartLine) -or - ($parsedModule[$x].Content -ne $parsedFileContent[$x].Content) -or - ($parsedModule[$x].Type -ne $parsedFileContent[$x].Type) -or - ($parsedModule[$x].Start -ne $parsedFileContent[$x].Start) -or - ($parsedModule[$x].Length -ne $parsedFileContent[$x].Length) -or - ($parsedModule[$x].StartColumn -ne $parsedFileContent[$x].StartColumn) -or - ($parsedModule[$x].EndLine -ne $parsedFileContent[$x].EndLine) -or - ($parsedModule[$x].EndColumn -ne $parsedFileContent[$x].EndColumn) - ) { - $flag = $false } - } + Remove-Item -Path $testPath -Force - Remove-Item -Path $testPath -Force + $flag | Should -BeFalse - $flag | Should -BeFalse + $parserErrorCount | Should -BeExactly 0 - $parserErrorCount | Should -BeExactly 0 + } } diff --git a/Tests/Unit/PSQualityCheck/GetScriptParameter.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetScriptParameter.Tests.ps1 index 500579f..89d3fa9 100644 --- a/Tests/Unit/PSQualityCheck/GetScriptParameter.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetScriptParameter.Tests.ps1 @@ -1,115 +1,120 @@ -Describe "GetScriptParameter.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -ForEach @( - @{ 'Name' = 'Content'; 'Type' = 'String' } - ) { + Describe "GetScriptParameter.Tests" { - BeforeAll { - $commandletUnderTest = "GetScriptParameter" - } + Context "Parameter Tests" -Foreach @( + @{ 'Name' = 'Content'; 'Type' = 'String[]' } + ) { - It "should have $Name as a mandatory parameter" { + BeforeAll { + $commandletUnderTest = "GetScriptParameter" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + It "should have $Name as a mandatory parameter" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - It "should $Name not belong to a parameter set" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + It "should $Name not belong to a parameter set" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - It "should $Name type be $Type" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + It "should $Name type be $Type" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - } + } - Context "Function tests" { + } - It "should throw when passing null parameters" { + Context "Function tests" { - { + It "should throw when passing null parameters" { - GetScriptParameter -Content $null + { - } | Should -Throw + GetScriptParameter -Content $null - } + } | Should -Throw - It "should throw when passed no parameters" { + } - { - $fileContent = "function GetFileContent { }" + It "should throw when passed no parameters" { - $parameterVariables = GetScriptParameter -Content $fileContent + { + $fileContent = "function GetFileContent { }" - $parameterVariables | Should -BeNullOrEmpty + $parameterVariables = GetScriptParameter -Content $fileContent - } | Should -Throw + $parameterVariables | Should -BeNullOrEmpty - } + } | Should -Throw - It "should find one parameter without type" { + } - $fileContent = 'param ( $parameterOne )' + It "should find one parameter without type" { - $parameterVariables = GetScriptParameter -Content $fileContent + $fileContent = 'param ( $parameterOne )' - $parameterVariables.ContainsKey('parameterOne') | Should -BeTrue - $parameterVariables.('parameterOne') | Should -BeNullOrEmpty + $parameterVariables = GetScriptParameter -Content $fileContent - } + $parameterVariables.ContainsKey('parameterOne') | Should -BeTrue + $parameterVariables.('parameterOne') | Should -BeNullOrEmpty - It "should find one parameter with type" { + } - $fileContent = 'param ( [int]$parameterOne )' + It "should find one parameter with type" { - $parameterVariables = GetScriptParameter -Content $fileContent + $fileContent = 'param ( [int]$parameterOne )' - $parameterVariables.ContainsKey('parameterOne') | Should -BeTrue - $parameterVariables.('parameterOne') | Should -BeExactly '[int]' + $parameterVariables = GetScriptParameter -Content $fileContent - } + $parameterVariables.ContainsKey('parameterOne') | Should -BeTrue + $parameterVariables.('parameterOne') | Should -BeExactly '[int]' - It "should find two parameters with type" { + } - $fileContent = 'param ( + It "should find two parameters with type" { + + $fileContent = 'param ( [int]$parameterOne, [string]$parameterTwo )' - $parameterVariables = GetScriptParameter -Content $fileContent + $parameterVariables = GetScriptParameter -Content $fileContent - $parameterVariables.ContainsKey('parameterOne') | Should -BeTrue - $parameterVariables.('parameterOne') | Should -BeExactly '[int]' + $parameterVariables.ContainsKey('parameterOne') | Should -BeTrue + $parameterVariables.('parameterOne') | Should -BeExactly '[int]' - $parameterVariables.ContainsKey('parameterTwo') | Should -BeTrue - $parameterVariables.('parameterTwo') | Should -BeExactly '[string]' + $parameterVariables.ContainsKey('parameterTwo') | Should -BeTrue + $parameterVariables.('parameterTwo') | Should -BeExactly '[string]' - } + } - It "should find two parameters one with type and one without" { + It "should find two parameters one with type and one without" { - $fileContent = 'param ( + $fileContent = 'param ( [int]$parameterOne, $parameterTwo )' - $parameterVariables = GetScriptParameter -Content $fileContent + $parameterVariables = GetScriptParameter -Content $fileContent + + $parameterVariables.ContainsKey('parameterOne') | Should -BeTrue + $parameterVariables.('parameterOne') | Should -BeExactly '[int]' - $parameterVariables.ContainsKey('parameterOne') | Should -BeTrue - $parameterVariables.('parameterOne') | Should -BeExactly '[int]' + $parameterVariables.ContainsKey('parameterTwo') | Should -BeTrue + $parameterVariables.('parameterTwo') | Should -BeNullOrEmpty - $parameterVariables.ContainsKey('parameterTwo') | Should -BeTrue - $parameterVariables.('parameterTwo') | Should -BeNullOrEmpty + } } } } + diff --git a/Tests/Unit/PSQualityCheck/GetTagList.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetTagList.Tests.ps1 index 8a4b027..2842994 100644 --- a/Tests/Unit/PSQualityCheck/GetTagList.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetTagList.Tests.ps1 @@ -1,6 +1,10 @@ -Describe "Get-TagList.Tests" { +InModuleScope PSQualityCheck { - Context "Function tests" { + Describe "Get-TagList.Tests" { + + Context "Function tests" { + + } } diff --git a/Tests/Unit/PSQualityCheck/GetToken.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetToken.Tests.ps1 index 9aa6982..645119f 100644 --- a/Tests/Unit/PSQualityCheck/GetToken.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetToken.Tests.ps1 @@ -1,121 +1,125 @@ -Describe "GetToken.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -Foreach @( - @{ 'Name' = 'ParsedContent'; 'Type' = 'Object[]' } - @{ 'Name' = 'Type'; 'Type' = 'String' } - @{ 'Name' = 'Content'; 'Type' = 'String' } - ) { + Describe "GetToken.Tests" { - BeforeAll { - $commandletUnderTest = "GetToken" - } + Context "Parameter Tests" -ForEach @( + @{ 'Name' = 'ParsedContent'; 'Type' = 'Object[]' } + @{ 'Name' = 'Type'; 'Type' = 'String' } + @{ 'Name' = 'Content'; 'Type' = 'String' } + ) { - It "should have $Name as a mandatory parameter" { + BeforeAll { + $commandletUnderTest = "GetToken" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + It "should have $Name as a mandatory parameter" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - It "should $Name not belong to a parameter set" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + It "should $Name not belong to a parameter set" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - It "should $Name type be $Type" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + It "should $Name type be $Type" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - } + } - # TODO Broken Test, requires GetTokenMarker and GetTokenComponent mocking out - - Context "Function tests" { - - BeforeAll { - $ParsedContent = @( - @{ - "Content" = "function" - "Type" = "Keyword" - "Start" = 0 - "Length" = 8 - "StartLine" = 1 - "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 9 - }, - @{ - "Content" = "GetFileContent" - "Type" = "CommandArgument" - "Start" = 9 - "Length" = 15 - "StartLine" = 1 - "StartColumn" = 10 - "EndLine" = 1 - "EndColumn" = 25 - }, - @{ - "Content" = "{" - "Type" = "GroupStart" - "Start" = 25 - "Length" = 1 - "StartLine" = 1 - "StartColumn" = 26 - "EndLine" = 1 - "EndColumn" = 27 - }, - @{ - "Content" = "}" - "Type" = "GroupEnd" - "Start" = 26 - "Length" = 1 - "StartLine" = 1 - "StartColumn" = 27 - "EndLine" = 1 - "EndColumn" = 28 - } - ) } - It "should throw when passing null parameters" { + # TODO Broken Test, requires GetTokenMarker and GetTokenComponent mocking out + + Context "Function tests" { + + BeforeAll { + $ParsedContent = @( + @{ + "Content" = "function" + "Type" = "Keyword" + "Start" = 0 + "Length" = 8 + "StartLine" = 1 + "StartColumn" = 1 + "EndLine" = 1 + "EndColumn" = 9 + }, + @{ + "Content" = "GetFileContent" + "Type" = "CommandArgument" + "Start" = 9 + "Length" = 15 + "StartLine" = 1 + "StartColumn" = 10 + "EndLine" = 1 + "EndColumn" = 25 + }, + @{ + "Content" = "{" + "Type" = "GroupStart" + "Start" = 25 + "Length" = 1 + "StartLine" = 1 + "StartColumn" = 26 + "EndLine" = 1 + "EndColumn" = 27 + }, + @{ + "Content" = "}" + "Type" = "GroupEnd" + "Start" = 26 + "Length" = 1 + "StartLine" = 1 + "StartColumn" = 27 + "EndLine" = 1 + "EndColumn" = 28 + } + ) + } - { + It "should throw when passing null parameters" { - GetToken -ParsedContent $null -Type $null -Content $null + { - } | Should -Throw + GetToken -ParsedContent $null -Type $null -Content $null - } + } | Should -Throw + + } - It "should find token where parameters are valid" { + It "should find token where parameters are valid" { - $token = GetToken -ParsedContent $ParsedContent -Type "Keyword" -Content "Function" + $token = GetToken -ParsedContent $ParsedContent -Type "Keyword" -Content "Function" - for ($x = 0; $x -lt $parsedModule.Count; $x++) { + for ($x = 0; $x -lt $parsedModule.Count; $x++) { - ( - ($token[$x].StartLine -eq $ParsedContent[$x].StartLine) -and - ($token[$x].Content -eq $ParsedContent[$x].Content) -and - ($token[$x].Type -eq $ParsedContent[$x].Type) -and - ($token[$x].Start -eq $ParsedContent[$x].Start) -and - ($token[$x].Length -eq $ParsedContent[$x].Length) -and - ($token[$x].StartColumn -eq $ParsedContent[$x].StartColumn) -and - ($token[$x].EndLine -eq $ParsedContent[$x].EndLine) -and - ($token[$x].EndColumn -eq $ParsedContent[$x].EndColumn) - ) | Should -BeTrue + ( + ($token[$x].StartLine -eq $ParsedContent[$x].StartLine) -and + ($token[$x].Content -eq $ParsedContent[$x].Content) -and + ($token[$x].Type -eq $ParsedContent[$x].Type) -and + ($token[$x].Start -eq $ParsedContent[$x].Start) -and + ($token[$x].Length -eq $ParsedContent[$x].Length) -and + ($token[$x].StartColumn -eq $ParsedContent[$x].StartColumn) -and + ($token[$x].EndLine -eq $ParsedContent[$x].EndLine) -and + ($token[$x].EndColumn -eq $ParsedContent[$x].EndColumn) + ) | Should -BeTrue + + } } - } + It "should not find token where parameters are invalid" { - It "should not find token where parameters are invalid" { + $token = (GetToken -ParsedContent $ParsedContent -Type "Unknown" -Content "Data") - $token = (GetToken -ParsedContent $ParsedContent -Type "Unknown" -Content "Data") + $token | Should -BeNullOrEmpty - $token | Should -BeNullOrEmpty + } } diff --git a/Tests/Unit/PSQualityCheck/GetTokenComponent.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetTokenComponent.Tests.ps1 index 8a6ee88..cc5e902 100644 --- a/Tests/Unit/PSQualityCheck/GetTokenComponent.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetTokenComponent.Tests.ps1 @@ -1,107 +1,111 @@ -Describe "GetTokenComponent.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -Foreach @( - @{ 'Name' = 'ParsedContent'; 'Type' = 'Object[]' } - @{ 'Name' = 'StartLine'; 'Type' = 'Int32' } - ) { + Describe "GetTokenComponent.Tests" { - BeforeAll { - $commandletUnderTest = "GetTokenComponent" - } - - It "should have $Name as a mandatory parameter" { - - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - - } - - It "should $Name not belong to a parameter set" { - - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - - } + Context "Parameter Tests" -ForEach @( + @{ 'Name' = 'ParsedContent'; 'Type' = 'Object[]' } + @{ 'Name' = 'StartLine'; 'Type' = 'Int32' } + ) { - It "should $Name type be $Type" { + BeforeAll { + $commandletUnderTest = "GetTokenComponent" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + It "should have $Name as a mandatory parameter" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - } + } - Context "Function tests" { - - BeforeAll { - $ParsedContent = @( - @{ - "Content" = "function" - "Type" = "Keyword" - "Start" = 0 - "Length" = 8 - "StartLine" = 1 - "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 9 - }, - @{ - "Content" = "GetFileContent" - "Type" = "CommandArgument" - "Start" = 9 - "Length" = 15 - "StartLine" = 1 - "StartColumn" = 10 - "EndLine" = 1 - "EndColumn" = 25 - }, - @{ - "Content" = "{" - "Type" = "GroupStart" - "Start" = 25 - "Length" = 1 - "StartLine" = 1 - "StartColumn" = 26 - "EndLine" = 1 - "EndColumn" = 27 - }, - @{ - "Content" = "}" - "Type" = "GroupEnd" - "Start" = 26 - "Length" = 1 - "StartLine" = 1 - "StartColumn" = 27 - "EndLine" = 1 - "EndColumn" = 28 - } - ) - } + It "should $Name not belong to a parameter set" { - It "should throw when passing null parameters" { + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - { + } - GetTokenComponent -ParsedContent $null -StartLine $null + It "should $Name type be $Type" { - } | Should -Throw - - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - It "should find token where 'StartLine' is valid" { - - $token = GetTokenComponent -ParsedContent $ParsedContent -StartLine 1 - - Compare-Object -ReferenceObject $token.Values -DifferenceObject $ParsedContent.values | Should -BeNullOrEmpty + } } - It "should not find token where 'StartLine' is invalid" { - - $token = GetTokenComponent -ParsedContent $ParsedContent -StartLine 3 - $token | Should -BeNullOrEmpty - - $token = GetTokenComponent -ParsedContent $ParsedContent -StartLine $null - $token | Should -BeNullOrEmpty + Context "Function tests" { + + BeforeAll { + $ParsedContent = @( + @{ + "Content" = "function" + "Type" = "Keyword" + "Start" = 0 + "Length" = 8 + "StartLine" = 1 + "StartColumn" = 1 + "EndLine" = 1 + "EndColumn" = 9 + }, + @{ + "Content" = "GetFileContent" + "Type" = "CommandArgument" + "Start" = 9 + "Length" = 15 + "StartLine" = 1 + "StartColumn" = 10 + "EndLine" = 1 + "EndColumn" = 25 + }, + @{ + "Content" = "{" + "Type" = "GroupStart" + "Start" = 25 + "Length" = 1 + "StartLine" = 1 + "StartColumn" = 26 + "EndLine" = 1 + "EndColumn" = 27 + }, + @{ + "Content" = "}" + "Type" = "GroupEnd" + "Start" = 26 + "Length" = 1 + "StartLine" = 1 + "StartColumn" = 27 + "EndLine" = 1 + "EndColumn" = 28 + } + ) + } + + It "should throw when passing null parameters" { + + { + + GetTokenComponent -ParsedContent $null -StartLine $null + + } | Should -Throw + + } + + It "should find token where 'StartLine' is valid" { + + $token = GetTokenComponent -ParsedContent $ParsedContent -StartLine 1 + + Compare-Object -ReferenceObject $token.Values -DifferenceObject $ParsedContent.values | Should -BeNullOrEmpty + + } + + It "should not find token where 'StartLine' is invalid" { + + $token = GetTokenComponent -ParsedContent $ParsedContent -StartLine 3 + $token | Should -BeNullOrEmpty + + $token = GetTokenComponent -ParsedContent $ParsedContent -StartLine $null + $token | Should -BeNullOrEmpty + + } } diff --git a/Tests/Unit/PSQualityCheck/GetTokenMarker.Tests.ps1 b/Tests/Unit/PSQualityCheck/GetTokenMarker.Tests.ps1 index 8aa999f..c050509 100644 --- a/Tests/Unit/PSQualityCheck/GetTokenMarker.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/GetTokenMarker.Tests.ps1 @@ -1,51 +1,85 @@ -Describe "GetTokenMarker.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -Foreach @( - @{ 'Name' = 'ParsedContent'; 'Type' = 'Object[]' } - @{ 'Name' = 'Type'; 'Type' = 'String' } - @{ 'Name' = 'Content'; 'Type' = 'String' } - ) { + Describe "GetTokenMarker.Tests" { - BeforeAll { - $commandletUnderTest = "GetTokenMarker" - } + Context "Parameter Tests" -ForEach @( + @{ 'Name' = 'ParsedContent'; 'Type' = 'Object[]' } + @{ 'Name' = 'Type'; 'Type' = 'String' } + @{ 'Name' = 'Content'; 'Type' = 'String' } + ) { - It "should have $Name as a mandatory parameter" { + BeforeAll { + $commandletUnderTest = "GetTokenMarker" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + It "should have $Name as a mandatory parameter" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - It "should $Name not belong to a parameter set" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + It "should $Name not belong to a parameter set" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - It "should $Name type be $Type" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + It "should $Name type be $Type" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - } + } - Context "Function tests" { + } - BeforeAll { - $ParsedContent = @( - @{ - "Content" = "function" - "Type" = "Keyword" - "Start" = 0 - "Length" = 8 - "StartLine" = 1 - "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 9 - }, - @{ + Context "Function tests" { + + BeforeAll { + $ParsedContent = @( + @{ + "Content" = "function" + "Type" = "Keyword" + "Start" = 0 + "Length" = 8 + "StartLine" = 1 + "StartColumn" = 1 + "EndLine" = 1 + "EndColumn" = 9 + }, + @{ + "Content" = "GetFileContent" + "Type" = "CommandArgument" + "Start" = 9 + "Length" = 15 + "StartLine" = 1 + "StartColumn" = 10 + "EndLine" = 1 + "EndColumn" = 25 + }, + @{ + "Content" = "{" + "Type" = "GroupStart" + "Start" = 25 + "Length" = 1 + "StartLine" = 1 + "StartColumn" = 26 + "EndLine" = 1 + "EndColumn" = 27 + }, + @{ + "Content" = "}" + "Type" = "GroupEnd" + "Start" = 26 + "Length" = 1 + "StartLine" = 1 + "StartColumn" = 27 + "EndLine" = 1 + "EndColumn" = 28 + } + ) + + $tokenMatch = @{ "Content" = "GetFileContent" "Type" = "CommandArgument" "Start" = 9 @@ -54,83 +88,53 @@ Describe "GetTokenMarker.Tests" { "StartColumn" = 10 "EndLine" = 1 "EndColumn" = 25 - }, - @{ - "Content" = "{" - "Type" = "GroupStart" - "Start" = 25 - "Length" = 1 - "StartLine" = 1 - "StartColumn" = 26 - "EndLine" = 1 - "EndColumn" = 27 - }, - @{ - "Content" = "}" - "Type" = "GroupEnd" - "Start" = 26 - "Length" = 1 - "StartLine" = 1 - "StartColumn" = 27 - "EndLine" = 1 - "EndColumn" = 28 } - ) - - $tokenMatch = @{ - "Content" = "GetFileContent" - "Type" = "CommandArgument" - "Start" = 9 - "Length" = 15 - "StartLine" = 1 - "StartColumn" = 10 - "EndLine" = 1 - "EndColumn" = 25 + } - } + It "should throw when passing null parameters" { - It "should throw when passing null parameters" { + { - { + GetTokenMarker -ParsedContent $null -Type $null -Content $null - GetTokenMarker -ParsedContent $null -Type $null -Content $null + } | Should -Throw - } | Should -Throw + } - } + It "should find 'CommandArgument' type with 'GetFileContent' value" { - It "should find 'CommandArgument' type with 'GetFileContent' value" { + $token = GetTokenMarker -ParsedContent $ParsedContent -Type "CommandArgument" -Content "GetFileContent" - $token = GetTokenMarker -ParsedContent $ParsedContent -Type "CommandArgument" -Content "GetFileContent" + Compare-Object -ReferenceObject $token.Values -DifferenceObject $tokenMatch.values | Should -BeNullOrEmpty - Compare-Object -ReferenceObject $token.Values -DifferenceObject $tokenMatch.values | Should -BeNullOrEmpty + } - } + It "should not find 'Dummy' type with 'GetFileContent' value" { - It "should not find 'Dummy' type with 'GetFileContent' value" { + $token = GetTokenMarker -ParsedContent $ParsedContent -Type "Dummy" -Content "GetFileContent" - $token = GetTokenMarker -ParsedContent $ParsedContent -Type "Dummy" -Content "GetFileContent" + $token | Should -BeNullOrEmpty - $token | Should -BeNullOrEmpty + } - } + It "should not find 'CommandArgument' type with 'Dummy' value" { - It "should not find 'CommandArgument' type with 'Dummy' value" { + $token = GetTokenMarker -ParsedContent $ParsedContent -Type "CommandArgument" -Content "Dummy" - $token = GetTokenMarker -ParsedContent $ParsedContent -Type "CommandArgument" -Content "Dummy" + $token | Should -BeNullOrEmpty - $token | Should -BeNullOrEmpty + } - } + It "should throw with 'null' type and 'null' value" { - It "should throw with 'null' type and 'null' value" { + { - { + GetTokenMarker -ParsedContent $ParsedContent -Type $null -Content $null - GetTokenMarker -ParsedContent $ParsedContent -Type $null -Content $null + } | Should -Throw + } - } | Should -Throw } } diff --git a/Tests/Unit/PSQualityCheck/TestHelpTokensCountisValid.Tests.ps1 b/Tests/Unit/PSQualityCheck/TestHelpTokensCountisValid.Tests.ps1 index 12f151b..75f5160 100644 --- a/Tests/Unit/PSQualityCheck/TestHelpTokensCountisValid.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/TestHelpTokensCountisValid.Tests.ps1 @@ -1,41 +1,43 @@ -Describe "TestHelpTokensCountIsValid.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -Foreach @( - @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } - ) { + Describe "TestHelpTokensCountIsValid.Tests" { - BeforeAll { - $commandletUnderTest = "TestHelpTokensCountIsValid" - } + Context "Parameter Tests" -Foreach @( + @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } + ) { - It "should have $Name as a mandatory parameter" { + BeforeAll { + $commandletUnderTest = "TestHelpTokensCountIsValid" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + It "should have $Name as a mandatory parameter" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - It "should $Name not belong to a parameter set" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + It "should $Name not belong to a parameter set" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - It "should $Name type be $Type" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + It "should $Name type be $Type" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - } + } + + } - Context "Function tests" { + Context "Function tests" { - BeforeAll { - New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module') -ItemType Directory - New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data') -ItemType Directory + BeforeAll { + New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module') -ItemType Directory + New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data') -ItemType Directory - '@{ + '@{ ''1'' = @{ Key = ''.SYNOPSIS'' Required = $true @@ -84,131 +86,133 @@ Describe "TestHelpTokensCountIsValid.Tests" { MinOccurrences = 0 MaxOccurrences = 0 } - }' | Set-Content -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpElementRules.psd1') - } - - BeforeEach { - Mock Get-Module -ParameterFilter { $Name -eq "PSQualityCheck" } { - return @{'ModuleBase' = Join-Path -Path $TestDrive -ChildPath 'module' } + }' | Set-Content -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpRules.psd1') } - } - - It "should throw when passing null parameters" { - { + BeforeEach { + Mock Get-Module -ParameterFilter { $Name -eq "PSQualityCheck" } { + return @{'ModuleBase' = Join-Path -Path $TestDrive -ChildPath 'module' } + } + } - TestHelpTokensCountIsValid -HelpTokens $null + It "should throw when passing null parameters" { - } | Should -Throw + { - } + TestHelpTokensCountIsValid -HelpTokens $null -HelpRulesPath $null - It "should not throw when checking required help tokens count" { - - { - $helpTokens = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = "" - } - ) - } + } | Should -Throw - TestHelpTokensCountIsValid -HelpTokens $helpTokens - - Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } - - } | Should -Not -Throw + } - } + It "should not throw when checking required help tokens count" { - It "should throw when required help token is out of min/max range" { - - { - $helpTokens = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = "" - }, - @{ - "Name" = $null - "LineNumber" = 2 - "Text" = "" - } - ) - '.DESCRIPTION' = @( - @{ - "Name" = $null - "LineNumber" = 3 - "Text" = "" - } - ) - '.PARAMETER' = @( - @{ - "Name" = "Path" - "LineNumber" = 5 - "Text" = "" - } - ) - } + { + $helpTokens = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = "" + } + ) + } - TestHelpTokensCountIsValid -HelpTokens $helpTokens + TestHelpTokensCountIsValid -HelpTokens $helpTokens -HelpRulesPath (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpRules.psd1') - Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } + Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } - } | Should -Throw + } | Should -Not -Throw - } + } + It "should throw when required help token is out of min/max range" { + + { + $helpTokens = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = "" + }, + @{ + "Name" = $null + "LineNumber" = 2 + "Text" = "" + } + ) + '.DESCRIPTION' = @( + @{ + "Name" = $null + "LineNumber" = 3 + "Text" = "" + } + ) + '.PARAMETER' = @( + @{ + "Name" = "Path" + "LineNumber" = 5 + "Text" = "" + } + ) + } + + TestHelpTokensCountIsValid -HelpTokens $helpTokens -HelpRulesPath (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpRules.psd1') + + Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } + + } | Should -Throw - It "should not throw when optional help token is out of min/max range" { - - { - $helpTokens = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = "" - } - ) - '.DESCRIPTION' = @( - @{ - "Name" = $null - "LineNumber" = 3 - "Text" = "" - } - ) - '.PARAMETER' = @( - @{ - "Name" = "Path" - "LineNumber" = 5 - "Text" = "" - } - ) - '.NOTES' = @( - @{ - "Name" = "" - "LineNumber" = 10 - "Text" = "This is a note" - }, - @{ - "Name" = "" - "LineNumber" = 10 - "Text" = "This is a note" - } - ) - } + } - TestHelpTokensCountIsValid -HelpTokens $helpTokens - Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } + It "should not throw when optional help token is out of min/max range" { + + { + $helpTokens = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = "" + } + ) + '.DESCRIPTION' = @( + @{ + "Name" = $null + "LineNumber" = 3 + "Text" = "" + } + ) + '.PARAMETER' = @( + @{ + "Name" = "Path" + "LineNumber" = 5 + "Text" = "" + } + ) + '.NOTES' = @( + @{ + "Name" = "" + "LineNumber" = 10 + "Text" = "This is a note" + }, + @{ + "Name" = "" + "LineNumber" = 10 + "Text" = "This is a note" + } + ) + } + + TestHelpTokensCountIsValid -HelpTokens $helpTokens -HelpRulesPath (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpRules.psd1') + + Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } + + } | Should -Not -Throw - } | Should -Not -Throw + } } diff --git a/Tests/Unit/PSQualityCheck/TestHelpTokensParamsMatch.Tests.ps1 b/Tests/Unit/PSQualityCheck/TestHelpTokensParamsMatch.Tests.ps1 index 128e71b..afbf439 100644 --- a/Tests/Unit/PSQualityCheck/TestHelpTokensParamsMatch.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/TestHelpTokensParamsMatch.Tests.ps1 @@ -1,271 +1,275 @@ -Describe "TestHelpTokensParamsMatch.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -Foreach @( - @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } - @{ 'Name' = 'ParameterVariables'; 'Type' = 'PSObject' } - ) { + Describe "TestHelpTokensParamsMatch.Tests" { - BeforeAll { - $commandletUnderTest = "TestHelpTokensParamsMatch" - } - - It "should have $Name as a mandatory parameter" { - - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - - } - - It "should $Name not belong to a parameter set" { + Context "Parameter Tests" -ForEach @( + @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } + @{ 'Name' = 'ParameterVariables'; 'Type' = 'PSObject' } + ) { - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + BeforeAll { + $commandletUnderTest = "TestHelpTokensParamsMatch" + } - } - - It "should $Name type be $Type" { + It "should have $Name as a mandatory parameter" { - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - } + } - } + It "should $Name not belong to a parameter set" { - Context "Function tests" { + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - It "should throw when passing null parameters" { + } - { + It "should $Name type be $Type" { - TestHelpTokensParamsMatch -HelpTokens $null -ParameterVariables $null + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - } | Should -Throw + } } - It "should not throw when single param block variables matches .PARAMETER help when valid" { - - { - $help = @{ - '.PARAMETER' = @( - @{ - "Name" = 'ParameterWithType' - "LineNumber" = 1 - "Text" = "ParameterWithType description" - } - ) - } - $parameterVariable = @{ - "ParameterWithType" = '[string]' - } - - TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable - - } | Should -Not -Throw - - } - - It "should throw when single param block variable does not match .PARAMETER help when invalid" { - - { - $help = @{ - '.PARAMETER' = @( - @{ - "Name" = 'ParameterUnmatched' - "LineNumber" = 1 - "Text" = "ParameterUnmatched description" - } - ) - } - $parameterVariable = @{ - "ParameterWithType" = '[string]' - } - - TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable - - } | Should -Throw - - } - - It "should not throw when multiple param block variables match .PARAMETER help when valid" { - - { - $help = @{ - '.PARAMETER' = @( - @{ - "Name" = 'ParameterOne' - "LineNumber" = 1 - "Text" = "ParameterOne description" - }, - @{ - "Name" = 'ParameterTwo' - "LineNumber" = 1 - "Text" = "ParameterTwo description" - } - ) - } - $parameterVariable = @{ - "ParameterOne" = '[string]' - "ParameterTwo" = '[string]' - } - - TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable - - } | Should -Not -Throw - - } - - It "should throw when multiple param block variables do not match .PARAMETER help when one is invalid" { - - { - $help = @{ - '.PARAMETER' = @( - @{ - "Name" = 'ParameterA' - "LineNumber" = 1 - "Text" = "ParameterA description" - }, - @{ - "Name" = 'ParameterTwo' - "LineNumber" = 1 - "Text" = "ParameterTwo description" - } - ) - } - $parameterVariable = @{ - "ParameterOne" = '[string]' - "ParameterTwo" = '[string]' - } - - TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable - - } | Should -Throw - - } - - It "should throw when multiple param block variables do not match .PARAMETER help when all are invalid" { - - { - $help = @{ - '.PARAMETER' = @( - @{ - "Name" = 'ParameterA' - "LineNumber" = 1 - "Text" = "ParameterA description" - }, - @{ - "Name" = 'ParameterB' - "LineNumber" = 1 - "Text" = "ParameterB description" - } - ) - } - $parameterVariable = @{ - "ParameterOne" = '[string]' - "ParameterTwo" = '[string]' - } - - TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable - - } | Should -Throw - - } - - It "should throw when multiple param block variables do not match .PARAMETER help when one is missing" { - - { - $help = @{ - '.PARAMETER' = @( - @{ - "Name" = 'ParameterOne' - "LineNumber" = 1 - "Text" = "ParameterOne description" - } - ) - } - $parameterVariable = @{ - "ParameterOne" = '[string]' - "ParameterTwo" = '[string]' - } - - TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable - - } | Should -Throw - - } - - It "should throw when multiple param block variables do not match .PARAMETER help when all are missing" { - - { - $help = @{ - '.SYNOPSIS' = @( - @{ - "Name" = '' - "LineNumber" = 1 - "Text" = "Description" - } - ) - } - $parameterVariable = @{ - "ParameterOne" = '[string]' - "ParameterTwo" = '[string]' - } - - TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable - - } | Should -Throw - - } - - It "should throw when .PARAMETER help does not match param block variables when one is missing" { - - { - $help = @{ - '.PARAMETER' = @( - @{ - "Name" = 'ParameterOne' - "LineNumber" = 1 - "Text" = "ParameterOne description" - }, - @{ - "Name" = 'ParameterTwo' - "LineNumber" = 1 - "Text" = "ParameterTwo description" - } - ) - } - $parameterVariable = @{ - "ParameterTwo" = '[string]' - } - - TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable - - } | Should -Throw - - } + Context "Function tests" { + + It "should throw when passing null parameters" { + + { + + TestHelpTokensParamsMatch -HelpTokens $null -ParameterVariables $null + + } | Should -Throw + + } + + It "should not throw when single param block variables matches .PARAMETER help when valid" { - It "should throw when .PARAMETER help does not match param block variables when all are missing" { - - { - $help = @{ - '.PARAMETER' = @( - @{ - "Name" = 'ParameterOne' - "LineNumber" = 1 - "Text" = "ParameterOne description" - }, - @{ - "Name" = 'ParameterTwo' - "LineNumber" = 1 - "Text" = "ParameterTwo description" - } - ) - } - $parameterVariable = @{ - } - - TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable - - } | Should -Throw + { + $help = @{ + '.PARAMETER' = @( + @{ + "Name" = 'ParameterWithType' + "LineNumber" = 1 + "Text" = "ParameterWithType description" + } + ) + } + $parameterVariable = @{ + "ParameterWithType" = '[string]' + } + + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + + } | Should -Not -Throw + + } + + It "should throw when single param block variable does not match .PARAMETER help when invalid" { + + { + $help = @{ + '.PARAMETER' = @( + @{ + "Name" = 'ParameterUnmatched' + "LineNumber" = 1 + "Text" = "ParameterUnmatched description" + } + ) + } + $parameterVariable = @{ + "ParameterWithType" = '[string]' + } + + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + + } | Should -Throw + + } + + It "should not throw when multiple param block variables match .PARAMETER help when valid" { + + { + $help = @{ + '.PARAMETER' = @( + @{ + "Name" = 'ParameterOne' + "LineNumber" = 1 + "Text" = "ParameterOne description" + }, + @{ + "Name" = 'ParameterTwo' + "LineNumber" = 1 + "Text" = "ParameterTwo description" + } + ) + } + $parameterVariable = @{ + "ParameterOne" = '[string]' + "ParameterTwo" = '[string]' + } + + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + + } | Should -Not -Throw + + } + + It "should throw when multiple param block variables do not match .PARAMETER help when one is invalid" { + + { + $help = @{ + '.PARAMETER' = @( + @{ + "Name" = 'ParameterA' + "LineNumber" = 1 + "Text" = "ParameterA description" + }, + @{ + "Name" = 'ParameterTwo' + "LineNumber" = 1 + "Text" = "ParameterTwo description" + } + ) + } + $parameterVariable = @{ + "ParameterOne" = '[string]' + "ParameterTwo" = '[string]' + } + + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + + } | Should -Throw + + } + + It "should throw when multiple param block variables do not match .PARAMETER help when all are invalid" { + + { + $help = @{ + '.PARAMETER' = @( + @{ + "Name" = 'ParameterA' + "LineNumber" = 1 + "Text" = "ParameterA description" + }, + @{ + "Name" = 'ParameterB' + "LineNumber" = 1 + "Text" = "ParameterB description" + } + ) + } + $parameterVariable = @{ + "ParameterOne" = '[string]' + "ParameterTwo" = '[string]' + } + + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + + } | Should -Throw + + } + + It "should throw when multiple param block variables do not match .PARAMETER help when one is missing" { + + { + $help = @{ + '.PARAMETER' = @( + @{ + "Name" = 'ParameterOne' + "LineNumber" = 1 + "Text" = "ParameterOne description" + } + ) + } + $parameterVariable = @{ + "ParameterOne" = '[string]' + "ParameterTwo" = '[string]' + } + + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + + } | Should -Throw + + } + + It "should throw when multiple param block variables do not match .PARAMETER help when all are missing" { + + { + $help = @{ + '.SYNOPSIS' = @( + @{ + "Name" = '' + "LineNumber" = 1 + "Text" = "Description" + } + ) + } + $parameterVariable = @{ + "ParameterOne" = '[string]' + "ParameterTwo" = '[string]' + } + + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + + } | Should -Throw + + } + + It "should throw when .PARAMETER help does not match param block variables when one is missing" { + + { + $help = @{ + '.PARAMETER' = @( + @{ + "Name" = 'ParameterOne' + "LineNumber" = 1 + "Text" = "ParameterOne description" + }, + @{ + "Name" = 'ParameterTwo' + "LineNumber" = 1 + "Text" = "ParameterTwo description" + } + ) + } + $parameterVariable = @{ + "ParameterTwo" = '[string]' + } + + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + + } | Should -Throw + + } + + It "should throw when .PARAMETER help does not match param block variables when all are missing" { + + { + $help = @{ + '.PARAMETER' = @( + @{ + "Name" = 'ParameterOne' + "LineNumber" = 1 + "Text" = "ParameterOne description" + }, + @{ + "Name" = 'ParameterTwo' + "LineNumber" = 1 + "Text" = "ParameterTwo description" + } + ) + } + $parameterVariable = @{ + } + + TestHelpTokensParamsMatch -HelpTokens $help -ParameterVariables $parameterVariable + + } | Should -Throw + + } } diff --git a/Tests/Unit/PSQualityCheck/TestHelpTokensTextIsValid.Tests.ps1 b/Tests/Unit/PSQualityCheck/TestHelpTokensTextIsValid.Tests.ps1 index 3249ef0..be053d6 100644 --- a/Tests/Unit/PSQualityCheck/TestHelpTokensTextIsValid.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/TestHelpTokensTextIsValid.Tests.ps1 @@ -1,265 +1,269 @@ -Describe "TestHelpTokensTextIsValid.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -ForEach @( - @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } - ) { + Describe "TestHelpTokensTextIsValid.Tests" { - BeforeAll { - $commandletUnderTest = "TestHelpTokensTextIsValid" - } - - It "should have $Name as a mandatory parameter" { + Context "Parameter Tests" -Foreach @( + @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } + ) { - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + BeforeAll { + $commandletUnderTest = "TestHelpTokensTextIsValid" + } - } + It "should have $Name as a mandatory parameter" { - It "should $Name not belong to a parameter set" { + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - - } + } - It "should $Name type be $Type" { + It "should $Name not belong to a parameter set" { - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - - } - - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - Context "Function tests" { + } - It "should throw when passing null parameters" { + It "should $Name type be $Type" { - { + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - TestHelpTokensTextIsValid -HelpTokens $null - - } | Should -Throw - - } - - It "should not throw when checking help element text where it exists" { - - { - $help = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = "Convert the help comment into an object" - } - ) - } - - TestHelpTokensTextIsValid -HelpTokens $help - - } | Should -Not -Throw + } } - It "should throw when checking help element text where it is empty" { + Context "Function tests" { - { - $help = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = "" - } - ) - } + It "should throw when passing null parameters" { - TestHelpTokensTextIsValid -HelpTokens $help + { - } | Should -Throw + TestHelpTokensTextIsValid -HelpTokens $null - } + } | Should -Throw - It "should throw when checking help element text where it is missing" { + } - { - $help = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = $null - } - ) - } - - TestHelpTokensTextIsValid -HelpTokens $help - - } | Should -Throw - - } - - It "should not throw when checking multiple valid help element text values" { - - { - $help = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = "The SYNOPSIS property" - } - ) - '.DESCRIPTION' = @( - @{ - "Name" = $null - "LineNumber" = 3 - "Text" = "The DESCRIPTION property" - } - ) - '.PARAMETER' = @( - @{ - "Name" = "Path" - "LineNumber" = 5 - "Text" = "The Path property" - } - ) - } - - TestHelpTokensTextIsValid -HelpTokens $help - - } | Should -Not -Throw - - } - - It "should throw when checking multiple help element text values where one is empty" { - - { - $help = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = "" - } - ) - '.DESCRIPTION' = @( - @{ - "Name" = $null - "LineNumber" = 3 - "Text" = "The DESCRIPTION property" - } - ) - '.PARAMETER' = @( - @{ - "Name" = "Path" - "LineNumber" = 5 - "Text" = "The Path property" - } - ) - } - - TestHelpTokensTextIsValid -HelpTokens $help - - } | Should -Throw - - } - - It "should throw when checking multiple help element text values where one is missing" { - - { - $help = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = $null - } - ) - '.DESCRIPTION' = @( - @{ - "Name" = $null - "LineNumber" = 3 - "Text" = "The DESCRIPTION property" - } - ) - '.PARAMETER' = @( - @{ - "Name" = "Path" - "LineNumber" = 5 - "Text" = "The Path property" - } - ) - } - - TestHelpTokensTextIsValid -HelpTokens $help - - } | Should -Throw - - } - - It "should throw when checking multiple help element text values where all are empty" { - - { - $help = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = "" - } - ) - '.DESCRIPTION' = @( - @{ - "Name" = $null - "LineNumber" = 3 - "Text" = "" - } - ) - '.PARAMETER' = @( - @{ - "Name" = "Path" - "LineNumber" = 5 - "Text" = "" - } - ) - } - - TestHelpTokensTextIsValid -HelpTokens $help - - } | Should -Throw - - } + It "should not throw when checking help element text where it exists" { - It "should throw when checking multiple help element text values where all are missing" { - - { - $help = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = $null - } - ) - '.DESCRIPTION' = @( - @{ - "Name" = $null - "LineNumber" = 3 - "Text" = $null - } - ) - '.PARAMETER' = @( - @{ - "Name" = "Path" - "LineNumber" = 5 - "Text" = $null - } - ) - } - - TestHelpTokensTextIsValid -HelpTokens $help - - } | Should -Throw + { + $help = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = "Convert the help comment into an object" + } + ) + } + + TestHelpTokensTextIsValid -HelpTokens $help + + } | Should -Not -Throw + + } + + It "should throw when checking help element text where it is empty" { + + { + $help = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = "" + } + ) + } + + TestHelpTokensTextIsValid -HelpTokens $help + + } | Should -Throw + + } + + It "should throw when checking help element text where it is missing" { + + { + $help = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = $null + } + ) + } + + TestHelpTokensTextIsValid -HelpTokens $help + + } | Should -Throw + + } + + It "should not throw when checking multiple valid help element text values" { + + { + $help = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = "The SYNOPSIS property" + } + ) + '.DESCRIPTION' = @( + @{ + "Name" = $null + "LineNumber" = 3 + "Text" = "The DESCRIPTION property" + } + ) + '.PARAMETER' = @( + @{ + "Name" = "Path" + "LineNumber" = 5 + "Text" = "The Path property" + } + ) + } + + TestHelpTokensTextIsValid -HelpTokens $help + + } | Should -Not -Throw + + } + + It "should throw when checking multiple help element text values where one is empty" { + + { + $help = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = "" + } + ) + '.DESCRIPTION' = @( + @{ + "Name" = $null + "LineNumber" = 3 + "Text" = "The DESCRIPTION property" + } + ) + '.PARAMETER' = @( + @{ + "Name" = "Path" + "LineNumber" = 5 + "Text" = "The Path property" + } + ) + } + + TestHelpTokensTextIsValid -HelpTokens $help + + } | Should -Throw + + } + + It "should throw when checking multiple help element text values where one is missing" { + + { + $help = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = $null + } + ) + '.DESCRIPTION' = @( + @{ + "Name" = $null + "LineNumber" = 3 + "Text" = "The DESCRIPTION property" + } + ) + '.PARAMETER' = @( + @{ + "Name" = "Path" + "LineNumber" = 5 + "Text" = "The Path property" + } + ) + } + + TestHelpTokensTextIsValid -HelpTokens $help + + } | Should -Throw + + } + + It "should throw when checking multiple help element text values where all are empty" { + + { + $help = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = "" + } + ) + '.DESCRIPTION' = @( + @{ + "Name" = $null + "LineNumber" = 3 + "Text" = "" + } + ) + '.PARAMETER' = @( + @{ + "Name" = "Path" + "LineNumber" = 5 + "Text" = "" + } + ) + } + + TestHelpTokensTextIsValid -HelpTokens $help + + } | Should -Throw + + } + + It "should throw when checking multiple help element text values where all are missing" { + + { + $help = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = $null + } + ) + '.DESCRIPTION' = @( + @{ + "Name" = $null + "LineNumber" = 3 + "Text" = $null + } + ) + '.PARAMETER' = @( + @{ + "Name" = "Path" + "LineNumber" = 5 + "Text" = $null + } + ) + } + + TestHelpTokensTextIsValid -HelpTokens $help + + } | Should -Throw + + } } diff --git a/Tests/Unit/PSQualityCheck/TestImportModuleIsValid.Tests.ps1 b/Tests/Unit/PSQualityCheck/TestImportModuleIsValid.Tests.ps1 index 74e84f7..5919545 100644 --- a/Tests/Unit/PSQualityCheck/TestImportModuleIsValid.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/TestImportModuleIsValid.Tests.ps1 @@ -1,244 +1,248 @@ -Describe "TestImportModuleIsValid.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -Foreach @( - @{ 'Name' = 'ParsedContent'; 'Type' = 'Object[]' } - @{ 'Name' = 'ImportModuleTokens'; 'Type' = 'Object[]' } - ) { + Describe "TestImportModuleIsValid.Tests" { - BeforeAll { - $commandletUnderTest = "TestImportModuleIsValid" - } - - It "should have $Name as a mandatory parameter" { - - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - - } + Context "Parameter Tests" -ForEach @( + @{ 'Name' = 'ParsedContent'; 'Type' = 'Object[]' } + @{ 'Name' = 'ImportModuleTokens'; 'Type' = 'Object[]' } + ) { - It "should $Name not belong to a parameter set" { + BeforeAll { + $commandletUnderTest = "TestImportModuleIsValid" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + It "should have $Name as a mandatory parameter" { - } - - It "should $Name type be $Type" { + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + } - } - - } + It "should $Name not belong to a parameter set" { - Context "Function tests" { + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - It "should throw when passing null parameter values" { + } - { + It "should $Name type be $Type" { - TestImportModuleIsValid -ParsedContent $null -ImportModuleTokens $null - - } | Should -Throw - - } - - It "should pass when passed a valid Import-Module command" { - - { - - $ParsedContent = @( - @{ - "Content" = "Import-Module" - "Type" = "Command" - "Start" = 0 - "Length" = 13 - "StartLine" = 1 - "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 14 - }, - @{ - "Content" = "-Name" - "Type" = "CommandParameter" - "Start" = 14 - "Length" = 5 - "StartLine" = 1 - "StartColumn" = 15 - "EndLine" = 1 - "EndColumn" = 20 - }, - @{ - "Content" = "ModuleName" - "Type" = "CommandArgument" - "Start" = 20 - "Length" = 10 - "StartLine" = 1 - "StartColumn" = 21 - "EndLine" = 1 - "EndColumn" = 31 - }, - @{ - "Content" = "-RequiredVersion" - "Type" = "CommandParameter" - "Start" = 31 - "Length" = 16 - "StartLine" = 1 - "StartColumn" = 32 - "EndLine" = 1 - "EndColumn" = 48 - }, - @{ - "Content" = "1.0.0" - "Type" = "String" - "Start" = 48 - "Length" = 7 - "StartLine" = 1 - "StartColumn" = 49 - "EndLine" = 1 - "EndColumn" = 56 - } - ) - - $importModuleTokens = $ParsedContent - - TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens - - } | Should -Not -Throw - - } - - It "should throw when passed a valid Import-Module command missing all required parameters" { - - { - - $ParsedContent = @( - @{ - "Content" = "Import-Module" - "Type" = "Command" - "Start" = 0 - "Length" = 13 - "StartLine" = 1 - "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 14 - }, - @{ - "Content" = "ModuleName" - "Type" = "CommandArgument" - "Start" = 14 - "Length" = 10 - "StartLine" = 1 - "StartColumn" = 15 - "EndLine" = 1 - "EndColumn" = 25 - } - ) - - $importModuleTokens = $ParsedContent - - TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens - - } | Should -Throw - - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - It "should throw when passed a valid Import-Module command missing -Name only" { - - { - - $ParsedContent = @( - @{ - "Content" = "Import-Module" - "Type" = "Command" - "Start" = 0 - "Length" = 13 - "StartLine" = 1 - "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 14 - }, - @{ - "Content" = "ModuleName" - "Type" = "CommandArgument" - "Start" = 14 - "Length" = 10 - "StartLine" = 1 - "StartColumn" = 15 - "EndLine" = 1 - "EndColumn" = 25 - }, - @{ - "Content" = "-RequiredVersion" - "Type" = "CommandParameter" - "Start" = 25 - "Length" = 16 - "StartLine" = 1 - "StartColumn" = 26 - "EndLine" = 1 - "EndColumn" = 42 - }, - @{ - "Content" = "1.0.0" - "Type" = "String" - "Start" = 42 - "Length" = 7 - "StartLine" = 1 - "StartColumn" = 43 - "EndLine" = 1 - "EndColumn" = 50 - } - ) - - $importModuleTokens = $ParsedContent - - TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens - - } | Should -Throw + } } - It "should throw when passed a valid Import-Module command missing -RequiredVersion, -MinimumVersion or -MaximumVersion" { - - { - - $ParsedContent = @( - @{ - "Content" = "Import-Module" - "Type" = "Command" - "Start" = 0 - "Length" = 13 - "StartLine" = 1 - "StartColumn" = 1 - "EndLine" = 1 - "EndColumn" = 14 - }, - @{ - "Content" = "-Name" - "Type" = "CommandParameter" - "Start" = 14 - "Length" = 5 - "StartLine" = 1 - "StartColumn" = 15 - "EndLine" = 1 - "EndColumn" = 20 - }, - @{ - "Content" = "ModuleName" - "Type" = "CommandArgument" - "Start" = 20 - "Length" = 10 - "StartLine" = 1 - "StartColumn" = 21 - "EndLine" = 1 - "EndColumn" = 31 - } - ) - - $importModuleTokens = $ParsedContent - - TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens - - } | Should -Throw + Context "Function tests" { + + It "should throw when passing null parameter values" { + + { + + TestImportModuleIsValid -ParsedContent $null -ImportModuleTokens $null + + } | Should -Throw + + } + + It "should pass when passed a valid Import-Module command" { + + { + + $ParsedContent = @( + @{ + "Content" = "Import-Module" + "Type" = "Command" + "Start" = 0 + "Length" = 13 + "StartLine" = 1 + "StartColumn" = 1 + "EndLine" = 1 + "EndColumn" = 14 + }, + @{ + "Content" = "-Name" + "Type" = "CommandParameter" + "Start" = 14 + "Length" = 5 + "StartLine" = 1 + "StartColumn" = 15 + "EndLine" = 1 + "EndColumn" = 20 + }, + @{ + "Content" = "ModuleName" + "Type" = "CommandArgument" + "Start" = 20 + "Length" = 10 + "StartLine" = 1 + "StartColumn" = 21 + "EndLine" = 1 + "EndColumn" = 31 + }, + @{ + "Content" = "-RequiredVersion" + "Type" = "CommandParameter" + "Start" = 31 + "Length" = 16 + "StartLine" = 1 + "StartColumn" = 32 + "EndLine" = 1 + "EndColumn" = 48 + }, + @{ + "Content" = "1.0.0" + "Type" = "String" + "Start" = 48 + "Length" = 7 + "StartLine" = 1 + "StartColumn" = 49 + "EndLine" = 1 + "EndColumn" = 56 + } + ) + + $importModuleTokens = $ParsedContent + + TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens + + } | Should -Not -Throw + + } + + It "should throw when passed a valid Import-Module command missing all required parameters" { + + { + + $ParsedContent = @( + @{ + "Content" = "Import-Module" + "Type" = "Command" + "Start" = 0 + "Length" = 13 + "StartLine" = 1 + "StartColumn" = 1 + "EndLine" = 1 + "EndColumn" = 14 + }, + @{ + "Content" = "ModuleName" + "Type" = "CommandArgument" + "Start" = 14 + "Length" = 10 + "StartLine" = 1 + "StartColumn" = 15 + "EndLine" = 1 + "EndColumn" = 25 + } + ) + + $importModuleTokens = $ParsedContent + + TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens + + } | Should -Throw + + } + + It "should throw when passed a valid Import-Module command missing -Name only" { + + { + + $ParsedContent = @( + @{ + "Content" = "Import-Module" + "Type" = "Command" + "Start" = 0 + "Length" = 13 + "StartLine" = 1 + "StartColumn" = 1 + "EndLine" = 1 + "EndColumn" = 14 + }, + @{ + "Content" = "ModuleName" + "Type" = "CommandArgument" + "Start" = 14 + "Length" = 10 + "StartLine" = 1 + "StartColumn" = 15 + "EndLine" = 1 + "EndColumn" = 25 + }, + @{ + "Content" = "-RequiredVersion" + "Type" = "CommandParameter" + "Start" = 25 + "Length" = 16 + "StartLine" = 1 + "StartColumn" = 26 + "EndLine" = 1 + "EndColumn" = 42 + }, + @{ + "Content" = "1.0.0" + "Type" = "String" + "Start" = 42 + "Length" = 7 + "StartLine" = 1 + "StartColumn" = 43 + "EndLine" = 1 + "EndColumn" = 50 + } + ) + + $importModuleTokens = $ParsedContent + + TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens + + } | Should -Throw + + } + + It "should throw when passed a valid Import-Module command missing -RequiredVersion, -MinimumVersion or -MaximumVersion" { + + { + + $ParsedContent = @( + @{ + "Content" = "Import-Module" + "Type" = "Command" + "Start" = 0 + "Length" = 13 + "StartLine" = 1 + "StartColumn" = 1 + "EndLine" = 1 + "EndColumn" = 14 + }, + @{ + "Content" = "-Name" + "Type" = "CommandParameter" + "Start" = 14 + "Length" = 5 + "StartLine" = 1 + "StartColumn" = 15 + "EndLine" = 1 + "EndColumn" = 20 + }, + @{ + "Content" = "ModuleName" + "Type" = "CommandArgument" + "Start" = 20 + "Length" = 10 + "StartLine" = 1 + "StartColumn" = 21 + "EndLine" = 1 + "EndColumn" = 31 + } + ) + + $importModuleTokens = $ParsedContent + + TestImportModuleIsValid -ParsedContent $ParsedContent -ImportModuleTokens $importModuleTokens + + } | Should -Throw + + } } diff --git a/Tests/Unit/PSQualityCheck/TestParameterVariablesHaveType.Tests.ps1 b/Tests/Unit/PSQualityCheck/TestParameterVariablesHaveType.Tests.ps1 index 407784d..aca56c6 100644 --- a/Tests/Unit/PSQualityCheck/TestParameterVariablesHaveType.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/TestParameterVariablesHaveType.Tests.ps1 @@ -1,82 +1,86 @@ -Describe "TestParameterVariablesHaveType.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -Foreach @( - @{ 'Name' = 'ParameterVariables'; 'Type' = 'HashTable' } - ) { + Describe "TestParameterVariablesHaveType.Tests" { - BeforeAll { - $commandletUnderTest = "TestParameterVariablesHaveType" - } + Context "Parameter Tests" -ForEach @( + @{ 'Name' = 'ParameterVariables'; 'Type' = 'HashTable' } + ) { - It "should have $Name as a mandatory parameter" { + BeforeAll { + $commandletUnderTest = "TestParameterVariablesHaveType" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + It "should have $Name as a mandatory parameter" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - It "should $Name not belong to a parameter set" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + It "should $Name not belong to a parameter set" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + + } + + It "should $Name type be $Type" { - It "should $Name type be $Type" { + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + } } - } + Context "Function tests" { - Context "Function tests" { + It "should throw when passing null parameters" { - It "should throw when passing null parameters" { + { - { + TestParameterVariablesHaveType -ParameterVariables $null - TestParameterVariablesHaveType -ParameterVariables $null + } | Should -Throw - } | Should -Throw + } - } + It "should not throw with valid parameter" { - It "should not throw with valid parameter" { + { + $parameterVariable = @{ + 'ParameterWithType' = '[string]' + } - { - $parameterVariable = @{ - 'ParameterWithType' = '[string]' - } + TestParameterVariablesHaveType -ParameterVariables $parameterVariable - TestParameterVariablesHaveType -ParameterVariables $parameterVariable + } | Should -Not -Throw - } | Should -Not -Throw + } - } + It "should throw with null type parameter" { - It "should throw with null type parameter" { + { + $parameterVariable = @{ + 'ParameterWithoutType' = $null + } - { - $parameterVariable = @{ - 'ParameterWithoutType' = $null - } + TestParameterVariablesHaveType -ParameterVariables $parameterVariable - TestParameterVariablesHaveType -ParameterVariables $parameterVariable + } | Should -Throw - } | Should -Throw + } - } + It "should throw with empty type parameter" { - It "should throw with empty type parameter" { + { + $parameterVariable = @{ + 'ParameterWithEmptyType' = '' + } - { - $parameterVariable = @{ - 'ParameterWithEmptyType' = '' - } + TestParameterVariablesHaveType -ParameterVariables $parameterVariable - TestParameterVariablesHaveType -ParameterVariables $parameterVariable + } | Should -Throw - } | Should -Throw + } } diff --git a/Tests/Unit/PSQualityCheck/TestRequiredToken.Tests.ps1 b/Tests/Unit/PSQualityCheck/TestRequiredToken.Tests.ps1 index 6574dc4..38e8354 100644 --- a/Tests/Unit/PSQualityCheck/TestRequiredToken.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/TestRequiredToken.Tests.ps1 @@ -1,41 +1,43 @@ -Describe "TestRequiredToken.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -ForEach @( - @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } - ) { + Describe "TestRequiredToken.Tests" { - BeforeAll { - $commandletUnderTest = "TestRequiredToken" - } + Context "Parameter Tests" -ForEach @( + @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } + ) { - It "should have $Name as a mandatory parameter" { + BeforeAll { + $commandletUnderTest = "TestRequiredToken" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + It "should have $Name as a mandatory parameter" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - It "should $Name not belong to a parameter set" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + It "should $Name not belong to a parameter set" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - It "should $Name type be $Type" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + It "should $Name type be $Type" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - } + } + + } - Context "Function tests" { + Context "Function tests" { - BeforeAll { - New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module') -ItemType Directory - New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data') -ItemType Directory + BeforeAll { + New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module') -ItemType Directory + New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data') -ItemType Directory - '@{ + '@{ ''1'' = @{ Key = ''.SYNOPSIS'' Required = $true @@ -84,150 +86,152 @@ Describe "TestRequiredToken.Tests" { MinOccurrences = 0 MaxOccurrences = 0 } - }' | Set-Content -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpElementRules.psd1') - } - - BeforeEach { - Mock Get-Module -ParameterFilter { $Name -eq "PSQualityCheck" } { - return @{'ModuleBase' = Join-Path -Path $TestDrive -ChildPath 'module' } + }' | Set-Content -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpRules.psd1') } - } - - It "should throw when passing null parameters" { - - { - TestRequiredToken -HelpTokens $null - - } | Should -Throw - - } - - It "should not throw when checking required help tokens" { - - { - $helpTokens = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = "" - } - ) - '.DESCRIPTION' = @( - @{ - "Name" = $null - "LineNumber" = 3 - "Text" = "" - } - ) - '.PARAMETER' = @( - @{ - "Name" = "Path" - "LineNumber" = 5 - "Text" = "" - } - ) - '.EXAMPLE' = @( - @{ - "Name" = "" - "LineNumber" = 7 - "Text" = "This is example text" - } - ) + BeforeEach { + Mock Get-Module -ParameterFilter { $Name -eq "PSQualityCheck" } { + return @{'ModuleBase' = Join-Path -Path $TestDrive -ChildPath 'module' } } + } - TestRequiredToken -HelpTokens $helpTokens - - Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } - - } | Should -Not -Throw - - } + It "should throw when passing null parameters" { - It "should not throw when checking required help tokens plus optional help tokens" { - - { - - $helpTokens = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = "" - } - ) - '.DESCRIPTION' = @( - @{ - "Name" = $null - "LineNumber" = 3 - "Text" = "" - } - ) - '.PARAMETER' = @( - @{ - "Name" = "Path" - "LineNumber" = 5 - "Text" = "" - } - ) - '.EXAMPLE' = @( - @{ - "Name" = "" - "LineNumber" = 7 - "Text" = "This is example text" - } - ) - '.NOTES' = @( - @{ - "Name" = "" - "LineNumber" = 10 - "Text" = "This is a note" - } - ) + { - } + TestRequiredToken -HelpTokens $null -HelpRulesPath $null - TestRequiredToken -HelpTokens $helpTokens + } | Should -Throw - Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } + } - } | Should -Not -Throw + It "should not throw when checking required help tokens" { + + { + $helpTokens = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = "" + } + ) + '.DESCRIPTION' = @( + @{ + "Name" = $null + "LineNumber" = 3 + "Text" = "" + } + ) + '.PARAMETER' = @( + @{ + "Name" = "Path" + "LineNumber" = 5 + "Text" = "" + } + ) + '.EXAMPLE' = @( + @{ + "Name" = "" + "LineNumber" = 7 + "Text" = "This is example text" + } + ) + } + + TestRequiredToken -HelpTokens $helpTokens -HelpRulesPath (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpRules.psd1') + + Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } + + } | Should -Not -Throw - } + } - It "should throw when required help token is missing" { - - { - $helpTokens = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = "" - } - ) - '.DESCRIPTION' = @( - @{ - "Name" = $null - "LineNumber" = 3 - "Text" = "" - } - ) - '.PARAMETER' = @( - @{ - "Name" = "Path" - "LineNumber" = 5 - "Text" = "" - } - ) - } + It "should not throw when checking required help tokens plus optional help tokens" { + + { + + $helpTokens = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = "" + } + ) + '.DESCRIPTION' = @( + @{ + "Name" = $null + "LineNumber" = 3 + "Text" = "" + } + ) + '.PARAMETER' = @( + @{ + "Name" = "Path" + "LineNumber" = 5 + "Text" = "" + } + ) + '.EXAMPLE' = @( + @{ + "Name" = "" + "LineNumber" = 7 + "Text" = "This is example text" + } + ) + '.NOTES' = @( + @{ + "Name" = "" + "LineNumber" = 10 + "Text" = "This is a note" + } + ) + + } + + TestRequiredToken -HelpTokens $helpTokens -HelpRulesPath (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpRules.psd1') + + Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } + + } | Should -Not -Throw - TestRequiredToken -HelpTokens $helpTokens + } - Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } + It "should throw when required help token is missing" { + + { + $helpTokens = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = "" + } + ) + '.DESCRIPTION' = @( + @{ + "Name" = $null + "LineNumber" = 3 + "Text" = "" + } + ) + '.PARAMETER' = @( + @{ + "Name" = "Path" + "LineNumber" = 5 + "Text" = "" + } + ) + } + + TestRequiredToken -HelpTokens $helpTokens -HelpRulesPath (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpRules.psd1') + + Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } + + } | Should -Throw - } | Should -Throw + } } diff --git a/Tests/Unit/PSQualityCheck/TestUnspecifiedToken.Tests.ps1 b/Tests/Unit/PSQualityCheck/TestUnspecifiedToken.Tests.ps1 index 6f6e083..7c44955 100644 --- a/Tests/Unit/PSQualityCheck/TestUnspecifiedToken.Tests.ps1 +++ b/Tests/Unit/PSQualityCheck/TestUnspecifiedToken.Tests.ps1 @@ -1,41 +1,43 @@ -Describe "TestUnspecifiedToken.Tests" { +InModuleScope PSQualityCheck { - Context "Parameter Tests" -Foreach @( - @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } - ) { + Describe "TestUnspecifiedToken.Tests" { - BeforeAll { - $commandletUnderTest = "TestUnspecifiedToken" - } + Context "Parameter Tests" -ForEach @( + @{ 'Name' = 'HelpTokens'; 'Type' = 'HashTable' } + ) { - It "should have $Name as a mandatory parameter" { + BeforeAll { + $commandletUnderTest = "TestUnspecifiedToken" + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name - (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue + It "should have $Name as a mandatory parameter" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Name | Should -BeExactly $Name + (Get-Command -Name $commandletUnderTest).Parameters[$Name].Attributes.Mandatory | Should -BeTrue - It "should $Name not belong to a parameter set" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' + It "should $Name not belong to a parameter set" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterSets.Keys | Should -Be '__AllParameterSets' - It "should $Name type be $Type" { + } - (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type + It "should $Name type be $Type" { - } + (Get-Command -Name $commandletUnderTest).Parameters[$Name].ParameterType.Name | Should -Be $Type - } + } + + } - Context "Function tests" { + Context "Function tests" { - BeforeAll { - New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module') -ItemType Directory - New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data') -ItemType Directory + BeforeAll { + New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module') -ItemType Directory + New-Item -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data') -ItemType Directory - '@{ + '@{ ''1'' = @{ Key = ''.SYNOPSIS'' Required = $true @@ -84,136 +86,138 @@ Describe "TestUnspecifiedToken.Tests" { MinOccurrences = 0 MaxOccurrences = 0 } - }' | Set-Content -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpElementRules.psd1') - } - - BeforeEach { - Mock Get-Module -ParameterFilter { $Name -eq "PSQualityCheck" } { - return @{'ModuleBase' = Join-Path -Path $TestDrive -ChildPath 'module' } + }' | Set-Content -Path (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpRules.psd1') } - } - - It "should throw when passing null parameters" { - { - - TestUnspecifiedToken -HelpTokens $null - - } | Should -Throw - - } - - It "should not throw when checking required help tokens" { - - { - $helpTokens = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = "" - } - ) - '.DESCRIPTION' = @( - @{ - "Name" = $null - "LineNumber" = 3 - "Text" = "" - } - ) - '.PARAMETER' = @( - @{ - "Name" = "Path" - "LineNumber" = 5 - "Text" = "" - } - ) - '.EXAMPLE' = @( - @{ - "Name" = "" - "LineNumber" = 7 - "Text" = "This is example text" - } - ) + BeforeEach { + Mock Get-Module -ParameterFilter { $Name -eq "PSQualityCheck" } { + return @{'ModuleBase' = Join-Path -Path $TestDrive -ChildPath 'module' } } + } - TestUnspecifiedToken -HelpTokens $helpTokens + It "should throw when passing null parameters" { - Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } + { - } | Should -Not -Throw + TestUnspecifiedToken -HelpTokens $null -HelpRulesPath (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpRules.psd1') - } + } | Should -Throw - It "should not throw when checking required help tokens plus optional help tokens" { - - { - - $helpTokens = @{ - '.SYNOPSIS' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = "" - } - ) - '.DESCRIPTION' = @( - @{ - "Name" = $null - "LineNumber" = 3 - "Text" = "" - } - ) - '.PARAMETER' = @( - @{ - "Name" = "Path" - "LineNumber" = 5 - "Text" = "" - } - ) - '.EXAMPLE' = @( - @{ - "Name" = "" - "LineNumber" = 7 - "Text" = "This is example text" - } - ) - '.NOTES' = @( - @{ - "Name" = "" - "LineNumber" = 10 - "Text" = "This is a note" - } - ) + } - } + It "should not throw when checking required help tokens" { + + { + $helpTokens = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = "" + } + ) + '.DESCRIPTION' = @( + @{ + "Name" = $null + "LineNumber" = 3 + "Text" = "" + } + ) + '.PARAMETER' = @( + @{ + "Name" = "Path" + "LineNumber" = 5 + "Text" = "" + } + ) + '.EXAMPLE' = @( + @{ + "Name" = "" + "LineNumber" = 7 + "Text" = "This is example text" + } + ) + } + + TestUnspecifiedToken -HelpTokens $helpTokens -HelpRulesPath (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpRules.psd1') + + Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } + + } | Should -Not -Throw - TestUnspecifiedToken -HelpTokens $helpTokens + } - Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } + It "should not throw when checking required help tokens plus optional help tokens" { + + { + + $helpTokens = @{ + '.SYNOPSIS' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = "" + } + ) + '.DESCRIPTION' = @( + @{ + "Name" = $null + "LineNumber" = 3 + "Text" = "" + } + ) + '.PARAMETER' = @( + @{ + "Name" = "Path" + "LineNumber" = 5 + "Text" = "" + } + ) + '.EXAMPLE' = @( + @{ + "Name" = "" + "LineNumber" = 7 + "Text" = "This is example text" + } + ) + '.NOTES' = @( + @{ + "Name" = "" + "LineNumber" = 10 + "Text" = "This is a note" + } + ) + + } + + TestUnspecifiedToken -HelpTokens $helpTokens -HelpRulesPath (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpRules.psd1') + + Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } + + } | Should -Not -Throw - } | Should -Not -Throw + } - } + It "should throw when unspecified help token is present" { - It "should throw when unspecified help token is present" { - - { - $helpTokens = @{ - '.DUMMY' = @( - @{ - "Name" = $null - "LineNumber" = 1 - "Text" = "" - } - ) - } + { + $helpTokens = @{ + '.DUMMY' = @( + @{ + "Name" = $null + "LineNumber" = 1 + "Text" = "" + } + ) + } + + TestUnspecifiedToken -HelpTokens $helpTokens -HelpRulesPath (Join-Path -Path $TestDrive -ChildPath 'module\Data\HelpRules.psd1') - TestUnspecifiedToken -HelpTokens $helpTokens + Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } - Assert-MockCalled -CommandName Get-Module -Times 1 -ParameterFilter { $Name -eq "PSQualityCheck" } + } | Should -Throw - } | Should -Throw + } } From 4fd96ce82cf51f70d35851c1ed2b9fcae09cf877 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Wed, 28 Apr 2021 21:20:24 +0100 Subject: [PATCH 23/27] Update install.depend to correct install nuget.exe when required --- install.depend.ps1 | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/install.depend.ps1 b/install.depend.ps1 index 7a30b8e..ce893a6 100644 --- a/install.depend.ps1 +++ b/install.depend.ps1 @@ -1,36 +1,50 @@ +Write-Output "Checking for nuget.exe" if (-not ($NuGetPath = (Get-Command 'nuget.exe' -ErrorAction SilentlyContinue).Path)) { if (-not (Test-Path -Path ".\bin" -ErrorAction SilentlyContinue)) { New-Item -Path "bin" -ItemType Directory } + Write-Output "nuget.exe not found, downloading into project bin path" $NuGetPath = Resolve-Path -Path ".\bin" $NuGetFile = Join-Path -Path $NuGetPath -ChildPath "nuget.exe" Invoke-WebRequest -Uri 'https://dist.nuget.org/win-x86-commandline/latest/nuget.exe' -OutFile $NuGetFile - $env:Path += "$NuGetPath;" + + $path = [Environment]::GetEnvironmentVariable('Path', 'Machine') + $environmentPaths = $path.Split(";") + if (-not ($NuGetPath -contains $environmentPaths)) { + Write-Output "Updating System Environment path" + $path += ";$NuGetPath" + $env:Path = $path + [Environment]::SetEnvironmentVariable("Path", $path, 'Machine') + } + } + # Bootstrap environment +Write-Output "Bootstrap NuGet PackageProvider" Get-PackageProvider -Name 'NuGet' -ForceBootstrap | Out-Null # Install PSDepend module if it is not already installed if (-not (Get-Module -Name 'PSDepend' -ListAvailable)) { - Write-Output "`nPSDepend is not yet installed...installing PSDepend now..." + Write-Output "PSDepend is not yet installed, installing PSDepend" Install-Module -Name 'PSDepend' -Scope 'CurrentUser' -Force } else { - Write-Output "`nPSDepend already installed...skipping." + Write-Output "PSDepend already installed" } - # Install build dependencies -$psdependencyConfigPath = Join-Path -Path $PSScriptRoot -ChildPath 'install.depend.psd1' -Write-Output "Checking / resolving module dependencies from [$psdependencyConfigPath]..." +$psDependencyConfigPath = Join-Path -Path $PSScriptRoot -ChildPath 'install.depend.psd1' +Write-Output "Checking / resolving module dependencies from [$psDependencyConfigPath]..." Import-Module -Name 'PSDepend' $invokePSDependParams = @{ - Path = $psdependencyConfigPath + Path = $psDependencyConfigPath Import = $true Confirm = $false Install = $true Verbose = $false } Invoke-PSDepend @invokePSDependParams + +Write-Output "Finished installing all dependencies" From d77edf490a0888fbbe54a8c76d0436893034ca98 Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Wed, 28 Apr 2021 21:20:55 +0100 Subject: [PATCH 24/27] Stub file to keep folder in git --- scripts/readme.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 scripts/readme.md diff --git a/scripts/readme.md b/scripts/readme.md new file mode 100644 index 0000000..e69de29 From eb9c01f86d6a337f13ad114bdb3d59dc0cd6ef4b Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Wed, 28 Apr 2021 21:21:10 +0100 Subject: [PATCH 25/27] Updated build process --- build-functions.psm1 | 66 +++++++----- build.ps1 | 242 +++++++++++++++++++++++++++---------------- 2 files changed, 192 insertions(+), 116 deletions(-) diff --git a/build-functions.psm1 b/build-functions.psm1 index 528a240..36dfc16 100644 --- a/build-functions.psm1 +++ b/build-functions.psm1 @@ -70,12 +70,10 @@ function Install-BuiltModule { [OutputType([System.Void])] param ( [parameter(Mandatory = $true)] - [string]$Module + [string]$ModuleName ) - # $Module = "PSTemplate" - - Install-Module -Name $Module -Repository "$Module-local" + Install-Module -Name $ModuleName -Repository "$ModuleName-local" } @@ -85,31 +83,38 @@ function Publish-BuiltModule { [OutputType([System.Void])] param ( [parameter(Mandatory = $true)] - [string]$Module, + [string]$ModuleName, [parameter(Mandatory = $true)] [string]$ArtifactsFolder, + [parameter(Mandatory = $true)] + [string]$SourceFolder, + [parameter(Mandatory = $true)] [string]$BuildFolder, [switch]$Clean ) - # $Module = "PSTemplate" - $Version = (Import-PowerShellDataFile -Path ".\source\$Module\$Module.psd1").ModuleVersion + $version = (Import-PowerShellDataFile -Path "$SourceFolder\$ModuleName\$ModuleName.psd1").ModuleVersion + $repositoryName = "$moduleName-local" - # QUERY: Need this? - # New-Item -ItemType Directory -Path ./artifacts -Force - # $ArtifactsFolder = Resolve-Path -Path "./artifacts" - if ($PSBoundParameters.ContainsKey('Clean')) { - Remove-Item -Path $ArtifactsFolder -Recurse -Force - New-Item -Path $ArtifactsFolder -ItemType Directory + if ($null -ne (Get-InstalledModule -Name $ModuleName -ErrorAction SilentlyContinue)) { + Uninstall-Module -Name $ModuleName } - Register-PSRepository -Name "$Module-local" -SourceLocation $ArtifactsFolder -InstallationPolicy Trusted + if ($null -ne (Get-PSRepository -Name $repositoryName -ErrorAction SilentlyContinue)) { + Unregister-PSRepository -Name $repositoryName + } + + $artifact = Join-Path -Path $ArtifactsFolder -ChildPath "$($ModuleName).$($version).nupkg" - Publish-Module -Path "$BuildFolder\$Module\$Version" -Repository "$Module-local" -NuGetApiKey 'use real NuGetApiKey for real nuget server here' + if ($PSBoundParameters.ContainsKey('Clean')) { + if ((Test-Path -Path $artifact -ErrorAction SilentlyContinue)) { + Remove-Item -Path $artifact -Force + } + } - # Install-Module -Name "$($Module)" -Repository "$($Module)-local" + Register-PSRepository -Name $repositoryName -SourceLocation $ArtifactsFolder -InstallationPolicy Trusted - # Get-PSRepository + Publish-Module -Path "$BuildFolder\$ModuleName\$version" -Repository $repositoryName -NuGetApiKey 'use real NuGetApiKey for real nuget server here' } @@ -119,13 +124,10 @@ function Uninstall-BuiltModule { [OutputType([System.Void])] param ( [parameter(Mandatory = $true)] - [string]$Module + [string]$ModuleName ) - # $Module = "PSTemplate" - - Uninstall-Module -Name $Module - + Uninstall-Module -Name $ModuleName } @@ -135,15 +137,25 @@ function Unpublish-BuiltModule { [OutputType([System.Void])] param ( [parameter(Mandatory = $true)] - [string]$Module + [string]$ModuleName, + [parameter(Mandatory = $true)] + [string]$SourceFolder, + [parameter(Mandatory = $true)] + [string]$ArtifactsFolder ) - # $Module = 'PSTemplate' + $repositoryName = "$moduleName-local" + + $version = (Import-PowerShellDataFile -Path "$SourceFolder\$ModuleName\$ModuleName.psd1").ModuleVersion - Unregister-PSRepository -Name "$Module-local" + $artifact = Join-Path -Path $ArtifactsFolder -ChildPath "$ModuleName.$version.nupkg" - # Remove-Item -Path "./artifacts" -Recurse -Force + if ((Test-Path -Path $artifact -ErrorAction SilentlyContinue)) { + Remove-Item -Path $artifact -Force + } - # Get-PSRepository + if ($null -ne (Get-PSRepository -Name $repositoryName -ErrorAction SilentlyContinue)) { + Unregister-PSRepository -Name $repositoryName + } } diff --git a/build.ps1 b/build.ps1 index 687fa03..3060845 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,6 +1,12 @@ +[CmdletBinding()] +[OutputType([System.Void])] +param ( + [switch]$Install +) + Import-Module -Name Pester -MinimumVersion 5.1.0 Import-Module -Name Cofl.Util -MinimumVersion 1.2.2 -Import-Module -Name ".\build-functions.psm1" +Import-Module -Name ".\build-functions.psm1" -Force $InformationPreference = 'Continue' $ErrorActionPreference = 'Stop' @@ -30,19 +36,23 @@ $buildFolder = Join-Path -Path "$projectPath" -ChildPath "build" $artifactsFolder = Join-Path -Path "$projectPath" -ChildPath "artifacts" if (-not (Test-Path -Path $artifactsFolder -ErrorAction SilentlyContinue)) { - New-Item -Path $artifactsFolder -ItemType "directory" -force + New-Item -Path $artifactsFolder -ItemType "directory" -Force } if (-not (Test-Path -Path $buildFolder -ErrorAction SilentlyContinue)) { - New-Item -Path $buildFolder -ItemType "directory" -force + New-Item -Path $buildFolder -ItemType "directory" -Force } $modules = Get-ChildItem -Path $sourcePath -Directory -# Create a built version of the module (pre-testing) -# to allow us to use this module (PSQualityCheck) to test itself whist building +Write-Host "BUILD> Build bootstrap version of PSQualityCheck" -ForegroundColor Black -BackgroundColor Gray + +# Create a bootstrap built version of the module (pre-testing) +# to allow us to use this module (PSQualityCheck) to test itself whilst building try { foreach ($module in $modules) { + $repositoryName = "$module-local" + # QUERY: Why not just do Remove-Module -Name $module ? It will do nothing if there is no module loaded ? if ($module -in ((Get-Module) | Select-Object -Property Name)) { Remove-Module $module } @@ -50,22 +60,30 @@ try { $buildPropertiesFile = "$sourcePath\$($module.BaseName)\build.psd1" Write-Host $buildPropertiesFile Build-Module -SourcePath $buildPropertiesFile + + if ($repositoryName -in ((Get-PSRepository) | Select-Object -Property Name)) { + Unregister-PSRepository -Name $repositoryName + } + + Publish-BuiltModule -Module $moduleName -ArtifactsFolder $artifactsFolder -BuildFolder $buildFolder -SourceFolder $sourcePath -Clean + + Install-BuiltModule -Module $moduleName + } } catch { - throw "Build failed" + # try and tidy up? + # foreach ($module in $modules) { + # Uninstall-BuiltModule -Module $module + # Unpublish-BuiltModule -Module $module -SourceFolder $sourcePath -ArtifactsFolder $artifactsFolder + # } + throw "Bootstrap Build failed" break } -if ("$moduleName-local" -in ((Get-PSRepository) | Select-Object -Property Name)) { - unRegister-PSRepository -Name "$moduleName-local" -} - -Publish-BuiltModule -Module $moduleName -ArtifactsFolder $artifactsFolder -BuildFolder $buildFolder -Clean - -Install-BuiltModule -Module $moduleName - # Start of Project Based checks +Write-Host "BUILD> Running PSQualityCheck Project checks" -ForegroundColor Black -BackgroundColor Gray + $qualityCheckSplat = @{ 'ProjectPath' = $projectPath 'ScriptAnalyzerRulesPath' = $ScriptRules @@ -74,128 +92,174 @@ $qualityCheckSplat = @{ 'PesterConfiguration' = $PesterConfiguration 'IgnoreFile' = $ignoreFile } -$qualityResult = Invoke-PSQualityCheck @qualityCheckSplat +$qualityCheckResult = Invoke-PSQualityCheck @qualityCheckSplat # End of Project Based checks +# unpublish and remove the bootstrap version of the modules +Write-Host "BUILD> Uninstall and Unpublish bootstrap modules" -ForegroundColor Black -BackgroundColor Gray +foreach ($module in $modules) { + Uninstall-BuiltModule -Module $module.Name + Unpublish-BuiltModule -Module $module.Name -SourceFolder $sourcePath -ArtifactsFolder $artifactsFolder +} + # Running tests -if ($qualityResult.Script.FailedCount -eq 0 -and $qualityResult.Project.FailedCount -eq 0) { +if ($qualityCheckResult.Script.FailedCount -ne 0 -or $qualityCheckResult.Project.FailedCount -ne 0) { - $testResults = @() + Write-Error -Message "Project quality check failed" - # Run the unit tests for the public functions of any modules in the project +} - # Get the modules (the directories in the Source folder) - $modules = Get-ChildItem -Path $sourcePath -Directory +# Run the unit tests for the public functions of any modules in the project +Write-Host "BUILD> Running unit tests for functions" -ForegroundColor Black -BackgroundColor Gray - foreach ($module in $modules) { +$unitTestResults = @() - # Get the public functions (minus any excluded by the ignore file) - $functionFiles = @() - $functionFiles += Get-FilteredChildItem -Path (Join-Path -Path $module.FullName -ChildPath "public") -IgnoreFileName $ignoreFile +# Get the modules (the directories in the Source folder) +$modules = Get-ChildItem -Path $sourcePath -Directory - # If there are any scripts in the private folder with corresponding tests then run those too - # $privateFunctionFiles += Get-ChildItem -Path (Join-Path -Path $Module.FullName -ChildPath "private") - # Write-Host $privateFunctionFiles.Count -ForegroundColor Yellow - # foreach ($function in $privateFunctionFiles) { - # Write-Host $function.FullName -ForegroundColor Yellow - # if (Test-Path -Path ".\tests\unit\$($module.BaseName)\$($function.BaseName).Tests.ps1") { - # $functionFiles += (Get-ChildItem -Path ".\tests\unit\$($module.BaseName)\$($function.BaseName).Tests.ps1") - # } - # } +foreach ($module in $modules) { - foreach ($function in $functionFiles) { + # Get the public functions (minus any excluded by the ignore file) + $functionFiles = @() + $functionFiles += Get-FilteredChildItem -Path (Join-Path -Path $module.FullName -ChildPath "public") -IgnoreFileName $ignoreFile - $fileContent = Get-FunctionFileContent -Path $function.FullName - . "$($function.FullName)" + # If there are any scripts in the private folder with corresponding tests then run those too + # $privateFunctionFiles += Get-ChildItem -Path (Join-Path -Path $Module.FullName -ChildPath "private") + # Write-Host $privateFunctionFiles.Count -ForegroundColor Yellow + # foreach ($function in $privateFunctionFiles) { + # Write-Host $function.FullName -ForegroundColor Yellow + # if (Test-Path -Path ".\tests\unit\$($module.BaseName)\$($function.BaseName).Tests.ps1") { + # $functionFiles += (Get-ChildItem -Path ".\tests\unit\$($module.BaseName)\$($function.BaseName).Tests.ps1") + # } + # } - $container = New-PesterContainer -Path "$testsPath\unit\$($module.BaseName)\$($function.BaseName).Tests.ps1" -Data @{FileContent = $fileContent } - $PesterConfiguration.Run.Container = $container + foreach ($function in $functionFiles) { - $testResults += Invoke-Pester -Configuration $PesterConfiguration + $fileContent = Get-FunctionFileContent -Path $function.FullName + . "$($function.FullName)" - } - } + $container = New-PesterContainer -Path "$testsPath\unit\$($module.BaseName)\$($function.BaseName).Tests.ps1" -Data @{FileContent = $fileContent } + $PesterConfiguration.Run.Container = $container - # TODO: Add integration tests here + $unitTestResults += Invoke-Pester -Configuration $PesterConfiguration + } } -else { - # Write-Information 'Functions not tested - there were project quality check errors' - # Write-Warning -Message "Project Quality Check fails" - Write-Error -Message "Project quality check failed" - break -} -# End of running tests -# Start of module build -# Build the module(s) only if there are no unit/integration test failures -$testFailedCount = 0 - -foreach ($result in $testResults) { - $testFailedCount += $result.FailedCount +$unitTestFailedCount = 0 +foreach ($result in $unitTestResults) { + $unitTestFailedCount += $result.FailedCount } -if ($testFailedCount -eq 0 ) { - # foreach ($module in $modules) { - # $buildPropertiesFile = ".\source\$($module.BaseName)\build.psd1" - # Build-Module -SourcePath $buildPropertiesFile - # } -} -else { +# Check to see whether the unit tests have failed +if ($unitTestFailedCount -ne 0 ) { Write-Error -Message 'One or more module were not built because there were function unit test errors' throw } -# End of module build + +# TODO: Add integration tests here + + +# End of running tests # Run any available unit tests for files in Scripts folder +Write-Host "BUILD> Running unit tests for scripts" -ForegroundColor Black -BackgroundColor Gray + $scriptFiles = @() -$testResults = @() -$scriptFiles += Get-FilteredChildItem -Path $scriptsPath -IgnoreFileName $ignoreFile +$scriptTestResults = @() +$scriptTestFailedCount = 0 +$scriptFiles = Get-FilteredChildItem -Path $scriptsPath -IgnoreFileName $ignoreFile foreach ($scriptFile in $scriptFiles) { $scriptFolder = $scriptFile.FullName -ireplace [regex]::Escape($scriptsPath.Path), '' $scriptFolder = $scriptFolder -ireplace [regex]::Escape($scriptFile.Name), '' $fileContent = Get-FunctionFileContent -Path $scriptFile.FullName + try { + $testFile = Resolve-Path -Path "$testsPath\scripts$scriptFolder\$($scriptFile.BaseName).Tests.ps1" - $container = New-PesterContainer -Path "$testsPath\scripts$scriptFolder\$($scriptFile.BaseName).Tests.ps1" -Data @{FileContent = $fileContent } - $PesterConfiguration.Run.Container = $container + $container = New-PesterContainer -Path $testFile -Data @{FileContent = $fileContent } + $PesterConfiguration.Run.Container = $container - $testResults += Invoke-Pester -Configuration $PesterConfiguration + $scriptTestResults += Invoke-Pester -Configuration $PesterConfiguration + } + catch { + Write-Output "No test file" + } } -$testFailedCount = 0 - -foreach ($result in $testResults) { - $testFailedCount += $result.FailedCount +foreach ($result in $scriptTestResults) { + $scriptTestFailedCount += $result.FailedCount } +if ($scriptTestFailedCount -ne 0 ) { + Write-Error -Message 'One or more scripts failed unit test' + throw +} +## End of bootstrap build and tests -# If there are no script failures then copy the scripts to the build folder and archive to the Artifacts folder -if ($testFailedCount -eq 0) { - - $builtScriptsFolder = Join-Path -Path $buildFolder -ChildPath "scripts" +# Start of final module build +# Build the module(s) only if there are no unit/integration test failures - if (-not (Test-Path -Path $builtScriptsFolder -ErrorAction SilentlyContinue)) { - New-Item -Path $buildFolder -Name "scripts" -ItemType "directory" -force - } +Write-Host "BUILD> Building final version of module" -ForegroundColor Black -BackgroundColor Gray +try { + foreach ($module in $modules) { - Copy-Item -Path "Scripts" -Destination $buildFolder -Recurse -Force -Container + # QUERY: Why not just do Remove-Module -Name $module ? It will do nothing if there is no module loaded ? + if ($module -in ((Get-Module) | Select-Object -Property Name)) { + Remove-Module $module + } - $compressSplat = @{ - Path = $builtScriptsFolder - CompressionLevel = "Fastest" - DestinationPath = "$artifactsFolder\scripts.zip" + $buildPropertiesFile = "$sourcePath\$($module.BaseName)\build.psd1" + Write-Host $buildPropertiesFile + Build-Module -SourcePath $buildPropertiesFile } - Compress-Archive @compressSplat } -else { - Write-Error -Message "Scripts were not copied to artifacts folder because there were failed unit tests" +catch { + throw "Build failed" break } + +# If there are no script failures then copy the scripts to the build folder and archive to the Artifacts folder +Write-Host "BUILD> Building script archive" -ForegroundColor Black -BackgroundColor Gray +$builtScriptsFolder = Join-Path -Path $buildFolder -ChildPath "scripts" + +if (-not (Test-Path -Path $builtScriptsFolder -ErrorAction SilentlyContinue)) { + New-Item -Path $buildFolder -Name "scripts" -ItemType 'Directory' -Force +} + +Copy-Item -Path "Scripts" -Destination $buildFolder -Recurse -Force -Container # End of script copy -Uninstall-BuiltModule -Module $moduleName -Unpublish-BuiltModule -Module $moduleName +$archiveFile = "$artifactsFolder\scripts.zip" + +if (Test-Path -Path $archiveFile) { + Remove-Item -Path $archiveFile -Force +} +# Create archive of scripts into artifacts +$compressSplat = @{ + Path = $builtScriptsFolder + CompressionLevel = "Fastest" + DestinationPath = "$artifactsFolder\scripts.zip" +} +Compress-Archive @compressSplat +# End of create archive + +# End of final module build + +# Publish the final built modules +foreach ($module in $modules) { + Write-Host "BUILD> Publish final built module: $module" -ForegroundColor Black -BackgroundColor Gray + $repositoryName = "$module-local" + + Publish-BuiltModule -Module $module.Name -ArtifactsFolder $artifactsFolder -BuildFolder $buildFolder -SourceFolder $sourcePath -Clean + + # Optionally install + if ($PSBoundParameters.ContainsKey('Install')) { + Write-Host "BUILD> Install final built module: $module" -ForegroundColor Black -BackgroundColor Gray + Install-BuiltModule -Module $module.Name + } + +} ### END OF SCRIPT From f1917f703317d5dbdc7e9572b7f9e0090ae6f2eb Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Thu, 29 Apr 2021 15:14:18 +0100 Subject: [PATCH 26/27] Fixed throw error messages --- build.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.ps1 b/build.ps1 index 3060845..3b6e67a 100644 --- a/build.ps1 +++ b/build.ps1 @@ -77,7 +77,7 @@ catch { # Uninstall-BuiltModule -Module $module # Unpublish-BuiltModule -Module $module -SourceFolder $sourcePath -ArtifactsFolder $artifactsFolder # } - throw "Bootstrap Build failed" + throw $_ break } @@ -154,7 +154,7 @@ foreach ($result in $unitTestResults) { # Check to see whether the unit tests have failed if ($unitTestFailedCount -ne 0 ) { Write-Error -Message 'One or more module were not built because there were function unit test errors' - throw + throw $_ } # TODO: Add integration tests here @@ -194,7 +194,7 @@ foreach ($result in $scriptTestResults) { } if ($scriptTestFailedCount -ne 0 ) { Write-Error -Message 'One or more scripts failed unit test' - throw + throw $_ } ## End of bootstrap build and tests @@ -216,7 +216,7 @@ try { } } catch { - throw "Build failed" + throw $_ break } From 3048d77a17b539f68413f9652f052ce7a268f91f Mon Sep 17 00:00:00 2001 From: Andrew Davidson Date: Thu, 29 Apr 2021 15:42:10 +0100 Subject: [PATCH 27/27] Updted README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 1c28127..1ff200f 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ ## Summary +### **NEW** PSQualityCheck v2.0.0 and **COMING SOON!** its companion module PSQualityTempate + This is a PowerShell module which runs a series of Pester 5 tests to validate code quality. It uses a combination of Pester tests, PSScriptAnalyzer and a set of quality standards to ensure consistent quality on PowerShell scripts and modules. For more information please see the wiki here [Wiki](https://github.com/andrewrdavidson/PSQualityCheck/wiki)