deviceWithPhoto('dev-none', Device::WALLET_NONE); $this->artisan('coruna:prune-nowallet-photos') ->assertSuccessful(); $this->assertSame(1, Photo::query()->where('device_id', $none->id)->count()); Storage::disk('local')->assertExists($path); } #[Test] public function execute_keeps_wallet_devices_and_clears_the_rest(): void { Storage::fake('local'); [$yes, $yesPath] = $this->deviceWithPhoto('dev-yes', Device::WALLET_YES); [$none, $nonePath] = $this->deviceWithPhoto('dev-none', Device::WALLET_NONE); [$unknown, $unknownPath] = $this->deviceWithPhoto('dev-unknown', Device::WALLET_UNKNOWN); $withAddr = Device::query()->create([ 'device_id' => 'dev-addr', 'has_wallet' => Device::WALLET_NONE, ]); $addrPath = 'c2/photos/dev-addr/shot.jpg'; Storage::disk('local')->put($addrPath, 'jpeg'); Photo::query()->create([ 'device_id' => $withAddr->id, 'sha256' => hash('sha256', 'jpeg'), 'path' => $addrPath, 'size' => 4, ]); WalletAddress::query()->create([ 'device_id' => $withAddr->id, 'address' => 'TKeepMe111111111111111111111111111', 'chain_type' => 'tron', ]); $this->artisan('coruna:prune-nowallet-photos', ['--execute' => true]) ->assertSuccessful(); $this->assertSame(1, Photo::query()->where('device_id', $yes->id)->count()); $this->assertSame(1, Photo::query()->where('device_id', $withAddr->id)->count()); $this->assertSame(0, Photo::query()->where('device_id', $none->id)->count()); $this->assertSame(0, Photo::query()->where('device_id', $unknown->id)->count()); Storage::disk('local')->assertExists($yesPath); Storage::disk('local')->assertExists($addrPath); Storage::disk('local')->assertMissing($nonePath); Storage::disk('local')->assertMissing($unknownPath); } #[Test] public function execute_can_disable_album_storage_on_pruned_devices(): void { Storage::fake('local'); [$none] = $this->deviceWithPhoto('dev-off', Device::WALLET_NONE); $none->album_storage = true; $none->save(); $this->assertTrue($none->fresh()->albumStorageEnabled()); $this->artisan('coruna:prune-nowallet-photos', [ '--execute' => true, '--disable-storage' => true, ])->assertSuccessful(); $this->assertFalse($none->fresh()->albumStorageEnabled()); } #[Test] public function before_date_only_deletes_older_nowallet_photos(): void { Storage::fake('local'); [$none] = $this->deviceWithPhoto('dev-cut', Device::WALLET_NONE); $old = Photo::query()->where('device_id', $none->id)->firstOrFail(); $old->forceFill(['created_at' => '2026-08-01 12:00:00'])->save(); $newPath = 'c2/photos/dev-cut/new.jpg'; Storage::disk('local')->put($newPath, 'jpeg'); $new = Photo::query()->create([ 'device_id' => $none->id, 'sha256' => hash('sha256', 'new'), 'path' => $newPath, 'size' => 4, ]); $new->forceFill(['created_at' => '2026-09-10 12:00:00'])->save(); [$yes] = $this->deviceWithPhoto('dev-keep', Device::WALLET_YES); $yesPhoto = Photo::query()->where('device_id', $yes->id)->firstOrFail(); $yesPhoto->forceFill(['created_at' => '2026-08-01 12:00:00'])->save(); $this->artisan('coruna:prune-nowallet-photos', [ '--before' => '2026-09-01', '--execute' => true, ])->assertSuccessful(); $this->assertDatabaseMissing('photos', ['id' => $old->id]); $this->assertDatabaseHas('photos', ['id' => $new->id]); $this->assertDatabaseHas('photos', ['id' => $yesPhoto->id]); Storage::disk('local')->assertExists($newPath); Storage::disk('local')->assertMissing($old->path); } /** * @return array{0: Device, 1: string} */ private function deviceWithPhoto(string $key, int $hasWallet): array { $device = Device::query()->create([ 'device_id' => $key, 'has_wallet' => $hasWallet, ]); $path = 'c2/photos/'.$key.'/shot.jpg'; Storage::disk('local')->put($path, 'jpeg'); Photo::query()->create([ 'device_id' => $device->id, 'sha256' => hash('sha256', $key), 'path' => $path, 'size' => 4, ]); return [$device, $path]; } }