create(); $failed = DataExport::query()->create([ 'user_id' => $user->id, 'status' => DataExport::STATUS_FAILED, 'scope' => DataExportScope::TENANT->value, ]); $canceled = DataExport::query()->create([ 'user_id' => $user->id, 'status' => DataExport::STATUS_CANCELED, 'scope' => DataExportScope::TENANT->value, ]); $pending = DataExport::query()->create([ 'user_id' => $user->id, 'status' => DataExport::STATUS_PENDING, 'scope' => DataExportScope::TENANT->value, ]); $this->assertTrue($failed->canRetry()); $this->assertTrue($canceled->canRetry()); $this->assertFalse($pending->canRetry()); } public function test_can_cancel_only_for_pending_or_processing_exports(): void { $user = User::factory()->create(); $pending = DataExport::query()->create([ 'user_id' => $user->id, 'status' => DataExport::STATUS_PENDING, 'scope' => DataExportScope::TENANT->value, ]); $processing = DataExport::query()->create([ 'user_id' => $user->id, 'status' => DataExport::STATUS_PROCESSING, 'scope' => DataExportScope::TENANT->value, ]); $ready = DataExport::query()->create([ 'user_id' => $user->id, 'status' => DataExport::STATUS_READY, 'scope' => DataExportScope::TENANT->value, ]); $this->assertTrue($pending->canCancel()); $this->assertTrue($processing->canCancel()); $this->assertFalse($ready->canCancel()); } public function test_reset_for_retry_clears_export_fields(): void { $user = User::factory()->create(); $export = DataExport::query()->create([ 'user_id' => $user->id, 'status' => DataExport::STATUS_FAILED, 'scope' => DataExportScope::TENANT->value, 'error_message' => 'Boom', 'path' => 'exports/test.zip', 'size_bytes' => 123, 'expires_at' => now()->addDay(), ]); $export->resetForRetry(); $export->refresh(); $this->assertSame(DataExport::STATUS_PENDING, $export->status); $this->assertNull($export->error_message); $this->assertNull($export->path); $this->assertNull($export->size_bytes); $this->assertNull($export->expires_at); } public function test_mark_canceled_sets_status_and_clears_export_fields(): void { $user = User::factory()->create(); $export = DataExport::query()->create([ 'user_id' => $user->id, 'status' => DataExport::STATUS_PENDING, 'scope' => DataExportScope::TENANT->value, 'path' => 'exports/test.zip', 'size_bytes' => 321, 'expires_at' => now()->addDay(), ]); $export->markCanceled('Manual cancel.'); $export->refresh(); $this->assertSame(DataExport::STATUS_CANCELED, $export->status); $this->assertSame('Manual cancel.', $export->error_message); $this->assertNull($export->path); $this->assertNull($export->size_bytes); $this->assertNull($export->expires_at); } public function test_generate_data_export_ignores_non_pending_exports(): void { $user = User::factory()->create(); $export = DataExport::query()->create([ 'user_id' => $user->id, 'status' => DataExport::STATUS_CANCELED, 'scope' => DataExportScope::TENANT->value, ]); (new GenerateDataExport($export->id))->handle(); $export->refresh(); $this->assertSame(DataExport::STATUS_CANCELED, $export->status); } }