Merge lp:~elopio/ubuntuone-testing/newaccount into lp:ubuntuone-testing

Proposed by Leo Arias
Status: Superseded
Proposed branch: lp:~elopio/ubuntuone-testing/newaccount
Merge into: lp:ubuntuone-testing
Diff against target: 375 lines (+195/-27)
10 files modified
ubuntuone/web/tests/sst/payments/u1webp002_payadditionalstorage.py (+1/-1)
ubuntuone/web/tests/sst/shared/actions/header.py (+1/-1)
ubuntuone/web/tests/sst/shared/actions/payment.py (+8/-8)
ubuntuone/web/tests/sst/shared/actions/payment_confirmed.py (+13/-7)
ubuntuone/web/tests/sst/shared/actions/services.py (+3/-0)
ubuntuone/web/tests/sst/shared/actions/setup.py (+20/-10)
ubuntuone/web/tests/sst/shared/actions/sso.py (+15/-0)
ubuntuone/web/tests/sst/shared/config.py (+5/-0)
ubuntuone/web/tests/sst/shared/utils/mail.py (+93/-0)
ubuntuone/web/tests/sst/shared/utils/paymentperiods.py (+36/-0)
To merge this branch: bzr merge lp:~elopio/ubuntuone-testing/newaccount
Reviewer Review Type Date Requested Status
Rick McBride (community) Needs Fixing
Review via email: mp+84273@code.launchpad.net

This proposal has been superseded by a proposal from 2011-12-08.

Commit message

Added the code for the creation of a new account.
Added a utility module to calculate payments expiration dates.
Fixed a bug with the calculation of the next month of December.
Verify only the first 40 characters of the user name.

Description of the change

Added the code for the creation of a new account.
Added a utility module to calculate payments expiration dates.
Fixed a bug with the calculation of the next month of December.
Verify only the first 40 characters of the user name.

To post a comment you must log in.
Revision history for this message
Rick McBride (rmcbride) wrote :

One change:

I'd like to see the following:

4 + user_email = user_uuid + '@elopio.net'

not include a hard coded value. If we can put the '@elopio.net' bit in config and reference it here, that will be better long term. Otherwise, looks great!

review: Needs Fixing
63. By Leo Arias

