Projet

Général

Profil

0001-misc-fix-flake8-errors-29209.patch

Lauréline Guérin, 12 décembre 2019 10:57

Télécharger (48,7 ko)

Voir les différences:

Subject: [PATCH 1/4] misc: fix flake8 errors (#29209)

 chrono/agendas/models.py |  54 +++++----
 tests/test_agendas.py    |  44 +++++--
 tests/test_manager.py    | 246 +++++++++++++++++++++++++--------------
 3 files changed, 225 insertions(+), 119 deletions(-)
chrono/agendas/models.py
74 74
    minimal_booking_delay = models.PositiveIntegerField(
75 75
            _('Minimal booking delay (in days)'), default=1)
76 76
    maximal_booking_delay = models.PositiveIntegerField(
77
            _('Maximal booking delay (in days)'), default=56) # eight weeks
78
    edit_role = models.ForeignKey(Group, blank=True, null=True, default=None,
79
            related_name='+', verbose_name=_('Edit Role'),
80
            on_delete=models.SET_NULL)
81
    view_role = models.ForeignKey(Group, blank=True, null=True, default=None,
82
            related_name='+', verbose_name=_('View Role'),
83
            on_delete=models.SET_NULL)
77
            _('Maximal booking delay (in days)'), default=56)  # eight weeks
78
    edit_role = models.ForeignKey(
79
        Group, blank=True, null=True, default=None,
80
        related_name='+', verbose_name=_('Edit Role'),
81
        on_delete=models.SET_NULL)
82
    view_role = models.ForeignKey(
83
        Group, blank=True, null=True, default=None,
84
        related_name='+', verbose_name=_('View Role'),
85
        on_delete=models.SET_NULL)
84 86

  
85 87
    class Meta:
86 88
        ordering = ['label']
......
170 172
                Desk.import_json(desk).save()
171 173
        return created
172 174

  
175

  
173 176
WEEKDAYS_LIST = sorted(WEEKDAYS.items(), key=lambda x: x[0])
174 177

  
175 178

  
......
228 231
        if real_min_datetime < min_datetime:
229 232
            real_min_datetime += datetime.timedelta(days=7)
230 233

  
231
        event_datetime = real_min_datetime.replace(hour=self.start_time.hour,
232
                minute=self.start_time.minute, second=0, microsecond=0)
234
        event_datetime = real_min_datetime.replace(
235
            hour=self.start_time.hour,
236
            minute=self.start_time.minute, second=0, microsecond=0)
233 237
        while event_datetime < max_datetime:
234 238
            end_time = event_datetime + meeting_duration
235 239
            next_time = event_datetime + duration
......
286 290
    places = models.PositiveIntegerField(_('Places'))
287 291
    waiting_list_places = models.PositiveIntegerField(
288 292
            _('Places in waiting list'), default=0)
289
    label = models.CharField(_('Label'), max_length=150, null=True, blank=True,
290
            help_text=_('Optional label to identify this date.'))
293
    label = models.CharField(
294
        _('Label'), max_length=150, null=True, blank=True,
295
        help_text=_('Optional label to identify this date.'))
291 296
    slug = models.SlugField(_('Identifier'), max_length=160, null=True, blank=True, default=None)
292
    description = models.TextField(_('Description'), null=True, blank=True,
293
            help_text=_('Optional event description.'))
297
    description = models.TextField(
298
        _('Description'), null=True, blank=True,
299
        help_text=_('Optional event description.'))
294 300
    full = models.BooleanField(default=False)
295 301
    meeting_type = models.ForeignKey(MeetingType, null=True, on_delete=models.CASCADE)
296 302
    desk = models.ForeignKey('Desk', null=True, on_delete=models.CASCADE)
......
327 333

  
328 334
    @property
329 335
    def booked_places(self):
330
        return self.booking_set.filter(cancellation_datetime__isnull=True,
331
                in_waiting_list=False).count()
336
        return self.booking_set.filter(
337
            cancellation_datetime__isnull=True,
338
            in_waiting_list=False).count()
332 339

  
333 340
    @property
334 341
    def waiting_list(self):
335
        return self.booking_set.filter(cancellation_datetime__isnull=True,
336
                in_waiting_list=True).count()
342
        return self.booking_set.filter(
343
            cancellation_datetime__isnull=True,
344
            in_waiting_list=True).count()
337 345

  
338 346
    @property
339 347
    def end_datetime(self):
......
372 380
    in_waiting_list = models.BooleanField(default=False)
373 381
    creation_datetime = models.DateTimeField(auto_now_add=True)
374 382
    # primary booking is used to group multiple bookings together
375
    primary_booking = models.ForeignKey('self', null=True,
376
            on_delete=models.CASCADE, related_name='secondary_booking_set')
383
    primary_booking = models.ForeignKey(
384
        'self', null=True,
385
        on_delete=models.CASCADE, related_name='secondary_booking_set')
377 386

  
378 387
    label = models.CharField(max_length=250, blank=True)
379 388
    user_display_label = models.CharField(verbose_name=_('Label displayed to user'), max_length=250, blank=True)
......
422 431
        return ics.serialize()
423 432

  
424 433

  
425

  
426 434
@python_2_unicode_compatible
427 435
class Desk(models.Model):
428 436
    agenda = models.ForeignKey(Agenda, on_delete=models.CASCADE)
......
591 599

  
592 600
            if keep_synced_by_uid:
593 601
                # delete all outdated exceptions from remote calendar
594
                TimePeriodException.objects.filter(update_datetime__lt=update_datetime,
595
                                    desk=self).exclude(external_id='').delete()
602
                TimePeriodException.objects.filter(
603
                    update_datetime__lt=update_datetime,
604
                    desk=self
605
                ).exclude(external_id='').delete()
596 606

  
597 607
        return total_created
598 608

  
tests/test_agendas.py
8 8
from django.utils.timezone import now, make_aware, localtime
9 9
from django.contrib.auth.models import Group
10 10
from django.core.management import call_command
11
from django.core.management.base import CommandError
12 11

  
13
from chrono.agendas.models import (Agenda, Event, Booking, MeetingType,
14
                        Desk, TimePeriod, TimePeriodException, ICSError)
12
from chrono.agendas.models import (
13
    Agenda, Event, Booking, MeetingType,
14
    Desk, TimePeriodException, ICSError)
15 15

  
16 16
pytestmark = pytest.mark.django_db
17 17

  
......
154 154
    booking.save()
155 155
    assert Event.objects.all()[0].booked_places == 0
156 156

  
157

  
157 158
def test_event_bookable_period():
158 159
    agenda = Agenda(label=u'Foo bar')
