source: OpenWorkouts-current/ow/tests/views/test_user.py @ f0e64eb

currentfeature/docs
Last change on this file since f0e64eb was f0e64eb, checked in by Borja Lopez <borja@…>, 5 years ago

(#51) Fixed profile images were too big:

  • Added new dependency (Pillow)
  • Modified the user profile picture view. Now it accepts a GET parameter (size) telling the size of the image we want. Only one value is needed, the code will scale the image appropiately.
  • Modified the dashboard, profile and edit_profile templates to ask for a smaller version (200px) of the user profile picture.

IMPORTANT: Ensure you install Pillow in any existing environments after pulling:

pip install Pillow

  • Property mode set to 100644
File size: 30.2 KB
Line 
1import os
2import json
3from decimal import Decimal
4from datetime import datetime, timedelta, timezone
5from shutil import copyfileobj
6from unittest.mock import Mock, patch
7from io import BytesIO
8
9import pytest
10
11from ZODB.blob import Blob
12
13from pyramid.testing import DummyRequest
14from pyramid.httpexceptions import HTTPFound
15from pyramid.response import Response
16
17from webob.multidict import MultiDict
18
19from PIL import Image
20
21from ow.models.root import OpenWorkouts
22from ow.models.user import User
23from ow.models.workout import Workout
24from ow.views.renderers import OWFormRenderer
25import ow.views.user as user_views
26
27
28class TestUserViews(object):
29
30    @pytest.fixture
31    def john(self):
32        user = User(firstname='John', lastname='Doe',
33                    email='john.doe@example.net')
34        user.password = 's3cr3t'
35        return user
36
37    @pytest.fixture
38    def root(self, john):
39        root = OpenWorkouts()
40        root.add_user(john)
41        workout = Workout(
42            start=datetime(2015, 6, 28, 12, 55, tzinfo=timezone.utc),
43            duration=timedelta(minutes=60),
44            distance=30
45        )
46        john.add_workout(workout)
47        return root
48
49    @pytest.fixture
50    def dummy_request(self, root):
51        request = DummyRequest()
52        request.root = root
53        return request
54
55    @pytest.fixture
56    def profile_post_request(self, root, john):
57        """
58        This is a valid POST request to update an user profile.
59        Form will validate, but nothing will be really updated/changed.
60        """
61        user = john
62        request = DummyRequest()
63        request.root = root
64        request.method = 'POST'
65        request.POST = MultiDict({
66            'submit': True,
67            'firstname': user.firstname,
68            'lastname': user.lastname,
69            'email': user.email,
70            'bio': user.bio,
71            'weight': user.weight,
72            'height': user.height,
73            'gender': user.gender,
74            'birth_date': user.birth_date,
75            'picture': user.picture,
76            })
77        return request
78
79    @pytest.fixture
80    def passwd_post_request(self, root):
81        """
82        This is a valid POST request to change the user password, but
83        the form will not validate (empty fields)
84        """
85        request = DummyRequest()
86        request.root = root
87        request.method = 'POST'
88        request.POST = MultiDict({
89            'submit': True,
90            'old_password': '',
91            'password': '',
92            'password_confirm': ''
93            })
94        return request
95
96    @pytest.fixture
97    def signup_post_request(self, root):
98        """
99        This is a valid POST request to signup a new user.
100        """
101        request = DummyRequest()
102        request.root = root
103        request.method = 'POST'
104        request.POST = MultiDict({
105            'submit': True,
106            'nickname': 'JackBlack',
107            'email': 'jack.black@example.net',
108            'firstname': 'Jack',
109            'lastname': 'Black',
110            'password': 'j4ck s3cr3t',
111            'password_confirm': 'j4ck s3cr3t'
112            })
113        return request
114
115    def test_dashboard_redirect_unauthenticated(self, root):
116        """
117        Anoymous access to the root object, send the user to the login page.
118
119        Instead of reusing the DummyRequest from the request fixture, we do
120        Mock fully the request here, because we need to use
121        authenticated_userid, which cannot be easily set in the DummyRequest
122        """
123        request = DummyRequest()
124        request.root = root
125        response = user_views.dashboard_redirect(root, request)
126        assert isinstance(response, HTTPFound)
127        assert response.location == request.resource_url(root, 'login')
128
129    def test_dashboard_redirect_authenticated(self, root, john):
130        """
131        Authenticated user accesing the root object, send the user to her
132        dashboard
133
134        Instead of reusing the DummyRequest from the request fixture, we do
135        Mock fully the request here, because we need to use
136        authenticated_userid, which cannot be easily set in the DummyRequest
137        """
138        alt_request = DummyRequest()
139        request = Mock()
140        request.root = root
141        request.authenticated_userid = str(john.uid)
142        request.resource_url = alt_request.resource_url
143        response = user_views.dashboard_redirect(root, request)
144        assert isinstance(response, HTTPFound)
145        assert response.location == request.resource_url(john)
146        # if authenticated_userid is the id of an user that does not exist
147        # anymore, we send the user to the logout page
148        request.authenticated_userid = 'faked-uid'
149        response = user_views.dashboard_redirect(root, request)
150        assert isinstance(response, HTTPFound)
151        assert response.location == request.resource_url(root, 'logout')
152
153    def test_dashboard(self, dummy_request, john):
154        """
155        Renders the user dashboard
156        """
157        request = dummy_request
158        response = user_views.dashboard(john, request)
159        assert len(response) == 6
160        assert 'month_name' in response.keys()
161        assert response['current_year'] == datetime.now().year
162        assert response['current_day_name'] == datetime.now().strftime('%a')
163        # this user has a single workout, in 2015
164        assert response['viewing_year'] == 2015
165        assert response['viewing_month'] == 6
166        assert response['workouts'] == [w for w in john.workouts()]
167
168    def test_dashboard_year(self, dummy_request, john):
169        """
170        Renders the user dashboard for a chosen year.
171        """
172        request = dummy_request
173        # first test the year for which we know there is a workout
174        request.GET['year'] = 2015
175        response = user_views.dashboard(john, request)
176        assert len(response) == 6
177        assert 'month_name' in response.keys()
178        assert response['current_year'] == datetime.now().year
179        assert response['current_day_name'] == datetime.now().strftime('%a')
180        # this user has a single workout, in 2015
181        assert response['viewing_year'] == 2015
182        assert response['viewing_month'] == 6
183        assert response['workouts'] == [w for w in john.workouts()]
184        # now, a year we know there is no workout info
185        request.GET['year'] = 2000
186        response = user_views.dashboard(john, request)
187        assert len(response) == 6
188        assert 'month_name' in response.keys()
189        assert response['current_year'] == datetime.now().year
190        assert response['current_day_name'] == datetime.now().strftime('%a')
191        # this user has a single workout, in 2015
192        assert response['viewing_year'] == 2000
193        # we have no data for that year and we didn't ask for a certain month,
194        # so the passing value for that is None
195        assert response['viewing_month'] is None
196        assert response['workouts'] == []
197
198    def test_dashboard_year_month(self, dummy_request, john):
199        """
200        Renders the user dashboard for a chosen year and month.
201        """
202        request = dummy_request
203        # first test the year/month for which we know there is a workout
204        request.GET['year'] = 2015
205        request.GET['month'] = 6
206        response = user_views.dashboard(john, request)
207        assert len(response) == 6
208        assert 'month_name' in response.keys()
209        assert response['current_year'] == datetime.now().year
210        assert response['current_day_name'] == datetime.now().strftime('%a')
211        # this user has a single workout, in 2015
212        assert response['viewing_year'] == 2015
213        assert response['viewing_month'] == 6
214        assert response['workouts'] == [w for w in john.workouts()]
215        # now, change month to one without values
216        request.GET['month'] = 2
217        response = user_views.dashboard(john, request)
218        assert len(response) == 6
219        assert 'month_name' in response.keys()
220        assert response['current_year'] == datetime.now().year
221        assert response['current_day_name'] == datetime.now().strftime('%a')
222        # this user has a single workout, in 2015
223        assert response['viewing_year'] == 2015
224        assert response['viewing_month'] == 2
225        assert response['workouts'] == []
226        # now the month with data, but in a different year
227        request.GET['year'] = 2010
228        request.GET['month'] = 6
229        response = user_views.dashboard(john, request)
230        assert len(response) == 6
231        assert 'month_name' in response.keys()
232        assert response['current_year'] == datetime.now().year
233        assert response['current_day_name'] == datetime.now().strftime('%a')
234        # this user has a single workout, in 2015
235        assert response['viewing_year'] == 2010
236        assert response['viewing_month'] == 6
237        assert response['workouts'] == []
238
239    def test_dashboard_month(self, dummy_request, john):
240        """
241        Passing a month without a year when rendering the dashboard. The last
242        year for which workout data is available is assumed
243        """
244        request = dummy_request
245        # Set a month without workout data
246        request.GET['month'] = 5
247        response = user_views.dashboard(john, request)
248        assert len(response) == 6
249        assert 'month_name' in response.keys()
250        assert response['current_year'] == datetime.now().year
251        assert response['current_day_name'] == datetime.now().strftime('%a')
252        # this user has a single workout, in 2015
253        assert response['viewing_year'] == 2015
254        assert response['viewing_month'] == 5
255        assert response['workouts'] == []
256        # now a month with data
257        request.GET['month'] = 6
258        response = user_views.dashboard(john, request)
259        assert len(response) == 6
260        assert 'month_name' in response.keys()
261        assert response['current_year'] == datetime.now().year
262        assert response['current_day_name'] == datetime.now().strftime('%a')
263        # this user has a single workout, in 2015
264        assert response['viewing_year'] == 2015
265        assert response['viewing_month'] == 6
266        assert response['workouts'] == [w for w in john.workouts()]
267
268    def test_profile(self, dummy_request, john):
269        """
270        Renders the user profile page
271        """
272        request = dummy_request
273        # profile page for the current day (no workouts avalable)
274        response = user_views.profile(john, request)
275        assert len(response.keys()) == 5
276        current_month = datetime.now(timezone.utc).strftime('%Y-%m')
277        assert response['user'] == john
278        assert response['current_month'] == current_month
279        assert response['current_week'] is None
280        assert response['workouts'] == []
281        assert response['totals'] == {
282            'distance': Decimal(0),
283            'time': timedelta(0),
284            'elevation': Decimal(0)
285        }
286        # profile page for a previous date, that has workouts
287        request.GET['year'] = 2015
288        request.GET['month'] = 6
289        response = user_views.profile(john, request)
290        assert len(response.keys()) == 5
291        assert response['user'] == john
292        assert response['current_month'] == '2015-06'
293        assert response['current_week'] is None
294        workouts = john.workouts(2015, 6)
295        assert response['workouts'] == workouts
296        assert response['totals'] == {
297            'distance': workouts[0].distance,
298            'time': workouts[0].duration,
299            'elevation': Decimal(0)
300        }
301        # same, passing a week, first on a week without workouts
302        request.GET['year'] = 2015
303        request.GET['month'] = 6
304        request.GET['week'] = 25
305        response = user_views.profile(john, request)
306        assert len(response.keys()) == 5
307        assert response['user'] == john
308        assert response['current_month'] == '2015-06'
309        assert response['current_week'] == 25
310        assert response['workouts'] == []
311        assert response['totals'] == {
312            'distance': Decimal(0),
313            'time': timedelta(0),
314            'elevation': Decimal(0)
315        }
316        # now in a week with workouts
317        request.GET['year'] = 2015
318        request.GET['month'] = 6
319        request.GET['week'] = 26
320        response = user_views.profile(john, request)
321        assert len(response.keys()) == 5
322        assert response['user'] == john
323        assert response['current_month'] == '2015-06'
324        assert response['current_week'] == 26
325        workouts = john.workouts(2015, 6)
326        assert response['workouts'] == workouts
327        assert response['totals'] == {
328            'distance': workouts[0].distance,
329            'time': workouts[0].duration,
330            'elevation': Decimal(0)
331        }
332
333    def test_login_get(self, dummy_request):
334        """
335        GET request to access the login page
336        """
337        request = dummy_request
338        response = user_views.login(request.root, request)
339        assert response['message'] == ''
340        assert response['email'] == ''
341        assert response['password'] == ''
342        assert response['redirect_url'] == request.resource_url(request.root)
343
344    def test_login_get_return_to(self, dummy_request, john):
345        """
346        GET request to access the login page, if there is a page set to where
347        the user should be sent to, the response "redirect_url" key will have
348        such url
349        """
350        request = dummy_request
351        workout = john.workouts()[0]
352        workout_url = request.resource_url(workout)
353        request.params['return_to'] = workout_url
354        response = user_views.login(request.root, request)
355        assert response['redirect_url'] == workout_url
356
357    def test_login_post_wrong_email(self, dummy_request):
358        request = dummy_request
359        request.method = 'POST'
360        request.POST['submit'] = True
361        request.POST['email'] = 'jack@example.net'
362        response = user_views.login(request.root, request)
363        assert response['message'] == u'Wrong email address'
364
365    def test_login_post_wrong_password(self, dummy_request):
366        request = dummy_request
367        request.method = 'POST'
368        request.POST['submit'] = True
369        request.POST['email'] = 'john.doe@example.net'
370        request.POST['password'] = 'badpassword'
371        response = user_views.login(request.root, request)
372        assert response['message'] == u'Wrong password'
373
374    @patch('ow.views.user.remember')
375    def test_login_post_ok(self, rem, dummy_request, john):
376        request = dummy_request
377        request.method = 'POST'
378        request.POST['submit'] = True
379        request.POST['email'] = 'john.doe@example.net'
380        request.POST['password'] = 's3cr3t'
381        response = user_views.login(request.root, request)
382        assert isinstance(response, HTTPFound)
383        assert rem.called
384        assert response.location == request.resource_url(john)
385
386    @patch('ow.views.user.forget')
387    def test_logout(self, forg, dummy_request):
388        request = dummy_request
389        response = user_views.logout(request.root, request)
390        assert isinstance(response, HTTPFound)
391        assert forg.called
392        assert response.location == request.resource_url(request.root)
393
394    extensions = ('png', 'jpg', 'jpeg', 'gif')
395
396    @pytest.mark.parametrize('extension', extensions)
397    def test_profile_picture(self, extension, dummy_request, john):
398        """
399        GET request to get the profile picture of an user.
400        """
401        request = dummy_request
402        # Get the user
403        user = john
404        # Get the path to the image, then open it and copy it to a new Blob
405        # object
406        path = 'fixtures/image.' + extension
407        image_path = os.path.join(
408            os.path.dirname(os.path.dirname(__file__)), path)
409        blob = Blob()
410        with open(image_path, 'rb') as infile, blob.open('w') as out:
411            infile.seek(0)
412            copyfileobj(infile, out)
413
414        # Set the blob with the picture
415        user.picture = blob
416
417        # Call the profile_picture view
418        response = user_views.profile_picture(user, request)
419        assert isinstance(response, Response)
420        assert response.status_int == 200
421        assert response.content_type == 'image'
422        # as we did not pass a specific size as a get parameter, the size is
423        # the same as the original image
424        original_image = Image.open(image_path)
425        returned_image = Image.open(BytesIO(response.body))
426        assert original_image.size == returned_image.size
427
428        # now, ask for a smaller image
429        request.GET['size'] = original_image.size[0] - 20
430        response = user_views.profile_picture(user, request)
431        assert isinstance(response, Response)
432        assert response.status_int == 200
433        assert response.content_type == 'image'
434        # now the size of the original image is bigger
435        returned_image = Image.open(BytesIO(response.body))
436        assert original_image.size > returned_image.size
437
438        # now, ask for a size that is bigger than the original image,
439        # image will be the same size, as we do not "grow" its size
440        request.GET['size'] = original_image.size[0] + 1000
441        response = user_views.profile_picture(user, request)
442        assert isinstance(response, Response)
443        assert response.status_int == 200
444        assert response.content_type == 'image'
445        # now the size of the original image is bigger
446        returned_image = Image.open(BytesIO(response.body))
447        assert original_image.size == returned_image.size
448
449
450    def test_edit_profile_get(self, dummy_request, john):
451        """
452        GET request to the edit profile page, returns the form ready to
453        be rendered
454        """
455        request = dummy_request
456        user = john
457        response = user_views.edit_profile(user, request)
458        assert isinstance(response['form'], OWFormRenderer)
459        # no errors in the form (first load)
460        assert response['form'].errorlist() == ''
461        # the form carries along the proper data keys, taken from the
462        # loaded user profile
463        data = ['firstname', 'lastname', 'email', 'nickname', 'bio',
464                'birth_date', 'height', 'weight', 'gender', 'timezone']
465        assert list(response['form'].data.keys()) == data
466        # and check the email to see data is properly loaded
467        assert response['form'].data['email'] == 'john.doe@example.net'
468
469    def test_edit_profile_post_ok(self, profile_post_request, john):
470        request = profile_post_request
471        user = john
472        # Update the bio field
473        bio = 'Some text about this user'
474        request.POST['bio'] = bio
475        response = user_views.edit_profile(user, request)
476        assert isinstance(response, HTTPFound)
477        assert response.location == request.resource_url(user, 'profile')
478        assert user.bio == bio
479
480    def test_edit_profile_post_missing_required(
481            self, profile_post_request, john):
482        request = profile_post_request
483        request.POST['email'] = ''
484        user = john
485        response = user_views.edit_profile(user, request)
486        assert isinstance(response['form'], OWFormRenderer)
487        # error on the missing email field
488        error = u'Please enter an email address'
489        html_error = u'<ul class="error"><li>' + error + '</li></ul>'
490        assert response['form'].errorlist() == html_error
491        assert response['form'].errors_for('email') == [error]
492
493    def test_edit_profile_post_ok_picture_empty_bytes(
494            self, profile_post_request, john):
495        """
496        POST request with an empty picture, the content of
497        request['POST'].picture is a empty bytes string (b'') which triggers
498        a bug in formencode, we put a fix in place, test that
499        (more in ow.user.views.edit_profile)
500        """
501        # for the purposes of this test, we can mock the picture
502        picture = Mock()
503        john.picture = picture
504        request = profile_post_request
505        user = john
506        # Mimic what happens when a picture is not provided by the user
507        request.POST['picture'] = b''
508        response = user_views.edit_profile(user, request)
509        assert isinstance(response, HTTPFound)
510        assert response.location == request.resource_url(user, 'profile')
511        assert user.picture == picture
512
513    def test_edit_profile_post_ok_missing_picture(
514            self, profile_post_request, john):
515        """
516        POST request without picture
517        """
518        # for the purposes of this test, we can mock the picture
519        picture = Mock()
520        john.picture = picture
521        request = profile_post_request
522        user = john
523        # No pic is provided in the request POST values
524        del request.POST['picture']
525        response = user_views.edit_profile(user, request)
526        assert isinstance(response, HTTPFound)
527        assert response.location == request.resource_url(user, 'profile')
528        assert user.picture == picture
529
530    def test_edit_profile_post_ok_nickname(self, profile_post_request, john):
531        """
532        User with a nickname set saves profile without changing the profile,
533        we have to be sure there are no "nickname already in use" errors
534        """
535        request = profile_post_request
536        user = john
537        user.nickname = 'mr_jones'
538        # add the nickname, the default post request has not a nickname set
539        request.POST['nickname'] = 'mr_jones'
540        response = user_views.edit_profile(user, request)
541        assert isinstance(response, HTTPFound)
542        assert response.location == request.resource_url(user, 'profile')
543
544    def test_change_password_get(self, dummy_request, john):
545        request = dummy_request
546        user = john
547        response = user_views.change_password(user, request)
548        assert isinstance(response['form'], OWFormRenderer)
549        # no errors in the form (first load)
550        assert response['form'].errorlist() == ''
551
552    def test_change_password_post_ok(self, passwd_post_request, john):
553        request = passwd_post_request
554        user = john
555        request.POST['old_password'] = 's3cr3t'
556        request.POST['password'] = 'h1dd3n s3cr3t'
557        request.POST['password_confirm'] = 'h1dd3n s3cr3t'
558        response = user_views.change_password(user, request)
559        assert isinstance(response, HTTPFound)
560        assert response.location == request.resource_url(user, 'profile')
561        # password was changed
562        assert not user.check_password('s3cr3t')
563        assert user.check_password('h1dd3n s3cr3t')
564
565    def test_change_password_post_no_values(self, passwd_post_request, john):
566        request = passwd_post_request
567        user = john
568        response = user_views.change_password(user, request)
569        assert isinstance(response['form'], OWFormRenderer)
570        error = u'Please enter a value'
571        html_error = u'<ul class="error">'
572        html_error += ('<li>' + error + '</li>') * 3  # 3 fields
573        html_error += '</ul>'
574        errorlist = response['form'].errorlist().replace('\n', '')
575        assert errorlist == html_error
576        assert response['form'].errors_for('old_password') == [error]
577        assert response['form'].errors_for('password') == [error]
578        assert response['form'].errors_for('password_confirm') == [error]
579        # password was not changed
580        assert user.check_password('s3cr3t')
581
582    def test_change_password_post_bad_old_password(
583            self, passwd_post_request, john):
584        request = passwd_post_request
585        user = john
586        request.POST['old_password'] = 'FAIL PASSWORD'
587        request.POST['password'] = 'h1dd3n s3cr3t'
588        request.POST['password_confirm'] = 'h1dd3n s3cr3t'
589        response = user_views.change_password(user, request)
590        assert isinstance(response['form'], OWFormRenderer)
591        error = u'The given password does not match the existing one '
592        html_error = u'<ul class="error"><li>' + error + '</li></ul>'
593        assert response['form'].errorlist() == html_error
594        assert response['form'].errors_for('old_password') == [error]
595        # password was not changed
596        assert user.check_password('s3cr3t')
597        assert not user.check_password('h1dd3n s3cr3t')
598
599    def test_change_password_post_password_mismatch(
600            self, passwd_post_request, john):
601        request = passwd_post_request
602        user = john
603        request.POST['old_password'] = 's3cr3t'
604        request.POST['password'] = 'h1dd3n s3cr3ts'
605        request.POST['password_confirm'] = 'h1dd3n s3cr3t'
606        response = user_views.change_password(user, request)
607        assert isinstance(response['form'], OWFormRenderer)
608        error = u'Fields do not match'
609        html_error = u'<ul class="error"><li>' + error + '</li></ul>'
610        assert response['form'].errorlist() == html_error
611        assert response['form'].errors_for('password_confirm') == [error]
612        # password was not changed
613        assert user.check_password('s3cr3t')
614        assert not user.check_password('h1dd3n s3cr3t')
615
616    def test_signup_get(self, dummy_request):
617        request = dummy_request
618        response = user_views.signup(request.root, request)
619        assert isinstance(response['form'], OWFormRenderer)
620        # no errors in the form (first load)
621        assert response['form'].errorlist() == ''
622
623    def test_signup_post_ok(self, signup_post_request):
624        request = signup_post_request
625        assert 'jack.black@example.net' not in request.root.emails
626        assert 'JackBlack' not in request.root.all_nicknames
627        response = user_views.signup(request.root, request)
628        assert isinstance(response, HTTPFound)
629        assert response.location == request.resource_url(request.root)
630        assert 'jack.black@example.net' in request.root.emails
631        assert 'JackBlack' in request.root.all_nicknames
632
633    def test_signup_missing_required(self, signup_post_request):
634        request = signup_post_request
635        request.POST['email'] = ''
636        assert 'jack.black@example.net' not in request.root.emails
637        assert 'JackBlack' not in request.root.all_nicknames
638        response = user_views.signup(request.root, request)
639        assert isinstance(response['form'], OWFormRenderer)
640        error = u'Please enter an email address'
641        html_error = '<ul class="error">'
642        html_error += '<li>' + error + '</li>'
643        html_error += '</ul>'
644        errorlist = response['form'].errorlist().replace('\n', '')
645        assert errorlist == html_error
646        assert response['form'].errors_for('email') == [error]
647        assert 'jack.black@example.net' not in request.root.emails
648        assert 'JackBlack' not in request.root.all_nicknames
649
650    def test_signup_existing_nickname(self, signup_post_request, john):
651        request = signup_post_request
652        # assign john a nickname first
653        john.nickname = 'john'
654        # now set it for the POST request
655        request.POST['nickname'] = 'john'
656        # check jack is not there yet
657        assert 'jack.black@example.net' not in request.root.emails
658        assert 'JackBlack' not in request.root.all_nicknames
659        # now signup as jack, but trying to set the nickname 'john'
660        response = user_views.signup(request.root, request)
661        assert isinstance(response['form'], OWFormRenderer)
662        error = u'Another user is already using the nickname john'
663        html_error = '<ul class="error">'
664        html_error += '<li>' + error + '</li>'
665        html_error += '</ul>'
666        errorlist = response['form'].errorlist().replace('\n', '')
667        assert errorlist == html_error
668        assert response['form'].errors_for('nickname') == [error]
669        # all the errors, and jack is not there
670        assert 'jack.black@example.net' not in request.root.emails
671        assert 'JackBlack' not in request.root.all_nicknames
672
673    def test_signup_existing_email(self, signup_post_request):
674        request = signup_post_request
675        request.POST['email'] = 'john.doe@example.net'
676        assert 'jack.black@example.net' not in request.root.emails
677        assert 'JackBlack' not in request.root.all_nicknames
678        response = user_views.signup(request.root, request)
679        assert isinstance(response['form'], OWFormRenderer)
680        error = u'Another user is already registered with the email '
681        error += u'john.doe@example.net'
682        html_error = '<ul class="error">'
683        html_error += '<li>' + error + '</li>'
684        html_error += '</ul>'
685        errorlist = response['form'].errorlist().replace('\n', '')
686        assert errorlist == html_error
687        assert response['form'].errors_for('email') == [error]
688        assert 'jack.black@example.net' not in request.root.emails
689        assert 'JackBlack' not in request.root.all_nicknames
690
691    def test_week_stats_no_stats(self, dummy_request, john):
692        response = user_views.week_stats(john, dummy_request)
693        assert isinstance(response, Response)
694        assert response.content_type == 'application/json'
695        # the body is a valid json-encoded stream
696        obj = json.loads(response.body)
697        assert obj == [
698            {'distance': 0, 'elevation': 0, 'name': 'Mon',
699             'time': '00', 'workouts': 0},
700            {'distance': 0, 'elevation': 0, 'name': 'Tue',
701             'time': '00', 'workouts': 0},
702            {'distance': 0, 'elevation': 0, 'name': 'Wed',
703             'time': '00', 'workouts': 0},
704            {'distance': 0, 'elevation': 0, 'name': 'Thu',
705             'time': '00', 'workouts': 0},
706            {'distance': 0, 'elevation': 0, 'name': 'Fri',
707             'time': '00', 'workouts': 0},
708            {'distance': 0, 'elevation': 0, 'name': 'Sat',
709             'time': '00', 'workouts': 0},
710            {'distance': 0, 'elevation': 0, 'name': 'Sun',
711             'time': '00', 'workouts': 0}
712        ]
713
714    def test_week_stats(self, dummy_request, john):
715        workout = Workout(
716            start=datetime.now(timezone.utc),
717            duration=timedelta(minutes=60),
718            distance=30,
719            elevation=540
720        )
721        john.add_workout(workout)
722        response = user_views.week_stats(john, dummy_request)
723        assert isinstance(response, Response)
724        assert response.content_type == 'application/json'
725        # the body is a valid json-encoded stream
726        obj = json.loads(response.body)
727        assert len(obj) == 7
728        for day in obj:
729            if datetime.now(timezone.utc).strftime('%a') == day['name']:
730                day['distance'] == 30
731                day['elevation'] == 540
732                day['time'] == '01'
733                day['workouts'] == 1
734            else:
735                day['distance'] == 0
736                day['elevation'] == 0
737                day['time'] == '00'
738                day['workouts'] == 0
Note: See TracBrowser for help on using the repository browser.