diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 465542e02..0e984dff9 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -2,7 +2,7 @@ ### 4.3.4 (UNRELEASED) * Fix for dialback dialing. [#1021] -* Fix for when an invalid or out of service number is specified for a volunteer. [#971] +* Fix for when an invalid or busy number is specified for a volunteer. [#971] ### 4.3.3 (May 1, 2024) * Fix for reports where they are always recursing service bodies regardless of the setting [#980] diff --git a/src/app/Constants/EventId.php b/src/app/Constants/EventId.php index 9b74f83e1..2c59ccf49 100644 --- a/src/app/Constants/EventId.php +++ b/src/app/Constants/EventId.php @@ -29,6 +29,7 @@ class EventId const SPAD_LOOKUP_SMS = 24; const VOLUNTEER_SEARCH_FORCE_DIALED = 25; const VOLUNTEER_NUMBER_BAD = 26; + const VOLUNTEER_NUMBER_BUSY = 27; public static function getEventById($id) { @@ -85,6 +86,8 @@ public static function getEventById($id) return "Volunteer Search Force Dial"; case self::VOLUNTEER_NUMBER_BAD: return "Volunteer Number is Bad"; + case self::VOLUNTEER_NUMBER_BUSY: + return "Volunteer Number is Busy"; } } } diff --git a/src/app/Http/Controllers/HelplineController.php b/src/app/Http/Controllers/HelplineController.php index 8ab2e2373..473a8ea12 100644 --- a/src/app/Http/Controllers/HelplineController.php +++ b/src/app/Http/Controllers/HelplineController.php @@ -246,7 +246,9 @@ public function dial(Request $request) { if ($request->has('noop')) { if ($request->has('CallStatus') && - ($request->get('CallStatus') == TwilioCallStatus::NOANSWER || $request->get('CallStatus') == TwilioCallStatus::FAILED)) { + ($request->get('CallStatus') == TwilioCallStatus::NOANSWER + || $request->get('CallStatus') == TwilioCallStatus::FAILED + || $request->get('CallStatus') == TwilioCallStatus::BUSY)) { $this->twilio->incrementNoAnswerCount(); } @@ -301,7 +303,11 @@ public function dial(Request $request) // TODO: Make timeout configurable per volunteer if (( $request->has('SequenceNumber') && intval($request->get('SequenceNumber')) == 1 ) || - ( $request->has('CallStatus') && ($request->get('CallStatus') == TwilioCallStatus::NOANSWER || $request->get('CallStatus') == TwilioCallStatus::COMPLETED || $request->get('CallStatus') == TwilioCallStatus::FAILED ))) { + ( $request->has('CallStatus') && + ($request->get('CallStatus') == TwilioCallStatus::NOANSWER + || $request->get('CallStatus') == TwilioCallStatus::COMPLETED + || $request->get('CallStatus') == TwilioCallStatus::FAILED + || $request->get('CallStatus') == TwilioCallStatus::BUSY ))) { $callConfig = $this->getCallConfig($request, $serviceBodyCallHandling); if ($request->has('CallStatus') && $request->get('CallStatus') == TwilioCallStatus::NOANSWER) { @@ -319,6 +325,14 @@ public function dial(Request $request) $request->get('CallSid'), CallRole::VOLUNTEER ); + } else if ($request->has('CallStatus') && $request->get('CallStatus') == TwilioCallStatus::BUSY) { + Log::error(sprintf("Volunteer Call Busy %s: %s", $request->get('Called'), $request->get('ErrorMessage'))); + $this->call->insertCallEventRecord(EventId::VOLUNTEER_NUMBER_BUSY, (object)['to_number' => $request->get('Called')]); + $this->call->setConferenceParticipant( + $request->get('FriendlyName'), + $request->get('CallSid'), + CallRole::VOLUNTEER + ); } Log::debug("Next volunteer to call " . $callConfig->volunteer->phoneNumber); diff --git a/src/app/Models/ConfigData.php b/src/app/Models/ConfigData.php index b2729b922..5fcf6a60b 100644 --- a/src/app/Models/ConfigData.php +++ b/src/app/Models/ConfigData.php @@ -54,7 +54,7 @@ public static function createGroup( public static function createVolunteer( int $serviceBodyId, int $parentServiceBodyId, - object $volunteerConfiguration + VolunteerData $volunteerConfiguration ) : void { self::create([ "service_body_id"=>$serviceBodyId, @@ -63,4 +63,17 @@ public static function createVolunteer( "data_type"=>DataType::YAP_VOLUNTEERS_V2 ]); } + + public static function createVolunteers( + int $serviceBodyId, + int $parentServiceBodyId, + array $volunteerDataArray + ) : void { + self::create([ + "service_body_id"=>$serviceBodyId, + "parent_id"=>$parentServiceBodyId, + "data"=>json_encode($volunteerDataArray), + "data_type"=>DataType::YAP_VOLUNTEERS_V2 + ]); + } } diff --git a/src/tests/Feature/HelplineDialerTest.php b/src/tests/Feature/HelplineDialerTest.php index 7afffeb75..c855f0a24 100644 --- a/src/tests/Feature/HelplineDialerTest.php +++ b/src/tests/Feature/HelplineDialerTest.php @@ -11,6 +11,8 @@ use App\Models\ConfigData; use App\Models\RecordType; use App\Models\ServiceBodyCallHandling; +use App\Models\VolunteerData; +use App\Models\VolunteerInfo; use App\Repositories\ConfigRepository; use App\Constants\DataType; use App\Repositories\ReportsRepository; @@ -116,28 +118,21 @@ ]; } - $volunteer = [[ - "volunteer_name"=>$volunteer_name, - "volunteer_phone_number"=>"(555) 111-2222", - "volunteer_gender"=>$volunteer_gender, - "volunteer_responder"=>$volunteer_responder, - "volunteer_languages"=>$volunteer_languages, - "volunteer_notes"=>"", - "volunteer_enabled"=>true, - "volunteer_shift_schedule"=>base64_encode(json_encode($shifts)) - ]]; - $this->configRepository = Mockery::mock(ConfigRepository::class)->makePartial(); - $this->configRepository->shouldReceive("getDbData")->with( + $volunteer = new VolunteerData(); + $volunteer->volunteer_name = $volunteer_name; + $volunteer->volunteer_phone_number = "(555) 111-2222"; + $volunteer->volunteer_gender = $volunteer_gender; + $volunteer->volunteer_responder = $volunteer_responder; + $volunteer->volunteer_languages = $volunteer_languages; + $volunteer->volunteer_notes = ""; + $volunteer->volunteer_enabled = true; + $volunteer->volunteer_shift_schedule = base64_encode(json_encode($shifts)); + + ConfigData::createVolunteer( $this->serviceBodyId, - DataType::YAP_VOLUNTEERS_V2 - )->andReturn([(object)[ - "service_body_id" => $this->serviceBodyId, - "id" => "200", - "parent_id" => $this->parentServiceBodyId, - "data" => json_encode($volunteer) - ]]); - - app()->instance(ConfigRepository::class, $this->configRepository); + $this->parentServiceBodyId, + $volunteer, + ); $response = $this->call($method, '/helpline-dialer.php', [ 'Debug' => "1", @@ -224,27 +219,21 @@ ]; } - $volunteer = [[ - "volunteer_name"=>$volunteer_name, - "volunteer_phone_number"=>$volunteer_phone_number, - "volunteer_gender"=>$volunteer_gender, - "volunteer_responder"=>$volunteer_responder, - "volunteer_languages"=>$volunteer_languages, - "volunteer_notes"=>"", - "volunteer_enabled"=>true, - "volunteer_shift_schedule"=>base64_encode(json_encode($shifts)) - ]]; - $this->configRepository->shouldReceive("getDbData")->with( + $volunteer = new VolunteerData(); + $volunteer->volunteer_name = $volunteer_name; + $volunteer->volunteer_phone_number = $volunteer_phone_number; + $volunteer->volunteer_gender = $volunteer_gender; + $volunteer->volunteer_responder = $volunteer_responder; + $volunteer->volunteer_languages = $volunteer_languages; + $volunteer->volunteer_notes = ""; + $volunteer->volunteer_enabled = true; + $volunteer->volunteer_shift_schedule = base64_encode(json_encode($shifts)); + + ConfigData::createVolunteer( $this->serviceBodyId, - DataType::YAP_VOLUNTEERS_V2 - )->andReturn([(object)[ - "service_body_id" => $this->serviceBodyId, - "id" => "200", - "parent_id" => $this->parentServiceBodyId, - "data" => json_encode($volunteer) - ]]); - - app()->instance(ConfigRepository::class, $this->configRepository); + $this->parentServiceBodyId, + $volunteer, + ); $conferenceListMock = mock("\Twilio\Rest\Api\V2010\Account\ConferenceList"); $conferenceListMock->shouldReceive("read") @@ -381,27 +370,21 @@ ]; } - $volunteer = [[ - "volunteer_name"=>$volunteer_name, - "volunteer_phone_number"=>$volunteer_phone_number, - "volunteer_gender"=>$volunteer_gender, - "volunteer_responder"=>$volunteer_responder, - "volunteer_languages"=>$volunteer_languages, - "volunteer_notes"=>"", - "volunteer_enabled"=>true, - "volunteer_shift_schedule"=>base64_encode(json_encode($shifts)) - ]]; - $this->configRepository->shouldReceive("getDbData")->with( + $volunteer = new VolunteerData(); + $volunteer->volunteer_name = $volunteer_name; + $volunteer->volunteer_phone_number = $volunteer_phone_number; + $volunteer->volunteer_gender = $volunteer_gender; + $volunteer->volunteer_responder = $volunteer_responder; + $volunteer->volunteer_languages = $volunteer_languages; + $volunteer->volunteer_notes = ""; + $volunteer->volunteer_enabled = true; + $volunteer->volunteer_shift_schedule = base64_encode(json_encode($shifts)); + + ConfigData::createVolunteer( $this->serviceBodyId, - DataType::YAP_VOLUNTEERS_V2 - )->andReturn([(object)[ - "service_body_id" => $this->serviceBodyId, - "id" => "200", - "parent_id" => $this->parentServiceBodyId, - "data" => json_encode($volunteer) - ]]); - - app()->instance(ConfigRepository::class, $this->configRepository); + $this->parentServiceBodyId, + $volunteer, + ); $conferenceListMock = mock("\Twilio\Rest\Api\V2010\Account\ConferenceList"); $conferenceListMock->shouldReceive("read") @@ -478,7 +461,7 @@ ->assertHeader("Content-Type", "application/json"); })->with(['GET', 'POST']); -test('an invalid outgoing call happens with linear and voicemail and one volunteer', function ($method) { +test('an invalid or busy outgoing call happens with linear and voicemail and one volunteer', function ($method, $twilioCallStatus) { $_SESSION['override_service_body_id'] = $this->serviceBodyId; $_SESSION['no_answer_max'] = 1; $_SESSION['master_callersid'] = $this->callSid; @@ -517,27 +500,21 @@ ]; } - $volunteer = [[ - "volunteer_name"=>$volunteer_name, - "volunteer_phone_number"=>$volunteer_phone_number, - "volunteer_gender"=>$volunteer_gender, - "volunteer_responder"=>$volunteer_responder, - "volunteer_languages"=>$volunteer_languages, - "volunteer_notes"=>"", - "volunteer_enabled"=>true, - "volunteer_shift_schedule"=>base64_encode(json_encode($shifts)) - ]]; - $this->configRepository->shouldReceive("getDbData")->with( + $volunteer = new VolunteerData(); + $volunteer->volunteer_name = $volunteer_name; + $volunteer->volunteer_phone_number = $volunteer_phone_number; + $volunteer->volunteer_gender = $volunteer_gender; + $volunteer->volunteer_responder = $volunteer_responder; + $volunteer->volunteer_languages = $volunteer_languages; + $volunteer->volunteer_notes = ""; + $volunteer->volunteer_enabled = true; + $volunteer->volunteer_shift_schedule = base64_encode(json_encode($shifts)); + + ConfigData::createVolunteer( $this->serviceBodyId, - DataType::YAP_VOLUNTEERS_V2 - )->andReturn([(object)[ - "service_body_id" => $this->serviceBodyId, - "id" => "200", - "parent_id" => $this->parentServiceBodyId, - "data" => json_encode($volunteer) - ]]); - - app()->instance(ConfigRepository::class, $this->configRepository); + $this->parentServiceBodyId, + $volunteer, + ); $conferenceListMock = mock("\Twilio\Rest\Api\V2010\Account\ConferenceList"); $conferenceListMock->shouldReceive("read") @@ -607,15 +584,25 @@ return $data['from'] == $this->caller && !empty($data['body'][0]); })); + $eventId = 0; + $payload = ""; + if ($twilioCallStatus === TwilioCallStatus::FAILED) { + $eventId = EventId::VOLUNTEER_NUMBER_BAD; + $payload = ["to_number"=>$this->volunteer_phone_number, "error"=>"invalid phone number"]; + } elseif ($twilioCallStatus === TwilioCallStatus::BUSY) { + $eventId = EventId::VOLUNTEER_NUMBER_BUSY; + $payload = ["to_number"=>$this->volunteer_phone_number]; + } + $reportsRepository = Mockery::mock(ReportsRepository::class); $reportsRepository->shouldReceive('insertSession') ->with($this->callSid) ->once(); $reportsRepository->shouldReceive('insertCallEventRecord') ->withArgs([$this->callSid, - EventId::VOLUNTEER_NUMBER_BAD, + $eventId, $this->serviceBodyId, - json_encode((object)["to_number"=>$this->volunteer_phone_number, "error"=>"invalid phone number"]), + json_encode((object)$payload), RecordType::PHONE]) ->once(); $reportsRepository->shouldReceive('setConferenceParticipant') @@ -629,7 +616,7 @@ 'OriginalCallerId' => "19193559674", 'FriendlyName' => $this->conferenceName, 'Direction' => 'outbound-api', - 'CallStatus' => 'failed', + 'CallStatus' => $twilioCallStatus, 'CallbackSource' => 'call-progress-events', 'ErrorMessage' => 'invalid phone number', 'tracker' => 1 @@ -637,9 +624,9 @@ $response ->assertStatus(200) ->assertHeader("Content-Type", "application/json"); -})->with(['GET', 'POST']); +})->with(['GET', 'POST'], [TwilioCallStatus::FAILED, TwilioCallStatus::BUSY]); -test('an invalid outgoing call happens with linear and voicemail and two volunteers', function ($method) { +test('an invalid or busy outgoing call happens with linear and voicemail and two volunteers', function ($method, $twilioCallStatus) { $_SESSION['override_service_body_id'] = $this->serviceBodyId; $_SESSION['no_answer_max'] = 1; $_SESSION['master_callersid'] = $this->callSid; @@ -681,36 +668,31 @@ ]; } - $volunteer = [[ - "volunteer_name"=>$volunteer_name, - "volunteer_phone_number"=>$volunteer_phone_number, - "volunteer_gender"=>$volunteer_gender, - "volunteer_responder"=>$volunteer_responder, - "volunteer_languages"=>$volunteer_languages, - "volunteer_notes"=>"", - "volunteer_enabled"=>true, - "volunteer_shift_schedule"=>base64_encode(json_encode($shifts)) - ],[ - "volunteer_name"=>$volunteer_name_2, - "volunteer_phone_number"=>$this->volunteer_phone_number_2, - "volunteer_gender"=>$volunteer_gender, - "volunteer_responder"=>$volunteer_responder, - "volunteer_languages"=>$volunteer_languages, - "volunteer_notes"=>"", - "volunteer_enabled"=>true, - "volunteer_shift_schedule"=>base64_encode(json_encode($shifts)) - ]]; - $this->configRepository->shouldReceive("getDbData")->with( + $volunteer1 = new VolunteerData(); + $volunteer1->volunteer_name = $volunteer_name; + $volunteer1->volunteer_phone_number = $this->volunteer_phone_number; + $volunteer1->volunteer_gender = $volunteer_gender; + $volunteer1->volunteer_responder = $volunteer_responder; + $volunteer1->volunteer_languages = $volunteer_languages; + $volunteer1->volunteer_notes = ""; + $volunteer1->volunteer_enabled = true; + $volunteer1->volunteer_shift_schedule = base64_encode(json_encode($shifts)); + + $volunteer2 = new VolunteerData(); + $volunteer2->volunteer_name = $volunteer_name_2; + $volunteer2->volunteer_phone_number = $this->volunteer_phone_number_2; + $volunteer2->volunteer_gender = $volunteer_gender; + $volunteer2->volunteer_responder = $volunteer_responder; + $volunteer2->volunteer_languages = $volunteer_languages; + $volunteer2->volunteer_notes = ""; + $volunteer2->volunteer_enabled = true; + $volunteer2->volunteer_shift_schedule = base64_encode(json_encode($shifts)); + + ConfigData::createVolunteers( $this->serviceBodyId, - DataType::YAP_VOLUNTEERS_V2 - )->andReturn([(object)[ - "service_body_id" => $this->serviceBodyId, - "id" => "200", - "parent_id" => $this->parentServiceBodyId, - "data" => json_encode($volunteer) - ]]); - - app()->instance(ConfigRepository::class, $this->configRepository); + $this->parentServiceBodyId, + [$volunteer1, $volunteer2], + ); $conferenceListMock = mock("\Twilio\Rest\Api\V2010\Account\ConferenceList"); $conferenceListMock->shouldReceive("read") @@ -784,11 +766,20 @@ $reportsRepository->shouldReceive('insertSession') ->with($this->callSid) ->once(); + + if ($twilioCallStatus === TwilioCallStatus::FAILED) { + $eventId = EventId::VOLUNTEER_NUMBER_BAD; + $payload = ["to_number"=>$this->volunteer_phone_number, "error"=>"invalid phone number"]; + } elseif ($twilioCallStatus === TwilioCallStatus::BUSY) { + $eventId = EventId::VOLUNTEER_NUMBER_BUSY; + $payload = ["to_number"=>$this->volunteer_phone_number]; + } + $reportsRepository->shouldReceive('insertCallEventRecord') ->withArgs([$this->callSid, - EventId::VOLUNTEER_NUMBER_BAD, + $eventId, $this->serviceBodyId, - json_encode((object)["to_number"=>$this->volunteer_phone_number, "error"=>"invalid phone number"]), + json_encode((object)$payload), RecordType::PHONE]) ->once(); $reportsRepository->shouldReceive('insertCallEventRecord') @@ -810,7 +801,7 @@ 'OriginalCallerId' => $this->caller, 'FriendlyName' => $this->conferenceName, 'Direction' => 'outbound-api', - 'CallStatus' => 'failed', + 'CallStatus' => $twilioCallStatus, 'CallbackSource' => 'call-progress-events', 'ErrorMessage' => 'invalid phone number', 'tracker' => 1 @@ -818,9 +809,9 @@ $response ->assertStatus(200) ->assertHeader("Content-Type", "application/json"); -})->with(['GET', 'POST']); +})->with(['GET', 'POST'], [TwilioCallStatus::FAILED, TwilioCallStatus::BUSY]); -test('an invalid outgoing call happens with blasting and voicemail and one volunteer', function ($method) { +test('an invalid or busy outgoing call happens with blasting and voicemail and one volunteer', function ($method, $twilioCallStatus) { $_SESSION['override_service_body_id'] = $this->serviceBodyId; $_SESSION['no_answer_max'] = 1; $_SESSION['master_callersid'] = $this->callSid; @@ -859,27 +850,21 @@ ]; } - $volunteer = [[ - "volunteer_name"=>$volunteer_name, - "volunteer_phone_number"=>$volunteer_phone_number, - "volunteer_gender"=>$volunteer_gender, - "volunteer_responder"=>$volunteer_responder, - "volunteer_languages"=>$volunteer_languages, - "volunteer_notes"=>"", - "volunteer_enabled"=>true, - "volunteer_shift_schedule"=>base64_encode(json_encode($shifts)) - ]]; - $this->configRepository->shouldReceive("getDbData")->with( + $volunteer = new VolunteerData(); + $volunteer->volunteer_name = $volunteer_name; + $volunteer->volunteer_phone_number = $this->volunteer_phone_number; + $volunteer->volunteer_gender = $volunteer_gender; + $volunteer->volunteer_responder = $volunteer_responder; + $volunteer->volunteer_languages = $volunteer_languages; + $volunteer->volunteer_notes = ""; + $volunteer->volunteer_enabled = true; + $volunteer->volunteer_shift_schedule = base64_encode(json_encode($shifts)); + + ConfigData::createVolunteer( $this->serviceBodyId, - DataType::YAP_VOLUNTEERS_V2 - )->andReturn([(object)[ - "service_body_id" => $this->serviceBodyId, - "id" => "200", - "parent_id" => $this->parentServiceBodyId, - "data" => json_encode($volunteer) - ]]); - - app()->instance(ConfigRepository::class, $this->configRepository); + $this->parentServiceBodyId, + $volunteer, + ); $conferenceListMock = mock("\Twilio\Rest\Api\V2010\Account\ConferenceList"); $this->twilioClient->conferences = $conferenceListMock; @@ -948,7 +933,7 @@ 'OriginalCallerId' => "19193559674", 'FriendlyName' => $this->conferenceName, 'Direction' => 'outbound-api', - 'CallStatus' => 'failed', + 'CallStatus' => $twilioCallStatus, 'CallbackSource' => 'call-progress-events', 'ErrorMessage' => 'invalid phone number', 'tracker' => 1, @@ -957,9 +942,9 @@ $response ->assertStatus(200) ->assertHeader("Content-Type", "application/json"); -})->with(['GET', 'POST']); +})->with(['GET', 'POST'], [TwilioCallStatus::FAILED, TwilioCallStatus::BUSY]); -test('an invalid outgoing call happens with blasting and voicemail and two volunteers', function ($method) { +test('an invalid or busy outgoing call happens with blasting and voicemail and two volunteers', function ($method, $twilioCallStatus) { $_SESSION['override_service_body_id'] = $this->serviceBodyId; $_SESSION['no_answer_max'] = 1; $_SESSION['master_callersid'] = $this->callSid; @@ -1001,36 +986,31 @@ ]; } - $volunteer = [[ - "volunteer_name"=>$volunteer_name, - "volunteer_phone_number"=>$volunteer_phone_number, - "volunteer_gender"=>$volunteer_gender, - "volunteer_responder"=>$volunteer_responder, - "volunteer_languages"=>$volunteer_languages, - "volunteer_notes"=>"", - "volunteer_enabled"=>true, - "volunteer_shift_schedule"=>base64_encode(json_encode($shifts)) - ],[ - "volunteer_name"=>$volunteer_name_2, - "volunteer_phone_number"=>$this->volunteer_phone_number_2, - "volunteer_gender"=>$volunteer_gender, - "volunteer_responder"=>$volunteer_responder, - "volunteer_languages"=>$volunteer_languages, - "volunteer_notes"=>"", - "volunteer_enabled"=>true, - "volunteer_shift_schedule"=>base64_encode(json_encode($shifts)) - ]]; - $this->configRepository->shouldReceive("getDbData")->with( + $volunteer1 = new VolunteerData(); + $volunteer1->volunteer_name = $volunteer_name; + $volunteer1->volunteer_phone_number = $this->volunteer_phone_number; + $volunteer1->volunteer_gender = $volunteer_gender; + $volunteer1->volunteer_responder = $volunteer_responder; + $volunteer1->volunteer_languages = $volunteer_languages; + $volunteer1->volunteer_notes = ""; + $volunteer1->volunteer_enabled = true; + $volunteer1->volunteer_shift_schedule = base64_encode(json_encode($shifts)); + + $volunteer2 = new VolunteerData(); + $volunteer2->volunteer_name = $volunteer_name_2; + $volunteer2->volunteer_phone_number = $this->volunteer_phone_number_2; + $volunteer2->volunteer_gender = $volunteer_gender; + $volunteer2->volunteer_responder = $volunteer_responder; + $volunteer2->volunteer_languages = $volunteer_languages; + $volunteer2->volunteer_notes = ""; + $volunteer2->volunteer_enabled = true; + $volunteer2->volunteer_shift_schedule = base64_encode(json_encode($shifts)); + + ConfigData::createVolunteers( $this->serviceBodyId, - DataType::YAP_VOLUNTEERS_V2 - )->andReturn([(object)[ - "service_body_id" => $this->serviceBodyId, - "id" => "200", - "parent_id" => $this->parentServiceBodyId, - "data" => json_encode($volunteer) - ]]); - - app()->instance(ConfigRepository::class, $this->configRepository); + $this->parentServiceBodyId, + [$volunteer1, $volunteer2], + ); $conferenceListMock = mock("\Twilio\Rest\Api\V2010\Account\ConferenceList"); $this->twilioClient->conferences = $conferenceListMock; @@ -1099,7 +1079,7 @@ 'OriginalCallerId' => "19193559674", 'FriendlyName' => $this->conferenceName, 'Direction' => 'outbound-api', - 'CallStatus' => 'failed', + 'CallStatus' => $twilioCallStatus, 'CallbackSource' => 'call-progress-events', 'ErrorMessage' => 'invalid phone number', 'tracker' => 1, @@ -1108,7 +1088,7 @@ $response ->assertStatus(200) ->assertHeader("Content-Type", "application/json"); -})->with(['GET', 'POST']); +})->with(['GET', 'POST'], [TwilioCallStatus::FAILED, TwilioCallStatus::BUSY]); test('caller leaves the call', function ($method) { $callsid = "CA460d1728a3e07606f36aaa8879a7fbd3";