Projet

Général

Profil

0001-misc-split-backoffice_pages-tests-carddata.patch

Lauréline Guérin, 16 novembre 2020 15:22

Télécharger (33,7 ko)

Voir les différences:

Subject: [PATCH 1/2] misc: split backoffice_pages tests (carddata)

 tests/backoffice_pages/test_all.py      | 454 +--------------------
 tests/backoffice_pages/test_carddata.py | 504 ++++++++++++++++++++++++
 2 files changed, 505 insertions(+), 453 deletions(-)
 create mode 100644 tests/backoffice_pages/test_carddata.py
tests/backoffice_pages/test_all.py
18 18
from django.utils.six import StringIO, BytesIO
19 19
from django.utils.six.moves.urllib import parse as urllib
20 20

  
21
from webtest import Upload
22

  
23 21
from quixote import get_publisher
24 22
from quixote.http_request import Upload as QuixoteUpload
25 23
from wcs.api_utils import sign_url
......
46 44
from wcs.wf.create_formdata import CreateFormdataWorkflowStatusItem, Mapping
47 45
from wcs.wf.create_carddata import CreateCarddataWorkflowStatusItem
48 46
from wcs.carddef import CardDef
49
from wcs.categories import Category, CardDefCategory
47
from wcs.categories import Category
50 48
from wcs.formdef import FormDef
51 49
from wcs.logged_errors import LoggedError
52 50
from wcs import fields
......
6287 6285
    assert 'HELLO WORLD 2' in resp.text
6288 6286

  
6289 6287

  
6290
def test_carddata_management(pub, studio):
6291
    CardDef.wipe()
6292
    user = create_user(pub)
6293
    app = login(get_app(pub))
6294
    resp = app.get('/backoffice/')
6295
    assert 'Cards' not in resp.text
6296
    carddef = CardDef()
6297
    carddef.name = 'foo'
6298
    carddef.fields = [
6299
        fields.StringField(id='1', label='Test', type='string', varname='foo'),
6300
        fields.StringField(id='2', label='Condi', type='string', varname='bar',
6301
            required=True, condition={'type': 'django', 'value': 'form_var_foo == "ok"'}),
6302
    ]
6303
    carddef.store()
6304
    carddef.data_class().wipe()
6305

  
6306
    resp = app.get('/backoffice/')
6307
    assert 'Cards' not in resp.text
6308

  
6309
    carddef.backoffice_submission_roles = user.roles
6310
    carddef.store()
6311
    resp = app.get('/backoffice/')
6312
    assert 'Cards' in resp.text
6313

  
6314
    carddef.backoffice_submission_roles = None
6315
    carddef.workflow_roles = {'_editor': user.roles[0]}
6316
    carddef.store()
6317
    resp = app.get('/backoffice/')
6318
    assert 'Cards' in resp.text
6319

  
6320
    resp = app.get('/backoffice/data/')
6321
    resp = resp.click('foo')
6322
    assert 'Add' not in resp.text
6323

  
6324
    carddef.backoffice_submission_roles = user.roles
6325
    carddef.store()
6326

  
6327
    resp = app.get('/backoffice/data/')
6328
    resp = resp.click('foo')
6329
    assert resp.text.count('<tr') == 1  # header
6330
    assert 'Add' in resp.text
6331
    resp = resp.click('Add')
6332
    resp.form['f1'] = 'blah'
6333

  
6334
    live_url = resp.html.find('form').attrs['data-live-url']
6335
    assert '/backoffice/data/foo/add/live' in live_url
6336
    live_resp = app.post(live_url, params=resp.form.submit_fields())
6337
    assert live_resp.json['result']['1']['visible']
6338
    assert not live_resp.json['result']['2']['visible']
6339
    resp.form['f1'] = 'ok'
6340
    live_resp = app.post(live_url, params=resp.form.submit_fields())
6341
    assert live_resp.json['result']['1']['visible']
6342
    assert live_resp.json['result']['2']['visible']
6343
    resp.form['f2'] = 'blah'
6344

  
6345
    resp = resp.form.submit('submit')
6346
    assert resp.location.endswith('/backoffice/data/foo/1/')
6347
    resp = resp.follow()
6348
    assert 'Edit Card' in resp.text
6349
    assert 'Delete Card' in resp.text
6350

  
6351
    carddata = carddef.data_class().select()[0]
6352
    assert carddata.data == {'1': 'ok', '2': 'blah'}
6353
    assert carddata.user_id is None
6354
    assert carddata.submission_agent_id == str(user.id)
6355
    assert carddata.evolution[0].who == str(user.id)
6356
    assert 'Original Submitter' not in resp.text
6357

  
6358
    resp = app.get('/backoffice/data/')
6359
    resp = resp.click('foo')
6360
    assert resp.text.count('<tr') == 2  # header + row of data
6361

  
6362

  
6363
def test_carddata_management_categories(pub, studio):
6364
    user = create_user(pub)
6365

  
6366
    CardDef.wipe()
6367
    carddef = CardDef()
6368
    carddef.name = 'foo'
6369
    carddef.fields = []
6370
    carddef.backoffice_submission_roles = None
6371
    carddef.workflow_roles = {'_editor': user.roles[0]}
6372
    carddef.store()
6373

  
6374
    carddef2 = CardDef()
6375
    carddef2.name = 'card title 2'