159 160
    agenda.save()
......
179 180
    event.save()
180 181
    assert event.in_bookable_period() is False
181 182

  
183

  
182 184
def test_meeting_type_slugs():
183 185
    agenda1 = Agenda(label=u'Foo bar')
184 186
    agenda1.save()
......
197 199
    meeting_type3.save()
198 200
    assert meeting_type3.slug == 'baz'
199 201

  
202

  
200 203
def test_timeperiodexception_creation_from_ics():
201 204
    agenda = Agenda(label=u'Test 1 agenda')
202 205
    agenda.save()
......
206 209
    assert exceptions_count == 2
207 210
    assert TimePeriodException.objects.filter(desk=desk).count() == 2
208 211

  
212

  
209 213
def test_timeperiodexception_creation_from_ics_without_startdt():
210 214
    agenda = Agenda(label=u'Test 2 agenda')
211 215
    agenda.save()
......
219 223
        lines.append(line)
220 224
    ics_sample = "\n".join(lines)
221 225
    with pytest.raises(ICSError) as e:
222
        exceptions_count = desk.create_timeperiod_exceptions_from_ics(ics_sample)
226
        desk.create_timeperiod_exceptions_from_ics(ics_sample)
223 227
    assert 'Event "Event 1" has no start date.' == str(e.value)
224 228

  
229

  
225 230
def test_timeperiodexception_creation_from_ics_without_enddt():
226 231
    agenda = Agenda(label=u'Test 3 agenda')
227 232
    agenda.save()
......
234 239
            continue
235 240
        lines.append(line)
236 241
    ics_sample = "\n".join(lines)
237
    exceptions_count = desk.create_timeperiod_exceptions_from_ics(ics_sample)
242
    desk.create_timeperiod_exceptions_from_ics(ics_sample)
238 243
    for exception in TimePeriodException.objects.filter(desk=desk):
239 244
        end_time = localtime(exception.end_datetime).time()
240 245
        assert end_time == datetime.time(23, 59, 59, 999999)
......
257 262
    assert set(TimePeriodException.objects.values_list('start_datetime', flat=True)) == set([
258 263
        make_aware(datetime.datetime(2018, 1, 1)), make_aware(datetime.datetime(2018, 1, 2))])
259 264

  
265

  
260 266
def test_timeexception_creation_from_ics_with_dates():
261 267
    agenda = Agenda(label=u'Test 5 agenda')
262 268
    agenda.save()
......
275 281
        assert localtime(exception.start_datetime) == make_aware(datetime.datetime(2018, 1, 1, 0, 0))
276 282
        assert localtime(exception.end_datetime) == make_aware(datetime.datetime(2018, 1, 1, 0, 0))
277 283

  
284

  
278 285
def test_timeexception_create_from_invalid_ics():
279 286
    agenda = Agenda(label=u'Test 6 agenda')
280 287
    agenda.save()
281 288
    desk = Desk(label='Test 6 desk', agenda=agenda)
282 289
    desk.save()
283 290
    with pytest.raises(ICSError) as e:
284
        exceptions_count = desk.create_timeperiod_exceptions_from_ics(INVALID_ICS_SAMPLE)
291
        desk.create_timeperiod_exceptions_from_ics(INVALID_ICS_SAMPLE)
285 292
    assert str(e.value) == 'File format is invalid.'
286 293

  
294

  
287 295
def test_timeexception_create_from_ics_with_no_events():
288 296
    agenda = Agenda(label=u'Test 7 agenda')
289 297
    agenda.save()
290 298
    desk = Desk(label='Test 7 desk', agenda=agenda)
291 299
    desk.save()
292 300
    with pytest.raises(ICSError) as e:
293
        exceptions_count = desk.create_timeperiod_exceptions_from_ics(ICS_SAMPLE_WITH_NO_EVENTS)
301
        desk.create_timeperiod_exceptions_from_ics(ICS_SAMPLE_WITH_NO_EVENTS)
294 302
    assert str(e.value) == "The file doesn't contain any events."
295 303

  
304

  
296 305
@mock.patch('chrono.agendas.models.requests.get')
297 306
def test_timeperiodexception_creation_from_remote_ics(mocked_get):
298 307
    agenda = Agenda(label=u'Test 8 agenda')
......
304 313
    mocked_get.return_value = mocked_response
305 314
    exceptions_count = desk.create_timeperiod_exceptions_from_remote_ics('http://example.com/sample.ics')
306 315
    assert exceptions_count == 2
307
    mocked_response.text = re.sub('SUMMARY:\w+', 'SUMMARY:New summmary', ICS_SAMPLE, re.MULTILINE)
316
    mocked_response.text = re.sub(r'SUMMARY:\w+', 'SUMMARY:New summmary', ICS_SAMPLE, re.MULTILINE)
308 317
    mocked_get.return_value = mocked_response
309 318
    desk.create_timeperiod_exceptions_from_remote_ics('http://example.com/sample.ics')
310 319
    for timeperiod in TimePeriodException.objects.filter(external_id='desk-%s:' % desk.id, desk=desk):
......
316 325
    assert exceptions_count == 0
317 326
    TimePeriodException.objects.filter(external_id='desk-%s:' % desk.id).count() == 0
318 327

  
328

  
319 329
@mock.patch('chrono.agendas.models.requests.get')
320 330
def test_timeperiodexception_creation_from_unreachable_remote_ics(mocked_get):
321 331
    agenda = Agenda(label=u'Test 9 agenda')
......
325 335
    mocked_response = mock.Mock()
326 336
    mocked_response.text = ICS_SAMPLE
327 337
    mocked_get.return_value = mocked_response
338

  
328 339
    def mocked_requests_connection_error(*args, **kwargs):
329 340
        raise requests.ConnectionError('unreachable')
341

  
330 342
    mocked_get.side_effect = mocked_requests_connection_error
331 343
    with pytest.raises(ICSError) as e:
332
        exceptions_count = desk.create_timeperiod_exceptions_from_remote_ics('http://example.com/sample.ics')
344
        desk.create_timeperiod_exceptions_from_remote_ics('http://example.com/sample.ics')
333 345
    assert str(e.value) == "Failed to retrieve remote calendar (http://example.com/sample.ics, unreachable)."
334 346

  
347

  
335 348
@mock.patch('chrono.agendas.models.requests.get')
336 349
def test_timeperiodexception_creation_from_forbidden_remote_ics(mocked_get):
337 350
    agenda = Agenda(label=u'Test 10 agenda')
......
341 354
    mocked_response = mock.Mock()
342 355
    mocked_response.status_code = 403
343 356
    mocked_get.return_value = mocked_response
