Skip to content

fix: the failing Docs, iOS and macOS UI tests on main - #2992

Open
datlechin wants to merge 5 commits into
mainfrom
fix/failing-tests-on-main
Open

datlechin wants to merge 5 commits into
mainfrom
fix/failing-tests-on-main

Conversation

@datlechin

@datlechin datlechin commented Sep 18, 2026

Copy link
Copy Markdown
Member

Fixes the failures behind every red Docs, iOS Tests and macOS Tests run on main. Each one has a root cause below. None of them is a timeout bump or a quarantine.

Docs: check-links.py rejects a valid anchor

features/sql-editor.mdx links to /databases/oracle#pl%2Fsql (#2988). mint broken-links --check-anchors accepts it, but check-links.py failed it because the script made up its own slugs: every run of non-alphanumerics became -, so it expected pl-sql. Mintlify does something else. It percent-encodes the title, keeps the escapes, and compares both sides after cleanHeadingId. So "PL/SQL" becomes pl/sql, and #pl%2Fsql matches it.

The script now uses Mintlify's own rules (slugify and cleanHeadingId from @mintlify/common 4.2.816, the version CI pins), deduplication suffixes included. It checked out both ways:

  • Mintlify's own checker accepts all 1,257 anchors the script computes for the current docs.
  • On a set of probe links, both checkers flag the same three bad ones (#pl-sql, #plsql, #ssl-tls) and accept the same six good ones.

verify.sh docs never ran this script, so the broken link passed a local check. It runs now.

iOS: the test host traps before the first test

Every iOS Tests run since #2980 dies with "Test crashed with signal trap before establishing connection". The crash report in the result bundle shows the path:

  • ConnectionListView's .task(id: isSyncEnabled) runs.
  • It calls IOSSyncCoordinator.accountStatus(), which builds a CloudKitSyncEngine.
  • That builds a CKContainer, and CloudKit traps: "your process must have a com.apple.developer.icloud-services entitlement".

CI builds the host with CODE_SIGNING_ALLOWED=NO, so it has no entitlements. The engine already handles that case: hasICloudEntitlement() lets it skip the container. But the check read SecTask on macOS and returned true on every other platform. #2980 was the first change to reach CloudKit at launch while sync is off.

CloudKitEntitlement now answers the question on each platform:

  • macOS: SecTask, as before.
  • Simulator: reads the __TEXT,__entitlements section Xcode embeds in the main executable when it signs a simulator build. An unsigned build has no section.
  • Device: stays true, because an iOS app cannot launch without the signature that carries its entitlements.

A service only counts when it is CloudKit or CloudKit-Anonymous, which is CloudKit's own rule.

iOS: tests the crash had been hiding

Both came in with #2986, after the host had already stopped launching, so neither had ever run on CI. The first CI run of this PR got past the launch. It then lost BottomSafeAreaBarLayoutTests/barClearsTheTabBar() to its one-minute limit, and the timeout took the host down, so 284 later tests never ran.

  • barClearsTheTabBar waited for a layout change with no bound. If the final layout never met its condition, it waited until the time limit. It passes on iOS 26.5 and iOS 27 simulators built with the Xcode 27 SDK. CI builds with Xcode 26.4.1, which I cannot reproduce locally. The wait now gives up after 10 quiet seconds and fails with the measured geometry: the list inset, the tab bar band and the marker frame. If it still fails on CI, the message says whether the bar really sits under the tab bar there.

  • sealingLeavesMainActorFree spun on Task.yield() until the sealing task had started, and Task.yield promises nothing about ordering. In one full local run on iOS 26.5 the check ran after sealing had already finished. The sealing task now signals through an AsyncStream the moment it starts. That puts the test's continuation on the main queue before sealing can resume, whatever the load. Negative control: with ConnectionExportCrypto.encrypt changed from @concurrent to @MainActor, the test fails. With @concurrent it passes.

  • The same Task.yield() spin in three more places: the second CI run lost ScenePresenterTests/releasedEditorLetsGo() to the one-minute limit. That test spins on Task.yield() on the main actor, waiting for a @MainActor task that SceneEditorHold.deinit starts. QueryEditorViewModelTests (two cases) and QueryActivityControllerTests spin the same way. All four now wait on the event itself:

    • ObservedCondition.wait(until:) suspends on withObservationTracking until the @Observable model changes.
    • The live activity spy resumes a waiter when its end parks.

    Nothing in TableProMobileTests spins on Task.yield() any more.

macOS UI: two causes behind every intermittent failure

Even the green run 35375539350 only passed because retries covered five first-attempt failures. All of them come from the two causes below.

"The sample database never finished opening" hit a different test on nearly every run.

  • XCTest evaluates a query inside the app, on its main thread.
  • The sample opens Track, and its 1,000 rows usually reach the grid before the table list reaches the sidebar.
  • While the sidebar was still a spinner, the readiness query searched from the window for an outline and walked the whole grid, about 12,000 elements. That took 3.6 to 5.6s per check, followed by a 50ms pause.
  • The app got about 0.4s of main thread every five seconds, so the table-list load took 25 to 107s instead of 1 to 10s.

The element trees from the failing runs all show the sidebar spinning and "Rows 1-1,000" in the grid. The comment that blamed runner contention for the 90s timeout was wrong: each shard runs on its own macos-26 VM. Two changes:

  • The wait reaches the object browser through direct children only (objectBrowser(in:)), so a miss costs a few dozen elements.
  • UITestPoll now pauses for at least as long as the check that missed took, so no query can take more than half the app's main thread. This covers every other wait in the suite too.

The timeout goes back to 30s.

NavigationHistoryUITests.testForwardReturnsToTheTableBackSteppedAwayFrom failed both attempts in two of the last four runs.

  • The View menu is 878pt tall. On the runner's 1024x768 screen it gets 671pt, so it scrolls, and Forward sits under the bottom scroll zone.
  • The recorded mouse events show XCUITest hovering Forward at (335,690), which scrolls the menu, then clicking at (335,618), where the disabled Show Previous Connection had moved.
  • Nothing failed at that point. The menu stayed open and Forward never ran.

The test still waits for the item to validate as enabled in the open View menu. It then closes the menu and sends the item's key equivalent (⌃⌘[ or ⌃⌘]), which goes through NSMenu.performKeyEquivalent and needs no screen position.

Verification

  • TableProMobileTests, unsigned, on the iPhone 18 Pro simulator:
    • On main it crashes the same way CI does (CloudKitSyncEngine.swift:41).
    • With this branch: 636 passed, 0 failed, 27 skipped, on iOS 27.0 and on iOS 26.5 (the runtime CI uses).
  • Simulator launch check:
    • Signed build: creates the container, no warning.
    • Unsigned build: logs "iCloud entitlement missing: CloudKit sync disabled" and keeps running.
  • TableProSyncTests: 129 pass, including the 6 new CloudKitEntitlementTests.
  • verify.sh docs: PASS. check-links.py gives the same verdict as mint broken-links on every anchor, as above.
  • UI tests: the target builds. They could not run locally because the Mac was locked ("Timed out while enabling automation mode"), so this PR's macOS Tests run is their verification.
  • swiftlint lint --strict on the changed Swift files: clean. UITestCase.swift has two existing storage_environment_defaults findings on lines this PR does not touch.

Not addressed

The View menu scrolls on a 768pt-tall screen. A Go menu for Back and Forward, as Finder, Safari and Xcode have, or a submenu for the four result-tab commands, would shorten it. That is a product change and is not part of this PR.

No CHANGELOG entry: a signed app behaves the same as before. Only unsigned simulator builds, the docs checker and the tests change.

@mintlify

mintlify Bot commented Sep 18, 2026

Copy link
Copy Markdown

Preview deployment for your docs. Learn more about Mintlify Previews.

Project Status Preview Updated
TablePro 🟢 Ready View Preview Sep 18, 2026, 8:09 PM

💡 Tip: Enable Automations to automatically generate PRs for you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant