Skip to content

Commit bb8e278

Browse files
CopilotDaRacci
andcommitted
Add comprehensive test suites for Connection and Ensure modules
Co-authored-by: DaRacci <[email protected]>
1 parent 3dec7f6 commit bb8e278

File tree

2 files changed

+871
-0
lines changed

2 files changed

+871
-0
lines changed
Lines changed: 377 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,377 @@
1+
Describe "Connection Module Tests" {
2+
BeforeAll {
3+
# Import required modules
4+
Import-Module "$PSScriptRoot/../../../src/common/Connection.psm1" -Force
5+
6+
# Mock external dependencies for cross-platform testing
7+
Mock Connect-ExchangeOnline { } -ModuleName Connection
8+
Mock Disconnect-ExchangeOnline { } -ModuleName Connection
9+
Mock Connect-IPPSSession { } -ModuleName Connection
10+
Mock Connect-MgGraph { } -ModuleName Connection
11+
Mock Disconnect-MgGraph { } -ModuleName Connection
12+
Mock Get-ConnectionInformation {
13+
[PSCustomObject]@{
14+
UserPrincipalName = '[email protected]'
15+
ConnectionId = 'test-connection-id'
16+
}
17+
} -ModuleName Connection
18+
Mock Get-MgContext {
19+
[PSCustomObject]@{
20+
Account = '[email protected]'
21+
Scopes = @('User.Read', 'Mail.Read')
22+
}
23+
} -ModuleName Connection
24+
Mock Get-UserConfirmation { $true } -ModuleName Connection
25+
}
26+
27+
Context "Module Import" {
28+
It "Should import Connection module successfully" {
29+
Get-Module -Name Connection* | Should -Not -BeNullOrEmpty
30+
}
31+
32+
It "Should export expected functions" {
33+
$ExportedFunctions = (Get-Module -Name Connection*).ExportedFunctions.Keys
34+
$ExportedFunctions | Should -Contain 'Connect-Service'
35+
}
36+
}
37+
38+
Context "Connect-Service Parameter Validation" {
39+
It "Should require Services parameter" {
40+
{ Connect-Service } | Should -Throw
41+
}
42+
43+
It "Should validate Services parameter values" {
44+
{ Connect-Service -Services 'InvalidService' } | Should -Throw
45+
}
46+
47+
It "Should accept valid service names" {
48+
Mock Get-ConnectionInformation { $null } -ModuleName Connection
49+
50+
{ Connect-Service -Services 'ExchangeOnline' -DontConfirm } | Should -Not -Throw
51+
{ Connect-Service -Services 'SecurityComplience' -DontConfirm } | Should -Not -Throw
52+
{ Connect-Service -Services 'Graph' -DontConfirm } | Should -Not -Throw
53+
}
54+
55+
It "Should accept multiple services" {
56+
Mock Get-ConnectionInformation { $null } -ModuleName Connection
57+
Mock Get-MgContext { $null } -ModuleName Connection
58+
59+
{ Connect-Service -Services @('ExchangeOnline', 'Graph') -DontConfirm } | Should -Not -Throw
60+
}
61+
62+
It "Should accept optional Scopes parameter" {
63+
Mock Get-ConnectionInformation { $null } -ModuleName Connection
64+
Mock Get-MgContext { $null } -ModuleName Connection
65+
66+
{ Connect-Service -Services 'Graph' -Scopes @('User.Read') -DontConfirm } | Should -Not -Throw
67+
}
68+
69+
It "Should accept optional AccessToken parameter" {
70+
Mock Get-ConnectionInformation { $null } -ModuleName Connection
71+
Mock Get-MgContext { $null } -ModuleName Connection
72+
$SecureToken = ConvertTo-SecureString 'token123' -AsPlainText -Force
73+
74+
{ Connect-Service -Services 'Graph' -AccessToken $SecureToken -DontConfirm } | Should -Not -Throw
75+
}
76+
}
77+
78+
Context "ExchangeOnline Service Tests" {
79+
BeforeEach {
80+
Mock Get-ConnectionInformation { $null } -ModuleName Connection
81+
}
82+
83+
It "Should handle ExchangeOnline connection" {
84+
Mock Connect-ExchangeOnline { } -ModuleName Connection
85+
Mock Get-ConnectionInformation {
86+
[PSCustomObject]@{
87+
UserPrincipalName = '[email protected]'
88+
ConnectionId = 'exchange-connection'
89+
}
90+
} -ModuleName Connection
91+
92+
{ Connect-Service -Services 'ExchangeOnline' -DontConfirm } | Should -Not -Throw
93+
94+
Assert-MockCalled Connect-ExchangeOnline -Times 1 -ModuleName Connection
95+
}
96+
97+
It "Should handle existing ExchangeOnline connection" {
98+
Mock Get-ConnectionInformation {
99+
[PSCustomObject]@{
100+
UserPrincipalName = '[email protected]'
101+
ConnectionId = 'existing-connection'
102+
}
103+
} -ModuleName Connection
104+
Mock Get-UserConfirmation { $true } -ModuleName Connection
105+
106+
{ Connect-Service -Services 'ExchangeOnline' } | Should -Not -Throw
107+
108+
# Should not call Connect-ExchangeOnline if already connected and user confirms
109+
Assert-MockCalled Get-UserConfirmation -Times 1 -ModuleName Connection
110+
}
111+
112+
It "Should disconnect and reconnect if user declines" {
113+
Mock Get-ConnectionInformation {
114+
[PSCustomObject]@{
115+
UserPrincipalName = '[email protected]'
116+
ConnectionId = 'existing-connection'
117+
}
118+
} -ModuleName Connection
119+
Mock Get-UserConfirmation { $false } -ModuleName Connection
120+
Mock Disconnect-ExchangeOnline { } -ModuleName Connection
121+
Mock Connect-ExchangeOnline { } -ModuleName Connection
122+
123+
{ Connect-Service -Services 'ExchangeOnline' } | Should -Not -Throw
124+
125+
Assert-MockCalled Disconnect-ExchangeOnline -Times 1 -ModuleName Connection
126+
Assert-MockCalled Connect-ExchangeOnline -Times 1 -ModuleName Connection
127+
}
128+
}
129+
130+
Context "SecurityComplience Service Tests" {
131+
BeforeEach {
132+
Mock Get-ConnectionInformation { $null } -ModuleName Connection
133+
}
134+
135+
It "Should handle SecurityComplience connection" {
136+
Mock Connect-IPPSSession { } -ModuleName Connection
137+
Mock Get-ConnectionInformation {
138+
[PSCustomObject]@{
139+
UserPrincipalName = '[email protected]'
140+
ConnectionId = 'ipps-connection'
141+
}
142+
} -ModuleName Connection
143+
144+
{ Connect-Service -Services 'SecurityComplience' -DontConfirm } | Should -Not -Throw
145+
146+
Assert-MockCalled Connect-IPPSSession -Times 1 -ModuleName Connection
147+
}
148+
149+
It "Should handle SecurityComplience disconnection" {
150+
Mock Get-ConnectionInformation {
151+
[PSCustomObject]@{
152+
UserPrincipalName = '[email protected]'
153+
ConnectionId = 'ipps-connection'
154+
}
155+
} -ModuleName Connection
156+
Mock Disconnect-ExchangeOnline { } -ModuleName Connection
157+
158+
# The disconnect for SecurityComplience uses Disconnect-ExchangeOnline
159+
{ Connect-Service -Services 'SecurityComplience' -CheckOnly } | Should -Not -Throw
160+
}
161+
}
162+
163+
Context "Graph Service Tests" {
164+
BeforeEach {
165+
Mock Get-MgContext { $null } -ModuleName Connection
166+
}
167+
168+
It "Should handle Graph connection without scopes" {
169+
Mock Connect-MgGraph { } -ModuleName Connection
170+
Mock Get-MgContext {
171+
[PSCustomObject]@{
172+
Account = '[email protected]'
173+
Scopes = @()
174+
}
175+
} -ModuleName Connection
176+
177+
{ Connect-Service -Services 'Graph' -DontConfirm } | Should -Not -Throw
178+
179+
Assert-MockCalled Connect-MgGraph -Times 1 -ModuleName Connection
180+
}
181+
182+
It "Should handle Graph connection with scopes" {
183+
Mock Connect-MgGraph { } -ModuleName Connection
184+
Mock Get-MgContext {
185+
[PSCustomObject]@{
186+
Account = '[email protected]'
187+
Scopes = @('User.Read', 'Mail.Read')
188+
}
189+
} -ModuleName Connection
190+
191+
$Scopes = @('User.Read', 'Mail.Read')
192+
{ Connect-Service -Services 'Graph' -Scopes $Scopes -DontConfirm } | Should -Not -Throw
193+
194+
Assert-MockCalled Connect-MgGraph -Times 1 -ModuleName Connection
195+
}
196+
197+
It "Should handle Graph connection with access token" {
198+
Mock Connect-MgGraph { } -ModuleName Connection
199+
Mock Get-MgContext {
200+
[PSCustomObject]@{
201+
Account = '[email protected]'
202+
Scopes = @('User.Read')
203+
}
204+
} -ModuleName Connection
205+
206+
$SecureToken = ConvertTo-SecureString 'token123' -AsPlainText -Force
207+
{ Connect-Service -Services 'Graph' -AccessToken $SecureToken -DontConfirm } | Should -Not -Throw
208+
209+
Assert-MockCalled Connect-MgGraph -Times 1 -ModuleName Connection -ParameterFilter { $AccessToken -ne $null }
210+
}
211+
212+
It "Should handle insufficient scopes in Graph connection" {
213+
Mock Connect-MgGraph { } -ModuleName Connection
214+
Mock Get-MgContext {
215+
[PSCustomObject]@{
216+
Account = '[email protected]'
217+
Scopes = @('User.Read') # Missing Mail.Read
218+
}
219+
} -ModuleName Connection
220+
Mock Disconnect-MgGraph { } -ModuleName Connection
221+
222+
$RequiredScopes = @('User.Read', 'Mail.Read')
223+
{ Connect-Service -Services 'Graph' -Scopes $RequiredScopes -DontConfirm } | Should -Not -Throw
224+
225+
# Should disconnect due to insufficient scopes
226+
Assert-MockCalled Disconnect-MgGraph -Times 1 -ModuleName Connection
227+
}
228+
229+
It "Should handle Graph disconnection" {
230+
Mock Disconnect-MgGraph { } -ModuleName Connection
231+
232+
{ Disconnect-MgGraph } | Should -Not -Throw
233+
234+
Assert-MockCalled Disconnect-MgGraph -Times 1 -ModuleName Connection
235+
}
236+
}
237+
238+
Context "CheckOnly Parameter Tests" {
239+
It "Should check connection status without connecting" {
240+
Mock Get-ConnectionInformation { $null } -ModuleName Connection
241+
Mock Invoke-FailedExit { throw "Not connected" } -ModuleName Connection
242+
243+
{ Connect-Service -Services 'ExchangeOnline' -CheckOnly } | Should -Throw "Not connected"
244+
245+
# Should not attempt to connect
246+
Assert-MockCalled Connect-ExchangeOnline -Times 0 -ModuleName Connection
247+
}
248+
249+
It "Should pass check when already connected" {
250+
Mock Get-ConnectionInformation {
251+
[PSCustomObject]@{
252+
UserPrincipalName = '[email protected]'
253+
ConnectionId = 'existing-connection'
254+
}
255+
} -ModuleName Connection
256+
257+
{ Connect-Service -Services 'ExchangeOnline' -CheckOnly } | Should -Not -Throw
258+
}
259+
}
260+
261+
Context "DontConfirm Parameter Tests" {
262+
It "Should skip confirmation when DontConfirm is used" {
263+
Mock Get-ConnectionInformation {
264+
[PSCustomObject]@{
265+
UserPrincipalName = '[email protected]'
266+
ConnectionId = 'existing-connection'
267+
}
268+
} -ModuleName Connection
269+
270+
{ Connect-Service -Services 'ExchangeOnline' -DontConfirm } | Should -Not -Throw
271+
272+
# Should not call Get-UserConfirmation
273+
Assert-MockCalled Get-UserConfirmation -Times 0 -ModuleName Connection
274+
}
275+
276+
It "Should prompt for confirmation by default" {
277+
Mock Get-ConnectionInformation {
278+
[PSCustomObject]@{
279+
UserPrincipalName = '[email protected]'
280+
ConnectionId = 'existing-connection'
281+
}
282+
} -ModuleName Connection
283+
Mock Get-UserConfirmation { $true } -ModuleName Connection
284+
285+
{ Connect-Service -Services 'ExchangeOnline' } | Should -Not -Throw
286+
287+
Assert-MockCalled Get-UserConfirmation -Times 1 -ModuleName Connection
288+
}
289+
}
290+
291+
Context "Error Handling" {
292+
It "Should handle connection failures" {
293+
Mock Get-ConnectionInformation { $null } -ModuleName Connection
294+
Mock Connect-ExchangeOnline { throw "Connection failed" } -ModuleName Connection
295+
Mock Invoke-FailedExit { throw "Failed to connect" } -ModuleName Connection
296+
297+
{ Connect-Service -Services 'ExchangeOnline' -DontConfirm } | Should -Throw
298+
299+
Assert-MockCalled Invoke-FailedExit -Times 1 -ModuleName Connection
300+
}
301+
302+
It "Should handle disconnection failures" {
303+
Mock Disconnect-ExchangeOnline { throw "Disconnect failed" } -ModuleName Connection
304+
Mock Invoke-FailedExit { throw "Failed to disconnect" } -ModuleName Connection
305+
306+
{ Disconnect-ExchangeOnline } | Should -Throw
307+
}
308+
309+
It "Should handle Graph context retrieval failures" {
310+
Mock Get-MgContext { throw "Graph context error" } -ModuleName Connection
311+
Mock Connect-MgGraph { } -ModuleName Connection
312+
313+
{ Connect-Service -Services 'Graph' -DontConfirm } | Should -Not -Throw
314+
315+
# Should attempt to connect when context retrieval fails
316+
Assert-MockCalled Connect-MgGraph -Times 1 -ModuleName Connection
317+
}
318+
}
319+
320+
Context "Multiple Services Integration" {
321+
It "Should handle connecting to multiple services" {
322+
Mock Get-ConnectionInformation { $null } -ModuleName Connection
323+
Mock Get-MgContext { $null } -ModuleName Connection
324+
Mock Connect-ExchangeOnline { } -ModuleName Connection
325+
Mock Connect-MgGraph { } -ModuleName Connection
326+
327+
{ Connect-Service -Services @('ExchangeOnline', 'Graph') -DontConfirm } | Should -Not -Throw
328+
329+
Assert-MockCalled Connect-ExchangeOnline -Times 1 -ModuleName Connection
330+
Assert-MockCalled Connect-MgGraph -Times 1 -ModuleName Connection
331+
}
332+
333+
It "Should handle mixed connection states" {
334+
# ExchangeOnline already connected, Graph not connected
335+
Mock Get-ConnectionInformation {
336+
param($ConnectionId)
337+
if ($ConnectionId) {
338+
[PSCustomObject]@{
339+
UserPrincipalName = '[email protected]'
340+
ConnectionId = $ConnectionId
341+
}
342+
} else {
343+
[PSCustomObject]@{
344+
UserPrincipalName = '[email protected]'
345+
ConnectionId = 'exchange-connection'
346+
}
347+
}
348+
} -ModuleName Connection
349+
Mock Get-MgContext { $null } -ModuleName Connection
350+
Mock Connect-MgGraph { } -ModuleName Connection
351+
352+
{ Connect-Service -Services @('ExchangeOnline', 'Graph') -DontConfirm } | Should -Not -Throw
353+
354+
# Should only connect to Graph
355+
Assert-MockCalled Connect-ExchangeOnline -Times 0 -ModuleName Connection
356+
Assert-MockCalled Connect-MgGraph -Times 1 -ModuleName Connection
357+
}
358+
}
359+
360+
Context "Cross-Platform Considerations" {
361+
It "Should handle module import failures gracefully" {
362+
# Test that the function handles cases where Exchange/Graph modules aren't available
363+
Mock Connect-ExchangeOnline { throw "Module not found" } -ModuleName Connection
364+
Mock Invoke-FailedExit { throw "Connection failed" } -ModuleName Connection
365+
366+
{ Connect-Service -Services 'ExchangeOnline' -DontConfirm } | Should -Throw
367+
}
368+
369+
It "Should work with mock implementations" {
370+
# Verify that our mocking strategy allows tests to run on any platform
371+
Mock Get-ConnectionInformation { $null } -ModuleName Connection
372+
Mock Connect-ExchangeOnline { } -ModuleName Connection
373+
374+
{ Connect-Service -Services 'ExchangeOnline' -DontConfirm } | Should -Not -Throw
375+
}
376+
}
377+
}

0 commit comments

Comments
 (0)