🔥 **Cleanup:** Removed BookCase and OrangePill models, factories, migrations, and related references. Added tests for new service and meetup creation flows. Updated PHPUnit settings and browser-specific configurations.

This commit is contained in:
BT
2026-05-02 22:00:26 +01:00
parent 63aed880e1
commit 04e3e30fcf
54 changed files with 3440 additions and 298 deletions
@@ -0,0 +1,43 @@
<?php
use Illuminate\Auth\Events\Verified;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\URL;
it('verifies the email when the signed URL is correct', function () {
Event::fake();
$user = actingAsUser(['email_verified_at' => null]);
$verifyUrl = URL::temporarySignedRoute(
'verification.verify',
now()->addMinutes(60),
['id' => $user->id, 'hash' => sha1($user->email)],
);
$this->get($verifyUrl)->assertRedirect();
expect($user->refresh()->hasVerifiedEmail())->toBeTrue();
Event::assertDispatched(Verified::class);
});
it('does not re-fire the Verified event when email is already verified', function () {
Event::fake();
$user = actingAsUser(['email_verified_at' => now()]);
$verifyUrl = URL::temporarySignedRoute(
'verification.verify',
now()->addMinutes(60),
['id' => $user->id, 'hash' => sha1($user->email)],
);
$this->get($verifyUrl)->assertRedirect();
Event::assertNotDispatched(Verified::class);
});
it('rejects an invalid signed URL with 403', function () {
actingAsUser(['email_verified_at' => null]);
$this->get(route('verification.verify', ['id' => 1, 'hash' => 'invalid']))
->assertForbidden();
});
+60
View File
@@ -0,0 +1,60 @@
<?php
use App\Models\LoginKey;
use App\Models\User;
it('returns invalid request parameters when k1 is missing', function () {
$this->get('/api/lnurl-auth-callback')
->assertStatus(400)
->assertJson([
'status' => 'ERROR',
'reason' => 'Invalid request parameters',
]);
});
it('returns invalid request parameters when k1 is the wrong length', function () {
$this->getJson('/api/lnurl-auth-callback?'.http_build_query([
'k1' => 'tooshort',
'sig' => str_repeat('a', 128),
'key' => str_repeat('a', 64),
]))
->assertStatus(400)
->assertJson(['status' => 'ERROR']);
});
it('returns invalid request parameters when k1 is not hex', function () {
$this->getJson('/api/lnurl-auth-callback?'.http_build_query([
'k1' => str_repeat('Z', 64),
'sig' => str_repeat('a', 128),
'key' => str_repeat('a', 64),
]))
->assertStatus(400)
->assertJson(['status' => 'ERROR']);
});
it('returns no error from /api/check-auth-error when k1 is missing', function () {
$this->postJson('/api/check-auth-error', [])
->assertSuccessful()
->assertJson(['error' => null]);
});
it('returns no error from /api/check-auth-error when a recent LoginKey exists', function () {
$user = User::factory()->create();
$loginKey = LoginKey::factory()->create([
'user_id' => $user->id,
'created_at' => now(),
]);
$this->postJson('/api/check-auth-error', ['k1' => $loginKey->k1])
->assertSuccessful()
->assertJson(['error' => null]);
});
it('returns a session-expired error when no LoginKey exists and elapsed_seconds exceeds 300', function () {
$this->postJson('/api/check-auth-error', [
'k1' => str_repeat('a', 64),
'elapsed_seconds' => 400,
])
->assertSuccessful()
->assertJson(['error' => 'Session expired. Please try again.']);
});
+37
View File
@@ -0,0 +1,37 @@
<?php
use App\Jobs\FetchNostrProfileJob;
use App\Models\User;
use Illuminate\Support\Facades\Queue;
use Livewire\Livewire;
it('creates a new user and dispatches FetchNostrProfileJob when an unknown pubkey logs in', function () {
Queue::fake();
$pubkey = 'npub1'.str_repeat('z', 58);
Livewire::test('auth.login')
->dispatch('nostrLoggedIn', pubkey: $pubkey)
->assertRedirect();
$user = User::query()->where('nostr', $pubkey)->first();
expect($user)->not->toBeNull()
->and((bool) $user->is_lecturer)->toBeTrue()
->and($user->email)->toEndWith('@portal.einundzwanzig.space');
Queue::assertPushed(FetchNostrProfileJob::class);
expect(auth()->id())->toBe($user->id);
});
it('logs in an existing user without creating a duplicate when their pubkey is already known', function () {
Queue::fake();
$pubkey = 'npub1'.str_repeat('a', 58);
$existing = User::factory()->create(['nostr' => $pubkey]);
Livewire::test('auth.login')
->dispatch('nostrLoggedIn', pubkey: $pubkey)
->assertRedirect();
expect(User::query()->where('nostr', $pubkey)->count())->toBe(1);
expect(auth()->id())->toBe($existing->id);
Queue::assertPushed(FetchNostrProfileJob::class);
});