source: OpenWorkouts-current/ow/tests/models/test_user.py @ 7dc1f81

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

Better str and repr representation for the User model.

This is basically useful for developers using pshell for debugging
purposes, as adding the email address to the repr makes easier
(faster) to spot who a given user object is.

  • Property mode set to 100644
File size: 12.8 KB
Line 
1from decimal import Decimal
2from datetime import datetime, timedelta, timezone
3
4import pytest
5from pyramid.security import Allow, Everyone, Deny, ALL_PERMISSIONS
6
7from ow.models.root import OpenWorkouts
8from ow.models.workout import Workout
9from ow.models.user import User
10
11
12class TestUser(object):
13    @pytest.fixture
14    def root(self):
15        root = OpenWorkouts()
16        root['john'] = User(firstname='John', lastname='Doe',
17                            email='john.doe@example.net')
18        root['john'].password = 's3cr3t'
19        return root
20
21    @pytest.fixture
22    def workouts(self):
23        workouts = [Workout(sport='running'),
24                    Workout(sport='cycling'),
25                    Workout(sport='swimming')]
26        return workouts
27
28    def test_user_attrs(self, root):
29        assert root['john'].firstname == 'John'
30        assert root['john'].lastname == 'Doe'
31        assert root['john'].email == 'john.doe@example.net'
32
33    def test__acl__(self, root):
34        uid = str(root['john'].uid)
35        permissions = [
36            (Allow, uid, 'view'),
37            (Allow, uid, 'edit'),
38            (Deny, Everyone, ALL_PERMISSIONS),
39        ]
40        assert root['john'].__acl__() == permissions
41
42    def test__str__(self, root):
43        email = root['john'].email
44        uid = str(root['john'].uid)
45        assert root['john'].__str__() == u'User: ' + uid + ' (' + email + ')'
46
47    def test__repr__(self, root):
48        email = root['john'].email
49        uid = str(root['john'].uid)
50        expected = u'<ow.models.user.User: ' + uid + ' (' + email + ')>'
51        assert root['john'].__repr__() == expected
52
53    def test_fullname(self, root):
54        assert root['john'].fullname == 'John Doe'
55
56    def test_password_is_encrypted(self, root):
57        assert root['john'].password != 's3cr3t'
58
59    def test_check_wrong_password(self, root):
60        assert not root['john'].check_password('badpass')
61
62    def test_check_good_password(self, root):
63        assert root['john'].check_password('s3cr3t')
64
65    def test_add_workout(self, root, workouts):
66        # First add all workouts at once
67        for workout in workouts:
68            root['john'].add_workout(workout)
69        # Then check they are there, in the correct position/number
70        for workout in workouts:
71            index = workouts.index(workout) + 1
72            assert root['john'][str(index)] == workout
73
74    def test_workouts(self, root, workouts):
75        # First add all workouts at once
76        for workout in workouts:
77            root['john'].add_workout(workout)
78        # workouts() will return the workouts sorted from newest to oldest
79        workouts.reverse()
80        assert list(root['john'].workouts()) == workouts
81        assert list(root['john'].workout_ids()) == ['1', '2', '3']
82        assert root['john'].num_workouts == len(workouts)
83
84    def test_activity_dates_tree(self, root):
85        # first an empty test
86        assert root['john'].activity_dates_tree == {}
87        # now add a cycling workout in a given date (25/11/2018)
88        workout = Workout(
89            start=datetime(2018, 11, 25, 10, 00, tzinfo=timezone.utc),
90            duration=timedelta(minutes=(60*4)),
91            distance=115,
92            sport='cycling')
93        root['john'].add_workout(workout)
94        assert root['john'].activity_dates_tree == {
95            2018: {11: {'cycling': 1}}
96        }
97        # add a running workout on the same date
98        workout = Workout(
99            start=datetime(2018, 11, 25, 16, 30, tzinfo=timezone.utc),
100            duration=timedelta(minutes=60),
101            distance=12,
102            sport='running')
103        root['john'].add_workout(workout)
104        assert root['john'].activity_dates_tree == {
105            2018: {11: {'cycling': 1, 'running': 1}}
106        }
107        # add a swimming workout on a different date, same year
108        workout = Workout(
109            start=datetime(2018, 8, 15, 11, 30, tzinfo=timezone.utc),
110            duration=timedelta(minutes=30),
111            distance=2,
112            sport='swimming')
113        root['john'].add_workout(workout)
114        assert root['john'].activity_dates_tree == {
115            2018: {8: {'swimming': 1},
116                   11: {'cycling': 1, 'running': 1}}
117        }
118        # now add some more cycling in a different year
119        # add a swimming workout on a different date, same year
120        workout = Workout(
121            start=datetime(2017, 4, 15, 15, 00, tzinfo=timezone.utc),
122            duration=timedelta(minutes=(60*3)),
123            distance=78,
124            sport='cycling')
125        root['john'].add_workout(workout)
126        assert root['john'].activity_dates_tree == {
127            2017: {4: {'cycling': 1}},
128            2018: {8: {'swimming': 1},
129                   11: {'cycling': 1, 'running': 1}}
130        }
131
132    def test_stats(self, root):
133        expected_no_stats = {
134            'workouts': 0,
135            'time': timedelta(seconds=0),
136            'distance': Decimal(0),
137            'elevation': Decimal(0),
138            'sports': {}
139        }
140        # no stats
141        assert root['john'].stats() == expected_no_stats
142        # add a cycling workout
143        workout = Workout(
144            start=datetime(2018, 11, 25, 10, 00, tzinfo=timezone.utc),
145            duration=timedelta(minutes=(60*4)),
146            distance=115,
147            sport='cycling')
148        root['john'].add_workout(workout)
149        # asking for a different year, future
150        assert root['john'].stats(2019) == expected_no_stats
151        # asking for a different year, past
152        assert root['john'].stats(2016) == expected_no_stats
153        # asking fot the year the workout is in
154        assert root['john'].stats(2018) == {
155            'workouts': 1,
156            'time': timedelta(minutes=(60*4)),
157            'distance': Decimal(115),
158            'elevation': Decimal(0),
159            'sports': {
160                'cycling': {
161                    'workouts': 1,
162                    'time': timedelta(minutes=(60*4)),
163                    'distance': Decimal(115),
164                    'elevation': Decimal(0),
165                }
166            }
167        }
168        # add a second cycling workout
169        workout = Workout(
170            start=datetime(2018, 11, 26, 10, 00, tzinfo=timezone.utc),
171            duration=timedelta(minutes=(60*3)),
172            distance=100,
173            sport='cycling')
174        root['john'].add_workout(workout)
175        assert root['john'].stats(2018) == {
176            'workouts': 2,
177            'time': timedelta(minutes=(60*7)),
178            'distance': Decimal(215),
179            'elevation': Decimal(0),
180            'sports': {
181                'cycling': {
182                    'workouts': 2,
183                    'time': timedelta(minutes=(60*7)),
184                    'distance': Decimal(215),
185                    'elevation': Decimal(0),
186                }
187            }
188        }
189        # add a running workout
190        workout = Workout(
191            start=datetime(2018, 11, 26, 16, 00, tzinfo=timezone.utc),
192            duration=timedelta(minutes=(60)),
193            distance=10,
194            sport='running')
195        root['john'].add_workout(workout)
196        assert root['john'].stats(2018) == {
197            'workouts': 3,
198            'time': timedelta(minutes=(60*8)),
199            'distance': Decimal(225),
200            'elevation': Decimal(0),
201            'sports': {
202                'cycling': {
203                    'workouts': 2,
204                    'time': timedelta(minutes=(60*7)),
205                    'distance': Decimal(215),
206                    'elevation': Decimal(0),
207                },
208                'running': {
209                    'workouts': 1,
210                    'time': timedelta(minutes=(60)),
211                    'distance': Decimal(10),
212                    'elevation': Decimal(0),
213                }
214            }
215        }
216        # ensure the stats for future/past years did not change after
217        # adding those workouts
218        assert root['john'].stats(2019) == expected_no_stats
219        assert root['john'].stats(2016) == expected_no_stats
220
221    def test_get_week_stats(self, root):
222        expected_no_stats_per_day = {
223            'workouts': 0,
224            'time': timedelta(0),
225            'distance': Decimal(0),
226            'elevation': Decimal(0),
227            'sports': {}
228        }
229
230        expected_no_stats = {}
231        for i in range(19, 26):
232            day = datetime(2018, 11, i, 10, 00, tzinfo=timezone.utc)
233            expected_no_stats[day] = expected_no_stats_per_day
234
235        day = datetime(2018, 11, 25, 10, 00, tzinfo=timezone.utc)
236        assert root['john'].get_week_stats(day) == expected_no_stats
237
238        # add a cycling workout
239        workout = Workout(
240            start=datetime(2018, 11, 25, 10, 00, tzinfo=timezone.utc),
241            duration=timedelta(minutes=(60*4)),
242            distance=115,
243            sport='cycling')
244        root['john'].add_workout(workout)
245
246        # check a week in the future
247        day = datetime(2019, 11, 25, 10, 00, tzinfo=timezone.utc)
248        week_stats = root['john'].get_week_stats(day)
249        for day in week_stats:
250            assert week_stats[day] == expected_no_stats_per_day
251
252        # check a week in the past
253        day = datetime(2017, 11, 25, 10, 00, tzinfo=timezone.utc)
254        week_stats = root['john'].get_week_stats(day)
255        for day in week_stats:
256            assert week_stats[day] == expected_no_stats_per_day
257
258        # Check the week where the workout is
259        day = datetime(2018, 11, 25, 10, 00, tzinfo=timezone.utc)
260        week_stats = root['john'].get_week_stats(day)
261        for day in week_stats:
262            if day.day == 25:
263                # this is the day where we have a workout
264                assert week_stats[day] == {
265                    'workouts': 1,
266                    'time': timedelta(minutes=(60*4)),
267                    'distance': Decimal(115),
268                    'elevation': Decimal(0),
269                    'sports': {
270                        'cycling': {
271                            'workouts': 1,
272                            'time': timedelta(minutes=(60*4)),
273                            'distance': Decimal(115),
274                            'elevation': Decimal(0)
275                        }
276                    }
277                }
278            else:
279                # day without workout
280                assert week_stats[day] == expected_no_stats_per_day
281
282        # add a second cycling workout
283        workout = Workout(
284            start=datetime(2018, 11, 23, 10, 00, tzinfo=timezone.utc),
285            duration=timedelta(minutes=(60*3)),
286            distance=100,
287            sport='cycling')
288        root['john'].add_workout(workout)
289        day = datetime(2018, 11, 25, 10, 00, tzinfo=timezone.utc)
290        week_stats = root['john'].get_week_stats(day)
291        for day in week_stats:
292            if day.day == 25:
293                # this is the day where we have a workout
294                assert week_stats[day] == {
295                    'workouts': 1,
296                    'time': timedelta(minutes=(60*4)),
297                    'distance': Decimal(115),
298                    'elevation': Decimal(0),
299                    'sports': {
300                        'cycling': {
301                            'workouts': 1,
302                            'time': timedelta(minutes=(60*4)),
303                            'distance': Decimal(115),
304                            'elevation': Decimal(0)
305                        }
306                    }
307                }
308            elif day.day == 23:
309                # this is the day where we have a workout
310                assert week_stats[day] == {
311                    'workouts': 1,
312                    'time': timedelta(minutes=(60*3)),
313                    'distance': Decimal(100),
314                    'elevation': Decimal(0),
315                    'sports': {
316                        'cycling': {
317                            'workouts': 1,
318                            'time': timedelta(minutes=(60*3)),
319                            'distance': Decimal(100),
320                            'elevation': Decimal(0)
321                        }
322                    }
323                }
324            else:
325                # day without workout
326                assert week_stats[day] == expected_no_stats_per_day
327
328    def test_week_stats(self, root):
329        expected_no_stats_per_day = {
330            'workouts': 0,
331            'time': timedelta(0),
332            'distance': Decimal(0),
333            'elevation': Decimal(0),
334            'sports': {}
335        }
336
337        # no workouts for the current week (this tests is for coverage
338        # purposes mostly, as the main logic is tested in test_get_week_stats)
339        day = datetime.now(timezone.utc)
340        week_stats = root['john'].get_week_stats(day)
341        for day in week_stats:
342            assert week_stats[day] == expected_no_stats_per_day
343
344    def test_week_totals(self, root):
345        # no data, empty totals
346        assert root['john'].week_totals == {
347            'distance': Decimal(0),
348            'time': timedelta(0)
349        }
Note: See TracBrowser for help on using the repository browser.