feat: consolidate backend and docker-compose setup
This commit is contained in:
commit
ff3753a745
306 files changed
+35450
No files matched your search
@@ -0,0 +1,186 @@
|
||||
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();
|
||||
Reference in new issue
Block a user