Projet

Général

Profil

0001-misc-split-pricing-manager-tests-65459.patch

Lauréline Guérin, 23 mai 2022 17:03

Télécharger (61,5 ko)

Voir les différences:

Subject: [PATCH 1/3] misc: split pricing manager tests (#65459)

 tests/pricing/manager/__init__.py             |   0
 .../test_agenda.py}                           | 727 +-----------------
 tests/pricing/manager/test_criteria.py        | 186 +++++
 tests/pricing/manager/test_import_export.py   | 235 ++++++
 tests/pricing/manager/test_pricing.py         | 324 ++++++++
 5 files changed, 746 insertions(+), 726 deletions(-)
 create mode 100644 tests/pricing/manager/__init__.py
 rename tests/pricing/{test_manager.py => manager/test_agenda.py} (51%)
 create mode 100644 tests/pricing/manager/test_criteria.py
 create mode 100644 tests/pricing/manager/test_import_export.py
 create mode 100644 tests/pricing/manager/test_pricing.py
tests/pricing/test_manager.py → tests/pricing/manager/test_agenda.py
1
import copy
2 1
import datetime
3
import json
4 2
from unittest import mock
5 3

  
6 4
import pytest
7
from webtest import Upload
8 5

  
9 6
from lingo.agendas.models import Agenda
10
from lingo.pricing.models import AgendaPricing, Criteria, CriteriaCategory, Pricing, PricingCriteriaCategory
7
from lingo.pricing.models import AgendaPricing, Criteria, CriteriaCategory, Pricing
11 8
from tests.utils import login
12 9

  
13 10
pytestmark = pytest.mark.django_db
14 11

  
15 12

  
16
def test_export_site(freezer, app, admin_user):
17
    freezer.move_to('2020-06-15')
18
    login(app)
19
    resp = app.get('/manage/pricing/')
20
    resp = resp.click('Export')
21

  
22
    resp = resp.form.submit()
23
    assert resp.headers['content-type'] == 'application/json'
24
    assert resp.headers['content-disposition'] == 'attachment; filename="export_pricing_config_20200615.json"'
25

  
26
    site_json = json.loads(resp.text)
27
    assert site_json == {
28
        'agendas': [],
29
        'pricing_categories': [],
30
        'pricing_models': [],
31
    }
32

  
33
    Agenda.objects.create(label='Foo Bar')
34
    resp = app.get('/manage/pricing/export/')
35
    resp = resp.form.submit()
36

  
37
    site_json = json.loads(resp.text)
38
    assert len(site_json['agendas']) == 1
39

  
40
    resp = app.get('/manage/pricing/export/')
41
    resp.form['agendas'] = False
42
    resp.form['pricing_categories'] = False
43
    resp.form['pricing_models'] = False
44
    resp = resp.form.submit()
45

  
46
    site_json = json.loads(resp.text)
47
    assert 'agendas' not in site_json
48
    assert 'pricing_categories' not in site_json
49
    assert 'pricing_models' not in site_json
50

  
51

  
52
def test_add_pricing(app, admin_user):
53
    app = login(app)
54
    resp = app.get('/manage/')
55
    resp = resp.click('Pricing')
56
    resp = resp.click('New pricing model')
57
    resp.form['label'] = 'Pricing model for lunch'
58
    resp = resp.form.submit()
59
    pricing = Pricing.objects.latest('pk')
60
    assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
61
    assert pricing.label == 'Pricing model for lunch'
62
    assert pricing.slug == 'pricing-model-for-lunch'
63

  
64

  
65
def test_detail_pricing(app, admin_user):
66
    pricing = Pricing.objects.create(label='Model')
67

  
68
    app = login(app)
69
    resp = app.get('/manage/pricing/')
70
    resp = resp.click(href='/manage/pricing/%s/' % pricing.pk)
71
    assert '/manage/pricing/%s/edit/' % pricing.pk in resp
72
    assert '/manage/pricing/%s/delete/' % pricing.pk in resp
73

  
74

  
75
def test_edit_pricing(app, admin_user):
76
    pricing = Pricing.objects.create(label='Model 1')
77
    pricing2 = Pricing.objects.create(label='Model 2')
78

  
79
    app = login(app)
80
    resp = app.get('/manage/pricing/%s/' % pricing.pk)
81
    resp = resp.click(href='/manage/pricing/%s/edit/' % pricing.pk)
82
    resp.form['label'] = 'Model Foo'
83
    resp.form['slug'] = pricing2.slug
84
    resp = resp.form.submit()
85
    assert resp.context['form'].errors['slug'] == ['Pricing with this Identifier already exists.']
86

  
87
    resp.form['slug'] = 'foo-bar'
88
    resp = resp.form.submit()
89
    assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
90
    pricing.refresh_from_db()
91
    assert pricing.label == 'Model Foo'
92
    assert pricing.slug == 'foo-bar'
93

  
94

  
95
def test_delete_pricing(app, admin_user):
96
    pricing = Pricing.objects.create(label='Model')
97

  
98
    app = login(app)
99
    resp = app.get('/manage/pricing/%s/' % pricing.pk)
100
    resp = resp.click(href='/manage/pricing/%s/delete/' % pricing.pk)
101
    resp = resp.form.submit()
102
    assert resp.location.endswith('/manage/pricing/')
103
    assert Pricing.objects.exists() is False
104

  
105

  
106
def test_duplicate_pricing(app, admin_user):
107
    pricing = Pricing.objects.create(label='Model')
108
    assert Pricing.objects.count() == 1
109

  
110
    app = login(app)
111
    resp = app.get('/manage/pricing/%s/' % pricing.pk)
112
    resp = resp.click(href='/manage/pricing/%s/duplicate/' % pricing.pk)
113
    resp = resp.form.submit()
114
    assert Pricing.objects.count() == 2
115

  
116
    new_pricing = Pricing.objects.latest('pk')
117
    assert resp.location == '/manage/pricing/%s/' % new_pricing.pk
118
    assert new_pricing.pk != pricing.pk
119

  
120
    resp = resp.follow()
121
    assert 'copy-of-model' in resp.text
122

  
123
    resp = resp.click(href='/manage/pricing/%s/duplicate/' % new_pricing.pk)
124
    resp.form['label'] = 'hop'
125
    resp = resp.form.submit().follow()
126
    assert 'hop' in resp.text
127

  
128

  
129
@pytest.mark.freeze_time('2021-07-08')
130
def test_import_pricing(app, admin_user):
131
    pricing = Pricing.objects.create(label='Model')
132

  
133
    app = login(app)
134
    resp = app.get('/manage/pricing/%s/export/' % pricing.id)
135
    assert resp.headers['content-type'] == 'application/json'
136
    assert resp.headers['content-disposition'] == 'attachment; filename="export_pricing_model_20210708.json"'
137
    pricing_export = resp.text
138

  
139
    # existing pricing
140
    resp = app.get('/manage/pricing/', status=200)
141
    resp = resp.click('Import')
142
    resp.form['config_json'] = Upload('export.json', pricing_export.encode('utf-8'), 'application/json')
143
    resp = resp.form.submit()
144
    assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
145
    resp = resp.follow()
146
    assert 'No pricing model created. A pricing model has been updated.' not in resp.text
147
    assert Pricing.objects.count() == 1
148

  
149
    # new pricing
150
    Pricing.objects.all().delete()
151
    resp = app.get('/manage/pricing/', status=200)
152
    resp = resp.click('Import')
153
    resp.form['config_json'] = Upload('export.json', pricing_export.encode('utf-8'), 'application/json')
154
    resp = resp.form.submit()
155
    pricing = Pricing.objects.latest('pk')
156
    assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
157
    resp = resp.follow()
158
    assert 'A pricing model has been created. No pricing model updated.' not in resp.text
159
    assert Pricing.objects.count() == 1
160

  
161
    # multiple pricing
162
    pricings = json.loads(pricing_export)
163
    pricings['pricing_models'].append(copy.copy(pricings['pricing_models'][0]))
164
    pricings['pricing_models'].append(copy.copy(pricings['pricing_models'][0]))
165
    pricings['pricing_models'][1]['label'] = 'Foo bar 2'
166
    pricings['pricing_models'][1]['slug'] = 'foo-bar-2'
167
    pricings['pricing_models'][2]['label'] = 'Foo bar 3'
168
    pricings['pricing_models'][2]['slug'] = 'foo-bar-3'
169

  
170
    resp = app.get('/manage/pricing/', status=200)
171
    resp = resp.click('Import')
172
    resp.form['config_json'] = Upload('export.json', json.dumps(pricings).encode('utf-8'), 'application/json')
173
    resp = resp.form.submit()
