From a5697d886cbf71ee9694ec95edf4b7347bbead85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vi=CC=81ctor=20Falco=CC=81n?= Date: Fri, 3 Jul 2026 13:27:56 +0200 Subject: [PATCH] test(automation-rules): cover apply job execution and failure branches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ApplySingleAutomationRuleJob was only ever asserted to be *pushed* under Queue::fake() — its handle() body (chunked apply, progress accumulation) and failed() branch had no coverage. ReEvaluateTransactionRulesJob's failed() branch was likewise untested. Add direct handle() and failed() tests for the apply job, and a failed() test for the re-evaluate job, pinning the progress-cache payloads so the 'failed' status and preserved counts can't silently drift. --- .../Feature/AutomationRuleApplicationTest.php | 50 +++++++++++++++++++ .../ReEvaluateTransactionRulesTest.php | 18 +++++++ 2 files changed, 68 insertions(+) diff --git a/tests/Feature/AutomationRuleApplicationTest.php b/tests/Feature/AutomationRuleApplicationTest.php index d4d45ae9..65fd5f5c 100644 --- a/tests/Feature/AutomationRuleApplicationTest.php +++ b/tests/Feature/AutomationRuleApplicationTest.php @@ -290,6 +290,56 @@ test('apply endpoint queues a job when matches exceed threshold', function () { Queue::assertPushed(ApplySingleAutomationRuleJob::class); }); +test('apply job applies the rule and records done progress', function () { + $t1 = Transaction::factory()->enableBanking()->create([ + 'user_id' => $this->user->id, + 'account_id' => $this->account->id, + 'description' => 'Grocery Store', + 'amount' => -5000, + 'category_id' => null, + ]); + $t2 = Transaction::factory()->enableBanking()->create([ + 'user_id' => $this->user->id, + 'account_id' => $this->account->id, + 'description' => 'Grocery Store', + 'amount' => -3000, + 'category_id' => null, + ]); + + $jobId = 'apply-run-1'; + (new ApplySingleAutomationRuleJob($this->rule, $jobId, [$t1->id, $t2->id])) + ->handle(app(AutomationRuleService::class)); + + expect($t1->fresh()->category_id)->toBe($this->category->id) + ->and($t2->fresh()->category_id)->toBe($this->category->id); + + $progress = Cache::get(ApplySingleAutomationRuleJob::cacheKeyForJobId($this->user->id, $jobId)); + expect($progress['status'])->toBe('done') + ->and($progress['total'])->toBe(2) + ->and($progress['processed'])->toBe(2) + ->and($progress['applied'])->toBe(2) + ->and($progress['updated'])->toBe(2); +}); + +test('apply job marks cache as failed and preserves counts', function () { + $jobId = 'apply-failed'; + Cache::put( + ApplySingleAutomationRuleJob::cacheKeyForJobId($this->user->id, $jobId), + ['status' => 'processing', 'processed' => 3, 'total' => 10, 'applied' => 3, 'updated' => 2], + now()->addHour(), + ); + + (new ApplySingleAutomationRuleJob($this->rule, $jobId, ['x', 'y'])) + ->failed(new RuntimeException('boom')); + + $progress = Cache::get(ApplySingleAutomationRuleJob::cacheKeyForJobId($this->user->id, $jobId)); + expect($progress['status'])->toBe('failed') + ->and($progress['processed'])->toBe(3) + ->and($progress['total'])->toBe(10) + ->and($progress['applied'])->toBe(3) + ->and($progress['updated'])->toBe(2); +}); + test('apply endpoint returns done with zero matches when no transactions match', function () { Transaction::factory()->enableBanking()->create([ 'user_id' => $this->user->id, diff --git a/tests/Feature/ReEvaluateTransactionRulesTest.php b/tests/Feature/ReEvaluateTransactionRulesTest.php index db128a12..c4144a7f 100644 --- a/tests/Feature/ReEvaluateTransactionRulesTest.php +++ b/tests/Feature/ReEvaluateTransactionRulesTest.php @@ -337,6 +337,24 @@ test('job queries automation rules once regardless of transaction count', functi expect($ruleQueries)->toBe(1); }); +test('job marks cache as failed and preserves counts', function () { + $jobId = 'reeval-failed'; + Cache::put( + ReEvaluateTransactionRulesJob::cacheKeyForJobId($this->user->id, $jobId), + ['status' => 'processing', 'processed' => 4, 'total' => 20, 'updated' => 2], + now()->addHour(), + ); + + (new ReEvaluateTransactionRulesJob($this->user, $jobId)) + ->failed(new RuntimeException('boom')); + + $progress = Cache::get(ReEvaluateTransactionRulesJob::cacheKeyForJobId($this->user->id, $jobId)); + expect($progress['status'])->toBe('failed') + ->and($progress['processed'])->toBe(4) + ->and($progress['total'])->toBe(20) + ->and($progress['updated'])->toBe(2); +}); + test('job skips encrypted transactions', function () { AutomationRule::factory()->create([ 'user_id' => $this->user->id,