feat: Implement rides management with CRUD functionality

- Added rides index view with search and filter options.
- Created rides show view to display ride details.
- Implemented API routes for rides.
- Developed authentication routes for user registration, login, and email verification.
- Created tests for authentication, email verification, password reset, and user profile management.
- Added feature tests for rides and operators, including creation, updating, deletion, and searching.
- Implemented soft deletes and caching for rides and operators.
- Enhanced manufacturer and operator model tests for various functionalities.
This commit is contained in:
pacnpal
2025-06-19 22:34:10 -04:00
parent 86263db9d9
commit cc33781245
148 changed files with 14026 additions and 2482 deletions

View File

@@ -0,0 +1,86 @@
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Volt\Volt;
use Tests\TestCase;
class AuthenticationTest extends TestCase
{
use RefreshDatabase;
public function test_login_screen_can_be_rendered(): void
{
$response = $this->get('/login');
$response
->assertOk()
->assertSeeVolt('pages.auth.login');
}
public function test_users_can_authenticate_using_the_login_screen(): void
{
$user = User::factory()->create();
$component = Volt::test('pages.auth.login')
->set('form.email', $user->email)
->set('form.password', 'password');
$component->call('login');
$component
->assertHasNoErrors()
->assertRedirect(route('dashboard', absolute: false));
$this->assertAuthenticated();
}
public function test_users_can_not_authenticate_with_invalid_password(): void
{
$user = User::factory()->create();
$component = Volt::test('pages.auth.login')
->set('form.email', $user->email)
->set('form.password', 'wrong-password');
$component->call('login');
$component
->assertHasErrors()
->assertNoRedirect();
$this->assertGuest();
}
public function test_navigation_menu_can_be_rendered(): void
{
$user = User::factory()->create();
$this->actingAs($user);
$response = $this->get('/dashboard');
$response
->assertOk()
->assertSeeVolt('layout.navigation');
}
public function test_users_can_logout(): void
{
$user = User::factory()->create();
$this->actingAs($user);
$component = Volt::test('layout.navigation');
$component->call('logout');
$component
->assertHasNoErrors()
->assertRedirect('/');
$this->assertGuest();
}
}

View File