6376
    carddef2.fields = []
6377
    carddef2.backoffice_submission_roles = None
6378
    carddef2.workflow_roles = {'_editor': user.roles[0]}
6379
    carddef2.store()
6380

  
6381
    CardDefCategory.wipe()
6382
    cat = CardDefCategory(name='Foo')
6383
    cat.store()
6384
    cat2 = CardDefCategory(name='Bar')
6385
    cat2.store()
6386

  
6387
    app = login(get_app(pub))
6388
    resp = app.get('/backoffice/data/')
6389
    assert '<h3>Misc</h3>' not in resp.text
6390
    assert '<h3>Foo</h3>' not in resp.text
6391
    assert '<h3>Bar</h3>' not in resp.text
6392

  
6393
    carddef.category = cat2
6394
    carddef.store()
6395
    resp = app.get('/backoffice/data/')
6396
    assert '<h3>Misc</h3>' in resp.text
6397
    assert '<h3>Foo</h3>' not in resp.text
6398
    assert '<h3>Bar</h3>' in resp.text
6399

  
6400
    carddef2.category = cat
6401
    carddef2.store()
6402
    resp = app.get('/backoffice/data/')
6403
    assert '<h3>Misc</h3>' not in resp.text
6404
    assert '<h3>Foo</h3>' in resp.text
6405
    assert '<h3>Bar</h3>' in resp.text
6406

  
6407

  
6408
def test_studio_card_item_link(pub, studio):
6409
    user = create_user(pub)
6410
    CardDef.wipe()
6411
    carddef = CardDef()
6412
    carddef.name = 'foo'
6413
    carddef.fields = [
6414
        fields.StringField(id='1', label='Test', type='string', varname='foo'),
6415
    ]
6416
    carddef.backoffice_submission_roles = user.roles
6417
    carddef.workflow_roles = {'_editor': user.roles[0]}
6418
    carddef.digest_template = 'card {{form_var_foo}}'
6419
    carddef.store()
6420
    carddef.data_class().wipe()
6421

  
6422
    card = carddef.data_class()()
6423
    card.data = {'1': 'plop'}
6424
    card.just_created()
6425
    card.store()
6426

  
6427
    carddef2 = CardDef()
6428
    carddef2.name = 'bar'
6429
    carddef2.fields = [
6430
        fields.ItemField(id='1', label='Test', type='item',
6431
            data_source={'type': 'carddef:foo', 'value': ''}),
6432
    ]
6433
    carddef2.backoffice_submission_roles = user.roles
6434
    carddef2.workflow_roles = {'_editor': user.roles[0]}
6435
    carddef2.store()
6436
    carddef2.data_class().wipe()
6437

  
6438
    app = login(get_app(pub))
6439
    resp = app.get('/backoffice/data/')
6440
    resp = resp.click('bar')
6441
    resp = resp.click('Add')
6442
    resp.form['f1'] = card.id
6443
    resp = resp.form.submit('submit')
6444
    assert resp.location.endswith('/backoffice/data/bar/1/')
6445
    resp = resp.follow()
6446
    resp = resp.click('card plop')
6447
    assert '<div class="value">plop</div>' in resp
6448

  
6449
    # link to a unknown carddef
6450
    carddef2.fields = [
6451
        fields.ItemField(id='1', label='Test', type='item',
6452
            data_source={'type': 'carddef:unknown', 'value': ''}),
6453
    ]
6454
    carddef2.store()
6455
    app = login(get_app(pub))
6456
    resp = app.get('/backoffice/data/')
6457
    resp = resp.click('bar')
6458
    resp = resp.click('Add')  # no error
6459

  
6460
    # look without access rights
6461
    carddef.backoffice_submission_roles = None
6462
    carddef.workflow_roles = {'_editor': None}
6463
    carddef.store()
6464
    resp = app.get('/backoffice/data/bar/1/')
6465
    with pytest.raises(IndexError):
6466
        resp.click('card plop')
6467

  
6468

  
6469
def test_backoffice_cards_import_data_from_csv(pub, studio):
6470
    user = create_user(pub)
6471

  
6472
    data_source = {
6473
        'type': 'formula',
6474
        'value': repr([
6475
            {'id': '1', 'text': 'un', 'more': 'foo'},
6476
            {'id': '2', 'text': 'deux', 'more': 'bar'}])
6477
    }
6478

  
6479
    CardDef.wipe()
6480
    carddef = CardDef()
6481
    carddef.name = 'test'
6482
    carddef.fields = [
6483
        fields.TableField(id='0', label='Table'),
6484
        fields.MapField(id='1', label='Map'),
6485
        fields.StringField(id='2', label='Test'),
6486
        fields.BoolField(id='3', label='Boolean'),
6487
        fields.ItemField(id='4', label='List',
6488
                         items=['item1', 'item2']),
6489
        fields.DateField(id='5', label='Date'),
6490
        fields.TitleField(id='6', label='Title', type='title'),
6491
        fields.FileField(id='7', label='File'),
6492
        fields.EmailField(id='8', label='Email'),
6493
        fields.TextField(id='9', label='Long'),
6494
        fields.ItemField(id='10', label='List2', data_source=data_source),
6495
    ]
6496
    carddef.workflow_roles = {'_editor': user.roles[0]}
6497
    carddef.store()
6498
    carddef.data_class().wipe()
