Merge lp:~boiko/dialer-app/rtm-fix_call_hangup_and_test_multi_call into lp:dialer-app/rtm-14.09
- rtm-fix_call_hangup_and_test_multi_call
- Merge into rtm-14.09
Proposed by
Gustavo Pichorim Boiko
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Gustavo Pichorim Boiko | ||||
Approved revision: | 267 | ||||
Merged at revision: | 267 | ||||
Proposed branch: | lp:~boiko/dialer-app/rtm-fix_call_hangup_and_test_multi_call | ||||
Merge into: | lp:dialer-app/rtm-14.09 | ||||
Diff against target: |
560 lines (+305/-78) 8 files modified
src/qml/LiveCallPage/LiveCall.qml (+3/-2) src/qml/LiveCallPage/MultiCallDisplay.qml (+3/-0) tests/autopilot/dialer_app/__init__.py (+26/-1) tests/autopilot/dialer_app/fixture_setup.py (+83/-0) tests/autopilot/dialer_app/helpers.py (+39/-15) tests/autopilot/dialer_app/tests/test_calls.py (+7/-33) tests/autopilot/dialer_app/tests/test_logs.py (+7/-27) tests/autopilot/dialer_app/tests/test_multi_calls.py (+137/-0) |
||||
To merge this branch: | bzr merge lp:~boiko/dialer-app/rtm-fix_call_hangup_and_test_multi_call | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Gustavo Pichorim Boiko (community) | Approve | ||
Review via email: mp+256537@code.launchpad.net |
Commit message
Make sure the correct call is finished when pressing the hangup button on a multi-call scenario.
Also add autopilot tests to avoid this happening in the future.
Description of the change
Make sure the correct call is finished when pressing the hangup button on a multi-call scenario.
Also add autopilot tests to avoid this happening in the future.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/qml/LiveCallPage/LiveCall.qml' | |||
2 | --- src/qml/LiveCallPage/LiveCall.qml 2015-02-16 20:51:04 +0000 | |||
3 | +++ src/qml/LiveCallPage/LiveCall.qml 2015-04-16 16:26:21 +0000 | |||
4 | @@ -105,7 +105,7 @@ | |||
5 | 105 | } else { | 105 | } else { |
6 | 106 | closeTimer.running = false; | 106 | closeTimer.running = false; |
7 | 107 | statusLabel.text = ""; | 107 | statusLabel.text = ""; |
9 | 108 | liveCall.call = callManager.foregroundCall; | 108 | liveCall.call = Qt.binding(callManager.foregroundCall); |
10 | 109 | } | 109 | } |
11 | 110 | } | 110 | } |
12 | 111 | 111 | ||
13 | @@ -464,6 +464,7 @@ | |||
14 | 464 | 464 | ||
15 | 465 | MultiCallDisplay { | 465 | MultiCallDisplay { |
16 | 466 | id: multiCallArea | 466 | id: multiCallArea |
17 | 467 | objectName: "multiCallDisplay" | ||
18 | 467 | calls: callManager.calls | 468 | calls: callManager.calls |
19 | 468 | opacity: 0 | 469 | opacity: 0 |
20 | 469 | anchors { | 470 | anchors { |
21 | @@ -630,7 +631,7 @@ | |||
22 | 630 | } | 631 | } |
23 | 631 | 632 | ||
24 | 632 | LiveCallKeypadButton { | 633 | LiveCallKeypadButton { |
26 | 633 | objectName: "pauseStartButton" | 634 | objectName: "callHoldButton" |
27 | 634 | iconSource: { | 635 | iconSource: { |
28 | 635 | if (callManager.backgroundCall) { | 636 | if (callManager.backgroundCall) { |
29 | 636 | return "swap" | 637 | return "swap" |
30 | 637 | 638 | ||
31 | === modified file 'src/qml/LiveCallPage/MultiCallDisplay.qml' | |||
32 | --- src/qml/LiveCallPage/MultiCallDisplay.qml 2015-02-10 18:10:34 +0000 | |||
33 | +++ src/qml/LiveCallPage/MultiCallDisplay.qml 2015-04-16 16:26:21 +0000 | |||
34 | @@ -40,8 +40,11 @@ | |||
35 | 40 | 40 | ||
36 | 41 | Item { | 41 | Item { |
37 | 42 | id: callDelegate | 42 | id: callDelegate |
38 | 43 | objectName: "callDelegate" | ||
39 | 43 | property QtObject callEntry: modelData | 44 | property QtObject callEntry: modelData |
40 | 44 | property bool isLast: index == (multiCallRepeater.count - 1) | 45 | property bool isLast: index == (multiCallRepeater.count - 1) |
41 | 46 | property bool active: !callEntry.held | ||
42 | 47 | property string phoneNumber: callEntry.phoneNumber | ||
43 | 45 | 48 | ||
44 | 46 | height: units.gu(10) + conferenceArea.height | 49 | height: units.gu(10) + conferenceArea.height |
45 | 47 | anchors { | 50 | anchors { |
46 | 48 | 51 | ||
47 | === modified file 'tests/autopilot/dialer_app/__init__.py' | |||
48 | --- tests/autopilot/dialer_app/__init__.py 2015-02-11 18:29:21 +0000 | |||
49 | +++ tests/autopilot/dialer_app/__init__.py 2015-04-16 16:26:21 +0000 | |||
50 | @@ -35,6 +35,7 @@ | |||
51 | 35 | 35 | ||
52 | 36 | def _click_button(self, button): | 36 | def _click_button(self, button): |
53 | 37 | """Generic way to click a button""" | 37 | """Generic way to click a button""" |
54 | 38 | self.visible.wait_for(True) | ||
55 | 38 | button.visible.wait_for(True) | 39 | button.visible.wait_for(True) |
56 | 39 | self.pointing_device.click_object(button) | 40 | self.pointing_device.click_object(button) |
57 | 40 | return button | 41 | return button |
58 | @@ -50,11 +51,35 @@ | |||
59 | 50 | """Return the hangup button""" | 51 | """Return the hangup button""" |
60 | 51 | return self.wait_select_single(objectName='hangupButton') | 52 | return self.wait_select_single(objectName='hangupButton') |
61 | 52 | 53 | ||
62 | 54 | def _get_call_hold_button(self): | ||
63 | 55 | """Return the call holding button""" | ||
64 | 56 | return self.wait_select_single(objectName='callHoldButton') | ||
65 | 57 | |||
66 | 58 | def _get_swap_calls_button(self): | ||
67 | 59 | """Return the swap calls button""" | ||
68 | 60 | return self._get_call_hold_button() | ||
69 | 61 | |||
70 | 62 | def get_multi_call_display(self): | ||
71 | 63 | """Return the multi call display panel""" | ||
72 | 64 | return self.wait_select_single(objectName='multiCallDisplay') | ||
73 | 65 | |||
74 | 66 | def get_multi_call_item_for_number(self, number): | ||
75 | 67 | """Return the multi call display item for the given number""" | ||
76 | 68 | return self.wait_select_single(objectName='callDelegate', | ||
77 | 69 | phoneNumber=number) | ||
78 | 70 | |||
79 | 53 | def click_hangup_button(self): | 71 | def click_hangup_button(self): |
80 | 54 | """Click and return the hangup page""" | 72 | """Click and return the hangup page""" |
81 | 55 | self.visible.wait_for(True) | ||
82 | 56 | return self._click_button(self._get_hangup_button()) | 73 | return self._click_button(self._get_hangup_button()) |
83 | 57 | 74 | ||
84 | 75 | def click_call_hold_button(self): | ||
85 | 76 | """Click the call holding button""" | ||
86 | 77 | return self._click_button(self._get_call_hold_button()) | ||
87 | 78 | |||
88 | 79 | def click_swap_calls_button(self): | ||
89 | 80 | """Click the swap calls button""" | ||
90 | 81 | return self._click_button(self._get_swap_calls_button()) | ||
91 | 82 | |||
92 | 58 | 83 | ||
93 | 59 | class PageWithBottomEdge(MainView): | 84 | class PageWithBottomEdge(MainView): |
94 | 60 | 85 | ||
95 | 61 | 86 | ||
96 | === modified file 'tests/autopilot/dialer_app/fixture_setup.py' | |||
97 | --- tests/autopilot/dialer_app/fixture_setup.py 2014-08-01 15:25:39 +0000 | |||
98 | +++ tests/autopilot/dialer_app/fixture_setup.py 2015-04-16 16:26:21 +0000 | |||
99 | @@ -19,6 +19,8 @@ | |||
100 | 19 | 19 | ||
101 | 20 | import fixtures | 20 | import fixtures |
102 | 21 | import subprocess | 21 | import subprocess |
103 | 22 | import os | ||
104 | 23 | import shutil | ||
105 | 22 | 24 | ||
106 | 23 | 25 | ||
107 | 24 | class TestabilityEnvironment(fixtures.Fixture): | 26 | class TestabilityEnvironment(fixtures.Fixture): |
108 | @@ -48,3 +50,84 @@ | |||
109 | 48 | 'QT_LOAD_TESTABILITY' | 50 | 'QT_LOAD_TESTABILITY' |
110 | 49 | ] | 51 | ] |
111 | 50 | ) | 52 | ) |
112 | 53 | |||
113 | 54 | |||
114 | 55 | class FillCustomHistory(fixtures.Fixture): | ||
115 | 56 | |||
116 | 57 | history_db = "history.sqlite" | ||
117 | 58 | data_sys = "/usr/lib/python3/dist-packages/dialer_app/data/" | ||
118 | 59 | data_local = "dialer_app/data/" | ||
119 | 60 | database_path = '/tmp/' + history_db | ||
120 | 61 | |||
121 | 62 | prefilled_history_local = os.path.join(data_local, history_db) | ||
122 | 63 | prefilled_history_system = os.path.join(data_sys, history_db) | ||
123 | 64 | |||
124 | 65 | def setUp(self): | ||
125 | 66 | super(FillCustomHistory, self).setUp() | ||
126 | 67 | self.addCleanup(self._clear_test_data) | ||
127 | 68 | self.addCleanup(self._kill_service_to_respawn) | ||
128 | 69 | self._clear_test_data() | ||
129 | 70 | self._prepare_history_data() | ||
130 | 71 | self._kill_service_to_respawn() | ||
131 | 72 | self._start_service_with_custom_data() | ||
132 | 73 | |||
133 | 74 | def _prepare_history_data(self): | ||
134 | 75 | if os.path.exists(self.prefilled_history_local): | ||
135 | 76 | shutil.copy(self.prefilled_history_local, self.database_path) | ||
136 | 77 | else: | ||
137 | 78 | shutil.copy(self.prefilled_history_system, self.database_path) | ||
138 | 79 | |||
139 | 80 | def _clear_test_data(self): | ||
140 | 81 | if os.path.exists(self.database_path): | ||
141 | 82 | os.remove(self.database_path) | ||
142 | 83 | |||
143 | 84 | def _kill_service_to_respawn(self): | ||
144 | 85 | subprocess.call(['pkill', 'history-daemon']) | ||
145 | 86 | |||
146 | 87 | def _start_service_with_custom_data(self): | ||
147 | 88 | os.environ['HISTORY_SQLITE_DBPATH'] = self.database_path | ||
148 | 89 | with open(os.devnull, 'w') as devnull: | ||
149 | 90 | subprocess.Popen(['history-daemon'], stderr=devnull) | ||
150 | 91 | |||
151 | 92 | |||
152 | 93 | class UseEmptyHistory(FillCustomHistory): | ||
153 | 94 | database_path = ':memory:' | ||
154 | 95 | |||
155 | 96 | def setUp(self): | ||
156 | 97 | super(UseEmptyHistory, self).setUp() | ||
157 | 98 | |||
158 | 99 | def _prepare_history_data(self): | ||
159 | 100 | # just avoid doing anything | ||
160 | 101 | self.database_path = ':memory:' | ||
161 | 102 | |||
162 | 103 | def _clear_test_data(self): | ||
163 | 104 | # don't do anything | ||
164 | 105 | self.database_path = '' | ||
165 | 106 | |||
166 | 107 | |||
167 | 108 | class UsePhonesimModem(fixtures.Fixture): | ||
168 | 109 | |||
169 | 110 | def setUp(self): | ||
170 | 111 | super().setUp() | ||
171 | 112 | |||
172 | 113 | # configure the cleanups | ||
173 | 114 | self.addCleanup(self._hangupLeftoverCalls) | ||
174 | 115 | self.addCleanup(self._restoreModems) | ||
175 | 116 | |||
176 | 117 | self._switchToPhonesim() | ||
177 | 118 | |||
178 | 119 | def _switchToPhonesim(self): | ||
179 | 120 | # make sure the modem is running on phonesim | ||
180 | 121 | subprocess.call(['mc-tool', 'update', 'ofono/ofono/account0', | ||
181 | 122 | 'string:modem-objpath=/phonesim']) | ||
182 | 123 | subprocess.call(['mc-tool', 'reconnect', 'ofono/ofono/account0']) | ||
183 | 124 | |||
184 | 125 | def _hangupLeftoverCalls(self): | ||
185 | 126 | # ensure that there are no leftover calls in case of failed tests | ||
186 | 127 | subprocess.call(["/usr/share/ofono/scripts/hangup-all", "/phonesim"]) | ||
187 | 128 | |||
188 | 129 | def _restoreModems(self): | ||
189 | 130 | # set the modem objpath in telepathy-ofono to the real modem | ||
190 | 131 | subprocess.call(['mc-tool', 'update', 'ofono/ofono/account0', | ||
191 | 132 | 'string:modem-objpath=/ril_0']) | ||
192 | 133 | subprocess.call(['mc-tool', 'reconnect', 'ofono/ofono/account0']) | ||
193 | 51 | 134 | ||
194 | === modified file 'tests/autopilot/dialer_app/helpers.py' | |||
195 | --- tests/autopilot/dialer_app/helpers.py 2014-06-20 13:26:49 +0000 | |||
196 | +++ tests/autopilot/dialer_app/helpers.py 2015-04-16 16:26:21 +0000 | |||
197 | @@ -1,8 +1,8 @@ | |||
198 | 1 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- | 1 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- |
199 | 2 | # | 2 | # |
203 | 3 | # Copyright 2014 Canonical Ltd. | 3 | # Copyright 2014-2015 Canonical Ltd. |
204 | 4 | # Author: Omer Akram <omer.akram@canonical.com> | 4 | # Authors: Omer Akram <omer.akram@canonical.com> |
205 | 5 | # | 5 | # Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> |
206 | 6 | # This program is free software; you can redistribute it and/or modify | 6 | # This program is free software; you can redistribute it and/or modify |
207 | 7 | # it under the terms of the GNU General Public License version 3, as published | 7 | # it under the terms of the GNU General Public License version 3, as published |
208 | 8 | # by the Free Software Foundation. | 8 | # by the Free Software Foundation. |
209 | @@ -21,6 +21,9 @@ | |||
210 | 21 | import sys | 21 | import sys |
211 | 22 | import time | 22 | import time |
212 | 23 | import dbus | 23 | import dbus |
213 | 24 | import tempfile | ||
214 | 25 | import os | ||
215 | 26 | import shutil | ||
216 | 24 | 27 | ||
217 | 25 | 28 | ||
218 | 26 | def wait_for_incoming_call(): | 29 | def wait_for_incoming_call(): |
219 | @@ -32,7 +35,7 @@ | |||
220 | 32 | ['/usr/share/ofono/scripts/list-calls'], | 35 | ['/usr/share/ofono/scripts/list-calls'], |
221 | 33 | stderr=subprocess.PIPE, | 36 | stderr=subprocess.PIPE, |
222 | 34 | universal_newlines=True) | 37 | universal_newlines=True) |
224 | 35 | if 'State = incoming' in out: | 38 | if 'State = incoming' in out or 'State = waiting' in out: |
225 | 36 | break | 39 | break |
226 | 37 | timeout -= 1 | 40 | timeout -= 1 |
227 | 38 | time.sleep(0.5) | 41 | time.sleep(0.5) |
228 | @@ -44,17 +47,38 @@ | |||
229 | 44 | subprocess.call(['pkill', '-f', 'notify-osd']) | 47 | subprocess.call(['pkill', '-f', 'notify-osd']) |
230 | 45 | 48 | ||
231 | 46 | 49 | ||
243 | 47 | def invoke_incoming_call(): | 50 | def invoke_incoming_call(caller): |
244 | 48 | """Invoke an incoming call for test purpose.""" | 51 | """Receive an incoming call from the given caller |
245 | 49 | # magic number 199 will cause a callback from 1234567; dialing 199 | 52 | |
246 | 50 | # itself will fail, so quiesce the error | 53 | :parameter caller: the phone number calling |
247 | 51 | bus = dbus.SystemBus() | 54 | """ |
248 | 52 | vcm = dbus.Interface(bus.get_object('org.ofono', '/phonesim'), | 55 | |
249 | 53 | 'org.ofono.VoiceCallManager') | 56 | # prepare and send a Qt GUI script to phonesim, over its private D-BUS |
250 | 54 | try: | 57 | # set up by ofono-phonesim-autostart |
251 | 55 | vcm.Dial('199', 'default') | 58 | script_dir = tempfile.mkdtemp(prefix="phonesim_script") |
252 | 56 | except dbus.DBusException: | 59 | os.chmod(script_dir, 0o755) |
253 | 57 | pass | 60 | with open(os.path.join(script_dir, "call.js"), "w") as f: |
254 | 61 | f.write("""tabCall.gbIncomingCall.leCaller.text = "%s"; | ||
255 | 62 | tabCall.gbIncomingCall.pbIncomingCall.click(); | ||
256 | 63 | """ % (caller)) | ||
257 | 64 | |||
258 | 65 | with open("/run/lock/ofono-phonesim-dbus.address") as f: | ||
259 | 66 | phonesim_bus = f.read().strip() | ||
260 | 67 | bus = dbus.bus.BusConnection(phonesim_bus) | ||
261 | 68 | script_proxy = bus.get_object("org.ofono.phonesim", "/") | ||
262 | 69 | script_proxy.SetPath(script_dir) | ||
263 | 70 | script_proxy.Run("call.js") | ||
264 | 71 | shutil.rmtree(script_dir) | ||
265 | 72 | |||
266 | 73 | |||
267 | 74 | def accept_incoming_call(): | ||
268 | 75 | """Accept an existing incoming call""" | ||
269 | 76 | subprocess.check_call( | ||
270 | 77 | [ | ||
271 | 78 | "dbus-send", "--session", "--print-reply", | ||
272 | 79 | "--dest=com.canonical.Approver", "/com/canonical/Approver", | ||
273 | 80 | "com.canonical.TelephonyServiceApprover.AcceptCall" | ||
274 | 81 | ], stdout=subprocess.PIPE) | ||
275 | 58 | 82 | ||
276 | 59 | 83 | ||
277 | 60 | def get_phonesim(): | 84 | def get_phonesim(): |
278 | 61 | 85 | ||
279 | === modified file 'tests/autopilot/dialer_app/tests/test_calls.py' | |||
280 | --- tests/autopilot/dialer_app/tests/test_calls.py 2015-02-16 20:51:04 +0000 | |||
281 | +++ tests/autopilot/dialer_app/tests/test_calls.py 2015-04-16 16:26:21 +0000 | |||
282 | @@ -10,7 +10,6 @@ | |||
283 | 10 | 10 | ||
284 | 11 | """Tests for the Dialer App using ofono-phonesim""" | 11 | """Tests for the Dialer App using ofono-phonesim""" |
285 | 12 | 12 | ||
286 | 13 | import subprocess | ||
287 | 14 | import os | 13 | import os |
288 | 15 | import time | 14 | import time |
289 | 16 | 15 | ||
290 | @@ -20,6 +19,7 @@ | |||
291 | 20 | 19 | ||
292 | 21 | from dialer_app.tests import DialerAppTestCase | 20 | from dialer_app.tests import DialerAppTestCase |
293 | 22 | from dialer_app import helpers | 21 | from dialer_app import helpers |
294 | 22 | from dialer_app import fixture_setup | ||
295 | 23 | 23 | ||
296 | 24 | 24 | ||
297 | 25 | @skipUnless(helpers.is_phonesim_running(), | 25 | @skipUnless(helpers.is_phonesim_running(), |
298 | @@ -30,36 +30,15 @@ | |||
299 | 30 | """Tests for simulated phone calls.""" | 30 | """Tests for simulated phone calls.""" |
300 | 31 | 31 | ||
301 | 32 | def setUp(self): | 32 | def setUp(self): |
314 | 33 | # provide clean history | 33 | empty_history = fixture_setup.UseEmptyHistory() |
315 | 34 | self.history = os.path.expanduser( | 34 | self.useFixture(empty_history) |
316 | 35 | "~/.local/share/history-service/history.sqlite") | 35 | phonesim_modem = fixture_setup.UsePhonesimModem() |
317 | 36 | if os.path.exists(self.history): | 36 | self.useFixture(phonesim_modem) |
306 | 37 | subprocess.call(["pkill", "history-daemon"]) | ||
307 | 38 | os.rename(self.history, self.history + ".orig") | ||
308 | 39 | |||
309 | 40 | # make sure the modem is running on phonesim | ||
310 | 41 | subprocess.call(['mc-tool', 'update', 'ofono/ofono/account0', | ||
311 | 42 | 'string:modem-objpath=/phonesim']) | ||
312 | 43 | subprocess.call(['mc-tool', 'reconnect', 'ofono/ofono/account0']) | ||
313 | 44 | |||
318 | 45 | super().setUp() | 37 | super().setUp() |
319 | 46 | 38 | ||
320 | 47 | def tearDown(self): | 39 | def tearDown(self): |
321 | 48 | super().tearDown() | 40 | super().tearDown() |
322 | 49 | 41 | ||
323 | 50 | # ensure that there are no leftover calls in case of failed tests | ||
324 | 51 | subprocess.call(["/usr/share/ofono/scripts/hangup-all", "/phonesim"]) | ||
325 | 52 | |||
326 | 53 | # restore history | ||
327 | 54 | if os.path.exists(self.history + ".orig"): | ||
328 | 55 | subprocess.call(["pkill", "history-daemon"]) | ||
329 | 56 | os.rename(self.history + ".orig", self.history) | ||
330 | 57 | |||
331 | 58 | # set the modem objpath in telepathy-ofono to the real modem | ||
332 | 59 | subprocess.call(['mc-tool', 'update', 'ofono/ofono/account0', | ||
333 | 60 | 'string:modem-objpath=/ril_0']) | ||
334 | 61 | subprocess.call(['mc-tool', 'reconnect', 'ofono/ofono/account0']) | ||
335 | 62 | |||
336 | 63 | @property | 42 | @property |
337 | 64 | def history_list(self): | 43 | def history_list(self): |
338 | 65 | # because of the object tree, more than just one item is returned, but | 44 | # because of the object tree, more than just one item is returned, but |
339 | @@ -143,19 +122,14 @@ | |||
340 | 143 | def test_incoming(self): | 122 | def test_incoming(self): |
341 | 144 | """Incoming call""" | 123 | """Incoming call""" |
342 | 145 | number = "1234567" | 124 | number = "1234567" |
344 | 146 | helpers.invoke_incoming_call() | 125 | helpers.invoke_incoming_call(number) |
345 | 147 | 126 | ||
346 | 148 | # wait for incoming call, accept; it would be nicer to fake-click the | 127 | # wait for incoming call, accept; it would be nicer to fake-click the |
347 | 149 | # popup notification, but as this isn't generated by dialer-app it | 128 | # popup notification, but as this isn't generated by dialer-app it |
348 | 150 | # isn't exposed to autopilot | 129 | # isn't exposed to autopilot |
349 | 151 | helpers.wait_for_incoming_call() | 130 | helpers.wait_for_incoming_call() |
350 | 152 | time.sleep(1) # let's hear the ringing sound for a second :-) | 131 | time.sleep(1) # let's hear the ringing sound for a second :-) |
357 | 153 | subprocess.check_call( | 132 | helpers.accept_incoming_call() |
352 | 154 | [ | ||
353 | 155 | "dbus-send", "--session", "--print-reply", | ||
354 | 156 | "--dest=com.canonical.Approver", "/com/canonical/Approver", | ||
355 | 157 | "com.canonical.TelephonyServiceApprover.AcceptCall" | ||
356 | 158 | ], stdout=subprocess.PIPE) | ||
358 | 159 | 133 | ||
359 | 160 | # call back is from that number | 134 | # call back is from that number |
360 | 161 | self.assertThat( | 135 | self.assertThat( |
361 | 162 | 136 | ||
362 | === modified file 'tests/autopilot/dialer_app/tests/test_logs.py' | |||
363 | --- tests/autopilot/dialer_app/tests/test_logs.py 2015-02-13 17:54:03 +0000 | |||
364 | +++ tests/autopilot/dialer_app/tests/test_logs.py 2015-04-16 16:26:21 +0000 | |||
365 | @@ -10,10 +10,6 @@ | |||
366 | 10 | 10 | ||
367 | 11 | """Tests for the Dialer App""" | 11 | """Tests for the Dialer App""" |
368 | 12 | 12 | ||
369 | 13 | import os | ||
370 | 14 | import shutil | ||
371 | 15 | import subprocess | ||
372 | 16 | |||
373 | 17 | from autopilot.platform import model | 13 | from autopilot.platform import model |
374 | 18 | from autopilot.matchers import Eventually | 14 | from autopilot.matchers import Eventually |
375 | 19 | from testtools import skipIf | 15 | from testtools import skipIf |
376 | @@ -33,35 +29,19 @@ | |||
377 | 33 | class TestCallLogs(DialerAppTestCase): | 29 | class TestCallLogs(DialerAppTestCase): |
378 | 34 | """Tests for the call log panel.""" | 30 | """Tests for the call log panel.""" |
379 | 35 | 31 | ||
380 | 36 | db_file = 'history.sqlite' | ||
381 | 37 | local_db_dir = 'dialer_app/data/' | ||
382 | 38 | system_db_dir = '/usr/lib/python3/dist-packages/dialer_app/data/' | ||
383 | 39 | temp_db_file = '/tmp/' + db_file | ||
384 | 40 | |||
385 | 41 | def setUp(self): | 32 | def setUp(self): |
402 | 42 | if os.path.exists('../../src/dialer-app'): | 33 | # set the fixtures before launching the app |
387 | 43 | database = self.local_db_dir + self.db_file | ||
388 | 44 | else: | ||
389 | 45 | database = self.system_db_dir + self.db_file | ||
390 | 46 | |||
391 | 47 | if os.path.exists(self.temp_db_file): | ||
392 | 48 | os.remove(self.temp_db_file) | ||
393 | 49 | |||
394 | 50 | shutil.copyfile(database, self.temp_db_file) | ||
395 | 51 | |||
396 | 52 | subprocess.call(['pkill', 'history-daemon']) | ||
397 | 53 | os.environ['HISTORY_SQLITE_DBPATH'] = self.temp_db_file | ||
398 | 54 | with open(os.devnull, 'w') as devnull: | ||
399 | 55 | subprocess.Popen(['history-daemon'], stderr=devnull) | ||
400 | 56 | |||
401 | 57 | super().setUp() | ||
403 | 58 | testability_environment = fixture_setup.TestabilityEnvironment() | 34 | testability_environment = fixture_setup.TestabilityEnvironment() |
404 | 59 | self.useFixture(testability_environment) | 35 | self.useFixture(testability_environment) |
407 | 60 | self.main_view.dialer_page.reveal_bottom_edge_page() | 36 | fill_history = fixture_setup.FillCustomHistory() |
408 | 61 | self.addCleanup(subprocess.call, ['pkill', '-f', 'history-daemon']) | 37 | self.useFixture(fill_history) |
409 | 62 | self.fake_url_dispatcher = url_dispatcher_fixtures.FakeURLDispatcher() | 38 | self.fake_url_dispatcher = url_dispatcher_fixtures.FakeURLDispatcher() |
410 | 63 | self.useFixture(self.fake_url_dispatcher) | 39 | self.useFixture(self.fake_url_dispatcher) |
411 | 64 | 40 | ||
412 | 41 | # now launch the app | ||
413 | 42 | super().setUp() | ||
414 | 43 | self.main_view.dialer_page.reveal_bottom_edge_page() | ||
415 | 44 | |||
416 | 65 | def _get_main_view(self, proxy_object): | 45 | def _get_main_view(self, proxy_object): |
417 | 66 | return proxy_object.wait_select_single('QQuickView') | 46 | return proxy_object.wait_select_single('QQuickView') |
418 | 67 | 47 | ||
419 | 68 | 48 | ||
420 | === added file 'tests/autopilot/dialer_app/tests/test_multi_calls.py' | |||
421 | --- tests/autopilot/dialer_app/tests/test_multi_calls.py 1970-01-01 00:00:00 +0000 | |||
422 | +++ tests/autopilot/dialer_app/tests/test_multi_calls.py 2015-04-16 16:26:21 +0000 | |||
423 | @@ -0,0 +1,137 @@ | |||
424 | 1 | # -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*- | ||
425 | 2 | # Copyright 2015 Canonical | ||
426 | 3 | # Author: Gustavo Pichorim Boiko <gustavo.boiko@canonical.com> | ||
427 | 4 | # | ||
428 | 5 | # This file is part of dialer-app. | ||
429 | 6 | # | ||
430 | 7 | # dialer-app is free software: you can redistribute it and/or modify it | ||
431 | 8 | # under the terms of the GNU General Public License version 3, as published | ||
432 | 9 | # by the Free Software Foundation. | ||
433 | 10 | |||
434 | 11 | """Multiple calls tests for the Dialer App using ofono-phonesim""" | ||
435 | 12 | |||
436 | 13 | import time | ||
437 | 14 | |||
438 | 15 | from autopilot.matchers import Eventually | ||
439 | 16 | from testtools.matchers import Equals | ||
440 | 17 | from testtools import skipUnless | ||
441 | 18 | |||
442 | 19 | from dialer_app.tests import DialerAppTestCase | ||
443 | 20 | from dialer_app import helpers | ||
444 | 21 | from dialer_app import fixture_setup | ||
445 | 22 | |||
446 | 23 | |||
447 | 24 | @skipUnless(helpers.is_phonesim_running(), | ||
448 | 25 | "this test needs to run under with-ofono-phonesim") | ||
449 | 26 | class TestMultiCalls(DialerAppTestCase): | ||
450 | 27 | """Tests for simulated phone calls.""" | ||
451 | 28 | |||
452 | 29 | def setUp(self): | ||
453 | 30 | empty_history = fixture_setup.UseEmptyHistory() | ||
454 | 31 | self.useFixture(empty_history) | ||
455 | 32 | phonesim_modem = fixture_setup.UsePhonesimModem() | ||
456 | 33 | self.useFixture(phonesim_modem) | ||
457 | 34 | super().setUp() | ||
458 | 35 | |||
459 | 36 | def tearDown(self): | ||
460 | 37 | super().tearDown() | ||
461 | 38 | |||
462 | 39 | @property | ||
463 | 40 | def history_list(self): | ||
464 | 41 | # because of the object tree, more than just one item is returned, but | ||
465 | 42 | # all references point to the same item, so take the first | ||
466 | 43 | return self.app.select_many(objectName="historyList")[0] | ||
467 | 44 | |||
468 | 45 | def get_history_for_number(self, number): | ||
469 | 46 | # because of the bottom edge tree structure, multiple copies of the | ||
470 | 47 | # same item are returned, so just use the first one | ||
471 | 48 | return self.history_list.select_many( | ||
472 | 49 | "HistoryDelegate", phoneNumber=number)[0] | ||
473 | 50 | |||
474 | 51 | def place_calls(self, numbers): | ||
475 | 52 | for number in numbers: | ||
476 | 53 | helpers.invoke_incoming_call(number) | ||
477 | 54 | helpers.wait_for_incoming_call() | ||
478 | 55 | time.sleep(1) | ||
479 | 56 | helpers.accept_incoming_call() | ||
480 | 57 | time.sleep(1) | ||
481 | 58 | |||
482 | 59 | def test_multi_call_panel(self): | ||
483 | 60 | """Make sure the multi call panel is visible when two calls are | ||
484 | 61 | available""" | ||
485 | 62 | firstNumber = '11111111' | ||
486 | 63 | secondNumber = '22222222' | ||
487 | 64 | |||
488 | 65 | # place the calls | ||
489 | 66 | self.place_calls([firstNumber, secondNumber]) | ||
490 | 67 | |||
491 | 68 | # now ensure that the multi-call panel is visible | ||
492 | 69 | multi_call = self.main_view.live_call_page.get_multi_call_display() | ||
493 | 70 | self.assertThat(multi_call.visible, Eventually(Equals(True))) | ||
494 | 71 | |||
495 | 72 | # hangup one call | ||
496 | 73 | self.main_view.live_call_page.click_hangup_button() | ||
497 | 74 | self.assertThat(multi_call.visible, Eventually(Equals(False))) | ||
498 | 75 | |||
499 | 76 | # and the other one | ||
500 | 77 | self.main_view.live_call_page.click_hangup_button() | ||
501 | 78 | |||
502 | 79 | def test_swap_calls(self): | ||
503 | 80 | """Check that pressing the swap calls button change the call status""" | ||
504 | 81 | firstNumber = '11111111' | ||
505 | 82 | secondNumber = '22222222' | ||
506 | 83 | |||
507 | 84 | # place the calls | ||
508 | 85 | self.place_calls([firstNumber, secondNumber]) | ||
509 | 86 | |||
510 | 87 | live_call = self.main_view.live_call_page | ||
511 | 88 | firstCallItem = live_call.get_multi_call_item_for_number(firstNumber) | ||
512 | 89 | secondCallItem = live_call.get_multi_call_item_for_number(secondNumber) | ||
513 | 90 | |||
514 | 91 | # check the current status | ||
515 | 92 | self.assertThat(firstCallItem.active, Eventually(Equals(False))) | ||
516 | 93 | self.assertThat(secondCallItem.active, Eventually(Equals(True))) | ||
517 | 94 | |||
518 | 95 | # now swap the calls | ||
519 | 96 | live_call.click_swap_calls_button() | ||
520 | 97 | |||
521 | 98 | # and make sure the calls changed | ||
522 | 99 | self.assertThat(firstCallItem.active, Eventually(Equals(True))) | ||
523 | 100 | self.assertThat(secondCallItem.active, Eventually(Equals(False))) | ||
524 | 101 | |||
525 | 102 | # hangup the calls | ||
526 | 103 | self.main_view.live_call_page.click_hangup_button() | ||
527 | 104 | time.sleep(1) | ||
528 | 105 | self.main_view.live_call_page.click_hangup_button() | ||
529 | 106 | |||
530 | 107 | def test_swap_and_hangup(self): | ||
531 | 108 | """Check that after swapping calls and hanging up the correct call | ||
532 | 109 | stays active""" | ||
533 | 110 | firstNumber = '11111111' | ||
534 | 111 | secondNumber = '22222222' | ||
535 | 112 | |||
536 | 113 | # place the calls | ||
537 | 114 | self.place_calls([firstNumber, secondNumber]) | ||
538 | 115 | |||
539 | 116 | # at this point the calls should be like this: | ||
540 | 117 | # - 11111111: held | ||
541 | 118 | # - 22222222: active | ||
542 | 119 | # swap the calls then | ||
543 | 120 | self.main_view.live_call_page.click_swap_calls_button() | ||
544 | 121 | |||
545 | 122 | # - 11111111: active | ||
546 | 123 | # - 22222222: held | ||
547 | 124 | self.assertThat( | ||
548 | 125 | self.main_view.live_call_page.caller, | ||
549 | 126 | Eventually(Equals(firstNumber))) | ||
550 | 127 | |||
551 | 128 | # hangup the active call | ||
552 | 129 | self.main_view.live_call_page.click_hangup_button() | ||
553 | 130 | |||
554 | 131 | # and check that the remaining call is the one that was held | ||
555 | 132 | self.assertThat( | ||
556 | 133 | self.main_view.live_call_page.caller, | ||
557 | 134 | Eventually(Equals(secondNumber))) | ||
558 | 135 | |||
559 | 136 | # and hangup the remaining call too | ||
560 | 137 | self.main_view.live_call_page.click_hangup_button() |
Already reviewed for vivid, approving.