357

  
344 358
    def mocked_requests_http_forbidden_error(*args, **kwargs):
345 359
        raise requests.HTTPError(response=mocked_response)
360

  
346 361
    mocked_get.side_effect = mocked_requests_http_forbidden_error
347 362

  
348 363
    with pytest.raises(ICSError) as e:
349
        exceptions_count = desk.create_timeperiod_exceptions_from_remote_ics('http://example.com/sample.ics')
364
        desk.create_timeperiod_exceptions_from_remote_ics('http://example.com/sample.ics')
350 365
    assert str(e.value) == "Failed to retrieve remote calendar (http://example.com/sample.ics, HTTP error 403)."
351 366

  
367

  
352 368
@mock.patch('chrono.agendas.models.requests.get')
353 369
def test_sync_desks_timeperiod_exceptions_from_ics(mocked_get, capsys):
354 370
    agenda = Agenda(label=u'Test 11 agenda')
......
358 374
    mocked_response = mock.Mock()
359 375
    mocked_response.status_code = 403
360 376
    mocked_get.return_value = mocked_response
377

  
361 378
    def mocked_requests_http_forbidden_error(*args, **kwargs):
362 379
        raise requests.HTTPError(response=mocked_response)
380

  
363 381
    mocked_get.side_effect = mocked_requests_http_forbidden_error
364 382
    call_command('sync_desks_timeperiod_exceptions')
365 383
    out, err = capsys.readouterr()
366
    assert err == 'unable to create timeperiod exceptions for "Test 11 desk": Failed to retrieve remote calendar (http://example.com/sample.ics, HTTP error 403).\n'
384
    assert err == (
385
        'unable to create timeperiod exceptions for "Test 11 desk": '
386
        'Failed to retrieve remote calendar (http://example.com/sample.ics, HTTP error 403).\n')
387

  
367 388

  
368 389
@mock.patch('chrono.agendas.models.requests.get')
369 390
def test_sync_desks_timeperiod_exceptions_from_changing_ics(mocked_get, caplog):
......
397 418
    call_command('sync_desks_timeperiod_exceptions')
398 419
    assert not TimePeriodException.objects.filter(desk=desk).exists()
399 420

  
421

  
400 422
def test_base_meeting_duration():
401 423
    agenda = Agenda(label='Meeting', kind='meetings')
402 424
    agenda.save()
tests/test_manager.py
14 14
import requests
15 15
from webtest import Upload
16 16

  
17
from chrono.wsgi import application
18

  
19 17
from chrono.agendas.models import (Agenda, Event, Booking, MeetingType,
20 18
                                   TimePeriod, Desk, TimePeriodException)
21
from chrono.manager.utils import export_site
22 19

  
23 20
pytestmark = pytest.mark.django_db
24 21

  
22

  
25 23
@pytest.fixture
26 24
def simple_user():
27 25
    try:
......
30 28
        user = User.objects.create_user('user', password='user')
31 29
    return user
32 30

  
31

  
33 32
@pytest.fixture
34 33
def manager_user():
35 34
    try:
......
42 41
    user.groups.set([group])
43 42
    return user
44 43

  
44

  
45 45
@pytest.fixture
46 46
def admin_user():
47 47
    try:
......
50 50
        user = User.objects.create_superuser('admin', email=None, password='admin')
51 51
    return user
52 52

  
53

  
53 54
@pytest.fixture
54 55
def api_user():
55 56
    try:
56 57
        user = User.objects.get(username='api-user')
57 58
    except User.DoesNotExist:
58
        user = User.objects.create(username='john.doe',
59
                first_name=u'John', last_name=u'Doe', email='john.doe@example.net')
59
        user = User.objects.create(
60
            username='john.doe',
61
            first_name=u'John', last_name=u'Doe', email='john.doe@example.net')
60 62
        user.set_password('password')
61 63
        user.save()
62 64
    return user
63 65

  
66

  
64 67
def login(app, username='admin', password='admin'):
65 68
    login_page = app.get('/login/')
66 69
    login_form = login_page.forms[0]
......
70 73
    assert resp.status_int == 302
71 74
    return app
72 75

  
76

  
73 77
def test_unlogged_access(app):
74 78
    # connect while not being logged in
75 79
    assert app.get('/manage/', status=302).location.endswith('/login/?next=/manage/')
76 80

  
81

  
77 82
def test_simple_user_access(app, simple_user):
78 83
    # connect while being logged as a simple user, access should be forbidden
79 84
    app = login(app, username='user', password='user')
80 85
    assert app.get('/manage/', status=403)
81 86

  
87

  
82 88
def test_manager_user_access(app, manager_user):
83 89
    # connect while being logged as a manager user, access should be granted if
84 90
    # there's at least an agenda that is viewable or editable.
......
99 105
    agenda.save()
100 106
    assert app.get('/manage/', status=200)
101 107

  
108

  
102 109
def test_home_redirect(app):
103 110
    assert app.get('/', status=302).location.endswith('/manage/')
104 111

  
112

  
105 113
def test_access(app, admin_user):
106 114
    app = login(app)
107 115
    resp = app.get('/manage/', status=200)
108 116
    assert '<h2>Agendas</h2>' in resp.text
109 117
    assert "This site doesn't have any agenda yet." in resp.text
110 118

  
119

  
111 120
def test_logout(app, admin_user):
112 121
    app = login(app)
113 122
    app.get('/logout/')
114 123
    assert app.get('/manage/', status=302).location.endswith('/login/?next=/manage/')
115 124

  
125

  
116 126
def test_menu_json(app, admin_user):
117 127
    app = login(app)
118 128
    resp = app.get('/manage/menu.json', status=200)
......
123 133
    assert resp2.text == 'Q(%s);' % resp.text
124 134
    assert resp2.content_type == 'application/javascript'
125 135

  
136

  
126 137
def test_view_agendas_as_manager(app, manager_user):
127 138
    agenda = Agenda(label=u'Foo Bar')
128 139
    agenda.view_role = manager_user.groups.all()[0]
......
143 154
    # check view gives access to the settings page for "events" agenda
144 155
    resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
145 156
    # but there's no links to actions
146
    assert not '>New Event<' in resp.text
147
    assert not '>Options<' in resp.text
157
    assert '>New Event<' not in resp.text
158
    assert '>Options<' not in resp.text
148 159
    app.get('/manage/agendas/%s/add-event' % agenda.id, status=403)
149 160
    app.get('/manage/agendas/%s/edit' % agenda.id, status=403)
150 161

  
......
156 167
    # check it gives a 404 on unknown agendas
