miinventario-backend-v2/test/feedback.e2e-spec.ts
rckrdmrd 5a1c966ed2 Migración desde miinventario/backend - Estándar multi-repo v2
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 08:12:15 -06:00

203 lines
7.4 KiB
TypeScript

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication, ValidationPipe } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import { getRepositoryToken } from '@nestjs/typeorm';
import { User } from '../src/modules/users/entities/user.entity';
import { Store } from '../src/modules/stores/entities/store.entity';
import { StoreUser, StoreUserRole } from '../src/modules/stores/entities/store-user.entity';
import { InventoryItem } from '../src/modules/inventory/entities/inventory-item.entity';
import { Correction } from '../src/modules/feedback/entities/correction.entity';
import { JwtService } from '@nestjs/jwt';
import { Repository } from 'typeorm';
describe('FeedbackController (e2e)', () => {
let app: INestApplication;
let jwtService: JwtService;
let userRepository: Repository<User>;
let storeRepository: Repository<Store>;
let storeUserRepository: Repository<StoreUser>;
let inventoryRepository: Repository<InventoryItem>;
let correctionRepository: Repository<Correction>;
let testUser: User;
let testStore: Store;
let testItem: InventoryItem;
let authToken: string;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
app.useGlobalPipes(new ValidationPipe({ whitelist: true }));
await app.init();
jwtService = moduleFixture.get<JwtService>(JwtService);
userRepository = moduleFixture.get(getRepositoryToken(User));
storeRepository = moduleFixture.get(getRepositoryToken(Store));
storeUserRepository = moduleFixture.get(getRepositoryToken(StoreUser));
inventoryRepository = moduleFixture.get(getRepositoryToken(InventoryItem));
correctionRepository = moduleFixture.get(getRepositoryToken(Correction));
// Create test user
testUser = await userRepository.save({
phone: '+521234567890',
name: 'Test Feedback User',
});
// Create test store
testStore = await storeRepository.save({
name: 'Test Feedback Store',
ownerId: testUser.id,
});
// Create store-user relationship
await storeUserRepository.save({
storeId: testStore.id,
userId: testUser.id,
role: StoreUserRole.OWNER,
});
// Create test inventory item
testItem = await inventoryRepository.save({
storeId: testStore.id,
name: 'Test Product',
quantity: 10,
category: 'Test Category',
});
// Generate auth token
authToken = jwtService.sign({ sub: testUser.id, phone: testUser.phone });
});
afterAll(async () => {
// Cleanup
await correctionRepository.delete({ inventoryItemId: testItem.id });
await inventoryRepository.delete({ id: testItem.id });
await storeUserRepository.delete({ storeId: testStore.id });
await storeRepository.delete({ id: testStore.id });
await userRepository.delete({ id: testUser.id });
await app.close();
});
describe('/stores/:storeId/inventory/:itemId/correct-quantity (PATCH)', () => {
it('should correct item quantity', async () => {
const response = await request(app.getHttpServer())
.patch(`/stores/${testStore.id}/inventory/${testItem.id}/correct-quantity`)
.set('Authorization', `Bearer ${authToken}`)
.send({ quantity: 15, reason: 'Conteo incorrecto' })
.expect(200);
expect(response.body.message).toBe('Cantidad corregida exitosamente');
expect(response.body.correction.type).toBe('QUANTITY');
expect(response.body.correction.previousValue.quantity).toBe(10);
expect(response.body.correction.newValue.quantity).toBe(15);
expect(response.body.item.quantity).toBe(15);
});
it('should reject invalid quantity', async () => {
await request(app.getHttpServer())
.patch(`/stores/${testStore.id}/inventory/${testItem.id}/correct-quantity`)
.set('Authorization', `Bearer ${authToken}`)
.send({ quantity: -5 })
.expect(400);
});
it('should reject without auth', async () => {
await request(app.getHttpServer())
.patch(`/stores/${testStore.id}/inventory/${testItem.id}/correct-quantity`)
.send({ quantity: 20 })
.expect(401);
});
});
describe('/stores/:storeId/inventory/:itemId/correct-sku (PATCH)', () => {
it('should correct item SKU/name', async () => {
const response = await request(app.getHttpServer())
.patch(`/stores/${testStore.id}/inventory/${testItem.id}/correct-sku`)
.set('Authorization', `Bearer ${authToken}`)
.send({
name: 'Corrected Product Name',
category: 'New Category',
reason: 'Nombre incorrecto',
})
.expect(200);
expect(response.body.message).toBe('Nombre/SKU corregido exitosamente');
expect(response.body.correction.type).toBe('SKU');
expect(response.body.item.name).toBe('Corrected Product Name');
});
it('should reject empty name', async () => {
await request(app.getHttpServer())
.patch(`/stores/${testStore.id}/inventory/${testItem.id}/correct-sku`)
.set('Authorization', `Bearer ${authToken}`)
.send({ name: '' })
.expect(400);
});
});
describe('/stores/:storeId/inventory/:itemId/confirm (POST)', () => {
it('should confirm item as correct', async () => {
const response = await request(app.getHttpServer())
.post(`/stores/${testStore.id}/inventory/${testItem.id}/confirm`)
.set('Authorization', `Bearer ${authToken}`)
.expect(201);
expect(response.body.message).toBe('Item confirmado exitosamente');
expect(response.body.correction.type).toBe('CONFIRMATION');
});
});
describe('/stores/:storeId/inventory/:itemId/history (GET)', () => {
it('should return correction history', async () => {
const response = await request(app.getHttpServer())
.get(`/stores/${testStore.id}/inventory/${testItem.id}/history`)
.set('Authorization', `Bearer ${authToken}`)
.expect(200);
expect(response.body.corrections).toBeDefined();
expect(Array.isArray(response.body.corrections)).toBe(true);
expect(response.body.corrections.length).toBeGreaterThan(0);
});
it('should return 404 for non-existent item', async () => {
await request(app.getHttpServer())
.get(`/stores/${testStore.id}/inventory/00000000-0000-0000-0000-000000000000/history`)
.set('Authorization', `Bearer ${authToken}`)
.expect(404);
});
});
describe('/products/submit (POST)', () => {
it('should submit new product', async () => {
const response = await request(app.getHttpServer())
.post('/products/submit')
.set('Authorization', `Bearer ${authToken}`)
.send({
storeId: testStore.id,
name: 'New Product Submission',
category: 'Beverages',
})
.expect(201);
expect(response.body.message).toBe('Producto enviado para revision');
expect(response.body.submission.status).toBe('PENDING');
});
});
describe('/products/search (GET)', () => {
it('should search products', async () => {
const response = await request(app.getHttpServer())
.get('/products/search?q=test')
.set('Authorization', `Bearer ${authToken}`)
.expect(200);
expect(response.body.products).toBeDefined();
expect(Array.isArray(response.body.products)).toBe(true);
});
});
});