Projet

Général

Profil

0001-tracking_code-add-tests-on-formdata-access-38073.patch

Nicolas Roche, 11 février 2020 14:24

Télécharger (17,1 ko)

Voir les différences:

Subject: [PATCH 1/3] tracking_code: add tests on formdata access (#38073)

 tests/test_tracking_code.py | 384 +++++++++++++++++++++++++++++++++++-
 1 file changed, 378 insertions(+), 6 deletions(-)
tests/test_tracking_code.py
1 1
import pytest
2 2

  
3
from quixote import cleanup
4
from wcs import fields
5
from wcs.admin.settings import UserFieldsFormDef
3 6
from wcs.formdef import FormDef
7
from wcs.qommon.ident.password_accounts import PasswordAccount
8
from wcs.roles import Role
9
from wcs.wf.form import FormWorkflowStatusItem, WorkflowFormFieldsFormDef
10
from wcs.workflows import Workflow, ChoiceWorkflowStatusItem
4 11

  
5
from utilities import create_temporary_pub, clean_temporary_pub
12
from utilities import get_app, login, create_temporary_pub, clean_temporary_pub
6 13

  
7 14

  
8 15
def pytest_generate_tests(metafunc):
9 16
    if 'pub' in metafunc.fixturenames:
10 17
        metafunc.parametrize('pub', ['pickle', 'sql'], indirect=True)
11 18

  
19
def teardown_module(module):
20
    clean_temporary_pub()
12 21

  
13 22
@pytest.fixture
14 23
def pub(request):
15
    return create_temporary_pub(sql_mode=(request.param == 'sql'))
24
    cleanup()
25
    pub = create_temporary_pub(sql_mode=(request.param == 'sql'))
26
    pub.cfg['identification'] = {'methods': ['password']}
27
    pub.cfg['language'] = {'language': 'en'}
28
    pub.write_cfg()
29
    return pub
30

  
31
@pytest.fixture
32
def users(pub):
33
    def create_user(name):
34
        user = pub.user_class()
35
        user.email = '%s@example.net' % name
36
        user.name = name
37
        user.store()
38
        account = PasswordAccount(id=name)
39
        account.set_password(name)
40
        account.user_id = user.id
41
        account.store()
16 42

  
43
        user_formdef = UserFieldsFormDef(pub)
44
        user_formdef.fields = [
45
            fields.StringField(
46
                id='_first_name', label='first name',
47
                type='string', extra_css_class='autocomplete-given-name'),
48
        ]
49
        user_formdef.store()
50
        user.form_data = {'_first_name': name}
51
        user.set_attributes_from_formdata(user.form_data)
52
        user.store()
53
        return user
17 54

  
18
def teardown_module(module):
19
    clean_temporary_pub()
55
    pub.user_class.wipe()
56
    PasswordAccount.wipe()
57
    user1 = create_user('user1')
58
    user2 = create_user('user2')
59
    agent1 = create_user('agent1')
60
    agent2 = create_user('agent2')
61
    Role.wipe()
62
    role1 = Role(name='Submitters')
63
    role1.allows_backoffice_access = True
64
    role1.store()
65
    role2 = Role(name='Receivers')
66
    role2.store()
67
    agent1.roles = [role1.id]
68
    agent1.store()
69
    agent2.roles = [role2.id]
70
    agent2.store()
71
    return {
72
        'anonymous': None,
73
        'user1': user1,
74
        'user2': user2,
75
        'agent1': agent1,
76
        'agent2': agent2,
77
    }
78

  
79
@pytest.fixture
80
def simple_formdef(users):
81
    FormDef.wipe()
82
    formdef = FormDef()
83
    formdef.name = 'test'
84
    formdef.fields = []
85
    formdef.backoffice_submission_roles = users['agent1'].roles[:]
86
    formdef.workflow_roles = {'_receiver': users['agent2'].roles[0]}
87
    formdef.enable_tracking_codes = True
88
    workflow = Workflow.get_default_workflow()
89
    formdef.workflow_id = workflow.id
90
    formdef.store()
91
    return formdef
92

  
93
@pytest.fixture
94
def prefill_formdef(users):
95
    FormDef.wipe()
96
    formdef = FormDef()
97
    formdef.name = 'test'
98
    formdef.fields = [
99
        fields.PageField(id='0', label='1st page', type='page'),
100
        fields.CommentField(
101
            id='2', type='comment', display_locations=['validation', 'summary'],
102
            label='{{form_user_display_name}}'),
103
        fields.StringField(
104
            id='3', label='prefill-string-page1', required=False,
105
            prefill={'type': 'string', 'value': '{{form_user_display_name}}'}),
106
        fields.StringField(
107
            id='p3', label='prefill-user-page1', required=False,
108
            prefill={'type': 'user', 'value': '_first_name'}),
20 109

  
110
        # updated on draft using tracking code
111
        fields.PageField(id='4', label='2nd page', type='page'),
112
        fields.StringField(
113
            id='4', label='prefill-string-page2', required=False,
114
            prefill={'type': 'string', 'value': '{{form_user_display_name}}'}),
115
        fields.StringField(
116
            id='p4', label='prefill-user-page2', required=False,
117
            prefill={'type': 'user', 'value': '_first_name'}),
118
    ]
119
    formdef.backoffice_submission_roles = users['agent1'].roles[:]
120
    formdef.workflow_roles = {'_receiver': users['agent2'].roles[0]}
121
    formdef.enable_tracking_codes = True
122
    formdef.store()
123

  
124
    Workflow.wipe()
125
    workflow = Workflow(name='test')
126
    st1 = workflow.add_status('Status1')
127
    st2 = workflow.add_status('Status2')
128

  
129
    display_form = FormWorkflowStatusItem()
130
    display_form.formdef = WorkflowFormFieldsFormDef(item=display_form)
131
    display_form.formdef.fields = [
132
        # updated on workflow using tracking code
133
        fields.StringField(
134
            id='5', label='prefill-string-workflow', required=False,
135
            prefill={'type': 'string', 'value': '{{form_user_display_name}}'}),
136
        fields.StringField(
137
            id='p5', label='prefill-user-workflow', required=False,
138
            prefill={'type': 'user', 'value': '_first_name'}),
139
    ]
140
    display_form.by = ['_submitter']
141
    display_form.parent = st2
142

  
143
    jump = ChoiceWorkflowStatusItem()
144
    jump.id = '_jump'
145
    jump.label = 'Go form'
146
    jump.by = ['_submitter']
147
    jump.status = st2.id
148
    jump.parent = st1
149

  
150
    st1.items.append(jump)
151
    st2.items.append(display_form)
152
    workflow.store()
153

  
154
    formdef.workflow_id = workflow.id
155
    formdef.store()
156
    return formdef
157

  
158
def submit_demand(pub, formdef, user, is_front=True, nb_submit=1):
159
    assert nb_submit > 0
160
    app = get_app(pub)
161

  
162
    if user:
163
        app = login(app, username=user.name, password=user.name)
164
    if is_front:
165
        resp = app.get('/test/')
166
        assert '<h3>Tracking code</h3>' in resp.text
167
    else:
168
        resp = app.get('/backoffice/submission/test/')
169
        assert '<h3>Tracking Code</h3>' in resp.text
170

  
171
    formdef.data_class().wipe()
172
    resp = resp.form.submit('submit')
173
    for i in range(1, nb_submit):
174
        resp = resp.form.submit('submit')
175
    assert formdef.data_class().count() == 1
176

  
177
def get_comment_value(resp):
178
    html = resp.html.find('div', attrs={'class': 'comment-field'})
179
    if html:
180
        return html.p.text
181
    else:  # empty comment is not displayed in summary
182
        return ''
183

  
184
def get_field_value(resp, field_label):
185
    # validation page
186
    for html in resp.html.find_all('div', attrs={'class': 'WcsExtraStringWidget'}):
187
        if html.label.text == field_label:
188
            return html.input.get('value') or ''
189
    # summary
190
    for html in resp.html.find_all('div', attrs={'class': 'field'}):
191
        if html.span.text == field_label:
192
            return html.div.text
193
    return ''  # empty field is not displayed in summary
21 194

  
22 195
def test_tracking_code(pub):
23 196
    klass = pub.tracking_code_class
24 197
    klass.wipe()
25 198

  
26 199
    code = klass()
27 200
    code.store()
28 201
    code = klass()
......
45 218
    code.store()
46 219
    assert klass.count() == 2
47 220

  
48 221
    assert klass.get(code.id).formdef_id == code.formdef_id
49 222
    assert klass.get(code.id).formdata_id == code.formdata_id
50 223

  
51 224
    assert klass.get(code.id).formdata.tracking_code == code.id
52 225

  
53

  
54 226
def test_tracking_code_duplicate(pub):
55 227
    klass = pub.tracking_code_class
56 228
    klass.wipe()
57 229

  
58 230
    code = klass()
59 231
    code.store()
60 232
    code_id = code.id
61 233

  
......
72 244
            return code_id
73 245
        else:
74 246
            marker['done'] = True
75 247
            return real_get_new_id(cls)
76 248
    klass.get_new_id = fake_get_new_id
77 249
    code.store()
78 250
    klass.get_new_id = real_get_new_id
79 251

  
80
    assert marker.get('done') # makes sure we got to the real new id code
252
    assert marker.get('done')  # makes sure we got to the real new id code
81 253
    assert klass.count() == 2
254

  
255
@pytest.mark.parametrize("submitter, is_front, agent, expected_access", [
256
    ('anonymous', True, 'anonymous', 'login'),
257
    ('anonymous', True, 'user1', 'deny'),
258
    ('anonymous', True, 'user2', 'deny'),
259
    ('anonymous', True, 'agent1', 'deny'),
260
    ('anonymous', True, 'agent2', 'deny'),
261
    ('agent1', False, 'anonymous', 'login'),
262
    ('agent1', False, 'user1', 'deny'),
263
    ('agent1', False, 'user2', 'deny'),
264
    ('agent1', False, 'agent1', 'deny'),
265
    ('agent1', False, 'agent2', 'deny'),
266
    ('user1', True, 'anonymous', 'login'),
267
    ('user1', True, 'user1', 'front'),
268
    ('user1', True, 'user2', 'deny'),
269
    ('user1', True, 'agent1', 'deny'),
270
    ('user1', True, 'agent2', 'deny'),
271
])
272
def test_fo_direct_access_to_draft(nocache, pub, users, simple_formdef,
273
                                   submitter, is_front, agent, expected_access):
274
    submit_demand(pub, simple_formdef, users[submitter], is_front, 1)
275
    formdata = simple_formdef.data_class().select()[0]
276
    assert formdata.is_draft() is True
277
    formdata_id = formdata.id
278

  
279
    app = get_app(pub)
280
    if agent != 'anonymous':
281
        app = login(app, username=users[agent].name, password=users[agent].name)
282
    resp = app.get('/test/%s' % formdata_id)
283
    if expected_access == 'deny':
284
        assert resp.follow(status=403)
285
    elif expected_access == 'login':
286
        resp = resp.follow()
287
        assert resp.location.startswith('http://example.net/login/?next=')
288
    elif expected_access == 'front':
289
        resp = resp.follow()
290
        assert 'http://example.net/test/?mt=' in resp.location
291
        resp = resp.follow()
292
        assert '<title>Forms - test</title>' in resp.text
293
    else:
294
        assert expected_access in ('login', 'deny', 'front')
295

  
296
@pytest.mark.parametrize("submitter, is_front, agent, expected_access", [
297
    ('anonymous', True, 'anonymous', 'login'),
298
    ('anonymous', True, 'user1', 'deny'),
299
    ('anonymous', True, 'user2', 'deny'),
300
    ('anonymous', True, 'agent1', 'deny'),
301
    ('anonymous', True, 'agent2', 'back'),
302
    ('agent1', False, 'anonymous', 'login'),
303
    ('agent1', False, 'user1', 'deny'),
304
    ('agent1', False, 'user2', 'deny'),
305
    ('agent1', False, 'agent1', 'deny'),
306
    ('agent1', False, 'agent2', 'back'),
307
    ('user1', True, 'anonymous', 'login'),
308
    ('user1', True, 'user1', 'front'),
309
    ('user1', True, 'user2', 'deny'),
310
    ('user1', True, 'agent1', 'deny'),
311
    ('user1', True, 'agent2', 'back'),
312
])
313
def test_fo_direct_access_to_demand(nocache, pub, users, simple_formdef,
314
                                    submitter, is_front, agent, expected_access):
315
    submit_demand(pub, simple_formdef, users[submitter], is_front, 2)
316
    formdata = simple_formdef.data_class().select()[0]
317
    assert formdata.is_draft() is False
318
    formdata_id = formdata.id
319

  
320
    app = get_app(pub)
321
    if agent != 'anonymous':
322
        app = login(app, username=users[agent].name, password=users[agent].name)
323
    resp = app.get('/test/%s' % formdata_id)
324
    assert resp.location == 'http://example.net/test/%s/' % formdata_id
325
    if expected_access == 'deny':
326
        assert resp.follow(status=403)
327
    elif expected_access == 'login':
328
        resp = resp.follow()
329
        assert resp.location.startswith('http://example.net/login/?next=')
330
    elif expected_access == 'front':
331
        resp = resp.follow()
332
        assert '<title>Forms - test</title>' in resp.text
333
    elif expected_access == 'back':
334
        resp = resp.follow()
335
        assert '/backoffice/management/test/%s/' % formdata_id in resp.location
336
        resp = resp.follow()
337
        assert 'Back Office of wcs - test - %s' % formdata_id in resp.text
338
    else:
339
        assert expected_access in ('login', 'deny', 'front', 'back')
340

  
341
@pytest.mark.parametrize("submitter, is_front, agent, expected_access, expected_owner", [
342
    ('anonymous', True, 'anonymous', 'allow', 'anonymous'),
343
    ('anonymous', True, 'user1', 'allow', 'anonymous'),
344
    ('anonymous', True, 'user2', 'allow', 'anonymous'),
345
    ('anonymous', True, 'agent1', 'allow', 'anonymous'),
346
    ('anonymous', True, 'agent2', 'allow', 'anonymous'),
347
    ('agent1', False, 'anonymous', 'allow', 'anonymous'),
348
    ('agent1', False, 'user1', 'allow', 'anonymous'),
349
    ('agent1', False, 'user2', 'allow', 'anonymous'),
350
    ('agent1', False, 'agent1', 'allow', 'anonymous'),
351
    ('agent1', False, 'agent2', 'allow', 'anonymous'),
352
    ('user1', True, 'anonymous', 'allow', 'user1'),
353
    ('user1', True, 'user1', 'allow', 'user1'),
354
    ('user1', True, 'user2', 'allow', 'user1'),
355
    ('user1', True, 'agent1', 'allow', 'user1'),
356
    ('user1', True, 'agent2', 'allow', 'user1'),
357
])
358
def test_fo_indirect_access_to_draft(nocache, pub, users, prefill_formdef,
359
         submitter, is_front, agent, expected_access, expected_owner):
360
    user = users[agent]
361
    expected_owner = users[expected_owner]
362
    expected_new_owner = user
363

  
364
    submit_demand(pub, prefill_formdef, users[submitter], is_front, 1)
365
    formdata = prefill_formdef.data_class().select()[0]
366
    assert formdata.is_draft() is True
367
    formdata_id = formdata.id
368

  
369
    app = get_app(pub)
370
    if user:
371
        app = login(app, username=user.name, password=user.name)
372
    resp = app.get('/')
373
    resp.forms[0]['code'] = formdata.tracking_code
374
    resp = resp.forms[0].submit()
375
    resp = resp.follow()
376
    if expected_access == 'login':
377
        assert resp.location.startswith('http://example.net/login/?ReturnUrl=')
378
        return
379
    resp = resp.follow()
380
    resp = resp.follow()
381
    assert '<title>Forms - test</title>' in resp.text
382
    resp = resp.forms[1].submit('submit')  # submit page 2
383

  
384
    formdata = prefill_formdef.data_class().select()[0]
385
    assert formdata.id == formdata_id  # formdata must be reloaded here
386
    formdata_user = getattr(formdata.user, 'name', '')
387
    owner_value = getattr(expected_owner, 'name', '')
388
    new_owner_value = getattr(expected_new_owner, 'name', '')
389

  
390
    if expected_new_owner:
391
        assert formdata_user == new_owner_value
392
    else:  # formdata_user is not overidden by anonymous user
393
        assert formdata_user == owner_value
394
    assert get_comment_value(resp) == new_owner_value
395
    assert get_field_value(resp, 'prefill-string-page1') == owner_value
396
    assert get_field_value(resp, 'prefill-user-page1') == owner_value
397
    assert get_field_value(resp, 'prefill-string-page2') == new_owner_value
398
    assert get_field_value(resp, 'prefill-user-page2') == new_owner_value
399

  
400
@pytest.mark.parametrize("submitter, is_front, agent, expected_access, expected_owner", [
401
    ('anonymous', True, 'anonymous', 'allow', 'anonymous'),
402
    ('anonymous', True, 'user1', 'allow', 'anonymous'),
403
    ('anonymous', True, 'user2', 'allow', 'anonymous'),
404
    ('anonymous', True, 'agent1', 'allow', 'anonymous'),
405
    ('anonymous', True, 'agent2', 'allow', 'anonymous'),
406
    ('agent1', False, 'anonymous', 'allow', 'anonymous'),
407
    ('agent1', False, 'user1', 'allow', 'anonymous'),
408
    ('agent1', False, 'user2', 'allow', 'anonymous'),
409
    ('agent1', False, 'agent1', 'allow', 'anonymous'),
410
    ('agent1', False, 'agent2', 'allow', 'anonymous'),
411
    ('user1', True, 'anonymous', 'allow', 'user1'),
412
    ('user1', True, 'user1', 'allow', 'user1'),
413
    ('user1', True, 'user2', 'allow', 'user1'),
414
    ('user1', True, 'agent1', 'allow', 'user1'),
415
    ('user1', True, 'agent2', 'allow', 'user1'),
416
])
417
def test_fo_indirect_access_to_demand(nocache, pub, users, prefill_formdef,
418
         submitter, is_front, agent, expected_access, expected_owner):
419
    user = users[agent]
420
    expected_owner = users[expected_owner]
421
    expected_new_owner = user
422

  
423
    submit_demand(pub, prefill_formdef, users[submitter], is_front, 3)
424
    formdata = prefill_formdef.data_class().select()[0]
425
    assert formdata.is_draft() is False
426
    formdata_id = formdata.id
427

  
428
    app = get_app(pub)
429
    if user:
430
        app = login(app, username=user.name, password=user.name)
431
    resp = app.get('/')
432
    resp.forms[0]['code'] = formdata.tracking_code
433
    resp = resp.forms[0].submit()
434
    resp = resp.follow()
435
    if expected_access == 'login':
436
        return
437
    resp = resp.follow()
438
    assert '<title>Forms - test</title>' in resp.text
439
    resp = resp.form.submit('button_jump')  # go to display_form
440
    resp = resp.follow()
441

  
442
    formdata = prefill_formdef.data_class().select()[0]
443
    assert formdata.id == formdata_id  # formdata must be reloaded here
444
    formdata_user = getattr(formdata.user, 'name', '')
445
    owner_value = getattr(expected_owner, 'name', '')
446
    new_owner_value = getattr(expected_new_owner, 'name', '')
447

  
448
    assert formdata_user == owner_value
449
    assert get_comment_value(resp) == owner_value
450
    assert get_field_value(resp, 'prefill-string-page1') == owner_value
451
    assert get_field_value(resp, 'prefill-user-page1') == owner_value
452
    assert get_field_value(resp, 'prefill-string-workflow') == owner_value
453
    assert get_field_value(resp, 'prefill-user-workflow') == new_owner_value
82
-