6499

  
6500
    app = login(get_app(pub))
6501

  
6502
    resp = app.get(carddef.get_url())
6503
    assert 'Import data from a CSV file' not in resp.text
6504
    resp = app.get(carddef.get_url() + 'import-csv', status=403)
6505

  
6506
    carddef.backoffice_submission_roles = user.roles
6507
    carddef.store()
6508

  
6509
    resp = app.get(carddef.get_url())
6510
    resp = resp.click('Import data from a CSV file')
6511

  
6512
    assert 'Table, File are required but cannot be filled from CSV.' in resp
6513
    assert 'Download sample file for this card' not in resp
6514
    carddef.fields[0].required = False
6515
    carddef.fields[7].required = False
6516
    carddef.store()
6517

  
6518
    resp = app.get(carddef.get_url())
6519
    resp = resp.click('Import data from a CSV file')
6520
    sample_resp = resp.click('Download sample file for this card')
6521
    today = datetime.date.today()
6522
    assert sample_resp.text == (
6523
            "Table,Map,Test,Boolean,List,Date,File,Email,Long,List2\r\n"
6524
            "will be ignored - type Table not supported,"
6525
            "%s,"
6526
            "value,"
6527
            "Yes,"
6528
            "value,"
6529
            "%s,"
6530
            "will be ignored - type File Upload not supported,"
6531
            "foo@example.com,"
6532
            "value,"
6533
            "value\r\n" % (pub.get_default_position(), today))
6534

  
6535
    # missing file
6536
    resp = resp.forms[0].submit()
6537
    assert '>required field<' in resp
6538

  
6539
    resp.forms[0]['file'] = Upload('test.csv', b'\0', 'text/csv')
6540
    resp = resp.forms[0].submit()
6541
    assert 'Invalid file format.' in resp
6542

  
6543
    resp.forms[0]['file'] = Upload('test.csv', b'', 'text/csv')
6544
    resp = resp.forms[0].submit()
6545
    assert 'Invalid CSV file.' in resp
6546

  
6547
    resp.forms[0]['file'] = Upload('test.csv',
6548
                                   b'Test,List,Date\ndata1,item1,invalid',
6549
                                   'text/csv')
6550
    resp = resp.forms[0].submit()
6551
    assert 'CSV file contains less columns than card fields.' in resp.text
6552

  
6553
    data = [b'Table,Map,Test,Boolean,List,Date,File,Email,Long,List2']
6554
    for i in range(1, 150):
6555
        data.append(b'table,48.81;2.37,data%d ,%s,item%d,2020-01-%02d,filename-%d,test@localhost,"plop\nplop",1' % (
6556
            i, str(bool(i % 2)).encode('utf-8'), i, i % 31 + 1, i))
6557

  
6558
    resp.forms[0]['file'] = Upload('test.csv', b'\n'.join(data),
6559
                                   'text/csv')
6560
    resp = resp.forms[0].submit().follow()
6561
    assert 'Importing data into cards' in resp
6562
    assert 'Column File will be ignored: type File Upload not supported.' in resp
6563
    assert carddef.data_class().count() == 149
6564
    card1, card2 = carddef.data_class().select(order_by='id')[:2]
6565
    assert card1.data['1'] == '48.81;2.37'
6566
    assert card1.data['2'] == 'data1'
6567
    assert card1.data['3'] is True
6568
    assert card1.data['5'].tm_mday == 2
6569
    assert card1.data['9'] == 'plop\nplop'
6570
    assert card1.data['10'] == '1'
6571
    assert card1.data['10_display'] == 'un'
6572
    assert card1.data['10_structured'] == {'id': '1', 'text': 'un', 'more': 'foo'}
6573
    assert card2.data['2'] == 'data2'
6574
    assert card2.data['3'] is False
6575
    assert card2.data['5'].tm_mday == 3
6576

  
6577

  
6578
def test_backoffice_cards_import_data_csv_invalid_columns(pub):
6579
    user = create_user(pub)
6580

  
6581
    CardDef.wipe()
6582
    carddef = CardDef()
6583
    carddef.workflow_roles = {'_editor': user.roles[0]}
6584
    carddef.backoffice_submission_roles = user.roles
6585
    carddef.name = 'test'
6586
    carddef.fields = [
6587
        fields.StringField(id='1', label='String1'),
6588
        fields.StringField(id='2', label='String2'),
6589
        fields.TextField(id='3', label='Text'),
6590
    ]
6591
    carddef.store()
6592

  
6593
    app = login(get_app(pub))
6594
    resp = app.get(carddef.get_url())
6595
    resp = resp.click('Import data from a CSV file')
6596

  
6597
    csv_data = '''String1,String2,Text
6598
1,2,3
6599
4,5,6
6600
7,
6601
8,9,10,11
6602
12,13,14
6603

  
6604
'''
6605
    resp.forms[0]['file'] = Upload('test.csv', csv_data.encode('utf-8'), 'text/csv')
6606
    resp = resp.forms[0].submit()
6607
    assert 'CSV file contains lines with wrong number of columns.' in resp.text
6608
    assert '(line numbers 4, 5, 7)' in resp.text
6609

  
6610
    csv_data += '\n' * 10
6611
    resp.forms[0]['file'] = Upload('test.csv', csv_data.encode('utf-8'), 'text/csv')
