Skip to content

feat: Add double-open bug demonstration and fix toggle (EMT-2816)#14

Open
wpinho-branch wants to merge 19 commits intomainfrom
feature/double-open-sdk-test
Open

feat: Add double-open bug demonstration and fix toggle (EMT-2816)#14
wpinho-branch wants to merge 19 commits intomainfrom
feature/double-open-sdk-test

Conversation

@wpinho-branch
Copy link

Summary

This PR adds a demonstration and testing capability for the double-open bug fix (EMT-2816 / INTENG-21106) in scene-based iOS apps using Branch SDK.

The Bug

When a scene-based iOS app is cold-launched via a deep link, the OLD API pattern causes 2 OPEN requests to be sent instead of 1:

  • First OPEN from Branch.initSession(launchOptions: nil)
  • Second OPEN from scene(_:continue:) handling the Universal Link

The Fix

The NEW API (BranchScene.initSession(with: connectionOptions)) handles both initialization and deep link in a single call, sending only 1 OPEN request.

Changes

Core Implementation

  • SceneDelegate.swift: Implements toggle between OLD (buggy) and NEW (fixed) API modes
  • AppDelegate.swift: Enhanced logging and URLProtocol interceptor registration
  • BranchNetworkInterceptor.swift: Captures all Branch SDK network requests for debugging
  • RoundTripStore.swift: Improved OPEN request detection logic
  • HomeView.swift: UI section for EMT-2816 demo with toggle and request counter

App Architecture

  • BranchLinkSimulatorApp.swift: Changed to use UIApplicationMain to ensure SceneDelegate is properly invoked

E2E Tests

  • DoubleOpenBugUITests.swift: 15 UI tests covering toggle functionality, logs navigation, accessibility, and persistence

Test Plan

Prerequisites

  1. Build and run the app on iOS Simulator (iPhone 16 Pro recommended)
  2. Ensure the app is fully terminated before testing cold launch scenarios

Manual Testing: Reproducing the Bug (OLD API)

  1. Launch the app and scroll to "EMT-2816: Double-Open Test" section
  2. Disable the toggle "Use EMT-2816 Fix" (toggle OFF)
  3. Tap "Clear All Logs" to reset the counter
  4. Terminate the app completely (swipe up from app switcher)
  5. Cold launch via Universal Link:
    xcrun simctl openurl booted "https://branchlinksimulator.app.link/test"
  6. Expected Result:
    • OPEN Request counter shows 2 (RED)
    • "DOUBLE-OPEN BUG DETECTED!" warning appears

Manual Testing: Verifying the Fix (NEW API)

  1. Launch the app and scroll to "EMT-2816: Double-Open Test" section
  2. Enable the toggle "Use EMT-2816 Fix" (toggle ON)
  3. Tap "Clear All Logs" to reset the counter
  4. Terminate the app completely (swipe up from app switcher)
  5. Cold launch via Universal Link:
    xcrun simctl openurl booted "https://branchlinksimulator.app.link/test"
  6. Expected Result:
    • OPEN Request counter shows 1 (GREEN)
    • "Single OPEN - Working correctly!" message appears

Running E2E Tests

xcodebuild test \
  -project BranchLinkSimulator.xcodeproj \
  -scheme BranchLinkSimulatorUITests \
  -destination "platform=iOS Simulator,name=iPhone 16 Pro" \
  -only-testing:BranchLinkSimulatorUITests/DoubleOpenBugUITests

Expected: All 15 tests pass

Test Cases Covered

Test Description
testToggleExists Verify toggle is present in UI
testToggleFunctionality Toggle changes state correctly
testAPIModePersisters Toggle state persists across app restarts
testModeDescriptionUpdates API description text updates with toggle
testStatusIndicatorStates Status indicator reflects toggle state
testOpenRequestCounterVisible OPEN counter is visible
testViewLogsNavigation Navigate to logs screen
testLogsScreenTabs Logs screen has correct tabs
testClearLogs Clear logs button works
testAllSectionsVisible All UI sections render correctly
testAccessibilityElements Accessibility identifiers are set
testAppLaunchPerformance App launch performance baseline
testNavigateToLogsPerformance Navigation performance baseline
testNewAPIColdLaunchDocumentation Documents NEW API behavior
testOldAPIColdLaunchDocumentation Documents OLD API behavior

API Comparison

Aspect OLD API (Bug) NEW API (Fix)
Method Branch.initSession(launchOptions: nil) BranchScene.initSession(with: connectionOptions)
OPEN Requests 2 1
Deep Link Handling Separate in scene(_:continue:) Unified in single call

Related

  • JIRA: EMT-2816, INTENG-21106
  • Branch SDK Version: 3.9.1 (without deduplication)

Update SDK dependency to use fix/EMT-2816-double-open-issue branch
for testing the double-open prevention solution.

Changes:
- Point SPM to fix/EMT-2816-double-open-issue branch
- Update Package.resolved with new revision
- Fix .gitignore merge conflict (enable xcodeproj tracking)
Implement testing UI for the double-open SDK fix:

- Add SceneDelegate with toggle between old/new Branch init APIs
- Add toggle in HomeView to switch between APIs (requires app restart)
- Add OPEN request counter to track /v1/open and /v2/event(open) calls
- Add LogsView with Timeline and OPEN Requests tabs for log visualization
- Update RoundTrip model with isOpenRequest tracking
- Update RoundTripStore with log entries and OPEN detection
- Update Info.plist with UIApplicationSceneManifest configuration
- Update BranchLinkSimulatorApp.swift for Scene lifecycle

