kitchen-pester 0.12.1 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: da53197e406192ac305bcdc54725ecd52787ee9b9bccff32e8438f7bd8f31796
4
- data.tar.gz: 0c28027331124a37ce8dd730598b191a26f3e69df8b4240921eead3f289e7c52
3
+ metadata.gz: e31dac41f9925e0fb86d2b96a2ead03a1c1dabb42adbf038ef572966aeb6d7db
4
+ data.tar.gz: 9047b382ad4d31572b7515aeb70d495e54019a87207cad463598938a669c38f7
5
5
  SHA512:
6
- metadata.gz: bff325f80a68eb821aecd0d761c29e4caa5c6cb9bd2f738f13219d3c9c8496ee73d34b2dbaa6e41c44392971f85fce6387765a1c4c81a6e41a7801c42e2987ee
7
- data.tar.gz: d1ad67092b11dc19c7d455a1b51c62a55d1aeb5aaed613526005f2f264710d8504de18a96b56fb27646304001f5cc661e9b8945d909c79a71b3f212275bd4f1a
6
+ metadata.gz: 73bcc2e6ba82f652ca7ffd81d27c05b96d3eb1e0101043b0207d7dd583b8c040979f23a37f1b6c59c719979e026ce2df3ff7f8c319cb1dd41783668d3f0cd3e0
7
+ data.tar.gz: 7b63adcc2817a530bc5ddc8a2feb159353f80217abd739c8aba2019a222c6a841911c0a543dd8cb2fdf4159a3de9ae16aa3426333d71a4dd8175bb52dc0f9d80
data/Gemfile CHANGED
@@ -11,7 +11,7 @@ group :integration do
11
11
  end
12
12
 
13
13
  group :changelog do
14
- gem "github_changelog_generator", "1.15.2"
14
+ gem "github_changelog_generator", "1.16.4"
15
15
  end
16
16
 
17
17
  group :debug do
data/Rakefile CHANGED
@@ -1,5 +1,3 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
1
  require "bundler/gem_tasks"
4
2
 
5
3
  require "rake/testtask"
@@ -25,7 +23,7 @@ desc "Run all quality tasks"
25
23
  task quality: :style
26
24
 
27
25
  begin
28
- require "yard"
26
+ require "yard" unless defined?(YARD)
29
27
  YARD::Rake::YardocTask.new
30
28
  rescue LoadError
31
29
  puts "yard is not available. (sudo) gem install yard to generate yard documentation."