6612
    resp = resp.forms[0].submit()
6613
    assert 'CSV file contains lines with wrong number of columns.' in resp.text
6614
    assert '(line numbers 4, 5, 7, 8, 9 and more)' in resp.text
6615

  
6616

  
6617
def test_backoffice_cards_wscall_failure_display(http_requests, pub, studio):
6618
    LoggedError.wipe()
6619
    user = create_user(pub)
6620

  
6621
    Workflow.wipe()
6622
    workflow = Workflow(name='wscall')
6623
    workflow.roles = {
6624
        '_viewer': 'Viewer',
6625
        '_editor': 'Editor',
6626
    }
6627
    st1 = workflow.add_status('Recorded', 'recorded')
6628

  
6629
    wscall = WebserviceCallStatusItem()
6630
    wscall.id = '_wscall'
6631
    wscall.varname = 'xxx'
6632
    wscall.url = 'http://remote.example.net/xml'
6633
    wscall.action_on_bad_data = ':stop'
6634
    wscall.record_errors = True
6635
    st1.items.append(wscall)
6636
    wscall.parent = st1
6637

  
6638
    again = ChoiceWorkflowStatusItem()
6639
    again.id = '_again'
6640
    again.label = 'Again'
6641
    again.by = ['_editor']
6642
    again.status = st1.id
6643
    st1.items.append(again)
6644
    again.parent = st1
6645

  
6646
    workflow.store()
6647

  
6648
    CardDef.wipe()
6649
    carddef = CardDef()
6650
    carddef.name = 'foo'
6651
    carddef.fields = [
6652
        fields.StringField(id='1', label='Test', type='string', varname='foo'),
6653
    ]
6654
    carddef.backoffice_submission_roles = user.roles
6655
    carddef.workflow_id = workflow.id
6656
    carddef.workflow_roles = {'_editor': user.roles[0]}
6657
    carddef.digest_template = 'card {{form_var_foo}}'
6658
    carddef.store()
6659
    carddef.data_class().wipe()
6660

  
6661
    carddata = carddef.data_class()()
6662
    carddata.data = {'1': 'plop'}
6663
    carddata.just_created()
6664
    carddata.store()
6665

  
6666
    app = login(get_app(pub))
6667

  
6668
    resp = app.get('/backoffice/data/foo/%s/' % carddata.id)
6669
    assert 'Again' in resp.text
6670
    resp = resp.forms[0].submit('button_again')
6671
    resp = resp.follow()
6672
    assert 'Error during webservice call' in resp.text
6673

  
6674
    assert LoggedError.count() == 1
6675
    assert LoggedError.select()[0].get_formdata().data == {'1': 'plop'}
6676

  
6677

  
6678 6288
def test_lazy_eval_with_conditional_workflow_form(pub):
6679 6289
    role = Role(name='foobar')
6680 6290
    role.store()
......
7150 6760

  
7151 6761
    resp = resp.forms['listing-settings'].submit()
7152 6762
    assert resp.text.count('<tr') == 6
7153

  
7154

  
7155
def test_block_card_item_link(pub, studio, blocks_feature):
7156
    user = create_user(pub)
7157
    CardDef.wipe()
7158
    carddef = CardDef()
7159
    carddef.name = 'foo'
7160
    carddef.fields = [
7161
        fields.StringField(id='1', label='Test', type='string', varname='foo'),
7162
    ]
7163
    carddef.backoffice_submission_roles = user.roles
7164
    carddef.workflow_roles = {'_editor': user.roles[0]}
7165
    carddef.digest_template = 'card {{form_var_foo}}'
7166
    carddef.store()
7167
    carddef.data_class().wipe()
7168

  
7169
    card = carddef.data_class()()
7170
    card.data = {'1': 'plop'}
7171
    card.just_created()
7172
    card.store()
7173

  
7174
    card2 = carddef.data_class()()
7175
    card2.data = {'1': 'plop2'}
7176
    card2.just_created()
7177
    card2.store()
7178

  
7179
    BlockDef.wipe()
7180
    block = BlockDef()
7181
    block.name = 'foobar'
7182
    block.fields = [
7183
        fields.ItemField(id='1', label='Test', type='item',
7184
            data_source={'type': 'carddef:foo', 'value': ''}),
7185
    ]
7186
    block.store()
7187

  
7188
    formdef = FormDef()
7189
    formdef.name = 'bar'
7190
    formdef.fields = [
7191
        fields.BlockField(id='1', label='test', type='block:foobar', max_items=3),
7192
    ]
7193
    formdef.store()
7194
    formdef.data_class().wipe()
7195

  
7196
    app = login(get_app(pub))
7197
    resp = app.get('/bar/')
7198
    resp.form['f1$element0$f1'].value = card.id
7199
    resp = resp.form.submit('f1$add_element')
7200
    resp.form['f1$element1$f1'].value = card2.id
7201
    resp = resp.form.submit('submit')  # -> validation page
7202
    assert resp.form['f1$element0$f1'].value == str(card.id)
7203
    assert resp.form['f1$element0$f1_label'].value == 'card plop'
7204
    assert resp.form['f1$element1$f1'].value == str(card2.id)
7205
    assert resp.form['f1$element1$f1_label'].value == 'card plop2'
7206
    resp = resp.form.submit('submit')  # -> final submit