174
    assert resp.location.endswith('/manage/pricing/')
175
    resp = resp.follow()
176
    assert '2 pricing models have been created. A pricing model has been updated.' in resp.text
177
    assert Pricing.objects.count() == 3
178

  
179
    Pricing.objects.all().delete()
180
    resp = app.get('/manage/pricing/', status=200)
181
    resp = resp.click('Import')
182
    resp.form['config_json'] = Upload('export.json', json.dumps(pricings).encode('utf-8'), 'application/json')
183
    resp = resp.form.submit().follow()
184
    assert '3 pricing models have been created. No pricing model updated.' in resp.text
185
    assert Pricing.objects.count() == 3
186

  
187

  
188
def test_pricing_edit_extra_variables(app, admin_user):
189
    pricing = Pricing.objects.create(label='Model')
190
    assert pricing.extra_variables == {}
191

  
192
    app = login(app)
193
    resp = app.get('/manage/pricing/%s/' % pricing.id)
194
    assert '<label>Extra variables:</label>' not in resp.text
195
    resp = resp.click(href='/manage/pricing/%s/variable/' % pricing.id)
196
    resp.form['form-0-key'] = 'foo'
197
    resp.form['form-0-value'] = 'bar'
198
    resp = resp.form.submit().follow()
199
    pricing.refresh_from_db()
200
    assert pricing.extra_variables == {'foo': 'bar'}
201
    assert '<label>Extra variables:</label>' in resp.text
202
    assert '<i>foo</i>' in resp
203

  
204
    resp = resp.click(href='/manage/pricing/%s/variable/' % pricing.id)
205
    assert resp.form['form-TOTAL_FORMS'].value == '2'
206
    assert resp.form['form-0-key'].value == 'foo'
207
    assert resp.form['form-0-value'].value == 'bar'
208
    assert resp.form['form-1-key'].value == ''
209
    assert resp.form['form-1-value'].value == ''
210
    resp.form['form-0-value'] = 'bar-bis'
211
    resp.form['form-1-key'] = 'blah'
212
    resp.form['form-1-value'] = 'baz'
213
    resp = resp.form.submit().follow()
214
    pricing.refresh_from_db()
215
    assert pricing.extra_variables == {
216
        'foo': 'bar-bis',
217
        'blah': 'baz',
218
    }
219
    assert '<i>blah</i>, <i>foo</i>' in resp
220

  
221
    resp = resp.click(href='/manage/pricing/%s/variable/' % pricing.id)
222
    assert resp.form['form-TOTAL_FORMS'].value == '3'
223
    assert resp.form['form-0-key'].value == 'blah'
224
    assert resp.form['form-0-value'].value == 'baz'
225
    assert resp.form['form-1-key'].value == 'foo'
226
    assert resp.form['form-1-value'].value == 'bar-bis'
227
    assert resp.form['form-2-key'].value == ''
228
    assert resp.form['form-2-value'].value == ''
229
    resp.form['form-1-key'] = 'foo'
230
    resp.form['form-1-value'] = 'bar'
231
    resp.form['form-0-key'] = ''
232
    resp = resp.form.submit().follow()
233
    pricing.refresh_from_db()
234
    assert pricing.extra_variables == {
235
        'foo': 'bar',
236
    }
237
    assert '<i>foo</i>' in resp
238

  
239

  
240
def test_pricing_add_category(app, admin_user):
241
    pricing = Pricing.objects.create(label='Model')
242
    category1 = CriteriaCategory.objects.create(label='Cat 1')
243
    category2 = CriteriaCategory.objects.create(label='Cat 2')
244
    category3 = CriteriaCategory.objects.create(label='Cat 3')
245
    category4 = CriteriaCategory.objects.create(label='Cat 4')
246

  
247
    app = login(app)
248
    resp = app.get('/manage/pricing/%s/' % pricing.pk)
249
    resp = resp.click(href='/manage/pricing/%s/category/add/' % pricing.pk)
250
    assert list(resp.context['form'].fields['category'].queryset) == [
251
        category1,
252
        category2,
253
        category3,
254
        category4,
255
    ]
256
    resp.form['category'] = category1.pk
257
    resp = resp.form.submit()
258
    assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
259
    resp = resp.follow()
260
    assert '/manage/pricing/%s/category/add/' % pricing.pk in resp
261
    assert list(
262
        PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
263
    ) == [category1.pk]
264
    assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
265
        1
266
    ]
267

  
268
    resp = app.get('/manage/pricing/%s/category/add/' % pricing.pk)
269
    assert list(resp.context['form'].fields['category'].queryset) == [category2, category3, category4]
270
    resp.form['category'] = category4.pk
271
    resp = resp.form.submit().follow()
272
    assert list(
273
        PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
274
    ) == [category1.pk, category4.pk]
275
    assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
276
        1,
277
        2,
278
    ]
279

  
280
    resp = app.get('/manage/pricing/%s/category/add/' % pricing.pk)
281
    assert list(resp.context['form'].fields['category'].queryset) == [category2, category3]
282
    resp.form['category'] = category2.pk
283
    resp = resp.form.submit().follow()
284
    assert '/manage/pricing/%s/category/add/' % pricing.pk not in resp
285
    assert list(
286
        PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
287
    ) == [category1.pk, category4.pk, category2.pk]
288
    assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
289
        1,
290
        2,
291
        3,
292
    ]
293

  
294
    app.get('/manage/pricing/%s/category/add/' % pricing.pk, status=404)
295

  
296

  
297
def test_pricing_edit_category(app, admin_user):
298
    category1 = CriteriaCategory.objects.create(label='Cat 1')
299
    criteria1 = Criteria.objects.create(label='Crit 1', category=category1)
300
    criteria2 = Criteria.objects.create(label='Crit 2', category=category1)
301
    criteria3 = Criteria.objects.create(label='Crit 3', category=category1)
302
    criteria4 = Criteria.objects.create(label='Crit 4', category=category1)
303
    category2 = CriteriaCategory.objects.create(label='cat 2')
304
    criteria5 = Criteria.objects.create(label='Crit 5', category=category2)
305
    pricing = Pricing.objects.create(label='Model')
306
    pricing.categories.add(category1, through_defaults={'order': 1})
307
    pricing.categories.add(category2, through_defaults={'order': 2})
308

  
309
    app = login(app)
310
    resp = app.get('/manage/pricing/%s/' % pricing.pk)
311
    resp = resp.click(href='/manage/pricing/%s/category/%s/edit/' % (pricing.pk, category1.pk))
312
    assert list(resp.context['form'].fields['criterias'].queryset) == [
313
        criteria1,
314
        criteria2,
315
        criteria3,
316
        criteria4,
317
    ]
318
    assert list(resp.context['form'].initial['criterias']) == []
319
    resp.form['criterias'] = [criteria1.pk, criteria3.pk]
320
    resp = resp.form.submit()
321
    assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
322
    resp = resp.follow()
323
    assert list(pricing.criterias.order_by('pk')) == [criteria1, criteria3]
324

  
325
    resp = app.get('/manage/pricing/%s/category/%s/edit/' % (pricing.pk, category1.pk))
326
    assert list(resp.context['form'].initial['criterias']) == [criteria1, criteria3]
327
    resp.form['criterias'] = [criteria1.pk, criteria4.pk]
328
    resp = resp.form.submit().follow()
329
    assert list(pricing.criterias.order_by('pk')) == [criteria1, criteria4]
330

  
331
    resp = app.get('/manage/pricing/%s/category/%s/edit/' % (pricing.pk, category2.pk))
332
    assert list(resp.context['form'].fields['criterias'].queryset) == [criteria5]
333
    assert list(resp.context['form'].initial['criterias']) == []
334
    resp.form['criterias'] = [criteria5.pk]
335
    resp = resp.form.submit().follow()
336
    assert list(pricing.criterias.order_by('pk')) == [criteria1, criteria4, criteria5]
337

  
338

  
339
def test_pricing_delete_category(app, admin_user):
340
    category1 = CriteriaCategory.objects.create(label='Cat 1')
341
    criteria1 = Criteria.objects.create(label='Crit 1', category=category1)
342
    category2 = CriteriaCategory.objects.create(label='Cat 2')
343
    criteria2 = Criteria.objects.create(label='Crit 2', category=category2)
344
    pricing = Pricing.objects.create(label='Model')
345
    pricing.categories.add(category1, through_defaults={'order': 1})
346
    pricing.categories.add(category2, through_defaults={'order': 2})
347
    pricing.criterias.add(criteria1, criteria2)
348

  
349
    app = login(app)
350
    resp = app.get('/manage/pricing/%s/' % pricing.pk)
