Skip to content
Closed
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
69 changes: 69 additions & 0 deletions src/lib/__tests__/github/handleRateLimit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
import { handleRateLimit } from "@/lib/github";
import { RateLimitError } from "@/lib/types";

describe("handleRateLimit", () => {
beforeEach(() => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2024-01-01T00:00:00Z"));
});

afterEach(() => {
vi.useRealTimers();
});

it("throws RateLimitError using X-RateLimit-Reset header when available", () => {
const timestamp = 1704069000; // 2024-01-01T00:30:00Z
const headers = new Headers();
headers.set("X-RateLimit-Reset", timestamp.toString());
const mockResponse = {
headers
} as unknown as Response;

expect(() => handleRateLimit(mockResponse)).toThrow(RateLimitError);
try {
handleRateLimit(mockResponse);
} catch (e) {
expect(e).toBeInstanceOf(RateLimitError);
const error = e as RateLimitError;
expect(error.resetAt.getTime()).toBe(timestamp * 1000);
}
Comment on lines +23 to +30

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current test pattern executes handleRateLimit twice. Optimizing this by executing the function once inside a try-catch block ensures the test is more robust and correctly asserts the error state, which aligns with maintaining reliable error handling coverage.

Suggested change
expect(() => handleRateLimit(mockResponse)).toThrow(RateLimitError);
try {
handleRateLimit(mockResponse);
} catch (e) {
expect(e).toBeInstanceOf(RateLimitError);
const error = e as RateLimitError;
expect(error.resetAt.getTime()).toBe(timestamp * 1000);
}
let error: unknown;
try {
handleRateLimit(mockResponse);
} catch (e) {
error = e;
}
expect(error).toBeInstanceOf(RateLimitError);
expect((error as RateLimitError).resetAt.getTime()).toBe(timestamp * 1000);
References
  1. When refactoring API routes, ensure that existing test cases for error handling are preserved to maintain robust coverage.

});

it("throws RateLimitError using default time (1 hour from now) when header is missing", () => {
const headers = new Headers();
const mockResponse = {
headers
} as unknown as Response;

const expectedTimestamp = Math.floor(Date.now() / 1000) + 3600;

expect(() => handleRateLimit(mockResponse)).toThrow(RateLimitError);
try {
handleRateLimit(mockResponse);
} catch (e) {
expect(e).toBeInstanceOf(RateLimitError);
const error = e as RateLimitError;
expect(error.resetAt.getTime()).toBe(expectedTimestamp * 1000);
}
Comment on lines +41 to +48

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current test pattern executes handleRateLimit twice. Optimizing this by executing the function once inside a try-catch block ensures the test is more robust and correctly asserts the error state, which aligns with maintaining reliable error handling coverage.

Suggested change
expect(() => handleRateLimit(mockResponse)).toThrow(RateLimitError);
try {
handleRateLimit(mockResponse);
} catch (e) {
expect(e).toBeInstanceOf(RateLimitError);
const error = e as RateLimitError;
expect(error.resetAt.getTime()).toBe(expectedTimestamp * 1000);
}
let error: unknown;
try {
handleRateLimit(mockResponse);
} catch (e) {
error = e;
}
expect(error).toBeInstanceOf(RateLimitError);
expect((error as RateLimitError).resetAt.getTime()).toBe(expectedTimestamp * 1000);
References
  1. When refactoring API routes, ensure that existing test cases for error handling are preserved to maintain robust coverage.

});

it("throws RateLimitError using default time when header is invalid", () => {
const headers = new Headers();
headers.set("X-RateLimit-Reset", "invalid");
const mockResponse = {
headers
} as unknown as Response;

const expectedTimestamp = Math.floor(Date.now() / 1000) + 3600;

expect(() => handleRateLimit(mockResponse)).toThrow(RateLimitError);
try {
handleRateLimit(mockResponse);
} catch (e) {
expect(e).toBeInstanceOf(RateLimitError);
const error = e as RateLimitError;
expect(error.resetAt.getTime()).toBe(expectedTimestamp * 1000);
}
Comment on lines +60 to +67

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The current test pattern executes handleRateLimit twice. Optimizing this by executing the function once inside a try-catch block ensures the test is more robust and correctly asserts the error state, which aligns with maintaining reliable error handling coverage.

Suggested change
expect(() => handleRateLimit(mockResponse)).toThrow(RateLimitError);
try {
handleRateLimit(mockResponse);
} catch (e) {
expect(e).toBeInstanceOf(RateLimitError);
const error = e as RateLimitError;
expect(error.resetAt.getTime()).toBe(expectedTimestamp * 1000);
}
let error: unknown;
try {
handleRateLimit(mockResponse);
} catch (e) {
error = e;
}
expect(error).toBeInstanceOf(RateLimitError);
expect((error as RateLimitError).resetAt.getTime()).toBe(expectedTimestamp * 1000);
References
  1. When refactoring API routes, ensure that existing test cases for error handling are preserved to maintain robust coverage.

});
});
Loading