digidem / digidem/comapeo-core-react-native
Sentry: integration test for native captureEventJson / captureEnvelopeBase64 round-trip
Nobody has claimed this yet.
- Dominant language
- Kotlin
- Stars
- 1
- Forks
- 0
- Avg merge
- 8h 24m
- Merged PRs (30d)
- 9
Description
Context
Phase 10 of the Sentry integration landed in #63: @sentry/node envelopes are forwarded to the native side via the control socket, deserialised, and captured through the native SDK so they ride sentry-android / sentry-cocoa's offline transport (plan-doc §5.7).
The PR added unit tests for:
envelopeToFramerouting (Node) — see backend/lib/sentry-frame.test.mjs.ControlFrame.parsefor the two new variants (Android + iOS) — see [ControlFrame test files].
What's NOT covered: the native-side happy-path capture — given a control-socket frame, that SentryFgsBridge.captureEventJson / SentryNativeBridge.captureEventJson actually deserialise the JSON into a SentryEvent AND that the resulting capture lands in the SDK's outbox. The current ControlFrame tests stop at "frame parsed into the right variant"; they don't link a real SDK or exercise the capture path.
Why it matters
Two failure modes that the current tests would miss:
- Deserialiser breakage. If sentry-android's
SentryEvent.Deserializeror sentry-cocoa'sSentryEventDecoderchange their input contract — accepted JSON shape, mandatory fields, encoding — our forwarding silently drops events. TheSentryEventDecoderSpiTestadded in #63 catches sentry-cocoa renaming/removing the symbol, but not changing what it accepts. - Wire-protocol drift. If
@sentry/node's event JSON shape changes (a new mandatory field, a renamed field) and the native decoder requires it, again silent drop.
A short integration test that produces a known-good event JSON via @sentry/node's actual serializer, hands it to the bridge's captureEventJson, and asserts the event ended up in the SDK's envelope cache would catch both.
Scope
Android
A JVM unit test (using Robolectric if needed for Android Context, or a fake Hub if not) that:
- Initialises a
sentry-androidSDK with a fake DSN and a transport stub that records every envelope handed to it. - Calls
SentryFgsBridgeImpl.captureEventJson(payloadJson)with a JSON event built either by hand or by calling@sentry/node's serializer in a sibling Node test and embedding the result as a fixture. - Asserts the transport stub received exactly one envelope, whose event item has the expected
event_id/exception.values[0].value/ level / tags.
iOS
An XCTest in the example app's test target (apps/example/tests/ios/) that:
- Initialises
sentry-cocoawith a stub transport (SentryHttpTransportreplacement viaSentryOptions.transport) that records envelopes. - Calls
SentryNativeBridge.captureEventJson(_:)with a known event JSON. - Asserts the stub received the envelope and the event item decoded correctly.
iOS additionally needs to verify captureEnvelopeBase64 because that path uses PrivateSentrySDKOnly.envelope(with:) + captureEnvelope: — different code path from the event decoder.
Optional: pair the test with a Node-side fixture generator
To keep the fixture honest (i.e. matches what @sentry/node actually emits), add a Node script (or extend backend/lib/sentry-frame.test.mjs) that:
- Initialises
@sentry/nodewith a stub transport that captures the envelope. - Calls
Sentry.captureException(new Error("...")). - Extracts the single event-item payload from the captured envelope.
- Writes it as a fixture file (
backend/test/fixtures/sentry-event-error.json) that both the Android and iOS tests load.
That way the native fixtures stay in sync with whatever shape @sentry/node is emitting.
Acceptance criteria
- Android:
gradle :comapeo-core-react-native:testDebugUnitTest(orandroidTestif Robolectric is overkill) includes a test that fails ifSentryFgsBridgeImpl.captureEventJsondoesn't produce a single envelope containing the expected event. - iOS: the example-app test target includes a test that fails if
SentryNativeBridge.captureEventJson(_:)doesn't produce a captured envelope. - Test fixtures should be derivable from
@sentry/node's actual output (not hand-rolled) so they catch upstream shape drift.
Related
- PR #63 — Phase 10 — offline transport via control-socket forwarding
docs/sentry-integration-plan.md§5.7apps/example/tests/ios/SentryEventDecoderSpiTest.swift— the SPI-symbol regression test landed alongside this PR; complementary to the integration test proposed here.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with backend/lib/sentry-frame.test.mjs and the bridge entry points SentryFgsBridgeImpl.captureEventJson, SentryNativeBridge.captureEventJson, and captureEnvelopeBase64. Review the existing apps/example/tests/ios/SentryEventDecoderSpiTest.swift and run the specified Gradle test command. Done means Android and iOS tests capture and validate one expected envelope, using fixtures derived from @sentry/node output.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, kotlin, swift
- Domain
- mobile-dev, observability, testing-qa
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100