diff --git a/.github/actions/validate/entrypoint.sh b/.github/actions/validate/entrypoint.sh index 64d10db..714d1c5 100644 --- a/.github/actions/validate/entrypoint.sh +++ b/.github/actions/validate/entrypoint.sh @@ -1,3 +1,4 @@ #!/bin/sh -composer -h +composer require +./vendor/bin/phpunit tests diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 4ff1b5a..cad8a23 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -14,3 +14,15 @@ jobs: uses: actions/checkout@v2 - name: Validate uses: ./.github/actions/validate + env: + USERNAME: ${{ secrets.USERNAME }} + PASSWORD: ${{ secrets.PASSWORD }} + ACCOUNT_ID: ${{ secrets.ACCOUNT_ID }} + VOICE_APPLICATION_ID: ${{ secrets.VOICE_APPLICATION_ID }} + MESSAGING_APPLICATION_ID: ${{ secrets.MESSAGING_APPLICATION_ID }} + VOICE_CALLBACK_URL: ${{ secrets.VOICE_CALLBACK_URL }} + PHONE_NUMBER_OUTBOUND: ${{ secrets.PHONE_NUMBER_OUTBOUND }} + PHONE_NUMBER_INBOUND: ${{ secrets.PHONE_NUMBER_INBOUND }} + MFA_MESSAGING_APPLICATION_ID: ${{ secrets.MFA_MESSAGING_APPLICATION_ID }} + MFA_VOICE_APPLICATION_ID: ${{ secrets.MFA_VOICE_APPLICATION_ID }} + PHONE_NUMBER_MFA: ${{ secrets.PHONE_NUMBER_MFA }} diff --git a/composer.json b/composer.json index 46a90bc..c744b10 100644 --- a/composer.json +++ b/composer.json @@ -23,13 +23,11 @@ "apimatic/jsonmapper": "~1.3.0" }, "require-dev": { - "squizlabs/php_codesniffer": "^2.7", - "phan/phan": "^1.2", - "phpunit/phpunit": "4.8.*" + "phpunit/phpunit": "^9" }, "autoload": { "psr-4": { "BandwidthLib\\": "src/" } } -} \ No newline at end of file +} diff --git a/phpunit.xml b/phpunit.xml index 5844324..560f77c 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -1,7 +1,6 @@ getenv("USERNAME"), + 'messagingBasicAuthPassword' => getenv("PASSWORD"), + 'voiceBasicAuthUserName' => getenv("USERNAME"), + 'voiceBasicAuthPassword' => getenv("PASSWORD"), + 'twoFactorAuthBasicAuthUserName' => getenv("USERNAME"), + 'twoFactorAuthBasicAuthPassword' => getenv("PASSWORD") + ) + ); + $this->bandwidthClient = new BandwidthLib\BandwidthClient($config); + } + + public function testCreateMessage() { + $body = new BandwidthLib\Messaging\Models\MessageRequest(); + $body->from = getenv("PHONE_NUMBER_INBOUND"); + $body->to = [getenv("PHONE_NUMBER_OUTBOUND")]; + $body->applicationId = getenv("MESSAGING_APPLICATION_ID"); + $body->text = "PHP Monitoring"; + + $response = $this->bandwidthClient->getMessaging()->getClient()->createMessage(getenv("ACCOUNT_ID"), $body); + + $this->assertTrue(strlen($response->getResult()->id) > 0); //validate that _some_ id was returned + } + + public function testCreateMessageInvalidPhoneNumber() { + $body = new BandwidthLib\Messaging\Models\MessageRequest(); + $body->from = getenv("PHONE_NUMBER_INBOUND"); + $body->to = ["+1invalid"]; + $body->applicationId = getenv("MESSAGING_APPLICATION_ID"); + $body->text = "PHP Monitoring"; + + try { + $this->bandwidthClient->getMessaging()->getClient()->createMessage(getenv("ACCOUNT_ID"), $body); + //workaround to make sure that if the above error is not raised, the build will fail + $this->assertTrue(false); + } catch (BandwidthLib\Messaging\Exceptions\MessagingException $e) { + $this->assertTrue(strlen($e->description) > 0); + } + } + + public function testUploadDownloadMedia() { + //constants + + $mediaFileName = "php_monitoring"; + $mediaFile = "12345"; //todo: confirm binary string? + //media upload + $this->bandwidthClient->getMessaging()->getClient()->uploadMedia(getenv("ACCOUNT_ID"), $mediaFileName, strlen($mediaFile), $mediaFile); + + //media download + $downloadedMediaFile = $this->bandwidthClient->getMessaging()->getClient()->getMedia(getenv("ACCOUNT_ID"), $mediaFileName)->getResult(); + + //validate that response is the same + $this->assertEquals($downloadedMediaFile, $mediaFile); + } + + public function testCreateCallAndGetCallState() { + $body = new BandwidthLib\Voice\Models\ApiCreateCallRequest(); + $body->from = getenv("PHONE_NUMBER_INBOUND"); + $body->to = getenv("PHONE_NUMBER_OUTBOUND"); + $body->applicationId = getenv("VOICE_APPLICATION_ID"); + $body->answerUrl = getenv("VOICE_CALLBACK_URL"); + $response = $this->bandwidthClient->getVoice()->getClient()->createCall(getenv("ACCOUNT_ID"), $body); + $callId = $response->getResult()->callId; + $this->assertTrue(strlen($callId) > 0); + + //get phone call information + $response = $this->bandwidthClient->getVoice()->getClient()->getCallState(getenv("ACCOUNT_ID"), $callId); + $this->assertTrue(strlen($response->getResult()->state) > 0); + } + + public function testCreateCallInvalidPhoneNumber() { + $body = new BandwidthLib\Voice\Models\ApiCreateCallRequest(); + $body->from = getenv("PHONE_NUMBER_INBOUND"); + $body->to = "+1invalid"; + $body->applicationId = getenv("VOICE_APPLICATION_ID"); + $body->answerUrl = getenv("VOICE_CALLBACK_URL"); + + try { + $this->bandwidthClient->getVoice()->getClient()->createCall(getenv("ACCOUNT_ID"), $body); + //workaround to make sure that if the above error is not raised, the build will fail + $this->assertTrue(false); + } catch (BandwidthLib\Voice\Exceptions\ApiErrorResponseException $e) { + $this->assertTrue(strlen($e->description) > 0); + } + } + + public function testMfaMessaging() { + $body = new BandwidthLib\TwoFactorAuth\Models\TwoFactorCodeRequestSchema(); + $body->from = getenv("PHONE_NUMBER_MFA"); + $body->to = getenv("PHONE_NUMBER_INBOUND"); + $body->applicationId = getenv("MFA_MESSAGING_APPLICATION_ID"); + $body->scope = "scope"; + $body->digits = 6; + $body->message = "Your temporary {NAME} {SCOPE} code is {CODE}"; + + $response = $this->bandwidthClient->getTwoFactorAuth()->getMFA()->createMessagingTwoFactor(getenv("ACCOUNT_ID"), $body); + $this->assertTrue(strlen($response->getResult()->messageId) > 0); //validate that _some_ id was returned + } + + public function testMfaVoice() { + $body = new BandwidthLib\TwoFactorAuth\Models\TwoFactorCodeRequestSchema(); + $body->from = getenv("PHONE_NUMBER_MFA"); + $body->to = getenv("PHONE_NUMBER_INBOUND"); + $body->applicationId = getenv("MFA_VOICE_APPLICATION_ID"); + $body->scope = "scope"; + $body->digits = 6; + $body->message = "Your temporary {NAME} {SCOPE} code is {CODE}"; + + $response = $this->bandwidthClient->getTwoFactorAuth()->getMFA()->createVoiceTwoFactor(getenv("ACCOUNT_ID"), $body); + $this->assertTrue(strlen($response->getResult()->callId) > 0); //validate that _some_ id was returned + } + + public function testMfaVerify() { + $body = new BandwidthLib\TwoFactorAuth\Models\TwoFactorVerifyRequestSchema(); + $body->from = getenv("PHONE_NUMBER_MFA"); + $body->to = getenv("PHONE_NUMBER_INBOUND"); + $body->applicationId = getenv("MFA_VOICE_APPLICATION_ID"); + $body->scope = "scope"; + $body->code = "123456"; + $body->digits = 6; + $body->expirationTimeInMinutes = 3; + + $response = $this->bandwidthClient->getTwoFactorAuth()->getMFA()->createVerifyTwoFactor(getenv("ACCOUNT_ID"), $body); + $this->assertTrue(is_bool($response->getResult()->valid)); + } +} diff --git a/tests/BxmlTest.php b/tests/BxmlTest.php new file mode 100644 index 0000000..c154d80 --- /dev/null +++ b/tests/BxmlTest.php @@ -0,0 +1,404 @@ +to("+18888888888"); + $forward->from("+18889999999"); + $forward->callTimeout(3); + $forward->diversionTreatment("none"); + $forward->diversionReason("away"); + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($forward); + $expectedXml = ''; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testGatherNoNestedTag() { + $gather = new BandwidthLib\Voice\Bxml\Gather(); + $gather->gatherUrl("https://test.com"); + $gather->gatherMethod("GET"); + $gather->username("user"); + $gather->password("pass"); + $gather->tag("tag"); + $gather->terminatingDigits("123"); + $gather->maxDigits(3); + $gather->interDigitTimeout(4); + $gather->firstDigitTimeout(5); + $gather->repeatCount(3); + $gather->gatherFallbackUrl("https://test.com"); + $gather->gatherFallbackMethod("GET"); + $gather->fallbackUsername("fuser"); + $gather->fallbackPassword("fpass"); + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($gather); + $expectedXml = ''; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testGatherNestedSpeakSentence() { + $gather = new BandwidthLib\Voice\Bxml\Gather(); + $speakSentence = new BandwidthLib\Voice\Bxml\SpeakSentence("Test"); + $speakSentence->voice("susan"); + $speakSentence->locale("en_US"); + $speakSentence->gender("female"); + $gather = new BandwidthLib\Voice\Bxml\Gather(); + $gather->gatherUrl("https://test.com"); + $gather->gatherMethod("GET"); + $gather->username("user"); + $gather->password("pass"); + $gather->tag("tag"); + $gather->terminatingDigits("123"); + $gather->maxDigits(3); + $gather->interDigitTimeout(4); + $gather->firstDigitTimeout(5); + $gather->speakSentence($speakSentence); + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($gather); + $expectedXml = 'Test'; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testGatherNestedPlayAudio() { + $gather = new BandwidthLib\Voice\Bxml\Gather(); + $playAudio = new BandwidthLib\Voice\Bxml\PlayAudio("https://test.com"); + $playAudio->username("user"); + $playAudio->password("pass"); + $response = new BandwidthLib\Voice\Bxml\Response(); + $gather = new BandwidthLib\Voice\Bxml\Gather(); + $gather->gatherUrl("https://test.com"); + $gather->gatherMethod("GET"); + $gather->username("user"); + $gather->password("pass"); + $gather->tag("tag"); + $gather->terminatingDigits("123"); + $gather->maxDigits(3); + $gather->interDigitTimeout(4); + $gather->firstDigitTimeout(5); + $gather->playAudio($playAudio); + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($gather); + $expectedXml = 'https://test.com'; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testGatherNestedVerbs() { + $speakSentence1 = new BandwidthLib\Voice\Bxml\SpeakSentence("First Sentence"); + $playAudio1 = new BandwidthLib\Voice\Bxml\PlayAudio("https://audio1.com"); + $playAudio2 = new BandwidthLib\Voice\Bxml\PlayAudio("https://audio2.com"); + $speakSentence2 = new BandwidthLib\Voice\Bxml\SpeakSentence("Second Sentence"); + + $gather = new BandwidthLib\Voice\Bxml\Gather(); + $gather->gatherUrl("https://gather.url/nextBXML"); + $gather->speakSentence($speakSentence1); + $gather->playAudio($playAudio1); + $gather->playAudio($playAudio2); + $gather->speakSentence($speakSentence2); + + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($gather); + + $expectedXml = 'First Sentencehttps://audio1.comhttps://audio2.comSecond Sentence'; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testHangup() { + $hangup = new BandwidthLib\Voice\Bxml\Hangup(); + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($hangup); + $expectedXml = ''; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testRedirect() { + $redirect = new BandwidthLib\Voice\Bxml\Redirect(); + $redirect->username("user"); + $redirect->password("pass"); + $redirect->redirectUrl("https://test.com"); + $redirect->redirectMethod("GET"); + $redirect->tag("tag"); + $redirect->redirectFallbackUrl("https://test2.com"); + $redirect->redirectFallbackMethod("POST"); + $redirect->fallbackUsername("fuser"); + $redirect->fallbackPassword("fpass"); + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($redirect); + $expectedXml = ''; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testPause() { + $pause = new BandwidthLib\Voice\Bxml\Pause(); + $pause->duration("3"); + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($pause); + $expectedXml = ''; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testSendDtmf() { + $sendDtmf = new BandwidthLib\Voice\Bxml\SendDtmf("123"); + $sendDtmf->toneDuration("65"); + $sendDtmf->toneInterval(75); + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($sendDtmf); + $expectedXml = '123'; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testSpeakSentence() { + $speakSentence = new BandwidthLib\Voice\Bxml\SpeakSentence("Test"); + $speakSentence->voice("susan"); + $speakSentence->locale("en_US"); + $speakSentence->gender("female"); + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($speakSentence); + $expectedXml = 'Test'; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testSpeakSentenceSSML() { + $speakSentence = new BandwidthLib\Voice\Bxml\SpeakSentence('Hello, you have reached the home of Antonio Mendoza.Please leave a message.'); + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($speakSentence); + $expectedXml = 'Hello, you have reached the home of Antonio Mendoza.Please leave a message.'; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testPlayAudio() { + $playAudio = new BandwidthLib\Voice\Bxml\PlayAudio("https://test.com"); + $playAudio->username("user"); + $playAudio->password("pass"); + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($playAudio); + $expectedXml = 'https://test.com'; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testTransfer() { + $number1 = new BandwidthLib\Voice\Bxml\PhoneNumber("+17777777777"); + $number1->transferAnswerUrl("https://test.com"); + $number1->transferAnswerMethod("GET"); + $number1->username("user"); + $number1->password("pass"); + $number1->tag("tag"); + $number2 = new BandwidthLib\Voice\Bxml\PhoneNumber("+17777777779"); + $number2->transferAnswerUrl("https://test2.com"); + $number2->transferAnswerMethod("GET"); + $number2->username("user2"); + $number2->password("pass2"); + $number2->tag("tag2"); + $number2->transferAnswerFallbackUrl("https://test3.com"); + $number2->transferAnswerFallbackMethod("POST"); + $number2->fallbackUsername("fuser"); + $number2->fallbackPassword("fpass"); + $transfer = new BandwidthLib\Voice\Bxml\Transfer(); + $transfer->transferCallerId("+18999999999"); + $transfer->transferCompleteUrl("https://test.com"); + $transfer->transferCompleteMethod("GET"); + $transfer->username("user"); + $transfer->password("pass"); + $transfer->tag("tag"); + $transfer->callTimeout(3); + $transfer->diversionTreatment("none"); + $transfer->diversionReason("away"); + $transfer->phoneNumbers(array($number1, $number2)); + $transfer->transferCompleteFallbackUrl("https://test3.com"); + $transfer->transferCompleteFallbackMethod("POST"); + $transfer->fallbackUsername("fusern"); + $transfer->fallbackPassword("fpassw"); + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($transfer); + $expectedXml = '+17777777777+17777777779'; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testPauseRecording() { + $pauseRecording = new BandwidthLib\Voice\Bxml\PauseRecording(); + + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($pauseRecording); + + $expectedXml = ''; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testResumeRecording() { + $resumeRecording = new BandwidthLib\Voice\Bxml\ResumeRecording(); + + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($resumeRecording); + + $expectedXml = ''; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testStartRecording() { + $startRecording = new BandwidthLib\Voice\Bxml\StartRecording(); + $startRecording->tag("tag"); + $startRecording->recordingAvailableUrl("https://myapp.com/noBXML"); + $startRecording->recordingAvailableMethod("POST"); + $startRecording->username("user"); + $startRecording->password("pass"); + $startRecording->fileFormat("wav"); + $startRecording->multiChannel(true); + $startRecording->transcribe(false); + $startRecording->transcriptionAvailableUrl("https://available.com"); + $startRecording->transcriptionAvailableMethod("GET"); + + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($startRecording); + + $expectedXml = ''; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testStopRecording() { + $stopRecording = new BandwidthLib\Voice\Bxml\StopRecording(); + + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($stopRecording); + + $expectedXml = ''; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testRecord() { + $record = new BandwidthLib\Voice\Bxml\Record(); + $record->recordCompleteUrl("https://myapp.com/nextBXML"); + $record->maxDuration(10); + $record->recordCompleteFallbackUrl("https://test.com"); + $record->recordCompleteFallbackMethod("GET"); + $record->fallbackUsername("fuser"); + $record->fallbackPassword("fpass"); + + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($record); + + $expectedXml = ''; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testConference() { + $conference = new BandwidthLib\Voice\Bxml\Conference("conference-name"); + $conference->mute(true); + $conference->hold(false); + $conference->callIdsToCoach("c-abc,c-def"); + $conference->conferenceEventUrl("https://test.com"); + $conference->conferenceEventMethod("GET"); + $conference->username("user"); + $conference->password("pass"); + $conference->tag("tag"); + $conference->conferenceEventFallbackUrl("https://test2.com"); + $conference->conferenceEventFallbackMethod("POST"); + $conference->fallbackUsername("fuser"); + $conference->fallbackPassword("fpass"); + + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($conference); + + $expectedXml = 'conference-name'; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testConferenceCallIdsToCoachArray() { + $conference = new BandwidthLib\Voice\Bxml\Conference("conference-name"); + $conference->callIdsToCoachArray(["c-abc", "c-def"]); + + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($conference); + + $expectedXml = 'conference-name'; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testBridge() { + $bridge = new BandwidthLib\Voice\Bxml\Bridge("c-95ac8d6e-1a31c52e-b38f-4198-93c1-51633ec68f8d"); + $bridge->bridgeCompleteUrl("https://test.com"); + $bridge->bridgeCompleteMethod("GET"); + $bridge->bridgeTargetCompleteUrl("https://test2.com"); + $bridge->bridgeTargetCompleteMethod("POST"); + $bridge->username("user"); + $bridge->password("pass"); + $bridge->tag("custom tag"); + $bridge->bridgeCompleteFallbackUrl("https://test3.com"); + $bridge->bridgeCompleteFallbackMethod("GET"); + $bridge->bridgeTargetCompleteFallbackUrl("https://test4.com"); + $bridge->bridgeTargetCompleteFallbackMethod("POST"); + $bridge->fallbackUsername("fuser"); + $bridge->fallbackPassword("fpass"); + + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($bridge); + + $expectedXml = 'c-95ac8d6e-1a31c52e-b38f-4198-93c1-51633ec68f8d'; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testRing() { + $ring = new BandwidthLib\Voice\Bxml\Ring(); + $ring->duration(5); + + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($ring); + + $expectedXml = ''; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testStartGather() { + $startGather = new BandwidthLib\Voice\Bxml\StartGather(); + $startGather->username("user"); + $startGather->password("pass"); + $startGather->dtmfUrl("https://test.com"); + $startGather->dtmfMethod("GET"); + $startGather->tag("custom tag"); + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($startGather); + $expectedXml = ''; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } + + public function testStopGather() { + $stopGather = new BandwidthLib\Voice\Bxml\StopGather(); + $response = new BandwidthLib\Voice\Bxml\Response(); + $response->addVerb($stopGather); + $expectedXml = ''; + $responseXml = $response->toBxml(); + $this->assertEquals($expectedXml, $responseXml); + } +}