157 168
    resp = app.get('/manage/agendas/%s/settings' % '9999', status=404)
158 169

  
170

  
159 171
def test_add_agenda(app, admin_user):
160 172
    app = login(app)
161 173
    resp = app.get('/manage/', status=200)
......
169 181
    assert 'Foo bar' in resp.text
170 182
    assert '<h2>Settings' in resp.text
171 183

  
184

  
172 185
def test_add_agenda_as_manager(app, manager_user):
173 186
    # open /manage/ access to manager_user, and check agenda creation is not
174 187
    # allowed.
......
176 189
    agenda.view_role = manager_user.groups.all()[0]
177 190
    agenda.save()
178 191
    app = login(app, username='manager', password='manager')
179
    resp = app.get('/manage/', status=200)
180
    resp = app.get('/manage/agendas/add/', status=403)
192
    app.get('/manage/', status=200)
193
    app.get('/manage/agendas/add/', status=403)
194

  
181 195

  
182 196
def test_options_agenda(app, admin_user):
183 197
    agenda = Agenda(label=u'Foo bar')
......
194 208
    assert 'Foo baz' in resp.text
195 209
    assert '<h2>Settings' in resp.text
196 210

  
211

  
197 212
def test_options_agenda_as_manager(app, manager_user):
198 213
    agenda = Agenda(label=u'Foo bar')
199 214
    agenda.view_role = manager_user.groups.all()[0]
......
201 216
    app = login(app, username='manager', password='manager')
202 217
    resp = app.get('/manage/', status=200)
203 218
    resp = resp.click('Foo bar')
204
    assert not 'Settings' in resp.text
219
    assert 'Settings' not in resp.text
205 220
    resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)  # ok for "events" agendas
206 221
    resp = app.get('/manage/agendas/%s/edit' % agenda.id, status=403)
207 222
    agenda.kind = 'meetings'
......
227 242
    assert 'Foo baz' in resp.text
228 243
    assert '<h2>Settings' in resp.text
229 244

  
245

  
230 246
def test_delete_agenda(app, admin_user):
231 247
    agenda = Agenda(label=u'Foo bar')
232 248
    agenda.save()
......
237 253
    resp = resp.form.submit()
238 254
    assert resp.location.endswith('/manage/')
239 255
    resp = resp.follow()
240
    assert not 'Foo bar' in resp.text
256
    assert 'Foo bar' not in resp.text
257

  
241 258

  
242 259
def test_delete_busy_agenda(app, admin_user):
243 260
    agenda = Agenda(label=u'Foo bar')
......
272 289
    booking.save()
273 290
    resp = resp.form.submit(status=403)
274 291

  
292

  
275 293
def test_delete_agenda_as_manager(app, manager_user):
276 294
    agenda = Agenda(label=u'Foo bar')
277 295
    agenda.edit_role = manager_user.groups.all()[0]
......
288 306
    agenda = Agenda(label=u'Foo bar', kind='meetings')
289 307
    agenda.save()
290 308
    desk_a = Desk.objects.create(agenda=agenda, label='Desk A')
291
    desk_b = Desk.objects.create(agenda=agenda, label='Desk B')
309
    Desk.objects.create(agenda=agenda, label='Desk B')
292 310

  
293 311
    event = Event(start_datetime=now() + datetime.timedelta(days=10),
294 312
                  places=10, agenda=agenda, desk=desk_a)
......
329 347
    resp = resp.follow()
330 348
    event = Event.objects.get(places=10)
331 349
    assert event.slug is None
332
    assert not "This agenda doesn't have any event yet." in resp.text
350
    assert "This agenda doesn't have any event yet." not in resp.text
333 351
    assert '/manage/events/%s/' % event.id in resp.text
334 352
    assert ('Feb. 15, %s, 5 p.m.' % year) in resp.text
335 353
    assert '10 places' in resp.text
......
354 372
    app = login(app)
355 373
    app.get('/manage/agendas/%s/add-event' % '999', status=404)
356 374

  
375

  
357 376
def test_add_event_as_manager(app, manager_user):
358 377
    agenda = Agenda(label=u'Foo bar')
359 378
    agenda.view_role = manager_user.groups.all()[0]
......
373 392
    resp = resp.form.submit()
374 393
    resp = resp.follow()
375 394
    event = Event.objects.get(places=10)
376
    assert not "This agenda doesn't have any event yet." in resp.text
395
    assert "This agenda doesn't have any event yet." not in resp.text
377 396
    assert '/manage/events/%s/' % event.id in resp.text
378 397
    assert 'Feb. 15, 2016, 5 p.m.' in resp.text
379 398
    assert '10 places' in resp.text
380 399

  
400

  
381 401
def test_edit_event(app, admin_user):
382 402
    agenda = Agenda(label=u'Foo bar')
383 403
    agenda.save()
......
397 417
    assert 'Feb. 16, 2016, 5 p.m.' in resp.text
398 418
    assert '20 places' in resp.text
399 419

  
420

  
400 421
def test_edit_missing_event(app, admin_user):
401 422
    app = login(app)
402 423
    app.get('/manage/agendas/999/', status=404)
403 424

  
425

  
404 426
def test_edit_event_as_manager(app, manager_user):
405 427
    agenda = Agenda(label=u'Foo bar')
406 428
    agenda.view_role = manager_user.groups.all()[0]
......
424 446
    assert 'Feb. 16, 2016, 5 p.m.' in resp.text
425 447
    assert '20 places' in resp.text
426 448

  
449

  
427 450
def test_booked_places(app, admin_user):
428 451
    agenda = Agenda(label=u'Foo bar')
429 452
    agenda.save()
......
437 460
    assert '10 places' in resp.text
438 461
    assert '2 booked places' in resp.text
439 462

  
463

  
440 464
def test_event_classes(app, admin_user):
441 465
    agenda = Agenda(label=u'Foo bar')
442 466
    agenda.save()
......
448 472
    app = login(app)
449 473

  
450 474
    resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
451
    assert not 'full' in resp.text
452
    assert not 'overbooking' in resp.text
475
    assert 'full' not in resp.text
476
    assert 'overbooking' not in resp.text
453 477

  
454 478
    for i in range(8):
455 479
        Booking(event=event).save()
456 480

  
457 481
    resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
458 482
    assert 'full' in resp.text
459
    assert not 'overbooking' in resp.text
483
    assert 'overbooking' not in resp.text
460 484

  
461 485
    Booking(event=event).save()
462 486
    resp = app.get('/manage/agendas/%s/settings' % agenda.id, status=200)
463 487
    assert 'full' in resp.text
464 488
    assert 'overbooking' in resp.text
