Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions packages/bun/test/integrations/bunHttpServer.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import http from 'node:http';
import { getActiveSpan, getTraceData, spanToJSON } from '@sentry/core';
import { beforeAll, describe, expect, test } from 'bun:test';
import { getActiveSpan, getCurrentScope, getTraceData, spanToJSON } from '@sentry/core';
import { afterAll, beforeAll, describe, expect, test } from 'bun:test';
import { init } from '../../src';

async function startServer(handler: http.RequestListener): Promise<{ port: number; close: () => Promise<void> }> {
Expand Down Expand Up @@ -32,6 +32,10 @@ describe('Bun HTTP Server Integration', () => {
});
});

afterAll(() => {
getCurrentScope().setClient(undefined);
});

test('creates an http.server span for incoming requests', async () => {
let span: ReturnType<typeof spanToJSON> | undefined;

Expand Down
43 changes: 22 additions & 21 deletions packages/bun/test/integrations/bunserver.test.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
import * as SentryCore from '@sentry/core';
import { afterEach, beforeAll, beforeEach, describe, expect, spyOn, test } from 'bun:test';
import { init } from '../../src';
import type { BunOptions } from '../../src';
import { getDefaultIntegrationsWithoutPerformance, init } from '../../src';
import { instrumentBunServe } from '../../src/integrations/bunserver';
import type { DataCollection, Span } from '@sentry/core';

describe('Bun Serve Integration', () => {
const mockSpan = SentryCore.startInactiveSpan({ name: 'test span' });
const setAttributesSpy = spyOn(mockSpan, 'setAttributes');
const continueTraceSpy = spyOn(SentryCore, 'continueTrace');
const startSpanSpy = spyOn(SentryCore, 'startSpan').mockImplementation((_opts, cb) => {
return cb(mockSpan as unknown as Span);
return cb(mockSpan as unknown as SentryCore.Span);
});

const setupClient = (options?: BunOptions): void => {
init({
dsn: 'https://username@domain/123',
defaultIntegrations: false,
...options,
transport: () =>
SentryCore.createTransport({ recordDroppedEvent: () => undefined }, () => SentryCore.resolvedSyncPromise({})),
});
};

beforeAll(() => {
instrumentBunServe();
});
Expand All @@ -20,12 +30,16 @@ describe('Bun Serve Integration', () => {
startSpanSpy.mockClear();
continueTraceSpy.mockClear();
setAttributesSpy.mockClear();
// Header attributes are only collected while a client is active, so every test sets up its own instead of
// relying on one leaking in from whichever test file `bun test` happened to run first.
setupClient();
});

// Fun fact: Bun = 2 21 14 :)
let port: number = 22114;

afterEach(() => {
SentryCore.getCurrentScope().setClient(undefined);
Comment thread
Lms24 marked this conversation as resolved.
// Don't reuse the port; Bun server stops lazily so tests may accidentally hit a server still closing from a
// previous test
port += 1;
Expand Down Expand Up @@ -151,6 +165,7 @@ describe('Bun Serve Integration', () => {
});

test('includes HTTP request headers as span attributes', async () => {
setupClient({ defaultIntegrations: getDefaultIntegrationsWithoutPerformance() });
const server = Bun.serve({
async fetch(_req) {
return new Response('Headers test!');
Expand Down Expand Up @@ -476,22 +491,8 @@ describe('Bun Serve Integration', () => {
});

describe('data collection', () => {
const setupClient = (dataCollection: DataCollection): void => {
init({
dsn: 'https://username@domain/123',
defaultIntegrations: false,
transport: () =>
SentryCore.createTransport({ recordDroppedEvent: () => undefined }, () => SentryCore.resolvedSyncPromise({})),
dataCollection,
});
};

afterEach(() => {
SentryCore.getCurrentScope().setClient(undefined);
});

test('keeps PII request headers when dataCollection enables full header collection', async () => {
setupClient({ httpHeaders: { request: true, response: true } });
setupClient({ dataCollection: { httpHeaders: { request: true, response: true } } });

const server = Bun.serve({
async fetch(_req) {
Expand All @@ -514,7 +515,7 @@ describe('Bun Serve Integration', () => {
test('filters request headers according to the dataCollection deny list', async () => {
// Deny a header that is not part of the built-in sensitive snippets, so the assertion proves
// the deny list is applied (the header would otherwise be collected by default).
setupClient({ httpHeaders: { request: { deny: ['x-internal'] } } });
setupClient({ dataCollection: { httpHeaders: { request: { deny: ['x-internal'] } } } });

const server = Bun.serve({
async fetch(_req) {
Expand All @@ -536,7 +537,7 @@ describe('Bun Serve Integration', () => {
});

test('filters always-sensitive request headers even when collection is permissive', async () => {
setupClient({ httpHeaders: { request: true } });
setupClient({ dataCollection: { httpHeaders: { request: true } } });

const server = Bun.serve({
async fetch(_req) {
Expand All @@ -557,7 +558,7 @@ describe('Bun Serve Integration', () => {
});

test('applies the dataCollection response header collection behavior', async () => {
setupClient({ httpHeaders: { response: { deny: ['x-internal'] } } });
setupClient({ dataCollection: { httpHeaders: { response: { deny: ['x-internal'] } } } });

const server = Bun.serve({
async fetch(_req) {
Expand Down
Loading