@@ -629,12 +629,16 @@ final class BrowserPaneNavigationKeybindUITests: XCTestCase {
629629 )
630630 return
631631 }
632- guard let fixture = installBrowserContentEditableFixture (
632+ let installResult = installBrowserContentEditableFixture (
633633 surfaceId: surfaceId,
634634 secondaryClickOffsetX: secondaryClickOffsetX,
635635 secondaryClickOffsetY: secondaryClickOffsetY
636- ) else {
637- XCTFail ( " Expected contenteditable fixture installation to succeed " )
636+ )
637+ guard let fixture = installResult. fixture else {
638+ XCTFail (
639+ " Expected contenteditable fixture installation to succeed. " +
640+ " diagnostic= \( installResult. diagnostic) "
641+ )
638642 return
639643 }
640644
@@ -1541,7 +1545,18 @@ final class BrowserPaneNavigationKeybindUITests: XCTestCase {
15411545 surfaceId: String ,
15421546 secondaryClickOffsetX: Double ,
15431547 secondaryClickOffsetY: Double
1544- ) -> BrowserContentEditableFixture ? {
1548+ ) -> BrowserContentEditableFixtureInstallResult {
1549+ let prereq = waitForBrowserContentEditableFixturePrerequisites (
1550+ surfaceId: surfaceId,
1551+ timeout: 8.0
1552+ )
1553+ guard prereq. ready else {
1554+ return BrowserContentEditableFixtureInstallResult (
1555+ fixture: nil ,
1556+ diagnostic: " prerequisites_not_ready last= \( prereq. diagnostic) "
1557+ )
1558+ }
1559+
15451560 let script = """
15461561 (() => {
15471562 const secondary = document.getElementById( " cmux-ui-test-focus-input-secondary " );
@@ -1627,8 +1642,14 @@ final class BrowserPaneNavigationKeybindUITests: XCTestCase {
16271642 })();
16281643 """
16291644
1630- guard let payload = browserEvalDict ( surfaceId: surfaceId, script: script) ,
1631- ( payload [ " ok " ] as? Bool ) == true ,
1645+ guard let payload = browserEvalDict ( surfaceId: surfaceId, script: script) else {
1646+ return BrowserContentEditableFixtureInstallResult (
1647+ fixture: nil ,
1648+ diagnostic: " install_payload_nil prereq= \( prereq. diagnostic) "
1649+ )
1650+ }
1651+
1652+ guard ( payload [ " ok " ] as? Bool ) == true ,
16321653 let editorId = payload [ " editorId " ] as? String ,
16331654 !editorId. isEmpty,
16341655 let activeId = payload [ " activeId " ] as? String ,
@@ -1637,16 +1658,54 @@ final class BrowserPaneNavigationKeybindUITests: XCTestCase {
16371658 let secondaryCenterY = ( payload [ " secondaryCenterY " ] as? NSNumber ) ? . doubleValue,
16381659 let editorCenterX = ( payload [ " editorCenterX " ] as? NSNumber ) ? . doubleValue,
16391660 let editorCenterY = ( payload [ " editorCenterY " ] as? NSNumber ) ? . doubleValue else {
1640- return nil
1661+ return BrowserContentEditableFixtureInstallResult (
1662+ fixture: nil ,
1663+ diagnostic: " install_payload_incomplete payload= \( payload) prereq= \( prereq. diagnostic) "
1664+ )
16411665 }
16421666
1643- return BrowserContentEditableFixture (
1644- editorId: editorId,
1645- clickOffsetX: secondaryClickOffsetX + ( editorCenterX - secondaryCenterX) ,
1646- clickOffsetY: secondaryClickOffsetY + ( editorCenterY - secondaryCenterY)
1667+ return BrowserContentEditableFixtureInstallResult (
1668+ fixture: BrowserContentEditableFixture (
1669+ editorId: editorId,
1670+ clickOffsetX: secondaryClickOffsetX + ( editorCenterX - secondaryCenterX) ,
1671+ clickOffsetY: secondaryClickOffsetY + ( editorCenterY - secondaryCenterY)
1672+ ) ,
1673+ diagnostic: " ok "
16471674 )
16481675 }
16491676
1677+ private func waitForBrowserContentEditableFixturePrerequisites(
1678+ surfaceId: String ,
1679+ timeout: TimeInterval
1680+ ) -> ( ready: Bool , diagnostic: String ) {
1681+ let script = """
1682+ (() => {
1683+ const active = document.activeElement;
1684+ return {
1685+ readyState: String(document.readyState || " " ),
1686+ hasBody: !!document.body,
1687+ hasPrimary: !!document.getElementById( " cmux-ui-test-focus-input " ),
1688+ hasSecondary: !!document.getElementById( " cmux-ui-test-focus-input-secondary " ),
1689+ activeId: active && typeof active.id === " string " ? active.id : " "
1690+ };
1691+ })();
1692+ """
1693+
1694+ var lastDiagnostic = " nil "
1695+ let didMatch = waitForCondition ( timeout: timeout) {
1696+ guard let payload = self . browserEvalDict ( surfaceId: surfaceId, script: script) else {
1697+ lastDiagnostic = " nil "
1698+ return false
1699+ }
1700+ lastDiagnostic = String ( describing: payload)
1701+ return ( payload [ " readyState " ] as? String ) == " complete " &&
1702+ ( payload [ " hasBody " ] as? Bool ) == true &&
1703+ ( payload [ " hasPrimary " ] as? Bool ) == true &&
1704+ ( payload [ " hasSecondary " ] as? Bool ) == true
1705+ }
1706+ return ( ready: didMatch, diagnostic: lastDiagnostic)
1707+ }
1708+
16501709 private func waitForBrowserContentEditableSnapshot(
16511710 surfaceId: String ,
16521711 timeout: TimeInterval ,
@@ -1863,6 +1922,11 @@ final class BrowserPaneNavigationKeybindUITests: XCTestCase {
18631922 let clickOffsetY : Double
18641923 }
18651924
1925+ private struct BrowserContentEditableFixtureInstallResult {
1926+ let fixture : BrowserContentEditableFixture ?
1927+ let diagnostic : String
1928+ }
1929+
18661930 private struct BrowserContentEditableSnapshot {
18671931 let activeId : String
18681932 let downCount : Int
0 commit comments