count(2)->create([ 'paddle_product_id' => 'pro_test', 'paddle_price_id' => 'pri_test', ]); BusFacade::fake(); $this->artisan('paddle:sync-packages', [ '--dry-run' => true, '--queue' => true, ])->assertExitCode(0); BusFacade::assertDispatched(SyncPackageToPaddle::class, 2); } public function test_command_filters_packages_by_id(): void { $package = Package::factory()->create(); Package::factory()->create(); BusFacade::fake(); $this->artisan('paddle:sync-packages', [ '--dry-run' => true, '--queue' => true, '--package' => [$package->id], ])->assertExitCode(0); BusFacade::assertDispatched(SyncPackageToPaddle::class, function (SyncPackageToPaddle $job) use ($package) { return $this->getJobPackageId($job) === $package->id; }); } public function test_command_blocks_bulk_sync_with_unmapped_packages(): void { Package::factory()->create([ 'paddle_product_id' => null, 'paddle_price_id' => null, ]); BusFacade::fake(); $this->artisan('paddle:sync-packages', [ '--dry-run' => true, '--queue' => true, ])->assertExitCode(Command::FAILURE); BusFacade::assertNotDispatched(SyncPackageToPaddle::class); } public function test_command_allows_unmapped_packages_when_overridden(): void { Package::factory()->create([ 'paddle_product_id' => null, 'paddle_price_id' => null, ]); BusFacade::fake(); $this->artisan('paddle:sync-packages', [ '--dry-run' => true, '--queue' => true, '--allow-unmapped' => true, ])->assertExitCode(Command::SUCCESS); BusFacade::assertDispatched(SyncPackageToPaddle::class, 1); } protected function getJobPackageId(SyncPackageToPaddle $job): int { $reflection = new \ReflectionClass($job); $property = $reflection->getProperty('packageId'); $property->setAccessible(true); return (int) $property->getValue($job); } }