351
    resp = resp.click(href='/manage/pricing/%s/category/%s/delete/' % (pricing.pk, category1.pk))
352
    resp = resp.form.submit()
353
    assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
354
    resp = resp.follow()
355
    assert list(pricing.categories.all()) == [category2]
356
    assert list(pricing.criterias.all()) == [criteria2]
357

  
358
    # not linked
359
    app.get('/manage/pricing/%s/category/%s/delete/' % (pricing.pk, category1.pk), status=404)
360
    # unknown
361
    app.get('/manage/pricing/%s/category/%s/delete/' % (pricing.pk, 0), status=404)
362

  
363

  
364
def test_pricing_reorder_categories(app, admin_user):
365
    category1 = CriteriaCategory.objects.create(label='Cat 1')
366
    category2 = CriteriaCategory.objects.create(label='Cat 2')
367
    category3 = CriteriaCategory.objects.create(label='Cat 3')
368
    category4 = CriteriaCategory.objects.create(label='Cat 4')
369
    pricing = Pricing.objects.create(label='Model')
370
    pricing.categories.add(category1, through_defaults={'order': 1})
371
    pricing.categories.add(category2, through_defaults={'order': 2})
372
    pricing.categories.add(category3, through_defaults={'order': 3})
373
    assert list(
374
        PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
375
    ) == [category1.pk, category2.pk, category3.pk]
376
    assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
377
        1,
378
        2,
379
        3,
380
    ]
381

  
382
    app = login(app)
383
    # missing get params
384
    app.get('/manage/pricing/%s/order/' % (pricing.pk), status=400)
385

  
386
    # bad new-order param
387
    bad_params = [
388
        # missing category3 in order
389
        ','.join(str(x) for x in [category1.pk, category2.pk]),
390
        # category1 mentionned twice
391
        ','.join(str(x) for x in [category1.pk, category2.pk, category3.pk, category1.pk]),
392
        # category4 not in pricing categories
393
        ','.join(str(x) for x in [category1.pk, category2.pk, category3.pk, category4.pk]),
394
        # not an id
395
        'foo,1,2,3',
396
        ' 1 ,2,3',
397
    ]
398
    for bad_param in bad_params:
399
        app.get(
400
            '/manage/pricing/%s/order/' % (pricing.pk),
401
            params={'new-order': bad_param},
402
            status=400,
403
        )
404
    # not changed
405
    assert list(
406
        PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
407
    ) == [category1.pk, category2.pk, category3.pk]
408
    assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
409
        1,
410
        2,
411
        3,
412
    ]
413

  
414
    # change order
415
    app.get(
416
        '/manage/pricing/%s/order/' % (pricing.pk),
417
        params={'new-order': ','.join(str(x) for x in [category3.pk, category1.pk, category2.pk])},
418
    )
419
    assert list(
420
        PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
421
    ) == [category3.pk, category1.pk, category2.pk]
422
    assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
423
        1,
424
        2,
425
        3,
426
    ]
427

  
428

  
429
def test_add_category(app, admin_user):
430
    app = login(app)
431
    resp = app.get('/manage/')
432
    resp = resp.click('Pricing')
433
    resp = resp.click('Criterias')
434
    resp = resp.click('New category')
435
    resp.form['label'] = 'QF'
436
    resp = resp.form.submit()
437
    category = CriteriaCategory.objects.latest('pk')
438
    assert resp.location.endswith('/manage/pricing/criterias/')
439
    assert category.label == 'QF'
440
    assert category.slug == 'qf'
441

  
442

  
443
def test_edit_category(app, admin_user):
444
    category = CriteriaCategory.objects.create(label='QF')
445
    category2 = CriteriaCategory.objects.create(label='Domicile')
446

  
447
    app = login(app)
448
    resp = app.get('/manage/pricing/criterias/')
449
    resp = resp.click(href='/manage/pricing/criteria/category/%s/edit/' % category.pk)
450
    resp.form['label'] = 'QF Foo'
451
    resp.form['slug'] = category2.slug
452
    resp = resp.form.submit()
453
    assert resp.context['form'].errors['slug'] == ['Criteria category with this Identifier already exists.']
454

  
455
    resp.form['slug'] = 'baz2'
456
    resp = resp.form.submit()
457
    assert resp.location.endswith('/manage/pricing/criterias/')
458
    category.refresh_from_db()
459
    assert category.label == 'QF Foo'
460
    assert category.slug == 'baz2'
461

  
462

  
463
def test_delete_category(app, admin_user):
464
    category = CriteriaCategory.objects.create(label='QF')
465
    Criteria.objects.create(label='QF 1', category=category)
466

  
467
    app = login(app)
468
    resp = app.get('/manage/pricing/criterias/')
469
    resp = resp.click(href='/manage/pricing/criteria/category/%s/delete/' % category.pk)
470
    resp = resp.form.submit()
471
    assert resp.location.endswith('/manage/pricing/criterias/')
472
    assert CriteriaCategory.objects.exists() is False
473
    assert Criteria.objects.exists() is False
474

  
475

  
476
def test_add_criteria(app, admin_user):
477
    category = CriteriaCategory.objects.create(label='QF')
478

  
479
    app = login(app)
480
    resp = app.get('/manage/pricing/criterias/')
481
    resp = resp.click('Add a criteria')
482
    resp.form['label'] = 'QF < 1'
483
    resp.form['condition'] = 'qf < 1 #'
484
    assert 'slug' not in resp.context['form'].fields
485
    resp = resp.form.submit()
486
    assert resp.context['form'].errors['condition'] == ['Invalid syntax.']
487
    resp.form['condition'] = 'qf < 1'
488
    resp = resp.form.submit()
489
    criteria = Criteria.objects.latest('pk')
490
    assert resp.location.endswith('/manage/pricing/criterias/')
491
    assert criteria.label == 'QF < 1'
492
    assert criteria.category == category
493
    assert criteria.slug == 'qf-1'
494
    assert criteria.condition == 'qf < 1'
495
    assert criteria.order == 1
496

  
497
    resp = app.get('/manage/pricing/criteria/category/%s/add/' % category.pk)
498
    resp.form['label'] = 'QF < 1'
499
    resp.form['condition'] = 'qf < 1'
500
    resp = resp.form.submit()
501
    assert resp.location.endswith('/manage/pricing/criterias/')
502
    criteria = Criteria.objects.latest('pk')
503
    assert criteria.label == 'QF < 1'
504
    assert criteria.category == category
505
    assert criteria.slug == 'qf-1-1'
506
    assert criteria.condition == 'qf < 1'
507
    assert criteria.order == 2
508

  
509

  
510
def test_edit_criteria(app, admin_user):
511
    category = CriteriaCategory.objects.create(label='QF')
512
    criteria = Criteria.objects.create(label='QF 1', category=category)
513
    criteria2 = Criteria.objects.create(label='QF 2', category=category)
514
    category2 = CriteriaCategory.objects.create(label='Foo')
515
    criteria3 = Criteria.objects.create(label='foo-bar', category=category2)
516

  
517
    app = login(app)
518
    resp = app.get('/manage/pricing/criterias/')
519
    resp = resp.click(href='/manage/pricing/criteria/category/%s/%s/edit/' % (category.pk, criteria.pk))
520
    resp.form['label'] = 'QF 1 bis'
521
    resp.form['slug'] = criteria2.slug
522
    resp.form['condition'] = 'qf <= 1 #'
523
    resp = resp.form.submit()
524
    assert resp.context['form'].errors['slug'] == ['Another criteria exists with the same identifier.']
525
    assert resp.context['form'].errors['condition'] == ['Invalid syntax.']
526

  
527
    resp.form['condition'] = 'qf <= 1'
528
    resp.form['slug'] = criteria3.slug
529
    resp = resp.form.submit()
530
    assert resp.location.endswith('/manage/pricing/criterias/')
531
    criteria.refresh_from_db()
532
    assert criteria.label == 'QF 1 bis'
533
    assert criteria.slug == 'foo-bar'
534
    assert criteria.condition == 'qf <= 1'
535

  
536

  
537
def test_delete_criteria(app, admin_user):
538
    category = CriteriaCategory.objects.create(label='QF')
539
    criteria = Criteria.objects.create(label='QF 1', category=category)
540

  
541
    app = login(app)
542
    resp = app.get('/manage/pricing/criterias/')
543
    resp = resp.click(href='/manage/pricing/criteria/category/%s/%s/delete/' % (category.pk, criteria.pk))
544
    resp = resp.form.submit()
545
    assert resp.location.endswith('/manage/pricing/criterias/')
546
    assert CriteriaCategory.objects.exists() is True
547
    assert Criteria.objects.exists() is False
