Permalink
Browse files

finish testing queues

  • Loading branch information...
1 parent 5805181 commit 66a919d20533678ca348e925dce84d812236edcd @dsyang dsyang committed Aug 8, 2012
@@ -0,0 +1 @@
+{"call_sid": "CAaaf2e9ded94aba3e57c42a3d55be6ff2", "date_enqueued": "Tue, 07 Aug 2012 22:57:41 +0000", "wait_time": 143, "current_position": 1, "uri": "/2010-04-01/Accounts/ACf5af0ea0c9955b67b39c52fb11ee6e69/Queues/QUe675e1913214346f48a9d2296a8d3788/Members/CAaaf2e9ded94aba3e57c42a3d55be6ff2.json"}
@@ -0,0 +1 @@
+{"first_page_uri": "/2010-04-01/Accounts/ACf5af0ea0c9955b67b39c52fb11ee6e69/Queues/QUe675e1913214346f48a9d2296a8d3788/Members.json?Page=0&PageSize=50", "num_pages": 1, "previous_page_uri": null, "last_page_uri": "/2010-04-01/Accounts/ACf5af0ea0c9955b67b39c52fb11ee6e69/Queues/QUe675e1913214346f48a9d2296a8d3788/Members.json?Page=0&PageSize=50", "uri": "/2010-04-01/Accounts/ACf5af0ea0c9955b67b39c52fb11ee6e69/Queues/QUe675e1913214346f48a9d2296a8d3788/Members.json", "page_size": 50, "start": 0, "next_page_uri": null, "end": 0, "total": 1, "queue_members": [{"call_sid": "CAaaf2e9ded94aba3e57c42a3d55be6ff2", "date_enqueued": "Tue, 07 Aug 2012 22:57:41 +0000", "wait_time": 124, "current_position": 1, "uri": "/2010-04-01/Accounts/ACf5af0ea0c9955b67b39c52fb11ee6e69/Queues/QUe675e1913214346f48a9d2296a8d3788/Members/CAaaf2e9ded94aba3e57c42a3d55be6ff2.json"}], "page": 0}
@@ -0,0 +1 @@
+{"sid": "QU6e2cd5a7c8074edc8b383a3b198b2f8b", "friendly_name": "CutieQueue", "current_size": null, "average_wait_time": null, "max_size": 100, "date_created": "Tue, 07 Aug 2012 21:08:51 +0000", "date_updated": "Tue, 07 Aug 2012 21:08:51 +0000", "uri": "/2010-04-01/Accounts/ACf5af0ea0c9955b67b39c52fb11ee6e69/Queues/QU6e2cd5a7c8074edc8b383a3b198b2f8b.json"}
@@ -0,0 +1 @@
+{"first_page_uri": "/2010-04-01/Accounts/ACf5af0ea0c9955b67b39c52fb11ee6e69/Queues.json?Page=0&PageSize=50", "num_pages": 1, "previous_page_uri": null, "queues": [{"sid": "QU1b9faddec3d54ec18488f86c83019bf0", "friendly_name": "Support", "current_size": 0, "average_wait_time": 0, "max_size": 100, "date_created": "Tue, 07 Aug 2012 21:09:04 +0000", "date_updated": "Tue, 07 Aug 2012 21:09:04 +0000", "uri": "/2010-04-01/Accounts/ACf5af0ea0c9955b67b39c52fb11ee6e69/Queues/QU1b9faddec3d54ec18488f86c83019bf0.json"}, {"sid": "QU6e2cd5a7c8074edc8b383a3b198b2f8b", "friendly_name": "CutieQueue", "current_size": 0, "average_wait_time": 0, "max_size": 100, "date_created": "Tue, 07 Aug 2012 21:08:51 +0000", "date_updated": "Tue, 07 Aug 2012 21:08:51 +0000", "uri": "/2010-04-01/Accounts/ACf5af0ea0c9955b67b39c52fb11ee6e69/Queues/QU6e2cd5a7c8074edc8b383a3b198b2f8b.json"}, {"sid": "QUa8ce40f68d3f41958e2519646d55b989", "friendly_name": "Test1", "current_size": 0, "average_wait_time": 0, "max_size": 64, "date_created": "Tue, 07 Aug 2012 19:09:17 +0000", "date_updated": "Tue, 07 Aug 2012 19:09:17 +0000", "uri": "/2010-04-01/Accounts/ACf5af0ea0c9955b67b39c52fb11ee6e69/Queues/QUa8ce40f68d3f41958e2519646d55b989.json"}], "uri": "/2010-04-01/Accounts/ACf5af0ea0c9955b67b39c52fb11ee6e69/Queues.json", "page_size": 50, "start": 0, "next_page_uri": null, "end": 2, "total": 3, "last_page_uri": "/2010-04-01/Accounts/ACf5af0ea0c9955b67b39c52fb11ee6e69/Queues.json?Page=0&PageSize=50", "page": 0}
View
@@ -12,17 +12,6 @@
list_resource = Calls(BASE_URI, AUTH)
@patch("twilio.rest.resources.make_twilio_request")
-def test_paging(mock):
- resp = create_mock_json("tests/resources/calls_list.json")
- mock.return_value = resp
-
- uri = "%s/Calls" % (BASE_URI)
- list_resource.list(started=date(2010,12,5))
- exp_params = {'StartTime': '2010-12-05'}
-
- mock.assert_called_with("GET", uri, params=exp_params, auth=AUTH)
-
-@patch("twilio.rest.resources.make_twilio_request")
def test_create_call(mock):
resp = create_mock_json("tests/resources/calls_instance.json")
resp.status_code = 201
View
@@ -0,0 +1,70 @@
+from mock import patch, Mock
+from datetime import date
+from mock import patch, Mock
+from nose.tools import raises, assert_equals, assert_true
+from tools import create_mock_json
+from twilio.rest.resources import Queues, Queue
+
+BASE_URI = "https://api.twilio.com/2010-04-01/Accounts/AC123"
+ACCOUNT_SID = "AC123"
+AUTH = (ACCOUNT_SID, "token")
+QUEUE_SID = "QU1b9faddec3d54ec18488f86c83019bf0"
+CALL_SID = "CAaaf2e9ded94aba3e57c42a3d55be6ff2"
+
+list_resource = Queues(BASE_URI, AUTH)
+instance_resource = Queue(list_resource, QUEUE_SID)
+
+@patch("twilio.rest.resources.make_twilio_request")
+def test_queues_list(mock):
+ resp = create_mock_json("tests/resources/queues_list.json")
+ mock.return_value = resp
+
+ uri = "%s/Queues" % (BASE_URI)
+ list_resource.list()
+
+ mock.assert_called_with("GET", uri, params={}, auth=AUTH)
+
+@patch("twilio.rest.resources.make_twilio_request")
+def test_queues_create(mock):
+ resp = create_mock_json("tests/resources/queues_instance.json")
+ resp.status_code = 201
+ mock.return_value = resp
+
+ uri = "%s/Queues" % (BASE_URI)
+ list_resource.create('test', max_size=9001)
+
+ mock.assert_called_with("POST", uri,
+ data={'FriendlyName': 'test', 'MaxSize': 9001},
+ auth=AUTH)
+
+@patch("twilio.rest.resources.make_twilio_request")
+def test_queues_get(mock):
+ resp = create_mock_json("tests/resources/queues_instance.json")
+ mock.return_value = resp
+
+ uri = "%s/Queues/%s" % (BASE_URI, QUEUE_SID)
+ r = list_resource.get(QUEUE_SID)
+
+ mock.assert_called_with("GET", uri, auth=AUTH)
+
+
+@patch("twilio.rest.resources.make_twilio_request")
+def test_queue_update(mock):
+ resp = create_mock_json("tests/resources/queues_instance.json")
+ mock.return_value = resp
+
+ uri = "%s/Queues/%s" % (BASE_URI, QUEUE_SID)
+ r = instance_resource.update(friendly_name='QQ')
+
+ mock.assert_called_with("POST", uri, data={'FriendlyName':'QQ'}, auth=AUTH)
+
+
+@patch("twilio.rest.resources.make_twilio_request")
+def test_queue_delete(mock):
+ resp = create_mock_json("tests/resources/queues_instance.json")
+ mock.return_value = resp
+
+ uri = "%s/Queues/%s" % (BASE_URI, QUEUE_SID)
+ r = instance_resource.delete()
+
+ mock.assert_called_with("DELETE", uri, auth=AUTH)
View
@@ -26,7 +26,11 @@ def improperAppend(self, verb):
self.assertRaises(TwimlException, verb.append, twiml.Reject())
self.assertRaises(TwimlException, verb.append, twiml.Redirect())
self.assertRaises(TwimlException, verb.append, twiml.Dial())
+ self.assertRaises(TwimlException, verb.append, twiml.Enqueue(""))
+ self.assertRaises(TwimlException, verb.append, twiml.Queue(""))
+ self.assertRaises(TwimlException, verb.append, twiml.Leave())
self.assertRaises(TwimlException, verb.append, twiml.Conference(""))
+ self.assertRaises(TwimlException, verb.append, twiml.Client(""))
self.assertRaises(TwimlException, verb.append, twiml.Sms(""))
self.assertRaises(TwimlException, verb.append, twiml.Pause())
@@ -240,6 +244,20 @@ def testBadAppend(self):
self.improperAppend(twiml.Hangup())
+class TestLeave(TwilioTest):
+
+ def testLeave(self):
+ """convenience: should Hangup to a url via POST"""
+ r = Response()
+ r.append(twiml.Leave())
+ r = self.strip(r)
+ self.assertEquals(r, '<?xml version="1.0" encoding="UTF-8"?><Response><Leave /></Response>')
+
+ def testBadAppend(self):
+ """ should raise exceptions for wrong appending"""
+ self.improperAppend(twiml.Leave())
+
+
class TestReject(TwilioTest):
def testReject(self):
@@ -338,22 +356,51 @@ def setUp(self):
r = Response()
with r.dial() as dial:
dial.queue("TestQueueAttribute", url="", method='GET')
+ xml = r.toxml()
+
+ #parse twiml XML string with Element Tree and inspect
+ #structure
+ tree = ET.fromstring(xml)
+ self.conf = tree.find(".//Dial/Queue")
+
+ def test_conf_text(self):
+ self.assertEqual(self.conf.text.strip(), "TestQueueAttribute")
+
+ def test_conf_waiturl(self):
+ self.assertEqual(self.conf.get('url'), "")
+
+ def test_conf_method(self):
+ self.assertEqual(self.conf.get('method'), "GET")
+
+
+class TestEnqueue(TwilioTest):
+
+ def setUp(self):
+ r = Response()
+ r.enqueue("TestEnqueueAttribute", action="act", method='GET',
+ wait_url='wait', wait_url_method='POST')
xml = r.toxml()
#parse twiml XML string with Element Tree and inspect
#structure
tree = ET.fromstring(xml)
- self.conf = tree.find(".//Dial/Queue")
+ self.conf = tree.find(".//Enqueue")
def test_conf_text(self):
- self.assertEqual(self.conf.text.strip(), "TestQueueAttribute")
+ self.assertEqual(self.conf.text.strip(), "TestEnqueueAttribute")
def test_conf_waiturl(self):
- self.assertEqual(self.conf.get('url'), "")
+ self.assertEqual(self.conf.get('wait_url'), "wait")
def test_conf_method(self):
self.assertEqual(self.conf.get('method'), "GET")
+ def test_conf_action(self):
+ self.assertEqual(self.conf.get('action'), "act")
+
+ def test_conf_waitmethod(self):
+ self.assertEqual(self.conf.get('wait_url_method'), "POST")
+
class TestDial(TwilioTest):
View
@@ -7,6 +7,7 @@
from twilio.rest.resources import AuthorizedConnectApps
from twilio.rest.resources import Calls
from twilio.rest.resources import CallerIds
+from twilio.rest.resources import Queues
from twilio.rest.resources import ConnectApps
from twilio.rest.resources import Notifications
from twilio.rest.resources import Recordings
@@ -108,7 +109,7 @@ def __init__(self, account=None, token=None, base="https://api.twilio.com",
and be sure to replace the values for the Account SID and auth token with the
values from your Twilio Account at https://www.twilio.com/user/account.
""")
-
+
self.base = base
auth = (account, token)
version_uri = "%s/%s" % (base, version)
@@ -126,6 +127,7 @@ def __init__(self, account=None, token=None, base="https://api.twilio.com",
self.sms = Sms(account_uri, auth)
self.phone_numbers = PhoneNumbers(account_uri, auth)
self.conferences = Conferences(account_uri, auth)
+ self.queues = Queues(account_uri, auth)
self.sandboxes = Sandboxes(account_uri, auth)
self.auth = auth
@@ -138,4 +140,3 @@ def participants(self, conference_sid):
"""
base_uri = "%s/Conferences/%s" % (self.account_uri, conference_sid)
return Participants(base_uri, self.auth)
-
View
@@ -340,7 +340,7 @@ def update_instance(self, sid, body):
Update an InstanceResource via a POST
sid: string -- String identifier for the list resource
- body: string -- Dict of items to POST
+ body: dictionary -- Dict of items to POST
"""
uri = "%s/%s" % (self.uri, sid)
resp, entry = self.request("POST", uri, data=transform_params(body))
@@ -1183,13 +1183,13 @@ def update(self, **kwargs):
current size results in the queue rejecting incoming
requests until it shrinks below the new max size
"""
- return self.parent.update(self.sid, kwargs)
+ return self.parent.update_instance(self.name, kwargs)
def delete(self):
"""
Delete this queue. Can only be run on empty queues.
"""
- return self.parent.delete(self.sid)
+ return self.parent.delete_instance(self.name)
class Queues(ListResource):
@@ -1199,12 +1199,13 @@ class Queues(ListResource):
def list(self, **kwargs):
return self.get_instances(kwargs)
- def create(self, **kwargs):
+ def create(self, name, **kwargs):
""" Create an :class:`Queue` with any of these optional parameters.
- :param friendly_name: A human readable description of the application,
+ :param name: A human readable description of the application,
with maximum length 64 characters.
- :param max_size: The upper limit of calls allowed into the queue
+ :param max_size: The limit on calls allowed into the queue (optional)
"""
+ kwargs['friendly_name'] = name
return self.create_instance(kwargs)
@@ -1317,6 +1318,7 @@ class Account(InstanceResource):
PhoneNumbers,
Conferences,
ConnectApps,
+ Queues,
AuthorizedConnectApps,
]
View
@@ -82,7 +82,7 @@ def xml(self):
def append(self, verb):
if not self.nestables or verb.name not in self.nestables:
- raise TwimlException("%s is not nestable inside %s" % \
+ raise TwimlException("%s is not nestable inside %s" %
(verb.name, self.name))
self.verbs.append(verb)
return verb
@@ -101,6 +101,8 @@ class Response(Verb):
'Hangup',
'Reject',
'Sms',
+ 'Enqueue',
+ 'Leave'
]
def __init__(self, **kwargs):
@@ -147,6 +149,16 @@ def dial(self, number=None, **kwargs):
:class:`Response` """
return self.append(Dial(number, **kwargs))
+ def enqueue(self, name, **kwargs):
+ """Return a newly created :class:`Enqueue` verb, nested inside this
+ :class:`Response` """
+ return self.append(Enqueue(name, **kwargs))
+
+ def leave(self, **kwargs):
+ """Return a newly created :class:`Leave` verb, nested inside this
+ :class:`Response` """
+ return self.append(Leave(**kwargs))
+
def record(self, **kwargs):
"""Return a newly created :class:`Record` verb, nested inside this
:class:`Response` """
@@ -411,7 +423,23 @@ class Queue(Verb):
:param name: friendly name for the queue
:param url: url to a twiml document that executes after a call is dequeued
- and before the call is connected
+ and before the call is connected
+ :param method: HTTP method for url GET/POST
+ """
+ GET = 'GET'
+ POST = 'POST'
+
+ def __init__(self, name, **kwargs):
+ super(Queue, self).__init__(**kwargs)
+ self.body = name
+
+
+class Queue(Verb):
+ """Specify queue in a nested Dial element.
+
+ :param name: friendly name for the queue
+ :param url: url to a twiml document that executes after a call is dequeued
+ and before the call is connected
:param method: HTTP method for url GET/POST
"""
GET = 'GET'
@@ -422,6 +450,33 @@ def __init__(self, name, **kwargs):
self.body = name
+class Enqueue(Verb):
+ """Enqueue the call into a specific queue.
+
+ :param name: friendly name for the queue
+ :param action: url to a twiml document that executes when the call
+ leaves the queue. When dequeued vial a <Dial> verb,
+ this url is executed after the bridged parties disconnect
+ :param method: HTTP method for action GET/POST
+ :param wait_url: url to a twiml document that executes
+ while the call is on the queue
+ :param wait_url_methid: HTTP method for wait_url GET/POST
+ """
+ GET = 'GET'
+ POST = 'POST'
+
+ def __init__(self, name, **kwargs):
+ super(Enqueue, self).__init__(**kwargs)
+ self.body = name
+
+
+class Leave(Verb):
+ """Signals the call to leave it's queue
+ """
+ GET = 'GET'
+ POST = 'POST'
+
+
class Record(Verb):
"""Record audio from caller

0 comments on commit 66a919d

Please sign in to comment.