Take the new email address server from the config file.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ubuntuone/web/tests/sst/payments/u1webp002_payadditionalstorage.py'
2--- ubuntuone/web/tests/sst/payments/u1webp002_payadditionalstorage.py 2011-11-24 04:58:16 +0000
3+++ ubuntuone/web/tests/sst/payments/u1webp002_payadditionalstorage.py 2011-12-08 15:26:27 +0000
4@@ -34,7 +34,7 @@
5 services_actions.buy_extra_storage()
6 payment_actions.assert_title()
7 payment_actions.place_order_with_valid_card()
8-payment_confirmed_actions.assert_title()
9+payment_actions.confirm_payment_details()
10 payment_confirmed_actions.assert_processed_payment('annually', 29.99, 29.99)
11 payment_confirmed_actions.view_account()
12 # TODO move this to the module account actions.
13
14=== modified file 'ubuntuone/web/tests/sst/shared/actions/header.py'
15--- ubuntuone/web/tests/sst/shared/actions/header.py 2011-11-15 07:18:27 +0000
16+++ ubuntuone/web/tests/sst/shared/actions/header.py 2011-12-08 15:26:27 +0000
17@@ -31,7 +31,7 @@
18
19 def _assert_full_name(full_name):
20 welcome_element = get_element_by_css('#ac-status > span')
21- text_is(welcome_element, 'Welcome %s' % full_name)
22+ text_is(welcome_element, 'Welcome %s' % full_name[:40])
23
24 def _get_my_account_link():
25 return get_element(tag='a', css_class='account', text='My Account')
26
27=== modified file 'ubuntuone/web/tests/sst/shared/actions/payment.py'
28--- ubuntuone/web/tests/sst/shared/actions/payment.py 2011-10-25 17:10:29 +0000
29+++ ubuntuone/web/tests/sst/shared/actions/payment.py 2011-12-08 15:26:27 +0000
30@@ -21,6 +21,7 @@
31
32 from datetime import datetime
33 from sst.actions import *
34+from utils import paymentperiods
35
36 def assert_title():
37 """Assert that the title of the page is the expected."""
38@@ -46,13 +47,13 @@
39 get_element(css_class='price', text=price)
40 get_element(tag='span', css_class='price', text=price)
41 today = datetime.utcnow()
42- next_month = today.replace(month = today.month + 1)
43+ trial_expiration_date = paymentperiods.get_trial_expiration_date()
44 get_element(tag='p', text='This is a trial subscription which will '
45- 'expire %(next_month)s after which your card '
46- 'will automatically be billed %(price)s '
47+ 'expire %(trial_expiration)s after which your '
48+ 'card will automatically be billed %(price)s '
49 '%(period)s'
50- % {'next_month':
51- next_month.strftime('%B %-d, %Y'),
52+ % {'trial_expiration':
53+ trial_expiration_date.strftime('%B %-d, %Y'),
54 'price': price, 'period': period})
55
56 def assert_monthly_music_streaming_subscription():
57@@ -83,12 +84,11 @@
58 if period == 'monthly':
59 price_per_add_on = 2.99
60 period_alternate = period
61- period_end = today.replace(month = today.month + 1)
62+ period_end = paymentperiods.get_monthly_expiration_date()
63 elif period == 'annually':
64 price_per_add_on = 29.99
65 period_alternate = 'yearly'
66- period_end = today.replace(year = today.year + 1,
67- day = today.day + 1)
68+ period_end = paymentperiods.get_yearly_expiration_date()
69 else:
70 # TODO throw an error.
71 pass
72
73=== modified file 'ubuntuone/web/tests/sst/shared/actions/payment_confirmed.py'
74--- ubuntuone/web/tests/sst/shared/actions/payment_confirmed.py 2011-10-20 05:24:23 +0000
75+++ ubuntuone/web/tests/sst/shared/actions/payment_confirmed.py 2011-12-08 15:26:27 +0000
76@@ -21,6 +21,7 @@
77
78 from sst.actions import *
79 from datetime import datetime
80+from utils import paymentperiods
81
82 def assert_title():
83 """Assert that the title of the page is the expected."""
84@@ -45,19 +46,24 @@
85 """
86 get_element(tag='h1', text='Payment Processed')
87 today = datetime.utcnow()
88- if trial or period == 'monthly':
89- expire_date = today.replace(month = today.month + 1)
90+ if trial:
91+ expire_date = paymentperiods.get_trial_expiration_date()
92+ elif period == 'monthly':
93+ expire_date = paymentperiods.get_monthly_expiration_date()
94 elif period == 'annually':
95- expire_date = today.replace(year = today.year + 1)
96+ expire_date = paymentperiods.get_yearly_expiration_date()
97 # TODO assert the paid amount.
98 # TODO assert payments in euros.
99- get_element(tag='dt', css_class='purchase_details',
100- text='Expires: %(expire_date)s'
101- % {'expire_date': expire_date.strftime('%B %-d, %Y')})
102+ element_expire_date = _get_purchase_details_data_elements()[0]
103+ text_is(element_expire_date, expire_date.strftime('%B %-d, %Y'))
104 get_element(tag='p', css_class='explanation',
105 text='Your card will automatically be billed $%(price)s ' \
106 '%(period)s' % {'price': str(price), 'period': period})
107- get_element(tag='dd', text='AUTHORISED')
108+ element_payment_status = _get_purchase_details_data_elements()[1]
109+ text_is(element_payment_status, 'AUTHORISED')
110+
111+def _get_purchase_details_data_elements():
112+ return get_elements_by_css('dl.purchase_details > dd')
113
114 def view_account():
115 """Go to the account information page."""
116
117=== modified file 'ubuntuone/web/tests/sst/shared/actions/services.py'
118--- ubuntuone/web/tests/sst/shared/actions/services.py 2011-10-07 00:45:14 +0000
119+++ ubuntuone/web/tests/sst/shared/actions/services.py 2011-12-08 15:26:27 +0000
120@@ -31,6 +31,9 @@
121 """Assert that the title of the page is the expected."""
122 title_is(u'Ubuntu One : Services')
123
124+def agree_and_subscribe_to_free_plan():
125+ button_click(get_element(name='subscribe'))
126+
127 def assert_services_information():
128 """Assert that the information about the services is the expected."""
129 assert_free_service_information()
130
131=== modified file 'ubuntuone/web/tests/sst/shared/actions/setup.py'
132--- ubuntuone/web/tests/sst/shared/actions/setup.py 2011-11-24 04:58:16 +0000
133+++ ubuntuone/web/tests/sst/shared/actions/setup.py 2011-12-08 15:26:27 +0000
134@@ -1,9 +1,5 @@
135 # -*- coding: utf-8 -*-
136
137-# Authors:
138-# Rick McBride <rick.mcbride@canonical.com>
139-# Leo Arias <leo.arias@canonical.com>
140-#
141 # Copyright 2011 Canonical Ltd.
142 #
143 # This program is free software: you can redistribute it and/or modify it
144@@ -22,16 +18,20 @@
145
146 from sst.actions import *
147 from config import *
148+import actions.header as header_actions
149+import actions.sso as sso_actions
150+import actions.services as services_actions
151+import uuid
152+from utils import mail
153 try:
154 from _passwords import full_name, email, password
155 except:
156 skip('Try adding a _passwords.py file to the shared folder if you ' \
157 'expect this to work. Read the README.txt file ;)')
158-import actions.header as header_actions
159-import actions.sso as sso_actions
160+
161
162 def setup(new_user=False):
163- """Create new user (optional) and log in to the Ubuntu One website.
164+ """Log in to the Ubuntu One website. Optionally, you can create a new user.
165
166 After calling setup, the browser will be in the Dashboard ready to
167 start testing.
168@@ -45,11 +45,21 @@
169 goto()
170 waitfor(title_is, 'Ubuntu One : Home')
171 header_actions.click_login_or_sign_up()
172+ user_name = full_name
173+ user_email = email
174 if new_user:
175- skip('New user creation is not yet implemented.')
176+ user_uuid = str(uuid.uuid1())
177+ user_name = 'Test user ' + user_uuid
178+ user_email = user_uuid + '@' IMAP_SERVER
179+ sso_actions.create_new_account(user_name, user_email, 'Hola123*')
180+ confirmation_code = mail.get_confirmation_code_for_address(user_email)
181+ sso_actions.confirm_email(confirmation_code)
182 else:
183- sso_actions.login(email, password)
184- header_actions.assert_login(full_name)
185+ sso_actions.login(user_email, password)
186+ sso_actions.authenticate()
187+ if new_user:
188+ services_actions.agree_and_subscribe_to_free_plan()
189+ header_actions.assert_login(user_name)
190
191 def get_base_url():
192 base_url = None
193
194=== modified file 'ubuntuone/web/tests/sst/shared/actions/sso.py'
195--- ubuntuone/web/tests/sst/shared/actions/sso.py 2011-11-24 04:58:16 +0000
196+++ ubuntuone/web/tests/sst/shared/actions/sso.py 2011-12-08 15:26:27 +0000
197@@ -38,6 +38,21 @@
198 textfield_write('id_email', email)
199 textfield_write('id_password', password)
200 button_click(get_element(css_class='btn', name='continue'), wait=False)
201+
202+def create_new_account(full_name, email, password):
203+ link_click(get_element(href='+new_account'))
204+ waitfor(title_is, 'Create account')
205+ textfield_write('id_displayname', full_name)
206+ textfield_write('id_email', email)
207+ textfield_write('id_password', password)
208+ textfield_write('id_passwordconfirm', password)
209+ button_click(get_element(name='continue'))
210+
211+def confirm_email(confirmation_code):
212+ textfield_write(get_element(name='confirmation_code'), confirmation_code)
213+ button_click(get_element(css_class='btn', text='Continue'))
214+
215+def authenticate():
216 waitfor(title_is, 'Authenticate to %s' % get_base_url())
217 waitfor(get_element, tag='body')
218 button_click(get_element(css_class='btn', name='yes'))
219
220=== modified file 'ubuntuone/web/tests/sst/shared/config.py'
221--- ubuntuone/web/tests/sst/shared/config.py 2011-11-30 22:39:09 +0000
222+++ ubuntuone/web/tests/sst/shared/config.py 2011-12-08 15:26:27 +0000
223@@ -23,6 +23,11 @@
224 #ENVIRONMENT = 'edge'
225 #ENVIRONMENT = 'production'
226
227+# Email inbox data
228+IMAP_SERVER = 'mail.canonical.com'
229+IMAP_USERNAME = 'u1test'
230+IMAP_PASSWORD = 'password'
231+
232 # You can overwrite the default configuration setting the variables on
233 # the file shared/_local_config.py.
234 try:
235
236=== added directory 'ubuntuone/web/tests/sst/shared/utils'
237=== added file 'ubuntuone/web/tests/sst/shared/utils/__init__.py'
238=== added file 'ubuntuone/web/tests/sst/shared/utils/mail.py'
239--- ubuntuone/web/tests/sst/shared/utils/mail.py 1970-01-01 00:00:00 +0000
240+++ ubuntuone/web/tests/sst/shared/utils/mail.py 2011-12-08 15:26:27 +0000
241@@ -0,0 +1,93 @@
242+# -*- coding: utf-8 -*-
243+
244+# Copyright 2011 Canonical Ltd.
245+#
246+# This program is free software: you can redistribute it and/or modify it
247+# under the terms of the GNU General Public License version 3, as published
248+# by the Free Software Foundation.
249+#
250+# This program is distributed in the hope that it will be useful, but
251+# WITHOUT ANY WARRANTY; without even the implied warranties of
252+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
253+# PURPOSE. See the GNU General Public License for more details.
254+#
255+# You should have received a copy of the GNU General Public License along
256+# with this program. If not, see <http://www.gnu.org/licenses/>.
257+
258+"""Email reading utility copied from ISD test scripts."""
259+
260+import quopri
261+import re
262+import imaplib
263+import time
264+from config import IMAP_SERVER, IMAP_USERNAME, IMAP_PASSWORD
265+
266+def get_confirmation_code_for_address(email_address):
267+ email_msg = get_latest_email_sent_to(email_address)
268+ vcode = None
269+ if email_msg:
270+ # The body is encoded as quoted-printable. This affects any line
271+ # longer than a certain length. Decode now to not have to worry
272+ # about it in the regexen.
273+ body = quopri.decodestring(email_msg.get_payload())
274+ match = re.search(
275+ 'Here is your confirmation code:(.*)(Enter|If you made)',
276+ body, re.S)
277+ if match:
278+ vcode = match.group(1).strip()
279+ else:
280+ raise AssertionError("No verification link found in email.")
281+ return vcode
282+
283+def get_latest_email_sent_to(email_address):
284+ with MailBox(IMAP_USERNAME, IMAP_PASSWORD) as mbox:
285+ email_msg = mbox.get_latest_email_sent_to(email_address)
286+ mbox.delete_msgs_sent_to(email_address)
287+ return email_msg
288+
289+class MailBox(object):
290+ def __init__(self, user, password):
291+ self.user = user
292+ self.password = password
293+ self.imap = imaplib.IMAP4_SSL(IMAP_SERVER, 993)
294+
295+ def __enter__(self):
296+ self.imap.login(self.user, self.password)
297+ return self
298+
299+ def __exit__(self, type, value, traceback):
300+ self.imap.close()
301+ self.imap.logout()
302+
303+ def get_latest_email_sent_to(self, email_address, timeout=300, poll=1):
304+ start_time = time.time()
305+ while ((time.time() - start_time) < timeout):
306+ # It's no use continuing until we've successfully selected
307+ # the inbox. And if we don't select it on each iteration
308+ # before searching, we get intermittent failures.
309+ status, data = self.imap.select('Inbox')
310+ if status != 'OK':
311+ time.sleep(poll)
312+ continue
313+
314+ status, data = self.imap.search(None, 'TO', email_address)
315+ if status == 'OK':
316+ for num in reversed(data[0].split()):
317+ status, data = self.imap.fetch(num, '(RFC822)')
318+ email_msg = email.message_from_string(data[0][1])
319+ return email_msg
320+ time.sleep(poll)
321+
322+ raise AssertionError("No email sent to '%s' found in inbox "
323+ "after polling for %s seconds."
324+ % (email_address, timeout))
325+
326+ def delete_msgs_sent_to(self, email_address):
327+ self.imap.select('Inbox')
328+ status, data = self.imap.search(None, 'TO', email_address)
329+ if status == 'OK':
330+ for num in reversed(data[0].split()):
331+ status, data = self.imap.fetch(num, '(RFC822)')
332+ body = data[0][1]
333+ self.imap.store(num, '+FLAGS', r'\Deleted')
334+ self.imap.expunge()
335
336=== added file 'ubuntuone/web/tests/sst/shared/utils/paymentperiods.py'
337--- ubuntuone/web/tests/sst/shared/utils/paymentperiods.py 1970-01-01 00:00:00 +0000
338+++ ubuntuone/web/tests/sst/shared/utils/paymentperiods.py 2011-12-08 15:26:27 +0000
339@@ -0,0 +1,36 @@
340+# -*- coding: utf-8 -*-
341+
342+# Copyright 2011 Canonical Ltd.
343+#
344+# This program is free software: you can redistribute it and/or modify it
345+# under the terms of the GNU General Public License version 3, as published
346+# by the Free Software Foundation.
347+#
348+# This program is distributed in the hope that it will be useful, but
349+# WITHOUT ANY WARRANTY; without even the implied warranties of
350+# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
351+# PURPOSE. See the GNU General Public License for more details.
352+#
353+# You should have received a copy of the GNU General Public License along
354+# with this program. If not, see <http://www.gnu.org/licenses/>.
355+
356+"""Utilities to help the calculation of payment periods."""
357+
358+from datetime import datetime
359+
360+def get_monthly_expiration_date():
361+ today = _get_today()
362+ if today.month != 12:
363+ return today.replace(month=today.month + 1)
364+ else:
365+ return today.replace(month=1, year=today.year + 1)
366+
367+def get_yearly_expiration_date():
368+ today = _get_today()
369+ return today.replace(year = today.year + 1)
370+
371+def get_trial_expiration_date():
372+ return get_monthly_expiration_date()
373+
374+def _get_today():
375+ return datetime.utcnow()

Subscribers

People subscribed via source and target branches