This document describes the implementation of automatic dialog timeouts for the AutoRip2MKV-Mac application to ensure unit tests don't hang waiting for user input.
Previously, unit tests would hang indefinitely when the application attempted to display modal dialogs (NSAlert, NSOpenPanel, etc.) because these dialogs require user interaction to dismiss. This made automated testing unreliable and prevented continuous integration workflows.
We implemented a comprehensive testing utilities system that automatically detects test environments and simulates dialog interactions instead of showing actual modal dialogs.
A singleton utility class that provides:
-
Environment Detection: Detects when running in test environments using multiple methods:
- XCTest framework presence (
NSClassFromString("XCTestCase")) - XCTest configuration file path environment variable
- Command line arguments (
--headless,--testing,--ci,--automated) - Environment variables (
CI,GITHUB_ACTIONS,JENKINS_URL,TESTING,HEADLESS)
- XCTest framework presence (
-
Alert Simulation:
showAlert()method that:- In test environments: logs alerts to console or custom log handlers
- In normal environments: displays actual NSAlert dialogs
-
File Panel Simulation:
showFilePanel()method that:- In test environments: returns simulated file paths
- In normal environments: displays actual NSOpenPanel dialogs
Updated MainViewController.swift to use the testing utilities:
- Alert Handling: Replaced direct
NSAlert.runModal()calls withtestingUtils.showAlert() - File Panel Handling: Replaced direct
NSOpenPanel.runModal()calls withtestingUtils.showFilePanel() - Custom Log Integration: All simulated dialogs are logged to the application's log view
Added convenience extensions to NSViewController:
testingUtilsproperty for easy access toTestingUtilities.sharedisRunningInTestEnvironmentcomputed property
Comprehensive tests for the testing utilities:
- Environment detection verification
- Alert handling simulation
- File panel simulation
- Performance tests
- Thread safety tests
- Edge cases (empty messages, nil handlers)
Integration tests verifying that dialogs don't block in test environments:
- Alert timeout verification (< 1 second)
- File panel simulation verification
- Multiple concurrent dialogs handling
- Complete workflow testing
- Performance verification
No changes required. The application works exactly as before for end users.
Tests automatically benefit from dialog simulation without any additional configuration. Example:
func testRipperFailure() {
let viewController = MainViewController()
viewController.loadView()
// This will not block in test environment
viewController.ripperDidFail(with: someError)
// Test continues immediately
XCTAssertTrue(someCondition)
}The system automatically detects common CI environments and enables simulation mode. You can also force testing mode using:
- Command line:
--headless,--testing,--ci,--automated - Environment variables:
CI=1,TESTING=1,HEADLESS=1
- Reliable Testing: Unit tests no longer hang waiting for user input
- Faster Test Execution: No modal dialogs to slow down test runs
- CI/CD Compatible: Works seamlessly in automated environments
- Zero Impact on User Experience: Normal application behavior unchanged
- Comprehensive Coverage: Handles all types of modal dialogs
- Easy Maintenance: Centralized dialog handling logic
All 92 tests pass, including:
- 12 TestingUtilitiesTests
- 10 DialogTimeoutIntegrationTests
- All existing tests remain unaffected
The implementation successfully resolves the issue where unit tests would wait for user input, ensuring all dialogs automatically timeout in test environments while maintaining full functionality for end users.