@@ -1,5 +1,4 @@
1
- # encoding: utf-8
2
- lib = File.expand_path("../lib", __FILE__)
1
+ lib = File.expand_path("lib", __dir__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
 
5
4
  require "kitchen/verifier/pester_version"
@@ -22,5 +21,5 @@ Gem::Specification.new do |spec|
22
21
  spec.add_development_dependency "minitest", "~> 5.3", "< 5.15"
23
22
  spec.add_development_dependency "mocha", "~> 1.1"
24
23
 
25
- spec.add_dependency "test-kitchen", ">= 1.10", "< 3"
24
+ spec.add_dependency "test-kitchen", ">= 1.10", "< 4"
26
25
  end
@@ -1,5 +1,3 @@
1
- # -*- encoding: utf-8 -*-
2
- #
3
1
  # Author:: Steven Murawski (<steven.murawski@gmail.com>)
4
2
  #
5
3
  # Copyright (C) 2015, Steven Murawski
@@ -16,9 +14,12 @@
16
14
  # See the License for the specific language governing permissions and
17
15
  # limitations under the License.
18
16
 
19
- require "pathname"
17
+ require "fileutils" unless defined?(FileUtils)
18
+ require "pathname" unless defined?(Pathname)
19
+ require "kitchen/util"
20
20
  require "kitchen/verifier/base"
21
21
  require "kitchen/version"
22
+ require "base64" unless defined?(Base64)
22
23
  require_relative "pester_version"
23
24
 
24
25
  module Kitchen
@@ -32,9 +33,39 @@ module Kitchen
32
33
  plugin_version Kitchen::Verifier::PESTER_VERSION
33
34
 
34
35
  default_config :restart_winrm, false
35
- default_config :test_folder
36
- default_config :use_local_pester_module, false
37
- default_config :downloads, ["./PesterTestResults.xml"] => "./testresults"
36
+ default_config :test_folder, "tests"
37
+ default_config :remove_builtin_powershellget, true
38
+ default_config :remove_builtin_pester, true
39
+ default_config :skip_pester_install, false
40
+ default_config :bootstrap, {
41
+ repository_url: "https://www.powershellgallery.com/api/v2",
42
+ modules: [],
43
+ }
44
+ default_config :register_repository, []
45
+ default_config :pester_install, {
46
+ SkipPublisherCheck: true,
47
+ Force: true,
48
+ ErrorAction: "Stop",
49
+ }
50
+ default_config :pester_configuration, {
51
+ run: {
52
+ path: ".",
53
+ PassThru: true,
54
+ },
55
+ TestResult: {
56
+ Enabled: true,
57
+ OutputPath: "PesterTestResults.xml",
58
+ TestSuiteName: "",
59
+ },
60
+ Output: {
61
+ Verbosity: "Detailed",
62
+ },
63
+ }
64
+ default_config :install_modules, []
65
+ default_config :downloads, { "./PesterTestResults.xml" => "./testresults/" }
66
+ default_config :copy_folders, []
67
+ default_config :sudo, false
68
+ default_config :shell, nil
38
69
 
39
70
  # Creates a new Verifier object using the provided configuration data
40
71
  # which will be merged with any default configuration.
@@ -64,21 +95,56 @@ module Kitchen
64
95
  # end
65
96
  def create_sandbox
66
97
  super
67
- prepare_powershell_modules
98
+ prepare_supporting_psmodules
99
+ prepare_copy_folders
68
100
  prepare_pester_tests
69
101
  prepare_helpers
102
+
103
+ debug("\n\n")
104
+ debug("Sandbox content:\n")
105
+ list_files(sandbox_path).each do |f|
106
+ debug(" #{f}")
107
+ end
70
108
  end
71
109
 
72
110
  # Generates a command string which will install and configure the
73
111
  # verifier software on an instance. If no work is required, then `nil`
74
112
  # will be returned.
113
+ # PowerShellGet & Pester Bootstrap are done in prepare_command (after sandbox is transferred)
114
+ # so that we can use the PesterUtil.psm1
75
115
  #
76
116
  # @return [String] a command string
77
117
  def install_command
78
- return if local_suite_files.empty?
79
- return if config[:use_local_pester_module]
118
+ # the sandbox has not yet been copied to the SUT.
119
+ install_command_string = <<-PS1
120
+ Write-Verbose 'Running Install Command...'
121
+ $modulesToRemove = @(
122
+ if ($#{config[:remove_builtin_powershellget]}) {
123
+ Get-module -ListAvailable -FullyQualifiedName @{ModuleName = 'PackageManagement'; RequiredVersion = '1.0.0.1'}
124
+ Get-module -ListAvailable -FullyQualifiedName @{ModuleName = 'PowerShellGet'; RequiredVersion = '1.0.0.1'}
125
+ }
80
126
 
81
- really_wrap_shell_code(install_command_script)
127
+ if ($#{config[:remove_builtin_pester]}) {
128
+ Get-module -ListAvailable -FullyQualifiedName @{ModuleName = 'Pester'; RequiredVersion = '3.4.0'}
129
+ }
130
+ )
131
+
132
+ if ($modulesToRemove.ModuleBase.Count -eq 0) {
133
+ # for PS7 on linux
134
+ return
135
+ }
136
+
137
+ $modulesToRemove.ModuleBase | Foreach-Object {
138
+ $ModuleBaseLeaf = Split-Path -Path $_ -Leaf
139
+ if ($ModuleBaseLeaf -as [System.version]) {
140
+ Remove-Item -force -Recurse (Split-Path -Parent -Path $_) -ErrorAction SilentlyContinue
141
+ }
142
+ else {
143
+ Remove-Item -force -Recurse $_ -ErrorAction SilentlyContinue
144
+ }
145
+ }
146
+ PS1
147
+ really_wrap_shell_code(Util.outdent!(install_command_string))
82
148
  end
83
149
 
84
150
  # Generates a command string which will perform any data initialization
@@ -97,7 +163,11 @@ module Kitchen
97
163
  # required, then `nil` will be returned.
98
164
  #
99
165
  # @return [String] a command string
100
- def prepare_command; end
166
+ def prepare_command
167
+ info("Preparing the SUT and Pester dependencies...")
168
+ resolve_downloads_paths!
169
+ really_wrap_shell_code(install_command_script)
170
+ end
101
171
 
102
172
  # Generates a command string which will invoke the main verifier
103
173
  # command on the prepared instance. If no work is required, then `nil`
@@ -105,9 +175,38 @@ module Kitchen
105
175
  #
106
176
  # @return [String] a command string
107
177
  def run_command
108
- return if local_suite_files.empty?
178
+ really_wrap_shell_code(invoke_pester_scriptblock)
179
+ end
109
180
 
110
- really_wrap_shell_code(run_command_script)
181
+ # Resolves the remote Downloads path from the verifier root path,
182
+ # unless they're absolute path (starts with / or C:\)
183
+ # This updates the config[:downloads], nothing (nil) is returned.
184
+ #
185
+ # @return [nil] updates config downloads
186
+ def resolve_downloads_paths!
187
+ info("Resolving Downloads path from config.")
188
+ config[:downloads] = config[:downloads]
189
+ .map do |source, destination|
190
+ source = source.to_s
191
+ info(" resolving remote source's absolute path.")
192
+ unless source.match?('^/|^[a-zA-Z]:[\\/]') # is Absolute?
193
+ info(" '#{source}' is a relative path, resolving to: #{File.join(config[:root_path], source)}")
194
+ source = File.join(config[:root_path], source.to_s).to_s
195
+ end
196
+
197
+ if destination.match?('\\$|/$') # is Folder (ends with / or \)
198
+ destination = File.join(destination, File.basename(source)).to_s
199
+ end
200
+ info(" Destination: #{destination}")
201
+ if !File.directory?(File.dirname(destination))
202
+ FileUtils.mkdir_p(File.dirname(destination))
203
+ else
204
+ info(" Directory #{File.dirname(destination)} seem to exist.")
205
+ end
206
+
207
+ [ source, destination ]
208
+ end
209
+ nil # make sure we do not return anything
111
210
  end
112
211
 
113
212
  # Download functionality was added to the base verifier behavior after
@@ -116,7 +215,9 @@ module Kitchen
116
215
  def call(state)
117
216
  super
118
217
  ensure
119
- download_test_files(state)
218
+ info("Ensure download test files.")
219
+ download_test_files(state) unless config[:downloads].nil?
220
+ info("Download complete.")
120
221
  end
121
222
  else
122
223
  def call(state)
@@ -124,179 +225,291 @@ module Kitchen
124
225
  rescue
125
226
  # If the verifier reports failure, we need to download the files ourselves.
126
227
  # Test Kitchen's base verifier doesn't have the download in an `ensure` block.
127
- download_test_files(state)
128
-
228
+ info("Rescue to download test files.")
229
+ download_test_files(state) unless config[:downloads].nil?
129
230
  # Rethrow original exception, we still want to register the failure.
130
231
  raise
131
232
  end
132
233
  end
133
234
 
134
235
  # private
135
- def run_command_script
136
- <<-CMD
137
- Import-Module -Name Pester -Force
236
+ def invoke_pester_scriptblock
237
+ <<-PS1
238
+ $PesterModule = Import-Module -Name Pester -Force -ErrorAction Stop -PassThru
239
+
240
+ $TestPath = Join-Path "#{config[:root_path]}" -ChildPath "suites"
241
+ $OutputFilePath = Join-Path "#{config[:root_path]}" -ChildPath 'PesterTestResults.xml'
242
+
243
+ if ($PesterModule.Version.Major -le 4)
244
+ {
245
+ Write-Host -Object "Invoke Pester with v$($PesterModule.Version) Options"
246
+ $options = New-PesterOption -TestSuiteName "Pester - #{instance.to_str}"
247
+ $defaultPesterParameters = @{
248
+ Script = $TestPath
249
+ OutputFile = $OutputFilePath
250
+ OutputFormat = 'NUnitXml'
251
+ PassThru = $true
252
+ PesterOption = $options
253
+ }
254
+
255
+ $pesterCmd = Get-Command -Name 'Invoke-Pester'
256
+ $pesterConfig = #{ps_hash(config[:pester_configuration])}
257
+ $invokePesterParams = @{}
258
+
259
+ foreach ($paramName in $pesterCmd.Parameters.Keys)
260
+ {
261
+ $paramValue = $pesterConfig.($paramName)
262
+
263
+ if ($paramValue) {
264
+ Write-Host -Object "Using $paramName from Yaml config."
265
+ $invokePesterParams[$paramName] = $paramValue
266
+ }
267
+ elseif ($defaultPesterParameters.ContainsKey($paramName))
268
+ {
269
+ Write-Host -Object "Using $paramName from Defaults: $($defaultPesterParameters[$paramName])."
270
+ $invokePesterParams[$paramName] = $defaultPesterParameters[$paramName]
271
+ }
272
+ }
273
+
274
+ $result = Invoke-Pester @invokePesterParams
275
+ }
276
+ else
277
+ {
278
+ Write-Host -Object "Invoke Pester with v$($PesterModule.Version) Configuration."
279
+ $pesterConfigHash = #{ps_hash(config[:pester_configuration])}
280
+
281
+ if (-not $pesterConfigHash.ContainsKey('run')) {
282
+ $pesterConfigHash['run'] = @{}
283
+ }
284
+
285
+ if (-not $pesterConfigHash.ContainsKey('TestResult')) {
286
+ $pesterConfigHash['TestResult'] = @{}
287
+ }
288
+
289
+ if (-not $pesterConfigHash.run.path) {
290
+ $pesterConfigHash['run']['path'] = $TestPath
291
+ }
292
+
293
+ if (-not $pesterConfigHash.TestResult.TestSuiteName) {
294
+ $pesterConfigHash['TestResult']['TestSuiteName'] = 'Pester - #{instance.to_str}'
295
+ }
138
296
 
139
- $TestPath = "#{config[:root_path]}"
140
- $OutputFilePath = Join-Path $TestPath -ChildPath 'PesterTestResults.xml'
297
+ if (-not $pesterConfigHash.TestResult.OutputPath) {
298
+ $pesterConfigHash['TestResult']['OutputPath'] = $OutputFilePath
299
+ }
141
300
 
142
- $options = New-PesterOption -TestSuiteName "Pester - #{instance.to_str}"
301
+ $PesterConfig = New-PesterConfiguration -Hashtable $pesterConfigHash
302
+ $result = Invoke-Pester -Configuration $PesterConfig
303
+ }
143
304
 
144
- $result = Invoke-Pester -Script $TestPath -OutputFile $OutputFilePath -OutputFormat NUnitXml -PesterOption $options -PassThru
145
- $result | Export-CliXml -Path (Join-Path -Path $TestPath -ChildPath 'result.xml')
305
+ $resultXmlPath = (Join-Path -Path $TestPath -ChildPath 'result.xml')
306
+ if (Test-Path -Path $resultXmlPath) {
307
+ $result | Export-CliXml -Path
308
+ }
146
309
 
147
310
  $LASTEXITCODE = $result.FailedCount
148
311
  $host.SetShouldExit($LASTEXITCODE)
149
312
 
150
313
  exit $LASTEXITCODE
151
- CMD
314
+ PS1
315
+ end
316
+
317
+ def get_powershell_modules_from_nugetapi
318
+ # don't return anything is the modules subkey or bootstrap is null
319
+ return if config.dig(:bootstrap, :modules).nil?
320
+
321
+ bootstrap = config[:bootstrap]
322
+ # if the repository url is set, use that as parameter to Install-ModuleFromNuget. Default is the PSGallery url
323
+ gallery_url_param = bootstrap[:repository_url] ? "-GalleryUrl '#{bootstrap[:repository_url]}'" : ""
324
+
325
+ info("Bootstrapping environment without PowerShellGet Provider...")
326
+ Array(bootstrap[:modules]).map do |powershell_module|
327
+ if powershell_module.is_a? Hash
328
+ <<-PS1
329
+ ${#{powershell_module[:Name]}} = #{ps_hash(powershell_module)}
330
+
331
+ Install-ModuleFromNuget -Module ${#{powershell_module[:Name]}} #{gallery_url_param}
332
+ PS1
333
+ else
334
+ <<-PS1
335
+ Install-ModuleFromNuget -Module @{Name = '#{powershell_module}'} #{gallery_url_param}
336
+ PS1
337
+ end
338
+ end
339
+ end
340
+
341
+ # Returns the string command to set a PS Repository
342
+ # for each PSRepo configured.
343
+ #
344
+ # @return [Array<String>] array of suite files
345
+ # @api private
346
+ def register_psrepository_scriptblock
347
+ return if config[:register_repository].nil?
348
+
349
+ info("Registering a new PowerShellGet Repository")
350
+ Array(config[:register_repository]).map do |psrepo|
351
+ # Using Set-PSRepo from ../../*/*/*/PesterUtil.psm1
352
+ debug("Command to set PSRepo #{psrepo[:Name]}.")
353
+ <<-PS1
354
+ Write-Host 'Registering psrepo #{psrepo[:Name]}...'
355
+ ${#{psrepo[:Name]}} = #{ps_hash(psrepo)}
356
+ Set-PSRepo -Repository ${#{psrepo[:Name]}}
357
+ PS1
358
+ end
359
+ end
360
+
361
+ # Returns the string command set the PSGallery as trusted, and
362
+ # Install Pester from gallery based on the params from Pester_install_params config
363
+ #
364
+ # @return <String> command to install Pester Module
365
+ # @api private
366
+ def install_pester
367
+ return if config[:skip_pester_install]
368
+
369
+ pester_install_params = config[:pester_install] || {}
370
+ <<-PS1
371
+ if ((Get-PSRepository -Name PSGallery).InstallationPolicy -ne 'Trusted') {
372
+ Write-Host -Object "Trusting the PSGallery to install Pester without -Force"
373
+ Set-PSRepository -Name PSGallery -InstallationPolicy Trusted -ErrorAction SilentlyContinue
374
+ }
375
+
376
+ Write-Host "Installing Pester..."
377
+ $installPesterParams = #{ps_hash(pester_install_params)}
378
+ $installPesterParams['Name'] = 'Pester'
379
+ Install-module @installPesterParams
380
+ Write-Host 'Pester Installed.'
381
+ PS1
382
+ end
383
+
384
+ # returns a piece of PS scriptblock for each Module to install
385
+ # from gallery that has been sepcified in install_modules config.
386
+ #
387
+ # @return [Array<String>] array of PS commands.
388
+ # @api private
389
+ def install_modules_from_gallery
390
+ return if config[:install_modules].nil?
391
+
392
+ Array(config[:install_modules]).map do |powershell_module|
393
+ if powershell_module.is_a? Hash
394
+ # Sanitize variable name so that $powershell-yaml becomes $powershell_yaml
395
+ module_name = powershell_module[:Name].gsub(/[\W]/, "_")
396
+ # so we can splat that variable to install module
397
+ <<-PS1
398
+ $#{module_name} = #{ps_hash(powershell_module)}
399
+ Write-Host -NoNewline 'Installing #{module_name}'
400
+ Install-Module @#{module_name}
401
+ Write-host '... done.'
402
+ PS1
403
+ else
404
+ <<-PS1
405
+ Write-host -NoNewline 'Installing #{powershell_module} ...'
406
+ Install-Module -Name '#{powershell_module}'
407
+ Write-host '... done.'
408
+ PS1
409
+ end
410
+ end
152
411
  end
153
412
 
154
413
  def really_wrap_shell_code(code)
155
- wrap_shell_code(Util.outdent!(use_local_powershell_modules(code)))
414
+ windows_os? ? really_wrap_windows_shell_code(code) : really_wrap_posix_shell_code(code)
156
415
  end
157
416
 
158
- def use_local_powershell_modules(script)
159
- <<-EOH
417
+ # Get the defined shell or fall back to pwsh, unless we're on windows where we use powershell
418
+ # call via sudo if sudo is true.
419
+ # This allows to use pwsh-preview instead of pwsh, or a full path to a specific binary.
420
+ def shell_cmd
421
+ if !config[:shell].nil?
422
+ config[:sudo] ? "sudo #{config[:shell]}" : "#{config[:shell]}"
423
+ elsif windows_os?
424
+ "powershell"
425
+ else
426
+ config[:sudo] ? "sudo pwsh" : "pwsh"
427
+ end
428
+ end
429
+
430
+ def really_wrap_windows_shell_code(code)
431
+ my_command = <<-PWSH
432
+ echo "Running as '$(whoami)'..."
433
+ New-Item -ItemType Directory -Path '#{config[:root_path]}/modules' -Force -ErrorAction SilentlyContinue
434
+ Set-Location -Path "#{config[:root_path]}"
435
+ # Send the pwsh here string to the file kitchen_cmd.ps1
436
+ @'
160
437
  try {
161
438
  Set-ExecutionPolicy Unrestricted -force
162
439
  }
163
440
  catch {
164
441
  $_ | Out-String | Write-Warning
165
442
  }
166
-
167
- $global:ProgressPreference = 'SilentlyContinue'
168
- $env:PSModulePath = "$(Join-Path (Get-Item -Path $env:TEMP).FullName -ChildPath 'verifier/modules');$env:PSModulePath"
169
-
170
- #{script}
171
- EOH
443
+ #{Util.outdent!(use_local_powershell_modules(code))}
444
+ '@ | Set-Content -Path kitchen_cmd.ps1 -Encoding utf8 -Force -ErrorAction 'Stop'
445
+ # create the modules folder, making sure it's done as current user (not root)
446
+ #
447
+ # Invoke the created kitchen_cmd.ps1 file using pwsh
448
+ #{shell_cmd} ./kitchen_cmd.ps1
449
+ PWSH
450
+ wrap_shell_code(Util.outdent!(my_command))
172
451
  end
173
452
 
174
- def install_command_script
175
- <<-EOH
176
- [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
177
-
178
- function Confirm-Directory {
179
- [CmdletBinding()]
180
- param($Path)
181
-
182
- $Item = if (Test-Path $Path) {
183
- Get-Item -Path $Path
184
- }
185
- else {
186
- New-Item -Path $Path -ItemType Directory
187
- }
453
+ # Writing the command to a ps1 file, adding the pwsh shebang
454
+ # invoke the file
455
+ def really_wrap_posix_shell_code(code)
456
+ my_command = <<-BASH
457
+ echo "Running as '$(whoami)'"
458
+ # create the modules folder, making sure it's done as current user (not root)
459
+ mkdir -p #{config[:root_path]}/modules
460
+ cd #{config[:root_path]}
461
+ # Send the bash heredoc 'EOF' to the file kitchen_cmd.ps1 using the tool cat
462
+ cat << 'EOF' > kitchen_cmd.ps1
463
+ #!/usr/bin/env pwsh
464
+ #{Util.outdent!(use_local_powershell_modules(code))}
465
+ EOF
466
+ chmod +x kitchen_cmd.ps1
467
+ # Invoke the created kitchen_cmd.ps1 file using pwsh
468
+ #{shell_cmd} ./kitchen_cmd.ps1
469
+ BASH
470
+
471
+ debug(Util.outdent!(my_command))
472
+ Util.outdent!(my_command)
473
+ end
188
474
 
189
- $Item.FullName
475
+ def use_local_powershell_modules(script)
476
+ <<-PS1
477
+ Write-Host -Object ("{0} - PowerShell {1}" -f $PSVersionTable.OS,$PSVersionTable.PSVersion)
478
+ $global:ProgressPreference = 'SilentlyContinue'
479
+ $PSModPathToPrepend = Join-Path "#{config[:root_path]}" -ChildPath 'modules'
480
+ Write-Verbose "Adding '$PSModPathToPrepend' to `$Env:PSModulePath."
481
+ if (!$isLinux -and -not (Test-Path -Path $PSModPathToPrepend)) {
482
+ # if you create this folder now in Linux, it may run as root (via sudo).
483
+ $null = New-Item -Path $PSModPathToPrepend -Force -ItemType Directory
190
484
  }
191
485
 
192
- function Test-Module {
193
- [CmdletBinding()]
194
- param($Name)
195
-
196
- @(Get-Module -Name $Name -ListAvailable -ErrorAction SilentlyContinue).Count -gt 0
486
+ if ($Env:PSModulePath.Split([io.path]::PathSeparator) -notcontains $PSModPathToPrepend) {
487
+ $env:PSModulePath = @($PSModPathToPrepend, $env:PSModulePath) -Join [io.path]::PathSeparator
197
488
  }
198
489
 
199
- $VerifierModulePath = Confirm-Directory -Path $env:TEMP/verifier/modules
200
- $VerifierTestsPath = Confirm-Directory -Path $env:TEMP/verifier/pester
490
+ #{script}
491
+ PS1
492
+ end
201
493
 
202
- $env:PSModulePath = "$VerifierModulePath;$PSModulePath"
494
+ def install_command_script
495
+ <<-PS1
496
+ $PSModPathToPrepend = "#{config[:root_path]}"
203
497
 
204
- if (-not (Test-Module -Name Pester)) {
205
- if (Test-Module -Name PowerShellGet) {
206
- Import-Module PowerShellGet -Force
207
- Import-Module PackageManagement -Force
498
+ Import-Module -ErrorAction Stop PesterUtil
208
499
 
209
- Get-PackageProvider -Name NuGet -Force > $null
500
+ #{get_powershell_modules_from_nugetapi.join("\n") unless config.dig(:bootstrap, :modules).nil?}
210
501
 
211
- Install-Module Pester -Force
212
- }
213
- else {
214
- if (-not (Test-Module -Name PsGet)){
215
- $webClient = New-Object -TypeName System.Net.WebClient
216
-
217
- if ($env:HTTP_PROXY){
218
- if ($env:NO_PROXY){
219
- Write-Host "Creating WebProxy with 'HTTP_PROXY' and 'NO_PROXY' environment variables.
220
- $webproxy = New-Object -TypeName System.Net.WebProxy -ArgumentList $env:HTTP_PROXY, $true, $env:NO_PROXY
221
- }
222
- else {
223
- Write-Host "Creating WebProxy with 'HTTP_PROXY' environment variable.
224
- $webproxy = New-Object -TypeName System.Net.WebProxy -ArgumentList $env:HTTP_PROXY
225
- }
226
-
227
- $webClient.Proxy = $webproxy
228
- }
229
-
230
- Invoke-Expression -Command $webClient.DownloadString('http://bit.ly/GetPsGet')
231
- }
232
-
233
- try {
234
- # If the module isn't already loaded, ensure we can import it.
235
- if (-not (Get-Module -Name PsGet -ErrorAction SilentlyContinue)) {
236
- Import-Module -Name PsGet -Force -ErrorAction Stop
237
- }
238
-
239
- Install-Module -Name Pester -Force
240
- }
241
- catch {
242
- Write-Host "Installing from Github"
243
-
244
- $downloadFolder = if (Test-Path "$env:TEMP/PesterDownload") {
245
- "$env:TEMP/PesterDownload"
246
- }
247
- else {
248
- New-Item -ItemType Directory -Path "$env:TEMP/PesterDownload"
249
- }
250
-
251
- $zipFile = Join-Path (Get-Item -Path $downloadFolder).FullName -ChildPath "pester.zip"
252
-
253
- if (-not (Test-Path $zipfile)) {
254
- $source = 'https://github.com/pester/Pester/archive/4.10.1.zip'
255
- $webClient = New-Object -TypeName Net.WebClient
256
-
257
- if ($env:HTTP_PROXY) {
258
- if ($env:NO_PROXY) {
259
- Write-Host "Creating WebProxy with 'HTTP_PROXY' and 'NO_PROXY' environment variables."
260
- $webproxy = New-Object -TypeName System.Net.WebProxy -ArgumentList $env:HTTP_PROXY, $true, $env:NO_PROXY
261
- }
262
- else {
263
- Write-Host "Creating WebProxy with 'HTTP_PROXY' environment variable."
264
- $webproxy = New-Object -TypeName System.Net.WebProxy -ArgumentList $env:HTTP_PROXY
265
- }
266
-
267
- $webClient.Proxy = $webproxy
268
- }
269
-
270
- [IO.File]::WriteAllBytes($zipfile, $webClient.DownloadData($source))
271
-
272
- [GC]::Collect()
273
- Write-Host "Downloaded Pester.zip"
274
- }
275
-
276
- Write-Host "Creating Shell.Application COM object"
277
- $shellcom = New-Object -ComObject Shell.Application
278
-
279
- Write-Host "Creating COM object for zip file."
280
- $zipcomobject = $shellcom.Namespace($zipfile)
281
-
282
- Write-Host "Creating COM object for module destination."
283
- $destination = $shellcom.Namespace($VerifierModulePath)
284
-
285
- Write-Host "Unpacking zip file."
286
- $destination.CopyHere($zipcomobject.Items(), 0x610)
287
-
288
- Rename-Item -Path (Join-Path $VerifierModulePath -ChildPath "Pester-4.10.1") -NewName 'Pester' -Force
289
- }
290
- }
291
- }
502
+ #{register_psrepository_scriptblock.join("\n") unless config[:register_repository].nil?}
292
503
 
293
- if (-not (Test-Module Pester)) {
294
- throw "Unable to install Pester. Please include Pester in your base image or install during your converge."
295
- }
296
- EOH
504
+ #{install_pester}
505
+
506
+ #{install_modules_from_gallery.join("\n") unless config[:install_modules].nil?}
507
+ PS1
297
508
  end
298
509
 
299
510
  def restart_winrm_service
511
+ return unless verifier.windows_os?
512
+
300
513
  cmd = "schtasks /Create /TN restart_winrm /TR " \
301
514
  '"powershell -Command Restart-Service winrm" ' \
302
515
  "/SC ONCE /ST 00:00 "
@@ -308,11 +521,15 @@ module Kitchen
308
521
  end
309
522
 
310
523
  def download_test_files(state)
311
- info("Downloading test result files from #{instance.to_str}")
524
+ if config[:downloads].nil?
525
+ info("Skipped downloading test result file from #{instance.to_str}; 'downloads' hash is empty.")
526
+ return
527
+ end
312
528
 
529
+ info("Downloading test result files from #{instance.to_str}")
313
530
  instance.transport.connection(state) do |conn|
314
- config[:downloads].to_h.each do |remotes, local|
315
- debug("Downloading #{Array(remotes).join(", ")} to #{local}")
531
+ config[:downloads].each do |remotes, local|
532
+ debug("downloading #{Array(remotes).join(", ")} to #{local}")
316
533
  conn.download(remotes, local)
317
534
  end
318
535
  end
@@ -326,29 +543,25 @@ module Kitchen
326
543
  #
327
544
  # @return [Array<String>] array of suite files
328
545
  # @api private
329
-
330
546
  def suite_test_folder
331
547
  @suite_test_folder ||= File.join(test_folder, config[:suite_name])
332
548
  end
333
549
 
334
- def suite_level_glob
335
- Dir.glob(File.join(suite_test_folder, "*"))
336
- end
337
-
338
- def suite_verifier_level_glob
339
- Dir.glob(File.join(suite_test_folder, "*/**/*"))
340
- end
341
-
342
- def local_suite_files
343
- suite = suite_level_glob
344
- suite_verifier = suite_verifier_level_glob
345
- (suite << suite_verifier).flatten!.reject do |f|
346
- File.directory?(f)
347
- end
550
+ # Returns the current file's parent folder's full path.
551
+ #
552
+ # @return [string]
553
+ # @api private
554
+ def script_root
555
+ @script_root ||= File.dirname(__FILE__)
348
556
  end
349
557
 
350
- def sandboxify_path(path)
351
- File.join(sandbox_path, path.sub(%r{#{suite_test_folder}/}i, ""))
558
+ # Returns the absolute path of the Supporting PS module to
559
+ # be copied to the SUT via the Sandbox.
560
+ #
561
+ # @return [string]
562
+ # @api private
563
+ def support_psmodule_folder
564
+ @support_psmodule_folder ||= Pathname.new(File.join(script_root, "../../support/modules/PesterUtil")).cleanpath
352
565
  end
353
566
 
354
567
  # Returns an Array of common helper filenames currently residing on the
@@ -376,50 +589,128 @@ module Kitchen
376
589
  end
377
590
  end
378
591
 
379
- # Copies all test suite files into the suites directory in the sandbox.
592
+ # Creates a PowerShell hashtable from a ruby map.
593
+ # The only types supported for now are hash, array, string and Boolean.
380
594
  #
381
595
  # @api private
382
- def prepare_pester_tests
383
- info("Preparing to copy files from #{suite_test_folder} to the SUT.")
596
+ def ps_hash(obj, depth = 0)
597
+ if [true, false].include? obj
598
+ %{$#{obj}} # Return $true or $false when value is a bool
599
+ elsif obj.is_a?(Hash)
600
+ obj.map do |k, v|
601
+ # Format "Key = Value" enabling recursion
602
+ %{#{pad(depth + 2)}#{ps_hash(k)} = #{ps_hash(v, depth + 2)}}
603
+ end
604
+ .join("\n") # append \n to the key/value definitions
605
+ .insert(0, "@{\n") # prepend @{\n
606
+ .insert(-1, "\n#{pad(depth)}}\n") # append \n}\n
607
+
608
+ elsif obj.is_a?(Array)
609
+ array_string = obj.map { |v| ps_hash(v, depth + 4) }.join(",")
610
+ "#{pad(depth)}@(\n#{array_string}\n)"
611
+ else
612
+ # When the object is not a string nor a hash or array, it will be quoted as a string.
613
+ # In most cases, PS is smart enough to convert back to the type it needs.
614
+ "'" + obj.to_s + "'"
615
+ end
616
+ end
384
617
 
385
- local_suite_files.each do |src|
386
- dest = sandboxify_path(src)
387
- debug("Copying #{src} to #{dest}")
388
- FileUtils.mkdir_p(File.dirname(dest))
389
- FileUtils.cp(src, dest, preserve: true)
618
+ # returns the path of the modules subfolder
619
+ # in the sandbox, where PS Modules and folders will be copied to.
620
+ #
621
+ # @api private
622
+ def sandbox_module_path
623
+ File.join(sandbox_path, "modules")
624
+ end
625
+
626
+ # copy files into the 'modules' folder of the sandbox,
627
+ # so that copied folders can be discovered with the updated $Env:PSModulePath.
628
+ #
629
+ # @api private
630
+ def prepare_copy_folders
631
+ return if config[:copy_folders].nil?
632
+
633
+ info("Preparing to copy specified folders to #{sandbox_module_path}.")
634
+ kitchen_root_path = config[:kitchen_root]
635
+ config[:copy_folders].each do |folder|
636
+ debug("copying #{folder}")
637
+ folder_to_copy = File.join(kitchen_root_path, folder)
638
+ copy_if_src_exists(folder_to_copy, sandbox_module_path)
390
639
  end
391
640
  end
392
641
 
393
- def prepare_powershell_module(name)
394
- FileUtils.mkdir_p(File.join(sandbox_path, "modules/#{name}"))
395
- FileUtils.cp(
396
- File.join(File.dirname(__FILE__), "../../support/powershell/#{name}/#{name}.psm1"),
397
- File.join(sandbox_path, "modules/#{name}/#{name}.psm1"),
398
- preserve: true
399
- )
642
+ # returns an array of string
643
+ # Creates a flat list of files contained in a folder.
644
+ # This is useful when trying to debug what has been copied to
645
+ # the sandbox.
646
+ #
647
+ # @return [Array<String>] array of files in a folder
648
+ # @api private
649
+ def list_files(path)
650
+ base_directory_content = Dir.glob(File.join(path, "*"))
651
+ nested_directory_content = Dir.glob(File.join(path, "*/**/*"))
652
+ [base_directory_content, nested_directory_content].flatten
653
+ end
654
+
655
+ # Copies all test suite files into the suites directory in the sandbox.
656
+ #
657
+ # @api private
658
+ def prepare_pester_tests
659
+ info("Preparing to copy files from '#{suite_test_folder}' to the SUT.")
660
+ sandboxed_suites_path = File.join(sandbox_path, "suites")
661
+ copy_if_src_exists(suite_test_folder, sandboxed_suites_path)
662
+ end
663
+
664
+ def prepare_supporting_psmodules
665
+ info("Preparing to copy files from '#{support_psmodule_folder}' to the SUT.")
666
+ sandbox_module_path = File.join(sandbox_path, "modules")
667
+ copy_if_src_exists(support_psmodule_folder, sandbox_module_path)
400
668
  end
401
669
 
402
- def prepare_powershell_modules
403
- info("Preparing to copy supporting powershell modules.")
404
- %w{PesterUtil}.each do |module_name|
405
- prepare_powershell_module module_name
670
+ # Copies a folder recursively preserving its layers,
671
+ # mostly used to copy to the sandbox.
672
+ #
673
+ # @api private
674
+ def copy_if_src_exists(src_to_validate, destination)
675
+ unless Dir.exist?(src_to_validate)
676
+ info("The path #{src_to_validate} was not found. Not copying to #{destination}.")
677
+ return
678
+ end
679
+
680
+ info("Moving #{src_to_validate} to #{destination}")
681
+ unless Dir.exist?(destination)
682
+ FileUtils.mkdir_p(destination)
683
+ debug("Folder '#{destination}' created.")
406
684
  end
685
+ FileUtils.mkdir_p(File.join(destination, "__bugfix"))
686
+ FileUtils.cp_r(src_to_validate, destination, preserve: true)
407
687
  end
408
688
 
689
+ # returns the absolute path of the folders containing the
690
+ # test suites, use default if not set.
691
+ #
692
+ # @api private
409
693
  def test_folder
410
- return config[:test_base_path] if config[:test_folder].nil?
411
-
412
- absolute_test_folder
694
+ config[:test_folder].nil? ? config[:test_base_path] : absolute_test_folder
413
695
  end
414
696
 
697
+ # returns the absolute path of the relative folders containing the
698
+ # test suites, use default i not set.
699
+ #
700
+ # @api private
415
701
  def absolute_test_folder
416
702
  path = (Pathname.new config[:test_folder]).realpath
417
703
  integration_path = File.join(path, "integration")
418
- return path unless Dir.exist?(integration_path)
419
-
420
- integration_path
704
+ Dir.exist?(integration_path) ? integration_path : path
421
705
  end
422
706
 
707
+ # returns a string of space of the specified depth.
708
+ # This is used to pad messages or when building PS hashtables.
709
+ #
710
+ # @api private
711
+ def pad(depth = 0)
712
+ " " * depth
713
+ end
423
714
  end
424
715
  end
425
716
  end
@@ -1,5 +1,5 @@
1
1
  module Kitchen
2
2
  module Verifier
3
- PESTER_VERSION = "0.12.1".freeze
3
+ PESTER_VERSION = "1.1.1".freeze
4
4
  end
5
5
  end
@@ -0,0 +1,158 @@
1
+ [Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
2
+
3
+ function Install-ModuleFromNuget {
4
+ [CmdletBinding()]
5
+ param (
6
+ [hashtable]
7
+ $Module,
8
+
9
+ [string]
10
+ $GalleryUrl = 'https://www.powershellgallery.com/api/v2'
11
+ )
12
+
13
+ $tempPath = [System.IO.Path]::GetTempPath()
14
+ $zipFileName = "{0}.{1}.{2}" -f $Module.Name, $Module.Version, 'zip'
15
+ $downloadedZip = Join-Path -Path $tempPath $zipFileName
16
+ $ModulePath = Join-Path -Path $PSHome -ChildPath 'Modules'
17
+ $ModuleFolder = Join-Path -Path $ModulePath -ChildPath $Module.Name
18
+
19
+ if ((Test-Path $ModuleFolder) -and ($PSVersionTable.PSVersion.Major -lt 5 -or $module.Force)) {
20
+ # Check if available version is correct
21
+ $ModuleManifest = Join-Path -Path $ModuleFolder -ChildPath "$($Module.Name).psd1"
22
+ if ((Test-Path -Path $ModuleManifest) -and -not $Module.Force) {
23
+ # Import-PowerShellDataFile only exists since 5.1
24
+ $ManifestInfo = Import-LocalizedData -BaseDirectory (Split-Path -Parent -Path $ModuleManifest) -FileName $Module.Name
25
+ $ModuleVersionNoPreRelease = $Module.Version -replace '-.*$'
26
+ # Compare the version in manifest with version required without Pre-release
27
+ if ($ManifestInfo.ModuleVersion -eq $ModuleVersionNoPreRelease) {
28
+ Write-Host "Module $($Module.Name) already installed, skipping."
29
+ return
30
+ }
31
+ else {
32
+ Write-Host "Module $($Module.Name) found with version '$($ManifestInfo.ModuleVersion)', expecting '$ModuleVersionNoPreRelease'."
33
+ }
34
+ }
35
+ else {
36
+ # if incorrect, remove it before install
37
+ Remove-Item -Recurse -Force -Path $ModuleFolder
38
+ }
39
+ }
40
+ elseif ($PSVersionTable.PSVersion.Major -gt 5) {
41
+ # skip if the version already exists or if force is enabled
42
+ $ModuleVersionNoPreRelease = $Module.Version -replace '-.*$'
43
+ $ModuleFolder = Join-Path -Path $ModuleFolder -ChildPath $ModuleVersionNoPreRelease
44
+ if (-not $Module.Force -and (Test-Path -Path $ModuleFolder)) {
45
+ Write-Verbose -Message "Module already installed."
46
+ return
47
+ }
48
+ }
49
+
50
+ if (-not (Test-Path $ModuleFolder)) {
51
+ $null = New-Item -Path $ModuleFolder -force -ItemType Directory
52
+ }
53
+
54
+ $urlSuffix = "/package/$($Module.Name)/$($Module.Version)".TrimEnd('/')
55
+ $nupkgUrl = $GalleryUrl.TrimEnd('/') + '/' + $urlSuffix.Trim('/')
56
+ $webclient = New-Object 'system.net.webclient'
57
+
58
+ if ($env:HTTP_PROXY){
59
+ if ($env:NO_PROXY){
60
+ Write-Host "Creating WebProxy with 'HTTP_PROXY' and 'NO_PROXY' environment variables."
61
+ $webproxy = New-Object -TypeName System.Net.WebProxy -ArgumentList $env:HTTP_PROXY, $true, $env:NO_PROXY
62
+ }
63
+ else {
64
+ Write-Host "Creating WebProxy with 'HTTP_PROXY' environment variable."
65
+ $webproxy = New-Object -TypeName System.Net.WebProxy -ArgumentList $env:HTTP_PROXY
66
+ }
67
+
68
+ $webclient.Proxy = $webproxy
69
+ }
70
+
71
+ Write-Verbose -Message "Downloading Package from $nupkgUrl"
72
+ try {
73
+ if (Test-Path $downloadedZip) {
74
+ Remove-Item -Force -ErrorAction SilentlyContinue -Path $downloadedZip
75
+ }
76
+ $webclient.DownloadFile($nupkgUrl, $downloadedZip)
77
+ }
78
+ catch {
79
+ Write-Error "Error trying to download nupkg '$nupkgUrl' to '$downloadedZip'."
80
+ throw $_
81
+ }
82
+
83
+ if (-not (Test-Path -Path $downloadedZip)) {
84
+ throw "Error trying to download nupkg '$nupkgUrl' to '$downloadedZip'."
85
+ }
86
+
87
+ # Test to see if Expand-Archive is available first
88
+ if (Get-Command Expand-Archive) {
89
+ Expand-Archive -Path $downloadedZip -DestinationPath $ModuleFolder -Force
90
+ }
91
+ else {
92
+ # Fall back to COM object for Shell.Application zip extraction
93
+ Write-Host "Creating COM object for zip file '$downloadedZip'."
94
+ $shellcom = New-Object -ComObject Shell.Application
95
+ $zipcomobject = $shellcom.Namespace($downloadedZip)
96
+ $destination = $shellcom.Namespace($ModuleFolder)
97
+ $destination.CopyHere($zipcomobject.Items(), 0x610)
98
+ Write-Host "Nupkg installed at $ModuleFolder"
99
+ }
100
+
101
+ [GC]::Collect()
102
+ }
103
+
104
+ function Set-PSRepo {
105
+ param(
106
+ [Parameter(Mandatory)]
107
+ $Repository
108
+ )
109
+
110
+ if (-not (Get-Command Get-PSRepository) -and (Get-Command Get-PackageSource)) {
111
+ # Old versions of PSGet do not have a *-PSrepository but have *-PackageSource instead.
112
+ if (Get-PackageSource -Name $Repository.Name) {
113
+ Set-PackageSource @Repository
114
+ }
115
+ else {
116
+ Register-PackageSource @Repository
117
+ }
118
+ }
119
+ elseif (Get-Command Get-PSRepository) {
120
+ if (Get-PSRepository -Name $Repository.Name -ErrorAction SilentlyContinue) {
121
+ # The repo exists, we should use Set-PSRepository and splat parameters
122
+ Set-PSRepository @Repository
123
+ }
124
+ else {
125
+ # The repo does not exist, use Register-PSRepository and splat
126
+ Register-PSRepository @Repository
127
+ }
128
+ }
129
+ else {
130
+ throw "Cannot Set PS Repository, command Set or Register for PSRepository or PackageSource not found."
131
+ }
132
+ }
133
+
134
+ function ConvertFrom-PesterOutputObject {
135
+ param (
136
+ [parameter(ValueFromPipeline=$true)]
137
+ [object]
138
+ $InputObject
139
+ )
140
+ begin {
141
+ $PesterModule = Import-Module Pester -Passthru
142
+ }
143
+ process {
144
+ $DescribeGroup = $InputObject.testresult | Group-Object Describe
145
+ foreach ($DescribeBlock in $DescribeGroup) {
146
+ $PesterModule.Invoke({Write-Screen $args[0]}, "Describing $($DescribeBlock.Name)")
147
+ $ContextGroup = $DescribeBlock.group | Group-Object Context
148
+ foreach ($ContextBlock in $ContextGroup) {
149
+ $PesterModule.Invoke({Write-Screen $args[0]}, "`tContext $($subheader.name)")
150
+ foreach ($TestResult in $ContextBlock.group) {
151
+ $PesterModule.Invoke({Write-PesterResult $args[0]}, $TestResult)
152
+ }
153
+ }
154
+ }
155
+
156
+ $PesterModule.Invoke({Write-PesterReport $args[0]}, $InputObject)
157
+ }
158
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-pester
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.1
4
+ version: 1.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Murawski
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-05-06 00:00:00.000000000 Z
11
+ date: 2021-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -81,7 +81,7 @@ dependencies:
81
81
  version: '1.10'
82
82
  - - "<"
83
83
  - !ruby/object:Gem::Version
84
- version: '3'
84
+ version: '4'
85
85
  type: :runtime
86
86
  prerelease: false
87
87
  version_requirements: !ruby/object:Gem::Requirement
@@ -91,7 +91,7 @@ dependencies:
91
91
  version: '1.10'
92
92
  - - "<"
93
93
  - !ruby/object:Gem::Version
94
- version: '3'
94
+ version: '4'
95
95
  description: Skip all that Busser stuff and jump right into Pester.
96
96
  email:
97
97
  - steven.murawski@gmail.com
@@ -105,12 +105,12 @@ files:
105
105
  - kitchen-pester.gemspec
106
106
  - lib/kitchen/verifier/pester.rb
107
107
  - lib/kitchen/verifier/pester_version.rb
108
- - lib/support/powershell/PesterUtil/PesterUtil.psm1
108
+ - lib/support/modules/PesterUtil/PesterUtil.psm1
109
109
  homepage: https://github.com/test-kitchen/kitchen-pester
110
110
  licenses:
111
111
  - Apache-2.0
112
112
  metadata: {}
113
- post_install_message:
113
+ post_install_message:
114
114
  rdoc_options: []
115
115
  require_paths:
116
116
  - lib
@@ -126,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
126
  version: '0'
127
127
  requirements: []
128
128
  rubygems_version: 3.0.6
129
- signing_key:
129
+ signing_key:
130
130
  specification_version: 4
131
131
  summary: Test-Kitchen verifier for Pester.
132
132
  test_files: []
@@ -1,24 +0,0 @@
1
- function ConvertFrom-PesterOutputObject {
2
- param (
3
- [parameter(ValueFromPipeline=$true)]
4
- [object]
5
- $InputObject
6
- )
7
- begin {
8
- $PesterModule = Import-Module Pester -Passthru
9
- }
10
- process {
11
- $DescribeGroup = $InputObject.testresult | Group-Object Describe
12
- foreach ($DescribeBlock in $DescribeGroup) {
13
- $PesterModule.Invoke({Write-Screen $args[0]}, "Describing $($DescribeBlock.Name)")
14
- $ContextGroup = $DescribeBlock.group | Group-Object Context
15
- foreach ($ContextBlock in $ContextGroup) {
16
- $PesterModule.Invoke({Write-Screen $args[0]}, "`tContext $($subheader.name)")
17
- foreach ($TestResult in $ContextBlock.group) {
18
- $PesterModule.Invoke({Write-PesterResult $args[0]}, $TestResult)
19
- }
20
- }
21
- }
22
- $PesterModule.Invoke({Write-PesterReport $args[0]}, $InputObject)
23
- }
24
- }