const assert = require('assert'); const http = require('http'); const mysql = require('mysql2/promise'); require('dotenv').config(); const BASE_URL = 'http://localhost:3001'; function request(method, path, body = null) { return new Promise((resolve, reject) => { const url = `${BASE_URL}${path}`; const options = { method: method, headers: { 'Content-Type': 'application/json' } }; const req = http.request(url, options, (res) => { let data = ''; res.on('data', (chunk) => { data += chunk; }); res.on('end', () => { try { const parsed = JSON.parse(data); resolve({ status: res.statusCode, body: parsed }); } catch (e) { resolve({ status: res.statusCode, body: data }); } }); }); req.on('error', (err) => reject(err)); if (body) { req.write(JSON.stringify(body)); } req.end(); }); } async function runTests() { console.log('๐Ÿงช Starting Audit TDD Tests...'); const pool = mysql.createPool({ host: process.env.DB_HOST, user: process.env.DB_USER, password: process.env.DB_PASS, database: process.env.DB_NAME, port: process.env.DB_PORT }); const connection = await pool.getConnection(); try { // Clean up any test records console.log('๐Ÿงน Cleaning up test records...'); await connection.query("DELETE FROM asset_audit_pending WHERE asset_code LIKE 'TEST-ASSET-%'"); // Check if test assets exist in asset_core & asset_location // We will use an existing asset or insert a dummy test asset const [testAssets] = await connection.query("SELECT id FROM asset_core WHERE asset_code = 'TEST-ASSET-001'"); let testAssetId; if (testAssets.length === 0) { console.log('โณ Inserting dummy test asset...'); testAssetId = 'test_asset_uuid_123456'; await connection.query(` INSERT INTO asset_core (id, asset_code, category, asset_type, asset_purpose) VALUES (?, 'TEST-ASSET-001', 'server', 'Server', 'TDD Test Server') `, [testAssetId]); await connection.query(` INSERT INTO asset_location (asset_id, location, location_detail, location_photo, loc_x, loc_y, is_active) VALUES (?, 'Initial Location', 'Initial Detail', 'initial.png', '10.00', '10.00', 1) `, [testAssetId]); } else { testAssetId = testAssets[0].id; } // 1. Test GET /api/physical-locations console.log('๐Ÿ‘‰ Test 1: GET /api/physical-locations'); const res1 = await request('GET', '/api/physical-locations'); assert.strictEqual(res1.status, 200, 'GET /api/physical-locations should return 200'); assert(Array.isArray(res1.body), 'Response should be an array of physical locations'); assert(res1.body.length > 0, 'Should return at least one physical location'); console.log(`โœ… Test 1 Passed: Found ${res1.body.length} physical locations.`); const sampleLocation = res1.body[0].location_code; // 2. Test POST /api/audit/scan console.log(`๐Ÿ‘‰ Test 2: POST /api/audit/scan (Location: ${sampleLocation}, Asset: TEST-ASSET-001)`); const res2 = await request('POST', '/api/audit/scan', { asset_code: 'TEST-ASSET-001', physical_location_code: sampleLocation }); assert.strictEqual(res2.status, 200, 'POST /api/audit/scan should return 200'); assert.strictEqual(res2.body.success, true, 'Response success should be true'); assert(res2.body.pending_id, 'Response should contain pending_id'); console.log(`โœ… Test 2 Passed: Pending scan registered with ID: ${res2.body.pending_id}`); const pendingId = res2.body.pending_id; // 3. Test GET /api/audit/pending console.log('๐Ÿ‘‰ Test 3: GET /api/audit/pending'); const res3 = await request('GET', '/api/audit/pending'); assert.strictEqual(res3.status, 200, 'GET /api/audit/pending should return 200'); assert(Array.isArray(res3.body), 'Response should be an array'); const pendingItem = res3.body.find(item => item.id === pendingId); assert(pendingItem, 'Pending list should contain the newly registered scan'); assert.strictEqual(pendingItem.asset_code, 'TEST-ASSET-001', 'Asset code should match'); assert.strictEqual(pendingItem.physical_location_code, sampleLocation, 'Location code should match'); assert.strictEqual(pendingItem.status, 'PENDING', 'Status should be PENDING'); console.log('โœ… Test 3 Passed: Newly registered scan found in pending list with correct details.'); // 4. Test POST /api/audit/approve console.log(`๐Ÿ‘‰ Test 4: POST /api/audit/approve (Pending ID: ${pendingId})`); const res4 = await request('POST', '/api/audit/approve', { pending_ids: [pendingId], processed_by: 'TDD-TESTER' }); assert.strictEqual(res4.status, 200, 'POST /api/audit/approve should return 200'); assert.strictEqual(res4.body.success, true, 'Response success should be true'); console.log('โœ… Test 4 Passed: Audit approved.'); // Verify database updates console.log('๐Ÿ” Verifying updates in database...'); const [pendingCheck] = await connection.query( 'SELECT status, processed_by FROM asset_audit_pending WHERE id = ?', [pendingId] ); assert.strictEqual(pendingCheck[0].status, 'APPROVED', 'Pending record status should be APPROVED'); assert.strictEqual(pendingCheck[0].processed_by, 'TDD-TESTER', 'Processed by should match'); const [locationCheck] = await connection.query( 'SELECT physical_location_code, location_photo, loc_x, loc_y FROM asset_location WHERE asset_id = ? AND is_active = 1', [testAssetId] ); const [physLoc] = await connection.query( 'SELECT map_image, map_x, map_y FROM physical_locations WHERE location_code = ?', [sampleLocation] ); assert.strictEqual(locationCheck[0].physical_location_code, sampleLocation, 'Asset location code should be updated'); assert.strictEqual(locationCheck[0].location_photo, physLoc[0].map_image, 'Asset map_image should be updated'); assert.strictEqual(parseFloat(locationCheck[0].loc_x).toFixed(2), parseFloat(physLoc[0].map_x).toFixed(2), 'Asset map_x should be updated'); assert.strictEqual(parseFloat(locationCheck[0].loc_y).toFixed(2), parseFloat(physLoc[0].map_y).toFixed(2), 'Asset map_y should be updated'); console.log('โœ… Database verification passed: Asset location and map coordinates updated successfully!'); // Clean up console.log('๐Ÿงน Cleaning up test assets...'); await connection.query("DELETE FROM asset_audit_pending WHERE asset_code = 'TEST-ASSET-001'"); await connection.query("DELETE FROM asset_location WHERE asset_id = ?", [testAssetId]); await connection.query("DELETE FROM asset_core WHERE id = ?", [testAssetId]); console.log('๐ŸŽ‰ All TDD tests passed successfully!'); } catch (err) { console.error('โŒ TDD Test Suite Failed:', err.message); throw err; } finally { connection.release(); await pool.end(); } } runTests().catch(() => process.exit(1));