7207
    resp = resp.follow()
7208
    assert '<div class="value">card plop</div>' in resp
7209
    assert '<div class="value">card plop2</div>' in resp
7210

  
7211
    # check cards are links in backoffice
7212
    resp = app.get('/backoffice/management' + resp.request.path)
7213
    assert '<div class="value"><a href="http://example.net/backoffice/data/foo/%s/">card plop</a></div></div>' % card.id in resp
7214
    assert '<div class="value"><a href="http://example.net/backoffice/data/foo/%s/">card plop2</a></div></div>' % card2.id in resp
tests/backoffice_pages/test_carddata.py
1
# -*- coding: utf-8 -*-
2
import datetime
3
import os
4

  
5
import pytest
6
from webtest import Upload
7

  
8
from wcs import fields
9
from wcs.blocks import BlockDef
10
from wcs.carddef import CardDef
11
from wcs.categories import CardDefCategory
12
from wcs.formdef import FormDef
13
from wcs.logged_errors import LoggedError
14
from wcs.qommon.http_request import HTTPRequest
15
from wcs.wf.wscall import WebserviceCallStatusItem
16
from wcs.workflows import ChoiceWorkflowStatusItem, Workflow
17

  
18
from utilities import clean_temporary_pub, create_temporary_pub, get_app, login
19
from .test_all import create_user
20

  
21

  
22
def pytest_generate_tests(metafunc):
23
    if 'pub' in metafunc.fixturenames:
24
        metafunc.parametrize('pub', ['pickle', 'sql', 'pickle-templates'], indirect=True)
25

  
26

  
27
@pytest.fixture
28
def pub(request, emails):
29
    pub = create_temporary_pub(
30
            sql_mode=bool('sql' in request.param),
31
            templates_mode=bool('templates' in request.param)
32
            )
33

  
34
    req = HTTPRequest(None, {'SCRIPT_NAME': '/', 'SERVER_NAME': 'example.net'})
35
    pub.set_app_dir(req)
36
    pub.cfg['identification'] = {'methods': ['password']}
37
    pub.cfg['language'] = {'language': 'en'}
38
    pub.write_cfg()
39
    fd = open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w')
40
    fd.write('''
41
[api-secrets]
42
coucou = 1234
43
''')
44
    fd.close()
45

  
46
    return pub
47

  
48

  
49
def teardown_module(module):
50
    clean_temporary_pub()
51

  
52

  
53
def test_carddata_management(pub, studio):
54
    CardDef.wipe()
55
    user = create_user(pub)
56
    app = login(get_app(pub))
57
    resp = app.get('/backoffice/')
58
    assert 'Cards' not in resp.text
59
    carddef = CardDef()
60
    carddef.name = 'foo'
61
    carddef.fields = [
62
        fields.StringField(id='1', label='Test', type='string', varname='foo'),
63
        fields.StringField(
64
            id='2', label='Condi', type='string', varname='bar',
65
            required=True, condition={'type': 'django', 'value': 'form_var_foo == "ok"'}),
66
    ]
67
    carddef.store()
68
    carddef.data_class().wipe()
69

  
70
    resp = app.get('/backoffice/')
71
    assert 'Cards' not in resp.text
72

  
73
    carddef.backoffice_submission_roles = user.roles
74
    carddef.store()
75
    resp = app.get('/backoffice/')
76
    assert 'Cards' in resp.text
77

  
78
    carddef.backoffice_submission_roles = None
79
    carddef.workflow_roles = {'_editor': user.roles[0]}
80
    carddef.store()
81
    resp = app.get('/backoffice/')
82
    assert 'Cards' in resp.text
83

  
84
    resp = app.get('/backoffice/data/')
85
    resp = resp.click('foo')
86
    assert 'Add' not in resp.text
87

  
88
    carddef.backoffice_submission_roles = user.roles
89
    carddef.store()
90

  
91
    resp = app.get('/backoffice/data/')
92
    resp = resp.click('foo')
93
    assert resp.text.count('<tr') == 1  # header
94
    assert 'Add' in resp.text
95
    resp = resp.click('Add')
96
    resp.form['f1'] = 'blah'
97

  
98
    live_url = resp.html.find('form').attrs['data-live-url']
99
    assert '/backoffice/data/foo/add/live' in live_url
100
    live_resp = app.post(live_url, params=resp.form.submit_fields())
101
    assert live_resp.json['result']['1']['visible']
102
    assert not live_resp.json['result']['2']['visible']
103
    resp.form['f1'] = 'ok'
104
    live_resp = app.post(live_url, params=resp.form.submit_fields())
105
    assert live_resp.json['result']['1']['visible']
106
    assert live_resp.json['result']['2']['visible']
107
    resp.form['f2'] = 'blah'
108

  
109
    resp = resp.form.submit('submit')
110
    assert resp.location.endswith('/backoffice/data/foo/1/')
111
    resp = resp.follow()
112
    assert 'Edit Card' in resp.text
113
    assert 'Delete Card' in resp.text
114

  
115
    carddata = carddef.data_class().select()[0]
116
    assert carddata.data == {'1': 'ok', '2': 'blah'}
117
    assert carddata.user_id is None
118
    assert carddata.submission_agent_id == str(user.id)
119
    assert carddata.evolution[0].who == str(user.id)
120
    assert 'Original Submitter' not in resp.text
