completed story 1.1 with QA tests and fixes

This commit is contained in:
Naser Mansour
2025-12-26 13:46:39 +02:00
parent 028ce573b9
commit 84d9c2f66a
57 changed files with 2193 additions and 85 deletions
+3 -3
View File
@@ -10,7 +10,7 @@ test('login screen can be rendered', function () {
});
test('users can authenticate using the login screen', function () {
$user = User::factory()->withoutTwoFactor()->create();
$user = User::factory()->create();
$response = $this->post(route('login.store'), [
'email' => $user->email,
@@ -47,7 +47,7 @@ test('users with two factor enabled are redirected to two factor challenge', fun
'confirmPassword' => true,
]);
$user = User::factory()->create();
$user = User::factory()->withTwoFactor()->create();
$response = $this->post(route('login.store'), [
'email' => $user->email,
@@ -66,4 +66,4 @@ test('users can logout', function () {
$response->assertRedirect(route('home'));
$this->assertGuest();
});
});
+3 -2
View File
@@ -8,8 +8,9 @@ test('registration screen can be rendered', function () {
test('new users can register', function () {
$response = $this->post(route('register.store'), [
'name' => 'John Doe',
'full_name' => 'John Doe',
'email' => 'test@example.com',
'phone' => '+1234567890',
'password' => 'password',
'password_confirmation' => 'password',
]);
@@ -18,4 +19,4 @@ test('new users can register', function () {
->assertRedirect(route('dashboard', absolute: false));
$this->assertAuthenticated();
});
});
@@ -23,10 +23,10 @@ test('two factor challenge can be rendered', function () {
'confirmPassword' => true,
]);
$user = User::factory()->create();
$user = User::factory()->withTwoFactor()->create();
$this->post(route('login.store'), [
'email' => $user->email,
'password' => 'password',
])->assertRedirect(route('two-factor.login'));
});
});
+119
View File
@@ -0,0 +1,119 @@
<?php
use App\Enums\ConsultationStatus;
use App\Enums\PostStatus;
use App\Enums\TimelineStatus;
use App\Enums\UserStatus;
use App\Enums\UserType;
use App\Models\AdminLog;
use App\Models\BlockedTime;
use App\Models\Consultation;
use App\Models\Notification;
use App\Models\Post;
use App\Models\Timeline;
use App\Models\TimelineUpdate;
use App\Models\User;
use App\Models\WorkingHour;
test('user factory creates valid user', function () {
$user = User::factory()->create();
expect($user)->toBeInstanceOf(User::class)
->and($user->user_type)->toBeInstanceOf(UserType::class)
->and($user->status)->toBeInstanceOf(UserStatus::class)
->and($user->full_name)->toBeString()
->and($user->email)->toBeString()
->and($user->phone)->toBeString();
});
test('user factory admin state creates admin user', function () {
$user = User::factory()->admin()->create();
expect($user->user_type)->toBe(UserType::Admin);
});
test('user factory individual state creates individual user', function () {
$user = User::factory()->individual()->create();
expect($user->user_type)->toBe(UserType::Individual);
});
test('user factory company state creates company user', function () {
$user = User::factory()->company()->create();
expect($user->user_type)->toBe(UserType::Company)
->and($user->company_name)->toBeString()
->and($user->company_cert_number)->toBeString();
});
test('consultation factory creates valid consultation', function () {
$consultation = Consultation::factory()->create();
expect($consultation)->toBeInstanceOf(Consultation::class)
->and($consultation->user)->toBeInstanceOf(User::class)
->and($consultation->status)->toBeInstanceOf(ConsultationStatus::class)
->and($consultation->booking_date)->toBeInstanceOf(\Illuminate\Support\Carbon::class);
});
test('timeline factory creates valid timeline', function () {
$timeline = Timeline::factory()->create();
expect($timeline)->toBeInstanceOf(Timeline::class)
->and($timeline->user)->toBeInstanceOf(User::class)
->and($timeline->status)->toBeInstanceOf(TimelineStatus::class)
->and($timeline->case_name)->toBeString();
});
test('timeline update factory creates valid timeline update', function () {
$update = TimelineUpdate::factory()->create();
expect($update)->toBeInstanceOf(TimelineUpdate::class)
->and($update->timeline)->toBeInstanceOf(Timeline::class)
->and($update->admin)->toBeInstanceOf(User::class)
->and($update->update_text)->toBeString();
});
test('post factory creates valid post', function () {
$post = Post::factory()->create();
expect($post)->toBeInstanceOf(Post::class)
->and($post->status)->toBeInstanceOf(PostStatus::class)
->and($post->title)->toBeArray()
->and($post->body)->toBeArray()
->and($post->title)->toHaveKeys(['ar', 'en'])
->and($post->body)->toHaveKeys(['ar', 'en']);
});
test('working hour factory creates valid working hour', function () {
$workingHour = WorkingHour::factory()->create();
expect($workingHour)->toBeInstanceOf(WorkingHour::class)
->and($workingHour->day_of_week)->toBeInt()
->and($workingHour->day_of_week)->toBeBetween(0, 6)
->and($workingHour->is_active)->toBeBool();
});
test('blocked time factory creates valid blocked time', function () {
$blockedTime = BlockedTime::factory()->create();
expect($blockedTime)->toBeInstanceOf(BlockedTime::class)
->and($blockedTime->block_date)->toBeInstanceOf(\Illuminate\Support\Carbon::class);
});
test('notification factory creates valid notification', function () {
$notification = Notification::factory()->create();
expect($notification)->toBeInstanceOf(Notification::class)
->and($notification->user)->toBeInstanceOf(User::class)
->and($notification->type)->toBeString()
->and($notification->data)->toBeArray();
});
test('admin log factory creates valid admin log', function () {
$log = AdminLog::factory()->create();
expect($log)->toBeInstanceOf(AdminLog::class)
->and($log->admin)->toBeInstanceOf(User::class)
->and($log->action)->toBeString()
->and($log->ip_address)->toBeString();
});
+87
View File
@@ -0,0 +1,87 @@
<?php
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\Schema;
test('all tables exist after migration', function () {
expect(Schema::hasTable('users'))->toBeTrue()
->and(Schema::hasTable('consultations'))->toBeTrue()
->and(Schema::hasTable('timelines'))->toBeTrue()
->and(Schema::hasTable('timeline_updates'))->toBeTrue()
->and(Schema::hasTable('posts'))->toBeTrue()
->and(Schema::hasTable('working_hours'))->toBeTrue()
->and(Schema::hasTable('blocked_times'))->toBeTrue()
->and(Schema::hasTable('notifications'))->toBeTrue()
->and(Schema::hasTable('admin_logs'))->toBeTrue();
});
test('users table has all required columns', function () {
expect(Schema::hasColumns('users', [
'id',
'user_type',
'full_name',
'national_id',
'company_name',
'company_cert_number',
'contact_person_name',
'contact_person_id',
'email',
'phone',
'password',
'status',
'preferred_language',
'email_verified_at',
'remember_token',
'created_at',
'updated_at',
]))->toBeTrue();
});
test('consultations table has all required columns', function () {
expect(Schema::hasColumns('consultations', [
'id',
'user_id',
'booking_date',
'booking_time',
'problem_summary',
'consultation_type',
'payment_amount',
'payment_status',
'status',
'admin_notes',
'created_at',
'updated_at',
]))->toBeTrue();
});
test('timelines table has all required columns', function () {
expect(Schema::hasColumns('timelines', [
'id',
'user_id',
'case_name',
'case_reference',
'status',
'created_at',
'updated_at',
]))->toBeTrue();
});
test('posts table has all required columns', function () {
expect(Schema::hasColumns('posts', [
'id',
'title',
'body',
'status',
'published_at',
'created_at',
'updated_at',
]))->toBeTrue();
});
test('migrate rollback works without errors', function () {
$result = Artisan::call('migrate:rollback', ['--force' => true]);
expect($result)->toBe(0);
$result = Artisan::call('migrate', ['--force' => true]);
expect($result)->toBe(0);
});
+4 -4
View File
@@ -15,7 +15,7 @@ test('profile information can be updated', function () {
$this->actingAs($user);
$response = Volt::test('settings.profile')
->set('name', 'Test User')
->set('full_name', 'Test User')
->set('email', 'test@example.com')
->call('updateProfileInformation');
@@ -23,7 +23,7 @@ test('profile information can be updated', function () {
$user->refresh();
expect($user->name)->toEqual('Test User');
expect($user->full_name)->toEqual('Test User');
expect($user->email)->toEqual('test@example.com');
expect($user->email_verified_at)->toBeNull();
});
@@ -34,7 +34,7 @@ test('email verification status is unchanged when email address is unchanged', f
$this->actingAs($user);
$response = Volt::test('settings.profile')
->set('name', 'Test User')
->set('full_name', 'Test User')
->set('email', $user->email)
->call('updateProfileInformation');
@@ -72,4 +72,4 @@ test('correct password must be provided to delete account', function () {
$response->assertHasErrors(['password']);
expect($user->fresh())->not->toBeNull();
});
});