diff --git a/.github/workflows/Action-Test-Src-Default.yml b/.github/workflows/Action-Test-Src-Default.yml new file mode 100644 index 0000000..8df1691 --- /dev/null +++ b/.github/workflows/Action-Test-Src-Default.yml @@ -0,0 +1,42 @@ +name: Action-Test [Src-Default] + +run-name: "Action-Test [Src-Default] - ${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }} by @${{ github.actor }}" + +on: [pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: {} + +jobs: + ActionTest: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + shell: [pwsh] + include: + - os: windows-latest + shell: powershell + name: Action-Test [Src-Default] - [${{ matrix.os }}@${{ matrix.shell }}] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Initialize environment + uses: PSModule/Initialize-PSModule@main + with: + Shell: ${{ matrix.shell }} + + - name: Action-Test + uses: ./ + env: + GITHUB_TOKEN: ${{ github.token }} + with: + Name: PSModuleTest + Path: tests/src + Shell: ${{ matrix.shell }} + TestType: SourceCode diff --git a/.github/workflows/Action-Test-Src-UnnamedFolder.yml b/.github/workflows/Action-Test-Src-UnnamedFolder.yml new file mode 100644 index 0000000..dd642a9 --- /dev/null +++ b/.github/workflows/Action-Test-Src-UnnamedFolder.yml @@ -0,0 +1,42 @@ +name: Action-Test [Src-UnnamedFolder] + +run-name: "Action-Test [Src-UnnamedFolder] - ${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }} by @${{ github.actor }}" + +on: [pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: {} + +jobs: + ActionTest: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + shell: [pwsh] + include: + - os: windows-latest + shell: powershell + name: Action-Test [Src-UnnamedFolder] - [${{ matrix.os }}@${{ matrix.shell }}] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Initialize environment + uses: PSModule/Initialize-PSModule@main + with: + Shell: ${{ matrix.shell }} + + - name: Action-Test + uses: ./ + env: + GITHUB_TOKEN: ${{ github.token }} + with: + Name: PSModuleTest + Path: tests/srcNo + Shell: ${{ matrix.shell }} + TestType: SourceCode diff --git a/.github/workflows/Action-Test-Src-UnnamedWithManifest.yml b/.github/workflows/Action-Test-Src-UnnamedWithManifest.yml new file mode 100644 index 0000000..5b2b618 --- /dev/null +++ b/.github/workflows/Action-Test-Src-UnnamedWithManifest.yml @@ -0,0 +1,42 @@ +name: Action-Test [Src-UnnamedWithManifest] + +run-name: "Action-Test [Src-UnnamedWithManifest] - ${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }} by @${{ github.actor }}" + +on: [pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: {} + +jobs: + ActionTest: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + shell: [pwsh] + include: + - os: windows-latest + shell: powershell + name: Action-Test [Src-UnnamedWithManifest] - [${{ matrix.os }}@${{ matrix.shell }}] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Initialize environment + uses: PSModule/Initialize-PSModule@main + with: + Shell: ${{ matrix.shell }} + + - name: Action-Test + uses: ./ + env: + GITHUB_TOKEN: ${{ github.token }} + with: + Name: PSModuleTest + Path: tests/srcNoWithManifest + Shell: ${{ matrix.shell }} + TestType: SourceCode diff --git a/.github/workflows/Action-Test-outputs.yml b/.github/workflows/Action-Test-outputs.yml new file mode 100644 index 0000000..e4b7f09 --- /dev/null +++ b/.github/workflows/Action-Test-outputs.yml @@ -0,0 +1,42 @@ +name: Action-Test [outputs] + +run-name: "Action-Test [outputs] - ${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }} by @${{ github.actor }}" + +on: [pull_request] + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +permissions: {} + +jobs: + ActionTest: + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + shell: [pwsh] + include: + - os: windows-latest + shell: powershell + name: Action-Test [outputs] - [${{ matrix.os }}@${{ matrix.shell }}] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout repo + uses: actions/checkout@v4 + + - name: Initialize environment + uses: PSModule/Initialize-PSModule@main + with: + Shell: ${{ matrix.shell }} + + - name: Action-Test + uses: ./ + env: + GITHUB_TOKEN: ${{ github.token }} + with: + Name: PSModuleTest + Path: tests/outputs/modules + Shell: ${{ matrix.shell }} + TestType: Module diff --git a/.github/workflows/Action-Test.yml b/.github/workflows/Action-Test.yml deleted file mode 100644 index c731640..0000000 --- a/.github/workflows/Action-Test.yml +++ /dev/null @@ -1,70 +0,0 @@ -name: Action-Test - -run-name: "Action-Test - [${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}] by @${{ github.actor }}" - -on: [pull_request] - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -permissions: {} - -jobs: - ActionTest: - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-latest - shell: pwsh - path: tests/src - testtype: SourceCode - - os: ubuntu-latest - shell: pwsh - path: tests/outputs/modules - testtype: Module - - os: macos-latest - shell: pwsh - path: tests/src - testtype: sourcecode - - os: macos-latest - shell: pwsh - path: tests/outputs/modules - testtype: module - - os: windows-latest - shell: pwsh - path: tests/src - testtype: sourcecode - - os: windows-latest - shell: pwsh - path: tests/outputs/modules - testtype: module - - os: windows-latest - shell: powershell - path: tests/src - testtype: sourcecode - - os: windows-latest - shell: powershell - path: tests/outputs/modules - testtype: module - name: Action-Test - [${{ matrix.os }}@${{ matrix.shell }}] - [${{ matrix.path }}] - runs-on: ${{ matrix.os }} - steps: - - name: Checkout repo - uses: actions/checkout@v4 - - - name: Initialize environment - uses: PSModule/Initialize-PSModule@main - with: - Shell: ${{ matrix.shell }} - - - name: Action-Test - uses: ./ - env: - GITHUB_TOKEN: ${{ github.token }} - with: - Name: PSModuleTest - Path: ${{ matrix.path }} - Shell: ${{ matrix.shell }} - TestType: ${{ matrix.TestType }} diff --git a/.github/workflows/Auto-Release.yml b/.github/workflows/Auto-Release.yml index ec157c9..a8f1413 100644 --- a/.github/workflows/Auto-Release.yml +++ b/.github/workflows/Auto-Release.yml @@ -1,6 +1,6 @@ name: Auto-Release -run-name: "Auto-Release - [${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }}] by @${{ github.actor }}" +run-name: "${{ github.event.pull_request.title }} #${{ github.event.pull_request.number }} by @${{ github.actor }}" on: pull_request_target: diff --git a/.github/workflows/Linter.yml b/.github/workflows/Linter.yml index 5c9f300..360331a 100644 --- a/.github/workflows/Linter.yml +++ b/.github/workflows/Linter.yml @@ -27,3 +27,4 @@ jobs: uses: super-linter/super-linter@latest env: GITHUB_TOKEN: ${{ github.token }} + FILTER_REGEX_EXCLUDE: ${{ github.workspace }}/tests diff --git a/scripts/tests/PSScriptAnalyzer/Settings.SourceCode.psd1 b/scripts/tests/PSScriptAnalyzer/Settings.SourceCode.psd1 index bd8fb92..e9081f9 100644 --- a/scripts/tests/PSScriptAnalyzer/Settings.SourceCode.psd1 +++ b/scripts/tests/PSScriptAnalyzer/Settings.SourceCode.psd1 @@ -50,6 +50,7 @@ } } ExcludeRules = @( + 'PSMissingModuleManifestField', # This rule is not applicable until the module is built. 'PSAvoidUsingCmdletAliases', 'PSUseToExportFieldsInManifest' ) diff --git a/tests/src/PSModuleTest/PSModuleTest.psd1 b/tests/src/PSModuleTest/PSModuleTest.psd1 new file mode 100644 index 0000000..466eca8 --- /dev/null +++ b/tests/src/PSModuleTest/PSModuleTest.psd1 @@ -0,0 +1,4 @@ +@{ + ModuleVersion = '0.0.0' + RootModule = 'PSModuleTest.psm1' +} diff --git a/tests/src/PSModuleTest/PSModuleTest.psm1 b/tests/src/PSModuleTest/PSModuleTest.psm1 new file mode 100644 index 0000000..ab67c5e --- /dev/null +++ b/tests/src/PSModuleTest/PSModuleTest.psm1 @@ -0,0 +1,73 @@ +[Cmdletbinding()] +param() + +Write-Verbose 'Importing subcomponents' +$Folders = 'init', 'classes', 'private', 'public' +# Import everything in these folders +Foreach ($Folder in $Folders) { + $Root = Join-Path -Path $PSScriptRoot -ChildPath $Folder + Write-Verbose "Processing folder: $Root" + if (Test-Path -Path $Root) { + Write-Verbose "Getting all files in $Root" + $Files = $null + $Files = Get-ChildItem -Path $Root -Include '*.ps1', '*.psm1' -Recurse + # dot source each file + foreach ($File in $Files) { + Write-Verbose "Importing $($File)" + Import-Module $File + Write-Verbose "Importing $($File): Done" + } + } +} + +. "$PSScriptRoot\finally.ps1" + +# Define the types to export with type accelerators. +$ExportableTypes = @( + [Book] + [BookList] +) + +# Get the internal TypeAccelerators class to use its static methods. +$TypeAcceleratorsClass = [psobject].Assembly.GetType( + 'System.Management.Automation.TypeAccelerators' +) +# Ensure none of the types would clobber an existing type accelerator. +# If a type accelerator with the same name exists, throw an exception. +$ExistingTypeAccelerators = $TypeAcceleratorsClass::Get +foreach ($Type in $ExportableTypes) { + if ($Type.FullName -in $ExistingTypeAccelerators.Keys) { + $Message = @( + "Unable to register type accelerator '$($Type.FullName)'" + 'Accelerator already exists.' + ) -join ' - ' + + throw [System.Management.Automation.ErrorRecord]::new( + [System.InvalidOperationException]::new($Message), + 'TypeAcceleratorAlreadyExists', + [System.Management.Automation.ErrorCategory]::InvalidOperation, + $Type.FullName + ) + } +} +# Add type accelerators for every exportable type. +foreach ($Type in $ExportableTypes) { + $TypeAcceleratorsClass::Add($Type.FullName, $Type) +} +# Remove type accelerators when the module is removed. +$MyInvocation.MyCommand.ScriptBlock.Module.OnRemove = { + foreach ($Type in $ExportableTypes) { + $TypeAcceleratorsClass::Remove($Type.FullName) + } +}.GetNewClosure() + +$Param = @{ + Function = (Get-ChildItem -Path "$PSScriptRoot\public" -Include '*.ps1' -Recurse).BaseName + Variable = '*' + Cmdlet = '*' + Alias = '*' +} + +Write-Verbose 'Exporting module members' + +Export-ModuleMember @Param diff --git a/tests/src/assemblies/LsonLib.dll b/tests/src/PSModuleTest/assemblies/LsonLib.dll similarity index 100% rename from tests/src/assemblies/LsonLib.dll rename to tests/src/PSModuleTest/assemblies/LsonLib.dll diff --git a/tests/src/classes/Book.ps1 b/tests/src/PSModuleTest/classes/Book.ps1 similarity index 100% rename from tests/src/classes/Book.ps1 rename to tests/src/PSModuleTest/classes/Book.ps1 diff --git a/tests/src/data/Config.psd1 b/tests/src/PSModuleTest/data/Config.psd1 similarity index 100% rename from tests/src/data/Config.psd1 rename to tests/src/PSModuleTest/data/Config.psd1 diff --git a/tests/src/data/Settings.psd1 b/tests/src/PSModuleTest/data/Settings.psd1 similarity index 100% rename from tests/src/data/Settings.psd1 rename to tests/src/PSModuleTest/data/Settings.psd1 diff --git a/tests/src/PSModuleTest/finally.ps1 b/tests/src/PSModuleTest/finally.ps1 new file mode 100644 index 0000000..3911a3e --- /dev/null +++ b/tests/src/PSModuleTest/finally.ps1 @@ -0,0 +1,5 @@ +Write-Verbose '------------------------------' -Verbose +Write-Verbose '--- THIS IS A LAST LOADER ---' -Verbose +Write-Verbose '------------------------------' -Verbose + +$MyInvocation | ConvertTo-Json diff --git a/tests/src/formats/CultureInfo.Format.ps1xml b/tests/src/PSModuleTest/formats/CultureInfo.Format.ps1xml similarity index 100% rename from tests/src/formats/CultureInfo.Format.ps1xml rename to tests/src/PSModuleTest/formats/CultureInfo.Format.ps1xml diff --git a/tests/src/formats/Mygciview.Format.ps1xml b/tests/src/PSModuleTest/formats/Mygciview.Format.ps1xml similarity index 100% rename from tests/src/formats/Mygciview.Format.ps1xml rename to tests/src/PSModuleTest/formats/Mygciview.Format.ps1xml diff --git a/tests/src/header.ps1 b/tests/src/PSModuleTest/header.ps1 similarity index 100% rename from tests/src/header.ps1 rename to tests/src/PSModuleTest/header.ps1 diff --git a/tests/src/PSModuleTest/init/initializer.ps1 b/tests/src/PSModuleTest/init/initializer.ps1 new file mode 100644 index 0000000..f1ea638 --- /dev/null +++ b/tests/src/PSModuleTest/init/initializer.ps1 @@ -0,0 +1,5 @@ +Write-Verbose '-------------------------------' -Verbose +Write-Verbose '--- THIS IS AN INITIALIZER ---' -Verbose +Write-Verbose '-------------------------------' -Verbose + +$MyInvocation | ConvertTo-Json diff --git a/tests/src/modules/OtherPSModule.psm1 b/tests/src/PSModuleTest/modules/OtherPSModule.psm1 similarity index 100% rename from tests/src/modules/OtherPSModule.psm1 rename to tests/src/PSModuleTest/modules/OtherPSModule.psm1 diff --git a/tests/src/private/Get-InternalPSModule.ps1 b/tests/src/PSModuleTest/private/Get-InternalPSModule.ps1 similarity index 100% rename from tests/src/private/Get-InternalPSModule.ps1 rename to tests/src/PSModuleTest/private/Get-InternalPSModule.ps1 diff --git a/tests/src/private/Set-InternalPSModule.ps1 b/tests/src/PSModuleTest/private/Set-InternalPSModule.ps1 similarity index 100% rename from tests/src/private/Set-InternalPSModule.ps1 rename to tests/src/PSModuleTest/private/Set-InternalPSModule.ps1 diff --git a/tests/src/public/Get-PSModuleTest.ps1 b/tests/src/PSModuleTest/public/Get-PSModuleTest.ps1 similarity index 100% rename from tests/src/public/Get-PSModuleTest.ps1 rename to tests/src/PSModuleTest/public/Get-PSModuleTest.ps1 diff --git a/tests/src/PSModuleTest/public/New-PSModuleTest.ps1 b/tests/src/PSModuleTest/public/New-PSModuleTest.ps1 new file mode 100644 index 0000000..d97e8f3 --- /dev/null +++ b/tests/src/PSModuleTest/public/New-PSModuleTest.ps1 @@ -0,0 +1,29 @@ +#Requires -Modules @{ModuleName='PSSemVer'; ModuleVersion='1.0'} + +function New-PSModuleTest { + <# + .SYNOPSIS + Performs tests on a module. + + .EXAMPLE + Test-PSModule -Name 'World' + + "Hello, World!" + + .NOTES + Testing if a module can have a [Markdown based link](https://example.com). + !"#¤%&/()=?`´^¨*'-_+§½{[]}<>|@£$€¥¢:;.," + \[This is a test\] + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseShouldProcessForStateChangingFunctions', '', Scope = 'Function', + Justification = 'Reason for suppressing' + )] + [CmdletBinding()] + param ( + # Name of the person to greet. + [Parameter(Mandatory)] + [string] $Name + ) + Write-Output "Hello, $Name!" +} diff --git a/tests/src/public/Set-PSModuleTest.ps1 b/tests/src/PSModuleTest/public/Set-PSModuleTest.ps1 similarity index 100% rename from tests/src/public/Set-PSModuleTest.ps1 rename to tests/src/PSModuleTest/public/Set-PSModuleTest.ps1 diff --git a/tests/src/public/Test-PSModuleTest.ps1 b/tests/src/PSModuleTest/public/Test-PSModuleTest.ps1 similarity index 100% rename from tests/src/public/Test-PSModuleTest.ps1 rename to tests/src/PSModuleTest/public/Test-PSModuleTest.ps1 diff --git a/tests/src/PSModuleTest/scripts/loader.ps1 b/tests/src/PSModuleTest/scripts/loader.ps1 new file mode 100644 index 0000000..5fe652a --- /dev/null +++ b/tests/src/PSModuleTest/scripts/loader.ps1 @@ -0,0 +1,5 @@ +Write-Verbose '-------------------------' -Verbose +Write-Verbose '--- THIS IS A LOADER ---' -Verbose +Write-Verbose '-------------------------' -Verbose + +$MyInvocation | ConvertTo-Json diff --git a/tests/src/types/DirectoryInfo.Types.ps1xml b/tests/src/PSModuleTest/types/DirectoryInfo.Types.ps1xml similarity index 100% rename from tests/src/types/DirectoryInfo.Types.ps1xml rename to tests/src/PSModuleTest/types/DirectoryInfo.Types.ps1xml diff --git a/tests/src/types/FileInfo.Types.ps1xml b/tests/src/PSModuleTest/types/FileInfo.Types.ps1xml similarity index 100% rename from tests/src/types/FileInfo.Types.ps1xml rename to tests/src/PSModuleTest/types/FileInfo.Types.ps1xml diff --git a/tests/srcNo/assemblies/LsonLib.dll b/tests/srcNo/assemblies/LsonLib.dll new file mode 100644 index 0000000..3661807 Binary files /dev/null and b/tests/srcNo/assemblies/LsonLib.dll differ diff --git a/tests/srcNo/classes/Book.ps1 b/tests/srcNo/classes/Book.ps1 new file mode 100644 index 0000000..3e22c27 --- /dev/null +++ b/tests/srcNo/classes/Book.ps1 @@ -0,0 +1,132 @@ +class Book { + # Class properties + [string] $Title + [string] $Author + [string] $Synopsis + [string] $Publisher + [datetime] $PublishDate + [int] $PageCount + [string[]] $Tags + # Default constructor + Book() { $this.Init(@{}) } + # Convenience constructor from hashtable + Book([hashtable]$Properties) { $this.Init($Properties) } + # Common constructor for title and author + Book([string]$Title, [string]$Author) { + $this.Init(@{Title = $Title; Author = $Author }) + } + # Shared initializer method + [void] Init([hashtable]$Properties) { + foreach ($Property in $Properties.Keys) { + $this.$Property = $Properties.$Property + } + } + # Method to calculate reading time as 2 minutes per page + [timespan] GetReadingTime() { + if ($this.PageCount -le 0) { + throw 'Unable to determine reading time from page count.' + } + $Minutes = $this.PageCount * 2 + return [timespan]::new(0, $Minutes, 0) + } + # Method to calculate how long ago a book was published + [timespan] GetPublishedAge() { + if ( + $null -eq $this.PublishDate -or + $this.PublishDate -eq [datetime]::MinValue + ) { throw 'PublishDate not defined' } + + return (Get-Date) - $this.PublishDate + } + # Method to return a string representation of the book + [string] ToString() { + return "$($this.Title) by $($this.Author) ($($this.PublishDate.Year))" + } +} + +class BookList { + # Static property to hold the list of books + static [System.Collections.Generic.List[Book]] $Books + # Static method to initialize the list of books. Called in the other + # static methods to avoid needing to explicit initialize the value. + static [void] Initialize() { [BookList]::Initialize($false) } + static [bool] Initialize([bool]$force) { + if ([BookList]::Books.Count -gt 0 -and -not $force) { + return $false + } + + [BookList]::Books = [System.Collections.Generic.List[Book]]::new() + + return $true + } + # Ensure a book is valid for the list. + static [void] Validate([book]$Book) { + $Prefix = @( + 'Book validation failed: Book must be defined with the Title,' + 'Author, and PublishDate properties, but' + ) -join ' ' + if ($null -eq $Book) { throw "$Prefix was null" } + if ([string]::IsNullOrEmpty($Book.Title)) { + throw "$Prefix Title wasn't defined" + } + if ([string]::IsNullOrEmpty($Book.Author)) { + throw "$Prefix Author wasn't defined" + } + if ([datetime]::MinValue -eq $Book.PublishDate) { + throw "$Prefix PublishDate wasn't defined" + } + } + # Static methods to manage the list of books. + # Add a book if it's not already in the list. + static [void] Add([Book]$Book) { + [BookList]::Initialize() + [BookList]::Validate($Book) + if ([BookList]::Books.Contains($Book)) { + throw "Book '$Book' already in list" + } + + $FindPredicate = { + param([Book]$b) + + $b.Title -eq $Book.Title -and + $b.Author -eq $Book.Author -and + $b.PublishDate -eq $Book.PublishDate + }.GetNewClosure() + if ([BookList]::Books.Find($FindPredicate)) { + throw "Book '$Book' already in list" + } + + [BookList]::Books.Add($Book) + } + # Clear the list of books. + static [void] Clear() { + [BookList]::Initialize() + [BookList]::Books.Clear() + } + # Find a specific book using a filtering scriptblock. + static [Book] Find([scriptblock]$Predicate) { + [BookList]::Initialize() + return [BookList]::Books.Find($Predicate) + } + # Find every book matching the filtering scriptblock. + static [Book[]] FindAll([scriptblock]$Predicate) { + [BookList]::Initialize() + return [BookList]::Books.FindAll($Predicate) + } + # Remove a specific book. + static [void] Remove([Book]$Book) { + [BookList]::Initialize() + [BookList]::Books.Remove($Book) + } + # Remove a book by property value. + static [void] RemoveBy([string]$Property, [string]$Value) { + [BookList]::Initialize() + $Index = [BookList]::Books.FindIndex({ + param($b) + $b.$Property -eq $Value + }.GetNewClosure()) + if ($Index -ge 0) { + [BookList]::Books.RemoveAt($Index) + } + } +} diff --git a/tests/srcNo/data/Config.psd1 b/tests/srcNo/data/Config.psd1 new file mode 100644 index 0000000..fea4466 --- /dev/null +++ b/tests/srcNo/data/Config.psd1 @@ -0,0 +1,3 @@ +@{ + RandomKey = 'RandomValue' +} diff --git a/tests/srcNo/data/Settings.psd1 b/tests/srcNo/data/Settings.psd1 new file mode 100644 index 0000000..bcfa7b4 --- /dev/null +++ b/tests/srcNo/data/Settings.psd1 @@ -0,0 +1,3 @@ +@{ + RandomSetting = 'RandomSettingValue' +} diff --git a/tests/src/finally.ps1 b/tests/srcNo/finally.ps1 similarity index 100% rename from tests/src/finally.ps1 rename to tests/srcNo/finally.ps1 diff --git a/tests/srcNo/formats/CultureInfo.Format.ps1xml b/tests/srcNo/formats/CultureInfo.Format.ps1xml new file mode 100644 index 0000000..a715e08 --- /dev/null +++ b/tests/srcNo/formats/CultureInfo.Format.ps1xml @@ -0,0 +1,37 @@ + + + + + System.Globalization.CultureInfo + + System.Globalization.CultureInfo + + + + + 16 + + + 16 + + + + + + + + LCID + + + Name + + + DisplayName + + + + + + + + diff --git a/tests/srcNo/formats/Mygciview.Format.ps1xml b/tests/srcNo/formats/Mygciview.Format.ps1xml new file mode 100644 index 0000000..4c972c2 --- /dev/null +++ b/tests/srcNo/formats/Mygciview.Format.ps1xml @@ -0,0 +1,65 @@ + + + + + mygciview + + System.IO.DirectoryInfo + System.IO.FileInfo + + + PSParentPath + + + + + + 7 + Left + + + + 26 + Right + + + + 26 + Right + + + + 14 + Right + + + + Left + + + + + + + + ModeWithoutHardLink + + + LastWriteTime + + + CreationTime + + + Length + + + Name + + + + + + + + diff --git a/tests/srcNo/header.ps1 b/tests/srcNo/header.ps1 new file mode 100644 index 0000000..cc1fde9 --- /dev/null +++ b/tests/srcNo/header.ps1 @@ -0,0 +1,3 @@ +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains long links.')] +[CmdletBinding()] +param() diff --git a/tests/src/init/initializer.ps1 b/tests/srcNo/init/initializer.ps1 similarity index 100% rename from tests/src/init/initializer.ps1 rename to tests/srcNo/init/initializer.ps1 diff --git a/tests/srcNo/modules/OtherPSModule.psm1 b/tests/srcNo/modules/OtherPSModule.psm1 new file mode 100644 index 0000000..9e4353b --- /dev/null +++ b/tests/srcNo/modules/OtherPSModule.psm1 @@ -0,0 +1,19 @@ +Function Get-OtherPSModule { + <# + .SYNOPSIS + Performs tests on a module. + + .DESCRIPTION + A longer description of the function. + + .EXAMPLE + Get-OtherPSModule -Name 'World' + #> + [CmdletBinding()] + param( + # Name of the person to greet. + [Parameter(Mandatory)] + [string] $Name + ) + Write-Output "Hello, $Name!" +} diff --git a/tests/srcNo/private/Get-InternalPSModule.ps1 b/tests/srcNo/private/Get-InternalPSModule.ps1 new file mode 100644 index 0000000..3366e44 --- /dev/null +++ b/tests/srcNo/private/Get-InternalPSModule.ps1 @@ -0,0 +1,18 @@ +Function Get-InternalPSModule { + <# + .SYNOPSIS + Performs tests on a module. + + .EXAMPLE + Test-PSModule -Name 'World' + + "Hello, World!" + #> + [CmdletBinding()] + param ( + # Name of the person to greet. + [Parameter(Mandatory)] + [string] $Name + ) + Write-Output "Hello, $Name!" +} diff --git a/tests/src/public/New-PSModuleTest.ps1 b/tests/srcNo/private/Set-InternalPSModule.ps1 similarity index 83% rename from tests/src/public/New-PSModuleTest.ps1 rename to tests/srcNo/private/Set-InternalPSModule.ps1 index 7f26215..11c2fa1 100644 --- a/tests/src/public/New-PSModuleTest.ps1 +++ b/tests/srcNo/private/Set-InternalPSModule.ps1 @@ -1,6 +1,4 @@ -#Requires -Modules @{ModuleName='PSSemVer'; ModuleVersion='1.0'} - -function New-PSModuleTest { +Function Set-InternalPSModule { <# .SYNOPSIS Performs tests on a module. diff --git a/tests/srcNo/public/Get-PSModuleTest.ps1 b/tests/srcNo/public/Get-PSModuleTest.ps1 new file mode 100644 index 0000000..0e9aacf --- /dev/null +++ b/tests/srcNo/public/Get-PSModuleTest.ps1 @@ -0,0 +1,20 @@ +#Requires -Modules Utilities + +function Get-PSModuleTest { + <# + .SYNOPSIS + Performs tests on a module. + + .EXAMPLE + Test-PSModule -Name 'World' + + "Hello, World!" + #> + [CmdletBinding()] + param ( + # Name of the person to greet. + [Parameter(Mandatory)] + [string] $Name + ) + Write-Output "Hello, $Name!" +} diff --git a/tests/srcNo/public/New-PSModuleTest.ps1 b/tests/srcNo/public/New-PSModuleTest.ps1 new file mode 100644 index 0000000..d97e8f3 --- /dev/null +++ b/tests/srcNo/public/New-PSModuleTest.ps1 @@ -0,0 +1,29 @@ +#Requires -Modules @{ModuleName='PSSemVer'; ModuleVersion='1.0'} + +function New-PSModuleTest { + <# + .SYNOPSIS + Performs tests on a module. + + .EXAMPLE + Test-PSModule -Name 'World' + + "Hello, World!" + + .NOTES + Testing if a module can have a [Markdown based link](https://example.com). + !"#¤%&/()=?`´^¨*'-_+§½{[]}<>|@£$€¥¢:;.," + \[This is a test\] + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseShouldProcessForStateChangingFunctions', '', Scope = 'Function', + Justification = 'Reason for suppressing' + )] + [CmdletBinding()] + param ( + # Name of the person to greet. + [Parameter(Mandatory)] + [string] $Name + ) + Write-Output "Hello, $Name!" +} diff --git a/tests/srcNo/public/Set-PSModuleTest.ps1 b/tests/srcNo/public/Set-PSModuleTest.ps1 new file mode 100644 index 0000000..a87ac11 --- /dev/null +++ b/tests/srcNo/public/Set-PSModuleTest.ps1 @@ -0,0 +1,22 @@ +function Set-PSModuleTest { + <# + .SYNOPSIS + Performs tests on a module. + + .EXAMPLE + Test-PSModule -Name 'World' + + "Hello, World!" + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseShouldProcessForStateChangingFunctions', '', Scope = 'Function', + Justification = 'Reason for suppressing' + )] + [CmdletBinding()] + param ( + # Name of the person to greet. + [Parameter(Mandatory)] + [string] $Name + ) + Write-Output "Hello, $Name!" +} diff --git a/tests/srcNo/public/Test-PSModuleTest.ps1 b/tests/srcNo/public/Test-PSModuleTest.ps1 new file mode 100644 index 0000000..26be2b9 --- /dev/null +++ b/tests/srcNo/public/Test-PSModuleTest.ps1 @@ -0,0 +1,18 @@ +function Test-PSModuleTest { + <# + .SYNOPSIS + Performs tests on a module. + + .EXAMPLE + Test-PSModule -Name 'World' + + "Hello, World!" + #> + [CmdletBinding()] + param ( + # Name of the person to greet. + [Parameter(Mandatory)] + [string] $Name + ) + Write-Output "Hello, $Name!" +} diff --git a/tests/src/scripts/loader.ps1 b/tests/srcNo/scripts/loader.ps1 similarity index 100% rename from tests/src/scripts/loader.ps1 rename to tests/srcNo/scripts/loader.ps1 diff --git a/tests/srcNo/types/DirectoryInfo.Types.ps1xml b/tests/srcNo/types/DirectoryInfo.Types.ps1xml new file mode 100644 index 0000000..aef538b --- /dev/null +++ b/tests/srcNo/types/DirectoryInfo.Types.ps1xml @@ -0,0 +1,21 @@ + + + + System.IO.FileInfo + + + Status + Success + + + + + System.IO.DirectoryInfo + + + Status + Success + + + + diff --git a/tests/srcNo/types/FileInfo.Types.ps1xml b/tests/srcNo/types/FileInfo.Types.ps1xml new file mode 100644 index 0000000..4cfaf6b --- /dev/null +++ b/tests/srcNo/types/FileInfo.Types.ps1xml @@ -0,0 +1,14 @@ + + + + System.IO.FileInfo + + + Age + + ((Get-Date) - ($this.CreationTime)).Days + + + + + diff --git a/tests/srcNoWithManifest/Manifest.psd1 b/tests/srcNoWithManifest/Manifest.psd1 new file mode 100644 index 0000000..77348f1 --- /dev/null +++ b/tests/srcNoWithManifest/Manifest.psd1 @@ -0,0 +1,3 @@ +@{ + Author = 'Author' +} diff --git a/tests/srcNoWithManifest/assemblies/LsonLib.dll b/tests/srcNoWithManifest/assemblies/LsonLib.dll new file mode 100644 index 0000000..3661807 Binary files /dev/null and b/tests/srcNoWithManifest/assemblies/LsonLib.dll differ diff --git a/tests/srcNoWithManifest/classes/Book.ps1 b/tests/srcNoWithManifest/classes/Book.ps1 new file mode 100644 index 0000000..3e22c27 --- /dev/null +++ b/tests/srcNoWithManifest/classes/Book.ps1 @@ -0,0 +1,132 @@ +class Book { + # Class properties + [string] $Title + [string] $Author + [string] $Synopsis + [string] $Publisher + [datetime] $PublishDate + [int] $PageCount + [string[]] $Tags + # Default constructor + Book() { $this.Init(@{}) } + # Convenience constructor from hashtable + Book([hashtable]$Properties) { $this.Init($Properties) } + # Common constructor for title and author + Book([string]$Title, [string]$Author) { + $this.Init(@{Title = $Title; Author = $Author }) + } + # Shared initializer method + [void] Init([hashtable]$Properties) { + foreach ($Property in $Properties.Keys) { + $this.$Property = $Properties.$Property + } + } + # Method to calculate reading time as 2 minutes per page + [timespan] GetReadingTime() { + if ($this.PageCount -le 0) { + throw 'Unable to determine reading time from page count.' + } + $Minutes = $this.PageCount * 2 + return [timespan]::new(0, $Minutes, 0) + } + # Method to calculate how long ago a book was published + [timespan] GetPublishedAge() { + if ( + $null -eq $this.PublishDate -or + $this.PublishDate -eq [datetime]::MinValue + ) { throw 'PublishDate not defined' } + + return (Get-Date) - $this.PublishDate + } + # Method to return a string representation of the book + [string] ToString() { + return "$($this.Title) by $($this.Author) ($($this.PublishDate.Year))" + } +} + +class BookList { + # Static property to hold the list of books + static [System.Collections.Generic.List[Book]] $Books + # Static method to initialize the list of books. Called in the other + # static methods to avoid needing to explicit initialize the value. + static [void] Initialize() { [BookList]::Initialize($false) } + static [bool] Initialize([bool]$force) { + if ([BookList]::Books.Count -gt 0 -and -not $force) { + return $false + } + + [BookList]::Books = [System.Collections.Generic.List[Book]]::new() + + return $true + } + # Ensure a book is valid for the list. + static [void] Validate([book]$Book) { + $Prefix = @( + 'Book validation failed: Book must be defined with the Title,' + 'Author, and PublishDate properties, but' + ) -join ' ' + if ($null -eq $Book) { throw "$Prefix was null" } + if ([string]::IsNullOrEmpty($Book.Title)) { + throw "$Prefix Title wasn't defined" + } + if ([string]::IsNullOrEmpty($Book.Author)) { + throw "$Prefix Author wasn't defined" + } + if ([datetime]::MinValue -eq $Book.PublishDate) { + throw "$Prefix PublishDate wasn't defined" + } + } + # Static methods to manage the list of books. + # Add a book if it's not already in the list. + static [void] Add([Book]$Book) { + [BookList]::Initialize() + [BookList]::Validate($Book) + if ([BookList]::Books.Contains($Book)) { + throw "Book '$Book' already in list" + } + + $FindPredicate = { + param([Book]$b) + + $b.Title -eq $Book.Title -and + $b.Author -eq $Book.Author -and + $b.PublishDate -eq $Book.PublishDate + }.GetNewClosure() + if ([BookList]::Books.Find($FindPredicate)) { + throw "Book '$Book' already in list" + } + + [BookList]::Books.Add($Book) + } + # Clear the list of books. + static [void] Clear() { + [BookList]::Initialize() + [BookList]::Books.Clear() + } + # Find a specific book using a filtering scriptblock. + static [Book] Find([scriptblock]$Predicate) { + [BookList]::Initialize() + return [BookList]::Books.Find($Predicate) + } + # Find every book matching the filtering scriptblock. + static [Book[]] FindAll([scriptblock]$Predicate) { + [BookList]::Initialize() + return [BookList]::Books.FindAll($Predicate) + } + # Remove a specific book. + static [void] Remove([Book]$Book) { + [BookList]::Initialize() + [BookList]::Books.Remove($Book) + } + # Remove a book by property value. + static [void] RemoveBy([string]$Property, [string]$Value) { + [BookList]::Initialize() + $Index = [BookList]::Books.FindIndex({ + param($b) + $b.$Property -eq $Value + }.GetNewClosure()) + if ($Index -ge 0) { + [BookList]::Books.RemoveAt($Index) + } + } +} diff --git a/tests/srcNoWithManifest/data/Config.psd1 b/tests/srcNoWithManifest/data/Config.psd1 new file mode 100644 index 0000000..fea4466 --- /dev/null +++ b/tests/srcNoWithManifest/data/Config.psd1 @@ -0,0 +1,3 @@ +@{ + RandomKey = 'RandomValue' +} diff --git a/tests/srcNoWithManifest/data/Settings.psd1 b/tests/srcNoWithManifest/data/Settings.psd1 new file mode 100644 index 0000000..bcfa7b4 --- /dev/null +++ b/tests/srcNoWithManifest/data/Settings.psd1 @@ -0,0 +1,3 @@ +@{ + RandomSetting = 'RandomSettingValue' +} diff --git a/tests/srcNoWithManifest/finally.ps1 b/tests/srcNoWithManifest/finally.ps1 new file mode 100644 index 0000000..e51c226 --- /dev/null +++ b/tests/srcNoWithManifest/finally.ps1 @@ -0,0 +1,3 @@ +Write-Verbose '------------------------------' -Verbose +Write-Verbose '--- THIS IS A LAST LOADER ---' -Verbose +Write-Verbose '------------------------------' -Verbose diff --git a/tests/srcNoWithManifest/formats/CultureInfo.Format.ps1xml b/tests/srcNoWithManifest/formats/CultureInfo.Format.ps1xml new file mode 100644 index 0000000..a715e08 --- /dev/null +++ b/tests/srcNoWithManifest/formats/CultureInfo.Format.ps1xml @@ -0,0 +1,37 @@ + + + + + System.Globalization.CultureInfo + + System.Globalization.CultureInfo + + + + + 16 + + + 16 + + + + + + + + LCID + + + Name + + + DisplayName + + + + + + + + diff --git a/tests/srcNoWithManifest/formats/Mygciview.Format.ps1xml b/tests/srcNoWithManifest/formats/Mygciview.Format.ps1xml new file mode 100644 index 0000000..4c972c2 --- /dev/null +++ b/tests/srcNoWithManifest/formats/Mygciview.Format.ps1xml @@ -0,0 +1,65 @@ + + + + + mygciview + + System.IO.DirectoryInfo + System.IO.FileInfo + + + PSParentPath + + + + + + 7 + Left + + + + 26 + Right + + + + 26 + Right + + + + 14 + Right + + + + Left + + + + + + + + ModeWithoutHardLink + + + LastWriteTime + + + CreationTime + + + Length + + + Name + + + + + + + + diff --git a/tests/srcNoWithManifest/header.ps1 b/tests/srcNoWithManifest/header.ps1 new file mode 100644 index 0000000..cc1fde9 --- /dev/null +++ b/tests/srcNoWithManifest/header.ps1 @@ -0,0 +1,3 @@ +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidLongLines', '', Justification = 'Contains long links.')] +[CmdletBinding()] +param() diff --git a/tests/srcNoWithManifest/init/initializer.ps1 b/tests/srcNoWithManifest/init/initializer.ps1 new file mode 100644 index 0000000..f4121d2 --- /dev/null +++ b/tests/srcNoWithManifest/init/initializer.ps1 @@ -0,0 +1,3 @@ +Write-Verbose '-------------------------------' -Verbose +Write-Verbose '--- THIS IS AN INITIALIZER ---' -Verbose +Write-Verbose '-------------------------------' -Verbose diff --git a/tests/srcNoWithManifest/modules/OtherPSModule.psm1 b/tests/srcNoWithManifest/modules/OtherPSModule.psm1 new file mode 100644 index 0000000..9e4353b --- /dev/null +++ b/tests/srcNoWithManifest/modules/OtherPSModule.psm1 @@ -0,0 +1,19 @@ +Function Get-OtherPSModule { + <# + .SYNOPSIS + Performs tests on a module. + + .DESCRIPTION + A longer description of the function. + + .EXAMPLE + Get-OtherPSModule -Name 'World' + #> + [CmdletBinding()] + param( + # Name of the person to greet. + [Parameter(Mandatory)] + [string] $Name + ) + Write-Output "Hello, $Name!" +} diff --git a/tests/srcNoWithManifest/private/Get-InternalPSModule.ps1 b/tests/srcNoWithManifest/private/Get-InternalPSModule.ps1 new file mode 100644 index 0000000..3366e44 --- /dev/null +++ b/tests/srcNoWithManifest/private/Get-InternalPSModule.ps1 @@ -0,0 +1,18 @@ +Function Get-InternalPSModule { + <# + .SYNOPSIS + Performs tests on a module. + + .EXAMPLE + Test-PSModule -Name 'World' + + "Hello, World!" + #> + [CmdletBinding()] + param ( + # Name of the person to greet. + [Parameter(Mandatory)] + [string] $Name + ) + Write-Output "Hello, $Name!" +} diff --git a/tests/srcNoWithManifest/private/Set-InternalPSModule.ps1 b/tests/srcNoWithManifest/private/Set-InternalPSModule.ps1 new file mode 100644 index 0000000..11c2fa1 --- /dev/null +++ b/tests/srcNoWithManifest/private/Set-InternalPSModule.ps1 @@ -0,0 +1,22 @@ +Function Set-InternalPSModule { + <# + .SYNOPSIS + Performs tests on a module. + + .EXAMPLE + Test-PSModule -Name 'World' + + "Hello, World!" + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseShouldProcessForStateChangingFunctions', '', Scope = 'Function', + Justification = 'Reason for suppressing' + )] + [CmdletBinding()] + param ( + # Name of the person to greet. + [Parameter(Mandatory)] + [string] $Name + ) + Write-Output "Hello, $Name!" +} diff --git a/tests/srcNoWithManifest/public/Get-PSModuleTest.ps1 b/tests/srcNoWithManifest/public/Get-PSModuleTest.ps1 new file mode 100644 index 0000000..0e9aacf --- /dev/null +++ b/tests/srcNoWithManifest/public/Get-PSModuleTest.ps1 @@ -0,0 +1,20 @@ +#Requires -Modules Utilities + +function Get-PSModuleTest { + <# + .SYNOPSIS + Performs tests on a module. + + .EXAMPLE + Test-PSModule -Name 'World' + + "Hello, World!" + #> + [CmdletBinding()] + param ( + # Name of the person to greet. + [Parameter(Mandatory)] + [string] $Name + ) + Write-Output "Hello, $Name!" +} diff --git a/tests/srcNoWithManifest/public/New-PSModuleTest.ps1 b/tests/srcNoWithManifest/public/New-PSModuleTest.ps1 new file mode 100644 index 0000000..d97e8f3 --- /dev/null +++ b/tests/srcNoWithManifest/public/New-PSModuleTest.ps1 @@ -0,0 +1,29 @@ +#Requires -Modules @{ModuleName='PSSemVer'; ModuleVersion='1.0'} + +function New-PSModuleTest { + <# + .SYNOPSIS + Performs tests on a module. + + .EXAMPLE + Test-PSModule -Name 'World' + + "Hello, World!" + + .NOTES + Testing if a module can have a [Markdown based link](https://example.com). + !"#¤%&/()=?`´^¨*'-_+§½{[]}<>|@£$€¥¢:;.," + \[This is a test\] + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseShouldProcessForStateChangingFunctions', '', Scope = 'Function', + Justification = 'Reason for suppressing' + )] + [CmdletBinding()] + param ( + # Name of the person to greet. + [Parameter(Mandatory)] + [string] $Name + ) + Write-Output "Hello, $Name!" +} diff --git a/tests/srcNoWithManifest/public/Set-PSModuleTest.ps1 b/tests/srcNoWithManifest/public/Set-PSModuleTest.ps1 new file mode 100644 index 0000000..a87ac11 --- /dev/null +++ b/tests/srcNoWithManifest/public/Set-PSModuleTest.ps1 @@ -0,0 +1,22 @@ +function Set-PSModuleTest { + <# + .SYNOPSIS + Performs tests on a module. + + .EXAMPLE + Test-PSModule -Name 'World' + + "Hello, World!" + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSUseShouldProcessForStateChangingFunctions', '', Scope = 'Function', + Justification = 'Reason for suppressing' + )] + [CmdletBinding()] + param ( + # Name of the person to greet. + [Parameter(Mandatory)] + [string] $Name + ) + Write-Output "Hello, $Name!" +} diff --git a/tests/srcNoWithManifest/public/Test-PSModuleTest.ps1 b/tests/srcNoWithManifest/public/Test-PSModuleTest.ps1 new file mode 100644 index 0000000..26be2b9 --- /dev/null +++ b/tests/srcNoWithManifest/public/Test-PSModuleTest.ps1 @@ -0,0 +1,18 @@ +function Test-PSModuleTest { + <# + .SYNOPSIS + Performs tests on a module. + + .EXAMPLE + Test-PSModule -Name 'World' + + "Hello, World!" + #> + [CmdletBinding()] + param ( + # Name of the person to greet. + [Parameter(Mandatory)] + [string] $Name + ) + Write-Output "Hello, $Name!" +} diff --git a/tests/srcNoWithManifest/scripts/loader.ps1 b/tests/srcNoWithManifest/scripts/loader.ps1 new file mode 100644 index 0000000..29ad42f --- /dev/null +++ b/tests/srcNoWithManifest/scripts/loader.ps1 @@ -0,0 +1,3 @@ +Write-Verbose '-------------------------' -Verbose +Write-Verbose '--- THIS IS A LOADER ---' -Verbose +Write-Verbose '-------------------------' -Verbose diff --git a/tests/srcNoWithManifest/types/DirectoryInfo.Types.ps1xml b/tests/srcNoWithManifest/types/DirectoryInfo.Types.ps1xml new file mode 100644 index 0000000..aef538b --- /dev/null +++ b/tests/srcNoWithManifest/types/DirectoryInfo.Types.ps1xml @@ -0,0 +1,21 @@ + + + + System.IO.FileInfo + + + Status + Success + + + + + System.IO.DirectoryInfo + + + Status + Success + + + + diff --git a/tests/srcNoWithManifest/types/FileInfo.Types.ps1xml b/tests/srcNoWithManifest/types/FileInfo.Types.ps1xml new file mode 100644 index 0000000..4cfaf6b --- /dev/null +++ b/tests/srcNoWithManifest/types/FileInfo.Types.ps1xml @@ -0,0 +1,14 @@ + + + + System.IO.FileInfo + + + Age + + ((Get-Date) - ($this.CreationTime)).Days + + + + +