548

  
549

  
550
def test_reorder_criterias(app, admin_user):
551
    category = CriteriaCategory.objects.create(label='QF')
552
    criteria1 = Criteria.objects.create(label='QF 1', category=category)
553
    criteria2 = Criteria.objects.create(label='QF 2', category=category)
554
    criteria3 = Criteria.objects.create(label='QF 3', category=category)
555
    criteria4 = Criteria.objects.create(label='QF 4', category=category)
556
    assert list(category.criterias.values_list('pk', flat=True).order_by('order')) == [
557
        criteria1.pk,
558
        criteria2.pk,
559
        criteria3.pk,
560
        criteria4.pk,
561
    ]
562
    assert list(category.criterias.values_list('order', flat=True).order_by('order')) == [1, 2, 3, 4]
563

  
564
    app = login(app)
565
    # missing get params
566
    app.get('/manage/pricing/criteria/category/%s/order/' % (category.pk), status=400)
567

  
568
    # bad new-order param
569
    bad_params = [
570
        # missing criteria3 in order
571
        ','.join(str(x) for x in [criteria1.pk, criteria2.pk, criteria4.pk]),
572
        # criteria1 mentionned twice
573
        ','.join(str(x) for x in [criteria1.pk, criteria2.pk, criteria3.pk, criteria4.pk, criteria1.pk]),
574
        # not an id
575
        'foo,1,2,3,4',
576
        ' 1 ,2,3,4',
577
    ]
578
    for bad_param in bad_params:
579
        app.get(
580
            '/manage/pricing/criteria/category/%s/order/' % (category.pk),
581
            params={'new-order': bad_param},
582
            status=400,
583
        )
584
    # not changed
585
    assert list(category.criterias.values_list('pk', flat=True).order_by('order')) == [
586
        criteria1.pk,
587
        criteria2.pk,
588
        criteria3.pk,
589
        criteria4.pk,
590
    ]
591
    assert list(category.criterias.values_list('order', flat=True).order_by('order')) == [1, 2, 3, 4]
592

  
593
    # change order
594
    app.get(
595
        '/manage/pricing/criteria/category/%s/order/' % (category.pk),
596
        params={
597
            'new-order': ','.join(str(x) for x in [criteria3.pk, criteria1.pk, criteria4.pk, criteria2.pk])
598
        },
599
    )
600
    assert list(category.criterias.values_list('pk', flat=True).order_by('order')) == [
601
        criteria3.pk,
602
        criteria1.pk,
603
        criteria4.pk,
604
        criteria2.pk,
605
    ]
606
    assert list(category.criterias.values_list('order', flat=True).order_by('order')) == [1, 2, 3, 4]
607

  
608

  
609
@pytest.mark.freeze_time('2021-07-08')
610
def test_import_criteria_category(app, admin_user):
611
    category = CriteriaCategory.objects.create(label='Foo bar')
612
    Criteria.objects.create(label='Foo', category=category)
613
    Criteria.objects.create(label='Baz', category=category)
614

  
615
    app = login(app)
616
    resp = app.get('/manage/pricing/criteria/category/%s/export/' % category.id)
617
    assert resp.headers['content-type'] == 'application/json'
618
    assert (
619
        resp.headers['content-disposition']
620
        == 'attachment; filename="export_pricing_category_foo-bar_20210708.json"'
621
    )
622
    category_export = resp.text
623

  
624
    # existing category
625
    resp = app.get('/manage/pricing/', status=200)
626
    resp = resp.click('Import')
627
    resp.form['config_json'] = Upload('export.json', category_export.encode('utf-8'), 'application/json')
628
    resp = resp.form.submit()
629
    assert resp.location.endswith('/manage/pricing/criterias/')
630
    resp = resp.follow()
631
    assert (
632
        'No pricing criteria category created. A pricing criteria category has been updated.' not in resp.text
633
    )
634
    assert CriteriaCategory.objects.count() == 1
635
    assert Criteria.objects.count() == 2
636

  
637
    # new category
638
    CriteriaCategory.objects.all().delete()
639
    resp = app.get('/manage/pricing/', status=200)
640
    resp = resp.click('Import')
641
    resp.form['config_json'] = Upload('export.json', category_export.encode('utf-8'), 'application/json')
642
    resp = resp.form.submit()
643
    assert resp.location.endswith('/manage/pricing/criterias/')
644
    resp = resp.follow()
645
    assert (
646
        'A pricing criteria category has been created. No pricing criteria category updated.' not in resp.text
647
    )
648
    assert CriteriaCategory.objects.count() == 1
649
    assert Criteria.objects.count() == 2
650

  
651
    # multiple categories
652
    categories = json.loads(category_export)
653
    categories['pricing_categories'].append(copy.copy(categories['pricing_categories'][0]))
654
    categories['pricing_categories'].append(copy.copy(categories['pricing_categories'][0]))
655
    categories['pricing_categories'][1]['label'] = 'Foo bar 2'
656
    categories['pricing_categories'][1]['slug'] = 'foo-bar-2'
657
    categories['pricing_categories'][2]['label'] = 'Foo bar 3'
658
    categories['pricing_categories'][2]['slug'] = 'foo-bar-3'
659

  
660
    resp = app.get('/manage/pricing/', status=200)
661
    resp = resp.click('Import')
662
    resp.form['config_json'] = Upload(
663
        'export.json', json.dumps(categories).encode('utf-8'), 'application/json'
664
    )
665
    resp = resp.form.submit()
666
    assert resp.location.endswith('/manage/pricing/')
667
    resp = resp.follow()
668
    assert (
669
        '2 pricing criteria categories have been created. A pricing criteria category has been updated.'
670
        in resp.text
671
    )
672
    assert CriteriaCategory.objects.count() == 3
673
    assert Criteria.objects.count() == 6
674

  
675
    CriteriaCategory.objects.all().delete()
676
    resp = app.get('/manage/pricing/', status=200)
677
    resp = resp.click('Import')
678
    resp.form['config_json'] = Upload(
679
        'export.json', json.dumps(categories).encode('utf-8'), 'application/json'
680
    )
681
    resp = resp.form.submit().follow()
682
    assert (
683
        '3 pricing criteria categories have been created. No pricing criteria category updated.' in resp.text
684
    )
685
    assert CriteriaCategory.objects.count() == 3
686
    assert Criteria.objects.count() == 6
687

  
688

  
689 13
@mock.patch('lingo.pricing.views.refresh_agendas')
690 14
def test_refresh_agendas(mock_refresh, app, admin_user):
691 15
    app = login(app)
......
697 21
    assert mock_refresh.call_args_list == [mock.call()]
698 22

  
699 23

  
700
@pytest.mark.freeze_time('2021-07-08')
701
def test_import_agenda(app, admin_user):
702
    agenda = Agenda.objects.create(label='Foo Bar')
703

  
704
    app = login(app)
705
    resp = app.get('/manage/pricing/agenda/%s/' % agenda.pk)
706
    resp = resp.click('Export')
707
    assert resp.headers['content-type'] == 'application/json'
708
    assert (
709
        resp.headers['content-disposition']
710
        == 'attachment; filename="export_pricing_agenda_foo-bar_20210708.json"'
711
    )
712
    agenda_export = resp.text
713

  
714
    # existing agenda
715
    resp = app.get('/manage/pricing/', status=200)
716
    resp = resp.click('Import')
717
    resp.form['config_json'] = Upload('export.json', agenda_export.encode('utf-8'), 'application/json')
718
    resp = resp.form.submit()
719
    assert resp.location.endswith('/manage/pricing/agenda/%s/' % agenda.pk)
720
    resp = resp.follow()
721
    assert 'An agenda has been updated.' not in resp.text
722
    assert Agenda.objects.count() == 1
723

  
724
    # unknown agenda
725
    Agenda.objects.all().delete()
726
    resp = app.get('/manage/pricing/', status=200)
727
    resp = resp.click('Import')
728
    resp.form['config_json'] = Upload('export.json', agenda_export.encode('utf-8'), 'application/json')
729
    resp = resp.form.submit()
730
    assert resp.context['form'].errors['config_json'] == ['Missing "foo-bar" agenda']
731

  
732
    # multiple pricing
733
    Agenda.objects.create(label='Foo Bar')
734
    Agenda.objects.create(label='Foo Bar 2')
735
    agendas = json.loads(agenda_export)
736
    agendas['agendas'].append(copy.copy(agendas['agendas'][0]))
737
    agendas['agendas'][1]['slug'] = 'foo-bar-2'
738

  
739
    resp = app.get('/manage/pricing/', status=200)
740
    resp = resp.click('Import')