465 489

  
490

  
466 491
def test_delete_event(app, admin_user):
467 492
    agenda = Agenda(label=u'Foo bar')
468 493
    agenda.save()
......
478 503
    assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
479 504
    assert Event.objects.count() == 0
480 505

  
506

  
481 507
def test_delete_busy_event(app, admin_user):
482 508
    agenda = Agenda(label=u'Foo bar')
483 509
    agenda.save()
......
511 537
    booking.save()
512 538
    resp = resp.form.submit(status=403)
513 539

  
540

  
514 541
def test_delete_event_as_manager(app, manager_user):
515 542
    agenda = Agenda(label=u'Foo bar')
516 543
    agenda.edit_role = manager_user.groups.all()[0]
......
527 554
    assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
528 555
    assert Event.objects.count() == 0
529 556

  
557

  
530 558
def test_import_events(app, admin_user):
531 559
    agenda = Agenda(label=u'Foo bar')
532 560
    agenda.save()
......
590 618
    Event.objects.all().delete()
591 619

  
592 620
    resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
593
    resp.form['events_csv_file'] = Upload('t.csv',
594
            u'2016-09-16,18:00,10,5,éléphant'.encode('utf-8'), 'text/csv')
621
    resp.form['events_csv_file'] = Upload(
622
        't.csv',
623
        u'2016-09-16,18:00,10,5,éléphant'.encode('utf-8'), 'text/csv')
595 624
    resp = resp.form.submit(status=302)
596 625
    assert Event.objects.count() == 1
597 626
    assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
......
601 630
    Event.objects.all().delete()
602 631

  
603 632
    resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
604
    resp.form['events_csv_file'] = Upload('t.csv',
605
            u'2016-09-16,18:00,10,5,éléphant'.encode('iso-8859-15'), 'text/csv')
633
    resp.form['events_csv_file'] = Upload(
634
        't.csv',
635
        u'2016-09-16,18:00,10,5,éléphant'.encode('iso-8859-15'), 'text/csv')
606 636
    resp = resp.form.submit(status=302)
607 637
    assert Event.objects.count() == 1
608 638
    assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
......
612 642
    Event.objects.all().delete()
613 643

  
614 644
    resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
615
    resp.form['events_csv_file'] = Upload('t.csv',
616
            u'2016-09-16,18:00,10,5,éléphant'.encode('eucjp'), 'text/csv')
645
    resp.form['events_csv_file'] = Upload(
646
        't.csv',
647
        u'2016-09-16,18:00,10,5,éléphant'.encode('eucjp'), 'text/csv')
617 648
    resp = resp.form.submit(status=302)
618 649
    assert Event.objects.count() == 1
619 650
    assert Event.objects.all()[0].start_datetime == make_aware(datetime.datetime(2016, 9, 16, 18, 0))
......
623 654
    Event.objects.all().delete()
624 655

  
625 656
    resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
626
    resp.form['events_csv_file'] = Upload('t.csv', b'date,time,etc.\n'
627
                                                   b'2016-09-16,18:00,10,5,bla bla bla\n'
628
                                                   b'\n'
629
                                                   b'2016-09-19,18:00,10', 'text/csv')
657
    resp.form['events_csv_file'] = Upload(
658
        't.csv',
659
        b'date,time,etc.\n'
660
        b'2016-09-16,18:00,10,5,bla bla bla\n'
661
        b'\n'
662
        b'2016-09-19,18:00,10', 'text/csv')
630 663
    resp = resp.form.submit(status=302)
631 664
    assert Event.objects.count() == 2
632 665
    Event.objects.all().delete()
633 666

  
634 667
    resp = app.get('/manage/agendas/%s/import-events' % agenda.id, status=200)
635
    resp.form['events_csv_file'] = Upload('t.csv', '"date"\t"time"\t"etc."\n'
636
                                                   '"2016-09-16"\t"18:00"\t"10"\t"5"\t"éléphant"\n'
637
                                                   '"2016-09-19"\t"18:00"\t"10"'.encode('iso-8859-15'), 'text/csv')
668
    resp.form['events_csv_file'] = Upload(
669
        't.csv', '"date"\t"time"\t"etc."\n'
670
        '"2016-09-16"\t"18:00"\t"10"\t"5"\t"éléphant"\n'
671
        '"2016-09-19"\t"18:00"\t"10"'.encode('iso-8859-15'), 'text/csv')
638 672
    resp = resp.form.submit(status=302)
639 673
    assert Event.objects.count() == 2
640 674
    Event.objects.all().delete()
......
671 705
    agenda = Agenda.objects.get(label='Foo bar')
672 706
    assert agenda.kind == 'meetings'
673 707

  
708

  
674 709
def test_meetings_agenda_add_meeting_type(app, admin_user):
675 710
    agenda = Agenda(label=u'Foo bar', kind='meetings')
676 711
    agenda.save()
......
693 728
    resp = resp.form.submit()
694 729
    assert MeetingType.objects.get(agenda=agenda).duration == 30
695 730

  
731

  
696 732
def test_meetings_agenda_delete_meeting_type(app, admin_user):
697 733
    agenda = Agenda(label=u'Foo bar', kind='meetings')
698 734
    agenda.save()
......
709 745
    assert resp.location.endswith('/manage/agendas/%s/settings' % agenda.id)
710 746
    assert MeetingType.objects.count() == 0
711 747

  
748

  
712 749
def test_meetings_agenda_add_time_period(app, admin_user):
713 750
    agenda = Agenda(label=u'Foo bar', kind='meetings')
714 751
    agenda.save()
......
771 808
    resp = resp.form.submit()
772 809
    assert TimePeriod.objects.filter(desk=desk).count() == 4
773 810

  
811

  
774 812
def test_meetings_agenda_delete_time_period(app, admin_user):
775 813
    agenda = Agenda(label=u'Foo bar', kind='meetings')
776 814
    agenda.save()
......
778 816
    MeetingType(agenda=agenda, label='Blah').save()
779 817

  
780 818
    desk = Desk.objects.create(agenda=agenda, label='Desk A')
781
    time_period = TimePeriod(desk=desk, weekday=2,
782
            start_time=datetime.time(10, 0),
783
            end_time=datetime.time(18, 0))
819
    time_period = TimePeriod(
820
        desk=desk, weekday=2,
821
        start_time=datetime.time(10, 0),
822
        end_time=datetime.time(18, 0))
784 823
    time_period.save()
785 824

  
786 825
    app = login(app)
......
807 846
    desk = Desk.objects.create(agenda=agenda, label='Desk A')
808 847
    app = login(app, username='manager', password='manager')
