Skip to content

EMBR-12558 feat: roll over session part on soft navigation#1398

Merged
joaquin-diaz merged 7 commits into
mainfrom
joaquin-diaz/feat/EMBR-12558-session-part-soft-nav
Jul 2, 2026
Merged

EMBR-12558 feat: roll over session part on soft navigation#1398
joaquin-diaz merged 7 commits into
mainfrom
joaquin-diaz/feat/EMBR-12558-session-part-soft-nav

Conversation

@joaquin-diaz

@joaquin-diaz joaquin-diaz commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

What problem is this solving?

SPA soft navigations (React Router link clicks, browser back/forward) were not triggering session part rollovers. The Navigation API's currententrychange event is the right hook but was unwired.

Short description of changes

  • Wire _rolloverSessionPart to navigation.currententrychange via a new onSoftNavigation activity listener in activity.ts
  • Add Navigation and SoftNavigationEvent interfaces in common/types.ts to type the Navigation API without casting; NavigationHost now types navigation as Navigation instead of EventTarget
  • Add location: { href: string } to NavigationHost so the handler can detect same-URL replacements without accessing window.location directly
  • Skip rollover when event.from.url === navigationHost.location.href to avoid spurious rollovers from framework hydration (e.g. Next.js App Router fires currententrychange via history.replaceState during hydration with the same URL)
  • Add navigationHost?: NavigationHost to EmbraceUserSessionManagerArgs; defaults to window
  • Add 5 unit tests covering: rollover on soft-nav, no-op when no active part, listener cleanup on shutdown, graceful handling of absent Navigation API, no-op on same-URL navigation
  • Increase bundle size limit from 55 to 56 KB
  • Restructure integration test ReceivedSpans from Record<string, boolean> to Record<string, Record<string, { endReason }>>, keyed by session part ID — enables server-side count validation
  • Consolidate validateThatSessionPartEnded / validateThatSessionPartsEnded into a single validateThatSessionPartsEnded(expectedCount = 1, userSessionId?) that polls /received-spans for accuracy
  • Remove test.skip from all three Vite React Router SPA navigation e2e tests

How has this been tested?

  • Unit tests: all 27 tests in EmbraceSessionPartActivity.test.ts pass (22 existing + 5 new)
  • Integration tests: SPA navigation e2e tests in vite-react-router-tests.spec.ts are unskipped and exercise forward links, browser back, and browser forward scenarios; Next.js integration tests all pass (same-URL skip fix prevents spurious rollovers during hydration)

Checklist

  • Tests added
  • Documentation added

@github-actions

github-actions Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor
Chrome DevTools Protocol Tracing (Script: 120.63ms, Heap: 13.01MB)
Number of Requests Size of Requests Script Duration Task Duration Heap Used Size
Requests +4 requests +33.74 KB
Page Loaded +23.91 ms +21.28 ms +1.17 MB
Generate 100 fetch requests +21.19 ms +84.32 ms +1.69 MB
Generate 100 XHR requests +42.61 ms +112.75 ms +2.83 MB
Click 100 buttons and generate 100 logs +23.38 ms +43.50 ms +2.14 MB
Throw a 100 exceptions +0.03 ms +24.16 ms +3.21 MB
End Session +9.51 ms +25.27 ms +1.96 MB
Total +4 requests +33.74 KB +120.63 ms +311.28 ms +13.01 MB
Lighthouse (Script Eval: 123.86ms)
Difference Description
Total Blocking Time +1 ms Difference in Total Blocking Time: Sum of all time periods between FCP and Time to Interactive, when task length exceeded 50ms, expressed in milliseconds. Learn more about the Total Blocking Time metric.
Main Thread Time +95.35 ms Difference in Main Thread Time: Consider reducing the time spent parsing, compiling and executing JS. You may find delivering smaller JS payloads helps with this. Learn how to minimize main-thread work
Script Evaluation Time +123.86 ms Difference in Script Evaluation Time: Consider reducing the time spent parsing, compiling, and executing JS. You may find delivering smaller JS payloads helps with this. Learn how to reduce Javascript execution time.
Platform Tests (vite-7 es2015 gzip: 68.46KB)

vite-6 Platform Tests

Total Uncompressed Size Total Gzip Size
vite-6 - es2015 +198.80 KB +68.50 KB

vite-7 Platform Tests

Total Uncompressed Size Total Gzip Size
vite-7 - es2015 +198.80 KB +68.46 KB

webpack-5 Platform Tests

Total Uncompressed Size Total Gzip Size
webpack-5 - es2015 0 KB 0 KB

@codecov

codecov Bot commented Jun 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.64%. Comparing base (e004016) to head (d3341b0).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #1398      +/-   ##
==========================================
+ Coverage   96.41%   96.64%   +0.23%     
==========================================
  Files         230      230              
  Lines        9718     9759      +41     
  Branches     1353     1360       +7     
==========================================
+ Hits         9370     9432      +62     
+ Misses        346      325      -21     
  Partials        2        2              
Files with missing lines Coverage Δ
packages/web-sdk/src/common/index.ts 100.00% <100.00%> (ø)
...aceUserSessionManager/EmbraceUserSessionManager.ts 95.08% <100.00%> (+2.09%) ⬆️
...nagers/EmbraceUserSessionManager/utils/activity.ts 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread packages/web-sdk/src/common/types.ts Outdated
Comment thread server/server.ts Outdated
Comment thread tests/integration/types.ts Outdated

@overbalance overbalance left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend expanding the reason value. Otherwise looks great!

@joaquin-diaz
joaquin-diaz force-pushed the joaquin-diaz/feat/EMBR-12558-session-part-soft-nav branch from 214cd1d to d3341b0 Compare July 2, 2026 14:55
@joaquin-diaz
joaquin-diaz merged commit 1ac4df0 into main Jul 2, 2026
20 checks passed
@joaquin-diaz
joaquin-diaz deleted the joaquin-diaz/feat/EMBR-12558-session-part-soft-nav branch July 2, 2026 15:02
private readonly _onSoftNavigation = (
event: NavigationCurrentEntryChangeEvent,
): void => {
// Skip same-URL replacements (e.g. framework hydration via history.replaceState).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't we also need to ignore fragment and query string changes here?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

event.from.url and this._navigationHost.location.href include the entire query string so navigating to the same URL (including qs) would be ignored

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants