Merge lp:~canonical-platform-qa/ubuntu-system-tests/test_receive_sms into lp:ubuntu-system-tests

Proposed by Brendan Donegan
Status: Merged
Approved by: Richard Huddie
Approved revision: 116
Merged at revision: 121
Proposed branch: lp:~canonical-platform-qa/ubuntu-system-tests/test_receive_sms
Merge into: lp:ubuntu-system-tests
Prerequisite: lp:~canonical-platform-qa/ubuntu-system-tests/crendentials
Diff against target: 573 lines (+500/-0)
8 files modified
README.rst (+7/-0)
debian/tests/control (+2/-0)
ubuntu_system_tests/config.py (+14/-0)
ubuntu_system_tests/helpers/addressbook/dbus_service.py (+84/-0)
ubuntu_system_tests/helpers/telephony.py (+197/-0)
ubuntu_system_tests/helpers/unity8/notifications.py (+41/-0)
ubuntu_system_tests/tests/base.py (+26/-0)
ubuntu_system_tests/tests/test_messaging.py (+129/-0)
To merge this branch: bzr merge lp:~canonical-platform-qa/ubuntu-system-tests/test_receive_sms
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Richard Huddie (community) Approve
Brendan Donegan (community) Approve
Sergio Cazzolato Approve
Review via email: mp+260545@code.launchpad.net

Commit message

Test and framework for receiving an SMS

Description of the change

Add the sanity test for receiving an SMS and the supporting helpers

Note that the phone number cannot be queried from the SIM in all circumstances so we have to have it as a config option.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
100. By Brendan Donegan

Notifications helpers

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
101. By Brendan Donegan

Remove TODO comment

102. By Brendan Donegan

Update to/from_number config help text

103. By Brendan Donegan

Update README with info on getting telephony service access

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Richard Huddie (rhuddie) wrote :

This is looking good. I managed to get it working after a few problems (see comments below).

Also, some flake8 errors:
./ubuntu_system_tests/helpers/telephony.py:42:50: F821 undefined name 'message'
./ubuntu_system_tests/helpers/telephony.py:92:5: E303 too many blank lines (2)
./ubuntu_system_tests/helpers/telephony.py:107:9: F841 local variable 'response' is assigned to but never used
./ubuntu_system_tests/helpers/telephony.py:108:1: W293 blank line contains whitespace
./ubuntu_system_tests/helpers/telephony.py:120:9: F841 local variable 'url' is assigned to but never used
./ubuntu_system_tests/helpers/telephony.py:124:9: F841 local variable 'url' is assigned to but never used
./ubuntu_system_tests/helpers/unity8/notifications.py:23:1: E302 expected 2 blank lines, found 1
./ubuntu_system_tests/helpers/unity8/notifications.py:30:1: E302 expected 2 blank lines, found 1
./ubuntu_system_tests/helpers/unity8/notifications.py:36:1: W391 blank line at end of file

review: Needs Fixing
104. By Brendan Donegan

Fix flake8 issues in telephony helpers

105. By Brendan Donegan

Rename to_number to device_phone_number and from_number to telephony_service_number

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
106. By Brendan Donegan

Remove stray print statement

107. By Brendan Donegan

Added last bits of test and addressed last comments

Revision history for this message
Brendan Donegan (brendan-donegan) wrote :

Made a lot of updates, let's see what the Jenkins job comes back with.

Revision history for this message
Brendan Donegan (brendan-donegan) wrote :

Response to diff comments

Revision history for this message
Brendan Donegan (brendan-donegan) wrote :

Btw there is some new code at the end of the test to pay attention to, particularly to delete the message - maybe that should be done in a different way, not using the UI?

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Sergio Cazzolato (sergio-j-cazzolato) wrote :

2 comments inline

108. By Brendan Donegan

Comment up the test code

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Brendan Donegan (brendan-donegan) wrote :