809 848
    resp = app.get('/manage/agendas/%d/' % agenda.id)
810
    assert not 'Settings' in resp.text
849
    assert 'Settings' not in resp.text
811 850
    resp = app.get('/manage/agendas/%d/settings' % agenda.id, status=403)
812 851
    MeetingType(agenda=agenda, label='Blah').save()
813 852
    app.get('/manage/agendas/%d/desk/%d/add-time-period' % (agenda.id, desk.id), status=403)
......
945 984
    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
946 985
    resp = resp.click('Settings')
947 986
    resp = resp.click('Add a time period exception')
948
    resp = resp.form.submit() # submit empty form
987
    resp = resp.form.submit()  # submit empty form
949 988
    # fields should be marked with errors
950 989
    assert resp.text.count('This field is required.') == 2
951 990
    # try again with data in fields
......
967 1006
    resp = resp.form.submit()
968 1007
    assert TimePeriodException.objects.count() == 1
969 1008

  
1009

  
970 1010
def test_meetings_agenda_add_time_period_exception_when_cancelled_booking_exists(app, admin_user):
971 1011
    agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
972 1012
    desk = Desk.objects.create(agenda=agenda, label='Desk A')
......
975 1015
                              start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
976 1016
    event = Event.objects.create(agenda=agenda, places=1,
977 1017
                                 start_datetime=make_aware(datetime.datetime(2017, 5, 22, 10, 30)))
978
    Booking.objects.create(event=event,
979
            cancellation_datetime=make_aware(datetime.datetime(2017, 5, 20, 10, 30)))
1018
    Booking.objects.create(
1019
        event=event,
1020
        cancellation_datetime=make_aware(datetime.datetime(2017, 5, 20, 10, 30)))
980 1021
    login(app)
981 1022
    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
982 1023
    resp = resp.click('Settings')
......
987 1028
    assert 'One or several bookings exists within this time slot.' not in resp.text
988 1029
    assert TimePeriodException.objects.count() == 1
989 1030

  
1031

  
990 1032
def test_meetings_agenda_add_invalid_time_period_exception(app, admin_user):
991 1033
    agenda = Agenda.objects.create(label='Foo bar', kind='meetings')
992 1034
    desk = Desk.objects.create(agenda=agenda, label='Desk A')
......
1092 1134
    resp = resp.click('Settings')
1093 1135
    assert 'Import exceptions from .ics' not in resp.text
