**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:
BT
2026-05-02 22:27:06 +01:00
parent 172217d388
commit b3a688cf2b
12 changed files with 154 additions and 30 deletions
+22 -2
View File
@@ -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);
});
+27 -3
View File
@@ -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',
]);