sls/tests/Unit/InterviewCalendarServiceTest.php
kushal.saha e4fabef1d3 feat(interview): add icalendar invites, white date pickers, and drawer validation feedback
- integrate spatie/icalendar-generator for candidate & panelist .ics invitations (RSVP & 15m alerts)
    - add StoreInterviewRequest, ScheduleInterviewDto, and invitation/reminder queued actions
    - add migration for job_title, round, description, and reminder_sent_at on interviews table
    - style datetime-local picker indicators to pure white on dark input backgrounds
    - support button loading spinners with :showLoader="true" and loadingText
    - auto-open schedule drawer on validation failure with inline @error alerts and old() bindings
2026-08-27 10:16:46 +00:00

102 lines
4.1 KiB
PHP

<?php
namespace Tests\Unit;
use App\Models\Interview;
use App\Models\User;
use App\Services\Interview\InterviewCalendarService;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class InterviewCalendarServiceTest extends TestCase
{
use RefreshDatabase;
public function test_generates_standardized_event_title_matching_exact_pattern(): void
{
$service = new InterviewCalendarService;
// Target example: Interview Invitation_R1_Soumyadeep Mondal_AIML (Computer Vision & Agentic AI) Engineer_11/8/2026_1700
$scheduledAt = Carbon::create(2026, 8, 11, 17, 0, 0);
$interview = new Interview([
'candidate_name' => 'Soumyadeep Mondal',
'candidate_email' => 'soumyadeep@example.com',
'candidate_phone' => '9876543210',
'job_title' => 'AIML (Computer Vision & Agentic AI) Engineer',
'round' => 'R1',
'scheduled_at' => $scheduledAt,
'expires_at' => $scheduledAt->copy()->addHours(2),
'submission_unique_id' => 'soumyadeep-mondal_9876543210_1752000000',
'temp_password' => 'Pass-123456',
'language' => 'python',
]);
$this->assertEquals(
'Interview Invitation_R1_Soumyadeep Mondal_AIML (Computer Vision & Agentic AI) Engineer_11/8/2026_1700',
$interview->event_title
);
}
public function test_ics_generation_includes_start_time_rsvp_15min_alert_and_matching_request_method(): void
{
$service = new InterviewCalendarService;
$interviewer = User::create([
'name' => 'Panelist Reviewer',
'email' => 'panelist@company.com',
'role' => 'user',
]);
$scheduledAt = Carbon::create(2026, 8, 11, 17, 0, 0);
$interview = Interview::create([
'candidate_name' => 'Soumyadeep Mondal',
'candidate_email' => 'soumyadeep@example.com',
'candidate_phone' => '9876543210',
'job_title' => 'AIML (Computer Vision & Agentic AI) Engineer',
'round' => 'R1',
'description' => 'Focus on PyTorch & OpenCV live coding',
'scheduled_at' => $scheduledAt,
'expires_at' => $scheduledAt->copy()->addHours(2),
'submission_unique_id' => 'soumyadeep-mondal_9876543210_1752000001',
'temp_password' => 'Pass-998877',
'language' => 'python',
'status' => 'scheduled',
'assigned_interviewers' => [$interviewer->id],
]);
$ics = $service->generateIcs($interview);
$unfoldedIcs = str_replace(["\r\n ", "\n "], '', $ics);
// 1. Title
$this->assertStringContainsString('SUMMARY:Interview Invitation_R1_Soumyadeep Mondal_AIML (Computer Vision & Agentic AI) Engineer_11/8/2026_1700', $unfoldedIcs);
// 2. Start Time DTSTART is present
$this->assertStringContainsString('DTSTART', $ics);
// 3. RFC 5546 METHOD:REQUEST matching MIME method=REQUEST
$this->assertStringContainsString('METHOD:REQUEST', $ics);
$this->assertStringContainsString('SEQUENCE:0', $ics);
$this->assertStringContainsString('ORGANIZER', $ics);
// 4. Candidate Attendee with RSVP=TRUE
$this->assertStringContainsString('mailto:soumyadeep@example.com', strtolower($unfoldedIcs));
$this->assertStringContainsString('RSVP=TRUE', $ics);
$this->assertStringContainsString('PARTSTAT=NEEDS-ACTION', $ics);
// 5. Interviewer Attendee is included
$this->assertStringContainsString('mailto:panelist@company.com', strtolower($unfoldedIcs));
// 6. 15-Minute Alert / VALARM is included
$this->assertStringContainsString('BEGIN:VALARM', $ics);
$this->assertStringContainsString('-PT15M', $ics);
$this->assertStringContainsString('END:VALARM', $ics);
// 7. Description contains credentials
$this->assertStringContainsString('Pass-998877', $unfoldedIcs);
$this->assertStringContainsString('Focus on PyTorch & OpenCV live coding', $unfoldedIcs);
}
}