1094 1136

  
1095
    TimePeriod.objects.create(weekday=1, desk=desk,
1096
                start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
1137
    TimePeriod.objects.create(
1138
        weekday=1, desk=desk,
1139
        start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
1097 1140

  
1098 1141
    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
1099 1142
    resp = resp.click('Settings')
......
1182 1225
    resp = resp.click('Settings')
1183 1226
    assert 'Import exceptions from .ics' not in resp.text
1184 1227

  
1185
    TimePeriod.objects.create(weekday=1, desk=desk,
1186
                start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
1228
    TimePeriod.objects.create(
1229
        weekday=1, desk=desk,
1230
        start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
1187 1231

  
1188 1232
    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
1189 1233
    resp = resp.click('Settings')
......
1193 1237
    assert 'ics_url' in resp.form.fields
1194 1238
    resp.form['ics_url'] = 'http://example.com/foo.ics'
1195 1239
    mocked_response = mock.Mock()
1196
    mocked_response.text =  """BEGIN:VCALENDAR
1240
    mocked_response.text = """BEGIN:VCALENDAR
1197 1241
VERSION:2.0
1198 1242
PRODID:-//foo.bar//EN
1199 1243
BEGIN:VEVENT
......
1213 1257
    resp = resp.click('upload')
1214 1258
    resp.form['ics_url'] = ''
1215 1259
    resp = resp.form.submit(status=302)
1216
    assert not TimePeriodException.objects.filter(desk=desk,
1217
                    external_id='desk-%s:random-event-id' % desk.id).exists()
1260
    assert not TimePeriodException.objects.filter(
1261
        desk=desk,
1262
        external_id='desk-%s:random-event-id' % desk.id).exists()
1263

  
1218 1264

  
1219 1265
@mock.patch('chrono.agendas.models.requests.get')
1220 1266
def test_agenda_import_time_period_exception_with_remote_ics_no_events(mocked_get, app, admin_user):
......
1226 1272
    resp = resp.click('Settings')
1227 1273
    assert 'Import exceptions from .ics' not in resp.text
1228 1274

  
1229
    TimePeriod.objects.create(weekday=1, desk=desk,
1230
                start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
1275
    TimePeriod.objects.create(
1276
        weekday=1, desk=desk,
1277
        start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
1231 1278

  
1232 1279
    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
1233 1280
    resp = resp.click('Settings')
1234 1281
    resp = resp.click('upload')
1235 1282
    resp.form['ics_url'] = 'http://example.com/foo.ics'
1236 1283
    mocked_response = mock.Mock()
1237
    mocked_response.text =  """BEGIN:VCALENDAR
1284
    mocked_response.text = """BEGIN:VCALENDAR
1238 1285
VERSION:2.0
1239 1286
PRODID:-//foo.bar//EN
1240 1287
BEGIN:VEVENT
......
1257 1304
    resp = resp.click('Settings')
1258 1305
    resp = resp.click('upload')
1259 1306
    resp = resp.form.submit(status=302)
1260
    assert not TimePeriodException.objects.filter(desk=desk,
1261
                    external_id='random-event-id').exists()
1307
    assert not TimePeriodException.objects.filter(
1308
        desk=desk,
1309
        external_id='random-event-id').exists()
1262 1310

  
1263 1311

  
1264 1312
@mock.patch('chrono.agendas.models.requests.get')
......
1271 1319
    resp = resp.click('Settings')
1272 1320
    assert 'Import exceptions from .ics' not in resp.text
1273 1321

  
1274
    TimePeriod.objects.create(weekday=1, desk=desk,
1275
                start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
1322
    TimePeriod.objects.create(
1323
        weekday=1, desk=desk,
1324
        start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
1276 1325

  
1277 1326
    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
1278 1327
    resp = resp.click('Settings')
1279 1328
    resp = resp.click('upload')
1280 1329
    resp.form['ics_url'] = 'http://example.com/foo.ics'
1281 1330
    mocked_response = mock.Mock()
1282
    mocked_response.text =  """BEGIN:VCALENDAR
1331
    mocked_response.text = """BEGIN:VCALENDAR
1283 1332
VERSION:2.0
1284 1333
PRODID:-//foo.bar//EN
1285 1334
BEGIN:VEVENT
......
1316 1365
    resp = resp.form.submit(status=302)
1317 1366
    assert TimePeriodException.objects.filter(desk=desk).count() == 1
1318 1367

  
1368

  
1319 1369
@mock.patch('chrono.agendas.models.requests.get')
1320 1370
def test_agenda_import_time_period_exception_from_remote_ics_with_connection_error(mocked_get, app, admin_user):
1321 1371
    agenda = Agenda.objects.create(label='New Example', kind='meetings')
......
1326 1376
    resp = resp.click('Settings')
1327 1377
    assert 'Import exceptions from .ics' not in resp.text
1328 1378

  
1329
    TimePeriod.objects.create(weekday=1, desk=desk,
1330
                start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
1379
    TimePeriod.objects.create(
1380
        weekday=1, desk=desk,
1381
        start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
1331 1382

  
1332 1383
    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
1333 1384
    resp = resp.click('Settings')
......
1338 1389
    resp.form['ics_url'] = 'http://example.com/foo.ics'
1339 1390
    mocked_response = mock.Mock()
1340 1391
    mocked_get.return_value = mocked_response
1392

  
1341 1393
    def mocked_requests_connection_error(*args, **kwargs):
1342 1394
        raise requests.exceptions.ConnectionError('unreachable')
1395

  
1343 1396
    mocked_get.side_effect = mocked_requests_connection_error
1344 1397
    resp = resp.form.submit(status=200)
1345 1398
    assert 'Failed to retrieve remote calendar (http://example.com/foo.ics, unreachable).' in resp.text
1346 1399

  
1400

  
1347 1401
@mock.patch('chrono.agendas.models.requests.get')
1348 1402
def test_agenda_import_time_period_exception_from_forbidden_remote_ics(mocked_get, app, admin_user):
1349 1403
    agenda = Agenda.objects.create(label='New Example', kind='meetings')
......
1354 1408
    resp = resp.click('Settings')
1355 1409
    assert 'Import exceptions from .ics' not in resp.text
1356 1410

  
1357
    TimePeriod.objects.create(weekday=1, desk=desk,
1358
                start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
1411
    TimePeriod.objects.create(
1412
        weekday=1, desk=desk,
1413
        start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
1359 1414

  
1360 1415
    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
1361 1416
    resp = resp.click('Settings')
......
1364 1419
    mocked_response = mock.Mock()
1365 1420
    mocked_response.status_code = 403
1366 1421
    mocked_get.return_value = mocked_response
1422

  
1367 1423
    def mocked_requests_http_forbidden_error(*args, **kwargs):
1368 1424
        raise requests.exceptions.HTTPError(response=mocked_response)
1425

  
1369 1426
    mocked_get.side_effect = mocked_requests_http_forbidden_error
1370 1427
    resp = resp.form.submit(status=200)
1371 1428
    assert 'Failed to retrieve remote calendar (http://example.com/foo.ics, HTTP error 403).' in resp.text
1372 1429

  
1430

  
1373 1431
@mock.patch('chrono.agendas.models.requests.get')
1374 1432
def test_agenda_import_time_period_exception_from_remote_ics_with_ssl_error(mocked_get, app, admin_user):
1375 1433
    agenda = Agenda.objects.create(label='New Example', kind='meetings')
......
1379 1437
    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
1380 1438
    resp = resp.click('Settings')
1381 1439
    assert 'Import exceptions from .ics' not in resp.text
1382
    TimePeriod.objects.create(weekday=1, desk=desk,
1383
                start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
1440
    TimePeriod.objects.create(
1441
        weekday=1, desk=desk,
1442
        start_time=datetime.time(10, 0), end_time=datetime.time(12, 0))
1384 1443

  
1385 1444
    resp = app.get('/manage/agendas/%d/' % agenda.pk).follow()
1386 1445
    resp = resp.click('Settings')
......
1388 1447
    resp.form['ics_url'] = 'https://example.com/foo.ics'
1389 1448
    mocked_response = mock.Mock()
1390 1449
    mocked_get.return_value = mocked_response
1450

  
1391 1451
    def mocked_requests_http_ssl_error(*args, **kwargs):
1392 1452
        raise requests.exceptions.SSLError('SSL error')
1453

  
1393 1454
    mocked_get.side_effect = mocked_requests_http_ssl_error
1394 1455
    resp = resp.form.submit(status=200)
1395 1456
    assert 'Failed to retrieve remote calendar (https://example.com/foo.ics, SSL error).' in resp.text
1396 1457

  
1458

  
1397 1459
def test_agenda_day_view(app, admin_user, manager_user, api_user):
1398 1460
    agenda = Agenda.objects.create(label='New Example', kind='meetings')
1399 1461
    desk = Desk.objects.create(agenda=agenda, label='New Desk')
......
1409 1471
    resp = resp.follow()
1410 1472
    assert 'No opening hours this day.' in resp.text  # no time pediod
1411 1473

  
1412
    timeperiod = TimePeriod(desk=desk, weekday=today.weekday(),
1413
            start_time=datetime.time(10, 0),
1414
            end_time=datetime.time(18, 0))
1474
    timeperiod = TimePeriod(
1475
        desk=desk, weekday=today.weekday(),
1476
        start_time=datetime.time(10, 0),
1477
        end_time=datetime.time(18, 0))
1415 1478
    timeperiod.save()
1416 1479
    resp = app.get('/manage/agendas/%s/' % agenda.id, status=302).follow()
1417
    assert not 'No opening hours this day.' in resp.text
1418
    assert not 'div class="booking' in resp.text
1480
    assert 'No opening hours this day.' not in resp.text
1481
    assert 'div class="booking' not in resp.text
1419 1482
    assert resp.text.count('<tr') == 9  # 10->18 (not included)
1420 1483

  
1421 1484
    timeperiod.end_time = datetime.time(18, 30)  # end during an hour
......
1434 1497
    booking_url = resp.json['data'][0]['api']['fillslot_url']
1435 1498
    booking_url2 = resp.json['data'][2]['api']['fillslot_url']
1436 1499
    resp = app.post(booking_url)
1437
    resp = app.post_json(booking_url2,
1438
            params={'label': 'foo', 'user': 'bar', 'url': 'http://baz/'})
1500
    resp = app.post_json(
1501
        booking_url2,
1502
        params={'label': 'foo', 'user': 'bar', 'url': 'http://baz/'})
1439 1503

  
1440 1504
    app.reset()
1441 1505
    login(app)
......
1488 1552
    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (
1489 1553
        agenda.id, date.year, date.month, date.day), status=200)
1490 1554

  
1555

  
1491 1556
def test_agenda_day_view_late_meeting(app, admin_user, manager_user, api_user):
1492 1557
    agenda = Agenda.objects.create(label='New Example', kind='meetings')
1493 1558
    desk = Desk.objects.create(agenda=agenda, label='New Desk')
......
1498 1563

  
1499 1564
    today = datetime.date.today()
1500 1565

  
1501
    timeperiod = TimePeriod(desk=desk, weekday=today.weekday(),
1502
            start_time=datetime.time(10, 0),
1503
            end_time=datetime.time(23, 30))
1566
    timeperiod = TimePeriod(
1567
        desk=desk, weekday=today.weekday(),
1568
        start_time=datetime.time(10, 0),
1569
        end_time=datetime.time(23, 30))
1504 1570
    timeperiod.save()
1505 1571

  
1506 1572
    login(app)
......
1508 1574
    assert resp.text.count('<tr') == 15
1509 1575
    assert '<th class="hour">11 p.m.</th>' in resp.text
1510 1576

  
1577

  
1511 1578
def test_agenda_invalid_day_view(app, admin_user, manager_user, api_user):
1512 1579
    agenda = Agenda.objects.create(label='New Example', kind='meetings')
1513 1580
    desk = Desk.objects.create(agenda=agenda, label='New Desk')
......
1520 1587
    resp = app.get('/manage/agendas/%s/%d/%d/%d/' % (agenda.id, 2018, 11, 31), status=302)
1521 1588
    assert resp.location.endswith('2018/11/30/')
1522 1589

  
1590

  
1523 1591
def test_agenda_month_view(app, admin_user, manager_user, api_user):
1524 1592
    agenda = Agenda.objects.create(label='Passeports', kind='meetings')
1525 1593
    desk = Desk.objects.create(agenda=agenda, label='Desk A')
......
1535 1603
    today = datetime.date.today()
1536 1604
    assert resp.request.url.endswith('%s/%s/' % (today.year, today.month))
1537 1605

  
1538
    assert 'Day view' in resp.text # date view link should be present
1606
    assert 'Day view' in resp.text  # date view link should be present
1539 1607
    assert 'No opening hours this month.' in resp.text
1540 1608

  
1541 1609
    today = datetime.date(2018, 11, 10)  # fixed day
1542 1610
    timeperiod_weekday = today.weekday()
1543
    timeperiod = TimePeriod(desk=desk, weekday=timeperiod_weekday,
1544
            start_time=datetime.time(10, 0),
1545
            end_time=datetime.time(18, 0))
1611
    timeperiod = TimePeriod(
1612
        desk=desk, weekday=timeperiod_weekday,
1613
        start_time=datetime.time(10, 0),
1614
        end_time=datetime.time(18, 0))
1546 1615
    timeperiod.save()
1547 1616
    resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.id, today.year, today.month))
1548
    assert not 'No opening hours this month.' in resp.text
1549
    assert not '<div class="booking' in resp.text
1617
    assert 'No opening hours this month.' not in resp.text
1618
    assert '<div class="booking' not in resp.text
1550 1619
    first_month_day = today.replace(day=1)
1551 1620
    last_month_day = today.replace(day=1, month=today.month+1) - datetime.timedelta(days=1)
1552 1621
    start_week_number = first_month_day.isocalendar()[1]
......
1564 1633
    booking_url = resp.json['data'][0]['api']['fillslot_url']
1565 1634
    booking_url2 = resp.json['data'][2]['api']['fillslot_url']
1566 1635
    booking = app.post(booking_url)
1567
    booking_2 = app.post_json(booking_url2,
1568
            params={'label': 'foo', 'user': 'bar', 'url': 'http://baz/'})
1636
    booking_2 = app.post_json(
1637
        booking_url2,
1638
        params={'label': 'foo', 'user': 'bar', 'url': 'http://baz/'})
1569 1639

  
1570 1640
    app.reset()
1571 1641
    login(app)
1572 1642
    date = Booking.objects.all()[0].event.start_datetime
1573 1643
    resp = app.get('/manage/agendas/%s/%d/%d/' % (
1574 1644
        agenda.id, date.year, date.month))
1575
    assert resp.text.count('<div class="booking" style="left:1.0%;height:33.0%;') == 2 # booking cells
1645
    assert resp.text.count('<div class="booking" style="left:1.0%;height:33.0%;') == 2  # booking cells
1576 1646
    desk = Desk.objects.create(agenda=agenda, label='Desk B')
1577
    timeperiod = TimePeriod(desk=desk, weekday=timeperiod_weekday,
1578
            start_time=datetime.time(10, 0),
1579
            end_time=datetime.time(18, 0))
1647
    timeperiod = TimePeriod(
1648
        desk=desk, weekday=timeperiod_weekday,
1649
        start_time=datetime.time(10, 0),
1650
        end_time=datetime.time(18, 0))
1580 1651
    timeperiod.save()
1581 1652

  
1582 1653
    app.reset()
......
1611 1682
    # check December is correctly displayed
1612 1683
    today = datetime.date(2018, 12, 10)
1613 1684
    resp = app.get('/manage/agendas/%s/%s/%s/' % (agenda.id, today.year, today.month))
1614
    assert not 'No opening hours this month.' in resp.text
1685
    assert 'No opening hours this month.' not in resp.text
1686

  
1615 1687

  
1616 1688
def test_agenda_month_view_dst_change(app, admin_user, manager_user, api_user):
1617 1689
    agenda = Agenda.objects.create(label='Passeports', kind='meetings')
......
1621 1693
    meetingtype.save()
1622 1694

  
1623 1695
    for weekday in range(0, 7):  # open all mornings
1624
        TimePeriod(desk=desk, weekday=weekday,
1625
                start_time=datetime.time(9, 0),
1626
                end_time=datetime.time(12, 0)).save()
1696
        TimePeriod(
1697
            desk=desk, weekday=weekday,
1698
            start_time=datetime.time(9, 0),
1699
            end_time=datetime.time(12, 0)).save()
1627 1700

  
1628 1701
    login(app)
1629 1702
    for date in ('2019-10-01', '2019-10-31'):
......
1655 1728
    agenda.view_role = manager_user.groups.all()[0]
1656 1729
    agenda.save()
1657 1730
    app = login(app, username='manager', password='manager')
1658
    resp = app.get('/manage/', status=200)
1659
    resp = app.get('/manage/agendas/import/', status=403)
1731
    app.get('/manage/', status=200)
1732
    app.get('/manage/agendas/import/', status=403)
1733

  
1660 1734

  
1661 1735
def test_import_agenda(app, admin_user):
1662 1736
    agenda = Agenda(label=u'Foo bar')
1663
-