# 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:

```powershell
# 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:**

```powershell
# 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:**
```powershell
# 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:**
```powershell
# Catch errors in data processing, log, continue
foreach ($item in $items) {
    try {
        # Process item
    } catch { 
        BgLog "  Skipped: $($_.Exception.Message)" "DarkGray" 
    }
}
```

**Validation Before Operations:**
```powershell
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:
   ```powershell
   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*