121

  
122
    resp = app.get('/backoffice/data/')
123
    resp = resp.click('foo')
124
    assert resp.text.count('<tr') == 2  # header + row of data
125

  
126

  
127
def test_carddata_management_categories(pub, studio):
128
    user = create_user(pub)
129

  
130
    CardDef.wipe()
131
    carddef = CardDef()
132
    carddef.name = 'foo'
133
    carddef.fields = []
134
    carddef.backoffice_submission_roles = None
135
    carddef.workflow_roles = {'_editor': user.roles[0]}
136
    carddef.store()
137

  
138
    carddef2 = CardDef()
139
    carddef2.name = 'card title 2'
140
    carddef2.fields = []
141
    carddef2.backoffice_submission_roles = None
142
    carddef2.workflow_roles = {'_editor': user.roles[0]}
143
    carddef2.store()
144

  
145
    CardDefCategory.wipe()
146
    cat = CardDefCategory(name='Foo')
147
    cat.store()
148
    cat2 = CardDefCategory(name='Bar')
149
    cat2.store()
150

  
151
    app = login(get_app(pub))
152
    resp = app.get('/backoffice/data/')
153
    assert '<h3>Misc</h3>' not in resp.text
154
    assert '<h3>Foo</h3>' not in resp.text
155
    assert '<h3>Bar</h3>' not in resp.text
156

  
157
    carddef.category = cat2
158
    carddef.store()
159
    resp = app.get('/backoffice/data/')
160
    assert '<h3>Misc</h3>' in resp.text
161
    assert '<h3>Foo</h3>' not in resp.text
162
    assert '<h3>Bar</h3>' in resp.text
163

  
164
    carddef2.category = cat
165
    carddef2.store()
166
    resp = app.get('/backoffice/data/')
167
    assert '<h3>Misc</h3>' not in resp.text
168
    assert '<h3>Foo</h3>' in resp.text
169
    assert '<h3>Bar</h3>' in resp.text
170

  
171

  
172
def test_studio_card_item_link(pub, studio):
173
    user = create_user(pub)
174
    CardDef.wipe()
175
    carddef = CardDef()
176
    carddef.name = 'foo'
177
    carddef.fields = [
178
        fields.StringField(id='1', label='Test', type='string', varname='foo'),
179
    ]
180
    carddef.backoffice_submission_roles = user.roles
181
    carddef.workflow_roles = {'_editor': user.roles[0]}
182
    carddef.digest_template = 'card {{form_var_foo}}'
183
    carddef.store()
184
    carddef.data_class().wipe()
185

  
186
    card = carddef.data_class()()
187
    card.data = {'1': 'plop'}
188
    card.just_created()
189
    card.store()
190

  
191
    carddef2 = CardDef()
192
    carddef2.name = 'bar'
193
    carddef2.fields = [
194
        fields.ItemField(
195
            id='1', label='Test', type='item',
196
            data_source={'type': 'carddef:foo', 'value': ''}),
197
    ]
198
    carddef2.backoffice_submission_roles = user.roles
199
    carddef2.workflow_roles = {'_editor': user.roles[0]}
200
    carddef2.store()
201
    carddef2.data_class().wipe()
202

  
203
    app = login(get_app(pub))
204
    resp = app.get('/backoffice/data/')
205
    resp = resp.click('bar')
206
    resp = resp.click('Add')
207
    resp.form['f1'] = card.id
208
    resp = resp.form.submit('submit')
209
    assert resp.location.endswith('/backoffice/data/bar/1/')
210
    resp = resp.follow()
211
    resp = resp.click('card plop')
212
    assert '<div class="value">plop</div>' in resp
213

  
214
    # link to a unknown carddef
215
    carddef2.fields = [
216
        fields.ItemField(
217
            id='1', label='Test', type='item',
218
            data_source={'type': 'carddef:unknown', 'value': ''}),
219
    ]
220
    carddef2.store()
221
    app = login(get_app(pub))
222
    resp = app.get('/backoffice/data/')
223
    resp = resp.click('bar')
224
    resp = resp.click('Add')  # no error
225

  
226
    # look without access rights
227
    carddef.backoffice_submission_roles = None
228
    carddef.workflow_roles = {'_editor': None}
229
    carddef.store()
230
    resp = app.get('/backoffice/data/bar/1/')
231
    with pytest.raises(IndexError):
232
        resp.click('card plop')
233

  
234

  
235
def test_backoffice_cards_import_data_from_csv(pub, studio):
236
    user = create_user(pub)
237

  
238
    data_source = {
239
        'type': 'formula',
240
        'value': repr([
241
            {'id': '1', 'text': 'un', 'more': 'foo'},
242
            {'id': '2', 'text': 'deux', 'more': 'bar'}])
243
    }
244

  
245
    CardDef.wipe()
246
    carddef = CardDef()
247
    carddef.name = 'test'
248
    carddef.fields = [
249
        fields.TableField(id='0', label='Table'),
250
        fields.MapField(id='1', label='Map'),
251
        fields.StringField(id='2', label='Test'),
252
        fields.BoolField(id='3', label='Boolean'),
253
        fields.ItemField(id='4', label='List',
254
                         items=['item1', 'item2']),
255
        fields.DateField(id='5', label='Date'),
256
        fields.TitleField(id='6', label='Title', type='title'),
257
        fields.FileField(id='7', label='File'),
258
        fields.EmailField(id='8', label='Email'),
259
        fields.TextField(id='9', label='Long'),
260
        fields.ItemField(id='10', label='List2', data_source=data_source),
261
    ]
