template-saas/apps/backend/dist/modules/tenants/__tests__/tenants.service.spec.js
rckrdmrd 50a821a415
Some checks failed
CI / Backend CI (push) Has been cancelled
CI / Frontend CI (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / CI Summary (push) Has been cancelled
[SIMCO-V38] feat: Actualizar a SIMCO v3.8.0
- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8
- Actualizaciones de configuracion

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 08:53:08 -06:00

249 lines
11 KiB
JavaScript

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const testing_1 = require("@nestjs/testing");
const typeorm_1 = require("@nestjs/typeorm");
const common_1 = require("@nestjs/common");
const tenants_service_1 = require("../tenants.service");
const tenant_entity_1 = require("../entities/tenant.entity");
describe('TenantsService', () => {
let service;
let tenantRepository;
const mockTenant = {
id: 'tenant-123',
name: 'Test Company',
slug: 'test-company',
domain: 'test.example.com',
logo_url: 'https://example.com/logo.png',
status: 'active',
plan_id: 'plan-123',
trial_ends_at: new Date('2026-02-01'),
settings: { theme: 'dark' },
metadata: { industry: 'tech' },
created_at: new Date('2026-01-01'),
updated_at: new Date('2026-01-01'),
};
beforeEach(async () => {
const module = await testing_1.Test.createTestingModule({
providers: [
tenants_service_1.TenantsService,
{
provide: (0, typeorm_1.getRepositoryToken)(tenant_entity_1.Tenant),
useValue: {
findOne: jest.fn(),
find: jest.fn(),
save: jest.fn(),
create: jest.fn(),
update: jest.fn(),
delete: jest.fn(),
},
},
],
}).compile();
service = module.get(tenants_service_1.TenantsService);
tenantRepository = module.get((0, typeorm_1.getRepositoryToken)(tenant_entity_1.Tenant));
});
afterEach(() => {
jest.clearAllMocks();
});
describe('findOne', () => {
it('should return a tenant by id', async () => {
tenantRepository.findOne.mockResolvedValue(mockTenant);
const result = await service.findOne('tenant-123');
expect(result).toEqual(mockTenant);
expect(tenantRepository.findOne).toHaveBeenCalledWith({
where: { id: 'tenant-123' },
});
});
it('should throw NotFoundException if tenant not found', async () => {
tenantRepository.findOne.mockResolvedValue(null);
await expect(service.findOne('non-existent')).rejects.toThrow(common_1.NotFoundException);
await expect(service.findOne('non-existent')).rejects.toThrow('Tenant no encontrado');
});
it('should handle repository errors', async () => {
tenantRepository.findOne.mockRejectedValue(new Error('DB Error'));
await expect(service.findOne('tenant-123')).rejects.toThrow('DB Error');
});
});
describe('findBySlug', () => {
it('should return a tenant by slug', async () => {
tenantRepository.findOne.mockResolvedValue(mockTenant);
const result = await service.findBySlug('test-company');
expect(result).toEqual(mockTenant);
expect(tenantRepository.findOne).toHaveBeenCalledWith({
where: { slug: 'test-company' },
});
});
it('should return null if tenant not found by slug', async () => {
tenantRepository.findOne.mockResolvedValue(null);
const result = await service.findBySlug('non-existent');
expect(result).toBeNull();
});
it('should handle slugs with special characters', async () => {
tenantRepository.findOne.mockResolvedValue(mockTenant);
await service.findBySlug('company-name-123');
expect(tenantRepository.findOne).toHaveBeenCalledWith({
where: { slug: 'company-name-123' },
});
});
});
describe('create', () => {
const createDto = {
name: 'New Company',
slug: 'new-company',
domain: 'new.example.com',
logo_url: 'https://example.com/new-logo.png',
settings: {
timezone: 'America/Mexico_City',
industry: 'Technology',
},
};
it('should create a new tenant successfully', async () => {
const createdTenant = {
...mockTenant,
id: 'new-tenant-id',
name: createDto.name,
slug: createDto.slug,
domain: createDto.domain || null,
logo_url: createDto.logo_url || null,
status: 'trial',
settings: createDto.settings || {},
};
tenantRepository.findOne.mockResolvedValue(null);
tenantRepository.create.mockReturnValue(createdTenant);
tenantRepository.save.mockResolvedValue(createdTenant);
const result = await service.create(createDto);
expect(result).toEqual(createdTenant);
expect(tenantRepository.findOne).toHaveBeenCalledWith({
where: { slug: createDto.slug },
});
expect(tenantRepository.create).toHaveBeenCalledWith(expect.objectContaining({
name: createDto.name,
slug: createDto.slug,
domain: createDto.domain,
logo_url: createDto.logo_url,
status: 'trial',
settings: createDto.settings,
}));
expect(tenantRepository.save).toHaveBeenCalled();
});
it('should throw ConflictException if slug already exists', async () => {
tenantRepository.findOne.mockResolvedValue(mockTenant);
await expect(service.create(createDto)).rejects.toThrow(common_1.ConflictException);
await expect(service.create(createDto)).rejects.toThrow('Ya existe un tenant con este slug');
});
it('should create tenant with empty settings if not provided', async () => {
const dtoWithoutSettings = {
name: 'Minimal Company',
slug: 'minimal-company',
};
const createdTenant = {
...mockTenant,
name: dtoWithoutSettings.name,
slug: dtoWithoutSettings.slug,
domain: null,
logo_url: null,
settings: {},
status: 'trial',
};
tenantRepository.findOne.mockResolvedValue(null);
tenantRepository.create.mockReturnValue(createdTenant);
tenantRepository.save.mockResolvedValue(createdTenant);
const result = await service.create(dtoWithoutSettings);
expect(result.settings).toEqual({});
expect(result.domain).toBeNull();
expect(result.logo_url).toBeNull();
});
it('should set trial_ends_at to 14 days from now', async () => {
const dtoMinimal = {
name: 'Trial Company',
slug: 'trial-company',
};
const createdTenant = {
...mockTenant,
name: dtoMinimal.name,
slug: dtoMinimal.slug,
status: 'trial',
trial_ends_at: new Date(Date.now() + 14 * 24 * 60 * 60 * 1000),
};
tenantRepository.findOne.mockResolvedValue(null);
tenantRepository.create.mockReturnValue(createdTenant);
tenantRepository.save.mockResolvedValue(createdTenant);
await service.create(dtoMinimal);
expect(tenantRepository.create).toHaveBeenCalledWith(expect.objectContaining({
status: 'trial',
trial_ends_at: expect.any(Date),
}));
});
});
describe('update', () => {
const updateDto = {
name: 'Updated Company',
logo_url: 'https://example.com/updated-logo.png',
settings: {
timezone: 'America/New_York',
},
};
it('should update tenant successfully', async () => {
const updatedTenant = {
...mockTenant,
name: updateDto.name,
logo_url: updateDto.logo_url,
settings: { ...mockTenant.settings, ...updateDto.settings },
};
tenantRepository.findOne.mockResolvedValue(mockTenant);
tenantRepository.save.mockResolvedValue(updatedTenant);
const result = await service.update('tenant-123', updateDto);
expect(result.name).toBe(updateDto.name);
expect(result.logo_url).toBe(updateDto.logo_url);
expect(result.settings).toEqual(expect.objectContaining({ timezone: 'America/New_York' }));
expect(tenantRepository.save).toHaveBeenCalled();
});
it('should throw NotFoundException if tenant not found', async () => {
tenantRepository.findOne.mockResolvedValue(null);
await expect(service.update('non-existent', updateDto)).rejects.toThrow(common_1.NotFoundException);
});
it('should only update provided fields', async () => {
const partialUpdate = {
name: 'Only Name Updated',
};
tenantRepository.findOne.mockResolvedValue({ ...mockTenant });
tenantRepository.save.mockImplementation((tenant) => Promise.resolve(tenant));
const result = await service.update('tenant-123', partialUpdate);
expect(result.name).toBe('Only Name Updated');
expect(result.logo_url).toBe(mockTenant.logo_url);
expect(result.settings).toEqual(mockTenant.settings);
});
it('should merge settings with existing settings', async () => {
const settingsUpdate = {
settings: {
industry: 'Healthcare',
},
};
const tenantWithSettings = {
...mockTenant,
settings: { theme: 'dark', timezone: 'America/Mexico_City' },
};
tenantRepository.findOne.mockResolvedValue({ ...tenantWithSettings });
tenantRepository.save.mockImplementation((tenant) => Promise.resolve(tenant));
const result = await service.update('tenant-123', settingsUpdate);
expect(result.settings).toEqual({
theme: 'dark',
timezone: 'America/Mexico_City',
industry: 'Healthcare',
});
});
});
describe('slugExists', () => {
it('should return true if slug exists', async () => {
tenantRepository.findOne.mockResolvedValue(mockTenant);
const result = await service.slugExists('test-company');
expect(result).toBe(true);
});
it('should return false if slug does not exist', async () => {
tenantRepository.findOne.mockResolvedValue(null);
const result = await service.slugExists('non-existent');
expect(result).toBe(false);
});
});
});
//# sourceMappingURL=tenants.service.spec.js.map