get(route('transaction-review')); $response->assertRedirect(route('login')); }); test('authenticated users can view transaction review', function () { $this->actingAs(User::factory()->create()); $response = $this->get(route('transaction-review')); $response->assertOk(); }); test('transaction review filters by search and updates selection', function () { $this->actingAs(User::factory()->create()); $acme = Company::factory()->create(['name' => 'Acme', 'legal_name' => 'Acme Investigations AG']); $globex = Company::factory()->create(['name' => 'Globex', 'legal_name' => 'Globex Risk GmbH']); $priority = Transaction::factory()->for($acme)->requiresReview()->status(Transaction::STATUS_TRUE_POSITIVE)->create([ 'reference' => 'REF-ACME-001', 'counterparty' => 'Alpha Logistics', 'amount' => 125000.75, 'risk_score' => 95, 'executed_at' => Carbon::parse('2024-01-11 12:00:00'), ]); $match = Transaction::factory()->for($globex)->requiresReview()->status(Transaction::STATUS_FALSE_POSITIVE)->create([ 'reference' => 'REF-GLOBEX-001', 'counterparty' => 'Beta Holdings', 'amount' => 45000.50, 'risk_score' => 72, 'executed_at' => Carbon::parse('2024-01-10 09:00:00'), ]); Transaction::factory()->for($globex)->requiresReview(false)->status(Transaction::STATUS_CLEARED)->create([ 'reference' => 'REF-GLOBEX-002', 'counterparty' => 'Gamma Partners', 'amount' => 32000.25, 'risk_score' => 40, 'executed_at' => Carbon::parse('2024-01-09 08:15:00'), ]); $component = Volt::test('transaction-review'); expect($component->get('selectedTransactionId'))->toBe($priority->id); $component->set('search', 'Beta'); /** @var LengthAwarePaginator $transactions */ $transactions = $component->get('transactions'); expect($transactions->total())->toBe(1) ->and($transactions->items()[0]->id)->toBe($match->id) ->and($component->get('selectedTransactionId'))->toBe($match->id); }); test('transaction review metrics aggregate totals by status', function () { $this->actingAs(User::factory()->create()); $acme = Company::factory()->create(); $globex = Company::factory()->create(); $truePositive = Transaction::factory()->for($acme)->requiresReview()->status(Transaction::STATUS_TRUE_POSITIVE)->create([ 'amount' => 90000.00, 'risk_score' => 88, 'executed_at' => Carbon::parse('2024-01-08 10:00:00'), ]); $falsePositive = Transaction::factory()->for($globex)->requiresReview()->status(Transaction::STATUS_FALSE_POSITIVE)->create([ 'amount' => 15000.00, 'risk_score' => 65, 'executed_at' => Carbon::parse('2024-01-08 09:00:00'), ]); Transaction::factory()->for($globex)->requiresReview(false)->status(Transaction::STATUS_CLEARED)->create([ 'amount' => 6000.00, 'risk_score' => 35, 'executed_at' => Carbon::parse('2024-01-07 08:00:00'), ]); $component = Volt::test('transaction-review'); $metrics = $component->get('metrics'); expect($metrics['total']['count'])->toBe(3) ->and($metrics['by_status'][Transaction::STATUS_TRUE_POSITIVE]['count'])->toBe(1) ->and($metrics['by_status'][Transaction::STATUS_TRUE_POSITIVE]['amount'])->toEqualWithDelta(90000, 0.001) ->and($metrics['by_status'][Transaction::STATUS_FALSE_POSITIVE]['count'])->toBe(1) ->and($metrics['by_status'][Transaction::STATUS_FALSE_POSITIVE]['amount'])->toEqualWithDelta(15000, 0.001) ->and($metrics['by_status'][Transaction::STATUS_CLEARED]['count'])->toBe(1); $component->set('status', Transaction::STATUS_FALSE_POSITIVE); $filteredMetrics = $component->get('metrics'); expect($filteredMetrics['total']['count'])->toBe(1) ->and($filteredMetrics['total']['amount'])->toEqualWithDelta(15000, 0.001) ->and($component->get('selectedTransactionId'))->toBe($falsePositive->id); });