Skip to content

[SDK-822] Stop reporting every switchProject as noisy when no user is identified yet - #1095

Merged
joaodordio merged 2 commits into
feature/SDK-674-switch-projectfrom
feature/SDK-822-no-user-clean-start
Nov 6, 2026
Merged

joaodordio merged 2 commits into
feature/SDK-674-switch-projectfrom
feature/SDK-822-no-user-clean-start

Conversation

@joaodordio

@joaodordio joaodordio commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

📝 Summary

A real switchProject always reported .switchedWithWarnings and logged an error, because the new project's first in-app sync runs before the app has re-identified the user.

🎟️ Jira Ticket: SDK-822

📖 Description

ATG hit this while testing a pre-release build and asked whether the warning needed fixing before go-live (Slack). Nothing was broken, but .switchedCleanly was unreachable after a real switch.

Cause. The switch clears the previous user, then starts the new project. start() returns inAppManager.start(), whose first sync goes through RequestCreator.createGetInAppMessagesRequest, which refuses the request while auth.emailOrUserId is .none. initialize2 turns that refusal into started == false, and the switch folded it into the result. The app's setEmail from the callback schedules the sync again, so nothing is lost.

Fix. startCountsAsClean counts a failed start as clean when no identity is set, and logs at info instead of error. It checks auth, not noUserLoggedIn(): the unknown-user ID also lets the request through, so with it set a failed sync is a genuine failure and still reports warnings and logs an error. The start is evaluated before teardownWasClean &&, so a genuine failure is still logged when the teardown was noisy too.

Two commits, reviewable separately:

  1. dfdd53a2 The post-switch path. This is the ticket scope and the log line ATG saw.
  2. 4f35ad8c The pre-init path (switch before any initialize). Since SDK-758 it forwards the same start result, so a fresh install reported warnings on iOS while Android reports SWITCHED_CLEANLY, because Android's failure signal is an initialization that times out or throws and a missing user is neither. This narrows what SDK-758 locked in, so it is its own commit and can be dropped. SDK-758's existing failure test still passes: a start that fails with someone identified still warns.

Why the tests missed it. MockDependencyContainer.createInAppFetcher returns a MockInAppFetcher that succeeds without a user, so the real request creation never ran. The new tests subclass it to build the real InAppFetcher. FailingInAppFetcher now sets an unknown-user identity before failing, so it keeps modelling a genuine failure rather than the expected refusal.

🧪 How to test?

  • SwitchProjectGateTests.testASwitchWithNoUserYetOnTheNewProjectReportsCleanly: real fetch path, asserts the result is clean, that no in-app request goes out before identification, and that after setEmail from the callback the sync goes to project B with B's key. Fails without commit 1, on the result assertion only.
  • SwitchProjectGateTests.testSwitchProjectBeforeInitializeWithNoUserYetReportsCleanly: fresh-install pre-init switch on the real fetch path. Fails without commit 2.
  • Existing failing-start tests (post-switch and SDK-758's pre-init one) still report warnings.
  • Full suite: unit-tests 739, notification-extension-tests 15, offline-events-tests 103, 0 failures.

Local note: on Xcode 27.2 this repo only runs with IPHONEOS_DEPLOYMENT_TARGET=15.0 passed to xcodebuild and on a pre-iOS-27 simulator (I used iOS 18.5), because Xcode 27 rejects the 12.0 target and the iOS 27 runtime refuses to launch the test host app without UIScene adoption. CI is pinned to an older Xcode so it is unaffected for now. Not changed here.

Manual: on a device, switch from an identified user on A to B and re-identify from the callback. The result should be .switchedCleanly, with no did not start cleanly error, and in-apps should load for B after setEmail.

🧾 Changelog

Updated under [Unreleased]. The warning-cause list in the switchProject entry gains the real fifth cause, says that nobody identified yet on the new project is not a warning, explains the expected Both email and userId are nil log line, and notes that a simulator has no APNs token. A new Fixed entry covers this change. The pre-init Added bullet, left stale by SDK-758, and the SDK-758 Fixed entry now describe the actual behaviour.

📹 Loom recording if applicable

Not recorded.

🐞 Github Issues solved

None.

📚 Docs PR if applicable

switchProject docs are tracked in SDK-676. The result contract described there should match the corrected CHANGELOG wording.

…fied yet

Every switchProject done the documented way logged "the new project's SDK did
not start cleanly" at error level and reported .switchedWithWarnings, so
.switchedCleanly was unreachable after a real switch. ATG hit this while
testing and asked whether it needed fixing before go-live.

The switch clears the previous user, then starts the new project, and start()
runs the first in-app sync before the app can re-identify from the callback.
RequestCreator refuses that request while no identity is set, initialize2
turns the refusal into started == false, and the switch folded it into the
result. Nothing was wrong: setEmail from the callback schedules the sync again.

A failed start now counts as clean when auth.emailOrUserId is .none, and logs
at info. The check goes through auth rather than noUserLoggedIn() because the
unknown-user ID also lets the request through, so with it set a failed sync is
a genuine failure and still reports warnings and logs an error. The start is
evaluated before the teardown result so a genuine failure is logged even when
the teardown was noisy too.

The existing tests missed it because MockDependencyContainer hands out a
MockInAppFetcher that succeeds without a user. The new test builds the real
InAppFetcher, and fails without the fix. FailingInAppFetcher now sets an
unknown-user identity before failing, so it keeps modelling a genuine failure.

CHANGELOG: the warning-cause list gains the real fifth cause, says that nobody
identified yet on the new project is not a warning, explains the expected
"Both email and userId are nil" log line, and notes that a simulator has no
APNs token.
The pre-init path forwards the start result since SDK-758, so on a fresh install
switchProject reported .switchedWithWarnings for the same reason the post-switch
path did: nobody is identified yet, so the first in-app sync is refused and
start() fails. Android reports SWITCHED_CLEANLY in the same situation, because
its failure signal is an initialization that times out or throws, and a missing
user is neither. SDK-758's parity therefore broke in the case most apps hit first.

The pre-init callback now goes through the same startCountsAsClean rule. A start
that fails with someone identified, for example a returning user whose sync fails,
still reports warnings, which is what SDK-758's existing failure test asserts and
still passes. The new test drives a fresh-install pre-init switch through the real
InAppFetcher and fails without this change.

Kept as its own commit because it narrows behaviour SDK-758 locked in during
review, so it can be reviewed or dropped separately.

CHANGELOG: the Added bullet for pre-init still said it always reported cleanly,
which SDK-758 left stale; both it and the SDK-758 Fixed entry now describe the
actual behaviour.
@joaodordio
joaodordio requested a review from a team as a code owner November 5, 2026 18:37
@codecov

codecov Bot commented Nov 5, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 75.23%. Comparing base (6cfaf84) to head (4f35ad8).

Additional details and impacted files
@@                        Coverage Diff                         @@
##           feature/SDK-674-switch-project    #1095      +/-   ##
==================================================================
+ Coverage                           75.03%   75.23%   +0.20%     
==================================================================
  Files                                 118      118              
  Lines                               10634    10642       +8     
==================================================================
+ Hits                                 7979     8007      +28     
+ Misses                               2655     2635      -20     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@joaodordio
joaodordio merged commit 9e719dc into feature/SDK-674-switch-project Nov 6, 2026
13 checks passed
@joaodordio
joaodordio deleted the feature/SDK-822-no-user-clean-start branch November 6, 2026 10:07
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