Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit bff8e7a

Browse files
authoredFeb 8, 2025··
Merge pull request #133 from PoshCode/joel/Rebuild
Fix the test matrix
2 parents b715cf6 + 9d06dd8 commit bff8e7a

23 files changed

+1007
-887
lines changed
 

‎.github/workflows/build.yml

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,18 @@ jobs:
4242
name: TestResults
4343
path: Modules/ModuleBuilder-TestResults
4444

45-
- uses: actions/upload-artifact@v4
46-
with:
47-
name: Packages
48-
path: Modules/ModuleBuilder-Packages
49-
45+
# These ones are just for the test matrix
5046
- name: Upload Tests
5147
uses: actions/upload-artifact@v4
5248
with:
5349
name: PesterTests
5450
path: ${{github.workspace}}/Tests
55-
- name: Upload RequiredModules.psd1
51+
52+
- name: Upload build.requires.psd1
5653
uses: actions/upload-artifact@v4
5754
with:
58-
name: RequiredModules
59-
path: ${{github.workspace}}/RequiredModules.psd1
55+
name: build.requires.psd1
56+
path: ${{github.workspace}}/build.requires.psd1
6057
test:
6158
needs: build
6259
runs-on: ${{ matrix.os }}
@@ -69,29 +66,43 @@ jobs:
6966
uses: actions/download-artifact@v4
7067
with:
7168
name: ModuleBuilder
72-
path: Modules/ModuleBuilder
69+
path: Modules/ModuleBuilder # /home/runner/work/ModuleBuilder/ModuleBuilder/Modules/ModuleBuilder
7370
- name: Download Pester Tests
7471
uses: actions/download-artifact@v4
7572
with:
7673
name: PesterTests
7774
path: PesterTests
78-
- name: Download RequiredModules
75+
- name: Download build.requires.psd1
7976
uses: actions/download-artifact@v4
8077
with:
81-
name: RequiredModules
82-
83-
- uses: PoshCode/Actions/install-requiredmodules@v1
84-
- uses: PoshCode/Actions/pester@v1
85-
with:
86-
codeCoveragePath: Modules/ModuleBuilder
87-
moduleUnderTest: ModuleBuilder
88-
additionalModulePaths: ${{github.workspace}}/Modules
89-
- name: Publish Test Results
90-
uses: zyborg/dotnet-tests-report@v1
78+
name: build.requires.psd1
79+
- name: ⚡ Install PowerShell Modules
80+
uses: JustinGrote/ModuleFast-action@v0.0.1
81+
- name: Put Build output in PATH
82+
shell: pwsh
83+
run: | # PowerShell
84+
Convert-Path Modules -OutVariable BuiltModules
85+
Add-Content -Path $env:GITHUB_PATH -Value $BuiltModules -Encoding utf8
86+
# Uninstall the "installed" copy of ModuleBuilder
87+
Get-Module -Name ModuleBuilder -List | Where ModuleBase -notmatch ([regex]::escape($pwd)) | Split-Path | Remove-Item -Recurse -Force
88+
- name: Put Build output in PATH
89+
shell: pwsh
90+
run: | # PowerShell
91+
$Env:PATH -split ([IO.Path]::PathSeparator) | Out-Host
92+
- name: Invoke Pester Tests
93+
id: pester
94+
uses: zyborg/pester-tests-report@v1
9195
with:
92-
test_results_path: results.xml
93-
- name: Upload Results
94-
uses: actions/upload-artifact@v2
95-
with:
96-
name: Pester Results
97-
path: ${{github.workspace}}/*.xml
96+
# include_paths: tests
97+
# exclude_paths: tests/powershell1,tests/powershell2
98+
# exclude_tags: skip_ci
99+
report_name: module_tests
100+
report_title: My Module Tests
101+
github_token: ${{ secrets.GITHUB_TOKEN }}
102+
- name: dump test results
103+
shell: pwsh
104+
run: | # PowerShell
105+
Write-Host 'Total Tests Executed...: ${{ steps.pester.outputs.total_count }}'
106+
Write-Host 'Total Tests PASSED.....: ${{ steps.pester.outputs.passed_count }}'
107+
Write-Host 'Total Tests FAILED.....: ${{ steps.pester.outputs.failed_count }}'
108+

‎.github/workflows/dotnet-tools.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": 1,
3+
"isRoot": true,
4+
"tools": {
5+
"gitversion.tool": {
6+
"version": "5.6.0",
7+
"commands": [
8+
"dotnet-gitversion"
9+
]
10+
}
11+
}
12+
}

‎Build.build.ps1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ param(
1616
# Add the clean task before the default build
1717
[switch]$Clean,
1818

19-
# Collect code coverage when tests are run
20-
[switch]$CollectCoverage,
19+
# A minimum code coverage percentage to accept as a double: 0.85
20+
[double]$RequiredCodeCoverage = 0.85,
2121

2222
# Which projects to build
2323
[Alias("Projects")]

‎Earthfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
VERSION 0.7
22
IMPORT github.com/poshcode/tasks
3-
FROM mcr.microsoft.com/dotnet/sdk:7.0
3+
FROM mcr.microsoft.com/dotnet/sdk:9.0
44
WORKDIR /work
55

66
ARG --global EARTHLY_GIT_ORIGIN_URL
@@ -25,9 +25,9 @@ worker:
2525
COPY tasks+tasks/* /Tasks
2626
# Dealing with dependencies first allows docker to cache packages for us
2727
# So the dependency cach only re-builds when you add a new dependency
28-
COPY RequiredModules.psd1 .
28+
COPY build.requires.psd1 .
2929
# COPY *.csproj .
30-
RUN ["pwsh", "-File", "/Tasks/_Bootstrap.ps1", "-RequiredModulesPath", "RequiredModules.psd1"]
30+
RUN ["pwsh", "-File", "/Tasks/_Bootstrap.ps1", "-RequiresPath", "build.requires.psd1"]
3131

3232
build:
3333
FROM +worker

‎GitVersion.yml

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,46 @@
1-
mode: Mainline
2-
assembly-versioning-format: '{Major}.{Minor}.{Patch}.{env:BUILDCOUNT ?? 0}'
3-
assembly-informational-format: '{NuGetVersionV2}+Build.{env:BUILDCOUNT ?? 0}.Date.{CommitDate}.Branch.{env:SAFEBRANCHNAME ?? unknown}.Sha.{Sha}'
4-
major-version-bump-message: '\+?semver:\s?(breaking|major)'
5-
minor-version-bump-message: '\+?semver:\s?(feature|minor)'
6-
patch-version-bump-message: '\+?semver:\s?(fix|patch)'
7-
no-bump-message: '\+?semver:\s?(none|skip)'
1+
mode: mainline
2+
commit-date-format: "yyyyMMddTHHmmss"
3+
assembly-file-versioning-format: "{Major}.{Minor}.{Patch}.{env:GITHUB_RUN_NUMBER ?? 0}"
4+
5+
# This repo needs to use NuGetVersionV2 for compatibility with PowerShellGallery
6+
assembly-informational-format: "{NuGetVersionV2}+Build.{env:GITHUB_RUN_NUMBER ?? local}.Branch.{EscapedBranchName}.Sha.{Sha}.Date.{CommitDate}"
7+
major-version-bump-message: 'semver:\s?(breaking|major)'
8+
minor-version-bump-message: 'semver:\s?(feature|minor)'
9+
patch-version-bump-message: 'semver:\s?(fix|patch)'
10+
no-bump-message: 'semver:\s?(none|skip)'
11+
commit-message-incrementing: Enabled
12+
813
branches:
9-
master:
14+
main:
15+
tag: "" # explicitly no tag for main builds
16+
regex: ^main$
1017
increment: Patch
11-
pull-request:
18+
is-mainline: true
19+
tracks-release-branches: true
20+
hotfix:
21+
tag: rc
22+
regex: hotfix(es)?/\d+\.\d+\.\d+
23+
increment: None
24+
is-release-branch: true
25+
prevent-increment-of-merged-branch-version: true
26+
source-branches: [ "main" ]
27+
release:
1228
tag: rc
29+
regex: releases?/\d+\.\d+\.\d+
30+
increment: None
31+
is-release-branch: true
32+
prevent-increment-of-merged-branch-version: true
33+
source-branches: [ "main" ]
34+
pull-request:
35+
regex: pull/
36+
tag: pr
37+
tag-number-pattern: '[/-](?<number>\d+)'
1338
increment: Patch
39+
source-branches: [ "main", "feature", "release", "hotfix" ]
1440
feature:
41+
regex: .*/
42+
tag: useBranchName
43+
source-branches: [ "main", "feature" ]
44+
track-merge-target: true
45+
tracks-release-branches: true
1546
increment: Patch
16-
regex: .*?/
17-
source-branches:
18-
- master
19-
- feature

‎ReadMe.md

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,59 @@
1-
# The Module Builder Project
1+
# Module Builder - Simplifying Authoring PowerShell (Script) Modules
22

3-
This project is an attempt by a group of PowerShell MVPs and module authors to:
3+
This module makes it easier to break up your module source into several files for organization, even though you need to ship it as one big psm1 file.
44