262
    carddef.workflow_roles = {'_editor': user.roles[0]}
263
    carddef.store()
264
    carddef.data_class().wipe()
265

  
266
    app = login(get_app(pub))
267

  
268
    resp = app.get(carddef.get_url())
269
    assert 'Import data from a CSV file' not in resp.text
270
    resp = app.get(carddef.get_url() + 'import-csv', status=403)
271

  
272
    carddef.backoffice_submission_roles = user.roles
273
    carddef.store()
274

  
275
    resp = app.get(carddef.get_url())
276
    resp = resp.click('Import data from a CSV file')
277

  
278
    assert 'Table, File are required but cannot be filled from CSV.' in resp
279
    assert 'Download sample file for this card' not in resp
280
    carddef.fields[0].required = False
281
    carddef.fields[7].required = False
282
    carddef.store()
283

  
284
    resp = app.get(carddef.get_url())
285
    resp = resp.click('Import data from a CSV file')
286
    sample_resp = resp.click('Download sample file for this card')
287
    today = datetime.date.today()
288
    assert sample_resp.text == (
289
            "Table,Map,Test,Boolean,List,Date,File,Email,Long,List2\r\n"
290
            "will be ignored - type Table not supported,"
291
            "%s,"
292
            "value,"
293
            "Yes,"
294
            "value,"
295
            "%s,"
296
            "will be ignored - type File Upload not supported,"
297
            "foo@example.com,"
298
            "value,"
299
            "value\r\n" % (pub.get_default_position(), today))
300

  
301
    # missing file
302
    resp = resp.forms[0].submit()
303
    assert '>required field<' in resp
304

  
305
    resp.forms[0]['file'] = Upload('test.csv', b'\0', 'text/csv')
306
    resp = resp.forms[0].submit()
307
    assert 'Invalid file format.' in resp
308

  
309
    resp.forms[0]['file'] = Upload('test.csv', b'', 'text/csv')
310
    resp = resp.forms[0].submit()
311
    assert 'Invalid CSV file.' in resp
312

  
313
    resp.forms[0]['file'] = Upload('test.csv',
314
                                   b'Test,List,Date\ndata1,item1,invalid',
315
                                   'text/csv')
316
    resp = resp.forms[0].submit()
317
    assert 'CSV file contains less columns than card fields.' in resp.text
318

  
319
    data = [b'Table,Map,Test,Boolean,List,Date,File,Email,Long,List2']
320
    for i in range(1, 150):
321
        data.append(b'table,48.81;2.37,data%d ,%s,item%d,2020-01-%02d,filename-%d,test@localhost,"plop\nplop",1' % (
322
            i, str(bool(i % 2)).encode('utf-8'), i, i % 31 + 1, i))
323

  
324
    resp.forms[0]['file'] = Upload('test.csv', b'\n'.join(data),
325
                                   'text/csv')
326
    resp = resp.forms[0].submit().follow()
327
    assert 'Importing data into cards' in resp
328
    assert 'Column File will be ignored: type File Upload not supported.' in resp
329
    assert carddef.data_class().count() == 149
330
    card1, card2 = carddef.data_class().select(order_by='id')[:2]
331
    assert card1.data['1'] == '48.81;2.37'
332
    assert card1.data['2'] == 'data1'
333
    assert card1.data['3'] is True
334
    assert card1.data['5'].tm_mday == 2
335
    assert card1.data['9'] == 'plop\nplop'
336
    assert card1.data['10'] == '1'
337
    assert card1.data['10_display'] == 'un'
338
    assert card1.data['10_structured'] == {'id': '1', 'text': 'un', 'more': 'foo'}
339
    assert card2.data['2'] == 'data2'
340
    assert card2.data['3'] is False
341
    assert card2.data['5'].tm_mday == 3
342

  
343

  
344
def test_backoffice_cards_import_data_csv_invalid_columns(pub):
345
    user = create_user(pub)
346

  
347
    CardDef.wipe()
348
    carddef = CardDef()
349
    carddef.workflow_roles = {'_editor': user.roles[0]}
350
    carddef.backoffice_submission_roles = user.roles
351
    carddef.name = 'test'
352
    carddef.fields = [
353
        fields.StringField(id='1', label='String1'),
354
        fields.StringField(id='2', label='String2'),
355
        fields.TextField(id='3', label='Text'),
356
    ]
357
    carddef.store()
358

  
359
    app = login(get_app(pub))
360
    resp = app.get(carddef.get_url())
361
    resp = resp.click('Import data from a CSV file')
362

  
363
    csv_data = '''String1,String2,Text
364
1,2,3
365
4,5,6
366
7,
367
8,9,10,11
368
12,13,14
369

  
370
'''
371
    resp.forms[0]['file'] = Upload('test.csv', csv_data.encode('utf-8'), 'text/csv')
372
    resp = resp.forms[0].submit()
373
    assert 'CSV file contains lines with wrong number of columns.' in resp.text
374
    assert '(line numbers 4, 5, 7)' in resp.text
375

  
376
    csv_data += '\n' * 10
