mcp-memory-libsql
by spences10
Verified
import { GmailService } from '../../../modules/gmail/service.js';
import { gmail_v1 } from 'googleapis';
import { getAccountManager } from '../../../modules/accounts/index.js';
import { AccountManager } from '../../../modules/accounts/manager.js';
import { DraftResponse, GetDraftsResponse, SendEmailResponse } from '../../../modules/gmail/types.js';
jest.mock('../../../modules/accounts/index.js');
jest.mock('../../../modules/accounts/manager.js');
describe('GmailService', () => {
let gmailService: GmailService;
let mockGmailClient: jest.Mocked<gmail_v1.Gmail>;
let mockAccountManager: jest.Mocked<AccountManager>;
const testEmail = 'test@example.com';
beforeEach(async () => {
// Simplified mock setup
mockGmailClient = {
users: {
messages: {
list: jest.fn().mockImplementation(() => Promise.resolve({ data: {} })),
get: jest.fn().mockImplementation(() => Promise.resolve({ data: {} })),
send: jest.fn().mockImplementation(() => Promise.resolve({ data: {} })),
},
drafts: {
create: jest.fn().mockImplementation(() => Promise.resolve({ data: {} })),
list: jest.fn().mockImplementation(() => Promise.resolve({ data: {} })),
get: jest.fn().mockImplementation(() => Promise.resolve({ data: {} })),
send: jest.fn().mockImplementation(() => Promise.resolve({ data: {} })),
},
getProfile: jest.fn().mockImplementation(() => Promise.resolve({ data: {} })),
settings: {
getAutoForwarding: jest.fn().mockImplementation(() => Promise.resolve({ data: {} })),
getImap: jest.fn().mockImplementation(() => Promise.resolve({ data: {} })),
getLanguage: jest.fn().mockImplementation(() => Promise.resolve({ data: {} })),
getPop: jest.fn().mockImplementation(() => Promise.resolve({ data: {} })),
getVacation: jest.fn().mockImplementation(() => Promise.resolve({ data: {} })),
},
},
} as any;
mockAccountManager = {
validateToken: jest.fn().mockResolvedValue({ valid: true, token: {} }),
getAuthClient: jest.fn().mockResolvedValue({}),
withTokenRenewal: jest.fn().mockImplementation((email, operation) => operation()),
} as unknown as jest.Mocked<AccountManager>;
(getAccountManager as jest.Mock).mockReturnValue(mockAccountManager);
gmailService = new GmailService();
await gmailService.initialize();
// Mock the base service's getAuthenticatedClient method
(gmailService as any).getAuthenticatedClient = jest.fn().mockResolvedValue(mockGmailClient);
// Mock all internal services
(gmailService as any).emailService.gmailClient = mockGmailClient;
(gmailService as any).emailService.getAuthenticatedClient = jest.fn().mockResolvedValue(mockGmailClient);
(gmailService as any).draftService.gmailClient = mockGmailClient;
(gmailService as any).draftService.getAuthenticatedClient = jest.fn().mockResolvedValue(mockGmailClient);
(gmailService as any).settingsService.gmailClient = mockGmailClient;
(gmailService as any).settingsService.getAuthenticatedClient = jest.fn().mockResolvedValue(mockGmailClient);
});
describe('getEmails', () => {
it('should get emails with search criteria', async () => {
const mockMessages = [
{ id: 'msg1', threadId: 'thread1' },
{ id: 'msg2', threadId: 'thread2' }
];
(mockGmailClient.users.messages.list as jest.Mock).mockImplementation(() =>
Promise.resolve({ data: { messages: mockMessages, resultSizeEstimate: 2 } })
);
const result = await gmailService.getEmails({
email: testEmail,
search: { subject: 'test' }
});
expect(result.emails.length).toBe(2);
expect(result.resultSummary.total).toBe(2);
});
it('should handle empty results', async () => {
(mockGmailClient.users.messages.list as jest.Mock).mockImplementation(() =>
Promise.resolve({ data: { messages: [], resultSizeEstimate: 0 } })
);
const result = await gmailService.getEmails({ email: testEmail });
expect(result.emails).toEqual([]);
expect(result.resultSummary.total).toBe(0);
});
});
describe('sendEmail', () => {
const emailParams = {
email: testEmail,
to: ['recipient@example.com'],
subject: 'Test',
body: 'Hello'
};
it('should send email', async () => {
(mockGmailClient.users.messages.send as jest.Mock).mockImplementation(() =>
Promise.resolve({
data: { id: 'msg1', threadId: 'thread1', labelIds: ['SENT'] }
})
);
const result = await gmailService.sendEmail(emailParams);
expect(result.messageId).toBe('msg1');
expect(result.labelIds).toContain('SENT');
});
it('should handle send failure', async () => {
(mockGmailClient.users.messages.send as jest.Mock).mockImplementation(() =>
Promise.reject(new Error('Send failed'))
);
await expect(gmailService.sendEmail(emailParams)).rejects.toThrow();
});
});
describe('manageDraft', () => {
it('should create draft', async () => {
(mockGmailClient.users.drafts.create as jest.Mock).mockImplementation(() =>
Promise.resolve({
data: {
id: 'draft1',
message: { id: 'msg1' }
}
})
);
const result = await gmailService.manageDraft({
action: 'create',
email: testEmail,
data: {
to: ['test@example.com'],
subject: 'Draft',
body: 'Content'
}
}) as DraftResponse;
expect(result).toHaveProperty('id', 'draft1');
});
it('should list drafts', async () => {
// Mock the list call to return draft IDs
(mockGmailClient.users.drafts.list as jest.Mock).mockImplementation(() =>
Promise.resolve({
data: {
drafts: [
{ id: 'draft1' },
{ id: 'draft2' }
],
resultSizeEstimate: 2
}
})
);
// Mock the get call for each draft
(mockGmailClient.users.drafts.get as jest.Mock)
.mockImplementationOnce(() => Promise.resolve({
data: {
id: 'draft1',
message: {
id: 'msg1',
threadId: 'thread1',
labelIds: ['DRAFT']
}
}
}))
.mockImplementationOnce(() => Promise.resolve({
data: {
id: 'draft2',
message: {
id: 'msg2',
threadId: 'thread2',
labelIds: ['DRAFT']
}
}
}));
const result = await gmailService.manageDraft({
action: 'read',
email: testEmail
}) as GetDraftsResponse;
expect(result).toHaveProperty('drafts');
expect(result.drafts.length).toBe(2);
expect(result.drafts[0]).toHaveProperty('id', 'draft1');
expect(result.drafts[1]).toHaveProperty('id', 'draft2');
});
it('should send draft', async () => {
(mockGmailClient.users.drafts.send as jest.Mock).mockImplementation(() =>
Promise.resolve({
data: {
id: 'msg1',
threadId: 'thread1',
labelIds: ['SENT']
}
})
);
const result = await gmailService.manageDraft({
action: 'send',
email: testEmail,
draftId: 'draft1'
}) as SendEmailResponse;
expect(result).toHaveProperty('messageId', 'msg1');
expect(result).toHaveProperty('labelIds');
});
});
describe('getWorkspaceGmailSettings', () => {
it('should get settings', async () => {
(mockGmailClient.users.getProfile as jest.Mock).mockImplementation(() =>
Promise.resolve({
data: {
emailAddress: testEmail,
messagesTotal: 100
}
})
);
const result = await gmailService.getWorkspaceGmailSettings({
email: testEmail
});
expect(result.profile.emailAddress).toBe(testEmail);
expect(result.settings).toBeDefined();
});
it('should handle settings fetch error', async () => {
(mockGmailClient.users.getProfile as jest.Mock).mockImplementation(() =>
Promise.reject(new Error('Failed to fetch'))
);
await expect(gmailService.getWorkspaceGmailSettings({
email: testEmail
})).rejects.toThrow();
});
});
});