Skip to content
Open
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
300 changes: 298 additions & 2 deletions __tests__/instrumentation-client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,44 @@ jest.mock("@sentry/nextjs", () => ({
captureRouterTransitionStart: mockCaptureRouterTransitionStart,
}));

describe("instrumentation-client beforeSendTransaction", () => {
const loadBeforeSendTransaction = () => {
describe("instrumentation-client", () => {
const wrappedNetworkMessage =
"Network request failed. Please check your connection and try again. (/api/waves-overview)";

type BeforeSendResult = {
tags?: Record<string, unknown> | undefined;
fingerprint?: string[] | undefined;
exception?:
| {
values?: Array<{ value?: string | undefined } | undefined>;
}
| undefined;
message?: string | undefined;
} | null;

const loadSentryConfig = () => {
jest.isolateModules(() => {
require("@/instrumentation-client");
});

const config = mockInit.mock.calls[0]?.[0];
expect(config).toBeDefined();

return config;
};

const loadBeforeSend = () => {
const config = loadSentryConfig();
expect(typeof config.beforeSend).toBe("function");

return config.beforeSend as (
event: Record<string, unknown>,
hint?: Record<string, unknown>
) => BeforeSendResult;
};

const loadBeforeSendTransaction = () => {
const config = loadSentryConfig();
expect(typeof config.beforeSendTransaction).toBe("function");

return config.beforeSendTransaction as (event: Record<string, unknown>) => {
Expand All @@ -37,6 +67,272 @@ describe("instrumentation-client beforeSendTransaction", () => {
mockCaptureRouterTransitionStart.mockReset();
});

it("drops sampled-out first-party browser transport network errors", () => {
const beforeSend = loadBeforeSend();
const event = {
event_id: "network-drop-event",
exception: {
values: [
{
type: "TypeError",
value: "Load failed",
},
],
},
breadcrumbs: [
{
type: "http",
category: "fetch",
data: {
status_code: 0,
url: "/api/waves-overview",
"url.is_first_party": true,
},
},
],
};

const result = beforeSend(event, {
originalException: new TypeError("Load failed"),
});

expect(result).toBeNull();
});

it("uses the latest failed fetch breadcrumb for raw browser network errors", () => {
const beforeSend = loadBeforeSend();
const event = {
event_id: "network-drop-event",
exception: {
values: [
{
type: "TypeError",
value: "Load failed",
},
],
},
breadcrumbs: [
{
type: "http",
category: "fetch",
data: {
status_code: 0,
url: "/api/a",
"url.is_first_party": true,
},
},
{
type: "http",
category: "fetch",
data: {
status_code: 0,
url: "/api/b",
"url.is_first_party": true,
},
},
],
};

const result = beforeSend(event, {
originalException: new TypeError("Load failed"),
});

expect(result).toBeNull();
expect(event.exception.values[0]?.value).toBe(
"Network request failed. Please check your connection and try again. (/api/b)"
);
});

it("keeps and tags sampled-in first-party browser transport network errors", () => {
const beforeSend = loadBeforeSend();
const event = {
event_id: "event-200",
exception: {
values: [
{
type: "TypeError",
value: "Load failed",
},
],
},
breadcrumbs: [
{
type: "http",
category: "fetch",
data: {
status_code: 0,
url: "/api/waves-overview",
"url.is_first_party": true,
},
},
],
};

const result = beforeSend(event, {
originalException: new TypeError("Load failed"),
});

expect(result).not.toBeNull();
expect(result?.tags).toEqual(
expect.objectContaining({
errorType: "network",
handled: true,
network_failure_kind: "browser_transport",
network_noise_sampled: "true",
})
);
expect(result?.fingerprint).toEqual(["network-error"]);
});

it("drops sampled-out app-wrapped first-party browser transport network errors", () => {
const beforeSend = loadBeforeSend();
const event = {
event_id: "network-drop-event",
exception: {
values: [
{
type: "Error",
value: wrappedNetworkMessage,
},
],
},
breadcrumbs: [
{
type: "http",
category: "fetch",
data: {
status_code: 0,
url: "/api/waves-overview",
"url.is_first_party": true,
},
},
],
};

const result = beforeSend(event, {
originalException: new Error(wrappedNetworkMessage),
});

expect(result).toBeNull();
});

it("keeps and tags sampled-in app-wrapped first-party browser transport network errors without rewriting the message", () => {
const beforeSend = loadBeforeSend();
const event = {
event_id: "event-200",
message: wrappedNetworkMessage,
fingerprint: ["drop-reaction", "network"],
exception: {
values: [
{
type: "Error",
value: wrappedNetworkMessage,
},
],
},
breadcrumbs: [
{
type: "http",
category: "fetch",
data: {
status_code: 0,
url: "/api/waves-overview",
"url.is_first_party": true,
},
},
],
};

const result = beforeSend(event, {
originalException: new Error(wrappedNetworkMessage),
});

expect(result).not.toBeNull();
expect(result?.tags).toEqual(
expect.objectContaining({
errorType: "network",
handled: true,
network_failure_kind: "browser_transport",
network_noise_sampled: "true",
})
);
expect(result?.exception?.values?.[0]?.value).toBe(wrappedNetworkMessage);
expect(result?.message).toBe(wrappedNetworkMessage);
expect(result?.fingerprint).toEqual(["drop-reaction", "network"]);
});

it("does not tag unrelated plain errors that mention network", () => {
const beforeSend = loadBeforeSend();
const event = {
event_id: "event-200",
exception: {
values: [
{
type: "Error",
value: "network switch failed",
},
],
},
breadcrumbs: [
{
type: "http",
category: "fetch",
data: {
status_code: 0,
url: "/api/waves-overview",
"url.is_first_party": true,
},
},
],
};

const result = beforeSend(event, {
originalException: new Error("network switch failed"),
});

expect(result).not.toBeNull();
expect(result?.tags?.["errorType"]).toBeUndefined();
});

it("keeps browser network errors with a real HTTP status", () => {
const beforeSend = loadBeforeSend();
const event = {
event_id: "network-drop-event",
exception: {
values: [
{
type: "TypeError",
value: "Load failed",
},
],
},
breadcrumbs: [
{
type: "http",
category: "fetch",
data: {
status_code: 500,
url: "/api/waves-overview",
"url.is_first_party": true,
},
},
],
};

const result = beforeSend(event, {
originalException: new TypeError("Load failed"),
});

expect(result).not.toBeNull();
expect(result?.tags).toEqual(
expect.objectContaining({
errorType: "network",
handled: true,
})
);
expect(result?.tags?.["network_noise_sampled"]).toBeUndefined();
});

it("removes only the known noisy third-party telemetry spans", () => {
const beforeSendTransaction = loadBeforeSendTransaction();
const event = {
Expand Down
Loading
Loading