- 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
102 lines
4.1 KiB
PHP
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);
|
|
}
|
|
}
|