user = User::factory()->create(); // Provide a dummy clamav scanner binding so any scanning calls are mocked $this->app->instance('clamav', new class { public function scan(string $path): bool { return true; } }); $filesystem = $this->app->make(FilesystemManager::class); $this->service = new UploadDraftService($filesystem, 'local'); } public function test_createDraft_creates_directory_and_writes_meta() { $result = $this->service->createDraft(['title' => 'Test Draft', 'user_id' => $this->user->id, 'type' => 'image']); $this->assertArrayHasKey('id', $result); $id = $result['id']; Storage::disk('local')->assertExists("tmp/drafts/{$id}"); Storage::disk('local')->assertExists("tmp/drafts/{$id}/meta.json"); $meta = json_decode(Storage::disk('local')->get("tmp/drafts/{$id}/meta.json"), true); $this->assertSame('Test Draft', $meta['title']); $this->assertSame($id, $meta['id']); } public function test_storeMainFile_saves_file_and_updates_meta() { $draft = $this->service->createDraft(['user_id' => $this->user->id, 'type' => 'image']); $id = $draft['id']; $file = UploadedFile::fake()->create('song.mp3', 1500, 'audio/mpeg'); $info = $this->service->storeMainFile($id, $file); $this->assertArrayHasKey('path', $info); Storage::disk('local')->assertExists($info['path']); $meta = json_decode(Storage::disk('local')->get("tmp/drafts/{$id}/meta.json"), true); $this->assertArrayHasKey('main_file', $meta); $this->assertSame($info['hash'], $meta['main_file']['hash']); } public function test_storeScreenshot_saves_file_and_appends_meta() { $draft = $this->service->createDraft(['user_id' => $this->user->id, 'type' => 'image']); $id = $draft['id']; $img = UploadedFile::fake()->image('thumb.jpg', 640, 480); $info = $this->service->storeScreenshot($id, $img); $this->assertArrayHasKey('path', $info); Storage::disk('local')->assertExists($info['path']); $meta = json_decode(Storage::disk('local')->get("tmp/drafts/{$id}/meta.json"), true); $this->assertArrayHasKey('screenshots', $meta); $this->assertCount(1, $meta['screenshots']); $this->assertSame($info['hash'], $meta['screenshots'][0]['hash']); } public function test_calculateHash_for_local_file_and_storage_path() { $file = UploadedFile::fake()->create('doc.pdf', 10); $realPath = $file->getRealPath(); $expected = hash_file('sha256', $realPath); $this->assertSame($expected, $this->service->calculateHash($realPath)); // Store into drafts and calculate by storage path $draft = $this->service->createDraft(['user_id' => $this->user->id, 'type' => 'image']); $id = $draft['id']; $info = $this->service->storeMainFile($id, $file); $storageHash = $this->service->calculateHash($info['path']); $storedContents = Storage::disk('local')->get($info['path']); $this->assertSame(hash('sha256', $storedContents), $storageHash); } public function test_setExpiration_writes_expires_at_in_meta() { $draft = $this->service->createDraft(['user_id' => $this->user->id, 'type' => 'image']); $id = $draft['id']; $when = Carbon::now()->addDays(3); $ok = $this->service->setExpiration($id, $when); $this->assertTrue($ok); $meta = json_decode(Storage::disk('local')->get("tmp/drafts/{$id}/meta.json"), true); $this->assertArrayHasKey('expires_at', $meta); $this->assertSame($when->toISOString(), $meta['expires_at']); } public function test_calculateHash_throws_for_missing_file() { $this->expectException(\RuntimeException::class); $this->service->calculateHash('this/path/does/not/exist'); } }