5-
1. Build a common set of [tools for module authoring](#whats-in-the-module-so-far)
6-
2. Encourage a common pattern for [organizing PowerShell module projects](#organizing-your-module)
7-
3. Promote best practices for authoring functions and modules
5+
There are still some issues in Visual Studio Code and PSScriptAnalyzer when authoring modules as multiple files, but if you want to break up your module into multiple files for organization and maintainability, and still need to ship it as one big file for performance and compatibility reasons, this module is for you.
86

9-
In short, we want to make it easier for people to write great code and produce great modules.
7+
## You should ship your module as one big file!
108

11-
In service of this goal, we intend to produce:
9+
PowerShell expects script modules to be all in one file. A module in a single `.psm1` script file results in the best performance, natural "script" scope, and full support for classes and "using" statements.
1210

13-
1. Guidance on using the best of the existing tools: dotnet, Pester, PSDepends, etc.
14-
2. Module templates demonstrating best practices for organization
15-
3. Function templates demonstrating best practices for common parameters and error handling
16-
4. ModuleBuilder module - a set of tools for building modules following these best practices
11+
The single file option is particularly important for performance if you are signing your module (or your end users want to be able to code-sign it), because each file's signature must be checked, and each certificate must be checked against CRLs. It's also critical if you are using PowerShell classes (the `using` statement only supports classes defined in the root psm1 file). It's basically required if you want to use module-scope variables to share state between functions in your module.
1712

18-
## The ModuleBuilder module
13+
## What's in the ModuleBuilder module so far?
1914

20-
This module is the main output of the project, consisting of one primary command: `Build-Module` and a few helpers to translate input and output line numbers. It represents the collaboration of several module authors who had each written their own version of these tools for themselves, and have now decided to collaborate on creating a shared tool set. We are each using the patterns and tools that are represented here, and are committed to helping others to succeed at doing so.
15+
This module is the main output of the project, consisting of one primary command: `Build-Module` and a few helpers to translate input and output line numbers so you can trouble-shoot error messages from your module against the source files.
2116

22-
### What's in the module so far
23-
24-
#### Build-Module
17+
### Build-Module
2518

2619
Builds a script module from a source project containing one file per function in `Public` and `Private` folders.
2720

2821
The `Build-Module` command is a build task for PowerShell script modules that supports [incremental builds](https://docs.microsoft.com/en-us/visualstudio/msbuild/incremental-builds).
2922

30-
#### Convert-CodeCoverage
23+
### Convert-CodeCoverage
3124

3225
Takes the output from `Invoke-Pester -Passthru` run against the build output, and converts the code coverage report to the source lines.
3326

34-
#### ConvertFrom-SourceLineNumber
27+
### ConvertFrom-SourceLineNumber
3528

3629
Converts a line number from a source file to the corresponding line number in the built output.
3730

38-
#### ConvertTo-SourceLineNumber
31+
### ConvertTo-SourceLineNumber
3932

4033
Converts a line number from the built output to the corresponding file and line number in the source.
4134

42-
#### Convert-Breakpoint
35+
### Convert-Breakpoint
4336

4437
Convert any breakpoints on source files to module files _and vice-versa_.
4538

4639
## Organizing Your Module
4740

48-
For best results, you need to organize your module project similarly to how this project is organized. It doesn't have to be exact, because nearly all of our conventions can be overriden, but the module _is_ opinionated, so if you follow the conventions, it should feel wonderfully automatic.
41+
For best results, you need to organize your module project similarly to how this project is organized. It doesn't have to be exact, because you can override nearly all of our conventions, but the module _is_ opinionated, so if you follow the conventions, it should feel wonderfully automatic.
4942

50-
1. Create a `source` folder with a `build.psd1` file and your module manifest in it
43+
1. Create a `source` (or `src`) folder with a `build.psd1` file and your module manifest in it
5144
2. In the `build.psd1` specify the relative **Path** to your module's manifest, e.g. `@{ Path = "ModuleBuilder.psd1" }`
5245
3. In your manifest, make sure a few values are not commented out. You can leave them empty, because they'll be overwritten:
5346
- `FunctionsToExport` will be updated with the _file names_ that match the `PublicFilter`
5447
- `AliasesToExport` will be updated with the values from `[Alias()]` attributes on commands
5548
- `Prerelease` and `ReleaseNotes` in the `PSData` hash table in `PrivateData`
5649

57-
Once you start working on the module, you'll create sub-folders in source, and put script files in them with only **one** function in each file. You should name the files with _the same name_ as the function that's in them -- especially in the public folder, where we use the file name (without the extension) to determine the exported functions.
50+
Once you start working on the module, you'll create sub-folders in source, and put script files in them with only **one** function in each file. You should name the files with _the same name_ as the function that's in them -- especially in the `source\public` folder, where we use the file names to determine the exported functions.
5851

59-
1. By convention, use folders named "Classes" (and/or "Enum"), "Private", and "Public"
60-
2. By convention, the functions in "Public" will be exported from the module (you can override the `PublicFilter`)
52+
1. By convention, use SourceDirectories named "Classes" (and/or "Enum"), "Private", and "Public"
53+
2. By convention, the PublicFilter is all of the functions in the "Public" directory.
6154
3. To force classes to be in a certain order, you can prefix their file names with numbers, like `01-User.ps1`
6255

63-
There are a _lot_ of conventions in `Build-Module`, expressed as default values for its parameters. These defaults are documented in the help for Build-Module. You can override any parameter defaults by adding keys to the `build.psd1` file with your preferences, or by passing the values to the `Build-Module` command directly.
56+
There are a _lot_ of conventions in `Build-Module`, expressed as default values for its parameters. These defaults are documented in the help for Build-Module, and you can override any parameter defaults by adding keys to the `build.psd1` file with your preferences, or by passing the values to the `Build-Module` command directly. So in other words, you can override the default `SourceDirectories` and `PublicFilters` (and any others) by adding them to the `build.psd1` file.
6457

6558
## A note on build tools
6659

@@ -93,7 +86,7 @@ git clone https://github.com/PoshCode/ModuleBuilder.git
9386
git clone https://github.com/PoshCode/Tasks.git
9487
```
9588

96-
Once you've cloned both, the `Build.build.ps1` script will use the shared [Tasks\_Bootstrap.ps1](https://github.com/PoshCode/Tasks/blob/main/_Bootstrap.ps1) to install the other dependencies (see [RequiredModules.psd1](https://github.com/PoshCode/ModuleBuilder/blob/main/RequiredModules.psd1)), including [dotnet](https://dot.net), and will use [Invoke-Build](https://github.com/nightroman/Invoke-Build) and [Pester](https://github.com/Pester/Pester) to build and test the module.
89+
Once you've cloned both, the `Build.build.ps1` script will use the shared [Tasks\_Bootstrap.ps1](https://github.com/PoshCode/Tasks/blob/main/_Bootstrap.ps1) to install the other dependencies (see [build.requires.psd1](https://github.com/PoshCode/ModuleBuilder/blob/main/build.requires.psd1)), including [dotnet](https://dot.net), and will use [Invoke-Build](https://github.com/nightroman/Invoke-Build) and [Pester](https://github.com/Pester/Pester) to build and test the module.
9790

9891
```powershell
9992
cd ModuleBuilder
@@ -102,23 +95,18 @@ cd ModuleBuilder
10295

10396
This _should_ work on Windows, Linux, or MacOS. I test the build process on Windows, and in CI we run it in the Linux containers via earthly, and we run the full Pester test suit on all three platforms.
10497

105-
#### The old-fashioned way
98+
## Most recent releases
10699

107-
You _can_ build the module without any additional tools (and without running tests), by using the old `build.ps1` bootstrap script. You'll need to pass a version number in, and if you have [Pester](https://github.com/Pester/Pester) and [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer), you can run the 'test.ps1' script to run the tests.
100+
### 3.2.0 - Script Generators
108101

109-
```powershell
110-
./build.ps1 -Semver 5.0.0-prerelease | Split-Path | Import-Module -Force
111-
./test.ps1
112-
```
102+
Script Generators let developers modify their module's source code as it is being built. A generator can create new script functions on the fly, such that whole functions are added to the built module. A generator can also inject boilerplate code like error handling, logging, tracing and timing at build-time, so this code can be maintained once, and be automatically added (and updated) in all the places where it's needed when the module is built. The generators run during the build and can inspect existing functions, data files, or even data from an API, and produce code that is output into the module (and clearly marked as generated).
103+
104+
### 3.1.0 - Supports help outside the top of script commands
113105

114-
## Changelog
106+
Starting with this release, ModuleBuilder adds an empty line between the `#REGION filename` comment lines it injects, and the content of the files. This allows PowerShell to recognize help comments that are at the top of each file (outside the function block).
115107

116-
### 3.0.0 - Now with better alias support
108+
### 3.0.0 - Better alias support
117109

118110
Starting with this release, ModuleBuilder will automatically export aliases from `New-Alias` and `Set-Alias` as well as the `[Alias()]` attributes on commands. This is (probably not) a breaking change, but because it can change the aliases exported by existing modules that use ModuleBuilder, I've bumped the major version number as a precaution (if you're reading this, mission accomplished).
119111

120112
Additionally, the `Build-Module` command now _explicitly sorts_ the source files into alphabetical order, to ensure consistent behavior regardless of the native order of the underlying file system. This is technically also a breaking change, but it's unlikely to affect anyone except the people whose builds didn't work on non-Windows systems because of the previous behavior.
121-
122-
### 3.1.0 - Now allows help outside the top of script commands
123-
124-
Starting with this release, ModuleBuilder adds an empty line between the `#REGION filename` comment lines it injects, and the content of the files. This allows PowerShell to recognize help comments that are at the top of each file (outside the function block).

‎RequiredModules.psd1

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,42 @@
11
#requires -Module ModuleBuilder
2-
. $PSScriptRoot\..\Convert-FolderSeparator.ps1
32

4-
Describe "Parameters.Set in build manifest" -Tag Integration {
3+
Describe "Parameters" -Tag Integration {
54
BeforeAll {
6-
New-Item $PSScriptRoot\Result3\Parameters\ReadMe.md -ItemType File -Force
7-
$Output = Build-Module $PSScriptRoot\Parameters\build.psd1
8-
if ($Output) {
9-
$Module = [IO.Path]::ChangeExtension($Output.Path, "psm1")
10-
$Metadata = Import-Metadata $Output.Path
5+
. $PSScriptRoot/../Convert-FolderSeparator.ps1
6+
# Make sure the Result3 folder is really clean ;)
7+
if (Test-Path $PSScriptRoot/Result3) {
8+
Remove-Item $PSScriptRoot/Result3 -Recurse -Force
119
}
10+
# Throw in an extra file that would get cleaned up normally ...
11+
New-Item $PSScriptRoot/Result3/Parameters/3.0.0/DeleteMe.md -ItemType File -Force
12+
13+
Write-Host "Module Under Test:"
14+
Get-Command Build-Module
15+
| Get-Module -Name { $_.Source }
16+
| Get-Item
17+
| Out-Host
1218
}
1319

14-
It "Passthru works" {
20+
It "Passthru is read from the build manifest" {
21+
Build-Module (Convert-FolderSeparator "$PSScriptRoot/Parameters/build.psd1") -Verbose -OutVariable Output
22+
| Out-Host
23+
1524
$Output | Should -Not -BeNullOrEmpty
25+
$Output.Path | Convert-FolderSeparator | Should -Be (Convert-FolderSeparator "$PSScriptRoot/Result3/Parameters/3.0.0/Parameters.psd1")
1626
}
1727

18-
It "The Target is Build" {
19-
"$PSScriptRoot\Result3\Parameters\ReadMe.md" | Should -Exist
28+
It "The target is 'Build' (not CleanBuild) so pre-created extra files get left behind" {
29+
Convert-FolderSeparator "$PSScriptRoot/Result3/Parameters/3.0.0/DeleteMe.md" | Should -Exist
30+
Convert-FolderSeparator "$PSScriptRoot/Result3/Parameters/3.0.0/Parameters.psm1" | Should -Exist
2031
}
2132

2233
It "The version is set" {
34+
$Metadata = Import-Metadata "$PSScriptRoot/Result3/Parameters/3.0.0/Parameters.psd1"
2335
$Metadata.ModuleVersion | Should -Be "3.0.0"
2436
}
2537

2638
It "The PreRelease is set" {
39+
$Metadata = Import-Metadata "$PSScriptRoot/Result3/Parameters/3.0.0/Parameters.psd1"
2740
$Metadata.PrivateData.PSData.Prerelease | Should -Be 'alpha001'
2841
}
2942
}

‎Tests/Integration/Parameters/Parameters.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
@{
22
# The module version should be SemVer.org compatible
3-
ModuleVersion = "1.0.0"
3+
ModuleVersion = "3.0.0"
44

55
# PrivateData is where all third-party metadata goes
66
PrivateData = @{

‎Tests/Integration/Result3/Parameters/ReadMe.md

Whitespace-only changes.

‎Tests/Integration/Source1.Tests.ps1

Lines changed: 86 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22
. $PSScriptRoot\..\Convert-FolderSeparator.ps1
33

44
Describe "When we call Build-Module" -Tag Integration {
5-
$Output = Build-Module $PSScriptRoot\Source1\build.psd1 -Passthru
6-
$Module = [IO.Path]::ChangeExtension($Output.Path, "psm1")
5+
BeforeAll {
6+
$Output = Build-Module $PSScriptRoot\Source1\build.psd1 -Passthru
7+
$Module = [IO.Path]::ChangeExtension($Output.Path, "psm1")
8+
$Metadata = Import-Metadata $Output.Path
9+
}
710

811
It "Should not put the module's DefaultCommandPrefix into the psm1 as code. Duh!" {
912
$Module | Should -Not -FileContentMatch '^Source$'
1013
}
1114

12-
$Metadata = Import-Metadata $Output.Path
1315

1416
It "Should update FunctionsToExport in the manifest" {
1517
$Metadata.FunctionsToExport | Should -Be @("Get-Source", "Set-Source")
@@ -29,14 +31,16 @@ Describe "When we call Build-Module" -Tag Integration {
2931
}
3032

3133
Describe "Regression test for #55: I can pass SourceDirectories" -Tag Integration, Regression {
32-
$Output = Build-Module $PSScriptRoot\Source1\build.psd1 -SourceDirectories "Private" -Passthru
33-
$Module = [IO.Path]::ChangeExtension($Output.Path, "psm1")
34+
BeforeAll {
35+
$Output = Build-Module $PSScriptRoot\Source1\build.psd1 -SourceDirectories "Private" -Passthru
36+
$Module = [IO.Path]::ChangeExtension($Output.Path, "psm1")
37+
$Metadata = Import-Metadata $Output.Path
38+
}
3439

3540
It "Should not put the module's DefaultCommandPrefix into the psm1 as code. Duh!" {
3641
$Module | Should -Not -FileContentMatch '^Source$'
3742
}
3843

39-
$Metadata = Import-Metadata $Output.Path
4044

4145
It "Should not have any FunctionsToExport if SourceDirectories don't match the PublicFilter" {
4246
$Metadata.FunctionsToExport | Should -Be @()
@@ -80,27 +84,30 @@ Describe "Regression test for #55: I can pass SourceDirectories and PublicFilter
8084
}
8185

8286
Describe "Regression test for #84: Multiple Aliases per command will Export" -Tag Integration, Regression {
83-
$Output = Build-Module $PSScriptRoot\Source1\build.psd1 -Passthru
84-
85-
$Metadata = Import-Metadata $Output.Path
87+
BeforeAll {
88+
$Output = Build-Module $PSScriptRoot\Source1\build.psd1 -Passthru
89+
$Metadata = Import-Metadata $Output.Path
90+
}
8691

8792
It "Should update AliasesToExport in the manifest" {
8893
$Metadata.AliasesToExport | Should -Be @("Get-MyAlias","GS","GSou", "SS", "SSou")
8994
}
9095
}
9196

9297
Describe "Supports building without a build.psd1" -Tag Integration {
93-
Copy-Item $PSScriptRoot\Source1 TestDrive:\Source1 -Recurse
94-
# This is the old build, with a build.psd1
95-
$Output = Build-Module TestDrive:\Source1\build.psd1 -Passthru
96-
$ManifestContent = Get-Content $Output.Path
97-
$ModuleContent = Get-Content ([IO.Path]::ChangeExtension($Output.Path, ".psm1"))
98-
Remove-Item (Split-Path $Output.Path) -Recurse
98+
BeforeAll {
99+
Copy-Item $PSScriptRoot\Source1 TestDrive:\Source1 -Recurse
100+
# This is the old build, with a build.psd1
101+
$Output = Build-Module TestDrive:\Source1\build.psd1 -Passthru
102+
$ManifestContent = Get-Content $Output.Path
103+
$ModuleContent = Get-Content ([IO.Path]::ChangeExtension($Output.Path, ".psm1"))
104+
Remove-Item (Split-Path $Output.Path) -Recurse
99105

100-
# Then remove the build.psd1 and rebuild it
101-
Remove-Item TestDrive:\Source1\build.psd1
106+
# Then remove the build.psd1 and rebuild it
107+
Remove-Item TestDrive:\Source1\build.psd1
102108

103-
$Build = @{ }
109+
$Build = @{ }
110+
}
104111

105112
It "No longer fails if there's no build.psd1" {
106113
$BuildParameters = @{
@@ -158,17 +165,19 @@ Describe "Supports building without a build.psd1" -Tag Integration {
158165
}
159166

160167
Describe "Defaults to VersionedOutputDirectory" -Tag Integration {
161-
Copy-Item $PSScriptRoot\Source1 TestDrive:\Source1 -Recurse
162-
# This is the old build, with a build.psd1
163-
$Output = Build-Module TestDrive:\Source1\build.psd1 -Passthru
164-
$ManifestContent = Get-Content $Output.Path
165-
$ModuleContent = Get-Content ([IO.Path]::ChangeExtension($Output.Path, ".psm1"))
166-
Remove-Item (Split-Path $Output.Path) -Recurse
168+
BeforeAll {
169+
Copy-Item $PSScriptRoot\Source1 TestDrive:\Source1 -Recurse
170+
# This is the old build, with a build.psd1
171+
$Output = Build-Module TestDrive:\Source1\build.psd1 -Passthru
172+
$ManifestContent = Get-Content $Output.Path
173+
$ModuleContent = Get-Content ([IO.Path]::ChangeExtension($Output.Path, ".psm1"))
174+
Remove-Item (Split-Path $Output.Path) -Recurse
167175

168-
# Then remove the build.psd1 and rebuild it
169-
Remove-Item TestDrive:\Source1\build.psd1
176+
# Then remove the build.psd1 and rebuild it
177+
Remove-Item TestDrive:\Source1\build.psd1
170178

171-
$Build = @{ }
179+
$Build = @{ }
180+
}
172181

173182
It "Builds into a folder with version by default" {
174183
$BuildParameters = @{
@@ -207,20 +216,22 @@ Describe "Defaults to VersionedOutputDirectory" -Tag Integration {
207216
}
208217

209218
Describe "Supports building discovering the module without a build.psd1" -Tag Integration {
210-
Copy-Item $PSScriptRoot\Source1 TestDrive:\source -Recurse
219+
BeforeAll {
220+
Copy-Item $PSScriptRoot\Source1 TestDrive:\source -Recurse
211221

212-
# This is the old build, with a build.psd1
213-
$Output = Build-Module TestDrive:\source\build.psd1 -Passthru
214-
$ManifestContent = Get-Content $Output.Path
215-
$ModuleContent = Get-Content ([IO.Path]::ChangeExtension($Output.Path, ".psm1"))
216-
Remove-Item (Split-Path $Output.Path) -Recurse
222+
# This is the old build, with a build.psd1
223+
$Output = Build-Module TestDrive:\source\build.psd1 -Passthru
224+
$ManifestContent = Get-Content $Output.Path
225+
$ModuleContent = Get-Content ([IO.Path]::ChangeExtension($Output.Path, ".psm1"))
226+
Remove-Item (Split-Path $Output.Path) -Recurse
217227

218-
# Then remove the build.psd1 and rebuild it
219-
Remove-Item TestDrive:\source\build.psd1
228+
# Then remove the build.psd1 and rebuild it
229+
Remove-Item TestDrive:\source\build.psd1
220230

221-
Push-Location -StackName 'IntegrationTest' -Path TestDrive:\
231+
Push-Location -StackName 'IntegrationTest' -Path TestDrive:\
222232

223-
$Build = @{ }
233+
$Build = @{ }
234+
}
224235

225236
It "No longer fails if there's no build.psd1" {
226237
$Build.Output = Build-Module -Passthru
@@ -240,13 +251,16 @@ Describe "Supports building discovering the module without a build.psd1" -Tag In
240251
$Build.Metadata.FunctionsToExport | Should -Be @("Get-Source", "Set-Source")
241252
}
242253

243-
Pop-Location -StackName 'IntegrationTest'
254+
AfterAll {
255+
Pop-Location -StackName 'IntegrationTest'
256+
}
244257
}
245258

246259
Describe "Regression test for #88 not copying prefix files" -Tag Integration, Regression {
247-
$Output = Build-Module $PSScriptRoot\build.psd1 -Passthru
248-
249-
$Metadata = Import-Metadata $Output.Path
260+
BeforeAll {
261+
$Output = Build-Module $PSScriptRoot\build.psd1 -Passthru
262+
$Metadata = Import-Metadata $Output.Path
263+
}
250264

251265
It "Should update AliasesToExport in the manifest" {
252266
$Module = [IO.Path]::ChangeExtension($Output.Path, "psm1")
@@ -256,20 +270,22 @@ Describe "Regression test for #88 not copying prefix files" -Tag Integration, Re
256270
}
257271

258272
Describe "Regression test for #40.2 not copying suffix if prefix" -Tag Integration, Regression {
259-
Copy-Item $PSScriptRoot\Source1 TestDrive:\Source1 -Recurse
273+
BeforeAll {
274+
Copy-Item $PSScriptRoot\Source1 TestDrive:\Source1 -Recurse
260275

261-
New-Item TestDrive:\Source1\_GlobalScope.ps1 -Value '$Global:Module = "Testing"'
276+
New-Item TestDrive:\Source1\_GlobalScope.ps1 -Value '$Global:Module = "Testing"'
262277

263-
$metadata = Import-Metadata TestDrive:\Source1\build.psd1
264-
$metadata += @{
265-
Prefix = "./_GlobalScope.ps1"
266-
Suffix = "./_GlobalScope.ps1"
267-
}
268-
$metadata | Export-Metadata TestDrive:\Source1\build.psd1
278+
$metadata = Import-Metadata TestDrive:\Source1\build.psd1
279+
$metadata += @{
280+
Prefix = "./_GlobalScope.ps1"
281+
Suffix = "./_GlobalScope.ps1"
282+
}
283+
$metadata | Export-Metadata TestDrive:\Source1\build.psd1
269284

270-
$Output = Build-Module TestDrive:\Source1 -Passthru
285+
$Output = Build-Module TestDrive:\Source1 -Passthru
271286

272-
$Metadata = Import-Metadata $Output.Path
287+
$Metadata = Import-Metadata $Output.Path
288+
}
273289

274290
It "Should inject the content of the _GlobalScope file at the TOP and BOTTOM" {
275291
$Module = [IO.Path]::ChangeExtension($Output.Path, "psm1")
@@ -288,10 +304,12 @@ Describe "Regression test for #40.2 not copying suffix if prefix" -Tag Integrati
288304
# There's no such thing as a drive root on unix
289305
if ($PSVersionTable.Platform -eq "Win32NT") {
290306
Describe "Able to build from the drive root" {
291-
$null = New-ModuleManifest "TestDrive:/MyModule.psd1" -ModuleVersion "1.0.0" -Author "Tester"
292-
$null = New-Item "TestDrive:/Public/Test.ps1" -Type File -Value 'MATCHING TEST CONTENT' -Force
307+
BeforeAll {
308+
$null = New-ModuleManifest "TestDrive:/MyModule.psd1" -ModuleVersion "1.0.0" -Author "Tester"
309+
$null = New-Item "TestDrive:/Public/Test.ps1" -Type File -Value 'MATCHING TEST CONTENT' -Force
293310

294-
$Result = Build-Module -SourcePath 'TestDrive:/MyModule.psd1' -Version "1.0.0" -OutputDirectory './output' -Encoding UTF8 -SourceDirectories @('Public') -Target Build -Passthru
311+
$Result = Build-Module -SourcePath 'TestDrive:/MyModule.psd1' -Version "1.0.0" -OutputDirectory './output' -Encoding UTF8 -SourceDirectories @('Public') -Target Build -Passthru
312+
}
295313

296314
It "Builds the Module in the designated output folder" {
297315
$Result.ModuleBase | Convert-FolderSeparator | Should -Be (Convert-FolderSeparator "TestDrive:/Output/MyModule/1.0.0")
@@ -301,20 +319,21 @@ if ($PSVersionTable.Platform -eq "Win32NT") {
301319
}
302320

303321
Describe "Copies additional items specified in CopyPaths" {
322+
BeforeAll {
323+
$null = New-Item "TestDrive:/build.psd1" -Type File -Force -Value "@{
324+
SourcePath = 'TestDrive:/MyModule.psd1'
325+
SourceDirectories = @('Public')
326+
OutputDirectory = './output'
327+
CopyPaths = './lib', './MyModule.format.ps1xml'
328+
}"
329+
$null = New-ModuleManifest "TestDrive:/MyModule.psd1" -ModuleVersion "1.0.0" -Author "Tester"
330+
$null = New-Item "TestDrive:/Public/Test.ps1" -Type File -Value 'MATCHING TEST CONTENT' -Force
331+
$null = New-Item "TestDrive:/MyModule.format.ps1xml" -Type File -Value '<Configuration />' -Force
332+
$null = New-Item "TestDrive:/lib/imaginary1.dll" -Type File -Value '1' -Force
333+
$null = New-Item "TestDrive:/lib/subdir/imaginary2.dll" -Type File -Value '2' -Force
304334

305-
$null = New-Item "TestDrive:/build.psd1" -Type File -Force -Value "@{
306-
SourcePath = 'TestDrive:/MyModule.psd1'
307-
SourceDirectories = @('Public')
308-
OutputDirectory = './output'
309-
CopyPaths = './lib', './MyModule.format.ps1xml'
310-
}"
311-
$null = New-ModuleManifest "TestDrive:/MyModule.psd1" -ModuleVersion "1.0.0" -Author "Tester"
312-
$null = New-Item "TestDrive:/Public/Test.ps1" -Type File -Value 'MATCHING TEST CONTENT' -Force
313-
$null = New-Item "TestDrive:/MyModule.format.ps1xml" -Type File -Value '<Configuration />' -Force
314-
$null = New-Item "TestDrive:/lib/imaginary1.dll" -Type File -Value '1' -Force
315-
$null = New-Item "TestDrive:/lib/subdir/imaginary2.dll" -Type File -Value '2' -Force
316-
317-
$Result = Build-Module -SourcePath 'TestDrive:/build.psd1' -OutputDirectory './output' -Version '1.0.0' -Passthru -Target Build
335+
$Result = Build-Module -SourcePath 'TestDrive:/build.psd1' -OutputDirectory './output' -Version '1.0.0' -Passthru -Target Build
336+
}
318337

319338
It "Copies single files that are in CopyPaths" {
320339
(Convert-FolderSeparator $Result.ModuleBase) | Should -Be (Convert-FolderSeparator "$TestDrive/output/MyModule/1.0.0")

‎Tests/Private/ConvertToAst.Tests.ps1

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
Describe "ConvertToAst" {
33

44
Context "It returns a ParseResult for file paths" {
5-
$ParseResult = InModuleScope ModuleBuilder {
6-
ConvertToAst $PSCommandPath
5+
BeforeAll {
6+
$ParseResult = InModuleScope ModuleBuilder {
7+
ConvertToAst $PSCommandPath
8+
}
79
}
810

911
It "Returns a ParseResult object" {
@@ -22,8 +24,10 @@ Describe "ConvertToAst" {
2224
}
2325

2426
Context "It parses piped in commands" {
25-
$ParseResult = InModuleScope ModuleBuilder {
26-
Get-Command ConvertToAst | ConvertToAst
27+
BeforeAll {
28+
$ParseResult = InModuleScope ModuleBuilder {
29+
Get-Command ConvertToAst | ConvertToAst
30+
}
2731
}
2832

2933
It "Returns a ParseResult object with the AST" {
@@ -33,8 +37,10 @@ Describe "ConvertToAst" {
3337
}
3438

3539
Context "It parses piped in modules" {
36-
$ParseResult = InModuleScope ModuleBuilder {
37-
Get-Module ModuleBuilder | ConvertToAst
40+
BeforeAll {
41+
$ParseResult = InModuleScope ModuleBuilder {
42+
Get-Module ModuleBuilder | ConvertToAst
43+
}
3844
}
3945

4046
It "Returns a ParseResult object with the AST" {

‎Tests/Private/CopyReadMe.Tests.ps1

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#requires -Module ModuleBuilder
22
Describe "Copy ReadMe" {
3-
. $PSScriptRoot\..\Convert-FolderSeparator.ps1
3+
BeforeAll {
4+
. $PSScriptRoot\..\Convert-FolderSeparator.ps1
5+
}
46

57
Context "There's no ReadMe" {
68
# It should not even call Test-Path
@@ -30,32 +32,36 @@ Describe "Copy ReadMe" {
3032
}
3133

3234
Context "There is a ReadMe" {
33-
# Nothing is actually created when this test runs
34-
Mock New-Item -ModuleName ModuleBuilder
35-
Mock Copy-Item -ModuleName ModuleBuilder
35+
BeforeAll {
36+
# Nothing is actually created when this test runs
37+
Mock New-Item -ModuleName ModuleBuilder
38+
Mock Copy-Item -ModuleName ModuleBuilder
3639

37-
# Test-Path returns true only for the source document
38-
${global:Test Script Path} = Join-Path $PSScriptRoot CopyReadMe.Tests.ps1
39-
Mock Test-Path { $Path -eq ${global:Test Script Path} } -ModuleName ModuleBuilder
40+
# Test-Path returns true only for the source document
41+
${global:Test Script Path} = Join-Path $PSScriptRoot CopyReadMe.Tests.ps1
42+
Mock Test-Path { $Path -eq ${global:Test Script Path} } -ModuleName ModuleBuilder
4043

41-
Remove-Item TestDrive:\En -Recurse -Force -ErrorAction SilentlyContinue
44+
Remove-Item TestDrive:\En -Recurse -Force -ErrorAction SilentlyContinue
4245

43-
InModuleScope ModuleBuilder {
44-
CopyReadMe -ReadMe ${global:Test Script Path} -Module ModuleBuilder -OutputDirectory TestDrive:\ -Culture "En"
46+
InModuleScope ModuleBuilder {
47+
CopyReadMe -ReadMe ${global:Test Script Path} -Module ModuleBuilder -OutputDirectory TestDrive:\ -Culture "En"
48+
}
4549
}
4650

4751
It "Creates a language path in the output" {
4852
Assert-MockCalled New-Item -ModuleName ModuleBuilder -ParameterFilter {
4953
(Convert-FolderSeparator "$Path") -eq (Convert-FolderSeparator "TestDrive:\En")
50-
}
54+
} -Scope Context
5155
}
5256

5357
It "Copies the readme as about_module.help.txt" {
5458
Assert-MockCalled Copy-Item -ModuleName ModuleBuilder -ParameterFilter {
5559
(Convert-FolderSeparator $Destination) -eq (Convert-FolderSeparator "TestDrive:\En\about_ModuleBuilder.help.txt")
56-
}
60+
} -Scope Context
5761
}
5862

59-
Remove-Item TestDrive:\En -Recurse -Force -ErrorAction SilentlyContinue
63+
AfterAll {
64+
Remove-Item TestDrive:\En -Recurse -Force -ErrorAction SilentlyContinue
65+
}
6066
}
6167
}

‎Tests/Private/GetBuildInfo.Tests.ps1

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,48 @@
11
#requires -Module ModuleBuilder
22
Describe "GetBuildInfo" {
3-
. $PSScriptRoot\..\Convert-FolderSeparator.ps1
3+
BeforeAll {
4+
. $PSScriptRoot\..\Convert-FolderSeparator.ps1
45

5-
Mock Import-Metadata -ModuleName ModuleBuilder {
6-
@{
7-
#Omitting path to let it resolve [Path = "MyModule.psd1"]
8-
SourceDirectories = "Classes", "Public"
6+
Mock Import-Metadata -ModuleName ModuleBuilder {
7+
@{
8+
#Omitting path to let it resolve [Path = "MyModule.psd1"]
9+
SourceDirectories = "Classes", "Public"
10+
}
911
}
1012
}
1113

1214
Context "It collects the initial data" {
15+
BeforeAll {
16+
# use -Force to create the subdirectories
17+
New-Item -Force "TestDrive:\MyModule\Source\build.psd1" -Type File -Value "@{ Path = 'MyModule.psd1' }"
18+
New-ModuleManifest "TestDrive:\MyModule\Source\MyModule.psd1" -Author Tester
1319

14-
# use -Force to create the subdirectories
15-
New-Item -Force "TestDrive:\MyModule\Source\build.psd1" -Type File -Value "@{ Path = 'MyModule.psd1' }"
16-
New-ModuleManifest "TestDrive:\MyModule\Source\MyModule.psd1" -Author Tester
17-
18-
$Result = InModuleScope -ModuleName ModuleBuilder {
20+
$Result = InModuleScope -ModuleName ModuleBuilder {
1921

20-
# Used to resolve the overridden parameters in $Invocation
21-
$OutputDirectory = '..\ridiculoustestvalue'
22+
# Used to resolve the overridden parameters in $Invocation
23+
$OutputDirectory = '..\ridiculoustestvalue'
2224

23-
GetBuildInfo -BuildManifest TestDrive:\MyModule\Source\build.psd1 -BuildCommandInvocation @{
24-
MyCommand = @{
25-
Parameters = @{
26-
Encoding = @{ParameterType = "string" }
27-
Target = @{ParameterType = "string" }
28-
SourcePath = @{ParameterType = "string" }
29-
SourceDirectories = @{ParameterType = "string[]" }
30-
OutputDirectory = @{ParameterType = "string" }
25+
GetBuildInfo -BuildManifest TestDrive:\MyModule\Source\build.psd1 -BuildCommandInvocation @{
26+
MyCommand = @{
27+
Parameters = @{
28+
Encoding = @{ParameterType = "string" }
29+
Target = @{ParameterType = "string" }
30+
SourcePath = @{ParameterType = "string" }
31+
SourceDirectories = @{ParameterType = "string[]" }
32+
OutputDirectory = @{ParameterType = "string" }
33+
}
34+
}
35+
BoundParameters = @{
36+
OutputDirectory = '..\ridiculoustestvalue'
3137
}
32-
}
33-
BoundParameters = @{
34-
OutputDirectory = '..\ridiculoustestvalue'
3538
}
3639
}
3740
}
3841

3942
It "Parses the build.psd1" {
4043
Assert-MockCalled Import-Metadata -ModuleName ModuleBuilder -ParameterFilter {
4144
(Convert-FolderSeparator $Path) -eq (Convert-FolderSeparator "TestDrive:\MyModule\Source\build.psd1")
42-
}
45+
} -Scope Context
4346
}
4447

4548
It "Reads bound parameters from the BuildCommandInvocation" {

‎Tests/Private/GetRelativePath.Tests.ps1

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
#requires -Module ModuleBuilder
22
Describe "GetRelativePath" {
3-
. $PSScriptRoot\..\Convert-FolderSeparator.ps1
4-
$CommandInfo = InModuleScope ModuleBuilder { Get-Command GetRelativePath }
3+
BeforeAll {
4+
. $PSScriptRoot\..\Convert-FolderSeparator.ps1
5+
$CommandInfo = InModuleScope ModuleBuilder { Get-Command GetRelativePath }
6+
}
57

68
Context "All Parameters are mandatory" {
79

@@ -23,34 +25,36 @@ Describe "GetRelativePath" {
2325
# I'm not going to bother writing tests for this other than "it's the same as .NET's"
2426
if ([System.IO.Path]::GetRelativePath) {
2527
Context "The output always matches [System.IO.Path]::GetRelativePath" {
26-
$TestCases = @(
27-
@{ RelativeTo = "G:\Module"; Path = "G:\Module\Source" }
28-
@{ RelativeTo = "G:\Module"; Path = "G:\Module\Source\Public" }
29-
@{ RelativeTo = "G:\Module\Source"; Path = "G:\Module\Output" }
30-
@{ RelativeTo = "G:\Module\Source"; Path = "G:\Module\Output\" }
31-
@{ RelativeTo = "G:\Module\Source\"; Path = "G:\Module\Output\" }
32-
@{ RelativeTo = "G:\Module\Source\"; Path = "G:\Module\Output" }
33-
@{ RelativeTo = "G:\Projects\Modules\MyModule\Source\Public"; Path = "G:\Modules\MyModule" }
34-
@{ RelativeTo = "G:\Projects\Modules\MyModule\Source\Public"; Path = "G:\Projects\Modules\MyModule" }
35-
# These ones are backwards, but they still work
36-
@{ RelativeTo = "G:\Module\Source" ; Path = "G:\Module" }
37-
@{ RelativeTo = "G:\Module\Source\Public"; Path = "G:\Module" }
38-
# These are linux-like:
39-
@{ RelativeTo = "/mnt/c/Users/Jaykul/Projects/Modules/ModuleBuilder"; Path = "/mnt/c/Users/Jaykul/Projects/Modules/ModuleBuilder/Source"; }
40-
@{ RelativeTo = "/mnt/c/Users/Jaykul/Projects/Modules/ModuleBuilder"; Path = "/mnt/c/Users/Jaykul/Projects/Output"; }
41-
@{ RelativeTo = "/mnt/c/Users/Jaykul/Projects/Modules/ModuleBuilder"; Path = "/mnt/c/Users/Jaykul/Projects/"; }
42-
# Weird PowerShell Paths
43-
@{ RelativeTo = "TestDrive:/Projects/Modules/ModuleBuilder"; Path = "TestDrive:\Projects" }
44-
@{ RelativeTo = "TestDrive:/Projects/Modules/ModuleBuilder"; Path = "TestDrive:/Projects" }
45-
@{ RelativeTo = "TestDrive:/Projects"; Path = "TestDrive:/Projects/Modules/ModuleBuilder" }
46-
)
47-
48-
# On Windows, there's a shortcut when the path points to totally different drive letters:
49-
if ($PSVersionTable.Platform -eq "Win32NT") {
50-
$TestCases += @(
51-
@{ RelativeTo = "G:\Projects\Modules\MyModule\Source\Public"; Path = "C:\Modules\MyModule" }
52-
@{ RelativeTo = "G:\Projects\Modules\MyModule\Source\Public"; Path = "F:\Projects\Modules\MyModule" }
28+
BeforeDiscovery {
29+
$TestCases = @(
30+
@{ RelativeTo = "G:\Module"; Path = "G:\Module\Source" }
31+
@{ RelativeTo = "G:\Module"; Path = "G:\Module\Source\Public" }
32+
@{ RelativeTo = "G:\Module\Source"; Path = "G:\Module\Output" }
33+
@{ RelativeTo = "G:\Module\Source"; Path = "G:\Module\Output\" }
34+
@{ RelativeTo = "G:\Module\Source\"; Path = "G:\Module\Output\" }
35+
@{ RelativeTo = "G:\Module\Source\"; Path = "G:\Module\Output" }
36+
@{ RelativeTo = "G:\Projects\Modules\MyModule\Source\Public"; Path = "G:\Modules\MyModule" }
37+
@{ RelativeTo = "G:\Projects\Modules\MyModule\Source\Public"; Path = "G:\Projects\Modules\MyModule" }
38+
# These ones are backwards, but they still work
39+
@{ RelativeTo = "G:\Module\Source" ; Path = "G:\Module" }
40+
@{ RelativeTo = "G:\Module\Source\Public"; Path = "G:\Module" }
41+
# These are linux-like:
42+
@{ RelativeTo = "/mnt/c/Users/Jaykul/Projects/Modules/ModuleBuilder"; Path = "/mnt/c/Users/Jaykul/Projects/Modules/ModuleBuilder/Source"; }
43+
@{ RelativeTo = "/mnt/c/Users/Jaykul/Projects/Modules/ModuleBuilder"; Path = "/mnt/c/Users/Jaykul/Projects/Output"; }
44+
@{ RelativeTo = "/mnt/c/Users/Jaykul/Projects/Modules/ModuleBuilder"; Path = "/mnt/c/Users/Jaykul/Projects/"; }
45+
# Weird PowerShell Paths
46+
@{ RelativeTo = "TestDrive:/Projects/Modules/ModuleBuilder"; Path = "TestDrive:\Projects" }
47+
@{ RelativeTo = "TestDrive:/Projects/Modules/ModuleBuilder"; Path = "TestDrive:/Projects" }
48+
@{ RelativeTo = "TestDrive:/Projects"; Path = "TestDrive:/Projects/Modules/ModuleBuilder" }
5349
)
50+
51+
# On Windows, there's a shortcut when the path points to totally different drive letters:
52+
if ($PSVersionTable.Platform -eq "Win32NT") {
53+
$TestCases += @(
54+
@{ RelativeTo = "G:\Projects\Modules\MyModule\Source\Public"; Path = "C:\Modules\MyModule" }
55+
@{ RelativeTo = "G:\Projects\Modules\MyModule\Source\Public"; Path = "F:\Projects\Modules\MyModule" }
56+
)
57+
}
5458
}
5559

5660
It "Returns the same result as Path.GetRelativePath for <Path>" -TestCases $TestCases {

‎Tests/Private/ImportModuleManifest.Tests.ps1

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
Describe "ImportModuleManifest" {
33

44
Context "Mandatory Parameter" {
5-
$CommandInfo = InModuleScope ModuleBuilder { Get-Command ImportModuleManifest }
5+
BeforeAll {
6+
$CommandInfo = InModuleScope ModuleBuilder { Get-Command ImportModuleManifest }
7+
}
68

79
It 'has a mandatory Path parameter for the PSPath by pipeline' {
810
$Path = $CommandInfo.Parameters['Path']
Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,23 @@
11
#requires -Module ModuleBuilder
22
Describe "InitializeBuild" {
3-
. $PSScriptRoot\..\Convert-FolderSeparator.ps1
3+
BeforeAll {
4+
. $PSScriptRoot\..\Convert-FolderSeparator.ps1
5+
}
46

57
Context "It collects the initial data" {
8+
BeforeAll {
9+
# Note that "Path" is an alias for "SourcePath"
10+
New-Item "TestDrive:\build.psd1" -Type File -Force -Value '@{
11+
Path = ".\Source\MyModule.psd1"
12+
SourceDirectories = @("Classes", "Private", "Public")
13+
}'
614

7-
# Note that "Path" is an alias for "SourcePath"
8-
New-Item "TestDrive:\build.psd1" -Type File -Force -Value '@{
9-
Path = ".\Source\MyModule.psd1"
10-
SourceDirectories = @("Classes", "Private", "Public")
11-
}'
12-
13-
New-Item "TestDrive:\Source\" -Type Directory
15+
New-Item "TestDrive:\Source\" -Type Directory
1416

15-
New-ModuleManifest "TestDrive:\Source\MyModule.psd1" -RootModule "MyModule.psm1" -Author "Test Manager" -ModuleVersion "1.0.0"
17+
New-ModuleManifest "TestDrive:\Source\MyModule.psd1" -RootModule "MyModule.psm1" -Author "Test Manager" -ModuleVersion "1.0.0"
1618

17-
$Result = @{}
19+
$Result = @{}
20+
}
1821

1922
It "Handles Build-Module parameters, and the build.psd1 configuration" {
2023
Push-Location TestDrive:\
@@ -43,30 +46,33 @@ Describe "InitializeBuild" {
4346
Pop-Location
4447
$Result.Result | Should -Not -BeOfType [System.Management.Automation.ErrorRecord]
4548
}
46-
$Result = $Result.Result
4749
# $Result | Format-List * -Force | Out-Host
4850

4951
It "Returns the ModuleInfo combined with the BuildInfo" {
50-
$Result.Name | Should -Be "MyModule"
51-
$Result.SourceDirectories | Should -Be @("Classes", "Private", "Public")
52-
(Convert-FolderSeparator $Result.ModuleBase) | Should -Be (Convert-FolderSeparator "TestDrive:\Source")
53-
(Convert-FolderSeparator $Result.SourcePath) | Should -Be (Convert-FolderSeparator "TestDrive:\Source\MyModule.psd1")
52+
$Result.Result.Name | Should -Be "MyModule"
53+
$Result.Result.SourceDirectories | Should -Be @("Classes", "Private", "Public")
54+
55+
(Convert-FolderSeparator $Result.Result.ModuleBase)
56+
| Should -Be (Convert-FolderSeparator "TestDrive:\Source")
57+
58+
(Convert-FolderSeparator $Result.Result.SourcePath)
59+
| Should -Be (Convert-FolderSeparator "TestDrive:\Source\MyModule.psd1")
5460
}
5561

5662
It "Returns default values from the Build Command" {
57-
$Result.OutputDirectory | Should -Be ".\Output"
63+
$Result.Result.OutputDirectory | Should -Be ".\Output"
5864
}
5965

60-
It "Returns overriden values from the build manifest" {
61-
$Result.SourceDirectories | Should -Be @("Classes", "Private", "Public")
66+
It "Returns overridden values from the build manifest" {
67+
$Result.Result.SourceDirectories | Should -Be @("Classes", "Private", "Public")
6268
}
6369

64-
It "Returns overriden values from parameters" {
65-
$Result.SourcePath | Should -Be (Convert-Path 'TestDrive:\Source\MyModule.psd1')
70+
It "Returns overridden values from parameters" {
71+
$Result.Result.SourcePath | Should -Be (Convert-Path 'TestDrive:\Source\MyModule.psd1')
6672
}
6773

6874
It "Sets VersionedOutputDirectory FALSE when UnversionedOutputDirectory is TRUE" {
69-
$Result.VersionedOutputDirectory | Should -Be $false
75+
$Result.Result.VersionedOutputDirectory | Should -Be $false
7076
}
7177
}
7278
}

‎Tests/Private/MoveUsingStatements.Tests.ps1

Lines changed: 84 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
#requires -Module ModuleBuilder
22
Describe "MoveUsingStatements" {
3-
Context "Necessary Parameters" {
3+
BeforeAll {
44
$CommandInfo = InModuleScope ModuleBuilder { Get-Command MoveUsingStatements }
5+
}
6+
7+
Context "Necessary Parameters" {
58

69
It 'has a mandatory AST parameter' {
710
$AST = $CommandInfo.Parameters['AST']
@@ -19,78 +22,79 @@ Describe "MoveUsingStatements" {
1922
}
2023

2124
Context "Moving Using Statements to the beginning of the file" {
22-
23-
$MoveUsingStatementsCmd = InModuleScope ModuleBuilder {
24-
$null = Mock Write-Warning { }
25-
{ param($RootModule)
26-
ConvertToAst $RootModule | MoveUsingStatements
25+
BeforeAll {
26+
$MoveUsingStatementsCmd = InModuleScope ModuleBuilder {
27+
$null = Mock Write-Warning { }
28+
{ param($RootModule)
29+
ConvertToAst $RootModule | MoveUsingStatements
30+
}
2731
}
28-
}
2932

30-
$TestCases = @(
31-
@{
32-
TestCaseName = 'Moves all using statements in `n terminated files to the top'
33-
PSM1File = "function x {`n}`n" +
34-
"using namespace System.IO`n`n" + #UsingMustBeAtStartOfScript
35-
"function y {`n}`n" +
36-
"using namespace System.Drawing" #UsingMustBeAtStartOfScript
37-
ErrorBefore = 2
38-
ErrorAfter = 0
39-
},
40-
@{
41-
TestCaseName = 'Moves all using statements in`r`n terminated files to the top'
42-
PSM1File = "function x {`r`n}`r`n" +
43-
"USING namespace System.IO`r`n`r`n" + #UsingMustBeAtStartOfScript
44-
"function y {`r`n}`r`n" +
45-
"USING namespace System.Drawing" #UsingMustBeAtStartOfScript
46-
ErrorBefore = 2
47-
ErrorAfter = 0
48-
},
49-
@{
50-
TestCaseName = 'Prevents duplicate using statements'
51-
PSM1File = "using namespace System.IO`r`n" + #UsingMustBeAtStartOfScript
52-
"function x {`r`n}`r`n`r`n" +
53-
"using namespace System.IO`r`n" + #UsingMustBeAtStartOfScript
54-
"function y {`r`n}`r`n" +
55-
"USING namespace System.IO" #UsingMustBeAtStartOfScript
56-
ExpectedResult = "using namespace System.IO`r`n" +
57-
"#using namespace System.IO`r`n" +
58-
"function x {`r`n}`r`n`r`n" +
59-
"#using namespace System.IO`r`n" +
60-
"function y {`r`n}`r`n" +
61-
"#USING namespace System.IO"
62-
ErrorBefore = 2
63-
ErrorAfter = 0
64-
},
65-
@{
66-
TestCaseName = 'Does not change the content again if there are no out-of-place using statements'
67-
PSM1File = "using namespace System.IO`r`n`r`n" +
68-
"using namespace System.Drawing`r`n" +
69-
"function x {`r`n}`r`n" +
70-
"function y {`r`n}`r`n"
71-
ErrorBefore = 0
72-
ErrorAfter = 0
73-
},
74-
@{
75-
TestCaseName = 'Moves using statements even if types are used'
76-
PSM1File = "function x {`r`n}`r`n" +
77-
"using namespace System.IO`r`n`r`n" + #UsingMustBeAtStartOfScript
78-
"function y {`r`n}`r`n" +
79-
"using namespace System.Collections.Generic" + #UsingMustBeAtStartOfScript
80-
"function z { [Dictionary[String,PSObject]]::new() }" #TypeNotFound
81-
ErrorBefore = 3
82-
ErrorAfter = 0
83-
},
84-
@{
85-
TestCaseName = 'Moves using statements even when there are (other) parse errors'
86-
PSM1File = "using namespace System.IO`r`n`r`n" +
87-
"function x {`r`n}`r`n" +
88-
"using namespace System.Drawing`r`n" + # UsingMustBeAtStartOfScript
89-
"function y {`r`n}`r`n}" # Extra } at the end
90-
ErrorBefore = 2
91-
ErrorAfter = 1
92-
}
93-
)
33+
$TestCases = @(
34+
@{
35+
TestCaseName = 'Moves all using statements in `n terminated files to the top'
36+
PSM1File = "function x {`n}`n" +
37+
"using namespace System.IO`n`n" + #UsingMustBeAtStartOfScript
38+
"function y {`n}`n" +
39+
"using namespace System.Drawing" #UsingMustBeAtStartOfScript
40+
ErrorBefore = 2
41+
ErrorAfter = 0
42+
},
43+
@{
44+
TestCaseName = 'Moves all using statements in`r`n terminated files to the top'
45+
PSM1File = "function x {`r`n}`r`n" +
46+
"USING namespace System.IO`r`n`r`n" + #UsingMustBeAtStartOfScript
47+
"function y {`r`n}`r`n" +
48+
"USING namespace System.Drawing" #UsingMustBeAtStartOfScript
49+
ErrorBefore = 2
50+
ErrorAfter = 0
51+
},
52+
@{
53+
TestCaseName = 'Prevents duplicate using statements'
54+
PSM1File = "using namespace System.IO`r`n" + #UsingMustBeAtStartOfScript
55+
"function x {`r`n}`r`n`r`n" +
56+
"using namespace System.IO`r`n" + #UsingMustBeAtStartOfScript
57+
"function y {`r`n}`r`n" +
58+
"USING namespace System.IO" #UsingMustBeAtStartOfScript
59+
ExpectedResult = "using namespace System.IO`r`n" +
60+
"#using namespace System.IO`r`n" +
61+
"function x {`r`n}`r`n`r`n" +
62+
"#using namespace System.IO`r`n" +
63+
"function y {`r`n}`r`n" +
64+
"#USING namespace System.IO"
65+
ErrorBefore = 2
66+
ErrorAfter = 0
67+
},
68+
@{
69+
TestCaseName = 'Does not change the content again if there are no out-of-place using statements'
70+
PSM1File = "using namespace System.IO`r`n`r`n" +
71+
"using namespace System.Drawing`r`n" +
72+
"function x {`r`n}`r`n" +
73+
"function y {`r`n}`r`n"
74+
ErrorBefore = 0
75+
ErrorAfter = 0
76+
},
77+
@{
78+
TestCaseName = 'Moves using statements even if types are used'
79+
PSM1File = "function x {`r`n}`r`n" +
80+
"using namespace System.IO`r`n`r`n" + #UsingMustBeAtStartOfScript
81+
"function y {`r`n}`r`n" +
82+
"using namespace System.Collections.Generic" + #UsingMustBeAtStartOfScript
83+
"function z { [Dictionary[String,PSObject]]::new() }" #TypeNotFound
84+
ErrorBefore = 3
85+
ErrorAfter = 0
86+
},
87+
@{
88+
TestCaseName = 'Moves using statements even when there are (other) parse errors'
89+
PSM1File = "using namespace System.IO`r`n`r`n" +
90+
"function x {`r`n}`r`n" +
91+
"using namespace System.Drawing`r`n" + # UsingMustBeAtStartOfScript
92+
"function y {`r`n}`r`n}" # Extra } at the end
93+
ErrorBefore = 2
94+
ErrorAfter = 1
95+
}
96+
)
97+
}
9498

9599
It '<TestCaseName>' -TestCases $TestCases {
96100
param($TestCaseName, $PSM1File, $ErrorBefore, $ErrorAfter, $ExpectedResult)
@@ -123,14 +127,15 @@ Describe "MoveUsingStatements" {
123127
}
124128

125129
Context "When MoveUsingStatements should do nothing" {
126-
127-
$MoveUsingStatementsCmd = InModuleScope ModuleBuilder {
128-
$null = Mock Write-Warning {}
129-
$null = Mock Set-Content {}
130-
$null = Mock Write-Debug {} -ParameterFilter { $Message -eq "No using statement errors found." }
131-
132-
{ param($RootModule)
133-
ConvertToAst $RootModule | MoveUsingStatements
130+
BeforeAll {
131+
$MoveUsingStatementsCmd = InModuleScope ModuleBuilder {
132+
$null = Mock Write-Warning {}
133+
$null = Mock Set-Content {}
134+
$null = Mock Write-Debug {} -ParameterFilter { $Message -eq "No using statement errors found." }
135+
136+
{ param($RootModule)
137+
ConvertToAst $RootModule | MoveUsingStatements
138+
}
134139
}
135140
}
136141

‎Tests/Private/ParseLineNumber.Tests.ps1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ Describe "ParseLineNumber" {
4545
$Source.SourceLineNumber | Should -Be 14
4646
}
4747

48-
It 'Should get <ScriptBlock> and <No file> and line number from errors at the console' {
48+
It 'Should get [ScriptBlock] and [No file] and line number from errors at the console' {
4949
$Source = InModuleScope ModuleBuilder { ParseLineNumber "at <ScriptBlock>, <No file>: line 1" }
5050

5151
$Source.SourceFile | Should -Be "<No file>"

‎Tests/Private/ResolveOutputFolder.Tests.ps1

Lines changed: 56 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,61 @@
11
#requires -Module ModuleBuilder
22
Describe "ResolveOutputFolder" {
3-
. $PSScriptRoot\..\Convert-FolderSeparator.ps1
4-
$CommandInTest = InModuleScope ModuleBuilder { Get-Command ResolveOutputFolder }
5-
filter ToTestDrive { "$_".Replace($TestDrive, "TestDrive:") }
3+
BeforeAll {
4+
. $PSScriptRoot\..\Convert-FolderSeparator.ps1
5+
$CommandInTest = InModuleScope ModuleBuilder { Get-Command ResolveOutputFolder }
6+
filter ToTestDrive { "$_".Replace($TestDrive, "TestDrive:") }
67

7-
$TestCases = [Hashtable[]]@(
8-
@{ # Be like Jaykul
9-
Source = "ModuleName/Source"
10-
Output = "ModuleName"
11-
Result = "ModuleName/1.2.3"
12-
Forced = "ModuleName/1.2.3"
13-
}
14-
@{ # Be like azure
15-
Source = "1/s"
16-
Output = "1/b"
17-
Result = "1/b/ModuleName"
18-
Forced = "1/b/ModuleName/1.2.3"
19-
}
20-
@{ # The default option would be Module/Source build to Module/Output
21-
Source = "ModuleName/Source"
22-
Output = "ModuleName/Output"
23-
Result = "ModuleName/Output/ModuleName"
24-
Forced = "ModuleName/Output/ModuleName/1.2.3"
25-
}
26-
@{ # Which is the same even without the common named parent
27-
Source = "Source"
28-
Output = "Output"
29-
Result = "Output/ModuleName"
30-
Forced = "Output/ModuleName/1.2.3"
31-
}
32-
@{ # An edge case, build straight to a modules folder
33-
Source = "ModuleName/Source"
34-
Output = "Modules"
35-
Result = "Modules/ModuleName"
36-
Forced = "Modules/ModuleName/1.2.3"
37-
}
38-
@{ # What if they pass in the correct path ahead of time?
39-
Source = "1/s"
40-
Output = "1/b/ModuleName"
41-
Result = "1/b/ModuleName"
42-
Forced = "1/b/ModuleName/1.2.3"
43-
}
44-
@{ # What if they pass in the correct path ahead of time?
45-
Source = "1/s"
46-
Output = "1/b/ModuleName/1.2.3"
47-
Result = "1/b/ModuleName/1.2.3"
48-
Forced = "1/b/ModuleName/1.2.3"
49-
}
50-
@{ # Super edge case: what if they pass in an incorrectly versioned output path?
51-
Source = "1/s"
52-
Output = "1/b/ModuleName/4.5.6"
53-
Result = "1/b/ModuleName/4.5.6/ModuleName"
54-
Forced = "1/b/ModuleName/4.5.6/ModuleName/1.2.3"
55-
}
56-
)
8+
$TestCases = [Hashtable[]]@(
9+
@{ # Be like Jaykul
10+
Source = "ModuleName/Source"
11+
Output = "ModuleName"
12+
Result = "ModuleName/1.2.3"
13+
Forced = "ModuleName/1.2.3"
14+
}
15+
@{ # Be like azure
16+
Source = "1/s"
17+
Output = "1/b"
18+
Result = "1/b/ModuleName"
19+
Forced = "1/b/ModuleName/1.2.3"
20+
}
21+
@{ # The default option would be Module/Source build to Module/Output
22+
Source = "ModuleName/Source"
23+
Output = "ModuleName/Output"
24+
Result = "ModuleName/Output/ModuleName"
25+
Forced = "ModuleName/Output/ModuleName/1.2.3"
26+
}
27+
@{ # Which is the same even without the common named parent
28+
Source = "Source"
29+
Output = "Output"
30+
Result = "Output/ModuleName"
31+
Forced = "Output/ModuleName/1.2.3"
32+
}
33+
@{ # An edge case, build straight to a modules folder
34+
Source = "ModuleName/Source"
35+
Output = "Modules"
36+
Result = "Modules/ModuleName"
37+
Forced = "Modules/ModuleName/1.2.3"
38+
}
39+
@{ # What if they pass in the correct path ahead of time?
40+
Source = "1/s"
41+
Output = "1/b/ModuleName"
42+
Result = "1/b/ModuleName"
43+
Forced = "1/b/ModuleName/1.2.3"
44+
}
45+
@{ # What if they pass in the correct path ahead of time?
46+
Source = "1/s"
47+
Output = "1/b/ModuleName/1.2.3"
48+
Result = "1/b/ModuleName/1.2.3"
49+
Forced = "1/b/ModuleName/1.2.3"
50+
}
51+
@{ # Super edge case: what if they pass in an incorrectly versioned output path?
52+
Source = "1/s"
53+
Output = "1/b/ModuleName/4.5.6"
54+
Result = "1/b/ModuleName/4.5.6/ModuleName"
55+
Forced = "1/b/ModuleName/4.5.6/ModuleName/1.2.3"
56+
}
57+
)
58+
}
5759
Context "Build ModuleName" {
5860
It "From '<Source>' to '<Output>' creates '<Result>'" -TestCases $TestCases {
5961
param($Source, $Output, $Result)
@@ -125,7 +127,7 @@ Describe "ResolveOutputFolder" {
125127
Output = Convert-FolderSeparator "TestDrive:/ModuleName/"
126128
}
127129

128-
{ &$CommandInTest @Parameters -Name ModuleName -Target Build -Version 1.2.3 -Force } | Should -throw "There is a file in the way"
130+
{ &$CommandInTest @Parameters -Name ModuleName -Target Build -Version 1.2.3 -Force } | Should -throw "*There is a file in the way*"
129131
}
130132
}
131133
}

‎Tests/Private/SetModuleContent.Tests.ps1

Lines changed: 71 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
Describe "SetModuleContent" {
22

33
Context "Necessary Parameters" {
4-
$CommandInfo = InModuleScope ModuleBuilder { Get-Command SetModuleContent }
4+
BeforeAll {
5+
$CommandInfo = InModuleScope ModuleBuilder { Get-Command SetModuleContent }
6+
}
57

68
It "has a mandatory string OutputPath parameter" {
79
$OutputPath = $CommandInfo.Parameters['OutputPath']
@@ -30,37 +32,40 @@ Describe "SetModuleContent" {
3032
$Encoding.ParameterType | Should -Be ([String])
3133
$Encoding.Attributes.Where{$_ -is [Parameter]}.Mandatory | Should -Be $False
3234
}
33-
34-
$CommandInfo.Parameters['OutputPath']
35+
AfterAll {
36+
$CommandInfo.Parameters['OutputPath']
37+
}
3538
}
3639

3740

3841
Context "Joining files into one" {
39-
${global:mock get content index} = 1
42+
BeforeAll {
43+
${global:mock get content index} = 1
4044

41-
Mock Get-Content -ModuleName ModuleBuilder {
42-
"Script Content"
43-
"File $((${global:mock get content index}++))"
44-
"From $Path"
45-
}
45+
Mock Get-Content -ModuleName ModuleBuilder {
46+
"Script Content"
47+
"File $((${global:mock get content index}++))"
48+
"From $Path"
49+
}
4650

47-
Mock Resolve-Path -ModuleName ModuleBuilder {
48-
$path -replace "TestDrive:\\", ".\"
49-
} -ParameterFilter { $Relative }
51+
Mock Resolve-Path -ModuleName ModuleBuilder {
52+
$path -replace "TestDrive:\\", ".\"
53+
} -ParameterFilter { $Relative }
5054

5155

5256

53-
InModuleScope ModuleBuilder {
54-
$Files = "TestDrive:\Private\First.ps1",
55-
"TestDrive:\Private\Second.ps1",
56-
"TestDrive:\Public\Third.ps1"
57-
SetModuleContent -Source $Files -Output TestDrive:\Output.psm1
57+
InModuleScope ModuleBuilder {
58+
$Files = "TestDrive:\Private\First.ps1",
59+
"TestDrive:\Private\Second.ps1",
60+
"TestDrive:\Public\Third.ps1"
61+
SetModuleContent -Source $Files -Output TestDrive:\Output.psm1
62+
}
5863
}
5964

6065
It "Calls get-content on every source file" {
61-
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Private\First.ps1" }
62-
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Private\Second.ps1" }
63-
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Public\Third.ps1" }
66+
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Private\First.ps1" } -Scope Context
67+
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Private\Second.ps1" } -Scope Context
68+
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Public\Third.ps1" } -Scope Context
6469
}
6570

6671
It "Copies all three files into the Output" {
@@ -77,36 +82,36 @@ Describe "SetModuleContent" {
7782
}
7883

7984
Context "Supports adding Prefix and Suffix content" {
80-
${global:mock get content index} = 1
81-
82-
Mock Get-Content -ModuleName ModuleBuilder {
83-
"Script Content"
84-
"File $((${global:mock get content index}++))"
85-
"From $Path"
86-
}
85+
BeforeAll {
86+
${global:mock get content index} = 1
8787

88-
Mock Resolve-Path -ModuleName ModuleBuilder {
89-
if ($path -match "TestDrive:") {
90-
$path -replace "TestDrive:\\", ".\"
91-
} else {
92-
write-error "$path not found"
88+
Mock Get-Content -ModuleName ModuleBuilder {
89+
"Script Content"
90+
"File $((${global:mock get content index}++))"
91+
"From $Path"
9392
}
94-
} -ParameterFilter { $Relative }
9593

94+
Mock Resolve-Path -ModuleName ModuleBuilder {
95+
if ($path -match "TestDrive:") {
96+
$path -replace "TestDrive:\\", ".\"
97+
}
98+
} -ParameterFilter { $Relative }
99+
100+
InModuleScope ModuleBuilder {
101+
$MostlyFiles = "using module Configuration",
102+
"TestDrive:\Private\First.ps1",
103+
"TestDrive:\Private\Second.ps1",
104+
"TestDrive:\Public\Third.ps1",
105+
"Export-ModuleMember Stuff"
96106

97-
InModuleScope ModuleBuilder {
98-
$Files = "using module Configuration",
99-
"TestDrive:\Private\First.ps1",
100-
"TestDrive:\Private\Second.ps1",
101-
"TestDrive:\Public\Third.ps1",
102-
"Export-ModuleMember Stuff"
103-
SetModuleContent -Source $Files -Output TestDrive:\Output.psm1
107+
SetModuleContent -Source $MostlyFiles -Output TestDrive:\Output.psm1
108+
}
104109
}
105110

106111
It "Calls get-content on every source file" {
107-
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Private\First.ps1" }
108-
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Private\Second.ps1" }
109-
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Public\Third.ps1" }
112+
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Private\First.ps1" } -Scope Context
113+
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Private\Second.ps1" } -Scope Context
114+
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Public\Third.ps1" } -Scope Context
110115
}
111116

112117
It "Copies all three files into the Output" {
@@ -135,36 +140,36 @@ Describe "SetModuleContent" {
135140
}
136141

137142
Context "Adds a newline before the content of each script file" {
138-
${global:mock get content index} = 1
139-
140-
Mock Get-Content -ModuleName ModuleBuilder {
141-
"Script Content"
142-
"File $((${global:mock get content index}++))"
143-
"From $Path"
144-
}
143+
BeforeAll {
144+
${global:mock get content index} = 1
145145

146-
Mock Resolve-Path -ModuleName ModuleBuilder {
147-
if ($path -match "TestDrive:") {
148-
$path -replace "TestDrive:\\", ".\"
149-
} else {
150-
write-error "$path not found"
146+
Mock Get-Content -ModuleName ModuleBuilder {
147+
"Script Content"
148+
"File $((${global:mock get content index}++))"
149+
"From $Path"
151150
}
152-
} -ParameterFilter { $Relative }
153151

152+
Mock Resolve-Path -ModuleName ModuleBuilder {
153+
if ($path -match "TestDrive:") {
154+
$path -replace "TestDrive:\\", ".\"
155+
}
156+
} -ParameterFilter { $Relative }
154157

155-
InModuleScope ModuleBuilder {
156-
$Files = "using module Configuration",
157-
"TestDrive:\Private\First.ps1",
158-
"TestDrive:\Private\Second.ps1",
159-
"TestDrive:\Public\Third.ps1",
160-
"Export-ModuleMember Stuff"
161-
SetModuleContent -Source $Files -Output TestDrive:\Output.psm1
158+
159+
InModuleScope ModuleBuilder {
160+
$Files = "using module Configuration",
161+
"TestDrive:\Private\First.ps1",
162+
"TestDrive:\Private\Second.ps1",
163+
"TestDrive:\Public\Third.ps1",
164+
"Export-ModuleMember Stuff"
165+
SetModuleContent -Source $Files -Output TestDrive:\Output.psm1
166+
}
162167
}
163168

164169
It "Calls get-content on every source file" {
165-
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Private\First.ps1" }
166-
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Private\Second.ps1" }
167-
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Public\Third.ps1" }
170+
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Private\First.ps1" } -Scope Context
171+
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Private\Second.ps1" } -Scope Context
172+
Assert-MockCalled Get-Content -ModuleName ModuleBuilder -ParameterFilter { $Path -eq ".\Public\Third.ps1" } -Scope Context
168173
}
169174

170175
It "Copies all three files into the Output" {

‎Tests/Public/Build-Module.Tests.ps1

Lines changed: 434 additions & 422 deletions
Large diffs are not rendered by default.

‎build.requires.psd1

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# https://github.com/marketplace/actions/modulefast
2+
@{
3+
Configuration = ":[1.5.0, 2.0)"
4+
Metadata = ":[1.5.1, 2.0)"
5+
Pester = ":[5.0, 6.0)"
6+
ModuleBuilder = ":[3.0.0, 4.0)"
7+
PSScriptAnalyzer = ":[1.21.0, 2.0)"
8+
InvokeBuild = ":[5.10.4, 6.0)"
9+
}

0 commit comments

Comments
 (0)
Please sign in to comment.