@@ -0,0 +1,60 @@
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use Illuminate\Auth\Events\Verified;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\Facades\URL;
use Tests\TestCase;
class EmailVerificationTest extends TestCase
{
use RefreshDatabase;
public function test_email_verification_screen_can_be_rendered(): void
{
$user = User::factory()->unverified()->create();
$response = $this->actingAs($user)->get('/verify-email');
$response
->assertSeeVolt('pages.auth.verify-email')
->assertStatus(200);
}
public function test_email_can_be_verified(): void
{
$user = User::factory()->unverified()->create();
Event::fake();
$verificationUrl = URL::temporarySignedRoute(
'verification.verify',
now()->addMinutes(60),
['id' => $user->id, 'hash' => sha1($user->email)]
);
$response = $this->actingAs($user)->get($verificationUrl);
Event::assertDispatched(Verified::class);
$this->assertTrue($user->fresh()->hasVerifiedEmail());
$response->assertRedirect(route('dashboard', absolute: false).'?verified=1');
}
public function test_email_is_not_verified_with_invalid_hash(): void
{
$user = User::factory()->unverified()->create();
$verificationUrl = URL::temporarySignedRoute(
'verification.verify',
now()->addMinutes(60),
['id' => $user->id, 'hash' => sha1('wrong-email')]
);
$this->actingAs($user)->get($verificationUrl);
$this->assertFalse($user->fresh()->hasVerifiedEmail());
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Volt\Volt;
use Tests\TestCase;
class PasswordConfirmationTest extends TestCase
{
use RefreshDatabase;
public function test_confirm_password_screen_can_be_rendered(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->get('/confirm-password');
$response
->assertSeeVolt('pages.auth.confirm-password')
->assertStatus(200);
}
public function test_password_can_be_confirmed(): void
{
$user = User::factory()->create();
$this->actingAs($user);
$component = Volt::test('pages.auth.confirm-password')
->set('password', 'password');
$component->call('confirmPassword');
$component
->assertRedirect('/dashboard')
->assertHasNoErrors();
}
public function test_password_is_not_confirmed_with_invalid_password(): void
{
$user = User::factory()->create();
$this->actingAs($user);
$component = Volt::test('pages.auth.confirm-password')
->set('password', 'wrong-password');
$component->call('confirmPassword');
$component
->assertNoRedirect()
->assertHasErrors('password');
}
}

View File

@@ -0,0 +1,84 @@
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use Illuminate\Auth\Notifications\ResetPassword;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Notification;
use Livewire\Volt\Volt;
use Tests\TestCase;
class PasswordResetTest extends TestCase
{
use RefreshDatabase;
public function test_reset_password_link_screen_can_be_rendered(): void
{
$response = $this->get('/forgot-password');
$response
->assertSeeVolt('pages.auth.forgot-password')
->assertStatus(200);
}
public function test_reset_password_link_can_be_requested(): void
{
Notification::fake();
$user = User::factory()->create();
Volt::test('pages.auth.forgot-password')
->set('email', $user->email)
->call('sendPasswordResetLink');
Notification::assertSentTo($user, ResetPassword::class);
}
public function test_reset_password_screen_can_be_rendered(): void
{
Notification::fake();
$user = User::factory()->create();
Volt::test('pages.auth.forgot-password')
->set('email', $user->email)
->call('sendPasswordResetLink');
Notification::assertSentTo($user, ResetPassword::class, function ($notification) {
$response = $this->get('/reset-password/'.$notification->token);
$response
->assertSeeVolt('pages.auth.reset-password')
->assertStatus(200);
return true;
});
}
public function test_password_can_be_reset_with_valid_token(): void
{
Notification::fake();
$user = User::factory()->create();
Volt::test('pages.auth.forgot-password')
->set('email', $user->email)
->call('sendPasswordResetLink');
Notification::assertSentTo($user, ResetPassword::class, function ($notification) use ($user) {
$component = Volt::test('pages.auth.reset-password', ['token' => $notification->token])
->set('email', $user->email)
->set('password', 'password')
->set('password_confirmation', 'password');
$component->call('resetPassword');
$component
->assertRedirect('/login')
->assertHasNoErrors();
return true;
});
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Hash;
use Livewire\Volt\Volt;
use Tests\TestCase;
class PasswordUpdateTest extends TestCase
{
use RefreshDatabase;
public function test_password_can_be_updated(): void
{
$user = User::factory()->create();
$this->actingAs($user);
$component = Volt::test('profile.update-password-form')
->set('current_password', 'password')
->set('password', 'new-password')
->set('password_confirmation', 'new-password')
->call('updatePassword');
$component
->assertHasNoErrors()
->assertNoRedirect();
$this->assertTrue(Hash::check('new-password', $user->refresh()->password));
}
public function test_correct_password_must_be_provided_to_update_password(): void
{
$user = User::factory()->create();
$this->actingAs($user);
$component = Volt::test('profile.update-password-form')
->set('current_password', 'wrong-password')
->set('password', 'new-password')
->set('password_confirmation', 'new-password')
->call('updatePassword');
$component
->assertHasErrors(['current_password'])
->assertNoRedirect();
}
}

View File

@@ -0,0 +1,36 @@
<?php
namespace Tests\Feature\Auth;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Volt\Volt;
use Tests\TestCase;
class RegistrationTest extends TestCase
{
use RefreshDatabase;
public function test_registration_screen_can_be_rendered(): void
{
$response = $this->get('/register');
$response
->assertOk()
->assertSeeVolt('pages.auth.register');
}
public function test_new_users_can_register(): void
{
$component = Volt::test('pages.auth.register')
->set('name', 'Test User')
->set('email', 'test@example.com')
->set('password', 'password')
->set('password_confirmation', 'password');
$component->call('register');
$component->assertRedirect(route('dashboard', absolute: false));
$this->assertAuthenticated();
}
}

View File

@@ -1,7 +1,21 @@
<?php
it('returns a successful response', function () {
$response = $this->get('/');
namespace Tests\Feature;
$response->assertStatus(200);
});
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ExampleTest extends TestCase
{
use RefreshDatabase;
/**
* A basic feature test example.
*/
public function test_the_application_returns_a_successful_response(): void
{
$response = $this->get('/');
$response->assertStatus(200);
}
}

View File

@@ -0,0 +1,179 @@
<?php
namespace Tests\Feature;
use App\Models\Manufacturer;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
/**
* Manufacturer Model Feature Tests
*
* Tests for ThrillWiki Manufacturer model functionality
*/
class ManufacturerTest extends TestCase
{
use RefreshDatabase, WithFaker;
/**
* Test model creation.
*/
public function test_can_create_manufacturer(): void
{
$manufacturer = Manufacturer::factory()->create();
$this->assertDatabaseHas('manufacturers', [
'id' => $manufacturer->id,
'name' => $manufacturer->name,
]);
}
/**
* Test model factory.
*/
public function test_manufacturer_factory_works(): void
{
$manufacturer = Manufacturer::factory()->create();
$this->assertInstanceOf(Manufacturer::class, $manufacturer);
$this->assertNotEmpty($manufacturer->name);
$this->assertIsBool($manufacturer->is_active);
}
/**
* Test active scope.
*/
public function test_active_scope_filters_correctly(): void
{
Manufacturer::factory()->active()->create();
Manufacturer::factory()->inactive()->create();
$activeCount = Manufacturer::active()->count();
$totalCount = Manufacturer::count();
$this->assertEquals(1, $activeCount);
$this->assertEquals(2, $totalCount);
}
/**
* Test major manufacturers scope.
*/
public function test_major_manufacturers_scope(): void
{
// Create manufacturers with different ride counts
Manufacturer::factory()->create(['total_rides' => 10]);
Manufacturer::factory()->create(['total_rides' => 3]);
Manufacturer::factory()->create(['total_rides' => 8]);
$majorManufacturers = Manufacturer::majorManufacturers()->get();
$this->assertEquals(2, $majorManufacturers->count());
// Test custom minimum
$majorManufacturers = Manufacturer::majorManufacturers(8)->get();
$this->assertEquals(2, $majorManufacturers->count());
}
/**
* Test coaster manufacturers scope.
*/
public function test_coaster_manufacturers_scope(): void
{
Manufacturer::factory()->create(['total_roller_coasters' => 5]);
Manufacturer::factory()->create(['total_roller_coasters' => 0]);
$coasterManufacturers = Manufacturer::coasterManufacturers()->get();
$this->assertEquals(1, $coasterManufacturers->count());
}
/**
* Test optimized scope.
*/
public function test_optimized_scope(): void
{
$manufacturer = Manufacturer::factory()->create();
$optimized = Manufacturer::optimized()->first();
$this->assertInstanceOf(Manufacturer::class, $optimized);
$this->assertEquals($manufacturer->id, $optimized->id);
}
/**
* Test display name attribute.
*/
public function test_display_name_attribute(): void
{
$manufacturer = Manufacturer::factory()->create([
'name' => 'Intamin AG',
'total_rides' => 15
]);
$this->assertEquals('Intamin AG (15 rides)', $manufacturer->display_name);
}
/**
* Test website URL attribute.
*/
public function test_website_url_attribute(): void
{
// Test with https URL
$manufacturer1 = Manufacturer::factory()->create(['website' => 'https://intamin.com']);
$this->assertEquals('https://intamin.com', $manufacturer1->website_url);
// Test with http URL
$manufacturer2 = Manufacturer::factory()->create(['website' => 'http://intamin.com']);
$this->assertEquals('http://intamin.com', $manufacturer2->website_url);
// Test without protocol
$manufacturer3 = Manufacturer::factory()->create(['website' => 'intamin.com']);
$this->assertEquals('https://intamin.com', $manufacturer3->website_url);
// Test empty website
$manufacturer4 = Manufacturer::factory()->create(['website' => null]);
$this->assertEquals('', $manufacturer4->website_url);
}
/**
* Test update statistics method.
*/
public function test_update_statistics(): void
{
$manufacturer = Manufacturer::factory()->create([
'total_rides' => 0,
'total_roller_coasters' => 0
]);
// This test assumes Ride model exists and has proper relationship
// For now, we'll just test that the method exists and doesn't error
$manufacturer->updateStatistics();
// Verify the method completes without error
$this->assertTrue(true);
}
/**
* Test route key name.
*/
public function test_route_key_name(): void
{
$manufacturer = new Manufacturer();
$this->assertEquals('slug', $manufacturer->getRouteKeyName());
}
/**
* Test soft deletes.
*/
public function test_soft_deletes_work(): void
{
$manufacturer = Manufacturer::factory()->create();
$manufacturer->delete();
$this->assertSoftDeleted($manufacturer);
// Test that it's excluded from normal queries
$this->assertEquals(0, Manufacturer::count());
// Test that it's included in withTrashed queries
$this->assertEquals(1, Manufacturer::withTrashed()->count());
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace Tests\Feature;
use App\Models\Operator;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class OperatorControllerTest extends TestCase
{
use RefreshDatabase;
protected User $user;
protected function setUp(): void
{
parent::setUp();
$this->user = User::factory()->create();
}
/** @test */
public function it_can_display_operators_index(): void
{
Operator::factory()->count(3)->create();
$response = $this->actingAs($this->user)->get(route('operators.index'));
$response->assertStatus(200)
->assertSee('Operators');
}
/** @test */
public function it_can_create_a_operator(): void
{
$operatorData = [
'name' => 'Test Operator',
'description' => 'Test description',
'is_active' => true,
];
$response = $this->actingAs($this->user)->post(route('operators.store'), $operatorData);
$response->assertRedirect();
$this->assertDatabaseHas('operators', $operatorData);
}
/** @test */
public function it_can_show_a_operator(): void
{
$operator = Operator::factory()->create();
$response = $this->actingAs($this->user)->get(route('operators.show', $operator));
$response->assertStatus(200)
->assertSee($operator->name);
}
/** @test */
public function it_can_update_a_operator(): void
{
$operator = Operator::factory()->create();
$updateData = [
'name' => 'Updated Operator',
'description' => 'Updated description',
'is_active' => false,
];
$response = $this->actingAs($this->user)->put(route('operators.update', $operator), $updateData);
$response->assertRedirect();
$this->assertDatabaseHas('operators', $updateData);
}
/** @test */
public function it_can_delete_a_operator(): void
{
$operator = Operator::factory()->create();
$response = $this->actingAs($this->user)->delete(route('operators.destroy', $operator));
$response->assertRedirect();
$this->assertSoftDeleted('operators', ['id' => $operator->id]);
}
/** @test */
public function it_validates_required_fields(): void
{
$response = $this->actingAs($this->user)->post(route('operators.store'), []);
$response->assertSessionHasErrors(['name']);
}
/** @test */
public function it_can_search_operators(): void
{
$operator1 = Operator::factory()->create(['name' => 'Searchable Operator']);
$operator2 = Operator::factory()->create(['name' => 'Other Operator']);
$response = $this->actingAs($this->user)->get(route('operators.index', ['search' => 'Searchable']));
$response->assertStatus(200)
->assertSee($operator1->name)
->assertDontSee($operator2->name);
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace Tests\Feature;
use App\Models\Operator;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
/**
* Operator Model Feature Tests
*
* Tests for ThrillWiki Operator model functionality
*/
class OperatorTest extends TestCase
{
use RefreshDatabase, WithFaker;
/**
* Test model creation.
*/
public function test_can_create_operator(): void
{
$operator = Operator::factory()->create();
$this->assertDatabaseHas('operators', [
'id' => $operator->id,
'name' => $operator->name,
]);
}
/**
* Test model factory.
*/
public function test_operator_factory_works(): void
{
$operator = Operator::factory()->create();
$this->assertInstanceOf(Operator::class, $operator);
$this->assertNotEmpty($operator->name);
$this->assertIsBool($operator->is_active);
}
/**
* Test active scope.
*/
public function test_active_scope_filters_correctly(): void
{
Operator::factory()->active()->create();
Operator::factory()->inactive()->create();
$activeCount = Operator::active()->count();
$totalCount = Operator::count();
$this->assertEquals(1, $activeCount);
$this->assertEquals(2, $totalCount);
}
/**
* Test cache key generation.
*/
public function test_cache_key_generation(): void
{
$operator = Operator::factory()->create();
$cacheKey = $operator->getCacheKey();
$expectedKey = strtolower('operator') . '.' . $operator->id;
$this->assertEquals($expectedKey, $cacheKey);
}
/**
* Test cache key with suffix.
*/
public function test_cache_key_with_suffix(): void
{
$operator = Operator::factory()->create();
$cacheKey = $operator->getCacheKey('details');
$expectedKey = strtolower('operator') . '.' . $operator->id . '.details';
$this->assertEquals($expectedKey, $cacheKey);
}
/**
* Test soft deletes.
*/
public function test_soft_deletes_work(): void
{
$operator = Operator::factory()->create();
$operator->delete();
$this->assertSoftDeleted($operator);
// Test that it's excluded from normal queries
$this->assertEquals(0, Operator::count());
// Test that it's included in withTrashed queries
$this->assertEquals(1, Operator::withTrashed()->count());
}
}

View File

@@ -0,0 +1,101 @@
<?php
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Volt\Volt;
use Tests\TestCase;
class ProfileTest extends TestCase
{
use RefreshDatabase;
public function test_profile_page_is_displayed(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)->get('/profile');
$response
->assertOk()
->assertSeeVolt('profile.update-profile-information-form')
->assertSeeVolt('profile.update-password-form')
->assertSeeVolt('profile.delete-user-form');
}
public function test_profile_information_can_be_updated(): void
{
$user = User::factory()->create();
$this->actingAs($user);
$component = Volt::test('profile.update-profile-information-form')
->set('name', 'Test User')
->set('email', 'test@example.com')
->call('updateProfileInformation');
$component
->assertHasNoErrors()
->assertNoRedirect();
$user->refresh();
$this->assertSame('Test User', $user->name);
$this->assertSame('test@example.com', $user->email);
$this->assertNull($user->email_verified_at);
}
public function test_email_verification_status_is_unchanged_when_the_email_address_is_unchanged(): void
{
$user = User::factory()->create();
$this->actingAs($user);
$component = Volt::test('profile.update-profile-information-form')
->set('name', 'Test User')
->set('email', $user->email)
->call('updateProfileInformation');
$component
->assertHasNoErrors()
->assertNoRedirect();
$this->assertNotNull($user->refresh()->email_verified_at);
}
public function test_user_can_delete_their_account(): void
{
$user = User::factory()->create();
$this->actingAs($user);
$component = Volt::test('profile.delete-user-form')
->set('password', 'password')
->call('deleteUser');
$component
->assertHasNoErrors()
->assertRedirect('/');
$this->assertGuest();
$this->assertNull($user->fresh());
}
public function test_correct_password_must_be_provided_to_delete_account(): void
{
$user = User::factory()->create();
$this->actingAs($user);
$component = Volt::test('profile.delete-user-form')
->set('password', 'wrong-password')
->call('deleteUser');
$component
->assertHasErrors('password')
->assertNoRedirect();
$this->assertNotNull($user->fresh());
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace Tests\Feature;
use App\Models\Ride;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class RideControllerTest extends TestCase
{
use RefreshDatabase;
protected User $user;
protected function setUp(): void
{
parent::setUp();
$this->user = User::factory()->create();
}
/** @test */
public function it_can_display_rides_index(): void
{
Ride::factory()->count(3)->create();
$response = $this->actingAs($this->user)->get(route('rides.index'));
$response->assertStatus(200)
->assertSee('Rides');
}
/** @test */
public function it_can_create_a_ride(): void
{
$rideData = [
'name' => 'Test Ride',
'description' => 'Test description',
'is_active' => true,
];
$response = $this->actingAs($this->user)->post(route('rides.store'), $rideData);
$response->assertRedirect();
$this->assertDatabaseHas('rides', $rideData);
}
/** @test */
public function it_can_show_a_ride(): void
{
$ride = Ride::factory()->create();
$response = $this->actingAs($this->user)->get(route('rides.show', $ride));
$response->assertStatus(200)
->assertSee($ride->name);
}
/** @test */
public function it_can_update_a_ride(): void
{
$ride = Ride::factory()->create();
$updateData = [
'name' => 'Updated Ride',
'description' => 'Updated description',
'is_active' => false,
];
$response = $this->actingAs($this->user)->put(route('rides.update', $ride), $updateData);
$response->assertRedirect();
$this->assertDatabaseHas('rides', $updateData);
}
/** @test */
public function it_can_delete_a_ride(): void
{
$ride = Ride::factory()->create();
$response = $this->actingAs($this->user)->delete(route('rides.destroy', $ride));
$response->assertRedirect();
$this->assertSoftDeleted('rides', ['id' => $ride->id]);
}
/** @test */
public function it_validates_required_fields(): void
{
$response = $this->actingAs($this->user)->post(route('rides.store'), []);
$response->assertSessionHasErrors(['name']);
}
/** @test */
public function it_can_search_rides(): void
{
$ride1 = Ride::factory()->create(['name' => 'Searchable Ride']);
$ride2 = Ride::factory()->create(['name' => 'Other Ride']);
$response = $this->actingAs($this->user)->get(route('rides.index', ['search' => 'Searchable']));
$response->assertStatus(200)
->assertSee($ride1->name)
->assertDontSee($ride2->name);
}
}

101
tests/Feature/RideTest.php Normal file
View File

@@ -0,0 +1,101 @@
<?php
namespace Tests\Feature;
use App\Models\Ride;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
/**
* Ride Model Feature Tests
*
* Tests for ThrillWiki Ride model functionality
*/
class RideTest extends TestCase
{
use RefreshDatabase, WithFaker;
/**
* Test model creation.
*/
public function test_can_create_ride(): void
{
$ride = Ride::factory()->create();
$this->assertDatabaseHas('rides', [
'id' => $ride->id,
'name' => $ride->name,
]);
}
/**
* Test model factory.
*/
public function test_ride_factory_works(): void
{
$ride = Ride::factory()->create();
$this->assertInstanceOf(Ride::class, $ride);
$this->assertNotEmpty($ride->name);
$this->assertIsBool($ride->is_active);
}
/**
* Test active scope.
*/
public function test_active_scope_filters_correctly(): void
{
Ride::factory()->active()->create();
Ride::factory()->inactive()->create();
$activeCount = Ride::active()->count();
$totalCount = Ride::count();
$this->assertEquals(1, $activeCount);
$this->assertEquals(2, $totalCount);
}
/**
* Test cache key generation.
*/
public function test_cache_key_generation(): void
{
$ride = Ride::factory()->create();
$cacheKey = $ride->getCacheKey();
$expectedKey = strtolower('ride') . '.' . $ride->id;
$this->assertEquals($expectedKey, $cacheKey);
}
/**
* Test cache key with suffix.
*/
public function test_cache_key_with_suffix(): void
{
$ride = Ride::factory()->create();
$cacheKey = $ride->getCacheKey('details');
$expectedKey = strtolower('ride') . '.' . $ride->id . '.details';
$this->assertEquals($expectedKey, $cacheKey);
}
/**
* Test soft deletes.
*/
public function test_soft_deletes_work(): void
{
$ride = Ride::factory()->create();
$ride->delete();
$this->assertSoftDeleted($ride);
// Test that it's excluded from normal queries
$this->assertEquals(0, Ride::count());
// Test that it's included in withTrashed queries
$this->assertEquals(1, Ride::withTrashed()->count());
}
}