Files
obsidian-vault/work/projects/macos-tests-worktrees-2026-10-14.md
T

7.2 KiB
Raw Blame History

title, date, tags, status
title date tags status
macOS tests: worktrees from the 2026-10-14 session 2026-10-14
ddg
macos
tests
worktrees
in-progress

macOS tests: worktrees from the 2026-10-14 session

All worktrees are in /Users/admin/DuckDuckGo/apple-browsers.git/<name>, on branch alex/<name>. Nothing is committed.

Summary

Worktree Created from Purpose Status
macos-unit-tests-no-app-delegate origin/main ca834f869a Unit tests no longer use the app delegate, buildable folder, test plans Done, not committed
fix-address-bar-tests-flakiness origin/main ddb1a82283 Fix flaky AddressBarTests: mocks plus two leak root causes Done, not committed
fix-ask-ai-chat-button-animation-leak origin/main e698211924 Ask AI Chat button animation leak plus regression test In progress
animation-leak-audit origin/main e698211924 Audit NSAnimationContext completion handlers for leaks Done: no leaks found; worktree and branch removed
fix-fire-window-video-leak origin/main e698211924 Video keeps playing after a Fire Window is closed: reproduce, fix, regression test In progress
spm-browser-tests (existing) — Source of the unit-test changes (SwiftPM variant) Not changed

macos-unit-tests-no-app-delegate

Branch alex/macos-unit-tests-no-app-delegate. 207 files changed, +5553/−7870 lines of uncommitted changes. Most of the deletions are pbxproj entries.

  • Ported from spm-browser-tests. Four commits (915209f987, d22aa6ca14, 966cad8578, 7f39ce3952) take the unit tests off the app delegate, move tests that build a main window to the integration tests, and skip disabled tests in code. The commit that turns the app into a Swift package was left out. Unit Tests stays an Xcode target.
  • macOS/UnitTests is a buildable folder (pbxproj objectVersion 70), with exceptions for the 12 files main never compiled.
    • DataImportResources is listed in explicitFolders.
    • privacy-reference-tests stays a folder reference.
  • Test plans: UnitTests/Unit Tests.xctestplan, TestPlans/macOS Browser.xctestplan, and TestPlans/macOS Browser App Store.xctestplan. They set language en/US, keep code coverage, and keep the App Store skip.
  • No app delegate in unit tests: for runType == .unitTests, Application.init creates neither AppDelegate nor the main menu, so any access to the delegate crashes.
    • Every place unit tests still reached the delegate was found with a trace and a default-argument scanner, then given a mock.
    • App code takes those dependencies as parameters that default to the app's values: AIChat omnibar, PermissionAuthorizationView, BookmarkManagementDetailViewController, BookmarksEmptyStateView, SyncDeviceButtonModel, NewTabPageCoordinator/ActionsManager, NewTabPageOmnibarActionsHandler, and others.
    • open(_ bookmark:) and open(_ historyEntry:) moved into the WindowControllersManagerProtocol extension.
    • BookmarksBarShownTriggerTests moved to the integration tests.
  • No network in unit tests: allowsUpdates is false for unit tests, so there is no Sparkle appcast check, and SuggestionContainerTests uses a URL session mock.
  • Results:
    • Unit: all pass except 10 snapshot tests, which require macOS 27 (this machine runs 26.7.1).
    • Full plan: 9484 passed. Besides the snapshot tests, 6 AddressBarTests fail; they also fail on origin/main and are fixed in the next worktree.
    • App Store scheme builds.
    • swiftlint --strict is clean on 315 files.
  • Note: the privacy-reference-tests submodule had to be initialized in this worktree.

fix-address-bar-tests-flakiness

Branch alex/fix-address-bar-tests-flakiness. 3 files, +100/−6.

  • Root cause: the tests didn't actually hang. In DEBUG, ensureObjectDeallocated(... .interrupt) sends SIGINT when an object is still alive. Two causes:
    1. TestRunHelper read NSApp.windows, which autoreleased the address bar's suggestions window. Fixed with autoreleasepool.
    2. The animateAskAIChatButtonContraction() completion handler captured self strongly. Fixed with [weak self]. The audit refined this finding: it isn't a permanent leak. While the display is asleep, the completion is held until it wakes.
  • Mocks and settings in AddressBarTests:
    • OHHTTPStubs answers duckduckgo.com/ac/ and blocks all other external network.
    • AI Chat settings are pinned in NSArgumentDomain.
    • The user's settings are saved and restored.
  • Results:
    • Isolated: 7 out of 7 runs with 0 failures and 0 restarts. Before the fix, origin/main had 1–6 failures per run.
    • Full Integration Tests ×2: 0 AddressBarTests failures.
    • The 3 remaining failures also fail on main because of this machine's settings: FireCoordinator (locale) and NTP search (aichat.enabled=0).
  • TODO: reword the comment in AddressBarButtonsViewController to say the handler is held until the animation ends, rather than "never called". The wording will match the fix in fix-ask-ai-chat-button-animation-leak.

fix-ask-ai-chat-button-animation-leak

Branch alex/fix-ask-ai-chat-button-animation-leak. In progress. Separate production fix for the Ask AI Chat button animation in AddressBarButtonsViewController ([weak self]), plus a regression test.

  • Revised requirement after the audit: the test must fail on main deterministically regardless of whether the display is asleep or awake. It asserts deallocation right after teardown, before the 0.2 s animation ends.

animation-leak-audit (removed)

Checked with standalone AppKit harnesses (in the session scratchpad: scratchpad/anim/exp*.swift). No permanent leaks were found, and the code was not changed. The worktree and branch were removed.

  • Key finding: AppKit does call runAnimationGroup completion handlers after the window is closed.
    • Animations of a view's alphaValue/frame, performBatchUpdates, and scroll always complete.
    • Display-link-driven animations (NSLayoutConstraint.animator().constant, NSWindow.animator().alphaValue) stall while the display is asleep. Their completion, along with any strong captures, is held until the display wakes.
    • This Mac has displaysleep 10, so its display is often asleep. That explains the flaky dealloc checks in tests.
  • Checked, no leaks found:
    • NavigationBarBadgeAnimator (alpha only, no view controller or window captured).
    • BrowserTabViewController.dismissCookiePopupProtectionOptInDialog (alpha only, self not captured).
    • AIChatCoordinator.transitionSidebar and TabBarViewController (weak captures, or completions that always run).
    • PromptBarPresenter.dismiss, CircularProgressView, SpinnerView, JSAlertController, and others.

fix-fire-window-video-leak

Branch alex/fix-fire-window-video-leak. In progress. Reproduce (with a test) the bug where video and audio keep playing after a Fire Window is closed, find the root cause, and fix it. The test must work whether the display is asleep or awake.

Temporary and source worktrees

  • spm-browser-tests (alex/spm-browser-tests) is the existing source of the unit-test changes. Not changed.
  • A detached origin/main baseline in the session scratchpad was used to compare integration tests and has been removed.