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
@@ -0,0 +1,31 @@
<?php
use App\Enums\ConsultationStatus;
test('consultation status has correct cases', function () {
expect(ConsultationStatus::cases())->toHaveCount(6);
});
test('consultation status pending has correct value', function () {
expect(ConsultationStatus::Pending->value)->toBe('pending');
});
test('consultation status approved has correct value', function () {
expect(ConsultationStatus::Approved->value)->toBe('approved');
});
test('consultation status rejected has correct value', function () {
expect(ConsultationStatus::Rejected->value)->toBe('rejected');
});
test('consultation status completed has correct value', function () {
expect(ConsultationStatus::Completed->value)->toBe('completed');
});
test('consultation status no show has correct value', function () {
expect(ConsultationStatus::NoShow->value)->toBe('no_show');
});
test('consultation status cancelled has correct value', function () {
expect(ConsultationStatus::Cancelled->value)->toBe('cancelled');
});
+15
View File
@@ -0,0 +1,15 @@
<?php
use App\Enums\ConsultationType;
test('consultation type has correct cases', function () {
expect(ConsultationType::cases())->toHaveCount(2);
});
test('consultation type free has correct value', function () {
expect(ConsultationType::Free->value)->toBe('free');
});
test('consultation type paid has correct value', function () {
expect(ConsultationType::Paid->value)->toBe('paid');
});
+19
View File
@@ -0,0 +1,19 @@
<?php
use App\Enums\PaymentStatus;
test('payment status has correct cases', function () {
expect(PaymentStatus::cases())->toHaveCount(3);
});
test('payment status pending has correct value', function () {
expect(PaymentStatus::Pending->value)->toBe('pending');
});
test('payment status received has correct value', function () {
expect(PaymentStatus::Received->value)->toBe('received');
});
test('payment status not applicable has correct value', function () {
expect(PaymentStatus::NotApplicable->value)->toBe('na');
});
+15
View File
@@ -0,0 +1,15 @@
<?php
use App\Enums\PostStatus;
test('post status has correct cases', function () {
expect(PostStatus::cases())->toHaveCount(2);
});
test('post status draft has correct value', function () {
expect(PostStatus::Draft->value)->toBe('draft');
});
test('post status published has correct value', function () {
expect(PostStatus::Published->value)->toBe('published');
});
+15
View File
@@ -0,0 +1,15 @@
<?php
use App\Enums\TimelineStatus;
test('timeline status has correct cases', function () {
expect(TimelineStatus::cases())->toHaveCount(2);
});
test('timeline status active has correct value', function () {
expect(TimelineStatus::Active->value)->toBe('active');
});
test('timeline status archived has correct value', function () {
expect(TimelineStatus::Archived->value)->toBe('archived');
});
+15
View File
@@ -0,0 +1,15 @@
<?php
use App\Enums\UserStatus;
test('user status has correct cases', function () {
expect(UserStatus::cases())->toHaveCount(2);
});
test('user status active has correct value', function () {
expect(UserStatus::Active->value)->toBe('active');
});
test('user status deactivated has correct value', function () {
expect(UserStatus::Deactivated->value)->toBe('deactivated');
});
+19
View File
@@ -0,0 +1,19 @@
<?php
use App\Enums\UserType;
test('user type has correct cases', function () {
expect(UserType::cases())->toHaveCount(3);
});
test('user type admin has correct value', function () {
expect(UserType::Admin->value)->toBe('admin');
});
test('user type individual has correct value', function () {
expect(UserType::Individual->value)->toBe('individual');
});
test('user type company has correct value', function () {
expect(UserType::Company->value)->toBe('company');
});
+42
View File
@@ -0,0 +1,42 @@
<?php
use App\Enums\ConsultationStatus;
use App\Enums\ConsultationType;
use App\Enums\PaymentStatus;
use App\Models\Consultation;
use App\Models\User;
test('consultation has correct consultation type cast', function () {
$consultation = Consultation::factory()->create(['consultation_type' => 'free']);
expect($consultation->consultation_type)->toBeInstanceOf(ConsultationType::class)
->and($consultation->consultation_type)->toBe(ConsultationType::Free);
});
test('consultation has correct status cast', function () {
$consultation = Consultation::factory()->create(['status' => 'pending']);
expect($consultation->status)->toBeInstanceOf(ConsultationStatus::class)
->and($consultation->status)->toBe(ConsultationStatus::Pending);
});
test('consultation has correct payment status cast', function () {
$consultation = Consultation::factory()->create(['payment_status' => 'na']);
expect($consultation->payment_status)->toBeInstanceOf(PaymentStatus::class)
->and($consultation->payment_status)->toBe(PaymentStatus::NotApplicable);
});
test('consultation belongs to user', function () {
$user = User::factory()->create();
$consultation = Consultation::factory()->create(['user_id' => $user->id]);
expect($consultation->user)->toBeInstanceOf(User::class)
->and($consultation->user->id)->toBe($user->id);
});
test('consultation has booking date cast as date', function () {
$consultation = Consultation::factory()->create();
expect($consultation->booking_date)->toBeInstanceOf(\Illuminate\Support\Carbon::class);
});
+49
View File
@@ -0,0 +1,49 @@
<?php
use App\Models\Post;
test('post getTitle returns title in specified locale', function () {
$post = Post::factory()->create([
'title' => ['ar' => 'عنوان عربي', 'en' => 'English Title'],
]);
expect($post->getTitle('ar'))->toBe('عنوان عربي')
->and($post->getTitle('en'))->toBe('English Title');
});
test('post getTitle falls back to Arabic when locale missing', function () {
$post = Post::factory()->create([
'title' => ['ar' => 'عنوان عربي'],
]);
expect($post->getTitle('en'))->toBe('عنوان عربي');
});
test('post getTitle uses current locale by default', function () {
$post = Post::factory()->create([
'title' => ['ar' => 'عنوان عربي', 'en' => 'English Title'],
]);
app()->setLocale('en');
expect($post->getTitle())->toBe('English Title');
app()->setLocale('ar');
expect($post->getTitle())->toBe('عنوان عربي');
});
test('post getBody returns body in specified locale', function () {
$post = Post::factory()->create([
'body' => ['ar' => 'محتوى عربي', 'en' => 'English Content'],
]);
expect($post->getBody('ar'))->toBe('محتوى عربي')
->and($post->getBody('en'))->toBe('English Content');
});
test('post getBody falls back to Arabic when locale missing', function () {
$post = Post::factory()->create([
'body' => ['ar' => 'محتوى عربي'],
]);
expect($post->getBody('en'))->toBe('محتوى عربي');
});
+45
View File
@@ -0,0 +1,45 @@
<?php
use App\Enums\TimelineStatus;
use App\Models\Timeline;
use App\Models\TimelineUpdate;
use App\Models\User;
test('timeline belongs to user', function () {
$user = User::factory()->create();
$timeline = Timeline::factory()->create(['user_id' => $user->id]);
expect($timeline->user)->toBeInstanceOf(User::class)
->and($timeline->user->id)->toBe($user->id);
});
test('timeline has correct status cast', function () {
$timeline = Timeline::factory()->create(['status' => 'active']);
expect($timeline->status)->toBeInstanceOf(TimelineStatus::class)
->and($timeline->status)->toBe(TimelineStatus::Active);
});
test('timeline has many updates', function () {
$timeline = Timeline::factory()->create();
TimelineUpdate::factory()->count(3)->create(['timeline_id' => $timeline->id]);
expect($timeline->updates)->toHaveCount(3)
->and($timeline->updates->first())->toBeInstanceOf(TimelineUpdate::class);
});
test('timeline update belongs to timeline', function () {
$timeline = Timeline::factory()->create();
$update = TimelineUpdate::factory()->create(['timeline_id' => $timeline->id]);
expect($update->timeline)->toBeInstanceOf(Timeline::class)
->and($update->timeline->id)->toBe($timeline->id);
});
test('timeline update belongs to admin', function () {
$admin = User::factory()->admin()->create();
$update = TimelineUpdate::factory()->create(['admin_id' => $admin->id]);
expect($update->admin)->toBeInstanceOf(User::class)
->and($update->admin->id)->toBe($admin->id);
});
+68
View File
@@ -0,0 +1,68 @@
<?php
use App\Enums\UserStatus;
use App\Enums\UserType;
use App\Models\User;
test('user has correct user type cast', function () {
$user = User::factory()->create(['user_type' => 'admin']);
expect($user->user_type)->toBeInstanceOf(UserType::class)
->and($user->user_type)->toBe(UserType::Admin);
});
test('user has correct status cast', function () {
$user = User::factory()->create(['status' => 'active']);
expect($user->status)->toBeInstanceOf(UserStatus::class)
->and($user->status)->toBe(UserStatus::Active);
});
test('user is admin returns true for admin users', function () {
$user = User::factory()->admin()->create();
expect($user->isAdmin())->toBeTrue()
->and($user->isClient())->toBeFalse();
});
test('user is individual returns true for individual users', function () {
$user = User::factory()->individual()->create();
expect($user->isIndividual())->toBeTrue()
->and($user->isClient())->toBeTrue();
});
test('user is company returns true for company users', function () {
$user = User::factory()->company()->create();
expect($user->isCompany())->toBeTrue()
->and($user->isClient())->toBeTrue();
});
test('user initials are generated correctly', function () {
$user = User::factory()->create(['full_name' => 'John Doe']);
expect($user->initials())->toBe('JD');
});
test('user admins scope returns only admin users', function () {
User::factory()->admin()->count(2)->create();
User::factory()->individual()->count(3)->create();
expect(User::admins()->count())->toBe(2);
});
test('user clients scope returns only client users', function () {
User::factory()->admin()->count(2)->create();
User::factory()->individual()->count(2)->create();
User::factory()->company()->count(1)->create();
expect(User::clients()->count())->toBe(3);
});
test('user active scope returns only active users', function () {
User::factory()->count(2)->create();
User::factory()->deactivated()->count(1)->create();
expect(User::active()->count())->toBe(2);
});