Files
Sharepoint-Toolbox/.planning/codebase/TESTING.md
Kawa 63cf69f114 docs: map existing codebase
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 09:28:40 +02:00

7.8 KiB

Testing Patterns

Analysis Date: 2026-04-02

Test Framework

Status: No automated testing framework detected

Infrastructure: Not applicable

  • No test runner (Jest, Vitest, Pester)
  • No test configuration files
  • No test suite in codebase
  • No CI/CD pipeline test stage configured

Testing Approach

Current Testing Model: Manual testing via GUI

Test Methods:

  • GUI Testing: All functionality tested through WinForms UI
    • Manual interaction with controls and dialogs
    • Visual verification of results in generated reports
    • Log output observation in RichTextBox
  • Report Validation: HTML and CSV exports manually reviewed for correctness
  • API Integration: Manual testing of PnP.PowerShell operations against live SharePoint tenant
  • Regression Testing: Ad-hoc manual verification of features after changes

Code Organization for Testing

Testability Patterns: Limited

The monolithic single-file architecture (Sharepoint_ToolBox.ps1 at 6408 lines) makes isolated unit testing challenging. Key observations:

Tight Coupling to UI:

  • Core business logic embedded in event handlers
  • Heavy reliance on global $script: scope for state
  • Example: Load-Profiles reads from Get-ProfilesFilePath, which is file-system dependent
  • Site picker functionality (Show-SitePicker) spawns background runspace but depends on form being instantiated

Hard Dependencies:

  • PnP.PowerShell module imported dynamically in background runspace blocks
  • File system access (profiles, templates, settings) not abstracted
  • SharePoint connection state implicit in PnP connection context

Areas with Better Isolation:

  • Pure utility functions like Format-Bytes, EscHtml could be unit tested
  • Data transformation functions like Merge-PermissionRows accept input arrays and return structured output
  • HTML generation in Export-PermissionsToHTML and Export-StorageToHTML could be tested against expected markup

Background Runspace Pattern

Async Execution Model: Most long-running operations execute in separate PowerShell runspace to prevent UI blocking:

# 1. Create synchronized hashtable for communication
$sync = [hashtable]::Synchronized(@{
    Done   = $false
    Error  = $null
    Result = $null
    Queue  = [System.Collections.Generic.Queue[object]]::new()
})

# 2. Define background script block (has access to passed parameters only)
$bgScript = {
    param($Url, $ClientId, $Sync)
    try {
        Import-Module PnP.PowerShell -ErrorAction Stop
        Connect-PnPOnline -Url $Url -Interactive -ClientId $ClientId
        # Perform work
        $Sync.Result = $data
    } catch {
        $Sync.Error = $_.Exception.Message
    } finally {
        $Sync.Done = $true
    }
}