Spoke to renato - since the dbus API is essentially private it could potentially change and break at any time - however the only public and supported way is using the C++ API. Writing bindings is laborious and fraught with danger, so I'd prefer to stick with using the DBus API. I would point out that this code was initially written nearly a year ago and still works as is so it's not as unstable as it might sound initially.

109. By Brendan Donegan

Merged from trunk

110. By Brendan Donegan

Fix flake8 issue

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Sergio Cazzolato (sergio-j-cazzolato) :
review: Approve
Revision history for this message
Brendan Donegan (brendan-donegan) wrote :

Tested again to make sure it works, and it does. If no further objections, we can top-approve?

review: Approve
Revision history for this message
Richard Huddie (rhuddie) wrote :

This looks really good, I ran the test fine.
Just 1 comment below about skipping the test if no sim inserted.

review: Needs Fixing
111. By Brendan Donegan

Skip test_receive_sms if no SIM is inserted

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
112. By Brendan Donegan

Merged from trunk

Revision history for this message
Brendan Donegan (brendan-donegan) wrote :

Skip added, tested both with and without SIM inserted, all works properly. Just wait for the Jenkins job to return clean and we can top-approve I guess

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
113. By Brendan Donegan

Revert removal of restart_unity

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
114. By Brendan Donegan

Remove _ensure_application_closed from test_messaging.py

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
115. By Brendan Donegan

typo in ensure_application_closed

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
116. By Richard Huddie

Temporarily remove use of tap_on notification method to improve reliability.

Revision history for this message
Richard Huddie (rhuddie) wrote :