741
    resp.form['config_json'] = Upload('export.json', json.dumps(agendas).encode('utf-8'), 'application/json')
742
    resp = resp.form.submit()
743
    assert resp.location.endswith('/manage/pricing/')
744
    resp = resp.follow()
745
    assert '2 agendas have been updated.' in resp.text
746
    assert Agenda.objects.count() == 2
747

  
748

  
749 24
def test_add_agenda_pricing(app, admin_user):
750 25
    agenda = Agenda.objects.create(label='Foo Bar')
751 26
    pricing = Pricing.objects.create(label='Model')
tests/pricing/manager/test_criteria.py
1
import pytest
2

  
3
from lingo.pricing.models import Criteria, CriteriaCategory
4
from tests.utils import login
5

  
6
pytestmark = pytest.mark.django_db
7

  
8

  
9
def test_add_category(app, admin_user):
10
    app = login(app)
11
    resp = app.get('/manage/')
12
    resp = resp.click('Pricing')
13
    resp = resp.click('Criterias')
14
    resp = resp.click('New category')
15
    resp.form['label'] = 'QF'
16
    resp = resp.form.submit()
17
    category = CriteriaCategory.objects.latest('pk')
18
    assert resp.location.endswith('/manage/pricing/criterias/')
19
    assert category.label == 'QF'
20
    assert category.slug == 'qf'
21

  
22

  
23
def test_edit_category(app, admin_user):
24
    category = CriteriaCategory.objects.create(label='QF')
25
    category2 = CriteriaCategory.objects.create(label='Domicile')
26

  
27
    app = login(app)
28
    resp = app.get('/manage/pricing/criterias/')
29
    resp = resp.click(href='/manage/pricing/criteria/category/%s/edit/' % category.pk)
30
    resp.form['label'] = 'QF Foo'
31
    resp.form['slug'] = category2.slug
32
    resp = resp.form.submit()
33
    assert resp.context['form'].errors['slug'] == ['Criteria category with this Identifier already exists.']
34

  
35
    resp.form['slug'] = 'baz2'
36
    resp = resp.form.submit()
37
    assert resp.location.endswith('/manage/pricing/criterias/')
38
    category.refresh_from_db()
39
    assert category.label == 'QF Foo'
40
    assert category.slug == 'baz2'
41

  
42

  
43
def test_delete_category(app, admin_user):
44
    category = CriteriaCategory.objects.create(label='QF')
45
    Criteria.objects.create(label='QF 1', category=category)
46

  
47
    app = login(app)
48
    resp = app.get('/manage/pricing/criterias/')
49
    resp = resp.click(href='/manage/pricing/criteria/category/%s/delete/' % category.pk)
50
    resp = resp.form.submit()
51
    assert resp.location.endswith('/manage/pricing/criterias/')
52
    assert CriteriaCategory.objects.exists() is False
53
    assert Criteria.objects.exists() is False
54

  
55

  
56
def test_add_criteria(app, admin_user):
57
    category = CriteriaCategory.objects.create(label='QF')
58

  
59
    app = login(app)
60
    resp = app.get('/manage/pricing/criterias/')
61
    resp = resp.click('Add a criteria')
62
    resp.form['label'] = 'QF < 1'
63
    resp.form['condition'] = 'qf < 1 #'
64
    assert 'slug' not in resp.context['form'].fields
65
    resp = resp.form.submit()
66
    assert resp.context['form'].errors['condition'] == ['Invalid syntax.']
67
    resp.form['condition'] = 'qf < 1'
68
    resp = resp.form.submit()
69
    criteria = Criteria.objects.latest('pk')
70
    assert resp.location.endswith('/manage/pricing/criterias/')
71
    assert criteria.label == 'QF < 1'
72
    assert criteria.category == category
73
    assert criteria.slug == 'qf-1'
74
    assert criteria.condition == 'qf < 1'
75
    assert criteria.order == 1
76

  
77
    resp = app.get('/manage/pricing/criteria/category/%s/add/' % category.pk)
78
    resp.form['label'] = 'QF < 1'
79
    resp.form['condition'] = 'qf < 1'
80
    resp = resp.form.submit()
81
    assert resp.location.endswith('/manage/pricing/criterias/')
82
    criteria = Criteria.objects.latest('pk')
83
    assert criteria.label == 'QF < 1'
84
    assert criteria.category == category
85
    assert criteria.slug == 'qf-1-1'
86
    assert criteria.condition == 'qf < 1'
87
    assert criteria.order == 2
88

  
89

  
90
def test_edit_criteria(app, admin_user):
91
    category = CriteriaCategory.objects.create(label='QF')
92
    criteria = Criteria.objects.create(label='QF 1', category=category)
93
    criteria2 = Criteria.objects.create(label='QF 2', category=category)
94
    category2 = CriteriaCategory.objects.create(label='Foo')
95
    criteria3 = Criteria.objects.create(label='foo-bar', category=category2)
96

  
97
    app = login(app)
98
    resp = app.get('/manage/pricing/criterias/')
99
    resp = resp.click(href='/manage/pricing/criteria/category/%s/%s/edit/' % (category.pk, criteria.pk))
100
    resp.form['label'] = 'QF 1 bis'
101
    resp.form['slug'] = criteria2.slug
102
    resp.form['condition'] = 'qf <= 1 #'
103
    resp = resp.form.submit()
104
    assert resp.context['form'].errors['slug'] == ['Another criteria exists with the same identifier.']
105
    assert resp.context['form'].errors['condition'] == ['Invalid syntax.']
106

  
107
    resp.form['condition'] = 'qf <= 1'
108
    resp.form['slug'] = criteria3.slug
109
    resp = resp.form.submit()
110
    assert resp.location.endswith('/manage/pricing/criterias/')
111
    criteria.refresh_from_db()
112
    assert criteria.label == 'QF 1 bis'
113
    assert criteria.slug == 'foo-bar'
114
    assert criteria.condition == 'qf <= 1'
115

  
116

  
117
def test_delete_criteria(app, admin_user):
118
    category = CriteriaCategory.objects.create(label='QF')
119
    criteria = Criteria.objects.create(label='QF 1', category=category)
120

  
121
    app = login(app)
122
    resp = app.get('/manage/pricing/criterias/')
123
    resp = resp.click(href='/manage/pricing/criteria/category/%s/%s/delete/' % (category.pk, criteria.pk))
124
    resp = resp.form.submit()
125
    assert resp.location.endswith('/manage/pricing/criterias/')
126
    assert CriteriaCategory.objects.exists() is True
127
    assert Criteria.objects.exists() is False
128

  
129

  
130
def test_reorder_criterias(app, admin_user):
131
    category = CriteriaCategory.objects.create(label='QF')
132
    criteria1 = Criteria.objects.create(label='QF 1', category=category)
133
    criteria2 = Criteria.objects.create(label='QF 2', category=category)
134
    criteria3 = Criteria.objects.create(label='QF 3', category=category)
135
    criteria4 = Criteria.objects.create(label='QF 4', category=category)
136
    assert list(category.criterias.values_list('pk', flat=True).order_by('order')) == [
137
        criteria1.pk,
138
        criteria2.pk,
139
        criteria3.pk,
140
        criteria4.pk,
141
    ]
142
    assert list(category.criterias.values_list('order', flat=True).order_by('order')) == [1, 2, 3, 4]
143

  
144
    app = login(app)
145
    # missing get params
146
    app.get('/manage/pricing/criteria/category/%s/order/' % (category.pk), status=400)
147

  
148
    # bad new-order param
149
    bad_params = [
150
        # missing criteria3 in order
151
        ','.join(str(x) for x in [criteria1.pk, criteria2.pk, criteria4.pk]),
152
        # criteria1 mentionned twice
153
        ','.join(str(x) for x in [criteria1.pk, criteria2.pk, criteria3.pk, criteria4.pk, criteria1.pk]),
154
        # not an id
155
        'foo,1,2,3,4',
156
        ' 1 ,2,3,4',
157
    ]
158
    for bad_param in bad_params:
159
        app.get(
160
            '/manage/pricing/criteria/category/%s/order/' % (category.pk),
161
            params={'new-order': bad_param},
162
            status=400,
163
        )
164
    # not changed
165
    assert list(category.criterias.values_list('pk', flat=True).order_by('order')) == [
166
        criteria1.pk,
167
        criteria2.pk,
168
        criteria3.pk,
169
        criteria4.pk,
170
    ]
171
    assert list(category.criterias.values_list('order', flat=True).order_by('order')) == [1, 2, 3, 4]
172

  
173
    # change order
