microsoft / microsoft/CSS-Exchange

Finish and merge the shared M365 connection helper (PR #2090) — including Pester coverage

Open
#2,591 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Enhancement Pester Public Folders Shared Function Triage Work - Medium Change
Dominant language
PowerShell
Stars
1.3k
Forks
395
Avg merge
14h 7m
Merged PRs (30d)
5

Description

Parent: #2590

Complete PR #2090 so we have a single, correct, tested helper for Shared/M365/EXOConnection.ps1 (Connect-EXOAdvanced), Shared/M365/GraphConnection.ps1 (Connect-GraphAdvanced), and Shared/ModuleHandle.ps1 (Request-Module).

Housekeeping

  • Squash PR #2090 to a single commit (requested by @dpaulson45 five times over 2024–2026; blocking merge).

Connect-EXOAdvanced — required additions

  • 🚨 -AzureADAuthorizationEndpointUri — sovereign clouds (GCC High, DoD, 21Vianet, Germany) cannot connect without it. Splat only when non-empty.
  • -ConnectionUri — required for MailPublicFolderSync + 21Vianet callers. Default to https://outlook.office365.com/powerShell-liveID.
  • -Credential — required for non-interactive scenarios. Splat only when non-null.
  • Fix -Prefix parameter set binding. Today it's bound only to the AllowMultipleSessions set. Make it valid in the SingleSession set too — every MailPublicFolderSync script uses -Prefix "Remote" on a single session.
  • Default [string]$Prefix = '', not $null. Splat -Prefix only when non-empty.
  • Session reuse check must consider prefix + tenant + UPN, not just ModulePrefix. Mirror the tenant check that already exists in Connect-GraphAdvanced.
  • Get-Module -ListAvailable fallback when Get-InstalledModule returns nothing (modules installed via MSI, side-loading, or provisioned images aren't visible to PowerShellGet).
  • New Disconnect-EXOAdvanced companion — accepts the connection object the helper returned, disconnects only that session. Never touches sessions the helper didn't open. This closes the class of bugs seen in Import-MailPublicFolders.ps1 (unguarded Disconnect-ExchangeOnline).
  • Document unattended usage in the function help — ConfirmImpact = "High" requires the caller to pass -Confirm:$false for automation.
  • Document the return contract$null on failure (do not throw). Callers should code against if (-not $exo) { return }.

Connect-GraphAdvanced — required additions

  • -Environment (Global / USGov / USGovDoD / China) — sovereign-cloud parity with Connect-EXOAdvanced.
  • Verify same Disconnect-GraphAdvanced companion story.

Request-Module (Shared/ModuleHandle.ps1) — required additions

  • -MaximumVersion — some callers need to pin around known-bad module releases.
  • Reconsider Install-Module -AllowClobber — silently overrides other modules' cmdlets. At minimum, warn.
  • Get-Module -ListAvailable fallback same as above.

Pester coverage (new — not currently in PR #2090)

@dpaulson45 asked for tests on 11/04/2024; they were never added.

Follow the mocking pattern proven safe in Sync-ModernMailPublicFolders.Tests.ps1no real connection to Exchange Online or Graph is made. Every network cmdlet must be mocked; a stub Connect-ExchangeOnline at test-scope throws if a code path forgets to mock it:

BeforeAll {
    . $PSScriptRoot\..\M365\EXOConnection.ps1

    # Safety net: fail loudly if any test forgets to mock the real cmdlet
    function Connect-ExchangeOnline {
        param($ConnectionUri, $Prefix, $Credential, $AzureADAuthorizationEndpointUri, $ShowBanner, $ErrorAction)
        throw "Connect-ExchangeOnline must be mocked."
    }
    function Get-ConnectionInformation { throw "Get-ConnectionInformation must be mocked." }
    function Disconnect-ExchangeOnline  { throw "Disconnect-ExchangeOnline must be mocked." }
    function Install-Module             { throw "Install-Module must be mocked." }
}

Required test cases for Connect-EXOAdvanced:

  • Success on a clean environment (no existing session): calls Connect-ExchangeOnline -ErrorAction Stop -ShowBanner:$false, returns connection info.
  • Reuses an existing single session with matching prefix + tenant + UPN.
  • Does not reuse a session whose tenant/UPN differs (regression guard).
  • -AllowMultipleSessions opens a second session when one already exists with a different prefix.
  • -Prefix is accepted in the SingleSession parameter set.
  • -AzureADAuthorizationEndpointUri is forwarded when specified; not forwarded when empty.
  • -ConnectionUri is forwarded when specified.
  • -Credential is forwarded when specified.
  • Non-terminating Connect-ExchangeOnline error (mock throws) → helper returns $null, does not report success.
  • Import-Module failure → helper returns $null, never invokes Connect-ExchangeOnline.
  • Request-Module returning $false → helper returns $null.
  • Disconnect-EXOAdvanced disconnects only the session the helper opened; ignores sessions the helper didn't open.

Required test cases for Connect-GraphAdvanced:

  • Scope mismatch triggers reconnect.
  • Tenant mismatch triggers failure (as designed).
  • -Environment forwarded to Connect-MgGraph.
  • Non-terminating Connect-MgGraph error → returns $null.

Required test cases for Request-Module:

  • Get-InstalledModule hit → returns $true without calling Install-Module.
  • Get-InstalledModule miss + Get-Module -ListAvailable hit → returns $true without calling Install-Module.
  • Get-InstalledModule miss + no available → calls Install-Module with correct scope.
  • -InstallAllUsersIfNotAvailable without admin returns $false.
  • -MinModuleVersion / -MaximumVersion forwarded to both Get-InstalledModule and Install-Module.

Done when: PR #2090 is merged with all boxes above checked and CI green.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reviewing PR #2090 and the three named helper files: Shared/M365/EXOConnection.ps1, Shared/M365/GraphConnection.ps1, and Shared/ModuleHandle.ps1. Use the mocking pattern in PublicFolders/MailPublicFolderSync/Tests/Sync-ModernMailPublicFolders.Tests.ps1, then add the requested Pester coverage; done means every listed box is checked, PR #2090 is merged, and CI is green.

Written by the indexing model from the issue text.

Assessment

Tech stack
powershell
Domain
authentication, testing, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.