@ogcio/o11y-sdk-react
Version:
Opentelemetry standard instrumentation SDK for React based project
150 lines (131 loc) • 4.05 kB
text/typescript
import {
LogEvent,
LogLevel,
TransportItem,
TransportItemType,
} from "@grafana/faro-web-sdk";
import { beforeEach, describe, expect, it, vi } from "vitest";
import { _beforeSend } from "../../lib/internals/hooks";
// Mock faro.api.pushMeasurement
vi.mock("@grafana/faro-web-sdk", async () => {
const actual = await vi.importActual<any>("@grafana/faro-web-sdk");
return {
...actual,
faro: {
api: {
pushMeasurement: vi.fn(),
},
},
};
});
import { faro } from "@grafana/faro-web-sdk";
describe("_beforeSend", () => {
beforeEach(() => {
vi.clearAllMocks();
});
it("should deeply redact PII in object", () => {
const item = {
type: TransportItemType.LOG,
payload: {
level: LogLevel.INFO,
context: {},
timestamp: Date.now().toString(),
message: "my email is bob@abc.com",
},
meta: {
user: {
email: "carol@abc.com",
attributes: {
alternative_email: "foo@xyz.org",
},
},
},
} satisfies TransportItem<LogEvent>;
const redacted: TransportItem<LogEvent> = _beforeSend(
item,
) as TransportItem<LogEvent>;
expect(redacted.payload.message).toBe("my email is [REDACTED EMAIL]");
expect(redacted.meta.user).not.toBeNull();
expect(redacted.meta.user!.email).toBe("[REDACTED EMAIL]");
expect(redacted.meta.user!.attributes).toBeDefined();
expect(redacted.meta.user!.attributes!["alternative_email"]).toBe(
"[REDACTED EMAIL]",
);
expect(faro.api.pushMeasurement).toHaveBeenCalledTimes(3);
});
it("should redact email inside arrays of primitives", () => {
const item: TransportItem<LogEvent> = {
type: TransportItemType.LOG,
payload: {
message: "start",
context: {
messages: ["hello", "email: test@abc.com", "ok"],
},
timestamp: "123",
level: LogLevel.INFO,
},
};
const redacted = _beforeSend(item)!;
expect(redacted.payload.context.messages[1]).toBe(
"email: [REDACTED EMAIL]",
);
expect(faro.api.pushMeasurement).toHaveBeenCalledOnce();
});
it("should redact emails in arrays of objects", () => {
const item: TransportItem<LogEvent> = {
type: TransportItemType.LOG,
payload: {
message: "checking",
context: {
events: [
{ message: "contact a@b.com" },
{ message: "nothing here" },
{ note: "try c@d.net" },
],
},
timestamp: "123",
level: LogLevel.INFO,
},
};
const redacted = _beforeSend(item)!;
expect(redacted.payload.context.events[0].message).toBe(
"contact [REDACTED EMAIL]",
);
expect(redacted.payload.context.events[2].note).toBe(
"try [REDACTED EMAIL]",
);
expect(faro.api.pushMeasurement).toHaveBeenCalledTimes(2);
});
it("should not break on nulls, undefined, numbers, booleans", () => {
const item: TransportItem<LogEvent> = {
type: TransportItemType.LOG,
payload: {
message: null as any,
count: 123,
active: true,
description: undefined,
} as any,
meta: null,
};
const redacted = _beforeSend(item)!;
expect(redacted.payload.message).toBeNull();
expect(redacted.payload.count).toBe(123);
expect(redacted.payload.active).toBe(true);
expect("description" in redacted.payload).toBe(true); // still defined as undefined
expect(faro.api.pushMeasurement).not.toHaveBeenCalled();
});
it("should decode and redact encoded emails", () => {
const item: TransportItem<LogEvent> = {
type: TransportItemType.LOG,
payload: {
message: "contact%20user%40domain.com",
level: LogLevel.INFO,
context: {},
timestamp: "now",
},
};
const redacted = _beforeSend(item)!;
expect(redacted.payload.message).toBe("contact [REDACTED EMAIL]");
expect(faro.api.pushMeasurement).toHaveBeenCalledOnce();
});
});