From b0d994c99ffb6f9ce4f3b1df43d57f0cb43516f1 Mon Sep 17 00:00:00 2001 From: Lawrence Chen Date: Tue, 17 Mar 2026 00:14:28 -0700 Subject: [PATCH] Fix UI test helper closure captures --- .../BrowserOmnibarSuggestionsUITests.swift | 8 ++--- .../BrowserPaneNavigationKeybindUITests.swift | 6 ++-- .../MenuKeyEquivalentRoutingUITests.swift | 36 ++++++++++--------- .../MultiWindowNotificationsUITests.swift | 30 ++++++++-------- 4 files changed, 41 insertions(+), 39 deletions(-) diff --git a/cmuxUITests/BrowserOmnibarSuggestionsUITests.swift b/cmuxUITests/BrowserOmnibarSuggestionsUITests.swift index f1632666..1f6a85c8 100644 --- a/cmuxUITests/BrowserOmnibarSuggestionsUITests.swift +++ b/cmuxUITests/BrowserOmnibarSuggestionsUITests.swift @@ -98,7 +98,7 @@ final class BrowserOmnibarSuggestionsUITests: XCTestCase { // Note: example.com may redirect to example.org in some environments. XCTAssertTrue( waitForCondition(timeout: 8.0) { - containsExampleDomain((omnibar.value as? String) ?? "") + self.containsExampleDomain((omnibar.value as? String) ?? "") }, "Expected omnibar to navigate to example.com after keyboard nav + Enter. value=\(String(describing: omnibar.value))" ) @@ -134,7 +134,7 @@ final class BrowserOmnibarSuggestionsUITests: XCTestCase { // Note: example.com may redirect to example.org in some environments. XCTAssertTrue( waitForCondition(timeout: 8.0) { - containsExampleDomain((omnibar.value as? String) ?? "") + self.containsExampleDomain((omnibar.value as? String) ?? "") }, "Expected committed omnibar value to contain example.com or example.org. value=\(String(describing: omnibar.value))" ) @@ -328,7 +328,7 @@ final class BrowserOmnibarSuggestionsUITests: XCTestCase { let loaded = waitForCondition(timeout: 8.0) { let value = ((omnibar.value as? String) ?? "").lowercased() - return containsExampleDomain(value) + return self.containsExampleDomain(value) } XCTAssertTrue(loaded, "Expected baseline navigation to load before Cmd+L fast-typing check.") @@ -642,7 +642,7 @@ final class BrowserOmnibarSuggestionsUITests: XCTestCase { private func waitForSuggestionRowToBeSelected(_ row: XCUIElement, timeout: TimeInterval) -> Bool { waitForCondition(timeout: timeout) { - isSuggestionRowSelected(row) + self.isSuggestionRowSelected(row) } } diff --git a/cmuxUITests/BrowserPaneNavigationKeybindUITests.swift b/cmuxUITests/BrowserPaneNavigationKeybindUITests.swift index dcdcb220..1c2bd61b 100644 --- a/cmuxUITests/BrowserPaneNavigationKeybindUITests.swift +++ b/cmuxUITests/BrowserPaneNavigationKeybindUITests.swift @@ -973,14 +973,14 @@ final class BrowserPaneNavigationKeybindUITests: XCTestCase { private func waitForData(keys: [String], timeout: TimeInterval) -> Bool { waitForCondition(timeout: timeout) { - guard let data = loadData() else { return false } + guard let data = self.loadData() else { return false } return keys.allSatisfy { data[$0] != nil } } } - private func waitForDataMatch(timeout: TimeInterval, predicate: ([String: String]) -> Bool) -> Bool { + private func waitForDataMatch(timeout: TimeInterval, predicate: @escaping ([String: String]) -> Bool) -> Bool { waitForCondition(timeout: timeout) { - guard let data = loadData() else { return false } + guard let data = self.loadData() else { return false } return predicate(data) } } diff --git a/cmuxUITests/MenuKeyEquivalentRoutingUITests.swift b/cmuxUITests/MenuKeyEquivalentRoutingUITests.swift index 64d48cee..8ff0ab47 100644 --- a/cmuxUITests/MenuKeyEquivalentRoutingUITests.swift +++ b/cmuxUITests/MenuKeyEquivalentRoutingUITests.swift @@ -4,6 +4,16 @@ import CoreGraphics import ImageIO import Darwin +private extension XCTestCase { + func waitForCondition(timeout: TimeInterval, predicate: @escaping () -> Bool) -> Bool { + let expectation = XCTNSPredicateExpectation( + predicate: NSPredicate { _, _ in predicate() }, + object: nil + ) + return XCTWaiter().wait(for: [expectation], timeout: timeout) == .completed + } +} + final class MenuKeyEquivalentRoutingUITests: XCTestCase { private var gotoSplitPath = "" private var keyequivPath = "" @@ -127,21 +137,21 @@ final class MenuKeyEquivalentRoutingUITests: XCTestCase { private func waitForGotoSplit(keys: [String], timeout: TimeInterval) -> Bool { waitForCondition(timeout: timeout) { - guard let data = loadGotoSplit() else { return false } + guard let data = self.loadGotoSplit() else { return false } return keys.allSatisfy { data[$0] != nil } } } - private func waitForGotoSplitMatch(timeout: TimeInterval, predicate: ([String: String]) -> Bool) -> Bool { + private func waitForGotoSplitMatch(timeout: TimeInterval, predicate: @escaping ([String: String]) -> Bool) -> Bool { waitForCondition(timeout: timeout) { - guard let data = loadGotoSplit() else { return false } + guard let data = self.loadGotoSplit() else { return false } return predicate(data) } } private func waitForKeyequivInt(key: String, toBeAtLeast expected: Int, timeout: TimeInterval) -> Bool { waitForCondition(timeout: timeout) { - let value = loadKeyequiv()[key].flatMap(Int.init) ?? 0 + let value = self.loadKeyequiv()[key].flatMap(Int.init) ?? 0 return value >= expected } } @@ -798,14 +808,14 @@ final class SplitCloseRightBlankRegressionUITests: XCTestCase { private func waitForData(keys: [String], timeout: TimeInterval) -> Bool { waitForCondition(timeout: timeout) { - guard let data = loadData() else { return false } + guard let data = self.loadData() else { return false } return keys.allSatisfy { data[$0] != nil } } } private func waitForAnyData(timeout: TimeInterval) -> Bool { waitForCondition(timeout: timeout) { - loadData() != nil + self.loadData() != nil } } @@ -813,7 +823,7 @@ final class SplitCloseRightBlankRegressionUITests: XCTestCase { var last: [String: String]? _ = waitForCondition(timeout: timeout) { - guard let data = loadData() else { return false } + guard let data = self.loadData() else { return false } last = data if let setupError = data["setupError"], !setupError.isEmpty { @@ -866,24 +876,16 @@ final class SplitCloseRightBlankRegressionUITests: XCTestCase { private func waitForSocketPong(timeout: TimeInterval) -> Bool { waitForCondition(timeout: timeout) { - socketCommand("ping") == "PONG" + self.socketCommand("ping") == "PONG" } } private func waitForVisualDone(timeout: TimeInterval) -> Bool { waitForCondition(timeout: timeout) { - loadData()?["visualDone"] == "1" + self.loadData()?["visualDone"] == "1" } } - private func waitForCondition(timeout: TimeInterval, predicate: @escaping () -> Bool) -> Bool { - let expectation = XCTNSPredicateExpectation( - predicate: NSPredicate { _, _ in predicate() }, - object: nil - ) - return XCTWaiter().wait(for: [expectation], timeout: timeout) == .completed - } - private func socketCommand(_ cmd: String) -> String? { if socketClient == nil { socketClient = ControlSocketClient(path: socketPath) diff --git a/cmuxUITests/MultiWindowNotificationsUITests.swift b/cmuxUITests/MultiWindowNotificationsUITests.swift index cf7bd1c2..d433dc94 100644 --- a/cmuxUITests/MultiWindowNotificationsUITests.swift +++ b/cmuxUITests/MultiWindowNotificationsUITests.swift @@ -423,7 +423,7 @@ final class MultiWindowNotificationsUITests: XCTestCase { private func waitForFocusChange(from token: String?, timeout: TimeInterval) -> Bool { waitForCondition(timeout: timeout) { - guard let data = loadData(), + guard let data = self.loadData(), let current = data["focusToken"], !current.isEmpty else { return false @@ -434,14 +434,14 @@ final class MultiWindowNotificationsUITests: XCTestCase { private func waitForData(keys: [String], timeout: TimeInterval) -> Bool { waitForCondition(timeout: timeout) { - guard let data = loadData() else { return false } + guard let data = self.loadData() else { return false } return keys.allSatisfy { (data[$0] ?? "").isEmpty == false } } } - private func waitForDataMatch(timeout: TimeInterval, predicate: ([String: String]) -> Bool) -> Bool { + private func waitForDataMatch(timeout: TimeInterval, predicate: @escaping ([String: String]) -> Bool) -> Bool { waitForCondition(timeout: timeout) { - guard let data = loadData() else { return false } + guard let data = self.loadData() else { return false } return predicate(data) } } @@ -449,7 +449,7 @@ final class MultiWindowNotificationsUITests: XCTestCase { private func waitForSocketPong(timeout: TimeInterval) -> String? { var lastResponse: String? _ = waitForCondition(timeout: timeout) { - lastResponse = socketCommand("ping") + lastResponse = self.socketCommand("ping") return lastResponse == "PONG" } return lastResponse == "PONG" ? "PONG" : (socketCommand("ping") ?? lastResponse) @@ -457,7 +457,7 @@ final class MultiWindowNotificationsUITests: XCTestCase { private func waitForTerminalFocus(surfaceId: String, timeout: TimeInterval) -> Bool { waitForCondition(timeout: timeout) { - socketCommand("is_terminal_focused \(surfaceId)") == "true" + self.socketCommand("is_terminal_focused \(surfaceId)") == "true" } } @@ -465,8 +465,8 @@ final class MultiWindowNotificationsUITests: XCTestCase { var lastStdout: String? var lastStderr: String? let didSucceed = waitForCondition(timeout: timeout) { - let result = runCmuxCommand( - socketPath: socketPath, + let result = self.runCmuxCommand( + socketPath: self.socketPath, arguments: ["ping"], responseTimeoutSeconds: 2.0 ) @@ -481,8 +481,8 @@ final class MultiWindowNotificationsUITests: XCTestCase { if result.terminationStatus == 0, stdout == "PONG" { return true } - if isSocketPermissionFailure(stderr), - waitForSocketPong(timeout: 0.5) == "PONG" { + if self.isSocketPermissionFailure(stderr), + self.waitForSocketPong(timeout: 0.5) == "PONG" { return true } return false @@ -553,7 +553,7 @@ final class MultiWindowNotificationsUITests: XCTestCase { private func waitForSurfaceId(forWorkspaceId workspaceId: String, timeout: TimeInterval) -> String? { var surfaceId: String? _ = waitForCondition(timeout: timeout) { - surfaceId = firstSurfaceId(forWorkspaceId: workspaceId) + surfaceId = self.firstSurfaceId(forWorkspaceId: workspaceId) return surfaceId != nil } return surfaceId ?? firstSurfaceId(forWorkspaceId: workspaceId) @@ -562,7 +562,7 @@ final class MultiWindowNotificationsUITests: XCTestCase { private func waitForSurfaceIdViaCLI(forWorkspaceId workspaceId: String, timeout: TimeInterval) -> String? { var surfaceId: String? _ = waitForCondition(timeout: timeout) { - surfaceId = firstSurfaceIdViaCLI(forWorkspaceId: workspaceId) + surfaceId = self.firstSurfaceIdViaCLI(forWorkspaceId: workspaceId) return surfaceId != nil } return surfaceId ?? firstSurfaceIdViaCLI(forWorkspaceId: workspaceId) @@ -899,15 +899,15 @@ final class MultiWindowNotificationsUITests: XCTestCase { guard FileManager.default.fileExists(atPath: candidate) else { continue } // Primary candidate is the explicitly requested CMUX_SOCKET_PATH. If it responds, // prefer it even before workspace contents are fully initialized. - if socketRespondsToPing(at: candidate) { + if self.socketRespondsToPing(at: candidate) { resolvedPath = candidate return true } } for candidate in fallbackCandidates { guard FileManager.default.fileExists(atPath: candidate) else { continue } - if socketRespondsToPing(at: candidate), - socketMatchesRequiredWorkspace(candidate, workspaceId: requiredWorkspaceId) { + if self.socketRespondsToPing(at: candidate), + self.socketMatchesRequiredWorkspace(candidate, workspaceId: requiredWorkspaceId) { resolvedPath = candidate return true }