Skip to main content
Glama
client.test.ts4.27 kB
import MediumClient from '../src/client'; import MediumAuth from '../src/auth'; import axios from 'axios'; jest.mock('axios'); const mockedAxios = axios as jest.Mocked<typeof axios>; // Mock environment variables process.env.MEDIUM_CLIENT_ID = 'test_client_id'; process.env.MEDIUM_CLIENT_SECRET = 'test_client_secret'; process.env.MEDIUM_ACCESS_TOKEN = 'test_access_token'; describe('MediumClient', () => { let client: MediumClient; let auth: MediumAuth; beforeEach(async () => { auth = new MediumAuth(); await auth.authenticate(); client = new MediumClient(auth); // Reset all mocks jest.clearAllMocks(); }); describe('publishArticle', () => { it('should publish an article successfully', async () => { const mockUserResponse = { data: { data: { id: 'user123' } }, headers: {}, status: 200 }; const mockPublishResponse = { data: { data: { id: 'post123', title: 'Test Article', url: 'https://medium.com/@user/test-article' } }, headers: {}, status: 201 }; mockedAxios.mockResolvedValueOnce(mockUserResponse as any); mockedAxios.mockResolvedValueOnce(mockPublishResponse as any); const result = await client.publishArticle({ title: 'Test Article', content: '# Test Content', tags: ['test', 'jest'] }); expect(result.data.id).toBe('post123'); expect(mockedAxios).toHaveBeenCalledTimes(2); }); it('should handle API errors gracefully', async () => { const mockUserResponse = { data: { data: { id: 'user123' } }, headers: {}, status: 200 }; const mockPublishError = { response: { status: 400, statusText: 'Bad Request', data: { errors: [{ message: 'Invalid title' }] }, headers: {} } }; // getUserProfile succeeds, but publishArticle fails with 400 (not retryable) mockedAxios .mockResolvedValueOnce(mockUserResponse as any) .mockRejectedValueOnce(mockPublishError); await expect( client.publishArticle({ title: '', content: 'Content' }) ).rejects.toBeTruthy(); }); }); describe('getUserProfile', () => { it('should retrieve user profile', async () => { const mockResponse = { data: { data: { id: 'user123', username: 'testuser', name: 'Test User' } }, headers: {}, status: 200 }; mockedAxios.mockResolvedValueOnce(mockResponse as any); const result = await client.getUserProfile(); expect(result.data.username).toBe('testuser'); expect(mockedAxios).toHaveBeenCalledWith( expect.objectContaining({ method: 'get', url: expect.stringContaining('/me') }) ); }); }); describe('retry logic', () => { it('should retry on rate limit error', async () => { const rateLimitError = { response: { status: 429, statusText: 'Too Many Requests', data: { message: 'Rate limit exceeded' } } }; const successResponse = { data: { data: { id: 'user123' } }, headers: {}, status: 200 }; mockedAxios .mockRejectedValueOnce(rateLimitError) .mockResolvedValueOnce(successResponse as any); const result = await client.getUserProfile(); expect(result.data.id).toBe('user123'); expect(mockedAxios).toHaveBeenCalledTimes(2); }); }); describe('rate limit info', () => { it('should track rate limit information', async () => { const mockResponse = { data: { data: { id: 'user123' } }, headers: { 'x-ratelimit-remaining': '99', 'x-ratelimit-reset': '1699999999' }, status: 200 }; mockedAxios.mockResolvedValueOnce(mockResponse as any); await client.getUserProfile(); const rateLimitInfo = client.getRateLimitInfo(); expect(rateLimitInfo.remaining).toBe(99); expect(rateLimitInfo.resetAt).toBeInstanceOf(Date); }); }); });

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/aliiqbal208/medium-mcp'

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