--- title: 'macOS tests: worktrees from the 2026-10-14 session' date: '2026-10-14' tags: - ddg - macos - tests - worktrees status: in-progress --- # macOS tests: worktrees from the 2026-10-14 session All worktrees are in `/Users/admin/DuckDuckGo/apple-browsers.git/`, on branch `alex/`. 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.