"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 rbac_service_1 = require("../services/rbac.service");
const entities_1 = require("../entities");
describe('RbacService', () => {
    let service;
    let roleRepository;
    let permissionRepository;
    let userRoleRepository;
    let rolePermissionRepository;
    const mockRole = {
        id: 'role-123',
        tenant_id: 'tenant-123',
        name: 'Admin',
        code: 'admin',
        description: 'Administrator role',
        is_system: false,
        is_active: true,
        metadata: null,
        created_at: new Date('2026-01-01'),
        updated_at: new Date('2026-01-01'),
    };
    const mockSystemRole = {
        ...mockRole,
        id: 'role-system',
        code: 'owner',
        name: 'Owner',
        is_system: true,
    };
    const mockPermission = {
        id: 'perm-123',
        code: 'users:read',
        name: 'Read Users',
        description: 'Can read user data',
        category: 'users',
        is_sensitive: false,
        requires_owner: false,
        created_at: new Date('2026-01-01'),
    };
    const mockUserRole = {
        id: 'ur-123',
        user_id: 'user-123',
        role_id: 'role-123',
        tenant_id: 'tenant-123',
        assigned_by: 'admin-123',
        created_at: new Date('2026-01-01'),
    };
    const mockRolePermission = {
        id: 'rp-123',
        role_id: 'role-123',
        permission_id: 'perm-123',
        created_at: new Date('2026-01-01'),
    };
    beforeEach(async () => {
        const module = await testing_1.Test.createTestingModule({
            providers: [
                rbac_service_1.RbacService,
                {
                    provide: (0, typeorm_1.getRepositoryToken)(entities_1.Role),
                    useValue: {
                        findOne: jest.fn(),
                        find: jest.fn(),
                        save: jest.fn(),
                        create: jest.fn(),
                        delete: jest.fn(),
                        count: jest.fn(),
                    },
                },
                {
                    provide: (0, typeorm_1.getRepositoryToken)(entities_1.Permission),
                    useValue: {
                        findOne: jest.fn(),
                        find: jest.fn(),
                        save: jest.fn(),
                    },
                },
                {
                    provide: (0, typeorm_1.getRepositoryToken)(entities_1.UserRole),
                    useValue: {
                        findOne: jest.fn(),
                        find: jest.fn(),
                        save: jest.fn(),
                        create: jest.fn(),
                        delete: jest.fn(),
                        count: jest.fn(),
                    },
                },
                {
                    provide: (0, typeorm_1.getRepositoryToken)(entities_1.RolePermission),
                    useValue: {
                        findOne: jest.fn(),
                        find: jest.fn(),
                        save: jest.fn(),
                        delete: jest.fn(),
                    },
                },
            ],
        }).compile();
        service = module.get(rbac_service_1.RbacService);
        roleRepository = module.get((0, typeorm_1.getRepositoryToken)(entities_1.Role));
        permissionRepository = module.get((0, typeorm_1.getRepositoryToken)(entities_1.Permission));
        userRoleRepository = module.get((0, typeorm_1.getRepositoryToken)(entities_1.UserRole));
        rolePermissionRepository = module.get((0, typeorm_1.getRepositoryToken)(entities_1.RolePermission));
    });
    afterEach(() => {
        jest.clearAllMocks();
    });
    describe('createRole', () => {
        const createDto = {
            name: 'Manager',
            code: 'manager',
            description: 'Manager role',
            permissions: ['users:read'],
        };
        it('should create a new role', async () => {
            const createdRole = { ...mockRole, ...createDto, id: 'new-role-123' };
            roleRepository.findOne
                .mockResolvedValueOnce(null)
                .mockResolvedValueOnce(createdRole);
            roleRepository.create.mockReturnValue(createdRole);
            roleRepository.save.mockResolvedValue(createdRole);
            permissionRepository.find.mockResolvedValue([mockPermission]);
            rolePermissionRepository.delete.mockResolvedValue({ affected: 0, raw: {} });
            rolePermissionRepository.save.mockResolvedValue([mockRolePermission]);
            const result = await service.createRole(createDto, 'tenant-123');
            expect(result.name).toBe('Manager');
            expect(roleRepository.create).toHaveBeenCalled();
            expect(roleRepository.save).toHaveBeenCalled();
        });
        it('should throw ConflictException if role code exists', async () => {
            roleRepository.findOne.mockResolvedValue(mockRole);
            await expect(service.createRole(createDto, 'tenant-123')).rejects.toThrow(common_1.ConflictException);
        });
    });
    describe('updateRole', () => {
        const updateDto = { name: 'Updated Admin', description: 'Updated description' };
        it('should update a role', async () => {
            const roleCopy = { ...mockRole };
            roleRepository.findOne.mockResolvedValue(roleCopy);
            roleRepository.save.mockResolvedValue({ ...roleCopy, ...updateDto });
            const result = await service.updateRole('role-123', updateDto, 'tenant-123');
            expect(result.name).toBe('Updated Admin');
            expect(roleRepository.save).toHaveBeenCalled();
        });
        it('should throw NotFoundException if role not found', async () => {
            roleRepository.findOne.mockResolvedValue(null);
            await expect(service.updateRole('non-existent', updateDto, 'tenant-123')).rejects.toThrow(common_1.NotFoundException);
        });
        it('should throw ForbiddenException for system role', async () => {
            roleRepository.findOne.mockResolvedValue(mockSystemRole);
            await expect(service.updateRole('role-system', updateDto, 'tenant-123')).rejects.toThrow(common_1.ForbiddenException);
        });
    });
    describe('deleteRole', () => {
        it('should delete a role', async () => {
            roleRepository.findOne.mockResolvedValue(mockRole);
            userRoleRepository.count.mockResolvedValue(0);
            rolePermissionRepository.delete.mockResolvedValue({ affected: 1, raw: {} });
            roleRepository.delete.mockResolvedValue({ affected: 1, raw: {} });
            await service.deleteRole('role-123', 'tenant-123');
            expect(roleRepository.delete).toHaveBeenCalledWith({ id: 'role-123' });
        });
        it('should throw NotFoundException if role not found', async () => {
            roleRepository.findOne.mockResolvedValue(null);
            await expect(service.deleteRole('non-existent', 'tenant-123')).rejects.toThrow(common_1.NotFoundException);
        });
        it('should throw ForbiddenException for system role', async () => {
            roleRepository.findOne.mockResolvedValue(mockSystemRole);
            await expect(service.deleteRole('role-system', 'tenant-123')).rejects.toThrow(common_1.ForbiddenException);
        });
        it('should throw ConflictException if role is assigned to users', async () => {
            roleRepository.findOne.mockResolvedValue(mockRole);
            userRoleRepository.count.mockResolvedValue(5);
            await expect(service.deleteRole('role-123', 'tenant-123')).rejects.toThrow(common_1.ConflictException);
        });
    });
    describe('findAllRoles', () => {
        it('should return all active roles for tenant', async () => {
            roleRepository.find.mockResolvedValue([mockRole]);
            const result = await service.findAllRoles('tenant-123');
            expect(result).toEqual([mockRole]);
            expect(roleRepository.find).toHaveBeenCalledWith({
                where: { tenant_id: 'tenant-123', is_active: true },
                order: { is_system: 'DESC', name: 'ASC' },
            });
        });
    });
    describe('findRoleById', () => {
        it('should return a role by id', async () => {
            roleRepository.findOne.mockResolvedValue(mockRole);
            const result = await service.findRoleById('role-123', 'tenant-123');
            expect(result).toEqual(mockRole);
        });
        it('should throw NotFoundException if role not found', async () => {
            roleRepository.findOne.mockResolvedValue(null);
            await expect(service.findRoleById('non-existent', 'tenant-123')).rejects.toThrow(common_1.NotFoundException);
        });
    });
    describe('findAllPermissions', () => {
        it('should return all permissions', async () => {
            permissionRepository.find.mockResolvedValue([mockPermission]);
            const result = await service.findAllPermissions();
            expect(result).toEqual([mockPermission]);
            expect(permissionRepository.find).toHaveBeenCalledWith({
                order: { category: 'ASC', code: 'ASC' },
            });
        });
    });
    describe('assignRoleToUser', () => {
        const assignDto = { userId: 'user-123', roleId: 'role-123' };
        it('should assign a role to a user', async () => {
            roleRepository.findOne.mockResolvedValue(mockRole);
            userRoleRepository.findOne.mockResolvedValue(null);
            userRoleRepository.create.mockReturnValue(mockUserRole);
            userRoleRepository.save.mockResolvedValue(mockUserRole);
            const result = await service.assignRoleToUser(assignDto, 'tenant-123', 'admin-123');
            expect(result).toEqual(mockUserRole);
            expect(userRoleRepository.save).toHaveBeenCalled();
        });
        it('should throw ConflictException if role already assigned', async () => {
            roleRepository.findOne.mockResolvedValue(mockRole);
            userRoleRepository.findOne.mockResolvedValue(mockUserRole);
            await expect(service.assignRoleToUser(assignDto, 'tenant-123', 'admin-123')).rejects.toThrow(common_1.ConflictException);
        });
        it('should throw NotFoundException if role not found', async () => {
            roleRepository.findOne.mockResolvedValue(null);
            await expect(service.assignRoleToUser(assignDto, 'tenant-123', 'admin-123')).rejects.toThrow(common_1.NotFoundException);
        });
    });
    describe('removeRoleFromUser', () => {
        it('should remove a role from a user', async () => {
            userRoleRepository.delete.mockResolvedValue({ affected: 1, raw: {} });
            await service.removeRoleFromUser('user-123', 'role-123', 'tenant-123');
            expect(userRoleRepository.delete).toHaveBeenCalledWith({
                user_id: 'user-123',
                role_id: 'role-123',
                tenant_id: 'tenant-123',
            });
        });
        it('should throw NotFoundException if assignment not found', async () => {
            userRoleRepository.delete.mockResolvedValue({ affected: 0, raw: {} });
            await expect(service.removeRoleFromUser('user-123', 'role-123', 'tenant-123')).rejects.toThrow(common_1.NotFoundException);
        });
    });
    describe('getUserRoles', () => {
        it('should return all roles for a user', async () => {
            userRoleRepository.find.mockResolvedValue([mockUserRole]);
            roleRepository.find.mockResolvedValue([mockRole]);
            const result = await service.getUserRoles('user-123', 'tenant-123');
            expect(result).toEqual([mockRole]);
        });
        it('should return empty array if user has no roles', async () => {
            userRoleRepository.find.mockResolvedValue([]);
            const result = await service.getUserRoles('user-123', 'tenant-123');
            expect(result).toEqual([]);
        });
    });
    describe('getUserPermissions', () => {
        it('should return all permissions for a user', async () => {
            userRoleRepository.find.mockResolvedValue([mockUserRole]);
            roleRepository.find.mockResolvedValue([mockRole]);
            rolePermissionRepository.find.mockResolvedValue([mockRolePermission]);
            permissionRepository.find.mockResolvedValue([mockPermission]);
            const result = await service.getUserPermissions('user-123', 'tenant-123');
            expect(result).toEqual([mockPermission]);
        });
        it('should return empty array if user has no roles', async () => {
            userRoleRepository.find.mockResolvedValue([]);
            const result = await service.getUserPermissions('user-123', 'tenant-123');
            expect(result).toEqual([]);
        });
    });
    describe('userHasPermission', () => {
        it('should return true if user has permission', async () => {
            userRoleRepository.find.mockResolvedValue([mockUserRole]);
            roleRepository.find.mockResolvedValue([mockRole]);
            rolePermissionRepository.find.mockResolvedValue([mockRolePermission]);
            permissionRepository.find.mockResolvedValue([mockPermission]);
            const result = await service.userHasPermission('user-123', 'tenant-123', 'users:read');
            expect(result).toBe(true);
        });
        it('should return false if user lacks permission', async () => {
            userRoleRepository.find.mockResolvedValue([mockUserRole]);
            roleRepository.find.mockResolvedValue([mockRole]);
            rolePermissionRepository.find.mockResolvedValue([mockRolePermission]);
            permissionRepository.find.mockResolvedValue([mockPermission]);
            const result = await service.userHasPermission('user-123', 'tenant-123', 'users:delete');
            expect(result).toBe(false);
        });
    });
    describe('userHasRole', () => {
        it('should return true if user has role', async () => {
            userRoleRepository.find.mockResolvedValue([mockUserRole]);
            roleRepository.find.mockResolvedValue([mockRole]);
            const result = await service.userHasRole('user-123', 'tenant-123', 'admin');
            expect(result).toBe(true);
        });
        it('should return false if user lacks role', async () => {
            userRoleRepository.find.mockResolvedValue([]);
            const result = await service.userHasRole('user-123', 'tenant-123', 'admin');
            expect(result).toBe(false);
        });
    });
});
//# sourceMappingURL=rbac.service.spec.js.map