Certified/tests/Feature/Certificates/CertificateSharingTest.php
Joël van de Wouw ac340d125c
Some checks failed
linter / quality (push) Failing after 13s
tests / ci (8.3) (push) Failing after 2s
tests / ci (8.4) (push) Failing after 2s
tests / ci (8.5) (push) Failing after 3s
Initial commit
Certificate manager built on Laravel 13, Livewire 4, and Flux.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-12 14:44:58 +02:00

105 lines
3.1 KiB
PHP

<?php
use App\Mail\SharedCertificateLinksMail;
use App\Mail\SharedCertificatesMail;
use App\Models\Certificate;
use App\Models\User;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\URL;
use Livewire\Livewire;
beforeEach(function () {
Storage::fake('local');
Mail::fake();
});
function sharableCertificate(User $user): Certificate
{
$path = 'certificates/'.$user->id.'/'.uniqid().'.pdf';
Storage::disk('local')->put($path, 'file-contents');
return Certificate::factory()->for($user)->create(['file_path' => $path]);
}
test('sharing by secure link emails the recipient', function () {
$user = User::factory()->create();
$certificate = sharableCertificate($user);
$this->actingAs($user);
Livewire::test('pages::certificates.index')
->set('selected', [$certificate->id])
->set('shareEmail', 'friend@example.com')
->set('shareMethod', 'link')
->call('share')
->assertHasNoErrors();
Mail::assertSent(SharedCertificateLinksMail::class, fn ($mail) => $mail->hasTo('friend@example.com'));
});
test('sharing by zip emails an attachment and reveals a password', function () {
$user = User::factory()->create();
$certificate = sharableCertificate($user);
$this->actingAs($user);
$component = Livewire::test('pages::certificates.index')
->set('selected', [$certificate->id])
->set('shareEmail', 'friend@example.com')
->set('shareMethod', 'zip')
->call('share')
->assertHasNoErrors();
expect($component->get('sharePassword'))->toHaveLength(12);
Mail::assertSent(SharedCertificatesMail::class, fn ($mail) => $mail->hasTo('friend@example.com'));
});
test('sharing requires a recipient and a selection', function () {
$this->actingAs(User::factory()->create());
Livewire::test('pages::certificates.index')
->set('shareEmail', '')
->set('selected', [])
->call('share')
->assertHasErrors(['shareEmail', 'selected']);
Mail::assertNothingSent();
});
test('sharing is rate limited', function () {
$user = User::factory()->create();
$certificate = sharableCertificate($user);
$this->actingAs($user);
for ($i = 0; $i < 10; $i++) {
RateLimiter::hit('share-certificates:'.$user->id, 3600);
}
Livewire::test('pages::certificates.index')
->set('selected', [$certificate->id])
->set('shareEmail', 'friend@example.com')
->call('share')
->assertHasErrors(['shareEmail']);
Mail::assertNothingSent();
});
test('a valid signed link streams the file to an unauthenticated recipient', function () {
$user = User::factory()->create();
$certificate = sharableCertificate($user);
$url = URL::temporarySignedRoute('shared.certificate', now()->addHours(48), ['certificate' => $certificate->id]);
$this->get($url)->assertOk();
});
test('a tampered signed link is rejected', function () {
$user = User::factory()->create();
$certificate = sharableCertificate($user);
$this->get(route('shared.certificate', $certificate))->assertForbidden();
});