From 662f05b3c4d324019b97fa9c1ce1c8e86f115e6b Mon Sep 17 00:00:00 2001 From: Johan Ljunggren Date: Mon, 9 Mar 2020 08:58:38 +0100 Subject: [PATCH] Add function Assert-Module (#14) - Added the function `Assert-Module`. - Updated the localized strings to have the unique id according to style guideline. --- CHANGELOG.md | 9 ++++ README.md | 8 ++++ source/Public/Assert-Module.ps1 | 28 +++++++++++++ source/en-US/DscResource.Common.psd1 | 20 +++++---- tests/Unit/Public/Assert-Module.Tests.ps1 | 42 +++++++++++++++++++ .../New-InvalidArgumentException.Tests.ps1 | 4 +- .../New-ObjectNotFoundException.Tests.ps1 | 2 +- 7 files changed, 101 insertions(+), 12 deletions(-) create mode 100644 source/Public/Assert-Module.ps1 create mode 100644 tests/Unit/Public/Assert-Module.Tests.ps1 diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bf04da..b61b961 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Added + +- Added the function `Assert-Module`. + +### Changed + +- Updated the localized strings to have the unique id according to style + guideline. + ## [0.3.0] - 2020-02-15 ### Added diff --git a/README.md b/README.md index a1b947b..0e72300 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,14 @@ describing how to convert a DSC resource module to use DscResource.Common. Refer to the comment-based help for more information about these helper functions. +### `Assert-Module` + +Assert if the specific module is available to be imported. + +```powershell +Assert-Module -ModuleName 'DhcpServer' +``` + ### `Get-LocalizedData` Gets language-specific data into scripts and functions based on the UI culture diff --git a/source/Public/Assert-Module.ps1 b/source/Public/Assert-Module.ps1 new file mode 100644 index 0000000..74f2318 --- /dev/null +++ b/source/Public/Assert-Module.ps1 @@ -0,0 +1,28 @@ +<# + .SYNOPSIS + Assert if the specific module is available to be imported. + + .PARAMETER ModuleName + Specifies the name of the module to assert. + + .EXAMPLE + Assert-Module -ModuleName 'DhcpServer' + + This asserts that the module DhcpServer is available on the system. +#> +function Assert-Module +{ + [CmdletBinding()] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $ModuleName + ) + + if (-not (Get-Module -Name $ModuleName -ListAvailable)) + { + $errorMessage = $script:localizedData.ModuleNotFound -f $ModuleName + New-ObjectNotFoundException -Message $errorMessage + } +} diff --git a/source/en-US/DscResource.Common.psd1 b/source/en-US/DscResource.Common.psd1 index f7ae95a..fb9e404 100644 --- a/source/en-US/DscResource.Common.psd1 +++ b/source/en-US/DscResource.Common.psd1 @@ -1,11 +1,13 @@ +# Localized English (en-US) strings. + ConvertFrom-StringData @' -# English strings - PropertyTypeInvalidForDesiredValues = Property 'DesiredValues' must be either a [System.Collections.Hashtable], [CimInstance] or [PSBoundParametersDictionary]. The type detected was {0}. - PropertyTypeInvalidForValuesToCheck = If 'DesiredValues' is a CimInstance, then property 'ValuesToCheck' must contain a value. - PropertyValidationError = Expected to find an array value for property {0} in the current values, but it was either not present or was null. This has caused the test method to return false. - PropertiesDoesNotMatch = Found an array for property {0} in the current values, but this array does not match the desired state. Details of the changes are below. - PropertyThatDoesNotMatch = {0} - {1} - ValueOfTypeDoesNotMatch = {0} value for property {1} does not match. Current state is '{2}' and desired state is '{3}'. - UnableToCompareProperty = Unable to compare property {0} as the type {1} is not handled by the Test-DscParameterState cmdlet. - TestIsNanoServerOperatingSystemSku = OperatingSystemSKU {0} was returned by Win32_OperatingSystem when detecting if operating system is Nano Server. + PropertyTypeInvalidForDesiredValues = Property 'DesiredValues' must be either a [System.Collections.Hashtable], [CimInstance] or [PSBoundParametersDictionary]. The type detected was {0}. (DRC0001) + PropertyTypeInvalidForValuesToCheck = If 'DesiredValues' is a CimInstance, then property 'ValuesToCheck' must contain a value. (DRC0002) + PropertyValidationError = Expected to find an array value for property {0} in the current values, but it was either not present or was null. This has caused the test method to return false. (DRC0003) + PropertiesDoesNotMatch = Found an array for property {0} in the current values, but this array does not match the desired state. Details of the changes are below. (DRC0004) + PropertyThatDoesNotMatch = {0} - {1} (DRC0005) + ValueOfTypeDoesNotMatch = {0} value for property {1} does not match. Current state is '{2}' and desired state is '{3}'. (DRC0006) + UnableToCompareProperty = Unable to compare property {0} as the type {1} is not handled by the Test-DscParameterState cmdlet. (DRC0007) + TestIsNanoServerOperatingSystemSku = OperatingSystemSKU {0} was returned by Win32_OperatingSystem when detecting if operating system is Nano Server. (DRC0008) + ModuleNotFound = Please ensure that the PowerShell module '{0}' is installed. (DRC0009) '@ diff --git a/tests/Unit/Public/Assert-Module.Tests.ps1 b/tests/Unit/Public/Assert-Module.Tests.ps1 new file mode 100644 index 0000000..591537c --- /dev/null +++ b/tests/Unit/Public/Assert-Module.Tests.ps1 @@ -0,0 +1,42 @@ +$ProjectPath = "$PSScriptRoot\..\..\.." | Convert-Path +$ProjectName = ((Get-ChildItem -Path $ProjectPath\*\*.psd1).Where{ + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try { Test-ModuleManifest -Path $_.FullName -ErrorAction Stop } catch { $false } ) + }).BaseName + + +Import-Module $ProjectName + +InModuleScope $ProjectName { + Describe 'Assert-Module' { + BeforeAll { + $testModuleName = 'TestModule' + } + + Context 'When module is not installed' { + BeforeAll { + Mock -CommandName Get-Module + } + + It 'Should throw the correct error' { + { Assert-Module -ModuleName $testModuleName -Verbose } | ` + Should -Throw ($script:localizedData.RoleNotFound -f $testModuleName) + } + } + + Context 'When module is available' { + BeforeAll { + Mock -CommandName Import-Module + Mock -CommandName Get-Module -MockWith { + return @{ + Name = $testModuleName + } + } + } + + It 'Should not throw an error' { + { Assert-Module -ModuleName $testModuleName -Verbose } | Should -Not -Throw + } + } + } +} diff --git a/tests/Unit/Public/New-InvalidArgumentException.Tests.ps1 b/tests/Unit/Public/New-InvalidArgumentException.Tests.ps1 index 9515b4a..078756d 100644 --- a/tests/Unit/Public/New-InvalidArgumentException.Tests.ps1 +++ b/tests/Unit/Public/New-InvalidArgumentException.Tests.ps1 @@ -5,7 +5,7 @@ $ProjectName = ((Get-ChildItem -Path $ProjectPath\*\*.psd1).Where{ }).BaseName Import-Module $ProjectName -Force -Describe 'DscResource.Common\New-InvalidArgumentException' { +Describe 'New-InvalidArgumentException' { Context 'When calling with both the Message and ArgumentName parameter' { It 'Should throw the correct error' { $mockErrorMessage = 'Mocked error' @@ -16,4 +16,4 @@ Describe 'DscResource.Common\New-InvalidArgumentException' { } Assert-VerifiableMock -} \ No newline at end of file +} diff --git a/tests/Unit/Public/New-ObjectNotFoundException.Tests.ps1 b/tests/Unit/Public/New-ObjectNotFoundException.Tests.ps1 index eead96b..7e8e1fe 100644 --- a/tests/Unit/Public/New-ObjectNotFoundException.Tests.ps1 +++ b/tests/Unit/Public/New-ObjectNotFoundException.Tests.ps1 @@ -6,7 +6,7 @@ $ProjectName = ((Get-ChildItem -Path $ProjectPath\*\*.psd1).Where{ Import-Module $ProjectName -Force -Describe 'DscResource.Common\New-ObjectNotFoundException' { +Describe 'New-ObjectNotFoundException' { Context 'When calling with Message parameter only' { It 'Should throw the correct error' { $mockErrorMessage = 'Mocked error'