174
    app.get(
175
        '/manage/pricing/criteria/category/%s/order/' % (category.pk),
176
        params={
177
            'new-order': ','.join(str(x) for x in [criteria3.pk, criteria1.pk, criteria4.pk, criteria2.pk])
178
        },
179
    )
180
    assert list(category.criterias.values_list('pk', flat=True).order_by('order')) == [
181
        criteria3.pk,
182
        criteria1.pk,
183
        criteria4.pk,
184
        criteria2.pk,
185
    ]
186
    assert list(category.criterias.values_list('order', flat=True).order_by('order')) == [1, 2, 3, 4]
tests/pricing/manager/test_import_export.py
1
import copy
2
import json
3

  
4
import pytest
5
from webtest import Upload
6

  
7
from lingo.agendas.models import Agenda
8
from lingo.pricing.models import Criteria, CriteriaCategory, Pricing
9
from tests.utils import login
10

  
11
pytestmark = pytest.mark.django_db
12

  
13

  
14
def test_export_site(freezer, app, admin_user):
15
    freezer.move_to('2020-06-15')
16
    login(app)
17
    resp = app.get('/manage/pricing/')
18
    resp = resp.click('Export')
19

  
20
    resp = resp.form.submit()
21
    assert resp.headers['content-type'] == 'application/json'
22
    assert resp.headers['content-disposition'] == 'attachment; filename="export_pricing_config_20200615.json"'
23

  
24
    site_json = json.loads(resp.text)
25
    assert site_json == {
26
        'agendas': [],
27
        'pricing_categories': [],
28
        'pricing_models': [],
29
    }
30

  
31
    Agenda.objects.create(label='Foo Bar')
32
    resp = app.get('/manage/pricing/export/')
33
    resp = resp.form.submit()
34

  
35
    site_json = json.loads(resp.text)
36
    assert len(site_json['agendas']) == 1
37

  
38
    resp = app.get('/manage/pricing/export/')
39
    resp.form['agendas'] = False
40
    resp.form['pricing_categories'] = False
41
    resp.form['pricing_models'] = False
42
    resp = resp.form.submit()
43

  
44
    site_json = json.loads(resp.text)
45
    assert 'agendas' not in site_json
46
    assert 'pricing_categories' not in site_json
47
    assert 'pricing_models' not in site_json
48

  
49

  
50
@pytest.mark.freeze_time('2021-07-08')
51
def test_import_pricing(app, admin_user):
52
    pricing = Pricing.objects.create(label='Model')
53

  
54
    app = login(app)
55
    resp = app.get('/manage/pricing/%s/export/' % pricing.id)
56
    assert resp.headers['content-type'] == 'application/json'
57
    assert resp.headers['content-disposition'] == 'attachment; filename="export_pricing_model_20210708.json"'
58
    pricing_export = resp.text
59

  
60
    # existing pricing
61
    resp = app.get('/manage/pricing/', status=200)
62
    resp = resp.click('Import')
63
    resp.form['config_json'] = Upload('export.json', pricing_export.encode('utf-8'), 'application/json')
64
    resp = resp.form.submit()
65
    assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
66
    resp = resp.follow()
67
    assert 'No pricing model created. A pricing model has been updated.' not in resp.text
68
    assert Pricing.objects.count() == 1
69

  
70
    # new pricing
71
    Pricing.objects.all().delete()
72
    resp = app.get('/manage/pricing/', status=200)
73
    resp = resp.click('Import')
74
    resp.form['config_json'] = Upload('export.json', pricing_export.encode('utf-8'), 'application/json')
75
    resp = resp.form.submit()
76
    pricing = Pricing.objects.latest('pk')
77
    assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
78
    resp = resp.follow()
79
    assert 'A pricing model has been created. No pricing model updated.' not in resp.text
80
    assert Pricing.objects.count() == 1
81

  
82
    # multiple pricing
83
    pricings = json.loads(pricing_export)
84
    pricings['pricing_models'].append(copy.copy(pricings['pricing_models'][0]))
85
    pricings['pricing_models'].append(copy.copy(pricings['pricing_models'][0]))
86
    pricings['pricing_models'][1]['label'] = 'Foo bar 2'
87
    pricings['pricing_models'][1]['slug'] = 'foo-bar-2'
88
    pricings['pricing_models'][2]['label'] = 'Foo bar 3'
89
    pricings['pricing_models'][2]['slug'] = 'foo-bar-3'
90

  
91
    resp = app.get('/manage/pricing/', status=200)
92
    resp = resp.click('Import')
93
    resp.form['config_json'] = Upload('export.json', json.dumps(pricings).encode('utf-8'), 'application/json')
94
    resp = resp.form.submit()
95
    assert resp.location.endswith('/manage/pricing/')
96
    resp = resp.follow()
97
    assert '2 pricing models have been created. A pricing model has been updated.' in resp.text
98
    assert Pricing.objects.count() == 3
99

  
100
    Pricing.objects.all().delete()
101
    resp = app.get('/manage/pricing/', status=200)
102
    resp = resp.click('Import')
103
    resp.form['config_json'] = Upload('export.json', json.dumps(pricings).encode('utf-8'), 'application/json')
104
    resp = resp.form.submit().follow()
105
    assert '3 pricing models have been created. No pricing model updated.' in resp.text
106
    assert Pricing.objects.count() == 3
107

  
108

  
109
@pytest.mark.freeze_time('2021-07-08')
110
def test_import_criteria_category(app, admin_user):
111
    category = CriteriaCategory.objects.create(label='Foo bar')
112
    Criteria.objects.create(label='Foo', category=category)
113
    Criteria.objects.create(label='Baz', category=category)
114

  
115
    app = login(app)
116
    resp = app.get('/manage/pricing/criteria/category/%s/export/' % category.id)
117
    assert resp.headers['content-type'] == 'application/json'
118
    assert (
119
        resp.headers['content-disposition']
120
        == 'attachment; filename="export_pricing_category_foo-bar_20210708.json"'
121
    )
122
    category_export = resp.text
123

  
124
    # existing category
125
    resp = app.get('/manage/pricing/', status=200)
126
    resp = resp.click('Import')
127
    resp.form['config_json'] = Upload('export.json', category_export.encode('utf-8'), 'application/json')
128
    resp = resp.form.submit()
129
    assert resp.location.endswith('/manage/pricing/criterias/')
130
    resp = resp.follow()
131
    assert (
132
        'No pricing criteria category created. A pricing criteria category has been updated.' not in resp.text
133
    )
134
    assert CriteriaCategory.objects.count() == 1
135
    assert Criteria.objects.count() == 2
136

  
137
    # new category
138
    CriteriaCategory.objects.all().delete()
139
    resp = app.get('/manage/pricing/', status=200)
140
    resp = resp.click('Import')
141
    resp.form['config_json'] = Upload('export.json', category_export.encode('utf-8'), 'application/json')
142
    resp = resp.form.submit()
143
    assert resp.location.endswith('/manage/pricing/criterias/')
144
    resp = resp.follow()
145
    assert (
146
        'A pricing criteria category has been created. No pricing criteria category updated.' not in resp.text
147
    )
148
    assert CriteriaCategory.objects.count() == 1
149
    assert Criteria.objects.count() == 2
150

  
151
    # multiple categories
152
    categories = json.loads(category_export)
153
    categories['pricing_categories'].append(copy.copy(categories['pricing_categories'][0]))
154
    categories['pricing_categories'].append(copy.copy(categories['pricing_categories'][0]))
155
    categories['pricing_categories'][1]['label'] = 'Foo bar 2'
156
    categories['pricing_categories'][1]['slug'] = 'foo-bar-2'
157
    categories['pricing_categories'][2]['label'] = 'Foo bar 3'
158
    categories['pricing_categories'][2]['slug'] = 'foo-bar-3'
159

  
160
    resp = app.get('/manage/pricing/', status=200)
161
    resp = resp.click('Import')
162
    resp.form['config_json'] = Upload(
163
        'export.json', json.dumps(categories).encode('utf-8'), 'application/json'
164
    )
165
    resp = resp.form.submit()
166
    assert resp.location.endswith('/manage/pricing/')
167
    resp = resp.follow()
168
    assert (
169
        '2 pricing criteria categories have been created. A pricing criteria category has been updated.'
170
        in resp.text
171
    )
172
    assert CriteriaCategory.objects.count() == 3
173
    assert Criteria.objects.count() == 6
174

  
175
    CriteriaCategory.objects.all().delete()
176
    resp = app.get('/manage/pricing/', status=200)
177
    resp = resp.click('Import')
178
    resp.form['config_json'] = Upload(
179
        'export.json', json.dumps(categories).encode('utf-8'), 'application/json'
180
    )
181
    resp = resp.form.submit().follow()
