2025-11-16 22:28:42 +01:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
use App\Jobs\SyncBackendDataPool;
|
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
|
|
|
|
|
|
beforeEach(function () {
|
|
|
|
|
// Clean up tables before each test
|
|
|
|
|
DB::table('backend_data_pool')->truncate();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
test('full sync truncates and rebuilds backend_data_pool', function () {
|
|
|
|
|
// Arrange: Insert some old data
|
|
|
|
|
DB::table('backend_data_pool')->insert([
|
|
|
|
|
'transaction_id' => 999,
|
|
|
|
|
'corporate_entity' => 'Old Company',
|
|
|
|
|
'corporate_counterparty' => 'Old Counterparty',
|
|
|
|
|
'tx_date' => '2024-01-01',
|
|
|
|
|
'tx_amount' => 1000.00,
|
|
|
|
|
'status' => 'done',
|
|
|
|
|
'created_at' => '2024-01-01',
|
|
|
|
|
'last_modified_at' => '2024-01-01',
|
|
|
|
|
'prompt_id' => 1,
|
|
|
|
|
'output_key' => 'test_key',
|
|
|
|
|
'content' => 'test content',
|
|
|
|
|
'synced_at' => now(),
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
expect(DB::table('backend_data_pool')->count())->toBe(1);
|
|
|
|
|
|
|
|
|
|
// Act: Perform full sync
|
|
|
|
|
$job = new SyncBackendDataPool(fullSync: true, batchSize: 100);
|
|
|
|
|
$job->handle();
|
|
|
|
|
|
|
|
|
|
// Assert: Old data should be removed, new data from backend should be present
|
|
|
|
|
$recordCount = DB::table('backend_data_pool')->count();
|
|
|
|
|
expect($recordCount)->toBeGreaterThanOrEqual(0); // Should have backend data
|
|
|
|
|
|
|
|
|
|
// Should not contain the old test record
|
|
|
|
|
$oldRecord = DB::table('backend_data_pool')
|
|
|
|
|
->where('transaction_id', 999)
|
|
|
|
|
->first();
|
|
|
|
|
|
|
|
|
|
expect($oldRecord)->toBeNull();
|
2025-12-17 18:04:42 +01:00
|
|
|
})->group('backend-db');
|
2025-11-16 22:28:42 +01:00
|
|
|
|
|
|
|
|
test('incremental sync only adds new records', function () {
|
|
|
|
|
// Arrange: Perform initial sync
|
|
|
|
|
$job = new SyncBackendDataPool(fullSync: true, batchSize: 100);
|
|
|
|
|
$job->handle();
|
|
|
|
|
|
|
|
|
|
$initialCount = DB::table('backend_data_pool')->count();
|
|
|
|
|
|
|
|
|
|
// Wait a moment to ensure timestamp difference
|
|
|
|
|
sleep(1);
|
|
|
|
|
|
|
|
|
|
// Act: Perform incremental sync (should not add duplicates)
|
|
|
|
|
$incrementalJob = new SyncBackendDataPool(fullSync: false, batchSize: 100);
|
|
|
|
|
$incrementalJob->handle();
|
|
|
|
|
|
|
|
|
|
// Assert: Count should not increase significantly (only if new records in backend)
|
|
|
|
|
$newCount = DB::table('backend_data_pool')->count();
|
|
|
|
|
expect($newCount)->toBeGreaterThanOrEqual($initialCount);
|
2025-12-17 18:04:42 +01:00
|
|
|
})->group('backend-db');
|
2025-11-16 22:28:42 +01:00
|
|
|
|
|
|
|
|
test('sync correctly maps backend.transactions and backend.transaction_outputs', function () {
|
|
|
|
|
// Act: Perform sync
|
|
|
|
|
$job = new SyncBackendDataPool(fullSync: true, batchSize: 100);
|
|
|
|
|
$job->handle();
|
|
|
|
|
|
|
|
|
|
// Assert: Check if records have correct structure
|
|
|
|
|
$record = DB::table('backend_data_pool')->first();
|
|
|
|
|
|
|
|
|
|
if ($record) {
|
|
|
|
|
expect($record)->toHaveProperty('transaction_id');
|
|
|
|
|
expect($record)->toHaveProperty('corporate_entity');
|
|
|
|
|
expect($record)->toHaveProperty('corporate_counterparty');
|
|
|
|
|
expect($record)->toHaveProperty('tx_date');
|
|
|
|
|
expect($record)->toHaveProperty('tx_amount');
|
|
|
|
|
expect($record)->toHaveProperty('status');
|
|
|
|
|
expect($record)->toHaveProperty('prompt_id');
|
|
|
|
|
expect($record)->toHaveProperty('output_key');
|
|
|
|
|
expect($record)->toHaveProperty('content');
|
|
|
|
|
expect($record)->toHaveProperty('synced_at');
|
|
|
|
|
}
|
2025-12-17 18:04:42 +01:00
|
|
|
})->group('backend-db');
|
2025-11-16 22:28:42 +01:00
|
|
|
|
|
|
|
|
test('sync only includes transactions with status done', function () {
|
|
|
|
|
// Act: Perform sync
|
|
|
|
|
$job = new SyncBackendDataPool(fullSync: true, batchSize: 100);
|
|
|
|
|
$job->handle();
|
|
|
|
|
|
|
|
|
|
// Assert: All records should have status = 'done'
|
|
|
|
|
$nonDoneRecords = DB::table('backend_data_pool')
|
|
|
|
|
->where('status', '!=', 'done')
|
|
|
|
|
->count();
|
|
|
|
|
|
|
|
|
|
expect($nonDoneRecords)->toBe(0);
|
2025-12-17 18:04:42 +01:00
|
|
|
})->group('backend-db');
|
2025-11-16 22:28:42 +01:00
|
|
|
|
|
|
|
|
test('sync processes records in batches', function () {
|
|
|
|
|
// Act: Perform sync with small batch size
|
|
|
|
|
$job = new SyncBackendDataPool(fullSync: true, batchSize: 10);
|
|
|
|
|
$job->handle();
|
|
|
|
|
|
|
|
|
|
// Assert: Should complete without errors
|
|
|
|
|
$recordCount = DB::table('backend_data_pool')->count();
|
|
|
|
|
expect($recordCount)->toBeGreaterThanOrEqual(0);
|
2025-12-17 18:04:42 +01:00
|
|
|
})->group('backend-db');
|
2025-11-16 22:28:42 +01:00
|
|
|
|
|
|
|
|
test('getStats returns correct statistics', function () {
|
|
|
|
|
// Arrange: Perform sync
|
|
|
|
|
$job = new SyncBackendDataPool(fullSync: true, batchSize: 100);
|
|
|
|
|
$job->handle();
|
|
|
|
|
|
|
|
|
|
// Act: Get stats
|
|
|
|
|
$stats = $job->getStats();
|
|
|
|
|
|
|
|
|
|
// Assert: Stats should have correct structure
|
|
|
|
|
expect($stats)->toBeArray();
|
|
|
|
|
expect($stats)->toHaveKey('backend_transactions_done');
|
|
|
|
|
expect($stats)->toHaveKey('backend_transaction_outputs');
|
|
|
|
|
expect($stats)->toHaveKey('backend_data_pool_records');
|
|
|
|
|
expect($stats)->toHaveKey('last_synced_at');
|
|
|
|
|
|
|
|
|
|
expect($stats['backend_data_pool_records'])->toBeGreaterThanOrEqual(0);
|
2025-12-17 18:04:42 +01:00
|
|
|
})->group('backend-db');
|
2025-11-16 22:28:42 +01:00
|
|
|
|
|
|
|
|
test('sync handles empty backend gracefully', function () {
|
|
|
|
|
// This test assumes backend might be empty or have no 'done' transactions
|
|
|
|
|
|
|
|
|
|
// Act: Perform sync
|
|
|
|
|
$job = new SyncBackendDataPool(fullSync: true, batchSize: 100);
|
|
|
|
|
$job->handle();
|
|
|
|
|
|
|
|
|
|
// Assert: Should complete without errors
|
|
|
|
|
$recordCount = DB::table('backend_data_pool')->count();
|
|
|
|
|
expect($recordCount)->toBeGreaterThanOrEqual(0);
|
2025-12-17 18:04:42 +01:00
|
|
|
})->group('backend-db');
|
2025-11-16 22:28:42 +01:00
|
|
|
|
|
|
|
|
test('sync orders records by transaction_id and prompt_id', function () {
|
|
|
|
|
// Act: Perform sync
|
|
|
|
|
$job = new SyncBackendDataPool(fullSync: true, batchSize: 100);
|
|
|
|
|
$job->handle();
|
|
|
|
|
|
|
|
|
|
// Assert: Check ordering
|
|
|
|
|
$records = DB::table('backend_data_pool')
|
|
|
|
|
->limit(10)
|
|
|
|
|
->get();
|
|
|
|
|
|
|
|
|
|
if ($records->count() > 1) {
|
|
|
|
|
$previousTransactionId = null;
|
|
|
|
|
$previousPromptId = null;
|
|
|
|
|
|
|
|
|
|
foreach ($records as $record) {
|
|
|
|
|
if ($previousTransactionId !== null) {
|
|
|
|
|
// Either transaction_id should increase or stay same (with prompt_id increasing)
|
|
|
|
|
expect($record->transaction_id)->toBeGreaterThanOrEqual($previousTransactionId);
|
|
|
|
|
|
|
|
|
|
if ($record->transaction_id === $previousTransactionId && $previousPromptId !== null) {
|
|
|
|
|
expect($record->prompt_id)->toBeGreaterThanOrEqual($previousPromptId);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$previousTransactionId = $record->transaction_id;
|
|
|
|
|
$previousPromptId = $record->prompt_id;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-12-17 18:04:42 +01:00
|
|
|
})->group('backend-db');
|