The toggle allows comparing behavior:
- OLD API: Branch.initSession(launchOptions:) - may cause double OPEN
- NEW API: BranchScene.initSession(with:) - prevents double OPEN

Expected results when testing:
- With OLD API: 2 OPEN requests on cold launch via deep link
- With NEW API: 1 OPEN request on cold launch via deep link
Add more detailed logs with visual separators to make it clear:
- When COLD LAUNCH happens (app was killed)
- When WARM LAUNCH happens (app was in background)
- Which API is being used (OLD vs NEW)
- What is expected (1 vs 2 OPEN requests)
- Branch callback results
Changes:
- OLD API now uses Branch.handleDeepLink() instead of BranchScene methods
- Cold launch with OLD API processes URL from connectionOptions manually,
  triggering a second OPEN request (demonstrating the bug)
- NEW API skips manual URL processing since BranchScene.initSession
  already handles the URL internally (demonstrating the fix)

Expected behavior:
- OLD API (toggle OFF): 2 OPEN requests on cold launch via deep link
- NEW API (toggle ON): 1 OPEN request on cold launch via deep link
Changes:
- OLD API now uses Branch.application(_:open:options:) for URL schemes
  (the actual AppDelegate method that would cause double-open)
- OLD API now uses Branch.continue(userActivity) for Universal Links
- Clear step-by-step logging showing:
  - Step 1: initSession(launchOptions: nil) → OPEN #1
  - Step 2: application(_:open:) → OPEN #2 (bug)
- NEW API uses BranchScene.initSession(with:) which handles
  everything in a single OPEN request
Create basic Info.plist configuration for the BranchLinkSimulatorUITests
target with standard bundle settings.
Add comprehensive UI test suite for verifying the double-open bug fix
in scene-based iOS apps with Branch SDK.

Test coverage:
- testToggleExists: Verify toggle accessibility identifier
- testToggleFunctionality: Test toggle state changes
- testModeDescriptionUpdates: Verify API mode description updates
- testViewLogsNavigation: Test navigation to logs screen
- testLogsScreenTabs: Verify segmented picker tabs
- testOpenRequestCounterVisible: Check OPEN request counter visibility
- testClearLogs: Test clear logs functionality
- testAllSectionsVisible: Verify main sections render
- testAPIModePersisters: Test toggle persistence across restarts
- testAccessibilityElements: Verify UI accessibility
- testStatusIndicatorStates: Test status indicator text
- testOldAPIColdLaunchDocumentation: Document OLD API behavior
- testNewAPIColdLaunchDocumentation: Document NEW API behavior
- testAppLaunchPerformance: Measure app launch time
- testNavigateToLogsPerformance: Measure logs navigation

Key implementation details:
- Uses coordinate-based tap (dx: 0.9, dy: 0.5) for reliable SwiftUI toggle
- Handles both IDFA permission and Branch SDK error alerts
- Properly detects SwiftUI SegmentedPickerStyle via segmentedControls
- Flexible element detection with multiple fallback checks
Configure BranchLinkSimulatorUITests target in Xcode project:
- Add PBXContainerItemProxy for test dependency
- Add file references for test sources and Info.plist
- Configure build phases (Sources, Frameworks, Resources)
- Add target dependency on BranchLinkSimulator app
- Configure test host and bundle identifier settings
- Add case-insensitive matching for URL and body patterns
- Detect BranchOpenRequest from SDK log messages
- Handle api.branch.io URLs with open in either URL or body
- Improves reliability of double-open bug detection
…h requests

- Intercept all Branch SDK network requests via URLProtocol
- Capture and log OPEN requests to RoundTripStore
- Track request/response details for debugging
- Support all Branch API domains (api.branch.io, api2.branch.io, etc.)
- Register BranchNetworkInterceptor to capture all Branch requests
- Parse SDK log messages to detect OPEN requests
- Log OPEN request detections to RoundTripStore
- Ensure SceneDelegate is used via explicit delegateClass
- Add NEW API mode: BranchScene.initSession(with: connectionOptions)
  Sends only 1 OPEN request (EMT-2816 fix)
- Add OLD API mode: Branch.initSession(launchOptions: nil)
  Demonstrates the double-open bug (2 OPEN requests)
- Add debug logging to file for cold launch analysis
- Log connectionOptions.urlContexts and userActivities
- Support toggle via @AppStorage("useDoubleOpenFix")
…gate

- Replace SwiftUI @main with UIApplicationMain
- Ensure SceneDelegate is properly invoked for window/scene management
- Required for proper Branch SDK integration with connectionOptions
- Rename section to "EMT-2816: Double-Open Test"
- Add accessibility identifiers for E2E testing
- Display API mode descriptions (NEW/OLD API)
- Add status indicators (fix enabled vs bug mode)
- Show visual feedback for double-open bug detection
- Add clear logs button for testing workflow
- Package resolution managed by SPM, no need to track
- BranchLinkSimulator.xcscheme - Main app scheme
- BranchLinkSimulatorTests.xcscheme - Unit tests scheme
- BranchLinkSimulatorUITests.xcscheme - UI tests scheme for E2E testing
- Automated test script for EMT-2816 / INTENG-21106
- Tests both OLD API (bug) and NEW API (fix) scenarios
- Cold launch via Universal Link simulation
- Validates OPEN request count for each API mode
- Package.resolved with Branch SDK dependency
- Points to fix/EMT-2816-double-open-issue_without-fix branch
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