From 21d65f6b9120a76f8c16f0dfc5bde16b0e48cb63 Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Tue, 16 Jun 2026 12:57:54 +0300 Subject: [PATCH] test(cloudflare): Add mTLS instrumentation test --- .../instrumentations/instrumentEnv.test.ts | 58 +++++++++++++++++-- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/packages/cloudflare/test/instrumentations/instrumentEnv.test.ts b/packages/cloudflare/test/instrumentations/instrumentEnv.test.ts index a324cb1e3678..296ac2e8f797 100644 --- a/packages/cloudflare/test/instrumentations/instrumentEnv.test.ts +++ b/packages/cloudflare/test/instrumentations/instrumentEnv.test.ts @@ -216,6 +216,56 @@ describe('instrumentEnv', () => { expect(instrumentDurableObjectNamespace).toHaveBeenCalledWith(doNamespace); }); + describe('mTLS Fetcher bindings', () => { + function createMtlsFetcherProxy(mockFetch: ReturnType) { + return new Proxy( + { fetch: mockFetch }, + { + get(target, prop) { + if (prop in target) { + return Reflect.get(target, prop); + } + return () => {}; + }, + }, + ); + } + + it('does not instrument mTLS Fetcher when enableRpcTracePropagation is disabled', () => { + const mockFetch = vi.fn(); + const mtlsFetcher = createMtlsFetcherProxy(mockFetch); + const env = { MY_CERT: mtlsFetcher }; + const instrumented = instrumentEnv(env); + + expect(instrumented.MY_CERT).toBe(mtlsFetcher); + }); + + it('preserves existing headers and response on mTLS Fetcher fetch', async () => { + vi.spyOn(SentryCore, '_INTERNAL_getTracingHeadersForFetchRequest').mockReturnValue({ + Authorization: 'Bearer client-cert-token', + 'sentry-trace': '12345678901234567890123456789012-1234567890123456-1', + baggage: 'sentry-environment=production', + }); + + const mockFetch = vi.fn().mockResolvedValue(new Response('mtls-response')); + const mtlsFetcher = createMtlsFetcherProxy(mockFetch); + const env = { MY_CERT: mtlsFetcher }; + const instrumented = instrumentEnv(env, { enableRpcTracePropagation: true }); + + const response = await instrumented.MY_CERT.fetch('https://example.com/api', { + headers: { Authorization: 'Bearer client-cert-token' }, + }); + + const [, init] = mockFetch.mock.calls[0]!; + const headers = new Headers(init?.headers); + + expect(instrumented.MY_CERT).not.toBe(mtlsFetcher); + expect(headers.get('Authorization')).toBe('Bearer client-cert-token'); + expect(headers.get('sentry-trace')).toBe('12345678901234567890123456789012-1234567890123456-1'); + expect(await response.text()).toBe('mtls-response'); + }); + }); + describe('JSRPC RPC method instrumentation', () => { it('does not inject Sentry RPC meta by default (enableRpcTracePropagation not set)', () => { vi.spyOn(SentryCore, 'getTraceData').mockReturnValue({ @@ -238,7 +288,7 @@ describe('instrumentEnv', () => { const env = { SERVICE: jsrpcProxy }; const instrumented = instrumentEnv(env); - (instrumented.SERVICE as any).myRpcMethod('arg1', 42); + instrumented.SERVICE.myRpcMethod('arg1', 42); // Without enableRpcTracePropagation, no metadata should be injected expect(rpcMethod).toHaveBeenCalledWith('arg1', 42); @@ -265,7 +315,7 @@ describe('instrumentEnv', () => { const env = { SERVICE: jsrpcProxy }; const instrumented = instrumentEnv(env, { enableRpcTracePropagation: true }); - (instrumented.SERVICE as any).myRpcMethod('arg1', 42); + instrumented.SERVICE.myRpcMethod('arg1', 42); expect(rpcMethod).toHaveBeenCalledWith('arg1', 42, { __sentry_rpc_meta__: { @@ -296,7 +346,7 @@ describe('instrumentEnv', () => { const env = { SERVICE: jsrpcProxy }; const instrumented = instrumentEnv(env, { enableRpcTracePropagation: true }); - (instrumented.SERVICE as any).fetch('https://example.com'); + instrumented.SERVICE.fetch('https://example.com'); // fetch should use HTTP header injection, not trailing arg const callArgs = mockFetch.mock.calls[0]; @@ -321,7 +371,7 @@ describe('instrumentEnv', () => { const env = { SERVICE: jsrpcProxy }; const instrumented = instrumentEnv(env, { enableRpcTracePropagation: true }); - (instrumented.SERVICE as any).myRpcMethod('arg1'); + instrumented.SERVICE.myRpcMethod('arg1'); expect(rpcMethod).toHaveBeenCalledWith('arg1'); });