Re-tested on mako with the notification change to improve reliability. Works fine.

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'README.rst'
2--- README.rst 2015-05-27 20:21:41 +0000
3+++ README.rst 2015-06-04 15:20:03 +0000
4@@ -92,6 +92,13 @@
5 To do this you need to be part of the platform-qa group on people.canonical.com
6 and have shell access there.
7
8+Set up telephony service access (currently Twilio)
9+--------------------------------------------------
10+
11+To run tests that use telephony service you will need an account on Twilio.com. Please
12+email qa-team@lists.canonical.com and they will set up a sub-account with its own API
13+credentials and an initial test number, as well as instructions on adding more.
14+
15 Copy data files to the testbed
16 ------------------------------
17
18
19=== modified file 'debian/tests/control'
20--- debian/tests/control 2015-05-26 16:23:26 +0000
21+++ debian/tests/control 2015-06-04 15:20:03 +0000
22@@ -4,12 +4,14 @@
23 Depends: address-book-app-autopilot (>=0.2+15.04.20150226-0ubuntu1),
24 camera-app-autopilot,
25 exiftool,
26+ messaging-app-autopilot,
27 oxideqt-chromedriver,
28 python3-autopilot,
29 python3-dbus,
30 python3-debian,
31 python3-gi,
32 python3-testtools,
33+ python3-requests,
34 python3-selenium,
35 subunit,
36 ubuntu-keyboard-autopilot,
37
38=== modified file 'ubuntu_system_tests/config.py'
39--- ubuntu_system_tests/config.py 2015-05-27 15:55:44 +0000
40+++ ubuntu_system_tests/config.py 2015-06-04 15:20:03 +0000
41@@ -54,6 +54,20 @@
42 'bluetooth_device_name',
43 help_string='Name of a nearby bluetooth pairing device'),
44 options.Option(
45+ 'device_phone_number',
46+ help_string="The phone number of the device to which calls "
47+ "and messages should be directed. This must "
48+ "be formatted exactly as you would dial it "
49+ "normally."),
50+ options.Option(
51+ 'telephony_service_number',
52+ help_string="The phone number to call and message from "
53+ "in the telephony service. In Twilio go to "
54+ "https://www.twilio.com/user/account/"
55+ "phone-numbers/incoming and click on the number "
56+ "you want to use, then copy the 'Phone Number' "
57+ "field exactly."),
58+ options.Option(
59 # this is a private key, that will not be exported to
60 # autopilot directly
61 '_twilio_account_sid', default=options.MANDATORY,
62
63=== added file 'ubuntu_system_tests/helpers/addressbook/dbus_service.py'
64--- ubuntu_system_tests/helpers/addressbook/dbus_service.py 1970-01-01 00:00:00 +0000
65+++ ubuntu_system_tests/helpers/addressbook/dbus_service.py 2015-06-04 15:20:03 +0000
66@@ -0,0 +1,84 @@
67+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
68+
69+#
70+# Ubuntu System Tests
71+# Copyright (C) 2015 Canonical
72+#
73+# This program is free software: you can redistribute it and/or modify
74+# it under the terms of the GNU General Public License version 3,
75+# as published by the Free Software Foundation.
76+#
77+# This program is distributed in the hope that it will be useful,
78+# but WITHOUT ANY WARRANTY; without even the implied warranty of
79+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
80+# GNU General Public License for more details.
81+#
82+# You should have received a copy of the GNU General Public License
83+# along with this program. If not, see <http://www.gnu.org/licenses/>.
84+#
85+
86+import dbus
87+import re
88+
89+
90+DBUS_NAME_PIM = 'com.canonical.pim'
91+DBUS_IFACE_ADDRESS_BOOK = 'com.canonical.pim.AddressBook'
92+DBUS_IFACE_ADDRESS_BOOKVIEW = 'com.canonical.pim.AddressBookView'
93+DBUS_OBJECT_ADDRESS_BOOK = '/com/canonical/pim/AddressBook'
94+
95+
96+class ContactsDbusService:
97+ def __init__(self):
98+ self.bus = None
99+ self.addr = None
100+ self.addr_iface = None
101+ self.bus = dbus.SessionBus()
102+ self.addr = self.bus.get_object(
103+ DBUS_NAME_PIM, DBUS_OBJECT_ADDRESS_BOOK)
104+ self.addr_iface = dbus.Interface(
105+ self.addr, dbus_interface=DBUS_IFACE_ADDRESS_BOOK)
106+
107+ def query_contacts(self, fields='', query='', sources=[]):
108+ view_path = self.addr_iface.query(fields, query, [])
109+ view = self.bus.get_object(
110+ DBUS_NAME_PIM, view_path)
111+ view_iface = dbus.Interface(
112+ view, dbus_interface=DBUS_IFACE_ADDRESS_BOOKVIEW)
113+ contacts = view_iface.contactsDetails([], 0, -1)
114+ view.close()
115+ return contacts
116+
117+ def update_contact(self, vcard):
118+ return self.addr_iface.updateContacts([vcard])
119+
120+ def create_contact(self, vcard):
121+ return self.addr_iface.createContact(vcard, "")
122+
123+ def delete_contact(self, ids):
124+ return self.addr_iface.removeContacts(ids)
125+
126+ def get_vcard_uid(self, vcard):
127+ """
128+ Return the UID of the provided vcard
129+ :param vcard: vcard formatted data
130+ :return: uid value from vcard, else None
131+ """
132+ uid_pattern = re.compile(r'^UID:(?P<uid>\S*)\r?$',
133+ re.MULTILINE | re.IGNORECASE)
134+ uid = None
135+ match = uid_pattern.search(vcard)
136+ if match:
137+ uid = match.group('uid')
138+ return uid
139+
140+ def delete_all_contacts(self):
141+ """
142+ Delete all contacts using the dbus service
143+ """
144+ uids = []
145+ contacts = self.query_contacts()
146+ for contact in contacts:
147+ uid = self.get_vcard_uid(contact)
148+ if uid:
149+ uids.append(uid)
150+ self.delete_contact(uids)
151
152=== added file 'ubuntu_system_tests/helpers/telephony.py'
153--- ubuntu_system_tests/helpers/telephony.py 1970-01-01 00:00:00 +0000
154+++ ubuntu_system_tests/helpers/telephony.py 2015-06-04 15:20:03 +0000
155@@ -0,0 +1,197 @@
156+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
157+
158+#
159+# Ubuntu Sanity Tests
160+# Copyright (C) 2015 Canonical
161+#
162+# This program is free software: you can redistribute it and/or modify
163+# it under the terms of the GNU General Public License as published by
164+# the Free Software Foundation, either version 3 of the License, or
165+# (at your option) any later version.
166+#
167+# This program is distributed in the hope that it will be useful,
168+# but WITHOUT ANY WARRANTY; without even the implied warranty of
169+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
170+# GNU General Public License for more details.
171+#
172+# You should have received a copy of the GNU General Public License
173+# along with this program. If not, see <http://www.gnu.org/licenses/>.
174+#
175+
176+import functools
177+import logging
178+import requests
179+
180+from requests.auth import HTTPBasicAuth
181+
182+logger = logging.getLogger(__name__)
183+
184+TWILIO_API_URL = "https://api.twilio.com/2010-04-01"
185+
186+
187+class Telephony:
188+
189+ def __init__(self, credentials, backend='twilio'):
190+ self._backend = _get_backend(backend)(credentials)
191+
192+ def send_sms(self, to, from_, message):
193+ return self._backend.send_sms(to, from_, message)
194+
195+ def get_sent_sms(self, to, from_, date):
196+ return self._backend.get_sent_sms(to, from_, date)
197+
198+ def send_mms(self, to, from_, message, media):
199+ return self._backend.send_mms(to, from_, message, media)
200+
201+ def make_phonecall(self, to, from_, hangup_timeout, voice_message):
202+ return self._backend.make_phonecall(to, from_, hangup_timeout,
203+ voice_message)
204+
205+
206+NeedBackendError = functools.partial(
207+ NotImplementedError,
208+ "This class cannot be instantiated. Please use a specific backend."
209+)
210+
211+
212+class TelephonyBackend:
213+
214+ def __init__(self, credentials):
215+ """
216+ :param credentials: dictionary containing the required credential
217+ details specific for the backend.
218+
219+ :raises ValueError: if any required credential details are missing.
220+
221+ """
222+ raise NeedBackendError()
223+
224+ def send_sms(self, to, from_, message):
225+ raise NeedBackendError()
226+
227+ def get_sent_sms(self, to, from_, date):
228+ raise NeedBackendError()
229+
230+ def send_mms(self, to, from_, message, media):
231+ raise NeedBackendError()
232+
233+ def make_phonecall(self, to, from_, hangup_timeout, voice_message):
234+ # Only a suggestion, not sure specifics what are required.
235+ raise NeedBackendError()
236+
237+
238+class TwilioBackend(TelephonyBackend):
239+ """Backend that utilises the Twilio service.
240+
241+ Required credentials are:
242+ - AccountSid: This represents the account id
243+ - AuthToken: This is the token used to authenticate the request against
244+ the account (Note: It must be kept secret!).
245+
246+ """
247+
248+ def __init__(self, credentials):
249+ _raise_if_required_credentials_missing(
250+ credentials, 'AccountSid', 'AuthToken')
251+ self._account_sid = credentials['AccountSid']
252+ self._account_auth = credentials['AuthToken']
253+ self._http_auth = HTTPBasicAuth(self._account_sid, self._account_auth)
254+
255+ def send_sms(self, to, from_, message):
256+ # Ensure recipient number meets expectations
257+ # (i.e. https://www.twilio.com/docs/api/rest/sending-messages#post 'To'
258+ # field details.)
259+ _raise_if_number_doesnt_look_valid(to)
260+ _raise_if_number_doesnt_look_valid(from_)
261+ url = self._get_api_url('Messages')
262+ params = {'From': from_, 'To': to, 'Body': message}
263+ response = requests.post(url, data=params, auth=self._http_auth)
264+ if not response.ok:
265+ logger.error(response.text)
266+ return response.ok
267+
268+ def get_sent_sms(self, to, from_, time):
269+ _raise_if_number_doesnt_look_valid(to)
270+ _raise_if_number_doesnt_look_valid(from_)
271+ url = self.get_api_url('Messages')
272+ params = {'From': from_, 'To': to, 'DateSent': str(time.date)}
273+ response = requests.get(url, data=params, auth=self._http_auth)
274+ for message in response.json()['messages']:
275+ print(message)
276+
277+ def send_mms(self, number, message, media):
278+ _raise_if_number_doesnt_look_valid(number)
279+ url = self._get_api_url('Messages') # NOQA
280+
281+ def make_phonecall(self, number, hangup_timeout, voice_message):
282+ _raise_if_number_doesnt_look_valid(number)
283+ url = self._get_api_url('Calls') # NOQA
284+
285+ def _get_api_url(self, action):
286+ """Return API URL to post to."""
287+ api_url = TWILIO_API_URL + '/Accounts/{sid}/{action}.json'.format(
288+ sid=self._account_sid,
289+ action=action
290+ )
291+ return api_url
292+
293+
294+class FakeBackend(TelephonyBackend):
295+ """A verified fake for use with testing.
296+
297+ Does not make any calls to external resources nor does it intiate any
298+ actual calls/messages.
299+
300+ """
301+ pass
302+
303+
304+def _make_rest_request(url, params, auth_details):
305+ """Return request object containing the results of the REST request."""
306+ # i.e. r = requests.post(....)
307+ # return r or should we check the status code here and raise an exception
308+ # if it's not what's expected (could be another arg.)
309+ pass
310+
311+
312+def _get_backend(backend):
313+ """Return the requested backend class
314+
315+ :raises ValueError: if the requested backend was not found.
316+
317+ """
318+ # i.e. return TwiloBackend (well, smarter than that)
319+ # The register (or whatever) could be a lot nicer too.
320+
321+ backend_register = dict(
322+ twilio=TwilioBackend,
323+ fake=FakeBackend,
324+ )
325+ return backend_register[backend]
326+
327+
328+def _raise_if_number_doesnt_look_valid(number):
329+ """Ensure number looks valid (i.e. E.164 format).
330+
331+ Does not ensure the number is in service etc.
332+ """
333+ pass
334+
335+
336+def _raise_if_required_credentials_missing(credentials, *required_keys):
337+ """Raise ValueError if any required keys are absent from credentials.
338+
339+ The exception string will include a description of which keys are missing.
340+
341+ """
342+ missing_keys = []
343+ for key in required_keys:
344+ if credentials.get(key, None) is None:
345+ missing_keys.append(key)
346+
347+ if missing_keys:
348+ raise ValueError(
349+ "Missing required credential detail{plural}: '{details}'".format(
350+ plural='s' if len(missing_keys) > 1 else '',
351+ details=', '.join(missing_keys))
352+ )
353
354=== added file 'ubuntu_system_tests/helpers/unity8/notifications.py'
355--- ubuntu_system_tests/helpers/unity8/notifications.py 1970-01-01 00:00:00 +0000
356+++ ubuntu_system_tests/helpers/unity8/notifications.py 2015-06-04 15:20:03 +0000
357@@ -0,0 +1,41 @@
358+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
359+
360+#
361+# Ubuntu System Tests
362+# Copyright (C) 2015 Canonical
363+#
364+# This program is free software: you can redistribute it and/or modify
365+# it under the terms of the GNU General Public License version 3,
366+# as published by the Free Software Foundation.
367+#
368+# This program is distributed in the hope that it will be useful,
369+# but WITHOUT ANY WARRANTY; without even the implied warranty of
370+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
371+# GNU General Public License for more details.
372+#
373+# You should have received a copy of the GNU General Public License
374+# along with this program. If not, see <http://www.gnu.org/licenses/>.
375+#
376+
377+
378+import ubuntuuitoolkit
379+
380+from ubuntu_system_tests.helpers.autopilot import override_proxy_timeout
381+
382+
383+class Notifications(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
384+
385+ def get_current_notification(self):
386+ with override_proxy_timeout(self, 60):
387+ return self.wait_select_single(
388+ 'Notification',
389+ objectName='notification1'
390+ )
391+
392+
393+class Notification(ubuntuuitoolkit.UbuntuUIToolkitCustomProxyObjectBase):
394+
395+ def tap_on(self):
396+ self.pointing_device.click_object(
397+ self.select_single(objectName="interactiveArea")
398+ )
399
400=== modified file 'ubuntu_system_tests/tests/base.py'
401--- ubuntu_system_tests/tests/base.py 2015-06-03 17:04:45 +0000
402+++ ubuntu_system_tests/tests/base.py 2015-06-04 15:20:03 +0000
403@@ -32,6 +32,7 @@
404 from unity8 import process_helpers
405 from unity8.shell.emulators import dash
406
407+from ubuntu_system_tests import config
408 from ubuntu_system_tests.helpers import unity8
409 from ubuntu_system_tests.helpers.unity8 import shell
410
411@@ -88,3 +89,28 @@
412 def ensure_application_closed(self, app_name):
413 """Stop the app before unity8 is restarted so it's not orphaned."""
414 subprocess.call(['ubuntu-app-stop', app_name])
415+
416+
417+class BaseTelephonyTestCase(BaseUbuntuSystemTestCase):
418+ """Base class to be used for all telephony tests."""
419+
420+ def setUp(self):
421+ """Base class setUp method."""
422+ super().setUp()
423+ self.config_stack = config.get_device_config_stack()
424+
425+ def get_telephony_service_account_id(self):
426+ """Return account id for telephony service."""
427+ return self.config_stack.get('_twilio_account_sid')
428+
429+ def get_telephony_service_auth_token(self):
430+ """Return auth token for telephony service."""
431+ return self.config_stack.get('_twilio_auth_token')
432+
433+ def get_telephony_service_number(self):
434+ """Return the number to call and message from."""
435+ return self.config_stack.get('telephony_service_number')
436+
437+ def get_device_phone_number(self):
438+ """Return the number to send messages and calls to."""
439+ return self.config_stack.get('device_phone_number')
440
441=== added file 'ubuntu_system_tests/tests/test_messaging.py'
442--- ubuntu_system_tests/tests/test_messaging.py 1970-01-01 00:00:00 +0000
443+++ ubuntu_system_tests/tests/test_messaging.py 2015-06-04 15:20:03 +0000
444@@ -0,0 +1,129 @@
445+# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
446+
447+#
448+# Ubuntu System Tests
449+# Copyright (C) 2015 Canonical
450+#
451+# This program is free software: you can redistribute it and/or modify
452+# it under the terms of the GNU General Public License version 3,
453+# as published by the Free Software Foundation.
454+#
455+# This program is distributed in the hope that it will be useful,
456+# but WITHOUT ANY WARRANTY; without even the implied warranty of
457+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
458+# GNU General Public License for more details.
459+#
460+# You should have received a copy of the GNU General Public License
461+# along with this program. If not, see <http://www.gnu.org/licenses/>.
462+#
463+
464+import uuid
465+
466+from autopilot.matchers import Eventually
467+from messaging_app import emulators as messaging_emulators
468+from testtools import skipUnless
469+from testtools.matchers import Equals
470+from ubuntuuitoolkit import emulators as toolkit_emulators
471+
472+from ubuntu_system_tests.helpers.addressbook import dbus_service
473+from ubuntu_system_tests.helpers import autopilot as autopilot_helpers
474+from ubuntu_system_tests.helpers import ofono
475+from ubuntu_system_tests.helpers.telephony import Telephony
476+from ubuntu_system_tests.helpers.unity8 import notifications # NOQA
477+from ubuntu_system_tests.tests import base
478+
479+CONTACT_NAME = 'Fulano de Tal'
480+
481+
482+class MessagingTestCase(base.BaseTelephonyTestCase):
483+
484+ @skipUnless(ofono.is_sim_inserted(ignore_phonesim=True), 'No SIM inserted')
485+ def setUp(self):
486+ super().setUp()
487+ self.unity_proxy = self.launch_unity()
488+ self.unity_proxy.unlock()
489+
490+ def _get_messaging_app_proxy(self):
491+ """Return messaging app proxy object from existing process."""
492+ return autopilot_helpers.get_proxy_object_for_existing_process(
493+ 'messaging-app',
494+ toolkit_emulators.UbuntuUIToolkitEmulatorBase)
495+
496+ def _create_temporary_contact(self):
497+ """
498+ Create a contact in the address book using the dbus service
499+ and remove it in the cleanup step.
500+ """
501+ vcard = """
502+BEGIN:VCARD
503+VERSION:3.0
504+FN:{name}
505+TEL;TYPE=CELL:{number}
506+END:VCARD""".format(name=CONTACT_NAME,
507+ number=self.get_telephony_service_number())
508+ self.addressbook_dbus = dbus_service.ContactsDbusService()
509+ contact_vcard = self.addressbook_dbus.create_contact(vcard)
510+ contact_uid = self.addressbook_dbus.get_vcard_uid(contact_vcard)
511+ self.addCleanup(self.addressbook_dbus.delete_contact, [contact_uid])
512+
513+ def _get_notifications_list(self):
514+ return self.unity_proxy.select_single(
515+ 'Notifications',
516+ objectName='notificationList'
517+ )
518+
519+ def test_receive_sms_from_contact(self):
520+ """
521+ Prerequisite: A contact in the address book with the number you
522+ are sending from
523+ 1. From another device send an SMS to the phone number of a SIM
524+ card that is in the SUT
525+ - A notification appears containing the senders
526+ name and the message content.
527+ 2. Tap on the message notification before it disappears
528+ - The messaging application is opened showing all
529+ messages received by that sender. The message
530+ just sent should appear at the bottom.
531+ """
532+ self._create_temporary_contact()
533+ # Get the notifications list first as we don't want to
534+ # waste precious time waiting for this call to return
535+ notifications_list = self._get_notifications_list()
536+ credentials = {'AccountSid': self.get_telephony_service_account_id(),
537+ 'AuthToken': self.get_telephony_service_auth_token()}
538+ tel = Telephony(credentials)
539+ # We use a UUID as the message body so that we know the message
540+ # that is received is the same one we sent.
541+ message_body = str(uuid.uuid1())
542+ sent = tel.send_sms(self.get_device_phone_number(),
543+ self.get_telephony_service_number(),
544+ message_body)
545+ self.assertTrue(sent, 'The SMS was not sent succesfully by the '
546+ 'telephony service.')
547+ # Tap on indicator when it appears and check the contents are
548+ # correct - message body is displayed and contact name is shown
549+ sms_notification = notifications_list.get_current_notification()
550+ self.assertThat(sms_notification.summary,
551+ Eventually(Equals('Message from {contact}'.format(
552+ contact='Fulano de Tal'))))
553+ self.assertThat(sms_notification.body,
554+ Eventually(Equals(message_body)))
555+ # Open the messaging app by tapping on the notification.
556+ # Due to launchpad.net/bugs/1457629 the following tap_on() method can
557+ # fail due to CPO inheritance problems in Autopilot.
558+ # A workaround is to select and press the object directly in the test.
559+ # This should be removed as soon as the Autopilot CPO bug is fixed.
560+ # sms_notification.tap_on()
561+ sms_notification.pointing_device.click_object(
562+ sms_notification.select_single(objectName="interactiveArea"))
563+
564+ messaging_app = self._get_messaging_app_proxy()
565+ self.addCleanup(self.ensure_application_closed, 'messaging-app')
566+ main_view = messaging_app.select_single(messaging_emulators.MainView)
567+ # Confirm that the message is displayed and the header title
568+ # is the name of the contact
569+ main_view.get_message(message_body)
570+ self.assertThat(main_view.get_header().title,
571+ Eventually(Equals(CONTACT_NAME)))
572+ # Delete the message
573+ main_view.delete_message(message_body)

Subscribers

People subscribed via source and target branches

to all changes: