-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
562 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,144 @@ | ||
import { describe, it } from 'vitest' | ||
import { describe, it, expect } from 'vitest' | ||
import { Email, type EmailOptions, type User } from '../../src/email' | ||
|
||
describe('Email', () => { | ||
it('can create a new email', async () => {}) | ||
describe('constructor', () => { | ||
it('should create an email with minimal options', () => { | ||
const options: EmailOptions = { | ||
from: '[email protected]', | ||
to: '[email protected]', | ||
subject: 'Test Subject', | ||
text: 'Test content' | ||
} | ||
const email = new Email(options) | ||
expect(email.from).toEqual({ email: '[email protected]' }) | ||
expect(email.to).toEqual([{ email: '[email protected]' }]) | ||
expect(email.subject).toBe('Test Subject') | ||
expect(email.text).toBe('Test content') | ||
}) | ||
|
||
it('should handle complex user objects', () => { | ||
const options: EmailOptions = { | ||
from: { name: 'Sender Name', email: '[email protected]' }, | ||
to: [ | ||
{ name: 'Recipient1', email: '[email protected]' }, | ||
{ name: 'Recipient2', email: '[email protected]' } | ||
], | ||
subject: 'Test Subject', | ||
html: '<p>Test content</p>' | ||
} | ||
const email = new Email(options) | ||
expect(email.from).toEqual({ name: 'Sender Name', email: '[email protected]' }) | ||
expect(email.to).toEqual([ | ||
{ name: 'Recipient1', email: '[email protected]' }, | ||
{ name: 'Recipient2', email: '[email protected]' } | ||
]) | ||
}) | ||
|
||
it('should throw error if neither text nor html is provided', () => { | ||
const options: EmailOptions = { | ||
from: '[email protected]', | ||
to: '[email protected]', | ||
subject: 'Test Subject' | ||
} | ||
expect(() => new Email(options)).toThrow() | ||
}) | ||
}) | ||
|
||
describe('getEmailData', () => { | ||
it('should generate correct email data with text content', () => { | ||
const email = new Email({ | ||
from: '[email protected]', | ||
to: '[email protected]', | ||
subject: 'Test Subject', | ||
text: 'Hello World' | ||
}) | ||
const data = email.getEmailData() | ||
expect(data).toContain('From: [email protected]') | ||
expect(data).toContain('To: [email protected]') | ||
expect(data).toContain('Subject: Test Subject') | ||
expect(data).toContain('Content-Type: text/plain') | ||
expect(data).toContain('Hello World') | ||
}) | ||
|
||
it('should generate correct email data with HTML content', () => { | ||
const email = new Email({ | ||
from: '[email protected]', | ||
to: '[email protected]', | ||
subject: 'Test Subject', | ||
html: '<p>Hello World</p>' | ||
}) | ||
const data = email.getEmailData() | ||
expect(data).toContain('Content-Type: text/html') | ||
expect(data).toContain('<p>Hello World</p>') | ||
}) | ||
|
||
it('should include CC and BCC headers when provided', () => { | ||
const email = new Email({ | ||
from: '[email protected]', | ||
to: '[email protected]', | ||
// @ts-expect-error it works | ||
cc: ['[email protected]', { name: 'CC2', email: '[email protected]' }], | ||
bcc: '[email protected]', | ||
subject: 'Test Subject', | ||
text: 'Hello World' | ||
}) | ||
const data = email.getEmailData() | ||
expect(data).toContain('CC: [email protected], CC2 <[email protected]>') | ||
expect(data).toContain('BCC: [email protected]') | ||
}) | ||
|
||
it('should include Reply-To when provided', () => { | ||
const email = new Email({ | ||
from: '[email protected]', | ||
to: '[email protected]', | ||
reply: { name: 'Reply Name', email: '[email protected]' }, | ||
subject: 'Test Subject', | ||
text: 'Hello World' | ||
}) | ||
const data = email.getEmailData() | ||
expect(data).toContain('Reply-To: Reply Name <[email protected]>') | ||
}) | ||
|
||
it('should include custom headers when provided', () => { | ||
const email = new Email({ | ||
from: '[email protected]', | ||
to: '[email protected]', | ||
subject: 'Test Subject', | ||
text: 'Hello World', | ||
headers: { | ||
'X-Custom-Header': 'Custom Value' | ||
} | ||
}) | ||
const data = email.getEmailData() | ||
expect(data).toContain('X-Custom-Header: Custom Value') | ||
}) | ||
}) | ||
|
||
describe('sent promise', () => { | ||
it('should resolve when setSent is called', async () => { | ||
const email = new Email({ | ||
from: '[email protected]', | ||
to: '[email protected]', | ||
subject: 'Test Subject', | ||
text: 'Hello World' | ||
}) | ||
|
||
setTimeout(() => email.setSent(), 0) | ||
await expect(email.sent).resolves.toBeUndefined() | ||
}) | ||
|
||
it('should reject when setSentError is called', async () => { | ||
const email = new Email({ | ||
from: '[email protected]', | ||
to: '[email protected]', | ||
subject: 'Test Subject', | ||
text: 'Hello World' | ||
}) | ||
|
||
const error = new Error('Test error') | ||
setTimeout(() => email.setSentError(error), 0) | ||
await expect(email.sent).rejects.toBe(error) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' | ||
import Logger, { LogLevel } from '../../src/logger' | ||
|
||
describe('Logger', () => { | ||
let consoleSpy: { | ||
debug: any; | ||
info: any; | ||
warn: any; | ||
error: any; | ||
} | ||
|
||
beforeEach(() => { | ||
// Mock console methods | ||
consoleSpy = { | ||
debug: vi.spyOn(console, 'debug').mockImplementation(() => {}), | ||
info: vi.spyOn(console, 'info').mockImplementation(() => {}), | ||
warn: vi.spyOn(console, 'warn').mockImplementation(() => {}), | ||
error: vi.spyOn(console, 'error').mockImplementation(() => {}) | ||
} | ||
}) | ||
|
||
afterEach(() => { | ||
// Clear all mocks | ||
vi.clearAllMocks() | ||
}) | ||
|
||
describe('constructor', () => { | ||
it('should create logger with default level INFO', () => { | ||
const logger = new Logger(undefined, '[Test]') | ||
expect(logger).toBeInstanceOf(Logger) | ||
}) | ||
|
||
it('should create logger with specified level', () => { | ||
const logger = new Logger(LogLevel.DEBUG, '[Test]') | ||
expect(logger).toBeInstanceOf(Logger) | ||
}) | ||
}) | ||
|
||
describe('logging methods', () => { | ||
it('should log debug messages when level is DEBUG', () => { | ||
const logger = new Logger(LogLevel.DEBUG, '[Test]') | ||
const message = 'debug message' | ||
logger.debug(message) | ||
expect(consoleSpy.debug).toHaveBeenCalledWith('[Test]debug message') | ||
}) | ||
|
||
it('should not log debug messages when level is INFO', () => { | ||
const logger = new Logger(LogLevel.INFO, '[Test]') | ||
logger.debug('debug message') | ||
expect(consoleSpy.debug).not.toHaveBeenCalled() | ||
}) | ||
|
||
it('should log info messages when level is INFO', () => { | ||
const logger = new Logger(LogLevel.INFO, '[Test]') | ||
const message = 'info message' | ||
logger.info(message) | ||
expect(consoleSpy.info).toHaveBeenCalledWith('[Test]info message') | ||
}) | ||
|
||
it('should not log info messages when level is WARN', () => { | ||
const logger = new Logger(LogLevel.WARN, '[Test]') | ||
logger.info('info message') | ||
expect(consoleSpy.info).not.toHaveBeenCalled() | ||
}) | ||
|
||
it('should log warn messages when level is WARN', () => { | ||
const logger = new Logger(LogLevel.WARN, '[Test]') | ||
const message = 'warn message' | ||
logger.warn(message) | ||
expect(consoleSpy.warn).toHaveBeenCalledWith('[Test]warn message') | ||
}) | ||
|
||
it('should not log warn messages when level is ERROR', () => { | ||
const logger = new Logger(LogLevel.ERROR, '[Test]') | ||
logger.warn('warn message') | ||
expect(consoleSpy.warn).not.toHaveBeenCalled() | ||
}) | ||
|
||
it('should log error messages when level is ERROR', () => { | ||
const logger = new Logger(LogLevel.ERROR, '[Test]') | ||
const message = 'error message' | ||
logger.error(message) | ||
expect(consoleSpy.error).toHaveBeenCalledWith('[Test]error message') | ||
}) | ||
|
||
it('should not log any messages when level is NONE', () => { | ||
const logger = new Logger(LogLevel.NONE, '[Test]') | ||
logger.debug('debug message') | ||
logger.info('info message') | ||
logger.warn('warn message') | ||
logger.error('error message') | ||
expect(consoleSpy.debug).not.toHaveBeenCalled() | ||
expect(consoleSpy.info).not.toHaveBeenCalled() | ||
expect(consoleSpy.warn).not.toHaveBeenCalled() | ||
expect(consoleSpy.error).not.toHaveBeenCalled() | ||
}) | ||
}) | ||
|
||
describe('log formatting', () => { | ||
it('should format message with additional arguments', () => { | ||
const logger = new Logger(LogLevel.INFO, '[Test]') | ||
logger.info('message with %s', 'argument') | ||
expect(consoleSpy.info).toHaveBeenCalledWith('[Test]message with %s', 'argument') | ||
}) | ||
|
||
it('should handle multiple arguments', () => { | ||
const logger = new Logger(LogLevel.INFO, '[Test]') | ||
logger.info('message with %s and %d', 'string', 42) | ||
expect(consoleSpy.info).toHaveBeenCalledWith('[Test]message with %s and %d', 'string', 42) | ||
}) | ||
|
||
it('should handle objects in arguments', () => { | ||
const logger = new Logger(LogLevel.INFO, '[Test]') | ||
const obj = { key: 'value' } | ||
logger.info('message with object:', obj) | ||
expect(consoleSpy.info).toHaveBeenCalledWith('[Test]message with object:', obj) | ||
}) | ||
}) | ||
}) |
Oops, something went wrong.