Files
pfm-ocr/backend/pfm-web-app/test_api.js
T

187 lines
7.2 KiB
JavaScript

const fs = require('fs');
const path = require('path');
const BASE_URL = 'http://localhost:3000/api/v1';
async function runTests() {
console.log('=== STARTING BACKEND API TDD TESTS (PORT 3000) ===');
let failures = 0;
// Helper for reporting test cases
const assert = (condition, message) => {
if (condition) {
console.log(`[PASS] ${message}`);
} else {
console.error(`[FAIL] ${message}`);
failures++;
}
};
let token = '';
let uploadedDocId = '';
const testFilename = 'test-mobile-upload.jpg';
// Create a mock image file for uploading
const mockImagePath = path.join(__dirname, 'mock_upload.jpg');
fs.writeFileSync(mockImagePath, 'fake-jpeg-content-data');
try {
// -------------------------------------------------------------
// Test 1: POST /auth/login
// -------------------------------------------------------------
console.log('\n--- Test 1: Authentication Login ---');
const loginRes = await fetch(`${BASE_URL}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ username: 'admin', password: 'password' })
});
assert(loginRes.status === 200, `POST /auth/login status should be 200 (got ${loginRes.status})`);
if (loginRes.ok) {
const loginData = await loginRes.json();
assert(loginData.status === 'success', 'Login response status field should be "success"');
assert(loginData.data && loginData.data.token, 'Login response should contain auth token');
token = loginData.data?.token || '';
} else {
console.log('Skipping login payload asserts due to failed request');
}
// -------------------------------------------------------------
// Test 2: POST /documents/upload
// -------------------------------------------------------------
console.log('\n--- Test 2: Document Upload ---');
const form = new FormData();
const mockFile = new File(['fake-jpeg-content-data'], testFilename, { type: 'image/jpeg' });
form.append('image', mockFile);
form.append('latitude', '-6.2134');
form.append('longitude', '106.8451');
const uploadRes = await fetch(`${BASE_URL}/documents/upload`, {
method: 'POST',
headers: token ? { 'Authorization': `Bearer ${token}` } : {},
body: form
});
assert(uploadRes.status === 201, `POST /documents/upload status should be 201 (got ${uploadRes.status})`);
if (uploadRes.ok) {
const uploadData = await uploadRes.json();
assert(uploadData.status === 'success', 'Upload status should be "success"');
assert(uploadData.data && uploadData.data.id, 'Upload response should contain document id');
assert(uploadData.data?.latitude === -6.2134, 'Latitude should be returned correctly');
assert(uploadData.data?.longitude === 106.8451, 'Longitude should be returned correctly');
assert(uploadData.data?.header?.no_do === '', 'Header DO should be empty string initially');
assert(Array.isArray(uploadData.data?.items) && uploadData.data.items.length === 0, 'Items should be empty initially');
uploadedDocId = uploadData.data?.id || '';
} else {
console.log('Skipping upload payload asserts due to failed request');
const errText = await uploadRes.text();
console.log('Upload error response body:', errText);
}
// -------------------------------------------------------------
// Test 3: GET /documents (List with polling wait)
// -------------------------------------------------------------
console.log('\n--- Test 3: Documents List (Waiting for background parse) ---');
let found = false;
let retries = 0;
const maxRetries = 15;
let listData;
while (!found && retries < maxRetries) {
if (retries > 0) {
console.log(`Waiting 2s for background parse... (Attempt ${retries}/${maxRetries})`);
await new Promise(resolve => setTimeout(resolve, 2000));
}
const listRes = await fetch(`${BASE_URL}/documents`, {
method: 'GET',
headers: token ? { 'Authorization': `Bearer ${token}` } : {}
});
assert(listRes.status === 200, `GET /documents status should be 200 (got ${listRes.status})`);
if (listRes.ok) {
listData = await listRes.json();
assert(listData.status === 'success', 'List status should be "success"');
assert(Array.isArray(listData.data), 'List data should be an array');
found = listData.data?.some(doc => doc.id.toString() === uploadedDocId.toString());
}
retries++;
}
assert(found, `List should contain the newly uploaded document (id: ${uploadedDocId}) after background parsing`);
// -------------------------------------------------------------
// Test 4: PUT /documents/[id] (Confirm / Update)
// -------------------------------------------------------------
console.log('\n--- Test 4: Document Confirm/Update ---');
if (uploadedDocId) {
const updatePayload = {
tanggal: '2026-06-30',
noPo: 'PO-TEST-123',
noSo: 'SO-TEST-456',
noDo: 'DO-TEST-789',
kepadaYth: 'PT. PRIMAFOOD INTERNATIONAL',
orderUntuk: 'PRIMA FRESH MART',
alamat: 'Jl. Ancol Barat VIII/1',
platTruk: 'B 9999 XYZ',
namaDriver: 'Budi',
namaPenerima: 'Andi',
latitude: -6.2134,
longitude: 106.8451,
items: [
{ nomor_sku: '11048006', nama_barang: 'BEBEK PARTING-NEW(*)', banyak: '10 KRG', jumlah: '10' }
]
};
const updateRes = await fetch(`${BASE_URL}/documents/${uploadedDocId}`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
...(token ? { 'Authorization': `Bearer ${token}` } : {})
},
body: JSON.stringify(updatePayload)
});
assert(updateRes.status === 200, `PUT /documents/${uploadedDocId} status should be 200 (got ${updateRes.status})`);
if (updateRes.ok) {
const updateData = await updateRes.json();
assert(updateData.status === 'success', 'Update status should be "success"');
assert(updateData.data?.header?.no_do === 'DO-TEST-789', 'Header DO should be updated');
assert(updateData.data?.shipment?.nama_penerima === 'Andi', 'Shipment recipient name should be updated');
assert(updateData.data?.items?.length === 1, 'Items array length should be 1');
assert(updateData.data?.items?.[0]?.nomor_sku === '11048006', 'Item SKU should be correctly updated');
} else {
console.log('Skipping update payload asserts due to failed request');
const errText = await updateRes.text();
console.log('Update error response body:', errText);
}
} else {
console.log('Skipping Test 4: No uploadedDocId available');
}
} catch (err) {
console.error('Unhandled exception during tests:', err);
failures++;
} finally {
// Clean up mock image
if (fs.existsSync(mockImagePath)) {
fs.unlinkSync(mockImagePath);
}
}
console.log('\n=== TDD TEST RUN COMPLETED ===');
if (failures === 0) {
console.log('ALL TESTS PASSED SUCCESSFULLY! ✅');
process.exit(0);
} else {
console.error(`${failures} TEST(S) FAILED! ❌`);
process.exit(1);
}
}
runTests();