cvsa/packages/core/test/lib/randomID.test.ts

81 lines
2.8 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { generateRandomId, decodeTimestampFromId } from "@core/lib/randomID.ts";
describe("generateRandomId", () => {
it("should throw an error if the requested length is less than 8", () => {
expect(() => generateRandomId(7)).toThrowError("Length must be at least 8 to include the timestamp prefix.");
});
it("should generate an ID of the specified length", () => {
const length = 15;
const id = generateRandomId(length);
expect(id).toHaveLength(length);
});
it("should generate an ID with a timestamp prefix of length 8", () => {
const id = generateRandomId(12);
expect(id).toHaveProperty("substring");
expect(id).toHaveProperty("length");
expect(id.length).toBeGreaterThanOrEqual(8);
});
it("should generate an ID containing only allowed characters", () => {
const allowedChars = "abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789";
const id = generateRandomId(20);
for (const char of id) {
expect(allowedChars).toContain(char);
}
});
it("should generate IDs that are sortable by creation time", () => {
const id1 = generateRandomId(10);
// Simulate a slight delay to ensure different timestamps
return new Promise((resolve) => {
setTimeout(() => {
const id2 = generateRandomId(10);
expect(id2 >= id1).toBe(true);
resolve(null);
}, 10);
});
});
});
describe("decodeTimestampFromId", () => {
it("should throw an error if the ID length is less than 8", () => {
expect(() => decodeTimestampFromId("abcdefg")).toThrowError(
"ID must be at least 8 characters long to contain a timestamp prefix."
);
});
it("should throw an error if the timestamp prefix contains invalid characters", () => {
const invalidId = "0bcdefghijk";
expect(() => decodeTimestampFromId(invalidId)).toThrowError('Invalid character "0" found in timestamp prefix.');
});
it("should correctly decode the timestamp from a generated ID", () => {
const now = Date.now();
// Mock Date.now to control the timestamp for testing
const originalDateNow = Date.now;
global.Date.now = () => now;
const id = generateRandomId(16);
global.Date.now = originalDateNow; // Restore original Date.now
const decodedTimestamp = decodeTimestampFromId(id);
// Allow a small margin for potential timing differences in test execution
expect(decodedTimestamp).toBeGreaterThanOrEqual(now - 1);
expect(decodedTimestamp).toBeLessThanOrEqual(now + 1);
});
it("should correctly decode the timestamp even with a longer ID", () => {
const now = Date.now();
const originalDateNow = Date.now;
global.Date.now = () => now;
const id = generateRandomId(20);
global.Date.now = originalDateNow;
const decodedTimestamp = decodeTimestampFromId(id);
expect(decodedTimestamp).toBeGreaterThanOrEqual(now - 1);
expect(decodedTimestamp).toBeLessThanOrEqual(now + 1);
});
});