Merge lp:~dbarth/ubuntu-system-settings-online-accounts/fix-ap-test2 into lp:ubuntu-system-settings-online-accounts

Proposed by David Barth
Status: Superseded
Proposed branch: lp:~dbarth/ubuntu-system-settings-online-accounts/fix-ap-test2
Merge into: lp:ubuntu-system-settings-online-accounts
Diff against target: 570 lines (+103/-399)
4 files modified
debian/control (+1/-1)
debian/tests/autopilot (+6/-0)
debian/tests/control (+2/-0)
tests/autopilot/online_accounts_ui/tests/test_online_accounts_ui.py (+94/-398)
To merge this branch: bzr merge lp:~dbarth/ubuntu-system-settings-online-accounts/fix-ap-test2
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Alberto Mardegan (community) Approve
Review via email: mp+211547@code.launchpad.net

This proposal has been superseded by a proposal from 2014-03-19.

To post a comment you must log in.
Revision history for this message
Alberto Mardegan (mardy) wrote :

LGTM, thanks!

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

FAILED: Autolanding.
No commit message was specified in the merge proposal. Hit 'Add commit message' on the merge proposal web page or follow the link below. You can approve the merge proposal yourself to rerun.
https://code.launchpad.net/~dbarth/ubuntu-system-settings-online-accounts/fix-ap-test2/+merge/211547/+edit-commit-message

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

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/control'
2--- debian/control 2014-03-06 13:36:34 +0000
3+++ debian/control 2014-03-18 15:02:56 +0000
4@@ -22,6 +22,7 @@
5 # code again.
6 Vcs-Bzr: https://code.launchpad.net/~online-accounts/ubuntu-system-settings-online-accounts/trunk
7 X-Python-Version: 2.7
8+XS-Testsuite: autopkgtest
9
10 Package: ubuntu-system-settings-online-accounts
11 Architecture: any
12@@ -89,7 +90,6 @@
13 uoa-integration-tests,
14 libqt5test5,
15 python-autopilot,
16- python-oauth,
17 Description: Online Accounts setup for Ubuntu Touch - tests
18 Online Accounts setup utility for the Ubuntu Touch System Settings.
19 .
20
21=== added directory 'debian/tests'
22=== added file 'debian/tests/autopilot'
23--- debian/tests/autopilot 1970-01-01 00:00:00 +0000
24+++ debian/tests/autopilot 2014-03-18 15:02:56 +0000
25@@ -0,0 +1,6 @@
26+#!/bin/sh
27+
28+set -e
29+
30+autopilot run online_accounts_ui 2> /dev/null
31+
32
33=== added file 'debian/tests/control'
34--- debian/tests/control 1970-01-01 00:00:00 +0000
35+++ debian/tests/control 2014-03-18 15:02:56 +0000
36@@ -0,0 +1,2 @@
37+Tests: autopilot
38+Depends: @
39
40=== modified file 'tests/autopilot/online_accounts_ui/tests/test_online_accounts_ui.py'
41--- tests/autopilot/online_accounts_ui/tests/test_online_accounts_ui.py 2014-03-06 13:36:34 +0000
42+++ tests/autopilot/online_accounts_ui/tests/test_online_accounts_ui.py 2014-03-18 15:02:56 +0000
43@@ -12,230 +12,22 @@
44 from autopilot.input import Mouse, Touch, Pointer
45 from autopilot.platform import model
46 from autopilot.matchers import Eventually
47+from subprocess import Popen
48 from testtools.matchers import Contains, Equals, NotEquals, GreaterThan
49 from time import sleep
50-import BaseHTTPServer, SimpleHTTPServer, SocketServer, ssl, cgi
51-import threading
52-import oauth.oauth as oauth
53+import os
54
55 from online_accounts_ui.emulators.items import EmulatorBase
56
57-REQUEST_TOKEN_URL = 'http://localhost:5121/oauth1/request_token'
58-ACCESS_TOKEN_URL = 'http://localhost:5121/oauth1/access_token'
59-AUTHORIZATION_URL = 'http://localhost:5121/oauth1/authorize'
60-CALLBACK_URL = 'http://localhost:5121/success.html'
61-REALM = 'http://photos.example.net/'
62-VERIFIER = 'verifier'
63-
64-class MockOAuthDataStore(oauth.OAuthDataStore):
65- def __init__(self):
66- self.consumer = oauth.OAuthConsumer('C0nsum3rKey', 'C0nsum3rS3cr3t')
67- self.request_token = oauth.OAuthToken('requestkey', 'requestsecret')
68- self.access_token = oauth.OAuthToken('accesskey', 'accesssecret')
69- self.nonce = 'nonce'
70- self.verifier = VERIFIER
71-
72- def lookup_consumer(self, key):
73- if key == self.consumer.key:
74- return self.consumer
75- return None
76-
77- def lookup_token(self, token_type, token):
78- token_attrib = getattr(self, '%s_token' % token_type)
79- if token == token_attrib.key:
80- ## HACK
81- token_attrib.set_callback(CALLBACK_URL)
82- return token_attrib
83- return None
84-
85- def lookup_nonce(self, oauth_consumer, oauth_token, nonce):
86- if oauth_token and oauth_consumer.key == self.consumer.key and (oauth_token.key == self.request_token.key or oauth_token.key == self.access_token.key) and nonce == self.nonce:
87- return self.nonce
88- return None
89-
90- def fetch_request_token(self, oauth_consumer, oauth_callback):
91- if oauth_consumer.key == self.consumer.key:
92- if oauth_callback:
93- # want to check here if callback is sensible
94- # for mock store, we assume it is
95- self.request_token.set_callback(oauth_callback)
96- return self.request_token
97- return None
98-
99- def fetch_access_token(self, oauth_consumer, oauth_token, oauth_verifier):
100- if oauth_consumer.key == self.consumer.key and oauth_token.key == self.request_token.key and oauth_verifier == self.verifier:
101- # want to check here if token is authorized
102- # for mock store, we assume it is
103- return self.access_token
104- return None
105-
106- def authorize_request_token(self, oauth_token, user):
107- if oauth_token.key == self.request_token.key:
108- # authorize the request token in the store
109- # for mock store, do nothing
110- self.access_token.username = user
111- return self.request_token
112- return None
113-
114-class OAuth1Handler(BaseHTTPServer.BaseHTTPRequestHandler):
115- def __init__(self, *args, **kwargs):
116- BaseHTTPServer.BaseHTTPRequestHandler.__init__(self, *args, **kwargs)
117-
118- def do_HEAD(self):
119- self.send_response(200)
120- self.send_header("Content-type", "text/html")
121- s.end_headers()
122-
123- def do_GET(self):
124- print "Got GET to %s. headers: %s" % (self.path, self.headers)
125- if self.path.startswith('/oauth1/authorize'):
126- oauth_request = oauth.OAuthRequest.from_request(self.command,
127- 'http://localhost:%s%s' % (self.server.server_port, self.path),
128- headers=self.headers)
129- # get the request token
130- self.server.token = self.server.oauth_server.fetch_request_token(oauth_request)
131-
132- self.send_response(200)
133- self.send_header("Content-type", "text/html")
134- self.send_header('Content-Encoding', 'utf-8')
135- self.end_headers()
136- self.wfile.write("""
137- <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
138- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
139- <html xmlns="http://www.w3.org/1999/xhtml">
140- <head><title>Login here</title></head>
141- <body>
142- <h3>Login form</h3>
143- <form method="POST" action="http://localhost:%(port)s/login.html">
144- Username: <input type="text" name="username" size="15" /><br />
145- <p><input type="submit" value="Login" /></p>
146- </form>
147- </body>
148- </html>
149- """ % { 'port': self.server.server_port })
150- self.server.show_login_event.set()
151-
152- def do_POST(self):
153- if self.path == '/login.html':
154- form = cgi.FieldStorage(
155- fp=self.rfile,
156- headers=self.headers,
157- environ={'REQUEST_METHOD':'POST',
158- 'CONTENT_TYPE':self.headers['Content-Type'],
159- })
160- # authorize the token
161- token = self.server.oauth_server.authorize_token(self.server.token, form['username'].value)
162- token.set_verifier(VERIFIER)
163- self.send_response(301)
164- self.send_header("Location", token.get_callback_url())
165- self.end_headers()
166- self.server.login_done_event.set()
167- return
168-
169- # construct the oauth request from the request parameters
170- length = int(self.headers.getheader('content-length'))
171- postdata = self.rfile.read(length)
172- oauth_request = oauth.OAuthRequest.from_request(self.command,
173- 'http://localhost:%s%s' % (self.server.server_port, self.path),
174- headers=self.headers, query_string=postdata)
175-
176- if self.path == '/oauth1/request_token':
177- # create a request token
178- token = self.server.oauth_server.fetch_request_token(oauth_request)
179- # send okay response
180- self.send_response(200, 'OK')
181- self.send_header('Content-Type', 'application/x-www-form-urlencoded')
182- self.end_headers()
183- # return the token
184- self.wfile.write(token.to_string())
185- elif self.path == '/oauth1/access_token':
186- # create an access token
187- token = self.server.oauth_server.fetch_access_token(oauth_request)
188- # send okay response
189- self.send_response(200, 'OK')
190- self.send_header('Content-Type', 'application/x-www-form-urlencoded')
191- self.end_headers()
192- # return the token
193- self.wfile.write('%s&ScreenName=%s' % (token.to_string(), token.username))
194-
195-
196-class OAuth1LocalServer:
197- def __init__(self):
198- self.PORT = 5121
199- self.handler = OAuth1Handler
200- self.httpd = BaseHTTPServer.HTTPServer(('localhost', self.PORT), self.handler)
201- self.httpd.oauth_server = oauth.OAuthServer(MockOAuthDataStore())
202- self.httpd.oauth_server.add_signature_method(oauth.OAuthSignatureMethod_PLAINTEXT())
203- self.httpd.oauth_server.add_signature_method(oauth.OAuthSignatureMethod_HMAC_SHA1())
204- self.httpd.show_login_event = threading.Event()
205- self.httpd.login_done_event = threading.Event()
206- self.httpd_thread = threading.Thread(target=self.httpd.serve_forever)
207-
208- def run(self):
209- self.httpd_thread.setDaemon(True)
210- self.httpd_thread.start()
211-
212-
213-class Handler(BaseHTTPServer.BaseHTTPRequestHandler):
214- def do_HEAD(self):
215- self.send_response(200)
216- self.send_header("Content-type", "text/html")
217- s.end_headers()
218-
219- def do_GET(self):
220- self.send_response(200)
221- self.send_header("Content-type", "text/html")
222- self.send_header('Content-Encoding', 'utf-8')
223- self.end_headers()
224- self.wfile.write("""
225-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
226- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
227-<html xmlns="http://www.w3.org/1999/xhtml">
228-<head><title>Login here</title></head>
229-<body>
230-<h3>Login form</h3>
231-<form method="POST" action="https://localhost:%(port)s/login.html">
232- Username: <input type="text" name="username" size="15" /><br />
233- Password: <input type="password" name="password" size="15" /><br />
234- <p><input type="submit" value="Login" /></p>
235-</form>
236-</body>
237-</html>
238-""" % { 'port': self.server.server_port })
239- self.server.show_login_event.set()
240-
241- def do_POST(self):
242- form = cgi.FieldStorage(
243- fp=self.rfile,
244- headers=self.headers,
245- environ={'REQUEST_METHOD':'POST',
246- 'CONTENT_TYPE':self.headers['Content-Type'],
247- })
248- self.send_response(301)
249- self.send_header("Location",
250- "https://localhost:%(port)s/success.html#access_token=%(username)s%(password)s&expires_in=3600" % {
251- 'port': self.server.server_port,
252- 'username': form['username'].value,
253- 'password': form['password'].value
254- })
255- self.end_headers()
256- self.server.login_done_event.set()
257-
258-
259-class LocalServer:
260- def __init__(self):
261- self.PORT = 5120
262- #self.handler = SimpleHTTPServer.SimpleHTTPRequestHandler
263- self.handler = Handler
264- self.httpd = BaseHTTPServer.HTTPServer(("localhost", self.PORT), self.handler)
265- self.httpd.show_login_event = threading.Event()
266- self.httpd.login_done_event = threading.Event()
267- self.httpd.socket = ssl.wrap_socket (self.httpd.socket, certfile='/etc/ssl/certs/uoa-test-server.pem', server_side=True)
268- self.httpd_thread = threading.Thread(target=self.httpd.serve_forever)
269-
270- def run(self):
271- self.httpd_thread.setDaemon(True)
272- self.httpd_thread.start()
273+
274+# You can find a couple of OAuth 1.0a and 2.0 tests in the repository history
275+# (bazaar revision 100).
276+# These tests were removed because the signon-ui window where the webview is
277+# hosted will not be focused properly, both in Mir
278+# (https://bugs.launchpad.net/bugs/1231968) and Compiz
279+# (https://bugs.launchpad.net/bugs/455241)
280+# This issue will be solved when we move the signon-ui implementation in the
281+# same process as online-accounts-ui
282
283
284 class OnlineAccountsUiTests(AutopilotTestCase):
285@@ -256,14 +48,27 @@
286 return
287
288 self.pointer = Pointer(self.input_device_class.create())
289- self.app = self.launch_test_application('system-settings', 'online-accounts',
290- '--desktop_file_hint=/usr/share/applications/ubuntu-system-settings.desktop',
291+ # Increase the timeout of online-accounts-ui, to make sure it won't
292+ # quit before the system settings panel asks it to open.
293+ self.patch_environment('OAU_DAEMON_TIMEOUT', '120')
294+ self.app = self.launch_test_application('online-accounts-ui',
295+ '--desktop_file_hint=/usr/share/applications/online-accounts-ui.desktop',
296 app_type='qt',
297 emulator_base=EmulatorBase,
298 capture_output=True)
299+ self.system_settings = Popen(['system-settings', 'online-accounts',
300+ '--desktop_file_hint=/usr/share/applications/ubuntu-system-settings.desktop'])
301+ sleep(1)
302 self.window = self.app.select_single("QQuickView")
303 self.assertThat(self.window.visible, Eventually(Equals(True)))
304
305+ def tearDown(self):
306+ super(OnlineAccountsUiTests, self).tearDown()
307+ # This matches the logic in setUp()
308+ if model() != 'Desktop':
309+ return
310+ self.system_settings.terminate()
311+
312 def test_title(self):
313 """ Checks whether the Online Accounts window title is correct """
314 # On the phone, this fails because of https://bugs.launchpad.net/bugs/1252294
315@@ -272,7 +77,7 @@
316
317 header = self.window.select_single('Header', visible=True)
318 self.assertThat(header, NotEquals(None))
319- self.assertThat(header.title, Eventually(Equals('Accounts')))
320+ self.assertThat(header.title, Eventually(Equals('Online Accounts')))
321
322 def test_available_providers(self):
323 """ Checks whether all the expected providers are available """
324@@ -287,179 +92,70 @@
325 provider_item = self.app.select_single('Standard', text=provider)
326 self.assertThat(provider_item, NotEquals(None))
327
328- def test_create_oauth1_account(self):
329- """ Test the creation of an OAuth 1.0 account """
330- # On the phone, this fails because of https://bugs.launchpad.net/bugs/1231968
331- if model() != 'Desktop':
332- return
333- server = OAuth1LocalServer()
334- server.run()
335-
336- page = self.app.select_single('NoAccountsPage')
337- self.assertThat(page, NotEquals(None))
338-
339- provider_item = self.app.select_single('Standard', text='FakeOAuthOne')
340- self.assertThat(provider_item, NotEquals(None))
341-
342- # Depending on the number of installed providers, it may be that our
343- # test provider is not visible; in that case, scroll the page
344- self.pointer.move_to_object(page)
345- (page_center_x, page_center_y) = self.pointer.position()
346- page_bottom = page.globalRect[1] + page.globalRect[3]
347- while provider_item.center[1] > page_bottom:
348- self.pointer.move(page_center_x, page_center_y)
349- self.pointer.press()
350- self.pointer.move(page_center_x, page_center_y - provider_item.height * 2)
351- # wait some time before releasing, to avoid a flick
352- sleep(0.2)
353- self.pointer.release()
354- self.pointer.move_to_object(provider_item)
355- self.pointer.click()
356-
357- # At this point, the signon-ui process should be spawned by D-Bus and
358- # try to connect to our local webserver.
359- # Here we wait until we know that the webserver has served the login page:
360- server.httpd.show_login_event.wait(30)
361- self.assertThat(server.httpd.show_login_event.is_set(), Equals(True))
362- server.httpd.show_login_event.clear()
363-
364- # Give some time to signon-ui to render the page
365- sleep(2)
366- #self.signon_ui_window = self.signon_ui.select_single("QQuickView")
367- #self.assertThat(self.signon_ui_window.visible, Eventually(Equals(True)))
368-
369- # Move to the username field
370- self.keyboard.press_and_release('Tab')
371- self.keyboard.type('funnyguy')
372- self.keyboard.press_and_release('Enter')
373-
374- # At this point signon-ui should make a post request with the login
375- # data; let's wait for it:
376- server.httpd.login_done_event.wait(30)
377- self.assertThat(server.httpd.login_done_event.is_set(), Equals(True))
378- server.httpd.login_done_event.clear()
379-
380- if model() == 'Desktop':
381- # Close the signon-ui window
382- self.keyboard.press_and_release('Enter')
383-
384- # The account should be created shortly
385- sleep(5)
386- account_item = self.app.select_single('AccountItem', text='FakeOAuthOne')
387- self.assertThat(account_item, NotEquals(None))
388- self.assertThat(account_item.subText, Equals('funnyguy'))
389-
390- # Delete it
391- self.pointer.move_to_object(account_item)
392- self.pointer.click()
393-
394- sleep(1)
395- edit_page = self.app.select_single('AccountEditPage')
396- self.assertThat(edit_page, NotEquals(None))
397- remove_button = edit_page.select_single('Button')
398- self.assertThat(remove_button, NotEquals(None))
399- self.pointer.move_to_object(remove_button)
400- self.pointer.click()
401-
402- sleep(1)
403- removal_page = self.app.select_single('RemovalConfirmation')
404- self.assertThat(removal_page, NotEquals(None))
405- remove_button = removal_page.select_single('Button', text='Remove')
406- self.assertThat(remove_button, NotEquals(None))
407- self.pointer.move_to_object(remove_button)
408- self.pointer.click()
409-
410- # Check that the account has been deleted
411- sleep(1)
412- account_item = self.app.select_single('AccountItem', text='FakeOAuth')
413- self.assertThat(account_item, Equals(None))
414-
415- def test_create_oauth2_account(self):
416- """ Test the creation of an OAuth 2.0 account """
417- # WebKit2 cannot ignore SSL errors, so this test fails on the phone
418- if model() != 'Desktop':
419- return
420-
421- self.server = LocalServer()
422- self.server.run()
423-
424- page = self.app.select_single('NoAccountsPage')
425- self.assertThat(page, NotEquals(None))
426-
427- provider_item = self.app.select_single('Standard', text='FakeOAuth')
428- self.assertThat(provider_item, NotEquals(None))
429-
430- # Depending on the number of installed providers, it may be that our
431- # test provider is not visible; in that case, scroll the page
432- self.pointer.move_to_object(page)
433- (page_center_x, page_center_y) = self.pointer.position()
434- page_bottom = page.globalRect[1] + page.globalRect[3]
435- while provider_item.center[1] > page_bottom:
436- self.pointer.move(page_center_x, page_center_y)
437- self.pointer.press()
438- self.pointer.move(page_center_x, page_center_y - provider_item.height * 2)
439- # wait some time before releasing, to avoid a flick
440- sleep(0.2)
441- self.pointer.release()
442- self.pointer.move_to_object(provider_item)
443- self.pointer.click()
444-
445- # At this point, the signon-ui process should be spawned by D-Bus and
446- # try to connect to our local webserver.
447- # Here we wait until we know that the webserver has served the login page:
448- self.server.httpd.show_login_event.wait(30)
449- self.assertThat(self.server.httpd.show_login_event.is_set(), Equals(True))
450- self.server.httpd.show_login_event.clear()
451-
452- # Give some time to signon-ui to render the page
453- sleep(2)
454- #self.signon_ui_window = self.signon_ui.select_single("QQuickView")
455- #self.assertThat(self.signon_ui_window.visible, Eventually(Equals(True)))
456-
457- # Move to the username field
458- self.keyboard.press_and_release('Tab')
459- self.keyboard.type('john')
460- self.keyboard.press_and_release('Tab')
461- self.keyboard.type('loser')
462- self.keyboard.press_and_release('Enter')
463-
464- # At this point signon-ui should make a post request with the login
465- # data; let's wait for it:
466- self.server.httpd.login_done_event.wait(30)
467- self.assertThat(self.server.httpd.login_done_event.is_set(), Equals(True))
468- self.server.httpd.login_done_event.clear()
469-
470- if model() == 'Desktop':
471- # Close the signon-ui window
472- self.keyboard.press_and_release('Enter')
473-
474- # The account should be created shortly
475- sleep(5)
476- account_item = self.app.select_single('AccountItem', text='FakeOAuth')
477- self.assertThat(account_item, NotEquals(None))
478- self.assertThat(account_item.subText, Equals('john'))
479-
480- # Delete it
481- self.pointer.move_to_object(account_item)
482- self.pointer.click()
483-
484- sleep(1)
485- edit_page = self.app.select_single('AccountEditPage')
486- self.assertThat(edit_page, NotEquals(None))
487- remove_button = edit_page.select_single('Button')
488- self.assertThat(remove_button, NotEquals(None))
489- self.pointer.move_to_object(remove_button)
490- self.pointer.click()
491-
492- sleep(1)
493- removal_page = self.app.select_single('RemovalConfirmation')
494- self.assertThat(removal_page, NotEquals(None))
495- remove_button = removal_page.select_single('Button', text='Remove')
496- self.assertThat(remove_button, NotEquals(None))
497- self.pointer.move_to_object(remove_button)
498- self.pointer.click()
499-
500- # Check that the account has been deleted
501- sleep(1)
502- account_item = self.app.select_single('AccountItem', text='FakeOAuth')
503- self.assertThat(account_item, Equals(None))
504+ def test_create_account_with_form(self):
505+ """ Test the creation of an account using a username/password form"""
506+ # On the phone, this fails because of https://bugs.launchpad.net/bugs/1252294
507+ if model() != 'Desktop':
508+ return
509+ page = self.app.select_single('NoAccountsPage')
510+ self.assertThat(page, NotEquals(None))
511+
512+ provider_item = self.app.select_single('Standard', text='TestLogin')
513+ self.assertThat(provider_item, NotEquals(None))
514+
515+ # Depending on the number of installed providers, it may be that our
516+ # test provider is not visible; in that case, scroll the page
517+ self.pointer.move_to_object(page)
518+ (page_center_x, page_center_y) = self.pointer.position()
519+ page_bottom = page.globalRect[1] + page.globalRect[3]
520+ while provider_item.center[1] > page_bottom - 20:
521+ self.pointer.move(page_center_x, page_center_y)
522+ self.pointer.press()
523+ self.pointer.move(page_center_x, page_center_y - provider_item.height * 2)
524+ # wait some time before releasing, to avoid a flick
525+ sleep(0.2)
526+ self.pointer.release()
527+ self.pointer.move_to_object(provider_item)
528+ self.pointer.click()
529+
530+ # Move to the username field
531+ username_field = self.app.select_single('TextField', objectName='usernameField')
532+ self.pointer.move_to_object(username_field)
533+ self.pointer.click()
534+ self.keyboard.type('pinkuser')
535+ self.keyboard.press_and_release('Tab')
536+ self.keyboard.type('lolcat')
537+ # Submit
538+ continue_btn = self.app.select_single('Button', objectName='continueButton')
539+ self.pointer.move_to_object(continue_btn)
540+ self.pointer.click()
541+
542+ # The account should be created shortly
543+ sleep(5)
544+ account_item = self.app.select_single('AccountItem', text='TestLogin')
545+ self.assertThat(account_item, NotEquals(None))
546+ self.assertThat(account_item.subText, Equals('pinkuser'))
547+
548+ # Delete it
549+ self.pointer.move_to_object(account_item)
550+ self.pointer.click()
551+
552+ sleep(1)
553+ edit_page = self.app.select_single('AccountEditPage')
554+ self.assertThat(edit_page, NotEquals(None))
555+ remove_button = edit_page.select_single('Button')
556+ self.assertThat(remove_button, NotEquals(None))
557+ self.pointer.move_to_object(remove_button)
558+ self.pointer.click()
559+
560+ sleep(1)
561+ removal_page = self.app.select_single('RemovalConfirmation')
562+ self.assertThat(removal_page, NotEquals(None))
563+ remove_button = removal_page.select_single('Button', text='Remove')
564+ self.assertThat(remove_button, NotEquals(None))
565+ self.pointer.move_to_object(remove_button)
566+ self.pointer.click()
567+
568+ # Check that the account has been deleted
569+ account_item.wait_until_destroyed()
570+

Subscribers

People subscribed via source and target branches