update tests
This commit is contained in:
@@ -0,0 +1,279 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Concerns;
|
||||
|
||||
use App\Models\Role;
|
||||
use App\Models\SchoolYear;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Testing\TestResponse;
|
||||
|
||||
/**
|
||||
* Reusable deterministic fixtures for end-to-end API scenario tests.
|
||||
*
|
||||
* @see docs/alrahma_end_to_end_use_case_test_plan.md Part III
|
||||
*/
|
||||
trait SeedsE2ETestFixtures
|
||||
{
|
||||
use CreatesApiTestUsers;
|
||||
|
||||
protected const E2E_SCHOOL_YEAR = '2025-2026';
|
||||
protected const E2E_PREV_SCHOOL_YEAR = '2024-2025';
|
||||
protected const E2E_SEMESTER = 'Fall';
|
||||
|
||||
protected function seedE2EConfiguration(): void
|
||||
{
|
||||
// Pin calendar context so semester-aware services resolve to Fall 2025-2026.
|
||||
$this->travelTo('2025-10-05 10:00:00');
|
||||
|
||||
$this->seedApiTestConfig(self::E2E_SCHOOL_YEAR, self::E2E_SEMESTER);
|
||||
|
||||
DB::table('configuration')->updateOrInsert(
|
||||
['config_key' => 'fall_semester_start'],
|
||||
['config_value' => '2025-09-01']
|
||||
);
|
||||
DB::table('configuration')->updateOrInsert(
|
||||
['config_key' => 'spring_semester_start'],
|
||||
['config_value' => '2026-01-15']
|
||||
);
|
||||
DB::table('configuration')->updateOrInsert(
|
||||
['config_key' => 'last_school_day'],
|
||||
['config_value' => '2026-06-15']
|
||||
);
|
||||
}
|
||||
|
||||
protected function seedClosedSchoolYear(): void
|
||||
{
|
||||
SchoolYear::query()->updateOrCreate(
|
||||
['name' => self::E2E_PREV_SCHOOL_YEAR],
|
||||
[
|
||||
'start_date' => '2024-09-01',
|
||||
'end_date' => '2025-06-30',
|
||||
'status' => SchoolYear::STATUS_CLOSED,
|
||||
'is_current' => false,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
protected function seedClassSection(
|
||||
int $classSectionId = 701,
|
||||
string $name = '5A',
|
||||
int $classId = 5
|
||||
): int {
|
||||
DB::table('classSection')->insert([
|
||||
'class_id' => $classId,
|
||||
'class_section_id' => $classSectionId,
|
||||
'class_section_name' => $name,
|
||||
'semester' => self::E2E_SEMESTER,
|
||||
'school_year' => self::E2E_SCHOOL_YEAR,
|
||||
]);
|
||||
|
||||
return $classSectionId;
|
||||
}
|
||||
|
||||
protected function seedTeacherClassAssignment(int $teacherId, int $classSectionId, string $position = 'main'): void
|
||||
{
|
||||
DB::table('teacher_class')->insert([
|
||||
'teacher_id' => $teacherId,
|
||||
'class_section_id' => $classSectionId,
|
||||
'position' => $position,
|
||||
'school_year' => self::E2E_SCHOOL_YEAR,
|
||||
'semester' => self::E2E_SEMESTER,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function seedStudentClassAssignment(int $studentId, int $classSectionId): void
|
||||
{
|
||||
DB::table('student_class')->insert([
|
||||
'student_id' => $studentId,
|
||||
'class_section_id' => $classSectionId,
|
||||
'school_year' => self::E2E_SCHOOL_YEAR,
|
||||
'semester' => self::E2E_SEMESTER,
|
||||
'is_event_only' => 0,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array{teacher: User, class_section_id: int, student_id: int, parent_id: int}
|
||||
*/
|
||||
protected function seedTeacherClassWithStudent(?int $classSectionId = null): array
|
||||
{
|
||||
$this->seedE2EConfiguration();
|
||||
$classSectionId ??= $this->seedClassSection(801, '3A', 3);
|
||||
|
||||
$teacher = $this->createApiUserWithRole('teacher', [
|
||||
'firstname' => 'Tara',
|
||||
'lastname' => 'Teacher',
|
||||
'email' => 'e2e.teacher.' . uniqid('', true) . '@example.test',
|
||||
]);
|
||||
$this->seedTeacherClassAssignment($teacher->id, $classSectionId);
|
||||
|
||||
$parent = $this->createApiUserWithRole('parent', [
|
||||
'firstname' => 'Parent',
|
||||
'lastname' => 'Fixture',
|
||||
'email' => 'e2e.parent.' . uniqid('', true) . '@example.test',
|
||||
]);
|
||||
|
||||
$studentId = DB::table('students')->insertGetId([
|
||||
'school_id' => 'S-E2E-' . random_int(1000, 9999),
|
||||
'firstname' => 'Kai',
|
||||
'lastname' => 'Student',
|
||||
'dob' => '2014-09-01',
|
||||
'age' => 11,
|
||||
'gender' => 'Male',
|
||||
'photo_consent' => 1,
|
||||
'parent_id' => $parent->id,
|
||||
'year_of_registration' => '2025',
|
||||
'school_year' => self::E2E_SCHOOL_YEAR,
|
||||
'semester' => self::E2E_SEMESTER,
|
||||
'is_active' => 1,
|
||||
]);
|
||||
$this->seedStudentClassAssignment($studentId, $classSectionId);
|
||||
|
||||
return [
|
||||
'teacher' => $teacher,
|
||||
'class_section_id' => $classSectionId,
|
||||
'student_id' => $studentId,
|
||||
'parent_id' => $parent->id,
|
||||
'parent' => $parent,
|
||||
];
|
||||
}
|
||||
|
||||
protected function createParentAccountViaApi(array $overrides = []): int
|
||||
{
|
||||
$parentRoleId = (int) Role::query()->where('name', 'parent')->value('id');
|
||||
$unique = str_replace('.', '', uniqid('', true));
|
||||
|
||||
$payload = array_merge([
|
||||
'firstname' => 'E2E',
|
||||
'lastname' => 'Parent',
|
||||
'gender' => 'Female',
|
||||
'cellphone' => '5551234567',
|
||||
'email' => "e2e.parent.$unique@example.test",
|
||||
'address_street' => '42 Cedar Lane',
|
||||
'city' => 'Brooklyn',
|
||||
'state' => 'NY',
|
||||
'zip' => '11201',
|
||||
'accept_school_policy' => true,
|
||||
'role_id' => $parentRoleId,
|
||||
'password' => 'secret123',
|
||||
'semester' => self::E2E_SEMESTER,
|
||||
'school_year' => self::E2E_SCHOOL_YEAR,
|
||||
'user_type' => 'primary',
|
||||
'status' => 'Active',
|
||||
'is_verified' => true,
|
||||
], $overrides);
|
||||
|
||||
$response = $this->postJson('/api/v1/users', $payload);
|
||||
$response->assertStatus(201)->assertJsonPath('ok', true);
|
||||
|
||||
return (int) $response->json('user_id');
|
||||
}
|
||||
|
||||
protected function createStudentViaApi(int $parentId, array $overrides = [], bool $firstChild = true): int
|
||||
{
|
||||
$unique = str_replace('.', '', uniqid('', true));
|
||||
$payload = array_merge([
|
||||
'firstname' => 'E2E',
|
||||
'lastname' => 'Student',
|
||||
'dob' => '2015-05-10',
|
||||
'age' => 10,
|
||||
'gender' => 'Male',
|
||||
'is_active' => true,
|
||||
'registration_grade' => '5',
|
||||
'is_new' => true,
|
||||
'photo_consent' => true,
|
||||
'parent_id' => $parentId,
|
||||
'registration_date' => '2025-09-01',
|
||||
'tuition_paid' => false,
|
||||
'semester' => self::E2E_SEMESTER,
|
||||
'year_of_registration' => 2025,
|
||||
'school_year' => self::E2E_SCHOOL_YEAR,
|
||||
], $overrides);
|
||||
|
||||
if ($firstChild) {
|
||||
$payload = array_merge($payload, [
|
||||
'name' => $overrides['name'] ?? 'E2E Parent',
|
||||
'cellphone' => $overrides['cellphone'] ?? '5551234567',
|
||||
'email' => $overrides['email'] ?? "e2e.contact.$unique@example.test",
|
||||
'relation' => $overrides['relation'] ?? 'Mother',
|
||||
]);
|
||||
}
|
||||
|
||||
$response = $this->postJson('/api/v1/students', $payload);
|
||||
$response->assertStatus(201)->assertJsonPath('ok', true);
|
||||
|
||||
return (int) $response->json('student.id');
|
||||
}
|
||||
|
||||
protected function assignStudentToClassViaApi(int $studentId, int $classSectionId): TestResponse
|
||||
{
|
||||
return $this->postJson('/api/v1/students/assign-class', [
|
||||
'student_id' => $studentId,
|
||||
'class_section_id' => [$classSectionId],
|
||||
]);
|
||||
}
|
||||
|
||||
protected function postEnrollmentStatuses(array $studentStatusMap): TestResponse
|
||||
{
|
||||
return $this->post(
|
||||
'/api/v1/administrator/enrollment-withdrawal/update-statuses?' .
|
||||
http_build_query(['enrollment_status' => $studentStatusMap]),
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
protected function seedInvoiceForParent(int $parentId, array $overrides = []): int
|
||||
{
|
||||
return DB::table('invoices')->insertGetId(array_merge([
|
||||
'parent_id' => $parentId,
|
||||
'invoice_number' => 'INV-E2E-' . random_int(1000, 9999),
|
||||
'total_amount' => 500.00,
|
||||
'balance' => 500.00,
|
||||
'paid_amount' => 0,
|
||||
'has_discount' => 0,
|
||||
'issue_date' => '2025-09-01',
|
||||
'due_date' => '2025-10-01',
|
||||
'status' => 'unpaid',
|
||||
'school_year' => self::E2E_SCHOOL_YEAR,
|
||||
'semester' => self::E2E_SEMESTER,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
], $overrides));
|
||||
}
|
||||
|
||||
protected function seedPriorYearUnpaidInvoice(int $parentId): int
|
||||
{
|
||||
return DB::table('invoices')->insertGetId([
|
||||
'parent_id' => $parentId,
|
||||
'invoice_number' => 'INV-PRIOR-' . random_int(1000, 9999),
|
||||
'total_amount' => 200.00,
|
||||
'balance' => 150.00,
|
||||
'paid_amount' => 50.00,
|
||||
'has_discount' => 0,
|
||||
'issue_date' => '2024-09-01',
|
||||
'due_date' => '2024-10-01',
|
||||
'status' => 'unpaid',
|
||||
'school_year' => self::E2E_PREV_SCHOOL_YEAR,
|
||||
'semester' => self::E2E_SEMESTER,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
|
||||
protected function seedDiscountVoucher(): int
|
||||
{
|
||||
return DB::table('discount_vouchers')->insertGetId([
|
||||
'code' => 'E2E10-' . random_int(100, 999),
|
||||
'discount_type' => 'fixed',
|
||||
'discount_value' => 50,
|
||||
'max_uses' => 100,
|
||||
'times_used' => 0,
|
||||
'is_active' => 1,
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user