From cf4a633ded8322f648acdf07afc79c21cceadd24 Mon Sep 17 00:00:00 2001 From: Cameron Koegel <53310569+ckoegel@users.noreply.github.com> Date: Tue, 18 Jun 2024 15:59:27 -0400 Subject: [PATCH] SWI-5462 Add Real Time Transcriptions Tests (#207) * add privacy field to calls api test * remove unused env var * update recordings smoke tests to use new method names * add files for stats and transcriptions apis * update smoke test header blocks * add statistics smoke tests * fill in skeleton of transcriptions test * transcriptions * 403 from manteca :( * finalize transcriptions tests * update smoke test wf * only main --- .../{test-nightly.yml => test-smoke.yml} | 9 +- test/smoke/test_calls_api.py | 3 +- test/smoke/test_conferences_api.py | 2 +- test/smoke/test_media_api.py | 2 +- test/smoke/test_messages_api.py | 10 +- test/smoke/test_recordings_api.py | 32 ++-- test/smoke/test_statistics_api.py | 41 +++++ test/smoke/test_transcriptions_api.py | 154 ++++++++++++++++++ test/utils/env_variables.py | 1 - 9 files changed, 219 insertions(+), 35 deletions(-) rename .github/workflows/{test-nightly.yml => test-smoke.yml} (95%) create mode 100644 test/smoke/test_statistics_api.py create mode 100644 test/smoke/test_transcriptions_api.py diff --git a/.github/workflows/test-nightly.yml b/.github/workflows/test-smoke.yml similarity index 95% rename from .github/workflows/test-nightly.yml rename to .github/workflows/test-smoke.yml index 15325927..e3cd470d 100644 --- a/.github/workflows/test-nightly.yml +++ b/.github/workflows/test-smoke.yml @@ -1,4 +1,4 @@ -name: Nightly Smoke Tests +name: Smoke Tests on: schedule: @@ -13,6 +13,11 @@ on: options: - WARNING - DEBUG + pull_request: + branches: + - main + paths: + - 'test/smoke/**' concurrency: group: ${{ github.workflow }}-${{ github.head_ref }} @@ -39,7 +44,7 @@ env: jobs: test: - name: Nightly Smoke Test + name: Smoke Test runs-on: ubuntu-latest env: PYTHON_VERSION: '3.12' diff --git a/test/smoke/test_calls_api.py b/test/smoke/test_calls_api.py index 0dea554e..03b90049 100644 --- a/test/smoke/test_calls_api.py +++ b/test/smoke/test_calls_api.py @@ -1,5 +1,5 @@ """ -Integration test for Bandwidth's Voice Voice Calls API +Integration test for Bandwidth's Voice Calls API """ from bandwidth import ApiResponse from test.utils.env_variables import * @@ -57,6 +57,7 @@ def setUp(self): self.createCallBody = CreateCall( to=USER_NUMBER, var_from=BW_NUMBER, + privacy=True, application_id=BW_VOICE_APPLICATION_ID, answer_url=BASE_CALLBACK_URL, answer_method=CallbackMethodEnum("POST"), diff --git a/test/smoke/test_conferences_api.py b/test/smoke/test_conferences_api.py index e222c7b4..4af01266 100644 --- a/test/smoke/test_conferences_api.py +++ b/test/smoke/test_conferences_api.py @@ -1,5 +1,5 @@ """ -Integration tests for Bandwidth's Voice Voice Conferences API +Integration tests for Bandwidth's Voice Conferences API """ from cgi import test diff --git a/test/smoke/test_media_api.py b/test/smoke/test_media_api.py index 3c7dd6c4..23147811 100644 --- a/test/smoke/test_media_api.py +++ b/test/smoke/test_media_api.py @@ -1,5 +1,5 @@ """ -Integration test for Bandwidth's Media API +Integration test for Bandwidth's Messaging Media API """ import uuid diff --git a/test/smoke/test_messages_api.py b/test/smoke/test_messages_api.py index 8e5bcb27..074350a0 100644 --- a/test/smoke/test_messages_api.py +++ b/test/smoke/test_messages_api.py @@ -1,13 +1,5 @@ """ - Bandwidth - - - Bandwidth's Communication APIs # noqa: E501 - - - The version of the OpenAPI document: 1.0.0 - Contact: letstalk@bandwidth.com - Generated by: https://openapi-generator.tech +Integration test for Bandwidth's Messaging API """ import os diff --git a/test/smoke/test_recordings_api.py b/test/smoke/test_recordings_api.py index 17c9c4bf..e631a7a0 100644 --- a/test/smoke/test_recordings_api.py +++ b/test/smoke/test_recordings_api.py @@ -1,14 +1,6 @@ """ - Bandwidth - - Bandwidth's Communication APIs # noqa: E501 - - The version of the OpenAPI document: 1.0.0 - Contact: letstalk@bandwidth.com - Generated by: https://openapi-generator.tech +Integration test for Bandwidth's Voice Recordings API """ - - import os from typing import Dict, List, Tuple import unittest @@ -219,8 +211,8 @@ def test_successful_call_recording(self) -> None: - get_call_recording - download_call_recording - transcribe_call_recording - - get_call_transcription - - delete_call_transcription + - get_recording_transcription + - delete_recording_transcription - delete_recording_media - delete_recording """ @@ -288,7 +280,7 @@ def test_successful_call_recording(self) -> None: assert_that(call_status['callTranscribed'], equal_to(True)) # Get the transcription - transcription_response = self.recordings_api_instance.get_call_transcription_with_http_info( + transcription_response = self.recordings_api_instance.get_recording_transcription_with_http_info( BW_ACCOUNT_ID, call_id, recording_id) assert_that(transcription_response.status_code, equal_to(200)) # Check response code @@ -302,11 +294,11 @@ def test_successful_call_recording(self) -> None: )) # Delete the transcription - delete_transcription_response = self.recordings_api_instance.delete_call_transcription_with_http_info( + delete_transcription_response = self.recordings_api_instance.get_recording_transcription_with_http_info( BW_ACCOUNT_ID, call_id, recording_id) assert_that(delete_transcription_response.status_code, equal_to(204)) # Check response code - assert_that(calling(self.recordings_api_instance.get_call_transcription).with_args( + assert_that(calling(self.recordings_api_instance.get_recording_transcription).with_args( BW_ACCOUNT_ID, call_id, recording_id), raises(NotFoundException)) # Delete Recording media @@ -454,28 +446,28 @@ def test_4xx_errors(self) -> None: assert_that(call_status['callTranscribed'], equal_to(True)) # Use the unauthorized client to get transcripion (401) - assert_that(calling(self.unauthorized_recordings_api_instance.get_call_transcription).with_args( + assert_that(calling(self.unauthorized_recordings_api_instance.get_recording_transcription).with_args( BW_ACCOUNT_ID, call_id, recording_id), raises(UnauthorizedException)) # Non-existent account id (403) - assert_that(calling(self.recordings_api_instance.get_call_transcription).with_args( + assert_that(calling(self.recordings_api_instance.get_recording_transcription).with_args( "not an account id", call_id, recording_id), raises(ForbiddenException)) # Non-existent recording id (404) - assert_that(calling(self.recordings_api_instance.get_call_transcription).with_args( + assert_that(calling(self.recordings_api_instance.get_recording_transcription).with_args( BW_ACCOUNT_ID, call_id, "not a recording id"), raises(NotFoundException)) # Delete Transcription # Use the unauthorized client to delete transcripion (401) - assert_that(calling(self.unauthorized_recordings_api_instance.delete_call_transcription).with_args( + assert_that(calling(self.unauthorized_recordings_api_instance.delete_recording_transcription).with_args( BW_ACCOUNT_ID, call_id, recording_id), raises(UnauthorizedException)) # Non-existent account id (403) - assert_that(calling(self.recordings_api_instance.delete_call_transcription).with_args( + assert_that(calling(self.recordings_api_instance.delete_recording_transcription).with_args( "not an account id", call_id, recording_id), raises(ForbiddenException)) # Non-existent recording id (404) - assert_that(calling(self.recordings_api_instance.delete_call_transcription).with_args( + assert_that(calling(self.recordings_api_instance.delete_recording_transcription).with_args( BW_ACCOUNT_ID, call_id, "not a recording id"), raises(NotFoundException)) # Delete Recording Media diff --git a/test/smoke/test_statistics_api.py b/test/smoke/test_statistics_api.py new file mode 100644 index 00000000..2e99f0e7 --- /dev/null +++ b/test/smoke/test_statistics_api.py @@ -0,0 +1,41 @@ +""" +Integration test for Bandwidth's Statistics API +""" +import unittest +import logging + +from hamcrest import * +from bandwidth import ApiClient, Configuration +from bandwidth.api.statistics_api import StatisticsApi +from bandwidth.models import AccountStatistics +from test.utils.env_variables import * + + +class TestStatisticsApi(unittest.TestCase): + """StatisticsApi integration Test + """ + + def setUp(self): + configuration = Configuration( + username=BW_USERNAME, + password=BW_PASSWORD + ) + self.api_client = ApiClient(configuration) + self.api_instance = StatisticsApi(self.api_client) + self.account_id = BW_ACCOUNT_ID + + def test_get_statistics(self): + api_response_with_http_info = self.api_instance.get_statistics_with_http_info(self.account_id) + + logging.debug(api_response_with_http_info) + assert_that(api_response_with_http_info.status_code, equal_to(200)) + + api_response = self.api_instance.get_statistics(self.account_id) + assert_that(api_response, instance_of(AccountStatistics)) + assert_that(api_response, has_properties( + 'current_call_queue_size', instance_of(int), + 'max_call_queue_size', instance_of(int) + )) + +if __name__ == '__main__': + unittest.main() diff --git a/test/smoke/test_transcriptions_api.py b/test/smoke/test_transcriptions_api.py new file mode 100644 index 00000000..dda936ef --- /dev/null +++ b/test/smoke/test_transcriptions_api.py @@ -0,0 +1,154 @@ +""" +Integration test for Bandwidth's Voice Transcriptions API +""" +import unittest +import time + +from hamcrest import * +from bandwidth import ApiClient, Configuration +from bandwidth.rest import RESTClientObject, RESTResponse +from bandwidth.api.transcriptions_api import TranscriptionsApi +from bandwidth.api.calls_api import CallsApi +from bandwidth.models import CreateCall, CallTranscriptionMetadata, CallTranscriptionResponse, CallTranscription +from test.utils.env_variables import * + + +class TestTranscriptionsApi(unittest.TestCase): + """TranscriptionsApi integration Test""" + + def setUp(self) -> None: + configuration = Configuration( + username=BW_USERNAME, + password=BW_PASSWORD + ) + api_client = ApiClient(configuration) + + self.calls_api_instance = CallsApi(api_client) + self.transcriptions_api_instance = TranscriptionsApi(api_client) + + # Rest client for interacting with Manteca + self.rest_client = RESTClientObject(Configuration.get_default_copy()) + + # Call ID Array + self.callIdArray = [] + self.SLEEP_TIME_SEC = 3 + + # Transcription ID + self.transcription_id: str + + def create_call_transcription(self) -> None: + + # Initialize the call with Manteca + response = self.rest_client.request( + method='POST', + url=MANTECA_BASE_URL + '/tests', + body={ + 'os': OPERATING_SYSTEM, + 'language': 'python' + PYTHON_VERSION, + 'type': 'CALL' + }, + headers={ + 'Content-Type': 'application/json' + } + ) + + # Get the test id from the response + test_id = response.response.data.decode("utf-8") + answer_url = MANTECA_BASE_URL + '/bxml/idle' + + # Make a CreateCall body and assign the appropriate params + call_body = CreateCall(to=MANTECA_IDLE_NUMBER, var_from=MANTECA_ACTIVE_NUMBER, + application_id=MANTECA_APPLICATION_ID, answer_url=answer_url, tag=test_id) + + # Make the call + create_call_response: CreateCallResponse = self.calls_api_instance.create_call( + BW_ACCOUNT_ID, call_body) + # assert_that(create_call_response.status_code, equal_to(201)) + + # Get the call id from the response + self.call_id = create_call_response.call_id + + # Adding the call to the callIdArray + self.callIdArray.append(create_call_response.call_id) + + + time.sleep(self.SLEEP_TIME_SEC) + start_transcription_bxml = "" + start_response = self.calls_api_instance.update_call_bxml_with_http_info( + BW_ACCOUNT_ID, self.call_id, start_transcription_bxml) + assert_that(start_response.status_code, equal_to(204)) + + stop_transcription_bxml = "" + stop_response = self.calls_api_instance.update_call_bxml_with_http_info( + BW_ACCOUNT_ID, self.call_id, stop_transcription_bxml) + assert_that(stop_response.status_code, equal_to(204)) + time.sleep(self.SLEEP_TIME_SEC) + + end_response = self.calls_api_instance.update_call_with_http_info( + BW_ACCOUNT_ID, self.call_id, {"state": "completed"}) + assert_that(end_response.status_code, equal_to(200)) + + def list_real_time_transcriptions(self) -> None: + """Test case for list_real_time_transcriptions + + Enumerate transcriptions made with StartTranscription + """ + time.sleep(self.SLEEP_TIME_SEC * 20) + response = self.transcriptions_api_instance.list_real_time_transcriptions_with_http_info( + BW_ACCOUNT_ID, self.call_id) + + assert_that(response.status_code, equal_to(200)) + assert_that(response.data, instance_of(list)) + assert_that(response.data[0], instance_of(CallTranscriptionMetadata)) + assert_that(response.data[0].transcription_id, instance_of(str)) + assert_that(response.data[0].transcription_url, instance_of(str)) + + self.transcription_id = response.data[0].transcription_id + + def get_real_time_transcription(self) -> None: + """Test case for get_real_time_transcription + + Retrieve a specific transcription + """ + response = self.transcriptions_api_instance.get_real_time_transcription_with_http_info( + BW_ACCOUNT_ID, self.call_id, self.transcription_id) + + assert_that(response.status_code, equal_to(200)) + assert_that(response.data, instance_of(CallTranscriptionResponse)) + assert_that(response.data.account_id, equal_to(BW_ACCOUNT_ID)) + assert_that(response.data.call_id, equal_to(self.call_id)) + assert_that(response.data.transcription_id, equal_to(self.transcription_id)) + assert_that(response.data.tracks, instance_of(list)) + assert_that(response.data.tracks[0], instance_of(CallTranscription)) + assert_that(response.data.tracks[0].track, equal_to('inbound')) + assert_that(response.data.tracks[0].confidence, instance_of(float)) + + def delete_real_time_transcription(self) -> None: + """Test case for delete_real_time_transcription + + Delete a specific transcription + """ + response = self.transcriptions_api_instance.delete_real_time_transcription_with_http_info( + BW_ACCOUNT_ID, self.call_id, self.transcription_id) + + assert_that(response.status_code, equal_to(200)) + + def _steps(self): + call_order = [ + 'create_call_transcription', + 'list_real_time_transcriptions', + 'get_real_time_transcription', + 'delete_real_time_transcription' + ] + for name in call_order: + yield name, getattr(self, name) + + def test_steps(self) -> None: + """Test each function from _steps.call_order in specified order + """ + + for name, step in self._steps(): + step() + +if __name__ == '__main__': + unittest.main() diff --git a/test/utils/env_variables.py b/test/utils/env_variables.py index a6d11ef8..d9a89c73 100644 --- a/test/utils/env_variables.py +++ b/test/utils/env_variables.py @@ -7,7 +7,6 @@ BW_MESSAGING_APPLICATION_ID = os.environ['BW_MESSAGING_APPLICATION_ID'] BW_VOICE_APPLICATION_ID = os.environ['BW_VOICE_APPLICATION_ID'] BASE_CALLBACK_URL = os.environ['BASE_CALLBACK_URL'] - BW_NUMBER_PROVIDER = os.environ['BW_NUMBER_PROVIDER'] BW_NUMBER = os.environ['BW_NUMBER'] VZW_NUMBER = os.environ['VZW_NUMBER'] ATT_NUMBER = os.environ['ATT_NUMBER']