'https://calendly.com/legacy/general', 'app.calendly_booking_urls.vetting' => 'https://calendly.com/mdn/vetting', ]); $this->assertSame('https://calendly.com/mdn/vetting', $this->bookingUrl('vetting')); } public function test_vetting_booking_url_falls_back_to_legacy_config(): void { config([ 'app.calendly_booking_url' => 'https://calendly.com/legacy/general', 'app.calendly_booking_urls.vetting' => null, ]); $this->assertSame('https://calendly.com/legacy/general', $this->bookingUrl('vetting')); } public function test_vetting_booking_url_can_be_overridden_per_request(): void { config([ 'app.calendly_booking_url' => 'https://calendly.com/legacy/general', 'app.calendly_booking_urls.vetting' => 'https://calendly.com/mdn/vetting', ]); $this->assertSame('https://calendly.com/custom/vetting', $this->bookingUrl('vetting', 'https://calendly.com/custom/vetting')); } public function test_tracked_booking_url_includes_application_and_vetting_identifiers(): void { $url = $this->trackedBookingUrl('https://calendly.com/mdn/vetting?month=2026-07', 'app-123', 'vetting-456'); $this->assertStringStartsWith('https://calendly.com/mdn/vetting?month=2026-07&', $url); $this->assertStringContainsString('utm_content=app-123', $url); $this->assertStringContainsString('utm_term=vetting-456', $url); $this->assertStringContainsString('utm_campaign=application_vetting', $url); } public function test_tracking_values_are_read_from_calendly_payload(): void { $payload = [ 'tracking' => [ 'utm_content' => 'app-123', 'utm_term' => 'vetting-456', ], ]; $this->assertSame('app-123', $this->trackingValue($payload, 'utm_content')); $this->assertSame('vetting-456', $this->trackingValue($payload, 'utm_term')); } private function bookingUrl(string $eventType, ?string $override = null): ?string { $reflection = new ReflectionClass(ApplicationService::class); $service = $reflection->newInstanceWithoutConstructor(); $method = $reflection->getMethod('calendlyBookingUrl'); $method->setAccessible(true); return $method->invoke($service, $eventType, $override); } private function trackedBookingUrl(string $bookingUrl, string $applicationId, string $vettingId): string { $reflection = new ReflectionClass(ApplicationService::class); $service = $reflection->newInstanceWithoutConstructor(); $method = $reflection->getMethod('calendlyTrackedBookingUrl'); $method->setAccessible(true); return $method->invoke($service, $bookingUrl, $applicationId, $vettingId); } private function trackingValue(array $payload, string $key): ?string { $reflection = new ReflectionClass(ApplicationService::class); $service = $reflection->newInstanceWithoutConstructor(); $method = $reflection->getMethod('calendlyTrackingValue'); $method->setAccessible(true); return $method->invoke($service, $payload, $key); } }