tenant = Tenant::factory()->create(); $this->user = User::factory()->for($this->tenant)->create(); DB::statement('SET app.current_tenant_id = '.$this->tenant->id); Mail::fake(); Storage::fake('local'); }); function storedCsv(int $tenantId, string $body): string { $header = "\xEF\xBB\xBF".'id,Проект,Тег проекта,Телефон,Создано,Напоминание,Комментарий,Состояние,Имя'; $path = "imports/{$tenantId}/test.csv"; Storage::disk('local')->put($path, $header."\n".$body); return $path; } function runImportJob(int $logId, int $tenantId): void { (new ImportLeadsJob($logId, $tenantId))->handle( app(HistoricalImportService::class), app(CsvLeadsParser::class), ); } test('job импортирует лиды и переводит import_log в done', function (): void { $path = storedCsv($this->tenant->id, '7001,Окна,окна,79161112233,2023/05/10 10:00:00,,,Новые,Иван' ); $log = ImportLog::create([ 'tenant_id' => $this->tenant->id, 'user_id' => $this->user->id, 'filename' => 'leads.csv', 'file_path' => $path, 'status' => 'pending', ]); runImportJob($log->id, $this->tenant->id); $log->refresh(); expect($log->status)->toBe('done') ->and($log->rows_added)->toBe(1) ->and($log->finished_at)->not->toBeNull() ->and(Deal::query()->where('source_crm_id', 7001)->exists())->toBeTrue(); Mail::assertSent(ImportCompletedNotification::class); }); test('job переводит import_log в failed при отсутствии файла', function (): void { $log = ImportLog::create([ 'tenant_id' => $this->tenant->id, 'user_id' => $this->user->id, 'filename' => 'leads.csv', 'file_path' => 'imports/missing.csv', 'status' => 'pending', ]); runImportJob($log->id, $this->tenant->id); expect($log->refresh()->status)->toBe('failed') ->and($log->error_message)->not->toBeNull(); }); test('job пишет unknown_statuses_count и rows_skipped', function (): void { $path = storedCsv($this->tenant->id, "7002,Окна,окна,79161112234,2023/05/11 10:00:00,,,Архив,\n". '7003,Окна,окна,BADPHONE,2023/05/12 10:00:00,,,Новые,' ); $log = ImportLog::create([ 'tenant_id' => $this->tenant->id, 'user_id' => $this->user->id, 'filename' => 'leads.csv', 'file_path' => $path, 'status' => 'pending', ]); runImportJob($log->id, $this->tenant->id); $log->refresh(); expect($log->status)->toBe('done') ->and($log->unknown_statuses_count)->toBe(1) // «Архив» ->and($log->rows_skipped)->toBe(1); // битый телефон });