mirror of
https://github.com/HolgerHatGarKeineNode/einundzwanzig-app.git
synced 2026-05-03 16:24:55 +00:00
✨ **Tests & Nullable Fixes:** Added tests to ensure no crashes when nullable Livewire properties are explicitly set to null. Updated several Livewire components to handle nullable properties gracefully. 🚀
This commit is contained in:
@@ -14,8 +14,8 @@ class extends Component {
|
||||
public $country = 'de';
|
||||
public string $name = '';
|
||||
public ?int $country_id = null;
|
||||
public float $latitude = 0;
|
||||
public float $longitude = 0;
|
||||
public ?float $latitude = null;
|
||||
public ?float $longitude = null;
|
||||
public ?int $population = null;
|
||||
public ?string $population_date = null;
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ class extends Component {
|
||||
public City $city;
|
||||
public string $name = '';
|
||||
public ?int $country_id = null;
|
||||
public float $latitude = 0;
|
||||
public float $longitude = 0;
|
||||
public ?float $latitude = null;
|
||||
public ?float $longitude = null;
|
||||
public ?int $population = null;
|
||||
public ?string $population_date = null;
|
||||
|
||||
|
||||
@@ -21,10 +21,10 @@ class extends Component {
|
||||
#[Locked]
|
||||
public $country = 'de';
|
||||
|
||||
public string $fromDate = '';
|
||||
public string $fromTime = '';
|
||||
public string $toDate = '';
|
||||
public string $toTime = '';
|
||||
public ?string $fromDate = null;
|
||||
public ?string $fromTime = null;
|
||||
public ?string $toDate = null;
|
||||
public ?string $toTime = null;
|
||||
|
||||
#[Validate('required|exists:venues,id')]
|
||||
public ?int $venue_id = null;
|
||||
|
||||
@@ -20,14 +20,14 @@ class extends Component {
|
||||
#[Locked]
|
||||
public $country = 'de';
|
||||
|
||||
public string $startDate = '';
|
||||
public string $startTime = '';
|
||||
public ?string $startDate = null;
|
||||
public ?string $startTime = null;
|
||||
|
||||
// Explicitly track timezone for reactivity
|
||||
public string $userTimezone = '';
|
||||
|
||||
public bool $seriesMode = false;
|
||||
public string $endDate = '';
|
||||
public ?string $endDate = null;
|
||||
|
||||
public ?RecurrenceType $recurrenceType = null;
|
||||
public ?string $recurrenceDayOfWeek = null;
|
||||
|
||||
@@ -39,8 +39,8 @@ class extends Component {
|
||||
// New City Modal
|
||||
public string $newCityName = '';
|
||||
public ?int $newCityCountryId = null;
|
||||
public float $newCityLatitude = 0;
|
||||
public float $newCityLongitude = 0;
|
||||
public ?float $newCityLatitude = null;
|
||||
public ?float $newCityLongitude = null;
|
||||
|
||||
public function createCity(): void
|
||||
{
|
||||
|
||||
@@ -56,8 +56,8 @@ class extends Component {
|
||||
// New City Modal
|
||||
public string $newCityName = '';
|
||||
public ?int $newCityCountryId = null;
|
||||
public float $newCityLatitude = 0;
|
||||
public float $newCityLongitude = 0;
|
||||
public ?float $newCityLatitude = null;
|
||||
public ?float $newCityLongitude = null;
|
||||
|
||||
public function createCity(): void
|
||||
{
|
||||
|
||||
+17
-10
@@ -1,5 +1,10 @@
|
||||
<?php
|
||||
|
||||
use App\Http\Controllers\DownloadMeetupCalendar;
|
||||
use App\Http\Controllers\ImageController;
|
||||
use App\Jobs\FetchNostrProfileJob;
|
||||
use App\Livewire\Helper\FollowTheRabbit;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
use Laravel\Nightwatch\Http\Middleware\Sample;
|
||||
|
||||
@@ -8,13 +13,15 @@ Route::redirect('/', 'welcome');
|
||||
|
||||
// Test route that dispatches a job to fetch Nostr profile for user with ID 1426
|
||||
Route::get('test', function () {
|
||||
\App\Jobs\FetchNostrProfileJob::dispatchSync(\App\Models\User::find(1426));
|
||||
FetchNostrProfileJob::dispatchSync(User::find(1426));
|
||||
});
|
||||
|
||||
// Error page route that aborts with given HTTP status code
|
||||
Route::get('error/{code}', function ($code) {
|
||||
abort($code);
|
||||
});
|
||||
// Error page route that aborts with given HTTP status code (digits only,
|
||||
// constrained to valid 4xx/5xx range to avoid TypeErrors from bot scans).
|
||||
Route::get('error/{code}', function (string $code) {
|
||||
$code = (int) $code;
|
||||
abort($code >= 400 && $code <= 599 ? $code : 404);
|
||||
})->where('code', '[0-9]{3}');
|
||||
|
||||
/*
|
||||
* Commented out routes related to book rental download and display
|
||||
@@ -38,16 +45,16 @@ Route::middleware([])
|
||||
->name('buecherverleih');*/
|
||||
|
||||
// Route for rabbit following helper page - Updated for Livewire v4
|
||||
Route::livewire('/kaninchenbau', \App\Livewire\Helper\FollowTheRabbit::class)
|
||||
Route::livewire('/kaninchenbau', FollowTheRabbit::class)
|
||||
->name('kaninchenbau');
|
||||
|
||||
// Generic image handler route that serves images from storage
|
||||
Route::get('/img/{path}', \App\Http\Controllers\ImageController::class)
|
||||
Route::get('/img/{path}', ImageController::class)
|
||||
->where('path', '.*')
|
||||
->name('img');
|
||||
|
||||
// Public image handler route for serving public images
|
||||
Route::get('/img-public/{path}', \App\Http\Controllers\ImageController::class)
|
||||
Route::get('/img-public/{path}', ImageController::class)
|
||||
->where('path', '.*')
|
||||
->name('imgPublic');
|
||||
|
||||
@@ -55,7 +62,7 @@ Route::get('/img-public/{path}', \App\Http\Controllers\ImageController::class)
|
||||
Route::livewire('/welcome', 'welcome')->name('welcome');
|
||||
|
||||
// Stream calendar route to download meetup calendar as ICS file
|
||||
Route::get('stream-calendar', \App\Http\Controllers\DownloadMeetupCalendar::class)
|
||||
Route::get('stream-calendar', DownloadMeetupCalendar::class)
|
||||
->name('ics')
|
||||
->middleware(['throttle:calendar', Sample::never()]);
|
||||
|
||||
@@ -78,7 +85,7 @@ Route::middleware([])
|
||||
->group(function () {
|
||||
/* OLD URLS - redirects for legacy URLs */
|
||||
// Redirect old meetup calendar route to new one
|
||||
Route::get('meetup/stream-calendar', \App\Http\Controllers\DownloadMeetupCalendar::class)
|
||||
Route::get('meetup/stream-calendar', DownloadMeetupCalendar::class)
|
||||
->name('ics-meetup')
|
||||
->middleware(['throttle:calendar', Sample::never()]);
|
||||
// Redirect old meetup overview URL to new meetups page
|
||||
|
||||
@@ -22,12 +22,32 @@ it('creates a City with valid data', function () {
|
||||
expect(City::query()->where('name', 'Berlin')->exists())->toBeTrue();
|
||||
});
|
||||
|
||||
it('rejects city creation without a name (country_id is preset by mount() from the route prefix)', function () {
|
||||
it('rejects city creation when required fields are blank (country_id is preset by mount() from the route prefix)', function () {
|
||||
actingAsUser();
|
||||
|
||||
Livewire::test('cities.create')
|
||||
->call('createCity')
|
||||
->assertHasErrors(['name' => 'required']);
|
||||
->assertHasErrors([
|
||||
'name' => 'required',
|
||||
'latitude' => 'required',
|
||||
'longitude' => 'required',
|
||||
]);
|
||||
});
|
||||
|
||||
it('does not crash with PropertyNotFoundException when latitude is set to null', function () {
|
||||
actingAsUser();
|
||||
Livewire::test('cities.create')
|
||||
->set('latitude', null)
|
||||
->assertStatus(200)
|
||||
->assertSet('latitude', null);
|
||||
});
|
||||
|
||||
it('does not crash with PropertyNotFoundException when longitude is set to null', function () {
|
||||
actingAsUser();
|
||||
Livewire::test('cities.create')
|
||||
->set('longitude', null)
|
||||
->assertStatus(200)
|
||||
->assertSet('longitude', null);
|
||||
});
|
||||
|
||||
it('rejects city creation when country_id is explicitly cleared', function () {
|
||||
|
||||
@@ -53,3 +53,33 @@ it('mounts courses.create-edit-events for existing event', function () {
|
||||
'event' => $this->event,
|
||||
])->assertStatus(200);
|
||||
});
|
||||
|
||||
it('does not crash with PropertyNotFoundException when fromDate is set to null', function () {
|
||||
actingAsUser();
|
||||
Livewire::test('courses.create-edit-events', ['course' => $this->course])
|
||||
->set('fromDate', null)
|
||||
->assertStatus(200)
|
||||
->assertSet('fromDate', null);
|
||||
});
|
||||
|
||||
it('does not crash when toDate is set to null', function () {
|
||||
actingAsUser();
|
||||
Livewire::test('courses.create-edit-events', ['course' => $this->course])
|
||||
->set('toDate', null)
|
||||
->assertStatus(200)
|
||||
->assertSet('toDate', null);
|
||||
});
|
||||
|
||||
it('does not crash when fromTime is set to null', function () {
|
||||
actingAsUser();
|
||||
Livewire::test('courses.create-edit-events', ['course' => $this->course])
|
||||
->set('fromTime', null)
|
||||
->assertStatus(200);
|
||||
});
|
||||
|
||||
it('does not crash when toTime is set to null', function () {
|
||||
actingAsUser();
|
||||
Livewire::test('courses.create-edit-events', ['course' => $this->course])
|
||||
->set('toTime', null)
|
||||
->assertStatus(200);
|
||||
});
|
||||
|
||||
@@ -46,3 +46,30 @@ it('mounts meetups.create-edit-events for existing event', function () {
|
||||
'event' => $this->event,
|
||||
])->assertStatus(200);
|
||||
});
|
||||
|
||||
it('does not crash with PropertyNotFoundException when startDate is set to null in series mode', function () {
|
||||
actingAsUser();
|
||||
Livewire::test('meetups.create-edit-events', ['meetup' => $this->meetup])
|
||||
->set('seriesMode', true)
|
||||
->set('endDate', '2026-10-27')
|
||||
->set('startDate', null)
|
||||
->assertStatus(200)
|
||||
->assertSet('startDate', null);
|
||||
});
|
||||
|
||||
it('does not crash when endDate is set to null in series mode', function () {
|
||||
actingAsUser();
|
||||
Livewire::test('meetups.create-edit-events', ['meetup' => $this->meetup])
|
||||
->set('seriesMode', true)
|
||||
->set('endDate', null)
|
||||
->assertStatus(200)
|
||||
->assertSet('endDate', null);
|
||||
});
|
||||
|
||||
it('does not crash when startTime is set to null', function () {
|
||||
actingAsUser();
|
||||
Livewire::test('meetups.create-edit-events', ['meetup' => $this->meetup])
|
||||
->set('startTime', null)
|
||||
->assertStatus(200)
|
||||
->assertSet('startTime', null);
|
||||
});
|
||||
|
||||
@@ -98,3 +98,19 @@ it('creates a city via createCity within the meetup-create flow', function () {
|
||||
|
||||
expect(City::query()->where('name', 'Hamburg')->exists())->toBeTrue();
|
||||
});
|
||||
|
||||
it('does not crash with PropertyNotFoundException when newCityLatitude is set to null', function () {
|
||||
actingAsUser();
|
||||
Livewire::test('meetups.create')
|
||||
->set('newCityLatitude', null)
|
||||
->assertStatus(200)
|
||||
->assertSet('newCityLatitude', null);
|
||||
});
|
||||
|
||||
it('does not crash with PropertyNotFoundException when newCityLongitude is set to null', function () {
|
||||
actingAsUser();
|
||||
Livewire::test('meetups.create')
|
||||
->set('newCityLongitude', null)
|
||||
->assertStatus(200)
|
||||
->assertSet('newCityLongitude', null);
|
||||
});
|
||||
|
||||
@@ -55,6 +55,30 @@ it('returns 404 for the application fallback route', function () {
|
||||
$this->get('/this-route-does-not-exist')->assertNotFound();
|
||||
});
|
||||
|
||||
it('aborts with the requested status code for /error/{code}', function () {
|
||||
$this->get('/error/418')->assertStatus(418);
|
||||
});
|
||||
it('aborts with the requested status code for /error/{code}', function (int $code) {
|
||||
$this->get('/error/'.$code)->assertStatus($code);
|
||||
})->with([
|
||||
'teapot' => 418,
|
||||
'forbidden' => 403,
|
||||
'not found' => 404,
|
||||
'server error' => 500,
|
||||
]);
|
||||
|
||||
it('returns 404 for /error/{code} when the code is not three digits', function (string $path) {
|
||||
$this->get($path)->assertNotFound();
|
||||
})->with([
|
||||
'non-numeric' => '/error/error.log',
|
||||
'letters' => '/error/abc',
|
||||
'two digits' => '/error/42',
|
||||
'four digits' => '/error/1000',
|
||||
'mixed' => '/error/4xx',
|
||||
'path traversal' => '/error/..%2Fetc%2Fpasswd',
|
||||
]);
|
||||
|
||||
it('returns 404 for /error/{code} when code is outside the 4xx-5xx range', function (string $path) {
|
||||
$this->get($path)->assertNotFound();
|
||||
})->with([
|
||||
'success' => '/error/200',
|
||||
'redirect' => '/error/301',
|
||||
'too high' => '/error/600',
|
||||
]);
|
||||
|
||||
Reference in New Issue
Block a user