177 lines
6.0 KiB
TypeScript
177 lines
6.0 KiB
TypeScript
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')
|
|
})
|
|
})
|
|
})
|