import { describe, it, expect, beforeAll, afterAll } from 'vitest' import request from 'supertest' import { app } from '../../src/app' import { PrismaClient } from '@prisma/client' import path from 'path' import fs from 'fs' const prisma = new PrismaClient() describe('Document Integration Tests', () => { let authToken: string let userId: string const testUsername = `doc_user_${Date.now()}` const dummyFilePath = path.join(__dirname, 'dummy_test_image.png') beforeAll(async () => { // Clear old data await prisma.documentItem.deleteMany({}) await prisma.document.deleteMany({}) await prisma.user.deleteMany({ where: { username: { startsWith: 'doc_user_' } } }) // Create a dummy image file for testing fs.writeFileSync(dummyFilePath, 'dummy_png_content_data_here') // Create a user and get auth token const regRes = await request(app) .post('/api/v1/auth/register') .send({ username: testUsername, password: 'Password123' }) userId = regRes.body.data.id const loginRes = await request(app) .post('/api/v1/auth/login') .send({ username: testUsername, password: 'Password123' }) authToken = loginRes.body.data.token }) afterAll(async () => { // Clean up dummy file if (fs.existsSync(dummyFilePath)) { fs.unlinkSync(dummyFilePath) } // Clean up uploaded files in test environment if any const uploadsDir = path.join(__dirname, '../../uploads') if (fs.existsSync(uploadsDir)) { const files = fs.readdirSync(uploadsDir) for (const file of files) { if (file.startsWith('test-')) { fs.unlinkSync(path.join(uploadsDir, file)) } } } await prisma.documentItem.deleteMany({}) await prisma.document.deleteMany({}) await prisma.user.deleteMany({ where: { username: { startsWith: 'doc_user_' } } }) await prisma.$disconnect() }) describe('POST /api/v1/documents/upload', () => { it('should fail upload without authentication', async () => { const res = await request(app) .post('/api/v1/documents/upload') .attach('image', dummyFilePath) expect(res.status).toBe(401) expect(res.body.message).toMatch(/token/i) }) it('should upload document and return structured JSON with coordinates', async () => { const res = await request(app) .post('/api/v1/documents/upload') .set('Authorization', `Bearer ${authToken}`) .field('latitude', '-6.2088') .field('longitude', '106.8456') .attach('image', dummyFilePath) expect(res.status).toBe(201) expect(res.body).toHaveProperty('status', 'success') expect(res.body.data).toHaveProperty('header') expect(res.body.data.header).toHaveProperty('tanggal') expect(res.body.data.header).toHaveProperty('no_po') expect(res.body.data).toHaveProperty('shipment') expect(res.body.data.shipment).toHaveProperty('kepada_yth') expect(res.body.data).toHaveProperty('latitude', -6.2088) expect(res.body.data).toHaveProperty('longitude', 106.8456) expect(res.body.data).toHaveProperty('items') expect(res.body.data.items.length).toBeGreaterThan(0) const firstItem = res.body.data.items[0] expect(firstItem).toHaveProperty('nomor_sku') expect(firstItem).toHaveProperty('nama_barang') expect(firstItem).toHaveProperty('banyak') expect(firstItem).toHaveProperty('jumlah') }) }) describe('GET /api/v1/documents', () => { it('should fail listing without authentication', async () => { const res = await request(app) .get('/api/v1/documents') expect(res.status).toBe(401) }) it('should retrieve list of uploaded documents', async () => { const res = await request(app) .get('/api/v1/documents') .set('Authorization', `Bearer ${authToken}`) expect(res.status).toBe(200) expect(res.body).toHaveProperty('status', 'success') expect(Array.isArray(res.body.data)).toBe(true) expect(res.body.data.length).toBeGreaterThan(0) expect(res.body.data[0]).toHaveProperty('filePath') expect(res.body.data[0]).toHaveProperty('items') }) }) describe('PUT /api/v1/documents/:id', () => { it('should update document successfully', async () => { const uploadRes = await request(app) .post('/api/v1/documents/upload') .set('Authorization', `Bearer ${authToken}`) .attach('image', dummyFilePath) const docId = uploadRes.body.data.id const updateRes = await request(app) .put(`/api/v1/documents/${docId}`) .set('Authorization', `Bearer ${authToken}`) .send({ tanggal: '29 Juni 2026', noPo: 'PO/26/0000999999', noSo: '1122334455', noDo: '5544332211', kepadaYth: 'PT. PRIMAFOOD BEKASI', orderUntuk: 'PRIMA FRESH MART', alamat: 'JL. BEKASI RAYA NO. 1', platTruk: 'B 1234 XYZ', namaDriver: 'Sopir Baru', namaPenerima: 'Penerima Toko Baru', latitude: -6.1234, longitude: 106.5678, items: [ { nomor_sku: '12010112', nama_barang: 'FIESTA CHICKEN NUGGET 400 GR/PAC', banyak: '5 BOX', jumlah: '60 PAC' } ] }) expect(updateRes.status).toBe(200) expect(updateRes.body).toHaveProperty('status', 'success') expect(updateRes.body.data).toHaveProperty('header') expect(updateRes.body.data.header).toHaveProperty('no_po', 'PO/26/0000999999') expect(updateRes.body.data.shipment).toHaveProperty('nama_driver', 'Sopir Baru') expect(updateRes.body.data.shipment).toHaveProperty('nama_penerima', 'Penerima Toko Baru') expect(updateRes.body.data).toHaveProperty('latitude', -6.1234) expect(updateRes.body.data).toHaveProperty('longitude', 106.5678) expect(updateRes.body.data.items[0]).toHaveProperty('nomor_sku', '12010112') }) }) })