182
    assert (
183
        '3 pricing criteria categories have been created. No pricing criteria category updated.' in resp.text
184
    )
185
    assert CriteriaCategory.objects.count() == 3
186
    assert Criteria.objects.count() == 6
187

  
188

  
189
@pytest.mark.freeze_time('2021-07-08')
190
def test_import_agenda(app, admin_user):
191
    agenda = Agenda.objects.create(label='Foo Bar')
192

  
193
    app = login(app)
194
    resp = app.get('/manage/pricing/agenda/%s/' % agenda.pk)
195
    resp = resp.click('Export')
196
    assert resp.headers['content-type'] == 'application/json'
197
    assert (
198
        resp.headers['content-disposition']
199
        == 'attachment; filename="export_pricing_agenda_foo-bar_20210708.json"'
200
    )
201
    agenda_export = resp.text
202

  
203
    # existing agenda
204
    resp = app.get('/manage/pricing/', status=200)
205
    resp = resp.click('Import')
206
    resp.form['config_json'] = Upload('export.json', agenda_export.encode('utf-8'), 'application/json')
207
    resp = resp.form.submit()
208
    assert resp.location.endswith('/manage/pricing/agenda/%s/' % agenda.pk)
209
    resp = resp.follow()
210
    assert 'An agenda has been updated.' not in resp.text
211
    assert Agenda.objects.count() == 1
212

  
213
    # unknown agenda
214
    Agenda.objects.all().delete()
215
    resp = app.get('/manage/pricing/', status=200)
216
    resp = resp.click('Import')
217
    resp.form['config_json'] = Upload('export.json', agenda_export.encode('utf-8'), 'application/json')
218
    resp = resp.form.submit()
219
    assert resp.context['form'].errors['config_json'] == ['Missing "foo-bar" agenda']
220

  
221
    # multiple pricing
222
    Agenda.objects.create(label='Foo Bar')
223
    Agenda.objects.create(label='Foo Bar 2')
224
    agendas = json.loads(agenda_export)
225
    agendas['agendas'].append(copy.copy(agendas['agendas'][0]))
226
    agendas['agendas'][1]['slug'] = 'foo-bar-2'
227

  
228
    resp = app.get('/manage/pricing/', status=200)
229
    resp = resp.click('Import')
230
    resp.form['config_json'] = Upload('export.json', json.dumps(agendas).encode('utf-8'), 'application/json')
231
    resp = resp.form.submit()
232
    assert resp.location.endswith('/manage/pricing/')
233
    resp = resp.follow()
234
    assert '2 agendas have been updated.' in resp.text
235
    assert Agenda.objects.count() == 2
tests/pricing/manager/test_pricing.py
1
import pytest
2

  
3
from lingo.pricing.models import Criteria, CriteriaCategory, Pricing, PricingCriteriaCategory
4
from tests.utils import login
5

  
6
pytestmark = pytest.mark.django_db
7

  
8

  
9
def test_add_pricing(app, admin_user):
10
    app = login(app)
11
    resp = app.get('/manage/')
12
    resp = resp.click('Pricing')
13
    resp = resp.click('New pricing model')
14
    resp.form['label'] = 'Pricing model for lunch'
15
    resp = resp.form.submit()
16
    pricing = Pricing.objects.latest('pk')
17
    assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
18
    assert pricing.label == 'Pricing model for lunch'
19
    assert pricing.slug == 'pricing-model-for-lunch'
20

  
21

  
22
def test_detail_pricing(app, admin_user):
23
    pricing = Pricing.objects.create(label='Model')
24

  
25
    app = login(app)
26
    resp = app.get('/manage/pricing/')
27
    resp = resp.click(href='/manage/pricing/%s/' % pricing.pk)
28
    assert '/manage/pricing/%s/edit/' % pricing.pk in resp
29
    assert '/manage/pricing/%s/delete/' % pricing.pk in resp
30

  
31

  
32
def test_edit_pricing(app, admin_user):
33
    pricing = Pricing.objects.create(label='Model 1')
34
    pricing2 = Pricing.objects.create(label='Model 2')
35

  
36
    app = login(app)
37
    resp = app.get('/manage/pricing/%s/' % pricing.pk)
38
    resp = resp.click(href='/manage/pricing/%s/edit/' % pricing.pk)
39
    resp.form['label'] = 'Model Foo'
40
    resp.form['slug'] = pricing2.slug
41
    resp = resp.form.submit()
42
    assert resp.context['form'].errors['slug'] == ['Pricing with this Identifier already exists.']
43

  
44
    resp.form['slug'] = 'foo-bar'
45
    resp = resp.form.submit()
46
    assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
47
    pricing.refresh_from_db()
48
    assert pricing.label == 'Model Foo'
49
    assert pricing.slug == 'foo-bar'
50

  
51

  
52
def test_delete_pricing(app, admin_user):
53
    pricing = Pricing.objects.create(label='Model')
54

  
55
    app = login(app)
56
    resp = app.get('/manage/pricing/%s/' % pricing.pk)
57
    resp = resp.click(href='/manage/pricing/%s/delete/' % pricing.pk)
58
    resp = resp.form.submit()
59
    assert resp.location.endswith('/manage/pricing/')
60
    assert Pricing.objects.exists() is False
61

  
62

  
63
def test_duplicate_pricing(app, admin_user):
64
    pricing = Pricing.objects.create(label='Model')
65
    assert Pricing.objects.count() == 1
66

  
67
    app = login(app)
68
    resp = app.get('/manage/pricing/%s/' % pricing.pk)
69
    resp = resp.click(href='/manage/pricing/%s/duplicate/' % pricing.pk)
70
    resp = resp.form.submit()
71
    assert Pricing.objects.count() == 2
72

  
73
    new_pricing = Pricing.objects.latest('pk')
74
    assert resp.location == '/manage/pricing/%s/' % new_pricing.pk
75
    assert new_pricing.pk != pricing.pk
76

  
77
    resp = resp.follow()
78
    assert 'copy-of-model' in resp.text
79

  
80
    resp = resp.click(href='/manage/pricing/%s/duplicate/' % new_pricing.pk)
81
    resp.form['label'] = 'hop'
82
    resp = resp.form.submit().follow()
83
    assert 'hop' in resp.text
84

  
85

  
86
def test_pricing_edit_extra_variables(app, admin_user):
87
    pricing = Pricing.objects.create(label='Model')
88
    assert pricing.extra_variables == {}
89

  
90
    app = login(app)
91
    resp = app.get('/manage/pricing/%s/' % pricing.id)
92
    assert '<label>Extra variables:</label>' not in resp.text
93
    resp = resp.click(href='/manage/pricing/%s/variable/' % pricing.id)
94
    resp.form['form-0-key'] = 'foo'
95
    resp.form['form-0-value'] = 'bar'
96
    resp = resp.form.submit().follow()
97
    pricing.refresh_from_db()
98
    assert pricing.extra_variables == {'foo': 'bar'}
99
    assert '<label>Extra variables:</label>' in resp.text
100
    assert '<i>foo</i>' in resp
101

  
102
    resp = resp.click(href='/manage/pricing/%s/variable/' % pricing.id)
103
    assert resp.form['form-TOTAL_FORMS'].value == '2'
104
    assert resp.form['form-0-key'].value == 'foo'
105
    assert resp.form['form-0-value'].value == 'bar'
106
    assert resp.form['form-1-key'].value == ''
107
    assert resp.form['form-1-value'].value == ''
108
    resp.form['form-0-value'] = 'bar-bis'
109
    resp.form['form-1-key'] = 'blah'
110
    resp.form['form-1-value'] = 'baz'
111
    resp = resp.form.submit().follow()
112
    pricing.refresh_from_db()
113
    assert pricing.extra_variables == {
114
        'foo': 'bar-bis',
115
        'blah': 'baz',
116
    }
117
    assert '<i>blah</i>, <i>foo</i>' in resp
118

  
119
    resp = resp.click(href='/manage/pricing/%s/variable/' % pricing.id)
120
    assert resp.form['form-TOTAL_FORMS'].value == '3'
121
    assert resp.form['form-0-key'].value == 'blah'
122
    assert resp.form['form-0-value'].value == 'baz'
123
    assert resp.form['form-1-key'].value == 'foo'
124
    assert resp.form['form-1-value'].value == 'bar-bis'
125
    assert resp.form['form-2-key'].value == ''
126
    assert resp.form['form-2-value'].value == ''
127
    resp.form['form-1-key'] = 'foo'
128
    resp.form['form-1-value'] = 'bar'
129
    resp.form['form-0-key'] = ''
130
    resp = resp.form.submit().follow()
131
    pricing.refresh_from_db()
