Skip to main content
Glama
newsletterService.test.js6.6 kB
import { describe, it, expect, vi, beforeEach } from 'vitest'; import { mockDotenv } from '../../__tests__/helpers/testUtils.js'; import { createMockContextLogger } from '../../__tests__/helpers/mockLogger.js'; // Mock dotenv vi.mock('dotenv', () => mockDotenv()); // Mock logger vi.mock('../../utils/logger.js', () => ({ createContextLogger: createMockContextLogger(), })); // Mock ghostServiceImproved functions vi.mock('../ghostServiceImproved.js', () => ({ createNewsletter: vi.fn(), })); // Import after mocks are set up import { createNewsletterService } from '../newsletterService.js'; import { createNewsletter } from '../ghostServiceImproved.js'; describe('newsletterService', () => { beforeEach(() => { vi.clearAllMocks(); }); describe('createNewsletterService - validation', () => { it('should accept valid input and create a newsletter', async () => { const validInput = { name: 'Weekly Newsletter', }; const expectedNewsletter = { id: '1', name: 'Weekly Newsletter', slug: 'weekly-newsletter' }; createNewsletter.mockResolvedValue(expectedNewsletter); const result = await createNewsletterService(validInput); expect(result).toEqual(expectedNewsletter); expect(createNewsletter).toHaveBeenCalledWith( expect.objectContaining({ name: 'Weekly Newsletter', }) ); }); it('should reject input with missing name', async () => { const invalidInput = {}; await expect(createNewsletterService(invalidInput)).rejects.toThrow( 'Invalid newsletter input: "name" is required' ); expect(createNewsletter).not.toHaveBeenCalled(); }); it('should accept all optional fields', async () => { const fullInput = { name: 'Monthly Newsletter', description: 'Our monthly updates', sender_name: 'John Doe', sender_email: 'john@example.com', sender_reply_to: 'newsletter', subscribe_on_signup: true, show_header_icon: true, show_header_title: false, }; const expectedNewsletter = { id: '1', ...fullInput }; createNewsletter.mockResolvedValue(expectedNewsletter); const result = await createNewsletterService(fullInput); expect(result).toEqual(expectedNewsletter); expect(createNewsletter).toHaveBeenCalledWith(expect.objectContaining(fullInput)); }); it('should validate sender_email is a valid email', async () => { const invalidInput = { name: 'Newsletter', sender_email: 'not-an-email', }; await expect(createNewsletterService(invalidInput)).rejects.toThrow( 'Invalid newsletter input:' ); expect(createNewsletter).not.toHaveBeenCalled(); }); it('should accept valid sender_email', async () => { const validInput = { name: 'Newsletter', sender_email: 'valid@example.com', }; createNewsletter.mockResolvedValue({ id: '1', name: 'Newsletter' }); await createNewsletterService(validInput); expect(createNewsletter).toHaveBeenCalledWith( expect.objectContaining({ sender_email: 'valid@example.com', }) ); }); it('should validate sender_reply_to enum values', async () => { const invalidInput = { name: 'Newsletter', sender_reply_to: 'invalid', }; await expect(createNewsletterService(invalidInput)).rejects.toThrow( 'Invalid newsletter input:' ); expect(createNewsletter).not.toHaveBeenCalled(); }); it('should accept valid sender_reply_to values', async () => { const validValues = ['newsletter', 'support']; createNewsletter.mockResolvedValue({ id: '1', name: 'Newsletter' }); for (const value of validValues) { const input = { name: 'Newsletter', sender_reply_to: value, }; await createNewsletterService(input); expect(createNewsletter).toHaveBeenCalledWith( expect.objectContaining({ sender_reply_to: value }) ); vi.clearAllMocks(); } }); it('should validate subscribe_on_signup is boolean', async () => { const invalidInput = { name: 'Newsletter', subscribe_on_signup: 'yes', }; await expect(createNewsletterService(invalidInput)).rejects.toThrow( 'Invalid newsletter input:' ); expect(createNewsletter).not.toHaveBeenCalled(); }); it('should validate show_header_icon is boolean', async () => { const invalidInput = { name: 'Newsletter', show_header_icon: 'true', }; await expect(createNewsletterService(invalidInput)).rejects.toThrow( 'Invalid newsletter input:' ); expect(createNewsletter).not.toHaveBeenCalled(); }); it('should validate show_header_title is boolean', async () => { const invalidInput = { name: 'Newsletter', show_header_title: 1, }; await expect(createNewsletterService(invalidInput)).rejects.toThrow( 'Invalid newsletter input:' ); expect(createNewsletter).not.toHaveBeenCalled(); }); }); describe('createNewsletterService - defaults and transformations', () => { beforeEach(() => { createNewsletter.mockResolvedValue({ id: '1', name: 'Newsletter' }); }); it('should pass through all provided fields', async () => { const input = { name: 'Newsletter', description: 'Test description', sender_name: 'Sender', sender_email: 'sender@example.com', sender_reply_to: 'support', subscribe_on_signup: false, show_header_icon: false, show_header_title: true, }; await createNewsletterService(input); expect(createNewsletter).toHaveBeenCalledWith(expect.objectContaining(input)); }); it('should handle minimal input', async () => { const input = { name: 'Simple Newsletter', }; await createNewsletterService(input); expect(createNewsletter).toHaveBeenCalledWith( expect.objectContaining({ name: 'Simple Newsletter', }) ); }); }); describe('createNewsletterService - error handling', () => { it('should propagate errors from ghostServiceImproved', async () => { const input = { name: 'Newsletter', }; createNewsletter.mockRejectedValue(new Error('Ghost API error')); await expect(createNewsletterService(input)).rejects.toThrow('Ghost API error'); }); }); });

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/jgardner04/Ghost-MCP-Server'

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