Repository navigation
Expand file tree
/
Copy pathIntuneScripts.Tests.ps1.template
More file actions
145 lines (123 loc) · 6.91 KB
/
Copy pathIntuneScripts.Tests.ps1.template
File metadata and controls
145 lines (123 loc) · 6.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '6.2.0' }
<#
Template for testing a folder of Intune scripts with IntuneScriptLab. Copy it next to your
scripts as IntuneScripts.Tests.ps1, adjust the paths, run Invoke-Pester.
Layout it assumes:
.\Remediations\<Package>\Detect.ps1 and Remediate.ps1
.\Win32\<App>\Detect.ps1 and Package\ (the content that becomes the .intunewin), and for an
app detected by portal rules instead of a script, Rules.psd1 holding
@{ DetectionRules = @(@{ Type = 'File'; ... }); UninstallCommand = '...' }
.\PlatformScripts\*.ps1
Static checks run anywhere. The runtime checks start real Windows PowerShell 5.1 processes
and need Windows; -Context System additionally needs a session that can register a
scheduled task as SYSTEM (elevated).
A folder you do not have (no Win32 apps yet, say) yields an empty -ForEach, which Pester 6
treats as a discovery failure. -AllowNullOrEmptyForEach on each block turns that into
"nothing to test" instead; delete the switch where the folder must never be empty.
#>
BeforeAll {
Import-Module IntuneScriptLab
$script:IsAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).
IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
# The device's 64-bit host, for the WOW64 comparison: x64 on x64, arm64 on Windows on ARM
$script:Host64 = if ("$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)" -eq 'Arm64') {
'arm64'
}
else { 'x64' }
}
Describe 'Static analysis' -Tag 'Static' {
It 'has no warnings or errors: <_.Directory.Name>/<_.Name>' -AllowNullOrEmptyForEach -ForEach (
Get-ChildItem "$PSScriptRoot\Remediations" -Recurse -Filter *.ps1 -ErrorAction SilentlyContinue) {
# Detection/Remediation is inferred from the file name; use -ScriptType or a directive
# comment in the script if your names differ (see the README)
$_ | Should-PassIntuneAnalysis
}
It 'survives the stdout/stderr rules: <_.Directory.Name>/<_.Name>' -AllowNullOrEmptyForEach -ForEach (
Get-ChildItem "$PSScriptRoot\Win32" -Recurse -Filter Detect.ps1 -ErrorAction SilentlyContinue) {
$_ | Should-PassIntuneAnalysis -ScriptType Win32Detection
}
}
Describe 'Remediation packages' -Tag 'Runtime' {
Context '<_.Name>' -AllowNullOrEmptyForEach -ForEach (
Get-ChildItem "$PSScriptRoot\Remediations" -Directory -ErrorAction SilentlyContinue) {
It 'runs the detection cleanly in the 32-bit host' {
$result = Invoke-IntuneRemediationTest -DetectionPath "$($_.FullName)\Detect.ps1" -Architecture x86
($result.Status -in 'Without issues', 'Issue detected (no remediation script)') | Should-BeTrue
@($result.Warnings).Count | Should-Be 0
}
It 'reports the same in the 64-bit host (no WOW64 dependence)' {
# The 64-bit host is the device's own: x64 on x64, arm64 on Windows on ARM, where an
# explicit x64 is refused (the agent runs the native 64-bit host there too)
$detect = "$($_.FullName)\Detect.ps1"
$x86 = Invoke-IntuneRemediationTest -DetectionPath $detect -Architecture x86
$x64 = Invoke-IntuneRemediationTest -DetectionPath $detect -Architecture $script:Host64
$x64.PreDetection.ExitCode | Should-Be $x86.PreDetection.ExitCode
}
# Only where the remediation is safe to run on the test machine
It 'fixes the issue as SYSTEM' -Skip:(-not $script:IsAdmin) {
$intuneRemediationTestSplat = @{
DetectionPath = "$($_.FullName)\Detect.ps1"
RemediationPath = "$($_.FullName)\Remediate.ps1"
Context = 'System'
}
Invoke-IntuneRemediationTest @intuneRemediationTestSplat |
Should-HaveIntuneStatus 'Fixed'
}
}
}
Describe 'Win32 apps' -Tag 'Runtime' {
Context '<_.Name>' -AllowNullOrEmptyForEach -ForEach (
Get-ChildItem "$PSScriptRoot\Win32" -Directory -ErrorAction SilentlyContinue) {
It 'is not detected before install' {
Invoke-IntuneDetectionTest -Path "$($_.FullName)\Detect.ps1" | Should-NotBeIntuneDetected
}
# Only where the app has a PowerShell requirement rule; mirror the rule configured in the portal
It 'meets its requirement rule' -Skip:(-not (Test-Path "$($_.FullName)\Requirement.ps1")) {
Invoke-IntuneRequirementTest -Path "$($_.FullName)\Requirement.ps1" -OutputType String -Value 'ok' |
Should-BeIntuneApplicable
}
It 'installs and is then detected' -Skip:(-not $script:IsAdmin) {
$intuneWin32AppTestSplat = @{
DetectionPath = "$($_.FullName)\Detect.ps1"
ContentPath = "$($_.FullName)\Package"
InstallCommand = 'powershell.exe -ExecutionPolicy Bypass -File install.ps1'
Context = 'System'
}
Invoke-IntuneWin32AppTest @intuneWin32AppTestSplat |
Should-HaveIntuneStatus 'Installed after install'
}
# Only where the app is detected by file, registry or MSI rules: mirror the portal rules in
# Rules.psd1; all of them must be met, as under the agent
It 'meets every detection rule after install' -Skip:(-not ($script:IsAdmin -and
(Test-Path "$($_.FullName)\Rules.psd1"))) {
$rules = Import-PowerShellDataFile "$($_.FullName)\Rules.psd1"
$intuneWin32AppTestSplat = @{
DetectionRule = $rules.DetectionRules
ContentPath = "$($_.FullName)\Package"
InstallCommand = 'powershell.exe -ExecutionPolicy Bypass -File install.ps1'
Context = 'System'
}
Invoke-IntuneWin32AppTest @intuneWin32AppTestSplat |
Should-HaveIntuneStatus 'Installed after install'
}
It 'uninstalls and is no longer detected' -Skip:(-not ($script:IsAdmin -and
(Test-Path "$($_.FullName)\Rules.psd1"))) {
$rules = Import-PowerShellDataFile "$($_.FullName)\Rules.psd1"
$intuneWin32AppTestSplat = @{
DetectionPath = "$($_.FullName)\Detect.ps1"
ContentPath = "$($_.FullName)\Package"
Intent = 'Uninstall'
UninstallCommand = $rules.UninstallCommand
Context = 'System'
}
Invoke-IntuneWin32AppTest @intuneWin32AppTestSplat |
Should-HaveIntuneStatus 'Uninstalled'
}
}
}
Describe 'Platform scripts' -Tag 'Runtime' {
It 'succeeds: <_.Name>' -AllowNullOrEmptyForEach -ForEach (
Get-ChildItem "$PSScriptRoot\PlatformScripts" -Filter *.ps1 -ErrorAction SilentlyContinue) {
Invoke-IntunePlatformScriptTest -Path $_.FullName | Should-HaveIntuneRunState 'Success'
}
}