Skip to main content
Glama
gmail-api.test.ts4.02 kB
import { describe, it, expect, vi, beforeEach, afterEach, } from 'vitest'; import {makeGmailApiCall, GMAIL_API_BASE_URL} from './gmail-api.js'; describe('makeGmailApiCall', () => { const mockFetch = vi.fn(); const originalFetch = global.fetch; beforeEach(() => { global.fetch = mockFetch; mockFetch.mockReset(); }); afterEach(() => { global.fetch = originalFetch; }); it('constructs correct URL from endpoint', async () => { mockFetch.mockResolvedValue({ ok: true, headers: new Headers({'content-type': 'application/json'}), text: async () => '{"messages": []}', }); await makeGmailApiCall('GET', '/users/me/messages', 'test-token'); expect(mockFetch).toHaveBeenCalledWith( `${GMAIL_API_BASE_URL}/users/me/messages`, expect.any(Object), ); }); it('sets Authorization header with bearer token', async () => { mockFetch.mockResolvedValue({ ok: true, headers: new Headers({'content-type': 'application/json'}), text: async () => '{}', }); await makeGmailApiCall('GET', '/users/me/messages', 'my-access-token'); expect(mockFetch).toHaveBeenCalledWith( expect.any(String), expect.objectContaining({ headers: expect.objectContaining({ Authorization: 'Bearer my-access-token', }), }), ); }); it('uses specified HTTP method', async () => { mockFetch.mockResolvedValue({ ok: true, headers: new Headers({'content-type': 'application/json'}), text: async () => '{}', }); await makeGmailApiCall('DELETE', '/users/me/messages/123', 'token'); expect(mockFetch).toHaveBeenCalledWith( expect.any(String), expect.objectContaining({method: 'DELETE'}), ); }); it('sends JSON body when provided', async () => { mockFetch.mockResolvedValue({ ok: true, headers: new Headers({'content-type': 'application/json'}), text: async () => '{}', }); const body = {addLabelIds: ['INBOX'], removeLabelIds: ['UNREAD']}; await makeGmailApiCall('POST', '/users/me/messages/123/modify', 'token', body); expect(mockFetch).toHaveBeenCalledWith( expect.any(String), expect.objectContaining({ headers: expect.objectContaining({ 'Content-Type': 'application/json', }), body: JSON.stringify(body), }), ); }); it('parses JSON response', async () => { const responseData = {messages: [{id: '123', threadId: '456'}]}; mockFetch.mockResolvedValue({ ok: true, headers: new Headers({'content-type': 'application/json'}), text: async () => JSON.stringify(responseData), }); const result = await makeGmailApiCall('GET', '/users/me/messages', 'token'); expect(result).toEqual(responseData); }); it('returns success object for empty JSON response', async () => { mockFetch.mockResolvedValue({ ok: true, headers: new Headers({'content-type': 'application/json'}), text: async () => '', }); const result = await makeGmailApiCall('POST', '/users/me/messages/123/trash', 'token'); expect(result).toEqual({success: true, message: 'Operation completed successfully'}); }); it('returns text for non-JSON response', async () => { mockFetch.mockResolvedValue({ ok: true, headers: new Headers({'content-type': 'text/plain'}), text: async () => 'OK', }); const result = await makeGmailApiCall('GET', '/some/endpoint', 'token'); expect(result).toBe('OK'); }); it('throws on API error response', async () => { mockFetch.mockResolvedValue({ ok: false, status: 401, statusText: 'Unauthorized', text: async () => '{"error": "invalid_token"}', }); await expect(makeGmailApiCall('GET', '/users/me/messages', 'bad-token')) .rejects.toThrow('Gmail API error: 401 Unauthorized'); }); it('throws on malformed JSON response', async () => { mockFetch.mockResolvedValue({ ok: true, headers: new Headers({'content-type': 'application/json'}), text: async () => 'not valid json', }); await expect(makeGmailApiCall('GET', '/users/me/messages', 'token')) .rejects.toThrow('Failed to parse JSON response'); }); });

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/domdomegg/gmail-mcp'

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