187 lines
7.2 KiB
JavaScript
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();
|