feat: add CourseSchedule model factory and feature tests for CRUD operations and authorization
This commit is contained in:
parent
9d7a5d206c
commit
a37ccd64df
27
database/factories/CourseScheduleFactory.php
Normal file
27
database/factories/CourseScheduleFactory.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\Course;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/**
|
||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\CourseSchedule>
|
||||
*/
|
||||
class CourseScheduleFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'course_id' => Course::factory(),
|
||||
'day_of_week' => fake()->numberBetween(1, 7),
|
||||
'start_time' => '08:00',
|
||||
'end_time' => '10:00',
|
||||
];
|
||||
}
|
||||
}
|
||||
196
tests/Feature/CourseScheduleTest.php
Normal file
196
tests/Feature/CourseScheduleTest.php
Normal file
@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
use App\Enums\RoleEnum;
|
||||
use App\Filament\Pages\Information\CourseSchedule\Index as CourseSchedulePage;
|
||||
use App\Models\Course;
|
||||
use App\Models\CourseSchedule;
|
||||
use App\Models\User;
|
||||
use App\Settings\GeneralSettings;
|
||||
use Livewire\Livewire;
|
||||
use Spatie\Permission\Models\Permission;
|
||||
use Spatie\Permission\Models\Role;
|
||||
|
||||
/**
|
||||
* Setup necessary roles and permissions
|
||||
*/
|
||||
beforeEach(function () {
|
||||
Role::findOrCreate(RoleEnum::Developer->value);
|
||||
Role::findOrCreate(RoleEnum::Kosma->value);
|
||||
Role::findOrCreate(RoleEnum::Student->value);
|
||||
|
||||
$permissions = [
|
||||
'View:CourseSchedule',
|
||||
'Create:CourseSchedule',
|
||||
'Update:CourseSchedule',
|
||||
'Delete:CourseSchedule',
|
||||
];
|
||||
|
||||
foreach ($permissions as $permission) {
|
||||
Permission::findOrCreate($permission);
|
||||
}
|
||||
});
|
||||
|
||||
describe('Course Schedule Authorization', function () {
|
||||
it('allows all roles to view the page but restricts actions to Developer and Kosma', function () {
|
||||
$developer = User::factory()->create();
|
||||
$developer->assignRole(RoleEnum::Developer);
|
||||
$developer->givePermissionTo(['View:CourseSchedule', 'Create:CourseSchedule']);
|
||||
|
||||
$kosma = User::factory()->create();
|
||||
$kosma->assignRole(RoleEnum::Kosma);
|
||||
$kosma->givePermissionTo(['View:CourseSchedule', 'Create:CourseSchedule']);
|
||||
|
||||
$regularStudent = User::factory()->create();
|
||||
$regularStudent->assignRole(RoleEnum::Student);
|
||||
$regularStudent->givePermissionTo('View:CourseSchedule');
|
||||
|
||||
// All can view the page
|
||||
$this->actingAs($developer);
|
||||
Livewire::test(CourseSchedulePage::class)->assertSuccessful();
|
||||
|
||||
$this->actingAs($kosma);
|
||||
Livewire::test(CourseSchedulePage::class)->assertSuccessful();
|
||||
|
||||
$this->actingAs($regularStudent);
|
||||
Livewire::test(CourseSchedulePage::class)->assertSuccessful();
|
||||
|
||||
// Only Developer and Kosma can see the Create action
|
||||
$this->actingAs($developer);
|
||||
Livewire::test(CourseSchedulePage::class)->assertActionVisible('createSchedule');
|
||||
|
||||
$this->actingAs($kosma);
|
||||
Livewire::test(CourseSchedulePage::class)->assertActionVisible('createSchedule');
|
||||
|
||||
$this->actingAs($regularStudent);
|
||||
Livewire::test(CourseSchedulePage::class)->assertActionHidden('createSchedule');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Course Schedule Model', function () {
|
||||
it('has a relationship with Course', function () {
|
||||
$schedule = CourseSchedule::factory()->create();
|
||||
expect($schedule->course)->toBeInstanceOf(Course::class);
|
||||
});
|
||||
|
||||
it('supports Soft Deletes', function () {
|
||||
$schedule = CourseSchedule::factory()->create();
|
||||
$schedule->delete();
|
||||
|
||||
expect($schedule->trashed())->toBeTrue();
|
||||
expect(CourseSchedule::find($schedule->id))->toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Course Schedule CRUD via Custom Actions', function () {
|
||||
beforeEach(function () {
|
||||
$user = User::factory()->create();
|
||||
$user->assignRole(RoleEnum::Developer);
|
||||
$user->givePermissionTo(['View:CourseSchedule', 'Create:CourseSchedule', 'Update:CourseSchedule', 'Delete:CourseSchedule']);
|
||||
$this->actingAs($user);
|
||||
|
||||
// Ensure semester matches settings for visibility
|
||||
$this->currentSemester = app(GeneralSettings::class)->current_semester;
|
||||
});
|
||||
|
||||
it('can create a new schedule', function () {
|
||||
$course = Course::factory()->create(['semester' => $this->currentSemester]);
|
||||
|
||||
Livewire::test(CourseSchedulePage::class)
|
||||
->callAction('createSchedule', [
|
||||
'course_id' => $course->id,
|
||||
'day_of_week' => 1, // Senin
|
||||
'start_time' => '10:00',
|
||||
'end_time' => '12:00',
|
||||
])
|
||||
->assertHasNoActionErrors();
|
||||
|
||||
$this->assertDatabaseHas('course_schedules', [
|
||||
'course_id' => $course->id,
|
||||
'day_of_week' => 1,
|
||||
'start_time' => '10:00',
|
||||
'end_time' => '12:00',
|
||||
]);
|
||||
});
|
||||
|
||||
it('can update an existing schedule', function () {
|
||||
$course = Course::factory()->create(['semester' => $this->currentSemester]);
|
||||
$schedule = CourseSchedule::factory()->create([
|
||||
'course_id' => $course->id,
|
||||
'day_of_week' => 2, // Selasa
|
||||
]);
|
||||
|
||||
Livewire::test(CourseSchedulePage::class)
|
||||
->callAction('editSchedule', [
|
||||
'day_of_week' => 3, // Rabu
|
||||
], ['schedule' => $schedule->id])
|
||||
->assertHasNoActionErrors();
|
||||
|
||||
expect($schedule->refresh()->day_of_week)->toBe(3);
|
||||
});
|
||||
|
||||
it('can delete a schedule', function () {
|
||||
$course = Course::factory()->create(['semester' => $this->currentSemester]);
|
||||
$schedule = CourseSchedule::factory()->create(['course_id' => $course->id]);
|
||||
|
||||
Livewire::test(CourseSchedulePage::class)
|
||||
->callAction('deleteSchedule', [], ['schedule' => $schedule->id])
|
||||
->assertHasNoActionErrors();
|
||||
|
||||
expect(CourseSchedule::find($schedule->id))->toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Search and Search Filtering', function () {
|
||||
beforeEach(function () {
|
||||
$user = User::factory()->create();
|
||||
$user->assignRole(RoleEnum::Developer);
|
||||
$user->givePermissionTo(['View:CourseSchedule']);
|
||||
$this->actingAs($user);
|
||||
$this->currentSemester = app(GeneralSettings::class)->current_semester;
|
||||
});
|
||||
|
||||
it('can search schedules by course name or lecturer', function () {
|
||||
$targetCourse = Course::factory()->create([
|
||||
'name' => 'Specific Course Name',
|
||||
'lecturer' => 'Specific Lecturer',
|
||||
'semester' => $this->currentSemester,
|
||||
]);
|
||||
$targetSchedule = CourseSchedule::factory()->create(['course_id' => $targetCourse->id]);
|
||||
|
||||
$otherCourse = Course::factory()->create([
|
||||
'name' => 'Other Course Name',
|
||||
'semester' => $this->currentSemester,
|
||||
]);
|
||||
$otherSchedule = CourseSchedule::factory()->create(['course_id' => $otherCourse->id]);
|
||||
|
||||
// Search by course name
|
||||
Livewire::test(CourseSchedulePage::class)
|
||||
->set('search', 'Specific Course Name')
|
||||
->assertSet('search', 'Specific Course Name');
|
||||
|
||||
// Since it's a custom page, we check visibility within the computed property or the view
|
||||
// The schedules are grouped by day name (translated)
|
||||
$dayNames = [1 => 'Senin', 2 => 'Selasa', 3 => 'Rabu', 4 => 'Kamis', 5 => 'Jumat', 6 => 'Sabtu', 7 => 'Minggu'];
|
||||
$dayName = $dayNames[$targetSchedule->day_of_week];
|
||||
|
||||
Livewire::test(CourseSchedulePage::class)
|
||||
->set('search', 'Specific Course Name')
|
||||
->assertSee($targetCourse->name)
|
||||
->assertDontSee($otherCourse->name);
|
||||
|
||||
// Search by lecturer
|
||||
Livewire::test(CourseSchedulePage::class)
|
||||
->set('search', 'Specific Lecturer')
|
||||
->assertSee($targetCourse->name)
|
||||
->assertDontSee($otherCourse->name);
|
||||
});
|
||||
|
||||
it('only shows schedules for the current semester', function () {
|
||||
$otherSemester = $this->currentSemester + 1;
|
||||
$otherCourse = Course::factory()->create(['name' => 'Other Semester Course', 'semester' => $otherSemester]);
|
||||
$otherSchedule = CourseSchedule::factory()->create(['course_id' => $otherCourse->id]);
|
||||
|
||||
Livewire::test(CourseSchedulePage::class)
|
||||
->assertDontSee($otherCourse->name);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user