22Integration tests for Bandwidth's Voice Voice Conferences API
33"""
44
5+ from cgi import test
56import json
67import time
7- from typing import List , Tuple
8+ from typing import Dict , List , Tuple
89import unittest
910
1011from hamcrest import assert_that , has_properties , not_none , instance_of , greater_than
@@ -89,6 +90,7 @@ def setUp(self):
8990 self .testRecordId = "Recording-Id"
9091 self .TEST_SLEEP = 3
9192 self .TEST_SLEEP_LONG = 10
93+ self .MAX_RETRIES = 40
9294
9395 def tearDown (self ):
9496 callCleanup (self )
@@ -141,24 +143,44 @@ def create_conference(self, answer_url: str) -> Tuple[str, str]:
141143 '_from' , MANTECA_ACTIVE_NUMBER
142144 ))
143145
144- list_conferences_response = self .conference_api_instance .list_conferences (BW_ACCOUNT_ID , _return_http_data_only = False )
145-
146+
146147 time .sleep (self .TEST_SLEEP )
148+ list_conferences_response = self .conference_api_instance .list_conferences (BW_ACCOUNT_ID , name = test_id , _return_http_data_only = False )
149+
147150 assert_that (list_conferences_response [1 ], 200 )
148- conferenceId = (list_conferences_response [0 ][len (list_conferences_response [0 ])- 1 ].id )
149151
152+ # TODO: This is not deterministic; our latest conference may not always be the one we just created due to parallelism.
153+ # This new solution should guarantee the right conference id is grabbed.
154+ conference_id = list_conferences_response [0 ][0 ].id
150155
151- get_conference_response = self .conference_api_instance .get_conference (BW_ACCOUNT_ID , conferenceId , _return_http_data_only = False )
156+ get_conference_response = self .conference_api_instance .get_conference (BW_ACCOUNT_ID , conference_id , _return_http_data_only = False )
152157 assert_that (get_conference_response [1 ], 200 )
153158
154159 self .callIdArray .append (create_call_response .call_id )
155160
156- return (test_id , create_call_response .call_id )
161+ return (test_id , create_call_response .call_id , conference_id )
157162
158163 def validate_recording (self , recording : ConferenceRecordingMetadata , conference_id : str ) -> None :
159164 assert_that (recording .status ,'complete' )
160165 assert_that (recording .file_format ,FileFormatEnum ('wav' ))
161166
167+ def get_test_status (self , test_id : str ) -> Dict :
168+ """
169+ Get the status of the specified test by its id value from Manteca services.
170+
171+ Args:
172+ test_id (str): The test id associated with the test to get the status of.
173+
174+ Returns:
175+ Dict: The status of the test requested.
176+ """
177+ status_url = MANTECA_STATUS_URL + test_id
178+ response : RESTResponse = self .rest_client .request (
179+ method = 'GET' ,
180+ url = status_url
181+ )
182+ return json .loads (response .data )
183+
162184 def test_conference_and_members (self ):
163185 """
164186 Tests a successful flow of creating and ending a conference.
@@ -171,42 +193,43 @@ def test_conference_and_members(self):
171193 - update_conference_bxml
172194 """
173195
174- answer_url = MANTECA_BASE_URL + "/ bxml/joinConferencePause"
175- (test_id , call_id ) = self .create_conference (answer_url )
196+ answer_url = MANTECA_BASE_URL + "bxml/joinConferencePause"
197+ (test_id , call_id , conference_id ) = self .create_conference (answer_url )
176198
177199 list_conferences_response = self .conference_api_instance .list_conferences (BW_ACCOUNT_ID , _return_http_data_only = False )
178200
179201 assert_that (list_conferences_response [1 ], 200 )
180202 assert_that (list_conferences_response [0 ][0 ].name , instance_of (str ))
181203 assert_that (list_conferences_response [0 ][0 ].id , instance_of (str ))
182204
183- conferenceId = (list_conferences_response [0 ][len (list_conferences_response [0 ])- 1 ].id )
205+ # TODO: Also non-deterministic; we could differentiate by conference name instead? The conference name is set to be the test id by Manteca
206+ # conferenceId = (list_conferences_response[0][len(list_conferences_response[0])-1].id)
184207
185- get_conference_response = self .conference_api_instance .get_conference (BW_ACCOUNT_ID , conferenceId , _return_http_data_only = False )
208+ get_conference_response = self .conference_api_instance .get_conference (BW_ACCOUNT_ID , conference_id , _return_http_data_only = False )
186209 assert_that (get_conference_response [1 ], 200 )
187- assert_that (get_conference_response [0 ].id , conferenceId )
210+ assert_that (get_conference_response [0 ].id , conference_id )
188211 assert_that (get_conference_response [0 ].name , instance_of (str ))
189212 callId = (get_conference_response [0 ].active_members [0 ].call_id )
190213 self .callIdArray .append (callId )
191214
192- get_conference_member_response = self .conference_api_instance .get_conference_member (BW_ACCOUNT_ID , conferenceId , callId , _return_http_data_only = False )
215+ get_conference_member_response = self .conference_api_instance .get_conference_member (BW_ACCOUNT_ID , conference_id , callId , _return_http_data_only = False )
193216 assert_that (get_conference_member_response [1 ], 200 )
194- assert_that (get_conference_member_response [0 ].conference_id , conferenceId )
217+ assert_that (get_conference_member_response [0 ].conference_id , conference_id )
195218 assert_that (get_conference_member_response [0 ].call_id , callId )
196219
197- time .sleep (self .TEST_SLEEP )
198- update_conference_member_response = self .conference_api_instance .update_conference_member (BW_ACCOUNT_ID , conferenceId , callId , self .testUpdateMember , _return_http_data_only = False )
220+ # time.sleep(self.TEST_SLEEP)
221+ update_conference_member_response = self .conference_api_instance .update_conference_member (BW_ACCOUNT_ID , conference_id , callId , self .testUpdateMember , _return_http_data_only = False )
199222 assert_that (update_conference_member_response [1 ], 204 )
200223
201- time .sleep (self .TEST_SLEEP )
202- update_conference_response = self .conference_api_instance .update_conference (BW_ACCOUNT_ID , conferenceId , self .testUpdateConf , _return_http_data_only = False )
224+ # time.sleep(self.TEST_SLEEP)
225+ update_conference_response = self .conference_api_instance .update_conference (BW_ACCOUNT_ID , conference_id , self .testUpdateConf , _return_http_data_only = False )
203226 assert_that (update_conference_response [1 ], 204 )
204227
205228
206229 updateBxmlBody = '<?xml version="1.0" encoding="UTF-8"?><Bxml><SpeakSentence locale="en_US" gender="female" voice="susan">This is a test bxml response</SpeakSentence></Bxml>'
207230
208- time .sleep (self .TEST_SLEEP )
209- update_conference_bxml_response = self .conference_api_instance .update_conference_bxml (BW_ACCOUNT_ID , conferenceId , updateBxmlBody , _return_http_data_only = False )
231+ # time.sleep(self.TEST_SLEEP)
232+ update_conference_bxml_response = self .conference_api_instance .update_conference_bxml (BW_ACCOUNT_ID , conference_id , updateBxmlBody , _return_http_data_only = False )
210233 assert_that (update_conference_bxml_response [1 ], 204 )
211234
212235 update_call = UpdateCall (state = CallStateEnum ('completed' ))
@@ -221,39 +244,47 @@ def test_conference_recordings(self) -> None:
221244 - download_conference_recording
222245 """
223246
224- answer_url = MANTECA_BASE_URL + "/ bxml/joinConferencePause"
225- (test_id , call_id ) = self .create_conference (answer_url )
247+ answer_url = MANTECA_BASE_URL + "bxml/joinConferencePause"
248+ (test_id , call_id , conference_id ) = self .create_conference (answer_url )
226249
227250 list_conferences_response = self .conference_api_instance .list_conferences (BW_ACCOUNT_ID , _return_http_data_only = False )
228251
229252 assert_that (list_conferences_response [1 ], 200 )
230- conferenceId = (list_conferences_response [0 ][len (list_conferences_response [0 ])- 1 ].id )
231253
232254 updateBxmlBody = '<?xml version="1.0" encoding="UTF-8"?><Bxml><StartRecording/><SpeakSentence locale="en_US" gender="female" voice="susan">This should be a conference recording.</SpeakSentence><StopRecording/></Bxml>'
233- update_conference_bxml_response = self .conference_api_instance .update_conference_bxml (BW_ACCOUNT_ID , conferenceId , updateBxmlBody , _return_http_data_only = False )
255+ update_conference_bxml_response = self .conference_api_instance .update_conference_bxml (BW_ACCOUNT_ID , conference_id , updateBxmlBody , _return_http_data_only = False )
234256 assert_that (update_conference_bxml_response [1 ], 204 )
235-
236- time .sleep (self .TEST_SLEEP_LONG )
237257
238- list_conference_recordings_response : List [ConferenceRecordingMetadata ] = self .conference_api_instance .list_conference_recordings (BW_ACCOUNT_ID , conferenceId , _return_http_data_only = False )
258+ # Poll Manteca to ensure our conference is recorded
259+ call_status = self .get_test_status (test_id )
260+ retries = 0
261+ while call_status ['callRecorded' ] == False and retries < self .MAX_RETRIES :
262+ time .sleep (self .TEST_SLEEP )
263+ call_status = self .get_test_status (test_id )
264+ retries += 1
265+
266+ # If we failed to get a recorded conference, fail due to polling timeout
267+ assert call_status ['callRecorded' ] == True
268+
269+ list_conference_recordings_response : List [ConferenceRecordingMetadata ] = self .conference_api_instance .list_conference_recordings (BW_ACCOUNT_ID , conference_id , _return_http_data_only = False )
239270 assert_that (list_conference_recordings_response [1 ],200 )
240271
241272 conference_recordings = list_conference_recordings_response [0 ]
242273 assert_that (len (conference_recordings ), greater_than (0 ))
243274
244275 first_recording : ConferenceRecordingMetadata = conference_recordings [0 ]
245- self .validate_recording (first_recording , conferenceId )
276+ self .validate_recording (first_recording , conference_id )
246277 recording_id = first_recording .recording_id
247278
248- recording_response : ConferenceRecordingMetadata = self .conference_api_instance .get_conference_recording (BW_ACCOUNT_ID , conferenceId , recording_id , _return_http_data_only = False )
279+ recording_response : ConferenceRecordingMetadata = self .conference_api_instance .get_conference_recording (BW_ACCOUNT_ID , conference_id , recording_id , _return_http_data_only = False )
249280 assert_that (recording_response [1 ], 200 )
250- assert_that (recording_response [0 ].conference_id , conferenceId )
281+ assert_that (recording_response [0 ].conference_id , conference_id )
251282 assert_that (recording_response [0 ].recording_id , recording_id )
252283 assert_that (recording_response [0 ].name , instance_of (str ))
253284
254- self .validate_recording (recording_response [0 ], conferenceId )
285+ self .validate_recording (recording_response [0 ], conference_id )
255286
256- recording_media_response = self .conference_api_instance .download_conference_recording (BW_ACCOUNT_ID , conferenceId , recording_id , _preload_content = False )
287+ recording_media_response = self .conference_api_instance .download_conference_recording (BW_ACCOUNT_ID , conference_id , recording_id , _preload_content = False )
257288 conference_recording_media = recording_media_response .data
258289
259290 def test_list_conferences_unauthorized (self ) -> None :
0 commit comments