132
    assert pricing.extra_variables == {
133
        'foo': 'bar',
134
    }
135
    assert '<i>foo</i>' in resp
136

  
137

  
138
def test_pricing_add_category(app, admin_user):
139
    pricing = Pricing.objects.create(label='Model')
140
    category1 = CriteriaCategory.objects.create(label='Cat 1')
141
    category2 = CriteriaCategory.objects.create(label='Cat 2')
142
    category3 = CriteriaCategory.objects.create(label='Cat 3')
143
    category4 = CriteriaCategory.objects.create(label='Cat 4')
144

  
145
    app = login(app)
146
    resp = app.get('/manage/pricing/%s/' % pricing.pk)
147
    resp = resp.click(href='/manage/pricing/%s/category/add/' % pricing.pk)
148
    assert list(resp.context['form'].fields['category'].queryset) == [
149
        category1,
150
        category2,
151
        category3,
152
        category4,
153
    ]
154
    resp.form['category'] = category1.pk
155
    resp = resp.form.submit()
156
    assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
157
    resp = resp.follow()
158
    assert '/manage/pricing/%s/category/add/' % pricing.pk in resp
159
    assert list(
160
        PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
161
    ) == [category1.pk]
162
    assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
163
        1
164
    ]
165

  
166
    resp = app.get('/manage/pricing/%s/category/add/' % pricing.pk)
167
    assert list(resp.context['form'].fields['category'].queryset) == [category2, category3, category4]
168
    resp.form['category'] = category4.pk
169
    resp = resp.form.submit().follow()
170
    assert list(
171
        PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
172
    ) == [category1.pk, category4.pk]
173
    assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
174
        1,
175
        2,
176
    ]
177

  
178
    resp = app.get('/manage/pricing/%s/category/add/' % pricing.pk)
179
    assert list(resp.context['form'].fields['category'].queryset) == [category2, category3]
180
    resp.form['category'] = category2.pk
181
    resp = resp.form.submit().follow()
182
    assert '/manage/pricing/%s/category/add/' % pricing.pk not in resp
183
    assert list(
184
        PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
185
    ) == [category1.pk, category4.pk, category2.pk]
186
    assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
187
        1,
188
        2,
189
        3,
190
    ]
191

  
192
    app.get('/manage/pricing/%s/category/add/' % pricing.pk, status=404)
193

  
194

  
195
def test_pricing_edit_category(app, admin_user):
196
    category1 = CriteriaCategory.objects.create(label='Cat 1')
197
    criteria1 = Criteria.objects.create(label='Crit 1', category=category1)
198
    criteria2 = Criteria.objects.create(label='Crit 2', category=category1)
199
    criteria3 = Criteria.objects.create(label='Crit 3', category=category1)
200
    criteria4 = Criteria.objects.create(label='Crit 4', category=category1)
201
    category2 = CriteriaCategory.objects.create(label='cat 2')
202
    criteria5 = Criteria.objects.create(label='Crit 5', category=category2)
203
    pricing = Pricing.objects.create(label='Model')
204
    pricing.categories.add(category1, through_defaults={'order': 1})
205
    pricing.categories.add(category2, through_defaults={'order': 2})
206

  
207
    app = login(app)
208
    resp = app.get('/manage/pricing/%s/' % pricing.pk)
209
    resp = resp.click(href='/manage/pricing/%s/category/%s/edit/' % (pricing.pk, category1.pk))
210
    assert list(resp.context['form'].fields['criterias'].queryset) == [
211
        criteria1,
212
        criteria2,
213
        criteria3,
214
        criteria4,
215
    ]
216
    assert list(resp.context['form'].initial['criterias']) == []
217
    resp.form['criterias'] = [criteria1.pk, criteria3.pk]
218
    resp = resp.form.submit()
219
    assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
220
    resp = resp.follow()
221
    assert list(pricing.criterias.order_by('pk')) == [criteria1, criteria3]
222

  
223
    resp = app.get('/manage/pricing/%s/category/%s/edit/' % (pricing.pk, category1.pk))
224
    assert list(resp.context['form'].initial['criterias']) == [criteria1, criteria3]
225
    resp.form['criterias'] = [criteria1.pk, criteria4.pk]
226
    resp = resp.form.submit().follow()
227
    assert list(pricing.criterias.order_by('pk')) == [criteria1, criteria4]
228

  
229
    resp = app.get('/manage/pricing/%s/category/%s/edit/' % (pricing.pk, category2.pk))
230
    assert list(resp.context['form'].fields['criterias'].queryset) == [criteria5]
231
    assert list(resp.context['form'].initial['criterias']) == []
232
    resp.form['criterias'] = [criteria5.pk]
233
    resp = resp.form.submit().follow()
234
    assert list(pricing.criterias.order_by('pk')) == [criteria1, criteria4, criteria5]
235

  
236

  
237
def test_pricing_delete_category(app, admin_user):
238
    category1 = CriteriaCategory.objects.create(label='Cat 1')
239
    criteria1 = Criteria.objects.create(label='Crit 1', category=category1)
240
    category2 = CriteriaCategory.objects.create(label='Cat 2')
241
    criteria2 = Criteria.objects.create(label='Crit 2', category=category2)
242
    pricing = Pricing.objects.create(label='Model')
243
    pricing.categories.add(category1, through_defaults={'order': 1})
244
    pricing.categories.add(category2, through_defaults={'order': 2})
245
    pricing.criterias.add(criteria1, criteria2)
246

  
247
    app = login(app)
248
    resp = app.get('/manage/pricing/%s/' % pricing.pk)
249
    resp = resp.click(href='/manage/pricing/%s/category/%s/delete/' % (pricing.pk, category1.pk))
250
    resp = resp.form.submit()
251
    assert resp.location.endswith('/manage/pricing/%s/' % pricing.pk)
252
    resp = resp.follow()
253
    assert list(pricing.categories.all()) == [category2]
254
    assert list(pricing.criterias.all()) == [criteria2]
255

  
256
    # not linked
257
    app.get('/manage/pricing/%s/category/%s/delete/' % (pricing.pk, category1.pk), status=404)
258
    # unknown
259
    app.get('/manage/pricing/%s/category/%s/delete/' % (pricing.pk, 0), status=404)
260

  
261

  
262
def test_pricing_reorder_categories(app, admin_user):
263
    category1 = CriteriaCategory.objects.create(label='Cat 1')
264
    category2 = CriteriaCategory.objects.create(label='Cat 2')
265
    category3 = CriteriaCategory.objects.create(label='Cat 3')
266
    category4 = CriteriaCategory.objects.create(label='Cat 4')
267
    pricing = Pricing.objects.create(label='Model')
268
    pricing.categories.add(category1, through_defaults={'order': 1})
269
    pricing.categories.add(category2, through_defaults={'order': 2})
270
    pricing.categories.add(category3, through_defaults={'order': 3})
271
    assert list(
272
        PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
273
    ) == [category1.pk, category2.pk, category3.pk]
274
    assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
275
        1,
276
        2,
277
        3,
278
    ]
279

  
280
    app = login(app)
281
    # missing get params
282
    app.get('/manage/pricing/%s/order/' % (pricing.pk), status=400)
283

  
284
    # bad new-order param
285
    bad_params = [
286
        # missing category3 in order
287
        ','.join(str(x) for x in [category1.pk, category2.pk]),
288
        # category1 mentionned twice
289
        ','.join(str(x) for x in [category1.pk, category2.pk, category3.pk, category1.pk]),
290
        # category4 not in pricing categories
291
        ','.join(str(x) for x in [category1.pk, category2.pk, category3.pk, category4.pk]),
292
        # not an id
293
        'foo,1,2,3',
294
        ' 1 ,2,3',
295
    ]
296
    for bad_param in bad_params:
297
        app.get(
298
            '/manage/pricing/%s/order/' % (pricing.pk),
299
            params={'new-order': bad_param},
300
            status=400,
301
        )
302
    # not changed
303
    assert list(
304
        PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
305
    ) == [category1.pk, category2.pk, category3.pk]
306
    assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
307
        1,
308
        2,
309
        3,
310
    ]
311

  
312
    # change order
313
    app.get(
314
        '/manage/pricing/%s/order/' % (pricing.pk),
315
        params={'new-order': ','.join(str(x) for x in [category3.pk, category1.pk, category2.pk])},
316
    )
317
    assert list(
318
        PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('category', flat=True)
319
    ) == [category3.pk, category1.pk, category2.pk]
320
    assert list(PricingCriteriaCategory.objects.filter(pricing=pricing).values_list('order', flat=True)) == [
321
        1,
322
        2,
323
        3,
324
    ]
0
-