Files
prowler/ui/sentry/event-policy.test.ts
2026-07-20 16:34:24 +02:00

309 lines
7.6 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type {
SentryEventHint,
SentryEventPolicyOptions,
SentryPolicyEvent,
} from "./event-policy";
import {
applySentryEventPolicy,
isErrorAlreadyReported,
isErrorCapturedBySentry,
markErrorAsReported,
} from "./event-policy";
describe("applySentryEventPolicy", () => {
describe("when events are actionable", () => {
it("should keep error events", () => {
// Given
const event = {
level: "error",
message: "Unexpected failure",
} satisfies SentryPolicyEvent & { level: string; message: string };
const options: SentryEventPolicyOptions = { source: "client" };
// When
const result = applySentryEventPolicy(event, undefined, options);
// Then
expect(result).toBe(event);
expect(result).toMatchObject({
tags: {
actionability: "actionable",
kind: "runtime",
source: "client",
},
});
});
it("should keep fatal events", () => {
// Given
const event = { level: "fatal", message: "Runtime crashed" };
// When
const result = applySentryEventPolicy(event);
// Then
expect(result).toBe(event);
});
it("should keep events without a level", () => {
// Given
const event = { message: "Default Sentry event" };
// When
const result = applySentryEventPolicy(event);
// Then
expect(result).toBe(event);
});
it("should keep fatal runtime messages that contain an expected HTTP status number", () => {
// Given
const event = {
level: "fatal",
message: "Runtime worker 401 crashed unexpectedly",
};
// When
const result = applySentryEventPolicy(event);
// Then
expect(result).toBe(event);
expect(result).toMatchObject({
tags: {
actionability: "actionable",
kind: "runtime",
},
});
});
it("should keep runtime error messages that contain an expected HTTP status number", () => {
// Given
const event = {
level: "error",
message: "Background import 404 failed after a null dereference",
};
// When
const result = applySentryEventPolicy(event);
// Then
expect(result).toBe(event);
expect(result).toMatchObject({
tags: {
actionability: "actionable",
kind: "runtime",
},
});
});
it("should keep fatal runtime messages that mention status without HTTP context", () => {
// Given
const event = {
level: "fatal",
message: "State transition status 403 caused worker crash",
};
// When
const result = applySentryEventPolicy(event);
// Then
expect(result).toBe(event);
expect(result).toMatchObject({
tags: {
actionability: "actionable",
kind: "runtime",
},
});
});
it("should keep fatal runtime messages that mention status code without HTTP context", () => {
// Given
const event = {
level: "fatal",
message: "State transition status code 403 caused worker crash",
};
// When
const result = applySentryEventPolicy(event);
// Then
expect(result).toBe(event);
expect(result).toMatchObject({
tags: {
actionability: "actionable",
kind: "runtime",
},
});
});
it("should keep fatal runtime messages that mention response without HTTP context", () => {
// Given
const event = {
level: "fatal",
message: "Worker response 404 triggered fatal cache corruption",
};
// When
const result = applySentryEventPolicy(event);
// Then
expect(result).toBe(event);
expect(result).toMatchObject({
tags: {
actionability: "actionable",
kind: "runtime",
},
});
});
it("should preserve existing tags on actionable API events", () => {
// Given
const event = {
level: "error",
message: "API response failed with status 500",
tags: {
feature: "providers",
status_code: "500",
},
};
// When
const result = applySentryEventPolicy(event, undefined, {
source: "server_action",
});
// Then
expect(result).toBe(event);
expect(result).toMatchObject({
tags: {
actionability: "actionable",
feature: "providers",
kind: "api",
source: "server_action",
status_code: "500",
},
});
});
});
describe("when events are non-actionable", () => {
it("should drop warning events", () => {
// Given
const event = { level: "warning", message: "Provider already exists" };
// When
const result = applySentryEventPolicy(event);
// Then
expect(result).toBeNull();
});
it("should drop Next.js redirect control-flow events", () => {
// Given
const event = { level: "error", message: "NEXT_REDIRECT" };
// When
const result = applySentryEventPolicy(event);
// Then
expect(result).toBeNull();
});
it("should drop AbortError events", () => {
// Given
const event = { level: "error", message: "The operation was aborted" };
const hint: SentryEventHint = {
originalException: new DOMException("Aborted", "AbortError"),
};
// When
const result = applySentryEventPolicy(event, hint);
// Then
expect(result).toBeNull();
});
it("should drop expected HTTP 401 events", () => {
// Given
const event = { level: "error", tags: { status_code: "401" } };
// When
const result = applySentryEventPolicy(event);
// Then
expect(result).toBeNull();
});
it("should drop expected HTTP 403 events", () => {
// Given
const event = { level: "error", message: "Request failed with 403" };
// When
const result = applySentryEventPolicy(event);
// Then
expect(result).toBeNull();
});
it("should drop expected HTTP 404 events", () => {
// Given
const event = { level: "error" };
const hint = { originalException: { status: 404 } };
// When
const result = applySentryEventPolicy(event, hint);
// Then
expect(result).toBeNull();
});
it("should drop clear HTTP messages with expected status codes", () => {
// Given
const event = {
level: "error",
message: "HTTP response status code 404",
};
// When
const result = applySentryEventPolicy(event);
// Then
expect(result).toBeNull();
});
it("should drop already-reported errors", () => {
// Given
const error = new Error("Already reported failure");
const event = { level: "error", message: error.message };
markErrorAsReported(error);
// When
const result = applySentryEventPolicy(event, {
originalException: error,
});
// Then
expect(isErrorAlreadyReported(error)).toBe(true);
expect(result).toBeNull();
});
it("should keep the first event for an error marked by Sentry", () => {
// Given
const error = new Error("First capture");
Object.defineProperty(error, "__sentry_captured__", { value: true });
const event = { level: "error", message: error.message };
// When
const result = applySentryEventPolicy(event, {
originalException: error,
});
// Then
expect(isErrorCapturedBySentry(error)).toBe(true);
expect(result).toBe(event);
});
});
});