UNPKG

@critters/next

Version:

Secure bug reporting library for Next.js applications

220 lines (219 loc) 9.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /** * Unit tests for utility functions */ const utils_1 = require("../src/utils"); // Mock the crypto module jest.mock("crypto", () => ({ createHmac: jest.fn().mockReturnValue({ update: jest.fn().mockReturnThis(), digest: jest.fn().mockReturnValue("mocked-server-signature"), }), })); // Mock crypto-js modules jest.mock("crypto-js/hmac-sha256", () => jest.fn().mockReturnValue({ toString: jest.fn().mockReturnValue("mocked-browser-signature"), })); jest.mock("crypto-js/enc-hex", () => ({})); describe("Utils", () => { describe("generateSignature", () => { // Store original window const originalWindow = global.window; beforeEach(() => { // Reset window for each test if (originalWindow === undefined) { // @ts-ignore - Ignoring TypeScript error as we need to test with window undefined global.window = undefined; } else { global.window = originalWindow; } }); afterAll(() => { // Restore original window after all tests if (originalWindow === undefined) { // @ts-ignore - Ignoring TypeScript error as we need to test with window undefined global.window = undefined; } else { global.window = originalWindow; } }); it("should return empty string if no secret key is provided", () => { const result = (0, utils_1.generateSignature)("payload", undefined); expect(result).toBe(""); }); it("should use server-side crypto in Node.js environment", () => { // Simulate server environment (no window) // @ts-ignore - Ignoring TypeScript error as we need to test with window undefined global.window = undefined; const result = (0, utils_1.generateSignature)("payload", "secret"); expect(result).toBe("mocked-server-signature"); }); it("should use browser-side crypto in browser environment", () => { // Simulate browser environment global.window = {}; const result = (0, utils_1.generateSignature)("payload", "secret"); expect(result).toBe("mocked-browser-signature"); }); }); describe("isBrowser and isServer", () => { // Store original window const originalWindow = global.window; beforeEach(() => { // Reset window for each test if (originalWindow === undefined) { // @ts-ignore - Ignoring TypeScript error as we need to test with window undefined global.window = undefined; } else { global.window = originalWindow; } }); afterAll(() => { // Restore original window after all tests if (originalWindow === undefined) { // @ts-ignore - Ignoring TypeScript error as we need to test with window undefined global.window = undefined; } else { global.window = originalWindow; } }); it("should correctly detect browser environment", () => { // Simulate browser environment global.window = {}; expect((0, utils_1.isBrowser)()).toBe(true); expect((0, utils_1.isServer)()).toBe(false); }); it("should correctly detect server environment", () => { // Simulate server environment // @ts-ignore - Ignoring TypeScript error as we need to test with window undefined global.window = undefined; expect((0, utils_1.isBrowser)()).toBe(false); expect((0, utils_1.isServer)()).toBe(true); }); }); describe("formatError", () => { it("should format Error objects", () => { const error = new Error("Test error"); error.name = "TestError"; const formatted = (0, utils_1.formatError)(error); expect(formatted.name).toBe("TestError"); expect(formatted.message).toBe("Test error"); expect(formatted.stack).toBeDefined(); }); it("should format string as error", () => { const formatted = (0, utils_1.formatError)("Error string"); expect(formatted.name).toBe("Unknown Error"); expect(formatted.message).toBe("Error string"); expect(formatted.stack).toBeUndefined(); }); it("should handle non-string, non-Error values", () => { const formatted = (0, utils_1.formatError)(123); expect(formatted.name).toBe("Unknown Error"); expect(formatted.message).toBe("123"); expect(formatted.stack).toBeUndefined(); }); }); describe("safeStringify", () => { it("should stringify simple objects", () => { const obj = { a: 1, b: "string", c: true }; const result = (0, utils_1.safeStringify)(obj); expect(result).toBe('{"a":1,"b":"string","c":true}'); }); it("should handle Error objects", () => { const error = new Error("Test error"); error.name = "TestError"; const result = JSON.parse((0, utils_1.safeStringify)({ error })); expect(result.error.name).toBe("TestError"); expect(result.error.message).toBe("Test error"); expect(result.error.stack).toBeDefined(); }); it("should handle circular references", () => { const obj = { a: 1 }; obj.self = obj; const result = JSON.parse((0, utils_1.safeStringify)(obj)); expect(result.a).toBe(1); expect(result.self).toBe("[Circular Reference]"); }); }); describe("sanitizeData", () => { it("should redact sensitive data", () => { const data = { username: "user1", password: "secret123", authToken: "abc123", apiKey: "xyz789", secretKey: "very-secret", normal: "not-sensitive", }; const sanitized = (0, utils_1.sanitizeData)(data); expect(sanitized.username).toBe("user1"); expect(sanitized.password).toBe("[REDACTED]"); expect(sanitized.authToken).toBe("[REDACTED]"); expect(sanitized.apiKey).toBe("[REDACTED]"); expect(sanitized.secretKey).toBe("[REDACTED]"); expect(sanitized.normal).toBe("not-sensitive"); }); it("should recursively sanitize nested objects", () => { const data = { user: { name: "John", credentials: { password: "secret123", token: "abc123", }, }, settings: { theme: "dark", }, }; const sanitized = (0, utils_1.sanitizeData)(data); expect(sanitized.user.name).toBe("John"); expect(sanitized.user.credentials.password).toBe("[REDACTED]"); expect(sanitized.user.credentials.token).toBe("[REDACTED]"); expect(sanitized.settings.theme).toBe("dark"); }); it("should sanitize arrays of objects", () => { const data = { users: [ { id: 1, name: "John", password: "secret1" }, { id: 2, name: "Jane", password: "secret2" }, ], }; const sanitized = (0, utils_1.sanitizeData)(data); expect(sanitized.users[0].id).toBe(1); expect(sanitized.users[0].name).toBe("John"); expect(sanitized.users[0].password).toBe("[REDACTED]"); expect(sanitized.users[1].id).toBe(2); expect(sanitized.users[1].name).toBe("Jane"); expect(sanitized.users[1].password).toBe("[REDACTED]"); }); it("should use custom sensitive keys if provided", () => { const data = { name: "John", ssn: "123-45-6789", creditCard: "1234-5678-9012-3456", }; const sanitized = (0, utils_1.sanitizeData)(data, ["ssn", "creditCard"]); expect(sanitized.name).toBe("John"); expect(sanitized.ssn).toBe("[REDACTED]"); expect(sanitized.creditCard).toBe("[REDACTED]"); }); }); describe("getTimestamp", () => { it("should return ISO formatted date string", () => { // Mock Date.now for consistent testing const mockDate = new Date("2023-01-01T12:00:00Z"); jest .spyOn(global, "Date") .mockImplementation(() => mockDate); const timestamp = (0, utils_1.getTimestamp)(); expect(timestamp).toBe("2023-01-01T12:00:00.000Z"); // Restore Date jest.restoreAllMocks(); }); }); });