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:
13
jest.setup.js
Normal file
13
jest.setup.js
Normal 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(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
@@ -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"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 = '';
|
||||||
|
|
||||||
|
|||||||
@@ -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');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user