fix: permite sellerId null no login e adiciona testes

- Ajusta validação para aceitar sellerId null/undefined
- Atualiza tipos JwtPayload e LoginResponseDto para permitir sellerId null
- Adiciona testes para validar login com sellerId null
- Adiciona jest.setup.js para resolver problema do TypeORM nos testes
This commit is contained in:
JurTI-BR
2025-11-10 13:31:26 -03:00
parent 054cc2f3bb
commit 6afba4f3b4
7 changed files with 141 additions and 17 deletions

13
jest.setup.js Normal file
View File

@@ -0,0 +1,13 @@
// Mock para resolver problema do TypeORM com node:url
// Este arquivo é executado antes de todos os testes
// Mock do módulo 'glob' do TypeORM que causa problemas
jest.mock('glob', () => {
const originalModule = jest.requireActual('glob');
return {
...originalModule,
glob: jest.fn(),
globSync: jest.fn(),
};
});

View File

@@ -112,6 +112,10 @@
"testEnvironment": "node", "testEnvironment": "node",
"moduleNameMapper": { "moduleNameMapper": {
"^src/(.*)$": "<rootDir>/$1" "^src/(.*)$": "<rootDir>/$1"
} },
"transformIgnorePatterns": [
"node_modules/(?!(typeorm|@nestjs)/)"
],
"setupFilesAfterEnv": ["../jest.setup.js"]
} }
} }

View File

@@ -243,6 +243,72 @@ describe('AuthService - createToken', () => {
).rejects.toThrow('ID de vendedor inválido'); ).rejects.toThrow('ID de vendedor inválido');
}); });
it('should accept null seller ID', async () => {
const mockToken = 'mock.jwt.token.null.seller';
const userId = 1427;
const sellerId = null;
const username = 'brunelle.c';
const email = 'brunelle.c@jurunense.com.br';
const storeId = '12';
const sessionId = 'session-null-seller';
context.mockJwtService.sign.mockReturnValue(mockToken);
const result = await context.service.createToken(
userId,
sellerId,
username,
email,
storeId,
sessionId,
);
expect(context.mockJwtService.sign).toHaveBeenCalledWith(
{
id: userId,
sellerId: null,
storeId: storeId,
username: username,
email: email,
sessionId: sessionId,
},
{ expiresIn: '8h' },
);
expect(result).toBe(mockToken);
});
it('should accept undefined seller ID', async () => {
const mockToken = 'mock.jwt.token.undefined.seller';
const userId = 1427;
const sellerId = undefined;
const username = 'brunelle.c';
const email = 'brunelle.c@jurunense.com.br';
const storeId = '12';
context.mockJwtService.sign.mockReturnValue(mockToken);
const result = await context.service.createToken(
userId,
sellerId as any,
username,
email,
storeId,
);
expect(context.mockJwtService.sign).toHaveBeenCalledWith(
{
id: userId,
sellerId: undefined,
storeId: storeId,
username: username,
email: email,
sessionId: undefined,
},
{ expiresIn: '8h' },
);
expect(result).toBe(mockToken);
});
it('should reject empty username', async () => { it('should reject empty username', async () => {
const emptyUsername = ''; const emptyUsername = '';

View File

@@ -321,5 +321,42 @@ describe('AuthService - createTokenPair', () => {
expect(result).toHaveProperty('expiresIn'); expect(result).toHaveProperty('expiresIn');
expect(Object.keys(result).length).toBe(3); expect(Object.keys(result).length).toBe(3);
}); });
it('should create token pair with null seller ID', async () => {
/**
* Cenário: Usuário sem sellerId (CODUSUR NULL no banco).
* Problema: Validação anterior rejeitava null sellerId.
* Solução esperada: Aceitar null sellerId e criar tokens normalmente.
*/
const result = await context.service.createTokenPair(
1427,
null,
'BRUNELLE BENILDA GAMA COSTA',
'BRUNELLE.C@JURUNENSE.COM.BR',
'12',
'session-null-seller',
);
expect(result).toHaveProperty('accessToken');
expect(result).toHaveProperty('refreshToken');
expect(result).toHaveProperty('expiresIn');
expect(result.expiresIn).toBe(28800); // 8 horas em segundos
expect(context.mockJwtService.sign).toHaveBeenCalledWith(
{
id: 1427,
sellerId: null,
storeId: '12',
username: 'BRUNELLE BENILDA GAMA COSTA',
email: 'BRUNELLE.C@JURUNENSE.COM.BR',
sessionId: 'session-null-seller',
},
{ expiresIn: '8h' },
);
expect(
context.mockRefreshTokenService.generateRefreshToken,
).toHaveBeenCalledWith(1427, 'session-null-seller');
});
}); });
}); });

View File

@@ -28,7 +28,7 @@ export class AuthService {
*/ */
async createToken( async createToken(
id: number, id: number,
sellerId: number, sellerId: number | null,
username: string, username: string,
email: string, email: string,
storeId: string, storeId: string,
@@ -54,7 +54,7 @@ export class AuthService {
*/ */
private validateTokenParameters( private validateTokenParameters(
id: number, id: number,
sellerId: number, sellerId: number | null,
username: string, username: string,
email: string, email: string,
storeId: string, storeId: string,
@@ -63,7 +63,11 @@ export class AuthService {
throw new BadRequestException('ID de usuário inválido'); throw new BadRequestException('ID de usuário inválido');
} }
if (sellerId === null || sellerId === undefined || sellerId < 0) { if (
sellerId !== null &&
sellerId !== undefined &&
sellerId < 0
) {
throw new BadRequestException('ID de vendedor inválido'); throw new BadRequestException('ID de vendedor inválido');
} }
@@ -112,7 +116,7 @@ export class AuthService {
*/ */
async createTokenPair( async createTokenPair(
id: number, id: number,
sellerId: number, sellerId: number | null,
username: string, username: string,
email: string, email: string,
storeId: string, storeId: string,

View File

@@ -3,7 +3,7 @@ import { ApiProperty } from '@nestjs/swagger';
export class LoginResponseDto { export class LoginResponseDto {
@ApiProperty() id: number; @ApiProperty() id: number;
@ApiProperty() sellerId: number; @ApiProperty({ nullable: true }) sellerId: number | null;
@ApiProperty() name: string; @ApiProperty() name: string;
@ApiProperty() username: string; @ApiProperty() username: string;
@ApiProperty() storeId: string; @ApiProperty() storeId: string;

View File

@@ -1,7 +1,7 @@
/* eslint-disable prettier/prettier */ /* eslint-disable prettier/prettier */
export interface JwtPayload { export interface JwtPayload {
id: number; id: number;
sellerId: number; sellerId: number | null;
storeId: string; storeId: string;
username: string; username: string;
email: string; email: string;