// // StartupTest.swift // UI Tests // // Created by Nico Verbruggen on 14/10/2022. // Copyright © 2025 Nico Verbruggen. All rights reserved. // import XCTest final class StartupTest: UITestCase { override func setUpWithError() throws { continueAfterFailure = false } override func tearDownWithError() throws {} final func test_launch_halts_due_to_system_configuration_issue() throws { var configuration = TestableConfigurations.working configuration.filesystem["/opt/homebrew/bin/php"] = nil // PHP binary must be missing let app = launch( waitForInitialization: false, // we expect an error during initialization with: configuration ) // Dialog 1: "PHP is not correctly installed" assertAllExist([ app.staticTexts["startup.errors.php_binary.title".localized], app.buttons["startup.alert.fix_manually".localized], app.buttons["startup.alert.fix_automatically".localized] ]) click(app.buttons["startup.alert.fix_manually".localized]) // Dialog 2: PHP Monitor failed to start assertAllExist([ app.dialogs["generic.notice".localized], app.staticTexts["alert.cannot_start.title".localized], app.buttons["alert.cannot_start.retry".localized], app.buttons["alert.cannot_start.close".localized] ]) click(app.buttons["alert.cannot_start.retry".localized]) // Dialog 1 again assertExists(app.staticTexts["startup.errors.php_binary.title".localized]) // At this point, we can terminate the test app.terminate() } final func test_launch_halts_and_automic_fix_cannot_be_applied() throws { var configuration = TestableConfigurations.working configuration.shellOutput["/opt/homebrew/bin/brew link php"] = .delayed(0.5, "Brew was unable to link PHP.", .stdErr) configuration.filesystem["/opt/homebrew/bin/php"] = nil // PHP binary must be missing let app = launch( waitForInitialization: false, // we expect an error during initialization with: configuration ) // Dialog 1: "PHP is not correctly installed" assertAllExist([ app.staticTexts["startup.errors.php_binary.title".localized], app.buttons["startup.alert.fix_manually".localized], app.buttons["startup.alert.fix_automatically".localized] ]) click(app.buttons["startup.alert.fix_automatically".localized]) // TODO: Verify the alert is in a failed state w/ buttons to retry or quit } final func test_launch_halts_and_automic_fix_can_be_applied() throws { var configuration = TestableConfigurations.working // TODO: Make fake shell output closure accessible w/ container so fake tests can manipulate the app's state configuration.shellOutput["/opt/homebrew/bin/brew link php"] = .delayed(0.5, "Linked PHP.", .stdOut) configuration.filesystem["/opt/homebrew/bin/php"] = nil // PHP binary must be missing let app = launch( waitForInitialization: false, // we expect an error during initialization with: configuration ) // Dialog 1: "PHP is not correctly installed" assertAllExist([ app.staticTexts["startup.errors.php_binary.title".localized], app.buttons["startup.alert.fix_manually".localized], app.buttons["startup.alert.fix_automatically".localized] ]) click(app.buttons["startup.alert.fix_automatically".localized]) // We wait for the app to complete launch waitForMenu(app) } final func test_get_warning_about_missing_fpm_symlink() throws { var configuration = TestableConfigurations.working configuration.filesystem["/opt/homebrew/etc/php/8.4/php-fpm.d/valet-fpm.conf"] = nil let app = launch( waitForInitialization: false, // we expect an error during initialization with: configuration ) assertExists(app.staticTexts["alert.php_fpm_broken.title".localized], 3.0) click(app.buttons["generic.ok".localized]) } final func test_get_warning_about_unsupported_valet_version() throws { var configuration = TestableConfigurations.working configuration.shellOutput["valet --version"] = .instant("Laravel Valet 5.0") let app = launch( waitForInitialization: false, // we expect an error during initialization with: configuration ) assertExists(app.staticTexts["startup.errors.valet_version_not_supported.title".localized], 3.0) click(app.buttons["startup.fix_manually".localized]) } }