import { Test } from "@nestjs/testing"
import { PermissionGuard } from "../permission.guard"
import { Reflector } from "@nestjs/core"
import { UserService } from "../../user/user.service";
import { I18nContext } from "nestjs-i18n";
import { ExecutionContext, HttpException, HttpStatus } from "@nestjs/common";
jest.mock('uuid', () => ({
v7: jest.fn(() => 'mocked-uuid-v7'),
}));
describe('Permission Guard', ()=>{
let guard: PermissionGuard;
const ref = {
getAllAndOverride: jest.fn()
};
const userService = {
getUserPermission: jest.fn().mockResolvedValue([])
}
const i18n= {
lang: '',
t: jest.fn()
}
beforeEach(async ()=>{
const module = await Test.createTestingModule({
providers: [
PermissionGuard,
{
provide: Reflector,
useValue: ref
},
{
provide: UserService,
useValue: userService
}
]
}).compile();
jest.spyOn(I18nContext, 'current').mockReturnValue(i18n as any);
guard = module.get(PermissionGuard);
})
it('should allow access if no required permissions are defined', async () => {
ref.getAllAndOverride.mockReturnValue([]);
const context = {
switchToHttp: () => ({
getRequest: () => ({
headers: {},
user: {},
}),
}),
getClass: jest.fn(),
getHandler: jest.fn(),
} as unknown as ExecutionContext;
const result = await guard.canActivate(context);
expect(result).toBe(true);
});
it('should allow access if user has all required permissions', async () => {
ref.getAllAndOverride.mockReturnValue(['read', 'write']);
userService.getUserPermission.mockResolvedValue(['read', 'write']);
const context = {
switchToHttp: () => ({
getRequest: () => ({
headers: { authorization: 'Bearer token' },
user: {},
}),
}),
getClass: jest.fn(),
getHandler: jest.fn(),
} as unknown as ExecutionContext;
const result = await guard.canActivate(context);
expect(result).toBe(true);
});
it('should allow access if user has wildcard permission', async () => {
ref.getAllAndOverride.mockReturnValue(['read', 'write']);
userService.getUserPermission.mockResolvedValue(['*']);
const context = {
switchToHttp: () => ({
getRequest: () => ({
headers: { authorization: 'Bearer token' },
user: {},
}),
}),
getClass: jest.fn(),
getHandler: jest.fn(),
} as unknown as ExecutionContext;
const result = await guard.canActivate(context);
expect(result).toBe(true);
});
it('should deny access if user lacks required permissions', async () => {
ref.getAllAndOverride.mockReturnValue(['read', 'write']);
userService.getUserPermission.mockResolvedValue(['read']);
const context = {
switchToHttp: () => ({
getRequest: () => ({
headers: { authorization: 'Bearer token' },
user: {},
}),
}),
getClass: jest.fn(),
getHandler: jest.fn(),
} as unknown as ExecutionContext;
await expect(guard.canActivate(context)).rejects.toThrow(HttpException);
await expect(guard.canActivate(context)).rejects.toThrowError(
expect.objectContaining({
status: HttpStatus.FORBIDDEN,
}),
);
});
})