allowlist.service.spec.tsβ’6.84 kB
import { describe, it, expect, beforeEach, vi } from 'vitest'
import { Test, TestingModule } from '@nestjs/testing'
import { ConfigService } from '@nestjs/config'
import { AllowlistService } from './allowlist.service'
describe('AllowlistService', () => {
let service: AllowlistService
let configService: Pick<ConfigService, 'get'>
beforeEach(async () => {
// Note: Service instance is created fresh in each test with proper mocking
configService = {
get: vi.fn(),
}
})
describe('initialization', () => {
it('should parse comma-separated emails from config', async () => {
const mockGet = vi
.spyOn(configService, 'get')
.mockReturnValue('user1@example.com,user2@example.com')
const module: TestingModule = await Test.createTestingModule({
providers: [
AllowlistService,
{
provide: ConfigService,
useValue: configService,
},
],
}).compile()
const newService = module.get<AllowlistService>(AllowlistService)
expect(newService.getCount()).toBe(2)
expect(newService.getAllowedEmails()).toContain('user1@example.com')
expect(newService.getAllowedEmails()).toContain('user2@example.com')
expect(mockGet).toHaveBeenCalledWith('ALLOWED_EMAILS', '')
})
it('should handle empty email list', async () => {
vi.spyOn(configService, 'get').mockReturnValue('')
const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
const module: TestingModule = await Test.createTestingModule({
providers: [
AllowlistService,
{
provide: ConfigService,
useValue: configService,
},
],
}).compile()
const newService = module.get<AllowlistService>(AllowlistService)
expect(newService.getCount()).toBe(0)
expect(consoleWarnSpy).toHaveBeenCalledWith(
'WARNING: ALLOWED_EMAILS is empty. No users will be able to authenticate.',
)
consoleWarnSpy.mockRestore()
})
it('should trim whitespace from emails', async () => {
vi.spyOn(configService, 'get').mockReturnValue(' user1@example.com , user2@example.com ')
const module: TestingModule = await Test.createTestingModule({
providers: [
AllowlistService,
{
provide: ConfigService,
useValue: configService,
},
],
}).compile()
const newService = module.get<AllowlistService>(AllowlistService)
expect(newService.getAllowedEmails()).toContain('user1@example.com')
expect(newService.getAllowedEmails()).toContain('user2@example.com')
})
it('should convert emails to lowercase', async () => {
vi.spyOn(configService, 'get').mockReturnValue('User1@Example.COM,USER2@EXAMPLE.COM')
const module: TestingModule = await Test.createTestingModule({
providers: [
AllowlistService,
{
provide: ConfigService,
useValue: configService,
},
],
}).compile()
const newService = module.get<AllowlistService>(AllowlistService)
expect(newService.getAllowedEmails()).toContain('user1@example.com')
expect(newService.getAllowedEmails()).toContain('user2@example.com')
})
})
describe('isEmailAllowed', () => {
beforeEach(async () => {
vi.spyOn(configService, 'get').mockReturnValue('user1@example.com,user2@example.com')
const module: TestingModule = await Test.createTestingModule({
providers: [
AllowlistService,
{
provide: ConfigService,
useValue: configService,
},
],
}).compile()
service = module.get<AllowlistService>(AllowlistService)
})
it('should return true for allowed email', () => {
expect(service.isEmailAllowed('user1@example.com')).toBe(true)
expect(service.isEmailAllowed('user2@example.com')).toBe(true)
})
it('should return false for non-allowed email', () => {
expect(service.isEmailAllowed('user3@example.com')).toBe(false)
expect(service.isEmailAllowed('hacker@evil.com')).toBe(false)
})
it('should be case-insensitive', () => {
expect(service.isEmailAllowed('USER1@EXAMPLE.COM')).toBe(true)
expect(service.isEmailAllowed('User2@Example.Com')).toBe(true)
})
it('should return false for empty email', () => {
expect(service.isEmailAllowed('')).toBe(false)
})
it('should return false for null/undefined email', () => {
expect(service.isEmailAllowed(null)).toBe(false)
expect(service.isEmailAllowed(undefined)).toBe(false)
})
it('should handle emails with whitespace', () => {
expect(service.isEmailAllowed(' user1@example.com ')).toBe(true)
})
})
describe('getAllowedEmails', () => {
it('should return array of allowed emails', async () => {
vi.spyOn(configService, 'get').mockReturnValue('user1@example.com,user2@example.com')
const module: TestingModule = await Test.createTestingModule({
providers: [
AllowlistService,
{
provide: ConfigService,
useValue: configService,
},
],
}).compile()
const newService = module.get<AllowlistService>(AllowlistService)
const emails = newService.getAllowedEmails()
expect(Array.isArray(emails)).toBe(true)
expect(emails).toHaveLength(2)
expect(emails).toContain('user1@example.com')
expect(emails).toContain('user2@example.com')
})
})
describe('getCount', () => {
it('should return correct count of allowed emails', async () => {
vi.spyOn(configService, 'get').mockReturnValue(
'user1@example.com,user2@example.com,user3@example.com',
)
const module: TestingModule = await Test.createTestingModule({
providers: [
AllowlistService,
{
provide: ConfigService,
useValue: configService,
},
],
}).compile()
const newService = module.get<AllowlistService>(AllowlistService)
expect(newService.getCount()).toBe(3)
})
it('should return 0 for empty list', async () => {
vi.spyOn(configService, 'get').mockReturnValue('')
const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})
const module: TestingModule = await Test.createTestingModule({
providers: [
AllowlistService,
{
provide: ConfigService,
useValue: configService,
},
],
}).compile()
const newService = module.get<AllowlistService>(AllowlistService)
expect(newService.getCount()).toBe(0)
consoleWarnSpy.mockRestore()
})
})
})