mirror of
https://github.com/HolgerHatGarKeineNode/einundzwanzig-app.git
synced 2026-05-05 04:54:53 +00:00
🔥 **Cleanup & Tests:** Removed the obsolete auth.register component and its related route, feature tests, and browser tests. Disabled public registration and added tests to ensure /register returns a 404. Added new tests for service, lecturer, city, venue, and meetup CRUD flows.
This commit is contained in:
@@ -7,9 +7,3 @@ it('renders the login page with QR code and language selector', function () {
|
||||
->assertSee('Bitcoin, not blockchain')
|
||||
->assertNoJavaScriptErrors();
|
||||
});
|
||||
|
||||
it('renders the registration page', function () {
|
||||
$page = visit('/register');
|
||||
|
||||
$page->assertNoJavaScriptErrors();
|
||||
});
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
use App\Models\City;
|
||||
use App\Models\Country;
|
||||
use App\Models\Venue;
|
||||
|
||||
beforeEach(function () {
|
||||
$this->country = Country::factory()->create(['code' => 'de', 'name' => 'Deutschland']);
|
||||
});
|
||||
|
||||
it('creates a new city end-to-end with valid coordinates', function () {
|
||||
actingAsUser();
|
||||
|
||||
$page = visit('/de/city-create');
|
||||
|
||||
$page->fill('[wire\\:model="name"]', 'BrowserTestCity')
|
||||
->fill('[wire\\:model="latitude"]', '52.520008')
|
||||
->fill('[wire\\:model="longitude"]', '13.404954')
|
||||
->click('[data-flux-button][type="submit"]')
|
||||
->wait(2)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect(City::query()->where('name', 'BrowserTestCity')->exists())->toBeTrue();
|
||||
});
|
||||
|
||||
it('shows validation errors when city form is submitted empty', function () {
|
||||
actingAsUser();
|
||||
|
||||
$page = visit('/de/city-create');
|
||||
|
||||
$page->click('[data-flux-button][type="submit"]')
|
||||
->wait(1)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect(City::query()->count())->toBe(0);
|
||||
});
|
||||
|
||||
it('creates a new venue connected to an existing city', function () {
|
||||
actingAsUser();
|
||||
$city = City::factory()->create(['country_id' => $this->country->id, 'name' => 'VenueTestCity']);
|
||||
|
||||
$page = visit('/de/venue-create');
|
||||
|
||||
$page->fill('[wire\\:model="name"]', 'BrowserTestVenue')
|
||||
->fill('[wire\\:model="street"]', 'Teststraße 1');
|
||||
$page->script("Livewire.getByName('venues.create')[0].set('city_id', {$city->id})");
|
||||
$page->wait(0.5)
|
||||
->click('[data-flux-button][type="submit"]')
|
||||
->wait(2)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect(Venue::query()->where('name', 'BrowserTestVenue')->exists())->toBeTrue();
|
||||
});
|
||||
|
||||
it('shows a validation error when creating a venue without a name', function () {
|
||||
actingAsUser();
|
||||
City::factory()->create(['country_id' => $this->country->id]);
|
||||
|
||||
$page = visit('/de/venue-create');
|
||||
|
||||
$page->fill('[wire\\:model="street"]', 'No-Name Street')
|
||||
->click('[data-flux-button][type="submit"]')
|
||||
->wait(1)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect(Venue::query()->count())->toBe(0);
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Lecturer;
|
||||
|
||||
it('creates a new lecturer end-to-end with valid data', function () {
|
||||
actingAsUser();
|
||||
|
||||
$page = visit('/de/lecturer-create');
|
||||
|
||||
$page->fill('[wire\\:model="name"]', 'BrowserTester Saylor')
|
||||
->fill('[wire\\:model="subtitle"]', 'Browser Test Subject')
|
||||
->fill('[wire\\:model="intro"]', 'A short intro line.')
|
||||
->click('[data-flux-button][type="submit"]')
|
||||
->wait(2)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect(Lecturer::query()->where('name', 'BrowserTester Saylor')->exists())->toBeTrue();
|
||||
});
|
||||
|
||||
it('shows a required error when submitting without a lecturer name', function () {
|
||||
actingAsUser();
|
||||
|
||||
$page = visit('/de/lecturer-create');
|
||||
|
||||
$page->click('[data-flux-button][type="submit"]')
|
||||
->wait(1)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect(Lecturer::query()->count())->toBe(0);
|
||||
});
|
||||
|
||||
it('rejects creation when the lecturer name already exists', function () {
|
||||
actingAsUser();
|
||||
Lecturer::factory()->create(['name' => 'Existing Saylor']);
|
||||
|
||||
$page = visit('/de/lecturer-create');
|
||||
|
||||
$page->fill('[wire\\:model="name"]', 'Existing Saylor')
|
||||
->click('[data-flux-button][type="submit"]')
|
||||
->wait(1)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect(Lecturer::query()->where('name', 'Existing Saylor')->count())->toBe(1);
|
||||
});
|
||||
|
||||
it('rejects creation with an invalid website URL', function () {
|
||||
actingAsUser();
|
||||
|
||||
$page = visit('/de/lecturer-create');
|
||||
|
||||
$page->fill('[wire\\:model="name"]', 'Bad URL Lecturer')
|
||||
->fill('[wire\\:model="website"]', 'not-a-url')
|
||||
->click('[data-flux-button][type="submit"]')
|
||||
->wait(1)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect(Lecturer::query()->where('name', 'Bad URL Lecturer')->exists())->toBeFalse();
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
use App\Models\City;
|
||||
use App\Models\Country;
|
||||
use App\Models\Meetup;
|
||||
|
||||
beforeEach(function () {
|
||||
$this->country = Country::factory()->create(['code' => 'de', 'name' => 'Deutschland']);
|
||||
$this->city = City::factory()->create([
|
||||
'country_id' => $this->country->id,
|
||||
'name' => 'BrowserMeetupTestCity',
|
||||
]);
|
||||
});
|
||||
|
||||
it('creates a new meetup end-to-end via the create form', function () {
|
||||
actingAsUser();
|
||||
$cityId = $this->city->id;
|
||||
|
||||
$page = visit('/de/meetup-create');
|
||||
|
||||
$page->fill('[wire\\:model="name"]', 'BrowserSeeded Meetup');
|
||||
$page->script("Livewire.getByName('meetups.create')[0].set('city_id', {$cityId})");
|
||||
$page->wait(0.5)
|
||||
->select('[wire\\:model="community"]', 'einundzwanzig');
|
||||
$page->script("Livewire.getByName('meetups.create')[0].call('createMeetup')");
|
||||
$page->wait(2)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect(Meetup::query()->where('name', 'BrowserSeeded Meetup')->exists())->toBeTrue();
|
||||
});
|
||||
|
||||
it('blocks meetup creation when the name is missing', function () {
|
||||
actingAsUser();
|
||||
$cityId = $this->city->id;
|
||||
|
||||
$page = visit('/de/meetup-create');
|
||||
|
||||
$page->script("Livewire.getByName('meetups.create')[0].set('city_id', {$cityId})");
|
||||
$page->wait(0.5)
|
||||
->select('[wire\\:model="community"]', 'einundzwanzig');
|
||||
$page->script("Livewire.getByName('meetups.create')[0].call('createMeetup')");
|
||||
$page->wait(1)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect(Meetup::query()->count())->toBe(0);
|
||||
});
|
||||
|
||||
it('blocks meetup creation when no city is selected', function () {
|
||||
actingAsUser();
|
||||
|
||||
$page = visit('/de/meetup-create');
|
||||
|
||||
$page->fill('[wire\\:model="name"]', 'NoCityMeetup')
|
||||
->select('[wire\\:model="community"]', 'einundzwanzig');
|
||||
$page->script("Livewire.getByName('meetups.create')[0].call('createMeetup')");
|
||||
$page->wait(1)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect(Meetup::query()->where('name', 'NoCityMeetup')->exists())->toBeFalse();
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\SelfHostedServiceType;
|
||||
use App\Models\City;
|
||||
use App\Models\Country;
|
||||
use App\Models\Meetup;
|
||||
use App\Models\SelfHostedService;
|
||||
|
||||
/**
|
||||
* NOTE: The Search-Inputs of the index pages use Postgres `ilike`, which the
|
||||
* SQLite test database does not support. We therefore exercise the type-badge
|
||||
* filter (uses plain `=`) instead and assert the index list itself reacts
|
||||
* to it.
|
||||
*/
|
||||
beforeEach(function () {
|
||||
$this->country = Country::factory()->create(['code' => 'de']);
|
||||
$this->city = City::factory()->create(['country_id' => $this->country->id]);
|
||||
});
|
||||
|
||||
it('renders all seeded services on the public services index', function () {
|
||||
SelfHostedService::factory()->create(['name' => 'NodeAlpha', 'type' => SelfHostedServiceType::Mempool]);
|
||||
SelfHostedService::factory()->create(['name' => 'BetaService', 'type' => SelfHostedServiceType::Other]);
|
||||
|
||||
$page = visit('/de/services');
|
||||
|
||||
$page->assertSee('NodeAlpha')
|
||||
->assertSee('BetaService')
|
||||
->assertNoJavaScriptErrors();
|
||||
});
|
||||
|
||||
it('filters services by clicking a type-badge in the type-cloud', function () {
|
||||
SelfHostedService::factory()->create(['name' => 'OnlyMempoolNode', 'type' => SelfHostedServiceType::Mempool]);
|
||||
SelfHostedService::factory()->create(['name' => 'OnlyOtherThing', 'type' => SelfHostedServiceType::Other]);
|
||||
|
||||
$page = visit('/de/services');
|
||||
|
||||
$page->assertSee('OnlyMempoolNode')
|
||||
->assertSee('OnlyOtherThing')
|
||||
->click('[wire\\:click="filterByType(\'mempool\')"]')
|
||||
->wait(1)
|
||||
->assertSee('OnlyMempoolNode')
|
||||
->assertDontSee('OnlyOtherThing')
|
||||
->assertNoJavaScriptErrors();
|
||||
});
|
||||
|
||||
it('shows seeded meetups on the public meetups index', function () {
|
||||
Meetup::factory()->create([
|
||||
'city_id' => $this->city->id,
|
||||
'name' => 'BrowserSeeded Meetup XYZ',
|
||||
'visible_on_map' => true,
|
||||
]);
|
||||
|
||||
$page = visit('/de/meetups');
|
||||
|
||||
$page->assertSee('BrowserSeeded Meetup XYZ')
|
||||
->assertNoJavaScriptErrors();
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\SelfHostedServiceType;
|
||||
use App\Models\SelfHostedService;
|
||||
|
||||
it('creates a new SelfHostedService end-to-end and shows it on the index', function () {
|
||||
actingAsUser();
|
||||
|
||||
$page = visit('/de/service-create');
|
||||
|
||||
$page->fill('[wire\\:model="form.name"]', 'BrowserTestNode')
|
||||
->select('[wire\\:model="form.type"]', SelfHostedServiceType::Mempool->value)
|
||||
->fill('[wire\\:model="form.url_clearnet"]', 'https://browsertest.example.com')
|
||||
->fill('[wire\\:model="form.intro"]', 'A node spun up by a browser test.')
|
||||
->click('[data-flux-button][type="submit"]')
|
||||
->wait(2)
|
||||
->assertNoJavaScriptErrors()
|
||||
->assertSee('BrowserTestNode');
|
||||
|
||||
expect(SelfHostedService::query()->where('name', 'BrowserTestNode')->exists())->toBeTrue();
|
||||
});
|
||||
|
||||
it('blocks submission without a name and shows a required error', function () {
|
||||
actingAsUser();
|
||||
|
||||
$page = visit('/de/service-create');
|
||||
|
||||
$page->select('[wire\\:model="form.type"]', SelfHostedServiceType::Other->value)
|
||||
->fill('[wire\\:model="form.url_clearnet"]', 'https://no-name.example.com')
|
||||
->click('[data-flux-button][type="submit"]')
|
||||
->wait(1)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect(SelfHostedService::query()->count())->toBe(0);
|
||||
});
|
||||
|
||||
it('rejects submission when no URL or IP is provided', function () {
|
||||
actingAsUser();
|
||||
|
||||
$page = visit('/de/service-create');
|
||||
|
||||
$page->fill('[wire\\:model="form.name"]', 'NoUrlService')
|
||||
->select('[wire\\:model="form.type"]', SelfHostedServiceType::Other->value)
|
||||
->click('[data-flux-button][type="submit"]')
|
||||
->wait(1)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect(SelfHostedService::query()->where('name', 'NoUrlService')->exists())->toBeFalse();
|
||||
});
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
it('lets an authenticated user update their profile name and persists it', function () {
|
||||
$user = actingAsUser(['name' => 'Old Name']);
|
||||
|
||||
$page = visit('/de/settings/profile');
|
||||
|
||||
$page->assertSee('Old Name')
|
||||
->fill('name', 'New Browser Name')
|
||||
->click('Save')
|
||||
->wait(1)
|
||||
->assertSee('Saved.')
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect($user->refresh()->name)->toBe('New Browser Name');
|
||||
});
|
||||
|
||||
it('shows a validation error when the profile name is cleared', function () {
|
||||
actingAsUser(['name' => 'Original']);
|
||||
|
||||
$page = visit('/de/settings/profile');
|
||||
|
||||
$page->fill('name', '')
|
||||
->click('Save')
|
||||
->wait(1)
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect(User::query()->where('name', '')->exists())->toBeFalse();
|
||||
});
|
||||
|
||||
it('still shows the updated name after a full page reload', function () {
|
||||
$user = actingAsUser(['name' => 'Before Reload']);
|
||||
|
||||
$page = visit('/de/settings/profile');
|
||||
$page->fill('name', 'After Reload')
|
||||
->click('Save')
|
||||
->wait(1);
|
||||
|
||||
$reloaded = visit('/de/settings/profile');
|
||||
$reloaded->assertSee('After Reload')
|
||||
->assertNoJavaScriptErrors();
|
||||
|
||||
expect($user->refresh()->name)->toBe('After Reload');
|
||||
});
|
||||
@@ -20,7 +20,6 @@ it('loads all listed public pages without console errors or JS errors', function
|
||||
$pages = visit([
|
||||
'/welcome',
|
||||
'/login',
|
||||
'/register',
|
||||
'/forgot-password',
|
||||
'/de/meetups',
|
||||
'/de/courses',
|
||||
|
||||
Reference in New Issue
Block a user