Skip to main content
Glama
rate-limiter.test.ts3.02 kB
/** * Tests for rate limiter. */ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { RateLimiter, createJiraRateLimiter, } from '../../../src/utils/rate-limiter.js'; import { RateLimitError } from '../../../src/utils/errors.js'; describe('RateLimiter', () => { beforeEach(() => { vi.useFakeTimers(); }); afterEach(() => { vi.useRealTimers(); }); it('should allow requests within limit', () => { const limiter = new RateLimiter({ maxRequests: 10, windowMs: 1000 }); // Should not throw for first 10 requests for (let i = 0; i < 10; i++) { expect(() => limiter.acquire()).not.toThrow(); } }); it('should throw RateLimitError when limit exceeded', () => { const limiter = new RateLimiter({ maxRequests: 2, windowMs: 1000 }); limiter.acquire(); limiter.acquire(); expect(() => limiter.acquire()).toThrow(RateLimitError); }); it('should refill tokens over time', () => { const limiter = new RateLimiter({ maxRequests: 2, windowMs: 1000 }); limiter.acquire(); limiter.acquire(); // Advance time by half the window vi.advanceTimersByTime(500); // Should have 1 token refilled expect(() => limiter.acquire()).not.toThrow(); }); it('should report remaining tokens', () => { const limiter = new RateLimiter({ maxRequests: 5, windowMs: 1000 }); expect(limiter.getRemainingTokens()).toBe(5); limiter.acquire(); expect(limiter.getRemainingTokens()).toBe(4); limiter.acquire(); limiter.acquire(); expect(limiter.getRemainingTokens()).toBe(2); }); it('should check if can acquire', () => { const limiter = new RateLimiter({ maxRequests: 1, windowMs: 1000 }); expect(limiter.canAcquire()).toBe(true); limiter.acquire(); expect(limiter.canAcquire()).toBe(false); vi.advanceTimersByTime(1000); expect(limiter.canAcquire()).toBe(true); }); it('should calculate time until next token', () => { const limiter = new RateLimiter({ maxRequests: 1, windowMs: 1000 }); expect(limiter.getTimeUntilNextToken()).toBe(0); limiter.acquire(); const waitTime = limiter.getTimeUntilNextToken(); expect(waitTime).toBeGreaterThan(0); expect(waitTime).toBeLessThanOrEqual(1000); }); it('should wait for token', async () => { const limiter = new RateLimiter({ maxRequests: 1, windowMs: 1000 }); limiter.acquire(); const waitPromise = limiter.waitForToken(); // Advance time vi.advanceTimersByTime(1000); await waitPromise; // Should have acquired the token expect(limiter.getRemainingTokens()).toBe(0); }); }); describe('createJiraRateLimiter', () => { it('should create limiter with default rate', () => { const limiter = createJiraRateLimiter(); expect(limiter.getRemainingTokens()).toBe(100); }); it('should create limiter with custom rate', () => { const limiter = createJiraRateLimiter(50); expect(limiter.getRemainingTokens()).toBe(50); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/icy-r/jira-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server