# 3. Launch in runspace
$rs = [System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace()
$rs.ApartmentState = "STA"; $rs.ThreadOptions = "ReuseThread"; $rs.Open()
$ps = [System.Management.Automation.PowerShell]::Create()
$ps.Runspace = $rs
[void]$ps.AddScript($bgScript)
[void]$ps.AddArgument($url)
$hnd = $ps.BeginInvoke()

# 4. Poll completion with timer
$tmr = New-Object System.Windows.Forms.Timer
$tmr.Interval = 300
$tmr.Add_Tick({
    if ($sync.Done) {
        [void]$ps.EndInvoke($hnd)
        $rs.Close(); $rs.Dispose()
        # Update UI with $sync.Result
    }
})
$tmr.Start()

Used for:

  • Site picker loading: Show-SitePicker (lines 212-471)
  • Template capture: Background job in template manager (lines 900+)
  • Site creation: Background job in bulk creation (lines 1134+)
  • Permission/storage export: Operations triggered from event handlers
  • File search: Background search execution

Message Queue Pattern

For logging from background runspaces:

# Background function enqueues messages
function BgLog([string]$m, [string]$c="LightGreen") {
    $Sync.Queue.Enqueue([PSCustomObject]@{ Text=$m; Color=$c })
}

# Main thread timer dequeues and displays
$tmr.Add_Tick({
    while ($sync.Queue.Count -gt 0) {
        $msg = $sync.Queue.Dequeue()
        _Tpl-Log -Box $textBox -Msg $msg.Text -Color $msg.Color
    }
})

Rationale: Avoids cross-thread UI access violations by queueing messages from worker thread.

Common Testing Patterns in Code

Null/Existence Checks:

# Before using objects
if ($script:LogBox -and !$script:LogBox.IsDisposed) { ... }
if ($data -and $data.Count -gt 0) { ... }
if ([string]::IsNullOrWhiteSpace($value)) { return $false }

Error Logging in Loops:

# Catch errors in data processing, log, continue
foreach ($item in $items) {
    try {
        # Process item
    } catch { 
        BgLog "  Skipped: $($_.Exception.Message)" "DarkGray" 
    }
}

Validation Before Operations:

function Validate-Inputs {
    if ([string]::IsNullOrWhiteSpace($script:txtClientId.Text)) {
        [System.Windows.Forms.MessageBox]::Show(...)
        return $false
    }
    return $true
}

# Called before starting long operations
if (-not (Validate-Inputs)) { return }

Data Flow Testing Approach

For Feature Development:

  1. Manual Test Cases (observed pattern, not formalized):

    • Permissions Export:

      • Select site with multiple libraries
      • Choose CSV format
      • Verify CSV contains all libraries and permissions
      • Test HTML format in browser for interactivity
    • Storage Metrics:

      • Run with PerLibrary flag
      • Verify folder hierarchy is captured
      • Test recursive subsite inclusion
      • Validate byte calculations
    • Template Capture/Apply:

      • Capture from source site
      • Verify JSON structure
      • Create new site from template
      • Verify structure, permissions, settings applied
    • File Search:

      • Test regex patterns
      • Verify date filtering
      • Test large result sets (pagination)
      • Check CSV/HTML output
  2. Visual Verification:

    • Log output reviewed in RichTextBox for progress
    • Generated HTML reports tested in multiple browsers
    • CSV files opened in Excel for format verification

Fragility Points & Testing Considerations

PnP Connection Management:

  • No connection pooling; each operation may create new connection
  • Interactive auth prompt appears per runspace
  • Risk: Auth failures not consistently handled
  • Testing Need: Mock PnP module or use test tenant

HTML Generation:

  • String concatenation for large HTML documents (lines 1475+)
  • Inline CSS for styling
  • JavaScript for interactivity
  • Risk: Complex HTML fragments prone to markup errors
  • Testing Need: Validate HTML structure and JavaScript functionality

JSON Persistence:

  • Profiles, templates, settings stored in JSON
  • ConvertTo-Json/-From-Json without depth specification can truncate
  • Risk: Nested objects may not round-trip correctly
  • Testing Need: Validate all object types persist/restore

Background Runspace Cleanup:

  • Runspace and PowerShell objects must be disposed
  • Timer must be stopped and disposed
  • Risk: Resource leaks if exception occurs before cleanup
  • Testing Need: Verify cleanup in error paths

Suggested Testing Improvements

Unit Testing:

  1. Extract pure functions (no UI/file system dependencies)

    • Format-Bytes, EscHtml, Merge-PermissionRows
    • HTML generation functions
  2. Use Pester framework for PowerShell unit tests:

    Describe "Format-Bytes" {
        It "Formats bytes to GB" {
            Format-Bytes (1GB * 2) | Should -Be "2 GB"
        }
    }
    
  3. Mock file system and PnP operations for integration tests

Integration Testing:

  1. Use test SharePoint tenant for functional testing
  2. Automate report generation and validation
  3. Script common user workflows

Regression Testing:

  1. Maintain test suite of sites with known structures
  2. Generate reports, compare outputs
  3. Run before major releases

Testing analysis: 2026-04-02