Projet

Général

Profil

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

Nicolas Roche, 05 février 2020 16:54

Télécharger (15,2 ko)

Voir les différences:

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

 tests/test_tracking_code.py | 359 +++++++++++++++++++++++++++++++++++-
 1 file changed, 353 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
......
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()
......
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_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_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("agent", [
342
    ('anonymous'), ('user1'), ('user2'), ('agent1'), ('agent2')])
343
@pytest.mark.parametrize("submitter, is_front, expected_owner", [
344
    ('anonymous', True, 'anonymous'),
345
    ('agent1', False, 'anonymous'),
346
    ('user1', True, 'user1'),
347
])
348
def test_indirect_access_to_draft(nocache, pub, users, prefill_formdef,
349
                                  submitter, is_front, agent, expected_owner):
350
    user = users[agent]
351
    expected_owner = users[expected_owner]
352
    expected_new_owner = user
353

  
354
    submit_demand(pub, prefill_formdef, users[submitter], is_front, 1)
355
    formdata = prefill_formdef.data_class().select()[0]
356
    assert formdata.is_draft() is True
357
    formdata_id = formdata.id
358

  
359
    app = get_app(pub)
360
    if user:
361
        app = login(app, username=user.name, password=user.name)
362
    resp = app.get('/')
363
    resp.forms[0]['code'] = formdata.tracking_code
364
    resp = resp.forms[0].submit()
365
    resp = resp.follow()
366
    resp = resp.follow()
367
    resp = resp.follow()
368
    assert '<title>Forms - test</title>' in resp.text
369
    resp = resp.forms[1].submit('submit')  # submit page 2
370

  
371
    formdata = prefill_formdef.data_class().select()[0]
372
    assert formdata.id == formdata_id  # formdata must be reloaded here
373
    formdata_user = getattr(formdata.user, 'name', '')
374
    owner_value = getattr(expected_owner, 'name', '')
375
    new_owner_value = getattr(expected_new_owner, 'name', '')
376

  
377
    if expected_new_owner:
378
        assert formdata_user == new_owner_value
379
    else:  # formdata_user is not overidden by anonymous user
380
        assert formdata_user == owner_value
381
    assert get_comment_value(resp) == new_owner_value
382
    assert get_field_value(resp, 'prefill-string-page1') == owner_value
383
    assert get_field_value(resp, 'prefill-user-page1') == owner_value
384
    assert get_field_value(resp, 'prefill-string-page2') == new_owner_value
385
    assert get_field_value(resp, 'prefill-user-page2') == new_owner_value
386

  
387
@pytest.mark.parametrize("agent", [
388
    ('anonymous'), ('user1'), ('user2'), ('agent1'), ('agent2')])
389
@pytest.mark.parametrize("submitter, is_front, expected_owner", [
390
    ('anonymous', True, 'anonymous'),
391
    ('agent1', False, 'anonymous'),
392
    ('user1', True, 'user1'),
393
])
394
def test_indirect_access_to_demand(nocache, pub, users, prefill_formdef,
395
                                   submitter, is_front, agent, expected_owner):
396
    user = users[agent]
397
    expected_owner = users[expected_owner]
398
    expected_new_owner = user
399

  
400
    submit_demand(pub, prefill_formdef, users[submitter], is_front, 3)
401
    formdata = prefill_formdef.data_class().select()[0]
402
    assert formdata.is_draft() is False
403
    formdata_id = formdata.id
404

  
405
    app = get_app(pub)
406
    if user:
407
        app = login(app, username=user.name, password=user.name)
408
    resp = app.get('/')
409
    resp.forms[0]['code'] = formdata.tracking_code
410
    resp = resp.forms[0].submit()
411
    resp = resp.follow()
412
    resp = resp.follow()
413
    assert '<title>Forms - test</title>' in resp.text
414
    resp = resp.form.submit('button_jump')  # go to display_form
415
    resp = resp.follow()
416

  
417
    formdata = prefill_formdef.data_class().select()[0]
418
    assert formdata.id == formdata_id  # formdata must be reloaded here
419
    formdata_user = getattr(formdata.user, 'name', '')
420
    owner_value = getattr(expected_owner, 'name', '')
421
    new_owner_value = getattr(expected_new_owner, 'name', '')
422

  
423
    assert formdata_user == owner_value
424
    assert get_comment_value(resp) == owner_value
425
    assert get_field_value(resp, 'prefill-string-page1') == owner_value
426
    assert get_field_value(resp, 'prefill-user-page1') == owner_value
427
    assert get_field_value(resp, 'prefill-string-workflow') == owner_value
428
    assert get_field_value(resp, 'prefill-user-workflow') == new_owner_value
82
-