377
    resp.forms[0]['file'] = Upload('test.csv', csv_data.encode('utf-8'), 'text/csv')
378
    resp = resp.forms[0].submit()
379
    assert 'CSV file contains lines with wrong number of columns.' in resp.text
380
    assert '(line numbers 4, 5, 7, 8, 9 and more)' in resp.text
381

  
382

  
383
def test_backoffice_cards_wscall_failure_display(http_requests, pub, studio):
384
    LoggedError.wipe()
385
    user = create_user(pub)
386

  
387
    Workflow.wipe()
388
    workflow = Workflow(name='wscall')
389
    workflow.roles = {
390
        '_viewer': 'Viewer',
391
        '_editor': 'Editor',
392
    }
393
    st1 = workflow.add_status('Recorded', 'recorded')
394

  
395
    wscall = WebserviceCallStatusItem()
396
    wscall.id = '_wscall'
397
    wscall.varname = 'xxx'
398
    wscall.url = 'http://remote.example.net/xml'
399
    wscall.action_on_bad_data = ':stop'
400
    wscall.record_errors = True
401
    st1.items.append(wscall)
402
    wscall.parent = st1
403

  
404
    again = ChoiceWorkflowStatusItem()
405
    again.id = '_again'
406
    again.label = 'Again'
407
    again.by = ['_editor']
408
    again.status = st1.id
409
    st1.items.append(again)
410
    again.parent = st1
411

  
412
    workflow.store()
413

  
414
    CardDef.wipe()
415
    carddef = CardDef()
416
    carddef.name = 'foo'
417
    carddef.fields = [
418
        fields.StringField(id='1', label='Test', type='string', varname='foo'),
419
    ]
420
    carddef.backoffice_submission_roles = user.roles
421
    carddef.workflow_id = workflow.id
422
    carddef.workflow_roles = {'_editor': user.roles[0]}
423
    carddef.digest_template = 'card {{form_var_foo}}'
424
    carddef.store()
425
    carddef.data_class().wipe()
426

  
427
    carddata = carddef.data_class()()
428
    carddata.data = {'1': 'plop'}
429
    carddata.just_created()
430
    carddata.store()
431

  
432
    app = login(get_app(pub))
433

  
434
    resp = app.get('/backoffice/data/foo/%s/' % carddata.id)
435
    assert 'Again' in resp.text
436
    resp = resp.forms[0].submit('button_again')
437
    resp = resp.follow()
438
    assert 'Error during webservice call' in resp.text
439

  
440
    assert LoggedError.count() == 1
441
    assert LoggedError.select()[0].get_formdata().data == {'1': 'plop'}
442

  
443

  
444
def test_block_card_item_link(pub, studio, blocks_feature):
445
    user = create_user(pub)
446
    CardDef.wipe()
447
    carddef = CardDef()
448
    carddef.name = 'foo'
449
    carddef.fields = [
450
        fields.StringField(id='1', label='Test', type='string', varname='foo'),
451
    ]
452
    carddef.backoffice_submission_roles = user.roles
453
    carddef.workflow_roles = {'_editor': user.roles[0]}
454
    carddef.digest_template = 'card {{form_var_foo}}'
455
    carddef.store()
456
    carddef.data_class().wipe()
457

  
458
    card = carddef.data_class()()
459
    card.data = {'1': 'plop'}
460
    card.just_created()
461
    card.store()
462

  
463
    card2 = carddef.data_class()()
464
    card2.data = {'1': 'plop2'}
465
    card2.just_created()
466
    card2.store()
467

  
468
    BlockDef.wipe()
469
    block = BlockDef()
470
    block.name = 'foobar'
471
    block.fields = [
472
        fields.ItemField(
473
            id='1', label='Test', type='item',
474
            data_source={'type': 'carddef:foo', 'value': ''}),
475
    ]
476
    block.store()
477

  
478
    formdef = FormDef()
479
    formdef.name = 'bar'
480
    formdef.fields = [
481
        fields.BlockField(id='1', label='test', type='block:foobar', max_items=3),
482
    ]
483
    formdef.store()
484
    formdef.data_class().wipe()
485

  
486
    app = login(get_app(pub))
487
    resp = app.get('/bar/')
488
    resp.form['f1$element0$f1'].value = card.id
489
    resp = resp.form.submit('f1$add_element')
490
    resp.form['f1$element1$f1'].value = card2.id
491
    resp = resp.form.submit('submit')  # -> validation page
492
    assert resp.form['f1$element0$f1'].value == str(card.id)
493
    assert resp.form['f1$element0$f1_label'].value == 'card plop'
494
    assert resp.form['f1$element1$f1'].value == str(card2.id)
495
    assert resp.form['f1$element1$f1_label'].value == 'card plop2'
496
    resp = resp.form.submit('submit')  # -> final submit
497
    resp = resp.follow()
498
    assert '<div class="value">card plop</div>' in resp
499
    assert '<div class="value">card plop2</div>' in resp
500

  
501
    # check cards are links in backoffice
502
    resp = app.get('/backoffice/management' + resp.request.path)
503
    assert '<div class="value"><a href="http://example.net/backoffice/data/foo/%s/">card plop</a></div></div>' % card.id in resp
504
    assert '<div class="value"><a href="http://example.net/backoffice/data/foo/%s/">card plop2</a></div></div>' % card2.id in resp
0
-