Projet

Général

Profil

0001-misc-split-test-module.patch

Lauréline Guérin, 23 juillet 2020 16:52

Télécharger (154 ko)

Voir les différences:

Subject: [PATCH 1/2] misc: split test module

 tests/test_admin_pages.py       | 2189 ------------------------------
 tests/test_forms_admin_pages.py | 2237 +++++++++++++++++++++++++++++++
 2 files changed, 2237 insertions(+), 2189 deletions(-)
 create mode 100644 tests/test_forms_admin_pages.py
tests/test_admin_pages.py
1 1
# -*- coding: utf-8 -*-
2 2

  
3
import datetime
4
from email.mime.text import MIMEText
5 3
import json
6 4
import logging
7 5
import os
8 6
import re
9
import shutil
10
import tarfile
11
import time
12 7
import xml.etree.ElementTree as ET
13 8
import zipfile
14 9

  
......
21 16
from webtest import Upload
22 17
import mock
23 18

  
24
from django.utils import six
25 19
from django.utils.six import StringIO, BytesIO
26 20
from django.utils.six.moves.urllib import parse as urlparse
27 21

  
28
from quixote import cleanup, get_publisher
29 22
from quixote.http_request import Upload as QuixoteUpload
30 23

  
31
from wcs.qommon import errors, sessions
32 24
from wcs.qommon.form import UploadedFile
33 25
from wcs.qommon.ident.password_accounts import PasswordAccount
34 26
from wcs.qommon.http_request import HTTPRequest
......
193 185
        user.store()
194 186

  
195 187

  
196
def test_forms(pub):
197
    user = create_superuser(pub)
198
    app = login(get_app(pub))
199
    resp = app.get('/backoffice/forms/')
200
    assert 'You first have to define roles.' in resp.text
201
    assert not 'New Form' in resp.text
202

  
203

  
204
def test_forms_new(pub):
205
    user = create_superuser(pub)
206
    app = login(get_app(pub))
207
    create_role()
208

  
209
    # create a new form
210
    resp = app.get('/backoffice/forms/')
211
    assert 'New Form' in resp.text
212
    resp = resp.click('New Form')
213
    resp.forms[0]['name'] = 'form title'
214
    resp = resp.forms[0].submit()
215
    assert resp.location == 'http://example.net/backoffice/forms/1/'
216
    resp = resp.follow()
217
    assert '<h2>form title' in resp.text
218

  
219
    # makes sure the data has been correctly saved
220
    formdef = FormDef.get(1)
221
    assert formdef.name == 'form title'
222
    assert formdef.url_name == 'form-title'
223
    assert formdef.fields == []
224
    assert formdef.disabled == True
225
    assert formdef.last_modification_user_id == str(user.id)
226

  
227

  
228
def test_forms_new_popup(pub):
229
    FormDef.wipe()
230
    user = create_superuser(pub)
231
    app = login(get_app(pub))
232
    create_role()
233

  
234
    # create a new form
235
    resp = app.get('/backoffice/forms/')
236
    assert 'New Form' in resp.text
237
    resp = resp.click('New Form', extra_environ={'HTTP_X_POPUP': 'true'})
238
    assert 'popup-content' in resp.text
239
    resp.forms[0]['name'] = 'form title'
240
    resp = resp.forms[0].submit()
241
    assert resp.location == 'http://example.net/backoffice/forms/1/'
242
    resp = resp.follow()
243
    assert '<h2>form title' in resp.text
244

  
245
    # makes sure the data has been correctly saved
246
    formdef = FormDef.get(1)
247
    assert formdef.name == 'form title'
248
    assert formdef.url_name == 'form-title'
249
    assert formdef.fields == []
250
    assert formdef.disabled == True
251
    assert formdef.last_modification_user_id == str(user.id)
252

  
253

  
254
def assert_option_display(resp, label, value):
255
    option_line = re.findall('%s.*%s' % (label, value), resp.text, re.DOTALL)
256
    assert option_line
257
    assert not '</li>' in option_line
258

  
259

  
260
def test_forms_edit(pub):
261
    create_superuser(pub)
262
    create_role()
263

  
264
    FormDef.wipe()
265
    formdef = FormDef()
266
    formdef.name = 'form title'
267
    formdef.fields = []
268
    formdef.store()
269

  
270
    app = login(get_app(pub))
271
    resp = app.get('/backoffice/forms/1/')
272

  
273
    # try changing an option
274

  
275
    # confirmation page
276
    assert_option_display(resp, 'Confirmation Page', 'Enabled')
277
    resp = resp.click('Confirmation Page')
278
    assert resp.forms[0]['confirmation'].checked
279
    resp.forms[0]['confirmation'].checked = False
280
    resp = resp.forms[0].submit()
281
    assert resp.location == 'http://example.net/backoffice/forms/1/'
282
    resp = resp.follow()
283
    assert_option_display(resp, 'Confirmation Page', 'Disabled')
284
    assert FormDef.get(1).confirmation == False
285

  
286
    # try cancel button
287
    resp = resp.click('Confirmation Page')
288
    assert resp.forms[0]['confirmation'].checked is False
289
    resp.forms[0]['confirmation'].checked = True
290
    resp = resp.forms[0].submit('cancel')
291
    assert resp.location == 'http://example.net/backoffice/forms/1/'
292
    resp = resp.follow()
293
    assert_option_display(resp, 'Confirmation Page', 'Disabled')
294
    assert FormDef.get(1).confirmation == False
295

  
296
    # Limit to one form
297
    assert_option_display(resp, 'Limit to one form', 'Disabled')
298
    resp = resp.click('Limit to one form')
299
    assert resp.forms[0]['only_allow_one'].checked is False
300
    resp.forms[0]['only_allow_one'].checked = True
301
    resp = resp.forms[0].submit()
302
    assert resp.location == 'http://example.net/backoffice/forms/1/'
303
    resp = resp.follow()
304
    assert_option_display(resp, 'Limit to one form', 'Enabled')
305
    assert FormDef.get(1).only_allow_one is True
306

  
307
    # Misc management
308
    assert_option_display(resp, 'Management', 'Default')
309
    resp = resp.click('Management', href='options/management')
310
    assert resp.forms[0]['include_download_all_button'].checked is False
311
    resp.forms[0]['include_download_all_button'].checked = True
312
    resp = resp.forms[0].submit()
313
    assert resp.location == 'http://example.net/backoffice/forms/1/'
314
    resp = resp.follow()
315
    assert_option_display(resp, 'Management', 'Custom')
316
    assert FormDef.get(1).include_download_all_button is True
317

  
318
    # Tracking code
319
    assert_option_display(resp, 'Tracking Code', 'Disabled')
320
    resp = resp.click('Tracking Code')
321
    assert resp.forms[0]['enable_tracking_codes'].checked is False
322
    resp.forms[0]['enable_tracking_codes'].checked = True
323
    resp = resp.forms[0].submit()
324
    assert resp.location == 'http://example.net/backoffice/forms/1/'
325
    resp = resp.follow()
326
    assert_option_display(resp, 'Tracking Code', 'Enabled')
327
    assert FormDef.get(1).enable_tracking_codes is True
328

  
329
    # CAPTCHA
330
    assert_option_display(resp, 'CAPTCHA for anonymous users', 'Disabled')
331
    resp = resp.click('CAPTCHA for anonymous users')
332
    assert resp.forms[0]['has_captcha'].checked is False
333
    resp.forms[0]['has_captcha'].checked = True
334
    resp = resp.forms[0].submit()
335
    assert resp.location == 'http://example.net/backoffice/forms/1/'
336
    resp = resp.follow()
337
    assert_option_display(resp, 'CAPTCHA for anonymous users', 'Enabled')
338
    assert FormDef.get(1).has_captcha is True
339

  
340
    # Appearance
341
    assert_option_display(resp, 'Appearance', 'Standard')
342
    resp = resp.click('Appearance')
343
    assert resp.forms[0]['appearance_keywords'].value == ''
344
    resp.forms[0]['appearance_keywords'] = 'foobar'
345
    resp = resp.forms[0].submit()
346
    assert resp.location == 'http://example.net/backoffice/forms/1/'
347
    resp = resp.follow()
348
    assert_option_display(resp, 'Appearance', 'foobar')
349
    assert FormDef.get(1).appearance_keywords == 'foobar'
350

  
351
    # Publication
352
    assert_option_display(resp, 'Online Status', 'Active')
353
    resp = resp.click('Online Status')
354
    assert resp.forms[0]['disabled'].checked is False
355
    resp.forms[0]['disabled'].checked = True
356
    resp = resp.forms[0].submit()
357
    assert resp.location == 'http://example.net/backoffice/forms/1/'
358
    resp = resp.follow()
359
    assert_option_display(resp, 'Online Status', 'Disabled')
360
    assert FormDef.get(1).disabled is True
361

  
362
    resp = resp.click('Online Status')
363
    assert resp.forms[0]['disabled'].checked is True
364
    resp.forms[0]['disabled_redirection'] = 'http://www.example.net'
365
    resp = resp.forms[0].submit()
366
    assert resp.location == 'http://example.net/backoffice/forms/1/'
367
    resp = resp.follow()
368
    assert_option_display(resp, 'Online Status', 'Redirected')
369
    assert FormDef.get(1).disabled is True
370
    assert FormDef.get(1).disabled_redirection == 'http://www.example.net'
371

  
372
    resp = resp.click('Online Status')
373
    resp.forms[0]['disabled'].checked = False
374
    resp.forms[0]['expiration_date$date'] = '2000-01-01'  # this is past(tm)
375
    resp = resp.forms[0].submit()
376
    assert resp.location == 'http://example.net/backoffice/forms/1/'
377
    resp = resp.follow()
378
    assert_option_display(resp, 'Online Status', 'Inactive by date')
379

  
380
    # enable geolocation
381
    resp = resp.click('Geolocation')
382
    resp.forms[0]['geoloc_label'] = 'Foobar'
383
    resp = resp.forms[0].submit()
384
    assert resp.location == 'http://example.net/backoffice/forms/1/'
385
    resp = resp.follow()
386
    assert_option_display(resp, 'Geolocation', 'Enabled')
387
    assert FormDef.get(formdef.id).geolocations == {'base': 'Foobar'}
388

  
389
    # and disable it
390
    resp = resp.click('Geolocation')
391
    resp.forms[0]['geoloc_label'] = ''
392
    resp = resp.forms[0].submit()
393
    assert resp.location == 'http://example.net/backoffice/forms/1/'
394
    resp = resp.follow()
395
    assert_option_display(resp, 'Geolocation', 'Disabled')
396
    assert FormDef.get(formdef.id).geolocations is None
397

  
398

  
399
def test_form_title_change(pub):
400
    create_superuser(pub)
401
    create_role()
402

  
403
    FormDef.wipe()
404
    formdef = FormDef()
405
    formdef.name = 'form title'
406
    formdef.fields = []
407
    formdef.store()
408

  
409
    app = login(get_app(pub))
410

  
411
    resp = app.get('/backoffice/forms/1/')
412
    resp = resp.click('change title')
413
    assert resp.form['name'].value == 'form title'
414
    assert 'data-slug-sync' in resp.text
415
    assert not 'change-nevertheless' in resp.text
416
    resp.form['name'] = 'new title'
417
    resp = resp.form.submit()
418
    assert resp.location == 'http://example.net/backoffice/forms/1/'
419
    resp = resp.follow()
420
    formdef = FormDef.get(formdef.id)
421
    assert formdef.name == 'new title'
422
    assert formdef.url_name == 'form-title'
423
    assert formdef.internal_identifier == 'new-title'
424

  
425
    resp = app.get('/backoffice/forms/1/')
426
    resp = resp.click('change title')
427
    assert not 'data-slug-sync' in resp.text
428
    assert not 'change-nevertheless' in resp.text
429

  
430
    formdef.data_class()().store()
431
    resp = app.get('/backoffice/forms/1/')
432
    resp = resp.click('change title')
433
    assert 'change-nevertheless' in resp.text
434

  
435
    formdef2 = FormDef()
436
    formdef2.name = 'other title'
437
    formdef2.fields = []
438
    formdef2.store()
439

  
440
    resp = app.get('/backoffice/forms/%s/' % formdef2.id)
441
    resp = resp.click('change title')
442
    assert resp.form['name'].value == 'other title'
443
    resp.form['url_name'] = formdef.url_name
444
    resp = resp.form.submit()
445
    assert 'This identifier is already used.' in resp.text
446

  
447
    resp.form['url_name'] = 'foobar'
448
    resp = resp.form.submit().follow()
449
    assert FormDef.get(formdef2.id).url_name == 'foobar'
450

  
451

  
452
def test_forms_edit_publication_date(pub):
453
    create_superuser(pub)
454
    create_role()
455

  
456
    FormDef.wipe()
457
    formdef = FormDef()
458
    formdef.name = 'form title'
459
    formdef.fields = []
460
    formdef.store()
461

  
462
    app = login(get_app(pub))
463
    resp = app.get('/backoffice/forms/1/options/online_status')
464
    resp.form['publication_date$date'] = '2020-01-01'
465
    resp = resp.form.submit()
466
    assert FormDef.get(formdef.id).publication_date == '2020-01-01 00:00'
467

  
468
    resp = app.get('/backoffice/forms/1/options/online_status')
469
    assert resp.form['publication_date$date'].value == '2020-01-01'
470
    resp.form['publication_date$time'] = '12:00'
471
    resp = resp.form.submit()
472
    assert FormDef.get(formdef.id).publication_date == '2020-01-01 12:00'
473

  
474
    resp = app.get('/backoffice/forms/1/options/online_status')
475
    assert resp.form['publication_date$date'].value == '2020-01-01'
476
    assert resp.form['publication_date$time'].value == '12:00'
477

  
478
    formdef.publication_date = None
479
    formdef.store()
480

  
481
    resp = app.get('/backoffice/forms/1/options/online_status')
482
    resp.form['publication_date$time'] = '12:00'
483
    resp = resp.form.submit()
484
    assert 'invalid value' in resp
485

  
486

  
487
def test_form_category(pub):
488
    create_superuser(pub)
489
    create_role()
490

  
491
    FormDef.wipe()
492
    formdef = FormDef()
493
    formdef.name = 'form title'
494
    formdef.fields = []
495
    formdef.store()
496

  
497
    app = login(get_app(pub))
498
    resp = app.get('/backoffice/forms/1/')
499
    assert_option_display(resp, 'Category', 'None')
500

  
501
    Category.wipe()
502
    cat = Category(name='Foo')
503
    cat.store()
504
    cat = Category(name='Bar')
505
    cat.store()
506
    resp = app.get('/backoffice/forms/1/')
507
    assert 'Category' in resp.text
508
    assert_option_display(resp, 'Category', 'None')
509

  
510

  
511
def test_form_category_select(pub):
512
    create_superuser(pub)
513
    create_role()
514

  
515
    FormDef.wipe()
516
    formdef = FormDef()
517
    formdef.name = 'form title'
518
    formdef.fields = []
519
    formdef.store()
520

  
521
    Category.wipe()
522
    cat = Category(name='Foo')
523
    cat.store()
524
    cat = Category(name='Bar')
525
    cat.store()
526

  
527
    app = login(get_app(pub))
528
    resp = app.get('/backoffice/forms/1/')
529
    resp = resp.click(href='category')
530
    resp = resp.forms[0].submit('cancel')
531
    assert FormDef.get(formdef.id).category_id is None
532

  
533
    resp = app.get('/backoffice/forms/1/')
534
    resp = resp.click(href='category')
535
    resp.forms[0]['category_id'] = cat.id
536
    resp = resp.forms[0].submit('submit')
537
    assert FormDef.get(formdef.id).category_id == cat.id
538

  
539

  
540
def test_form_workflow(pub):
541
    create_superuser(pub)
542
    create_role()
543

  
544
    FormDef.wipe()
545
    formdef = FormDef()
546
    formdef.name = 'form title'
547
    formdef.fields = []
548
    formdef.store()
549

  
550
    app = login(get_app(pub))
551
    resp = app.get('/backoffice/forms/1/')
552
    assert_option_display(resp, 'Workflow', 'Default')
553

  
554
    Workflow.wipe()
555
    workflow = Workflow(name='Workflow One')
556
    workflow.store()
557
    workflow = Workflow(name='Workflow Two')
558
    workflow.store()
559

  
560
    resp = app.get('/backoffice/forms/1/')
561
    assert_option_display(resp, 'Workflow', 'Default')
562

  
563

  
564
def test_form_workflow_change(pub):
565
    create_superuser(pub)
566
    create_role()
567

  
568
    FormDef.wipe()
569
    formdef = FormDef()
570
    formdef.name = 'form title'
571
    formdef.fields = []
572
    formdef.store()
573

  
574
    Workflow.wipe()
575
    workflow = Workflow(name='Workflow One')
576
    workflow.store()
577
    workflow = Workflow(name='Workflow Two')
578
    workflow.possible_status = Workflow.get_default_workflow().possible_status[:]
579
    workflow.store()
580

  
581
    app = login(get_app(pub))
582
    resp = app.get('/backoffice/forms/1/')
583
    resp = resp.click(href='workflow', index=1)
584
    resp = resp.forms[0].submit('cancel')
585
    assert FormDef.get(formdef.id).workflow_id is None
586

  
587
    resp = app.get('/backoffice/forms/1/')
588
    resp = resp.click(href='workflow', index=1)
589
    assert 'Workflow One' not in resp.text # this workflow doesn't have any status
590
    resp.forms[0]['workflow_id'] = workflow.id
591
    resp = resp.forms[0].submit('submit')
592
    assert FormDef.get(formdef.id).workflow_id == workflow.id
593

  
594

  
595
def test_form_workflow_link(pub):
596
    create_superuser(pub)
597
    create_role()
598

  
599
    FormDef.wipe()
600
    formdef = FormDef()
601
    formdef.name = 'form title'
602
    formdef.fields = []
603
    formdef.store()
604

  
605
    Workflow.wipe()
606
    workflow = Workflow(name='Workflow One')
607
    workflow.store()
608

  
609
    app = login(get_app(pub))
610

  
611
    resp = app.get('/backoffice/forms/%s/' % formdef.id)
612
    assert '../workflows/_default/' in resp.text
613

  
614
    formdef.workflow = workflow
615
    formdef.store()
616

  
617
    resp = app.get('/backoffice/forms/%s/' % formdef.id)
618
    assert '../workflows/%s/' % workflow.id in resp.text
619

  
620
    # check workflow link is not displayed if user has no access right
621
    pub.cfg['admin-permissions'] = {'workflows': ['x']}  #  block access
622
    pub.write_cfg()
623
    resp = app.get('/backoffice/forms/%s/' % formdef.id)
624
    assert '../workflows/%s/' % workflow.id not in resp.text
625

  
626

  
627
def test_form_workflow_remapping(pub):
628
    create_superuser(pub)
629
    create_role()
630

  
631
    FormDef.wipe()
632
    formdef = FormDef()
633
    formdef.name = 'form title'
634
    formdef.fields = []
635
    formdef.store()
636

  
637
    data_class = formdef.data_class()
638
    data_class.wipe()
639
    formdata1 = data_class()
640
    formdata1.status = 'wf-new'
641
    formdata1.store()
642

  
643
    formdata2 = data_class()
644
    formdata2.status = 'draft'
645
    formdata2.store()
646

  
647
    Workflow.wipe()
648
    workflow = Workflow(name='Workflow One')
649
    workflow.store()
650
    workflow = Workflow(name='Workflow Two')
651
    # create it with a single status
652
    workflow.possible_status = [Workflow.get_default_workflow().possible_status[-1]]
653
    workflow.store()
654

  
655
    app = login(get_app(pub))
656
    resp = app.get('/backoffice/forms/1/')
657
    resp = resp.click(href='workflow', index=1)
658
    resp.forms[0]['workflow_id'] = workflow.id
659
    resp = resp.forms[0].submit('submit')
660
    assert resp.location == 'http://example.net/backoffice/forms/1/workflow-status-remapping?new=2'
661
    resp = resp.follow()
662
    for status in Workflow.get_default_workflow().possible_status:
663
        assert resp.forms[0]['mapping-%s' % status.id]
664
        # there's only one possible new status
665
        assert len(resp.forms[0]['mapping-%s' % status.id].options) == 1
666
    assert data_class.get(formdata1.id).status == 'wf-new'
667
    assert data_class.get(formdata2.id).status == 'draft'
668
    resp = resp.forms[0].submit()
669
    assert data_class.get(formdata1.id).status == 'wf-finished'
670
    assert data_class.get(formdata2.id).status == 'draft'
671

  
672
    # change to another workflow, with no mapping change
673
    workflow2 = workflow
674
    workflow = Workflow(name='Workflow Three')
675
    workflow.possible_status = Workflow.get_default_workflow().possible_status[-2:][:]
676
    workflow.store()
677

  
678
    resp = app.get('/backoffice/forms/1/')
679
    resp = resp.click(href='workflow', index=1)
680
    resp.forms[0]['workflow_id'] = workflow.id
681
    resp = resp.forms[0].submit('submit')
682
    assert resp.location == 'http://example.net/backoffice/forms/1/workflow-status-remapping?new=3'
683
    resp = resp.follow()
684
    for status in workflow2.possible_status:
685
        assert resp.forms[0]['mapping-%s' % status.id]
686
        # there are two status
687
        assert len(resp.forms[0]['mapping-%s' % status.id].options) == 2
688
    resp = resp.forms[0].submit()
689
    assert data_class.get(formdata1.id).status == 'wf-finished'
690
    assert data_class.get(formdata2.id).status == 'draft'
691

  
692

  
693
def test_form_submitter_roles(pub):
694
    create_superuser(pub)
695
    role = create_role()
696

  
697
    FormDef.wipe()
698
    formdef = FormDef()
699
    formdef.name = 'form title'
700
    formdef.fields = []
701
    formdef.store()
702

  
703
    app = login(get_app(pub))
704
    resp = app.get('/backoffice/forms/1/')
705
    resp = resp.click(href=re.compile('^roles$'))
706
    resp.form['roles$element0'] = 'logged-users'
707
    assert not 'required_authentication_contexts' in resp.text
708
    resp = resp.form.submit()
709
    assert FormDef.get(formdef.id).roles == ['logged-users']
710

  
711
    # add auth contexts support
712
    if not pub.site_options.has_section('options'):
713
        pub.site_options.add_section('options')
714
    pub.site_options.set('options', 'auth-contexts', 'fedict')
715
    with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
716
        pub.site_options.write(fd)
717

  
718
    app = login(get_app(pub))
719
    resp = app.get('/backoffice/forms/1/')
720
    resp = resp.click(href=re.compile('^roles$'))
721
    assert 'required_authentication_contexts' in resp.text
722
    resp.form['required_authentication_contexts$element0'].checked = True
723
    resp = resp.form.submit()
724
    resp = resp.follow()
725
    assert FormDef.get(formdef.id).required_authentication_contexts == ['fedict']
726

  
727
    # check internal roles are not advertised
728
    role2 = Role(name='internal')
729
    role2.internal = True
730
    role2.store()
731

  
732
    resp = app.get('/backoffice/forms/1/')
733
    resp = resp.click(href=re.compile('^roles$'))
734
    assert len(resp.form['roles$element0'].options) == 3  # None, Logged users, foobar
735
    with pytest.raises(ValueError):
736
        resp.form['roles$element0'] = str(role2.id)
737

  
738

  
739
def test_form_workflow_role(pub):
740
    create_superuser(pub)
741
    role = create_role()
742

  
743
    FormDef.wipe()
744
    formdef = FormDef()
745
    formdef.name = 'form title'
746
    formdef.fields = []
747
    formdef.store()
748

  
749
    app = login(get_app(pub))
750
    resp = app.get('/backoffice/forms/1/')
751
    resp = resp.click(href='role/_receiver')
752
    resp = resp.forms[0].submit('cancel')
753

  
754
    resp = app.get('/backoffice/forms/1/')
755
    resp = resp.click(href='role/_receiver')
756
    resp.forms[0]['role_id'] = role.id
757
    resp = resp.forms[0].submit('submit')
758
    assert FormDef.get(1).workflow_roles == {'_receiver': '1'}
759

  
760
    # check it doesn't fail if a second role with the same name exists
761
    role = Role(name='foobar')
762
    role.store()
763
    resp = app.get('/backoffice/forms/1/')
764
    resp = resp.click(href='role/_receiver')
765

  
766

  
767
def test_form_workflow_options(pub):
768
    create_superuser(pub)
769
    create_role()
770

  
771
    Workflow.wipe()
772
    workflow = Workflow(name='Workflow One')
773
    workflow.store()
774

  
775
    FormDef.wipe()
776
    formdef = FormDef()
777
    formdef.name = 'form title'
778
    formdef.fields = []
779
    formdef.workflow_id = workflow.id
780
    formdef.workflow_options = {'2*1*body': 'xxx'}
781
    formdef.store()
782

  
783
    app = login(get_app(pub))
784
    resp = app.get('/backoffice/forms/1/')
785
    assert '"workflow-options"' in resp.text
786

  
787

  
788
def test_form_workflow_variables(pub):
789
    create_superuser(pub)
790
    create_role()
791

  
792
    Workflow.wipe()
793
    workflow = Workflow(name='Workflow One')
794
    from wcs.workflows import WorkflowVariablesFieldsFormDef
795
    workflow.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=workflow)
796
    workflow.variables_formdef.fields.append(
797
            fields.StringField(id='1', varname='test', label='Test', type='string'))
798
    workflow.store()
799

  
800
    FormDef.wipe()
801
    formdef = FormDef()
802
    formdef.name = 'form title'
803
    formdef.fields = []
804
    formdef.workflow_id = workflow.id
805
    formdef.store()
806

  
807
    app = login(get_app(pub))
808
    resp = app.get('/backoffice/forms/1/')
809
    assert '"workflow-variables"' in resp.text
810

  
811
    # visit the variables page
812
    resp = resp.click(href='workflow-variables')
813

  
814
    # and set a value
815
    resp.forms[0]['f1'] = 'foobar'
816
    resp = resp.forms[0].submit()
817
    assert resp.location == 'http://example.net/backoffice/forms/1/'
818

  
819
    # check the value has been correctly saved
820
    assert FormDef.get(formdef.id).workflow_options == {'test': 'foobar'}
821

  
822
    # go back to the variables page, also check value
823
    resp = resp.follow()
824
    resp = resp.click(href='workflow-variables')
825
    assert resp.forms[0]['f1'].value == 'foobar'
826
    resp.forms[0]['f1'] = 'barbaz'
827
    resp = resp.forms[0].submit('cancel')
828
    assert resp.location == 'http://example.net/backoffice/forms/1/'
829

  
830
    # check with a date field
831
    workflow.variables_formdef.fields.append(
832
            fields.DateField(id='2', varname='test2', label='Test2', type='date'))
833
    workflow.store()
834

  
835
    resp = app.get('/backoffice/forms/1/')
836
    resp = resp.click(href='workflow-variables')
837
    resp.form['f2'] = '2016-06-17'
838
    resp = resp.form.submit()
839
    assert time.strftime('%d %m %y', FormDef.get(formdef.id).workflow_options.get('test2')) == '17 06 16'
840

  
841

  
842
def test_form_workflow_table_variables(pub):
843
    create_superuser(pub)
844
    create_role()
845

  
846
    Workflow.wipe()
847
    workflow = Workflow(name='Workflow One')
848
    from wcs.workflows import WorkflowVariablesFieldsFormDef
849
    workflow.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=workflow)
850
    workflow.variables_formdef.fields.append(
851
            fields.TableRowsField(id='1', varname='test', label='Test2',
852
                type='tablerows', columns=['a']))
853
    workflow.variables_formdef.fields.append(
854
            fields.StringField(id='2', varname='test2', label='Test', type='string'))
855
    workflow.store()
856

  
857
    FormDef.wipe()
858
    formdef = FormDef()
859
    formdef.name = 'form title'
860
    formdef.fields = []
861
    formdef.workflow_id = workflow.id
862
    formdef.store()
863

  
864
    app = login(get_app(pub))
865
    resp = app.get('/backoffice/forms/1/')
866
    assert '"workflow-variables"' in resp.text
867

  
868
    # visit the variables page
869
    resp = resp.click(href='workflow-variables')
870

  
871
    # and set a value
872
    resp.form['f1$element0$col0'] = 'foobar'
873
    resp.form['f2'] = 'foobar'
874
    resp = resp.form.submit('submit')
875
    assert resp.location == 'http://example.net/backoffice/forms/1/'
876

  
877
    # check the value has been correctly saved
878
    assert FormDef.get(formdef.id).workflow_options == {
879
            'test': [['foobar']],
880
            'test2': 'foobar'}
881

  
882
    # go back to the variables page, also check value
883
    resp = resp.follow()
884
    resp = resp.click(href='workflow-variables')
885
    assert resp.form['f1$element0$col0'].value == 'foobar'
886
    assert resp.form['f2'].value == 'foobar'
887

  
888

  
889
def test_form_roles(pub):
890
    create_superuser(pub)
891
    role = create_role()
892

  
893
    FormDef.wipe()
894
    formdef = FormDef()
895
    formdef.name = 'form title'
896
    formdef.fields = []
897
    formdef.store()
898

  
899
    app = login(get_app(pub))
900
    resp = app.get('/backoffice/forms/1/')
901

  
902
    resp = resp.click('User Roles')
903
    resp = resp.forms[0].submit('cancel')
904

  
905
    resp = app.get('/backoffice/forms/1/')
906
    resp = resp.click('User Roles')
907
    resp.forms[0]['roles$element0'].value = role.id
908
    resp = resp.forms[0].submit('submit')
909
    assert FormDef.get(1).roles == [role.id]
910

  
911

  
912
def test_form_always_advertise(pub):
913
    create_superuser(pub)
914
    role = create_role()
915

  
916
    FormDef.wipe()
917
    formdef = FormDef()
918
    formdef.name = 'form title'
919
    formdef.fields = []
920
    formdef.store()
921

  
922
    app = login(get_app(pub))
923
    resp = app.get('/backoffice/forms/1/')
924

  
925
    # Display to unlogged users
926
    formdef.roles = [role.id]
927
    formdef.store()
928
    resp = app.get('/backoffice/forms/1/')
929
    assert_option_display(resp, 'Display to unlogged users', 'Disabled')
930
    resp = resp.click('Display to unlogged users')
931
    assert resp.forms[0]['always_advertise'].checked is False
932
    resp.forms[0]['always_advertise'].checked = True
933
    resp = resp.forms[0].submit()
934
    assert resp.location == 'http://example.net/backoffice/forms/1/'
935
    resp = resp.follow()
936
    assert_option_display(resp, 'Display to unlogged users', 'Enabled')
937
    assert FormDef.get(1).always_advertise is True
938

  
939

  
940
def test_form_digest_template(pub):
941
    create_superuser(pub)
942
    role = create_role()
943

  
944
    FormDef.wipe()
945
    formdef = FormDef()
946
    formdef.name = 'form title'
947
    formdef.fields = [fields.StringField(id='1', varname='test', label='Test', type='string')]
948
    formdef.store()
949

  
950
    formdata = formdef.data_class()()
951
    formdata.just_created()
952
    formdata.data = {'1': 'hello'}
953
    formdata.store()
954

  
955
    app = login(get_app(pub))
956
    resp = app.get('/backoffice/forms/1/')
957

  
958
    # Display to unlogged users
959
    assert_option_display(resp, 'Digest Template', 'None')
960
    resp = resp.click('Digest Template')
961
    resp.form['digest_template'] = 'X{{form_var_test}}Y'
962
    resp = resp.form.submit()
963
    assert resp.location == 'http://example.net/backoffice/forms/1/'
964
    resp = resp.follow()
965
    assert_option_display(resp, 'Digest Template', 'Custom')
966
    formdef = FormDef.get(formdef.id)
967
    assert formdef.digest_template == 'X{{form_var_test}}Y'
968

  
969
    assert 'Existing forms will be updated in the background.' in resp.text
970
    # afterjobs are actually run synchronously during tests; we don't have
971
    # to wait to check the digest has been updated:
972
    assert formdef.data_class().get(formdata.id).digest == 'XhelloY'
973

  
974

  
975
def test_form_delete(pub):
976
    create_superuser(pub)
977
    create_role()
978

  
979
    FormDef.wipe()
980
    formdef = FormDef()
981
    formdef.name = 'form title'
982
    formdef.fields = []
983
    formdef.store()
984

  
985
    app = login(get_app(pub))
986
    resp = app.get('/backoffice/forms/1/')
987

  
988
    resp = resp.click(href='delete')
989
    resp = resp.forms[0].submit()
990
    assert resp.location == 'http://example.net/backoffice/forms/'
991
    resp = resp.follow()
992
    assert FormDef.count() == 0
993

  
994

  
995
def test_form_duplicate(pub):
996
    create_superuser(pub)
997
    create_role()
998

  
999
    FormDef.wipe()
1000
    formdef = FormDef()
1001
    formdef.name = 'form title'
1002
    formdef.fields = []
1003
    formdef.store()
1004

  
1005
    app = login(get_app(pub))
1006
    resp = app.get('/backoffice/forms/1/')
1007

  
1008
    resp = resp.click(href='duplicate')
1009
    assert resp.location == 'http://example.net/backoffice/forms/2/'
1010
    resp = resp.follow()
1011
    assert FormDef.count() == 2
1012
    assert FormDef.get(2).name == 'form title (copy)'
1013

  
1014
    resp = app.get('/backoffice/forms/1/')
1015
    resp = resp.click(href='duplicate')
1016
    assert resp.location == 'http://example.net/backoffice/forms/3/'
1017
    resp = resp.follow()
1018
    assert FormDef.count() == 3
1019
    assert FormDef.get(3).name == 'form title (copy 2)'
1020

  
1021

  
1022
def test_form_export(pub):
1023
    create_superuser(pub)
1024
    create_role()
1025

  
1026
    FormDef.wipe()
1027
    formdef = FormDef()
1028
    formdef.name = 'form title'
1029
    formdef.fields = []
1030
    formdef.store()
1031

  
1032
    app = login(get_app(pub))
1033
    resp = app.get('/backoffice/forms/1/')
1034

  
1035
    resp = resp.click(href='export')
1036
    xml_export = resp.text
1037

  
1038
    fd = StringIO(xml_export)
1039
    formdef2 = FormDef.import_from_xml(fd)
1040
    assert formdef2.name == 'form title'
1041

  
1042

  
1043
def test_form_import(pub):
1044
    user = create_superuser(pub)
1045
    role = create_role()
1046

  
1047
    FormDef.wipe()
1048
    formdef = FormDef()
1049
    formdef.name = 'form title'
1050
    formdef.fields = []
1051
    formdef.store()
1052
    formdef_xml = ET.tostring(formdef.export_to_xml(include_id=True))
1053

  
1054
    FormDef.wipe()
1055
    assert FormDef.count() == 0
1056

  
1057
    app = login(get_app(pub))
1058
    resp = app.get('/backoffice/forms/')
1059
    resp = resp.click(href='import')
1060
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef_xml)
1061
    resp = resp.forms[0].submit()
1062
    assert FormDef.count() == 1
1063

  
1064
    # import the same formdef a second time, make sure url name and internal
1065
    # identifier are not reused
1066
    resp = app.get('/backoffice/forms/')
1067
    resp = resp.click(href='import')
1068
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef_xml)
1069
    resp = resp.forms[0].submit()
1070
    assert FormDef.count() == 2
1071
    assert FormDef.get(1).url_name == 'form-title'
1072
    assert FormDef.get(2).url_name == 'form-title-1'
1073
    assert FormDef.get(1).internal_identifier == 'form-title'
1074
    assert FormDef.get(2).internal_identifier == 'form-title-1'
1075

  
1076
    # import a formdef with an url name that doesn't match its title,
1077
    # it should be kept intact.
1078
    formdef.url_name = 'xxx-other-form-title'
1079
    formdef_xml = ET.tostring(formdef.export_to_xml(include_id=True))
1080

  
1081
    resp = app.get('/backoffice/forms/')
1082
    resp = resp.click(href='import')
1083
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef_xml)
1084
    resp = resp.forms[0].submit()
1085
    assert FormDef.get(3).url_name == 'xxx-other-form-title'
1086
    assert FormDef.get(3).internal_identifier == 'form-title-2'
1087

  
1088
    # import an invalid file
1089
    resp = app.get('/backoffice/forms/')
1090
    resp = resp.click(href='import')
1091
    resp.form['file'] = Upload('formdef.wcs', b'garbage')
1092
    resp = resp.form.submit()
1093
    assert 'Invalid File' in resp.text
1094

  
1095
    # xml with duplicate id, fix it
1096
    formdef = FormDef()
1097
    formdef.name = 'form title'
1098
    formdef.fields = [
1099
        fields.StringField(id='42', label='1st field', type='string'),
1100
        fields.StringField(id='42', label='2nd field', type='string'),
1101
    ]
1102
    formdef_xml = ET.tostring(formdef.export_to_xml(include_id=True))
1103
    FormDef.wipe()
1104
    resp = app.get('/backoffice/forms/')
1105
    resp = resp.click(href='import')
1106
    resp.form['file'] = Upload('formdef.wcs', formdef_xml)
1107
    resp = resp.form.submit()
1108
    resp = resp.follow()
1109
    assert 'form contained errors and has been automatically fixed' in resp.text
1110
    assert FormDef.count() == 1
1111
    assert FormDef.get(1).fields[0].id == '1'
1112
    assert FormDef.get(1).fields[1].id == '2'
1113

  
1114

  
1115
def test_form_qrcode(pub):
1116
    create_superuser(pub)
1117
    create_role()
1118

  
1119
    FormDef.wipe()
1120
    formdef = FormDef()
1121
    formdef.name = 'form title'
1122
    formdef.fields = []
1123
    formdef.store()
1124

  
1125
    app = login(get_app(pub))
1126
    resp = app.get('/backoffice/forms/1/')
1127

  
1128
    resp = resp.click(href='qrcode')
1129
    assert '<div id="qrcode">' in resp.text
1130
    resp = resp.click('Download')
1131
    assert resp.content_type == 'image/png'
1132

  
1133

  
1134
def test_form_description(pub):
1135
    create_superuser(pub)
1136
    create_role()
1137

  
1138
    FormDef.wipe()
1139
    formdef = FormDef()
1140
    formdef.name = 'form title'
1141
    formdef.fields = []
1142
    formdef.store()
1143

  
1144
    app = login(get_app(pub))
1145
    resp = app.get('/backoffice/forms/1/')
1146
    assert_option_display(resp, 'Description', 'None')
1147

  
1148
    resp = resp.click('Description')
1149
    resp.forms[0]['description'].value = '<p>Hello World</p>'
1150
    resp = resp.forms[0].submit()
1151
    assert resp.location == 'http://example.net/backoffice/forms/1/'
1152
    resp = resp.follow()
1153
    assert_option_display(resp, 'Description', 'On')
1154

  
1155

  
1156
def test_form_new_field(pub):
1157
    create_superuser(pub)
1158
    create_role()
1159

  
1160
    FormDef.wipe()
1161
    formdef = FormDef()
1162
    formdef.name = 'form title'
1163
    formdef.fields = []
1164
    formdef.store()
1165

  
1166
    app = login(get_app(pub))
1167
    resp = app.get('/backoffice/forms/1/')
1168
    resp = resp.click(href='fields/')
1169
    assert 'There are not yet any fields for this form' in resp.text
1170

  
1171
    resp.forms[0]['label'] = 'foobar'
1172
    resp.forms[0]['type'] = 'string'
1173
    resp = resp.forms[0].submit()
1174
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/'
1175
    resp = resp.follow()
1176
    assert 'foobar' in resp.text
1177
    assert 'Use drag and drop' in resp.text
1178

  
1179
    assert len(FormDef.get(1).fields) == 1
1180
    assert FormDef.get(1).fields[0].key == 'string'
1181
    assert FormDef.get(1).fields[0].label == 'foobar'
1182

  
1183
    # add a title too
1184
    resp.forms[0]['label'] = 'baz'
1185
    resp.forms[0]['type'] = 'title'
1186
    resp = resp.forms[0].submit()
1187
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/'
1188
    resp = resp.follow()
1189

  
1190
    # check it's in the preview
1191
    resp = app.get('/backoffice/forms/1/')
1192
    assert '<h3 data-field-id="1">baz</h3>' in resp.text
1193

  
1194

  
1195
def test_form_delete_field(pub):
1196
    create_superuser(pub)
1197
    create_role()
1198

  
1199
    FormDef.wipe()
1200
    formdef = FormDef()
1201
    formdef.name = 'form title'
1202
    formdef.fields = [fields.StringField(id='1', label='1st field', type='string')]
1203
    formdef.store()
1204
    formdef.data_class().wipe()
1205

  
1206
    app = login(get_app(pub))
1207
    resp = app.get('/backoffice/forms/1/')
1208
    resp = resp.click(href='fields/')
1209
    assert '1st field' in resp.text
1210
    assert 'Use drag and drop' in resp.text
1211
    assert 'Also remove all fields from the page' not in resp.text
1212

  
1213
    resp = resp.click(href='1/delete')
1214
    assert 'You are about to remove the "1st field" field.' in resp.text
1215
    assert 'Warning:' not in resp.text
1216
    resp = resp.forms[0].submit()
1217
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/'
1218
    resp = resp.follow()
1219
    assert len(FormDef.get(1).fields) == 0
1220

  
1221

  
1222
def test_form_delete_field_existing_data(pub):
1223
    create_superuser(pub)
1224
    create_role()
1225

  
1226
    FormDef.wipe()
1227
    formdef = FormDef()
1228
    formdef.name = 'form title'
1229
    formdef.fields = [
1230
        fields.StringField(id='1', label='1st field', type='string'),
1231
        fields.CommentField(id='2', label='comment field', type='comment'),
1232
    ]
1233
    formdef.store()
1234
    formdef.data_class().wipe()
1235

  
1236
    formdata = formdef.data_class()()
1237
    formdata.just_created()
1238
    formdata.data = {'1': 'hello'}
1239
    formdata.store()
1240

  
1241
    app = login(get_app(pub))
1242
    resp = app.get('/backoffice/forms/1/')
1243
    resp = resp.click(href='fields/')
1244
    resp = resp.click(href='1/delete')
1245
    assert 'You are about to remove the "1st field" field.' in resp.text
1246
    assert 'Warning:' in resp.text
1247
    resp = resp.forms[0].submit()
1248
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_2'
1249
    resp = resp.follow()
1250
    assert len(FormDef.get(1).fields) == 1
1251

  
1252
    # check non-data fields do not show this warning
1253
    resp = app.get('/backoffice/forms/1/')
1254
    resp = resp.click(href='fields/')
1255
    resp = resp.click(href='2/delete')
1256
    assert 'You are about to remove the "comment field" field.' in resp.text
1257
    assert 'Warning:' not in resp.text
1258
    resp = resp.forms[0].submit()
1259
    resp = resp.follow()
1260
    assert len(FormDef.get(1).fields) == 0
1261

  
1262

  
1263
def test_form_delete_page_field(pub):
1264
    create_superuser(pub)
1265
    create_role()
1266

  
1267
    FormDef.wipe()
1268
    formdef = FormDef()
1269
    formdef.name = 'form title'
1270
    formdef.fields = [
1271
        fields.PageField(id='1', label='page 1', type='page'),
1272
        fields.StringField(id='2', label='field 1 1', type='string'),
1273
        fields.StringField(id='3', label='field 1 2', type='string'),
1274
        fields.PageField(id='4', label='page 2', type='page'),
1275
        fields.PageField(id='5', label='page 3', type='page'),
1276
        fields.StringField(id='6', label='field 3 1', type='string'),
1277
        fields.StringField(id='7', label='field 3 2', type='string'),
1278
    ]
1279
    formdef.store()
1280
    formdef.data_class().wipe()
1281

  
1282
    app = login(get_app(pub))
1283

  
1284
    # delete fields from the page
1285
    resp = app.get('/backoffice/forms/1/fields/1/delete')
1286
    assert 'You are about to remove the "page 1" page.' in resp.text
1287
    assert 'Also remove all fields from the page' in resp.text
1288
    resp.forms[0]['delete_fields'] = True
1289
    resp = resp.forms[0].submit()
1290
    resp = resp.follow()
1291
    assert len(FormDef.get(1).fields) == 4
1292

  
1293
    # empty page
1294
    resp = app.get('/backoffice/forms/1/fields/4/delete')
1295
    assert 'You are about to remove the "page 2" page.' in resp.text
1296
    assert 'Also remove all fields from the page' not in resp.text
1297
    resp = resp.forms[0].submit()
1298
    resp = resp.follow()
1299
    assert len(FormDef.get(1).fields) == 3
1300

  
1301
    # keep fields
1302
    resp = app.get('/backoffice/forms/1/fields/5/delete')
1303
    assert 'You are about to remove the "page 3" page.' in resp.text
1304
    assert 'Also remove all fields from the page' in resp.text
1305
    resp.forms[0]['delete_fields'] = False
1306
    resp = resp.forms[0].submit()
1307
    resp = resp.follow()
1308
    assert len(FormDef.get(1).fields) == 2
1309

  
1310

  
1311
def test_form_duplicate_field(pub):
1312
    user = create_superuser(pub)
1313
    create_role()
1314

  
1315
    FormDef.wipe()
1316
    formdef = FormDef()
1317
    formdef.name = 'form title'
1318
    formdef.fields = [fields.StringField(id='1', label='1st field', type='string')]
1319
    formdef.store()
1320

  
1321
    app = login(get_app(pub))
1322
    resp = app.get('/backoffice/forms/1/')
1323
    resp = resp.click(href='fields/')
1324
    assert '1st field' in resp.text
1325

  
1326
    resp = resp.click(href='1/duplicate')
1327
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_2'
1328
    resp = resp.follow()
1329
    assert len(FormDef.get(1).fields) == 2
1330
    assert FormDef.get(1).fields[0].label == '1st field'
1331
    assert FormDef.get(1).fields[1].label == '1st field'
1332

  
1333

  
1334
def test_form_duplicate_file_field(pub):
1335
    create_superuser(pub)
1336
    create_role()
1337

  
1338
    FormDef.wipe()
1339
    formdef = FormDef()
1340
    formdef.name = 'form title'
1341
    formdef.fields = []
1342
    formdef.store()
1343

  
1344
    app = login(get_app(pub))
1345
    resp = app.get('/backoffice/forms/1/')
1346
    resp = resp.click(href='fields/')
1347

  
1348
    # add a first field
1349
    resp.forms[0]['label'] = 'foobar'
1350
    resp.forms[0]['type'] = 'file'
1351
    resp = resp.forms[0].submit()
1352
    assert resp.location == 'http://example.net/backoffice/forms/%s/fields/' % formdef.id
1353
    resp = resp.follow()
1354
    assert 'foobar' in resp.text
1355

  
1356
    resp = resp.click(href='%s/duplicate' % FormDef.get(formdef.id).fields[0].id)
1357
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_2'
1358
    resp = resp.follow()
1359

  
1360

  
1361
def test_form_edit_field(pub):
1362
    create_superuser(pub)
1363
    create_role()
1364

  
1365
    FormDef.wipe()
1366
    formdef = FormDef()
1367
    formdef.name = 'form title'
1368
    formdef.fields = [fields.StringField(id='1', label='1st field', type='string')]
1369
    formdef.store()
1370

  
1371
    app = login(get_app(pub))
1372
    resp = app.get('/backoffice/forms/1/')
1373
    resp = resp.click(href='fields/')
1374
    assert '1st field' in resp.text
1375

  
1376
    resp = resp.click('Edit', href='1/')
1377
    assert resp.forms[0]['label'].value == '1st field'
1378
    resp.forms[0]['label'] = 'changed field'
1379
    resp.forms[0]['required'] = False
1380
    resp = resp.forms[0].submit('submit')
1381
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1'
1382

  
1383
    assert FormDef.get(1).fields[0].label == 'changed field'
1384
    assert FormDef.get(1).fields[0].required == False
1385

  
1386

  
1387
def test_form_edit_field_advanced(pub):
1388
    create_superuser(pub)
1389
    create_role()
1390

  
1391
    FormDef.wipe()
1392
    formdef = FormDef()
1393
    formdef.name = 'form title'
1394
    formdef.fields = [fields.StringField(id='1', label='1st field', type='string')]
1395
    formdef.store()
1396

  
1397
    app = login(get_app(pub))
1398
    resp = app.get('/backoffice/forms/1/')
1399
    resp = resp.click(href='fields/')
1400
    assert '1st field' in resp.text
1401

  
1402
    resp = resp.click('Edit', href='1/')
1403
    assert resp.forms[0]['label'].value == '1st field'
1404
    assert '<legend>Additional parameters</legend>' in resp.text
1405
    assert '>Prefill</label>' in resp.text
1406
    # check the "prefill" field is under additional parameters
1407
    assert resp.text.index('<legend>Additional parameters</legend>') < \
1408
            resp.text.index('>Prefill</label>')
1409

  
1410
    # complete the "prefill" field
1411
    resp.forms[0]['prefill$type'] = 'String / Template'
1412
    resp.forms[0]['prefill$value_string'] = 'test'
1413
    resp = resp.forms[0].submit('submit')
1414
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1'
1415
    resp = resp.follow()
1416

  
1417
    assert FormDef.get(formdef.id).fields[0].prefill == {'type': 'string', 'value': 'test', 'locked': False}
1418

  
1419
    # do the same with 'data sources' field
1420
    resp = resp.click('Edit', href='1/')
1421
    assert resp.forms[0]['label'].value == '1st field'
1422
    assert '<legend>Additional parameters</legend>' in resp.text
1423
    assert '>Data Source</label>' in resp.text
1424
    # check the "data source" field is under additional parameters
1425
    assert resp.text.index('<legend>Additional parameters</legend>') < \
1426
            resp.text.index('>Data Source</label>')
1427

  
1428
    # start filling the "data source" field
1429
    resp.forms[0]['data_source$type'] = 'json'
1430
    resp.forms[0]['data_source$value'] = 'http://example.net'
1431
    resp = resp.forms[0].submit('submit')
1432
    resp = resp.follow()
1433

  
1434
    # it should now appear before the additional parameters section
1435
    resp = resp.click('Edit', href='1/')
1436
    assert resp.text.index('<legend>Additional parameters</legend>') > resp.text.index('>Data Source</label>')
1437

  
1438

  
1439
def test_form_prefill_field(pub):
1440
    create_superuser(pub)
1441
    create_role()
1442

  
1443
    FormDef.wipe()
1444
    formdef = FormDef()
1445
    formdef.name = 'form title'
1446
    formdef.fields = [fields.StringField(id='1', label='1st field', type='string')]
1447
    formdef.store()
1448

  
1449
    app = login(get_app(pub))
1450

  
1451
    resp = app.get('/backoffice/forms/1/fields/1/')
1452
    resp.form['prefill$type'] = 'String / Template'
1453
    resp.form['prefill$value_string'] = 'test'
1454
    resp = resp.form.submit('submit').follow()
1455
    assert FormDef.get(formdef.id).fields[0].prefill == {'type': 'string', 'value': 'test', 'locked': False}
1456

  
1457
    resp = app.get('/backoffice/forms/1/fields/1/')
1458
    resp.form['prefill$type'] = 'Python Expression'
1459
    resp.form['prefill$value_formula'] = 'True'
1460
    resp = resp.form.submit('submit').follow()
1461
    assert FormDef.get(formdef.id).fields[0].prefill == {'type': 'formula', 'value': 'True', 'locked': False}
1462

  
1463
    resp = app.get('/backoffice/forms/1/fields/1/')
1464
    resp.form['prefill$type'] = 'String / Template'
1465
    resp.form['prefill$value_string'] = '{{form_var_toto}}'
1466
    resp = resp.form.submit('submit').follow()
1467
    assert FormDef.get(formdef.id).fields[0].prefill == {'type': 'string', 'value': '{{form_var_toto}}', 'locked': False}
1468

  
1469
    # check error handling
1470
    resp = app.get('/backoffice/forms/1/fields/1/')
1471
    resp.form['prefill$type'] = 'Python Expression'
1472
    resp.form['prefill$value_formula'] = ':'
1473
    resp = resp.form.submit('submit')
1474
    assert 'invalid expression: unexpected EOF while parsing' in resp.text
1475

  
1476
    resp = app.get('/backoffice/forms/1/fields/1/')
1477
    resp.form['prefill$type'] = 'String / Template'
1478
    resp.form['prefill$value_string'] = '{% if %}'
1479
    resp = resp.form.submit('submit')
1480
    assert 'syntax error in Django template: Unexpected end of expression' in resp.text
1481

  
1482

  
1483
def test_form_edit_string_field_validation(pub):
1484
    create_superuser(pub)
1485
    create_role()
1486

  
1487
    FormDef.wipe()
1488
    formdef = FormDef()
1489
    formdef.name = 'form title'
1490
    formdef.fields = [fields.StringField(id='1', label='1st field', type='string')]
1491
    formdef.store()
1492

  
1493
    app = login(get_app(pub))
1494
    resp = app.get('/backoffice/forms/1/')
1495
    resp = resp.click(href='fields/')
1496
    assert '1st field' in resp.text
1497

  
1498
    resp = resp.click('Edit', href='1/')
1499
    resp.form['validation$type'] = 'Regular Expression'
1500
    resp.form['validation$value_regex'] = r'\d+'
1501
    resp = resp.form.submit('submit').follow()
1502
    assert FormDef.get(formdef.id).fields[0].validation == {'type': 'regex', 'value': r'\d+'}
1503

  
1504
    resp = resp.click('Edit', href='1/')
1505
    resp.form['validation$type'] = 'None'
1506
    resp = resp.form.submit('submit').follow()
1507
    assert FormDef.get(formdef.id).fields[0].validation is None
1508

  
1509
    resp = resp.click('Edit', href='1/')
1510
    resp.form['validation$type'] = 'Django Condition'
1511
    resp.form['validation$value_django'] = 'value|decimal < 20'
1512
    resp = resp.form.submit('submit').follow()
1513
    assert FormDef.get(formdef.id).fields[0].validation == {'type': 'django', 'value': 'value|decimal < 20'}
1514

  
1515
    resp = resp.click('Edit', href='1/')
1516
    resp.form['validation$type'] = 'Django Condition'
1517
    resp.form['validation$value_django'] = '{{ value|decimal < 20 }}'
1518
    resp = resp.form.submit('submit')
1519
    assert 'syntax error' in resp.text
1520

  
1521

  
1522
def test_form_edit_item_field(pub):
1523
    create_superuser(pub)
1524
    create_role()
1525

  
1526
    FormDef.wipe()
1527
    formdef = FormDef()
1528
    formdef.name = 'form title'
1529
    formdef.fields = [fields.ItemField(id='1', label='1st field', type='item')]
1530
    formdef.store()
1531

  
1532
    app = login(get_app(pub))
1533
    resp = app.get('/backoffice/forms/1/')
1534
    resp = resp.click(href='fields/')
1535
    assert '1st field' in resp.text
1536

  
1537
    resp = resp.click('Edit', href='1/')
1538
    assert resp.forms[0]['label'].value == '1st field'
1539
    resp.forms[0]['label'] = 'changed field'
1540
    resp.forms[0]['required'] = False
1541
    resp = resp.forms[0].submit('items$add_element')
1542
    # this adds a second field
1543
    assert 'items$element0' in resp.form.fields
1544
    assert 'items$element1' in resp.form.fields
1545
    # but don't fill anything
1546
    resp = resp.forms[0].submit('submit')
1547
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1'
1548
    resp = resp.follow()
1549

  
1550
    assert FormDef.get(1).fields[0].label == 'changed field'
1551
    assert FormDef.get(1).fields[0].required == False
1552
    assert FormDef.get(1).fields[0].items is None
1553

  
1554
    # edit and fill with one item
1555
    resp = resp.click('Edit', href='1/')
1556
    assert resp.forms[0]['label'].value == 'changed field'
1557
    resp.forms[0]['items$element0'] = 'XXX'
1558
    resp = resp.forms[0].submit('submit')
1559
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1'
1560
    assert FormDef.get(1).fields[0].items == ['XXX']
1561

  
1562

  
1563
def test_form_edit_item_field_data_source(pub):
1564
    create_superuser(pub)
1565
    create_role()
1566

  
1567
    FormDef.wipe()
1568
    formdef = FormDef()
1569
    formdef.name = 'form title'
1570
    formdef.fields = [fields.ItemField(id='1', label='1st field', type='item')]
1571
    formdef.store()
1572

  
1573
    app = login(get_app(pub))
1574
    resp = app.get('/backoffice/forms/1/fields/1/')
1575
    assert resp.form['data_source$type'].options == [
1576
        (u'None', True, u'None'),
1577
        (u'json', False, u'JSON URL'),
1578
        (u'jsonp', False, u'JSONP URL'),
1579
        (u'python', False, u'Python Expression')
1580
    ]
1581
    resp = resp.form.submit('submit').follow()
1582

  
1583
    data_source = NamedDataSource(name='Foobar')
1584
    data_source.data_source = {'type': 'formula', 'value': '[]'}
1585
    data_source.store()
1586

  
1587
    resp = app.get('/backoffice/forms/1/fields/1/')
1588
    assert resp.form['data_source$type'].options == [
1589
        (u'None', True, u'None'),
1590
        (u'foobar', False, u'Foobar'),
1591
        (u'json', False, u'JSON URL'),
1592
        (u'jsonp', False, u'JSONP URL'),
1593
        (u'python', False, u'Python Expression')
1594
    ]
1595
    resp.form['data_source$type'].value = 'foobar'
1596
    resp = resp.form.submit('submit').follow()
1597
    assert FormDef.get(formdef.id).fields[0].data_source == {'type': 'foobar'}
1598

  
1599
    carddef = CardDef()
1600
    carddef.name = 'Baz'
1601
    carddef.store()
1602

  
1603
    resp = app.get('/backoffice/forms/1/fields/1/')
1604
    assert resp.form['data_source$type'].options == [
1605
        (u'None', False, u'None'),
1606
        (u'foobar', True, u'Foobar'),
1607
        (u'json', False, u'JSON URL'),
1608
        (u'jsonp', False, u'JSONP URL'),
1609
        (u'python', False, u'Python Expression')
1610
    ]
1611

  
1612
    carddef.digest_template = 'plop'
1613
    carddef.store()
1614

  
1615
    resp = app.get('/backoffice/forms/1/fields/1/')
1616
    assert resp.form['data_source$type'].options == [
1617
        (u'None', False, u'None'),
1618
        (u'carddef:%s' % carddef.url_name, False, u'Baz'),
1619
        (u'foobar', True, u'Foobar'),
1620
        (u'json', False, u'JSON URL'),
1621
        (u'jsonp', False, u'JSONP URL'),
1622
        (u'python', False, u'Python Expression')
1623
    ]
1624

  
1625
    resp.form['data_source$type'].value = 'carddef:%s' % carddef.url_name
1626
    resp = resp.form.submit('submit').follow()
1627
    assert FormDef.get(formdef.id).fields[0].data_source == {'type': 'carddef:%s' % carddef.url_name}
1628

  
1629
    # set json source then back to none
1630
    resp = app.get('/backoffice/forms/1/fields/1/')
1631
    resp.form['data_source$type'].value = 'json'
1632
    resp.form['data_source$value'].value = 'http://whatever'
1633
    resp = resp.form.submit('submit').follow()
1634
    assert FormDef.get(formdef.id).fields[0].data_source == {'type': 'json', 'value': 'http://whatever'}
1635

  
1636
    resp = app.get('/backoffice/forms/1/fields/1/')
1637
    resp.form['data_source$type'].value = 'None'
1638
    resp = resp.form.submit('submit').follow()
1639
    resp = app.get('/backoffice/forms/1/')
1640

  
1641

  
1642
def test_form_edit_items_field(pub):
1643
    create_superuser(pub)
1644
    create_role()
1645

  
1646
    FormDef.wipe()
1647
    formdef = FormDef()
1648
    formdef.name = 'form title'
1649
    formdef.fields = [fields.ItemsField(id='1', label='1st field', type='items')]
1650
    formdef.store()
1651

  
1652
    app = login(get_app(pub))
1653
    resp = app.get('/backoffice/forms/1/')
1654
    resp = resp.click(href='fields/')
1655
    assert '1st field' in resp.text
1656

  
1657
    resp = resp.click('Edit', href='1/')
1658
    assert resp.forms[0]['label'].value == '1st field'
1659
    resp.forms[0]['label'] = 'changed field'
1660
    resp.forms[0]['required'] = False
1661
    resp = resp.forms[0].submit('items$add_element')
1662
    # this adds a second field
1663
    assert 'items$element0' in resp.form.fields
1664
    assert 'items$element1' in resp.form.fields
1665
    # but don't fill anything
1666
    resp = resp.forms[0].submit('submit')
1667
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1'
1668
    resp = resp.follow()
1669

  
1670
    assert FormDef.get(1).fields[0].label == 'changed field'
1671
    assert FormDef.get(1).fields[0].required == False
1672
    assert FormDef.get(1).fields[0].items is None
1673

  
1674
    # edit and fill with one item
1675
    resp = resp.click('Edit', href='1/')
1676
    assert resp.forms[0]['label'].value == 'changed field'
1677
    resp.forms[0]['items$element0'] = 'XXX'
1678
    resp = resp.forms[0].submit('submit')
1679
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1'
1680
    assert FormDef.get(1).fields[0].items == ['XXX']
1681

  
1682
    # check prefilling is only possible with Python
1683
    resp = resp.follow()
1684
    resp = resp.click('Edit', href='1/')
1685
    assert resp.forms[0]['prefill$type'].options == [
1686
            (u'None', True, u'None'), (u'Python Expression', False, u'Python Expression')]
1687

  
1688

  
1689
def test_form_edit_page_field(pub):
1690
    create_superuser(pub)
1691
    create_role()
1692

  
1693
    FormDef.wipe()
1694
    formdef = FormDef()
1695
    formdef.name = 'form title'
1696
    formdef.fields = []
1697
    formdef.store()
1698

  
1699
    app = login(get_app(pub))
1700
    resp = app.get('/backoffice/forms/1/')
1701
    resp = resp.click(href='fields/')
1702
    assert 'There are not yet any fields for this form' in resp.text
1703

  
1704
    resp.forms[0]['label'] = 'foobar'
1705
    resp.forms[0]['type'] = 'page'
1706
    resp = resp.forms[0].submit()
1707
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/'
1708
    resp = resp.follow()
1709
    assert 'Page #1' in resp.text
1710
    assert 'foobar' in resp.text
1711
    assert 'Use drag and drop' in resp.text
1712

  
1713
    assert len(FormDef.get(1).fields) == 1
1714
    assert FormDef.get(1).fields[0].key == 'page'
1715
    assert FormDef.get(1).fields[0].label == 'foobar'
1716

  
1717
    resp = resp.click('Edit', href='1/')
1718
    resp.form['post_conditions$element0$condition$type'] = 'python'
1719
    resp.form['post_conditions$element0$condition$value_python'] = 'foo'
1720
    resp.form['post_conditions$element0$error_message'] = 'bar'
1721
    resp = resp.form.submit('post_conditions$add_element')
1722
    resp.form['post_conditions$element1$condition$type'] = 'python'
1723
    resp.form['post_conditions$element1$condition$value_python'] = 'foo2'
1724
    resp = resp.form.submit('submit')
1725
    assert 'Both condition and error message are required.' in resp.text
1726
    resp.form['post_conditions$element1$error_message'] = 'bar2'
1727
    resp = resp.form.submit('submit').follow()
1728

  
1729
    assert FormDef.get(1).fields[0].post_conditions == [
1730
            {'condition': {'type': 'python', 'value': 'foo'}, 'error_message': 'bar'},
1731
            {'condition': {'type': 'python', 'value': 'foo2'}, 'error_message': 'bar2'},
1732
    ]
1733

  
1734
    resp = resp.click('Edit', href='1/')
1735
    resp.form['post_conditions$element1$condition$type'] = 'django'
1736
    resp.form['post_conditions$element1$condition$value_django'] = 'foo3'
1737
    resp = resp.form.submit('submit').follow()
1738
    assert FormDef.get(1).fields[0].post_conditions == [
1739
            {'condition': {'type': 'python', 'value': 'foo'}, 'error_message': 'bar'},
1740
            {'condition': {'type': 'django', 'value': 'foo3'}, 'error_message': 'bar2'},
1741
    ]
1742

  
1743

  
1744
def test_form_edit_comment_field(pub):
1745
    create_superuser(pub)
1746
    create_role()
1747

  
1748
    FormDef.wipe()
1749
    formdef = FormDef()
1750
    formdef.name = 'form title'
1751
    formdef.fields = [fields.CommentField(id='1', label='a comment field', type='comment')]
1752
    formdef.store()
1753

  
1754
    app = login(get_app(pub))
1755
    resp = app.get('/backoffice/forms/1/fields/1/')
1756
    assert 'a comment field' in resp.text
1757
    assert 'WysiwygTextWidget' in resp.text
1758

  
1759
    # legacy, double line breaks will be converted to paragraphs
1760
    formdef.fields = [fields.CommentField(id='1', type='comment',
1761
        label='a comment field\n\na second line')]
1762
    formdef.store()
1763
    resp = app.get('/backoffice/forms/1/fields/1/')
1764
    assert 'WysiwygTextWidget' in resp.text
1765
    resp = resp.form.submit('submit')
1766
    assert FormDef.get(formdef.id).fields[0].label == '<p>a comment field</p>\n<p>a second line</p>'
1767

  
1768
    # starting with a <
1769
    formdef.fields = [fields.CommentField(id='1', type='comment',
1770
        label='<strong>a comment field\n\na second line</strong>')]
1771
    formdef.store()
1772
    resp = app.get('/backoffice/forms/1/fields/1/')
1773
    assert 'WysiwygTextWidget' in resp.text
1774

  
1775
    # legacy, ezt syntax in a non-html field will be presented as a textarea
1776
    formdef.fields = [fields.CommentField(id='1', type='comment',
1777
        label='[if-any toto]hello world[end]')]
1778
    formdef.store()
1779
    resp = app.get('/backoffice/forms/1/fields/1/')
1780
    assert 'WysiwygTextWidget' not in resp.text
1781

  
1782
    # check a new field is created with label as HTML, enclosing label in <p>
1783
    resp = app.get('/backoffice/forms/1/fields/')
1784
    resp.forms[0]['label'] = 'foobar'
1785
    resp.forms[0]['type'] = 'comment'
1786
    resp = resp.forms[0].submit()
1787
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/'
1788
    assert FormDef.get(formdef.id).fields[-1].label == '<p>foobar</p>'
1789

  
1790
    # unless label is already given as HTML
1791
    resp = app.get('/backoffice/forms/1/fields/')
1792
    resp.forms[0]['label'] = '<div>blah</div>'
1793
    resp.forms[0]['type'] = 'comment'
1794
    resp = resp.forms[0].submit()
1795
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/'
1796
    assert FormDef.get(formdef.id).fields[-1].label == '<div>blah</div>'
1797

  
1798

  
1799
def test_form_comment_field_textwidget_validation(pub):
1800
    create_superuser(pub)
1801
    FormDef.wipe()
1802
    formdef = FormDef()
1803
    formdef.name = 'form title'
1804
    # legacy, ezt syntax in a non-html field will be presented as a textarea
1805
    formdef.fields = [fields.CommentField(id='1', type='comment',
1806
        label='[if-any toto]hello world[end]')]
1807
    formdef.store()
1808
    app = login(get_app(pub))
1809
    resp = app.get('/backoffice/forms/1/fields/1/')
1810

  
1811
    # bad {% %} Django template syntax
1812
    assert 'WysiwygTextWidget' not in resp.text
1813
    resp.form.fields['label'][0].value = '{% if cond %}no endif provided'
1814
    resp = resp.form.submit('submit')
1815
    assert 'syntax error in Django template: Unclosed tag on line 1' in resp.text
1816

  
1817
    # bad {{ }} Django template syntax
1818
    assert 'WysiwygTextWidget' not in resp.text
1819
    resp.form.fields['label'][0].value = '{{0+0}}'
1820
    resp = resp.form.submit('submit')
1821
    assert 'syntax error in Django template: Could not parse' in resp.text
1822

  
1823
    # bad EZT syntax
1824
    assert 'WysiwygTextWidget' not in resp.text
1825
    resp.form.fields['label'][0].value = '[end]'
1826
    resp = resp.form.submit('submit')
1827
    assert 'syntax error in ezt template: unmatched [end]' in resp.text
1828

  
1829
    # good syntax
1830
    assert 'WysiwygTextWidget' not in resp.text
1831
    resp.form.fields['label'][0].value = '{{variable}}'
1832
    resp = resp.form.submit('submit')
1833
    assert FormDef.get(formdef.id).fields[0].label == '{{variable}}'
1834

  
1835
def test_form_comment_field_wysiwygtextwidget_validation(pub):
1836
    create_superuser(pub)
1837
    create_role()
1838

  
1839
    FormDef.wipe()
1840
    formdef = FormDef()
1841
    formdef.name = 'form title'
1842
    formdef.fields = [fields.CommentField(id='1', label='a comment field', type='comment')]
1843
    formdef.store()
1844

  
1845
    app = login(get_app(pub))
1846
    resp = app.get('/backoffice/forms/1/fields/1/')
1847
    assert 'a comment field' in resp.text
1848

  
1849
    # bad {% %} Django template syntax
1850
    assert 'WysiwygTextWidget' in resp.text
1851
    resp.form.fields['label'][0].value = '{% if cond %}no endif provided'
1852
    resp = resp.form.submit('submit')
1853
    assert 'syntax error in Django template: Unclosed tag on line 1' in resp.text
1854

  
1855
    # bad {{ }} Django template syntax
1856
    assert 'WysiwygTextWidget' in resp.text
1857
    resp.form.fields['label'][0].value = '{{0+0}}'
1858
    resp = resp.form.submit('submit')
1859
    assert 'syntax error in Django template: Could not parse' in resp.text
1860

  
1861
    # bad EZT syntax
1862
    assert 'WysiwygTextWidget' in resp.text
1863
    resp.form.fields['label'][0].value = '[end]'
1864
    resp = resp.form.submit('submit')
1865
    assert 'syntax error in ezt template: unmatched [end]' in resp.text
1866

  
1867
    # good syntax
1868
    assert 'WysiwygTextWidget' in resp.text
1869
    resp.form.fields['label'][0].value = '{{variable}}'
1870
    resp = resp.form.submit('submit')
1871
    assert FormDef.get(formdef.id).fields[0].label == '{{variable}}'
1872

  
1873
def test_form_edit_map_field(pub):
1874
    create_superuser(pub)
1875
    create_role()
1876

  
1877
    FormDef.wipe()
1878
    formdef = FormDef()
1879
    formdef.name = 'form title'
1880
    formdef.fields = [fields.MapField(id='1', label='a field', type='map')]
1881
    formdef.store()
1882

  
1883
    app = login(get_app(pub))
1884

  
1885
    resp = app.get('/backoffice/forms/1/fields/1/')
1886
    resp = resp.form.submit('submit')
1887
    assert resp.location
1888

  
1889
    # min
1890
    formdef.store()
1891
    resp = app.get('/backoffice/forms/1/fields/1/')
1892
    resp.form['min_zoom'] = 'Wide area'
1893
    resp = resp.form.submit('submit')
1894
    assert FormDef.get(formdef.id).fields[0].min_zoom == '9'
1895

  
1896
    # max
1897
    formdef.store()
1898
    resp = app.get('/backoffice/forms/1/fields/1/')
1899
    resp.form['max_zoom'] = 'Small road'
1900
    resp = resp.form.submit('submit')
1901
    assert FormDef.get(formdef.id).fields[0].max_zoom == '16'
1902

  
1903
    # both
1904
    formdef.store()
1905
    resp = app.get('/backoffice/forms/1/fields/1/')
1906
    resp.form['min_zoom'] = 'Wide area'
1907
    resp.form['max_zoom'] = 'Small road'
1908
    resp = resp.form.submit('submit')
1909
    assert FormDef.get(formdef.id).fields[0].min_zoom == '9'
1910
    assert FormDef.get(formdef.id).fields[0].max_zoom == '16'
1911

  
1912
    # inverted
1913
    formdef.store()
1914
    resp = app.get('/backoffice/forms/1/fields/1/')
1915
    resp.form['min_zoom'] = 'Small road'
1916
    resp.form['max_zoom'] = 'Wide area'
1917
    resp = resp.form.submit('submit')
1918
    assert 'widget-with-error' in resp.text
1919

  
1920
    # initial out of range
1921
    formdef.store()
1922
    resp = app.get('/backoffice/forms/1/fields/1/')
1923
    resp.form['initial_zoom'] = 'Whole world'
1924
    resp.form['min_zoom'] = 'Wide area'
1925
    resp.form['max_zoom'] = 'Small road'
1926
    resp = resp.form.submit('submit')
1927
    assert 'widget-with-error' in resp.text
1928

  
1929
    # prefill fields
1930
    resp = app.get('/backoffice/forms/1/fields/1/')
1931
    resp.form['prefill$type'].value = 'Geolocation'
1932
    resp.form['prefill$value_geolocation'].value = 'Position'
1933
    resp = resp.form.submit('submit')
1934
    assert FormDef.get(formdef.id).fields[0].prefill == {
1935
            'type': 'geolocation', 'value': 'position', 'locked': False}
1936

  
1937

  
1938
def test_form_edit_field_warnings(pub):
1939
    create_superuser(pub)
1940
    create_role()
1941

  
1942
    FormDef.wipe()
1943
    formdef = FormDef()
1944
    formdef.name = 'form title'
1945
    formdef.fields = [fields.StringField(id='%d' % i, label='field %d' % i, type='string')
1946
                      for i in range(1,10)]
1947
    formdef.store()
1948

  
1949
    app = login(get_app(pub))
1950
    resp = app.get('/backoffice/forms/1/')
1951
    resp = resp.click(href='fields/')
1952
    assert 'more than 500 fields' not in resp.text
1953
    assert 'first field should be of type "page"' not in resp.text
1954

  
1955
    formdef.fields.append(fields.PageField(id='1000', label='page', type='page'))
1956
    formdef.store()
1957
    resp = app.get('/backoffice/forms/1/')
1958
    resp = resp.click(href='fields/')
1959
    assert 'more than 500 fields' not in resp.text
1960
    assert 'first field should be of type "page"' in resp.text
1961

  
1962
    formdef.fields.extend([fields.StringField(id='%d' % i, label='field %d' % i, type='string')
1963
                      for i in range(10,510)])
1964
    formdef.store()
1965
    resp = app.get('/backoffice/forms/1/')
1966
    resp = resp.click(href='fields/')
1967
    assert 'more than 500 fields' in resp.text
1968
    assert 'first field should be of type "page"' in resp.text
1969

  
1970
    FormDef.wipe()
1971

  
1972

  
1973
def test_form_limit_display_to_page(pub):
1974
    create_superuser(pub)
1975
    create_role()
1976

  
1977
    FormDef.wipe()
1978
    formdef = FormDef()
1979
    formdef.name = 'form title'
1980
    formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
1981
            fields.StringField(id='1', label='string', type='string', varname='foobar'),
1982
            fields.PageField(id='2', label='2nd page', type='page'),
1983
            fields.StringField(id='3', label='string 2', type='string', varname='baz')]
1984
    formdef.store()
1985

  
1986
    app = login(get_app(pub))
1987
    resp = app.get('/backoffice/forms/1/fields/')
1988
    assert '{{form_var_foobar}}' in resp.text
1989
    assert '2nd page' in resp.text
1990
    resp = resp.click('Limit display to this page', index=0)
1991
    hidden_fields = ''.join(re.findall('display:none.*', resp.text))
1992
    assert 'Display all pages' in resp.text
1993
    assert '{{form_var_foobar}}' not in hidden_fields
1994
    assert '{{form_var_baz}}' in hidden_fields
1995

  
1996

  
1997
def test_form_legacy_int_id(pub):
1998
    create_superuser(pub)
1999
    create_role()
2000

  
2001
    Category.wipe()
2002
    cat = Category(name='Foo')
2003
    cat.store()
2004

  
2005
    Workflow.wipe()
2006
    workflow = Workflow(name='Workflow One')
2007
    # create it with a single status
2008
    workflow.possible_status = [Workflow.get_default_workflow().possible_status[-1]]
2009
    workflow.store()
2010

  
2011
    FormDef.wipe()
2012
    formdef = FormDef()
2013
    formdef.name = 'form title'
2014
    formdef.fields = []
2015

  
2016
    role = Role(name='ZAB') # Z to get sorted last
2017
    role.store()
2018

  
2019
    # set attributes using integers
2020
    formdef.category_id = int(cat.id)
2021
    formdef.workflow_id = int(workflow.id)
2022
    formdef.workflow_roles = {'_receiver': int(role.id)}
2023
    formdef.roles = ['logged-users', int(role.id)]
2024

  
2025
    formdef.store()
2026

  
2027
    formdef = FormDef.get(formdef.id) # will run migrate
2028

  
2029
    app = login(get_app(pub))
2030
    resp = app.get('/backoffice/forms/1/')
2031

  
2032
    resp = resp.click(href='category')
2033
    assert resp.forms[0]['category_id'].value
2034

  
2035
    resp = app.get('/backoffice/forms/1/')
2036
    resp = resp.click(href='workflow', index=1)
2037
    assert resp.forms[0]['workflow_id'].value
2038

  
2039
    resp = app.get('/backoffice/forms/1/')
2040
    resp = resp.click('User Roles')
2041
    assert resp.forms[0]['roles$element0'].value == 'logged-users'
2042
    assert resp.forms[0]['roles$element1'].value == role.id
2043

  
2044
    resp = app.get('/backoffice/forms/1/')
2045
    resp = resp.click('Recipient')
2046
    assert resp.forms[0]['role_id'].value == role.id
2047

  
2048

  
2049
def test_form_anonymise(pub):
2050
    create_superuser(pub)
2051
    create_role()
2052

  
2053
    FormDef.wipe()
2054
    formdef = FormDef()
2055
    formdef.name = 'form title'
2056
    formdef.fields = []
2057
    formdef.store()
2058

  
2059
    data_class = formdef.data_class()
2060
    data_class.wipe()
2061
    for i in range(10):
2062
        formdata = data_class()
2063
        formdata.just_created()
2064
        if i < 3:
2065
            formdata.status = 'wf-new'
2066
        else:
2067
            formdata.status = 'wf-rejected'
2068
        formdata.store()
2069

  
2070
    app = login(get_app(pub))
2071
    resp = app.get('/backoffice/forms/1/')
2072
    resp = resp.click(href='anonymise')
2073
    resp = resp.form.submit('cancel')
2074
    assert len([x for x in formdef.data_class().select() if x.anonymised]) == 0
2075
    assert resp.location == 'http://example.net/backoffice/forms/1/'
2076

  
2077
    resp = app.get('/backoffice/forms/1/')
2078
    resp = resp.click(href='anonymise')
2079
    resp = resp.form.submit('submit')
2080
    assert resp.location == 'http://example.net/backoffice/forms/1/'
2081
    assert len([x for x in formdef.data_class().select() if x.anonymised]) == 0
2082

  
2083
    resp = app.get('/backoffice/forms/1/')
2084
    resp = resp.click(href='anonymise')
2085
    resp.form['before_request_date'].value = (datetime.datetime.today() +
2086
            datetime.timedelta(days=1)).strftime('%Y-%m-%d')
2087
    resp = resp.form.submit('submit')
2088
    assert resp.location == 'http://example.net/backoffice/forms/1/'
2089
    assert len([x for x in formdef.data_class().select() if x.anonymised]) == 7
2090

  
2091
    data_class.wipe()
2092
    for i in range(110):
2093
        formdata = data_class()
2094
        formdata.just_created()
2095
        if i < 3:
2096
            formdata.status = 'wf-rejected'
2097
        else:
2098
            formdata.status = 'wf-finished'
2099
        formdata.store()
2100

  
2101
    resp = app.get('/backoffice/forms/1/')
2102
    resp = resp.click(href='anonymise')
2103
    resp.form['before_request_date'].value = (datetime.datetime.today() +
2104
            datetime.timedelta(days=1)).strftime('%Y-%m-%d')
2105
    resp.form['endpoints$elementfinished'].checked = False
2106
    resp = resp.form.submit('submit')
2107
    assert '?job=' in resp.location
2108
    resp = resp.follow()
2109
    assert 'job-status' in resp.text
2110
    assert 'completed' in resp.text
2111
    assert len([x for x in formdef.data_class().select() if x.anonymised]) == 3
2112

  
2113

  
2114
def test_form_public_url(pub):
2115
    create_superuser(pub)
2116
    create_role()
2117

  
2118
    FormDef.wipe()
2119
    formdef = FormDef()
2120
    formdef.name = 'form title'
2121
    formdef.fields = []
2122
    formdef.store()
2123

  
2124
    app = login(get_app(pub))
2125
    resp = app.get('/backoffice/forms/1/')
2126
    resp = resp.click('Display public URL')
2127
    assert 'http://example.net/form-title/' in resp.text
2128

  
2129

  
2130
def test_form_archive(pub):
2131
    create_superuser(pub)
2132
    create_role()
2133

  
2134
    if pub.is_using_postgresql():
2135
        # this doesn't exist in SQL
2136
        pytest.skip('no archive in SQL mode')
2137
        return
2138

  
2139
    FormDef.wipe()
2140
    formdef = FormDef()
2141
    formdef.name = 'form title'
2142
    formdef.fields = []
2143
    formdef.store()
2144

  
2145
    data_class = formdef.data_class()
2146
    data_class.wipe()
2147
    for i in range(10):
2148
        formdata = data_class()
2149
        formdata.just_created()
2150
        if i < 3:
2151
            formdata.status = 'wf-new'
2152
        else:
2153
            formdata.status = 'wf-rejected'
2154
        formdata.store()
2155

  
2156
    app = login(get_app(pub))
2157
    resp = app.get('/backoffice/forms/1/')
2158
    resp = resp.click(href='archive')
2159
    resp = resp.form.submit('cancel')
2160
    assert data_class.count() == 10
2161
    assert resp.location == 'http://example.net/backoffice/forms/1/'
2162

  
2163
    resp = app.get('/backoffice/forms/1/')
2164
    resp = resp.click(href='archive')
2165
    resp = resp.form.submit('submit')
2166
    assert resp.content_type == 'application/x-wcs-archive'
2167
    tf = tarfile.open(fileobj=BytesIO(resp.body))
2168
    assert 'formdef' in [x.name for x in tf.getmembers()]
2169
    assert len(tf.getmembers()) == 8 # 7 formdata + 1 formdef
2170

  
2171
    # second archive, it shouldn't get anything (but the formdef)
2172
    resp = app.get('/backoffice/forms/1/')
2173
    resp = resp.click(href='archive')
2174
    resp = resp.form.submit('submit')
2175
    assert resp.content_type == 'application/x-wcs-archive'
2176
    tf = tarfile.open(fileobj=BytesIO(resp.body))
2177
    assert 'formdef' in [x.name for x in tf.getmembers()]
2178
    assert len(tf.getmembers()) == 1 # 0 formdata + 1 formdef
2179

  
2180

  
2181
def test_form_overwrite(pub):
2182
    user = create_superuser(pub)
2183
    role = create_role()
2184

  
2185
    FormDef.wipe()
2186
    formdef = FormDef()
2187
    formdef.name = 'form test'
2188
    formdef.table_name = 'xxx'
2189
    formdef.fields = [fields.StringField(id='1', label='1st field', type='string'),
2190
            fields.StringField(id='2', label='2nd field', type='string')]
2191
    formdef.store()
2192

  
2193
    formdata = formdef.data_class()()
2194
    formdata.data = {'1': 'foo', '2': 'bar'}
2195
    formdata.just_created()
2196
    formdata.store()
2197

  
2198
    formdef_id = formdef.id
2199
    formdef.fields[0].label = '1st modified field'
2200
    formdef_xml = ET.tostring(formdef.export_to_xml(include_id=True))
2201

  
2202
    app = login(get_app(pub))
2203
    resp = app.get('/backoffice/forms/%s/' % formdef_id)
2204
    resp = resp.click(href='overwrite')
2205
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef_xml)
2206
    resp = resp.forms[0].submit()
2207
    assert 'Overwrite - Summary of changes' in resp.text
2208
    resp = resp.forms[0].submit()
2209
    assert FormDef.get(formdef_id).fields[0].label == '1st modified field'
2210
    resp = resp.follow()
2211
    assert 'The form has been successfully overwritten.' in resp.text
2212

  
2213
    # check with added/removed field
2214
    new_formdef = FormDef()
2215
    new_formdef.name = 'form test overwrite'
2216
    new_formdef.fields = [
2217
            fields.StringField(id='2', label='2nd field', type='string'),
2218
            fields.StringField(id='3', label='3rd field', type='string')]
2219
    new_formdef_xml = ET.tostring(new_formdef.export_to_xml(include_id=True))
2220

  
2221
    # and no data within
2222
    formdef.data_class().wipe()
2223
    app = login(get_app(pub))
2224
    resp = app.get('/backoffice/forms/%s/' % formdef_id)
2225
    resp = resp.click(href='overwrite')
2226
    resp.forms[0]['file'] = Upload('formdef.wcs', new_formdef_xml)
2227
    resp = resp.forms[0].submit()
2228
    assert FormDef.get(formdef_id).fields[0].id == '2'
2229
    assert FormDef.get(formdef_id).fields[0].label == '2nd field'
2230
    assert FormDef.get(formdef_id).fields[1].id == '3'
2231
    assert FormDef.get(formdef_id).fields[1].label == '3rd field'
2232

  
2233
    # and data within
2234
    formdef.store()
2235
    formdata.data = {'1': 'foo', '2': 'bar'}
2236
    formdata.just_created()
2237
    formdata.store()
2238

  
2239
    resp = app.get('/backoffice/forms/%s/' % formdef_id)
2240
    resp = resp.click(href='overwrite')
2241
    resp.forms[0]['file'] = Upload('formdef.wcs', new_formdef_xml)
2242
    resp = resp.forms[0].submit()
2243
    assert 'The form removes or changes fields' in resp.text
2244
    assert resp.forms[0]['force'].checked is False
2245
    resp = resp.forms[0].submit()  # without checkbox (back to same form)
2246
    resp.forms[0]['force'].checked = True
2247
    resp = resp.forms[0].submit()
2248

  
2249
    assert FormDef.get(formdef_id).fields[0].id == '2'
2250
    assert FormDef.get(formdef_id).fields[0].label == '2nd field'
2251
    assert FormDef.get(formdef_id).fields[1].id == '3'
2252
    assert FormDef.get(formdef_id).fields[1].label == '3rd field'
2253

  
2254
    # check with a field of different type
2255
    formdef = FormDef.get(formdef_id)
2256
    formdata = formdef.data_class()()
2257
    formdata.data = {'1': 'foo', '2': 'bar', '3': 'baz'}
2258
    formdata.just_created()
2259
    formdata.store()
2260

  
2261
    new_formdef = FormDef()
2262
    new_formdef.name = 'form test overwrite'
2263
    new_formdef.fields = [
2264
            fields.StringField(id='2', label='2nd field', type='string'),
2265
            fields.DateField(id='3', label='3rd field, date', type='date')]  # (string -> date)
2266
    new_formdef_xml = ET.tostring(new_formdef.export_to_xml(include_id=True))
2267

  
2268
    app = login(get_app(pub))
2269
    resp = app.get('/backoffice/forms/%s/' % formdef_id)
2270
    resp = resp.click(href='overwrite', index=0)
2271
    resp.forms[0]['file'] = Upload('formdef.wcs', new_formdef_xml)
2272
    resp = resp.forms[0].submit()
2273
    assert 'The form removes or changes fields' in resp.text
2274
    resp.forms[0]['force'].checked = True
2275
    resp = resp.forms[0].submit()
2276
    assert FormDef.get(formdef_id).fields[1].id == '3'
2277
    assert FormDef.get(formdef_id).fields[1].label == '3rd field, date'
2278
    assert FormDef.get(formdef_id).fields[1].type == 'date'
2279

  
2280
    # check we kept stable references
2281
    assert FormDef.get(formdef_id).url_name == 'form-test'
2282
    assert FormDef.get(formdef_id).table_name == 'xxx'
2283

  
2284
    # check existing data
2285
    data = FormDef.get(formdef_id).data_class().get(formdata.id).data
2286
    assert data.get('2') == 'bar'
2287
    if pub.is_using_postgresql():
2288
        # in SQL, check data with different type has been removed
2289
        assert data.get('3') is None
2290

  
2291

  
2292
def test_form_export_import_export_overwrite(pub):
2293
    create_superuser(pub)
2294
    create_role()
2295

  
2296
    FormDef.wipe()
2297
    formdef = FormDef()
2298
    formdef.name = 'form title'
2299
    formdef.table_name = 'xxx'
2300
    formdef.fields = [  # unordered id
2301
        fields.StringField(id='1', label='field 1', type='string'),
2302
        fields.DateField(id='12', label='field 2', type='date'),
2303
        fields.ItemField(id='4', label='field 3', type='item'),
2304
    ]
2305
    formdef.store()
2306

  
2307
    # add data
2308
    formdata = formdef.data_class()()
2309
    formdata.data = {'1': 'foo'}
2310
    formdata.just_created()
2311
    formdata.store()
2312

  
2313
    formdef_xml = ET.tostring(formdef.export_to_xml(include_id=True))
2314

  
2315
    assert FormDef.count() == 1
2316
    assert formdef.url_name == 'form-title'
2317

  
2318
    app = login(get_app(pub))
2319
    resp = app.get('/backoffice/forms/')
2320
    resp = resp.click(href='import')
2321
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef_xml)
2322
    resp = resp.forms[0].submit()
2323
    assert FormDef.count() == 2
2324

  
2325
    formdef2 = FormDef.get(2)
2326
    assert formdef2.url_name == 'form-title-1'
2327
    # fields are imported with original ids
2328
    for i, field in enumerate(formdef.fields):
2329
        field2 = formdef2.fields[i]
2330
        assert (field.id, field.label, field.type) == (field2.id, field2.label, field2.type)
2331

  
2332
    # modify imported formdef, then overwrite original formdef with it
2333
    formdef2.fields.insert(2, fields.StringField(id='2', label='field 4', type='string'))
2334
    formdef2.fields.insert(3, fields.DateField(id='3', label='field 5', type='date'))
2335
    formdef2.fields.append(fields.ItemField(id='5', label='field 6', type='item'))
2336
    formdef2.store()
2337
    formdef2_xml = ET.tostring(formdef2.export_to_xml(include_id=True))
2338
    resp = app.get('/backoffice/forms/%s/' % formdef.id)
2339
    resp = resp.click(href='overwrite')
2340
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef2_xml)
2341
    resp = resp.forms[0].submit()
2342
    assert 'Overwrite - Summary of changes' in resp.text
2343
    resp = resp.forms[0].submit()
2344
    formdef_overwrited = FormDef.get(formdef.id)
2345
    for i, field in enumerate(formdef2.fields):
2346
        field_ow = formdef_overwrited.fields[i]
2347
        assert (field.id, field.label, field.type) == (field_ow.id, field_ow.label, field_ow.type)
2348

  
2349

  
2350
def test_form_comment_with_error_in_wscall(http_requests, pub):
2351
    create_superuser(pub)
2352
    NamedWsCall.wipe()
2353

  
2354
    wscall = NamedWsCall(name='xxx')
2355
    wscall.description = 'description'
2356
    wscall.request = {
2357
            'url': 'http://remote.example.net/404',
2358
            'request_signature_key': 'xxx',
2359
            'qs_data': {'a': 'b'},
2360
            'method': 'POST',
2361
            'post_data': {'c': 'd'},
2362
    }
2363
    wscall.store()
2364

  
2365
    FormDef.wipe()
2366
    formdef = FormDef()
2367
    formdef.name = 'form title'
2368
    formdef.fields = [fields.CommentField(id='1',
2369
        label='x [webservice.xxx.foobar] x', type='comment')]
2370
    formdef.store()
2371

  
2372
    app = login(get_app(pub))
2373
    resp = app.get('/backoffice/forms/%s/' % formdef.id)
2374
    assert 'x [webservice.xxx.foobar] x' in resp.text
2375

  
2376

  
2377 188
def test_workflows(pub):
2378 189
    create_superuser(pub)
2379 190
    app = login(get_app(pub))
tests/test_forms_admin_pages.py
1
# -*- coding: utf-8 -*-
2

  
3
import datetime
4
import os
5
import re
6
import tarfile
7
import time
8
import xml.etree.ElementTree as ET
9

  
10
try:
11
    import lasso
12
except ImportError:
13
    lasso = None
14

  
15
import pytest
16
from webtest import Upload
17

  
18
from django.utils.six import StringIO, BytesIO
19

  
20
from wcs.qommon.http_request import HTTPRequest
21
from wcs.categories import Category
22
from wcs.data_sources import NamedDataSource
23
from wcs.wscalls import NamedWsCall
24
from wcs.roles import Role
25
from wcs.workflows import Workflow
26
from wcs.formdef import FormDef
27
from wcs.carddef import CardDef
28
from wcs import fields
29

  
30
from utilities import get_app, login, create_temporary_pub, clean_temporary_pub
31
from test_admin_pages import create_superuser, create_role
32

  
33

  
34
def pytest_generate_tests(metafunc):
35
    if 'pub' in metafunc.fixturenames:
36
        metafunc.parametrize('pub', ['pickle', 'sql', 'pickle-templates'], indirect=True)
37

  
38

  
39
@pytest.fixture
40
def pub(request):
41
    pub = create_temporary_pub(
42
            sql_mode=bool('sql' in request.param),
43
            templates_mode=bool('templates' in request.param)
44
            )
45

  
46
    req = HTTPRequest(None, {'SCRIPT_NAME': '/', 'SERVER_NAME': 'example.net'})
47
    pub.set_app_dir(req)
48
    pub.cfg['identification'] = {'methods': ['password']}
49
    pub.cfg['language'] = {'language': 'en'}
50
    pub.write_cfg()
51

  
52
    return pub
53

  
54

  
55
def teardown_module(module):
56
    clean_temporary_pub()
57

  
58

  
59
def test_forms(pub):
60
    user = create_superuser(pub)
61
    app = login(get_app(pub))
62
    resp = app.get('/backoffice/forms/')
63
    assert 'You first have to define roles.' in resp.text
64
    assert not 'New Form' in resp.text
65

  
66

  
67
def test_forms_new(pub):
68
    user = create_superuser(pub)
69
    app = login(get_app(pub))
70
    create_role()
71

  
72
    # create a new form
73
    resp = app.get('/backoffice/forms/')
74
    assert 'New Form' in resp.text
75
    resp = resp.click('New Form')
76
    resp.forms[0]['name'] = 'form title'
77
    resp = resp.forms[0].submit()
78
    assert resp.location == 'http://example.net/backoffice/forms/1/'
79
    resp = resp.follow()
80
    assert '<h2>form title' in resp.text
81

  
82
    # makes sure the data has been correctly saved
83
    formdef = FormDef.get(1)
84
    assert formdef.name == 'form title'
85
    assert formdef.url_name == 'form-title'
86
    assert formdef.fields == []
87
    assert formdef.disabled == True
88
    assert formdef.last_modification_user_id == str(user.id)
89

  
90

  
91
def test_forms_new_popup(pub):
92
    FormDef.wipe()
93
    user = create_superuser(pub)
94
    app = login(get_app(pub))
95
    create_role()
96

  
97
    # create a new form
98
    resp = app.get('/backoffice/forms/')
99
    assert 'New Form' in resp.text
100
    resp = resp.click('New Form', extra_environ={'HTTP_X_POPUP': 'true'})
101
    assert 'popup-content' in resp.text
102
    resp.forms[0]['name'] = 'form title'
103
    resp = resp.forms[0].submit()
104
    assert resp.location == 'http://example.net/backoffice/forms/1/'
105
    resp = resp.follow()
106
    assert '<h2>form title' in resp.text
107

  
108
    # makes sure the data has been correctly saved
109
    formdef = FormDef.get(1)
110
    assert formdef.name == 'form title'
111
    assert formdef.url_name == 'form-title'
112
    assert formdef.fields == []
113
    assert formdef.disabled == True
114
    assert formdef.last_modification_user_id == str(user.id)
115

  
116

  
117
def assert_option_display(resp, label, value):
118
    option_line = re.findall('%s.*%s' % (label, value), resp.text, re.DOTALL)
119
    assert option_line
120
    assert not '</li>' in option_line
121

  
122

  
123
def test_forms_edit(pub):
124
    create_superuser(pub)
125
    create_role()
126

  
127
    FormDef.wipe()
128
    formdef = FormDef()
129
    formdef.name = 'form title'
130
    formdef.fields = []
131
    formdef.store()
132

  
133
    app = login(get_app(pub))
134
    resp = app.get('/backoffice/forms/1/')
135

  
136
    # try changing an option
137

  
138
    # confirmation page
139
    assert_option_display(resp, 'Confirmation Page', 'Enabled')
140
    resp = resp.click('Confirmation Page')
141
    assert resp.forms[0]['confirmation'].checked
142
    resp.forms[0]['confirmation'].checked = False
143
    resp = resp.forms[0].submit()
144
    assert resp.location == 'http://example.net/backoffice/forms/1/'
145
    resp = resp.follow()
146
    assert_option_display(resp, 'Confirmation Page', 'Disabled')
147
    assert FormDef.get(1).confirmation == False
148

  
149
    # try cancel button
150
    resp = resp.click('Confirmation Page')
151
    assert resp.forms[0]['confirmation'].checked is False
152
    resp.forms[0]['confirmation'].checked = True
153
    resp = resp.forms[0].submit('cancel')
154
    assert resp.location == 'http://example.net/backoffice/forms/1/'
155
    resp = resp.follow()
156
    assert_option_display(resp, 'Confirmation Page', 'Disabled')
157
    assert FormDef.get(1).confirmation == False
158

  
159
    # Limit to one form
160
    assert_option_display(resp, 'Limit to one form', 'Disabled')
161
    resp = resp.click('Limit to one form')
162
    assert resp.forms[0]['only_allow_one'].checked is False
163
    resp.forms[0]['only_allow_one'].checked = True
164
    resp = resp.forms[0].submit()
165
    assert resp.location == 'http://example.net/backoffice/forms/1/'
166
    resp = resp.follow()
167
    assert_option_display(resp, 'Limit to one form', 'Enabled')
168
    assert FormDef.get(1).only_allow_one is True
169

  
170
    # Misc management
171
    assert_option_display(resp, 'Management', 'Default')
172
    resp = resp.click('Management', href='options/management')
173
    assert resp.forms[0]['include_download_all_button'].checked is False
174
    resp.forms[0]['include_download_all_button'].checked = True
175
    resp = resp.forms[0].submit()
176
    assert resp.location == 'http://example.net/backoffice/forms/1/'
177
    resp = resp.follow()
178
    assert_option_display(resp, 'Management', 'Custom')
179
    assert FormDef.get(1).include_download_all_button is True
180

  
181
    # Tracking code
182
    assert_option_display(resp, 'Tracking Code', 'Disabled')
183
    resp = resp.click('Tracking Code')
184
    assert resp.forms[0]['enable_tracking_codes'].checked is False
185
    resp.forms[0]['enable_tracking_codes'].checked = True
186
    resp = resp.forms[0].submit()
187
    assert resp.location == 'http://example.net/backoffice/forms/1/'
188
    resp = resp.follow()
189
    assert_option_display(resp, 'Tracking Code', 'Enabled')
190
    assert FormDef.get(1).enable_tracking_codes is True
191

  
192
    # CAPTCHA
193
    assert_option_display(resp, 'CAPTCHA for anonymous users', 'Disabled')
194
    resp = resp.click('CAPTCHA for anonymous users')
195
    assert resp.forms[0]['has_captcha'].checked is False
196
    resp.forms[0]['has_captcha'].checked = True
197
    resp = resp.forms[0].submit()
198
    assert resp.location == 'http://example.net/backoffice/forms/1/'
199
    resp = resp.follow()
200
    assert_option_display(resp, 'CAPTCHA for anonymous users', 'Enabled')
201
    assert FormDef.get(1).has_captcha is True
202

  
203
    # Appearance
204
    assert_option_display(resp, 'Appearance', 'Standard')
205
    resp = resp.click('Appearance')
206
    assert resp.forms[0]['appearance_keywords'].value == ''
207
    resp.forms[0]['appearance_keywords'] = 'foobar'
208
    resp = resp.forms[0].submit()
209
    assert resp.location == 'http://example.net/backoffice/forms/1/'
210
    resp = resp.follow()
211
    assert_option_display(resp, 'Appearance', 'foobar')
212
    assert FormDef.get(1).appearance_keywords == 'foobar'
213

  
214
    # Publication
215
    assert_option_display(resp, 'Online Status', 'Active')
216
    resp = resp.click('Online Status')
217
    assert resp.forms[0]['disabled'].checked is False
218
    resp.forms[0]['disabled'].checked = True
219
    resp = resp.forms[0].submit()
220
    assert resp.location == 'http://example.net/backoffice/forms/1/'
221
    resp = resp.follow()
222
    assert_option_display(resp, 'Online Status', 'Disabled')
223
    assert FormDef.get(1).disabled is True
224

  
225
    resp = resp.click('Online Status')
226
    assert resp.forms[0]['disabled'].checked is True
227
    resp.forms[0]['disabled_redirection'] = 'http://www.example.net'
228
    resp = resp.forms[0].submit()
229
    assert resp.location == 'http://example.net/backoffice/forms/1/'
230
    resp = resp.follow()
231
    assert_option_display(resp, 'Online Status', 'Redirected')
232
    assert FormDef.get(1).disabled is True
233
    assert FormDef.get(1).disabled_redirection == 'http://www.example.net'
234

  
235
    resp = resp.click('Online Status')
236
    resp.forms[0]['disabled'].checked = False
237
    resp.forms[0]['expiration_date$date'] = '2000-01-01'  # this is past(tm)
238
    resp = resp.forms[0].submit()
239
    assert resp.location == 'http://example.net/backoffice/forms/1/'
240
    resp = resp.follow()
241
    assert_option_display(resp, 'Online Status', 'Inactive by date')
242

  
243
    # enable geolocation
244
    resp = resp.click('Geolocation')
245
    resp.forms[0]['geoloc_label'] = 'Foobar'
246
    resp = resp.forms[0].submit()
247
    assert resp.location == 'http://example.net/backoffice/forms/1/'
248
    resp = resp.follow()
249
    assert_option_display(resp, 'Geolocation', 'Enabled')
250
    assert FormDef.get(formdef.id).geolocations == {'base': 'Foobar'}
251

  
252
    # and disable it
253
    resp = resp.click('Geolocation')
254
    resp.forms[0]['geoloc_label'] = ''
255
    resp = resp.forms[0].submit()
256
    assert resp.location == 'http://example.net/backoffice/forms/1/'
257
    resp = resp.follow()
258
    assert_option_display(resp, 'Geolocation', 'Disabled')
259
    assert FormDef.get(formdef.id).geolocations is None
260

  
261

  
262
def test_form_title_change(pub):
263
    create_superuser(pub)
264
    create_role()
265

  
266
    FormDef.wipe()
267
    formdef = FormDef()
268
    formdef.name = 'form title'
269
    formdef.fields = []
270
    formdef.store()
271

  
272
    app = login(get_app(pub))
273

  
274
    resp = app.get('/backoffice/forms/1/')
275
    resp = resp.click('change title')
276
    assert resp.form['name'].value == 'form title'
277
    assert 'data-slug-sync' in resp.text
278
    assert not 'change-nevertheless' in resp.text
279
    resp.form['name'] = 'new title'
280
    resp = resp.form.submit()
281
    assert resp.location == 'http://example.net/backoffice/forms/1/'
282
    resp = resp.follow()
283
    formdef = FormDef.get(formdef.id)
284
    assert formdef.name == 'new title'
285
    assert formdef.url_name == 'form-title'
286
    assert formdef.internal_identifier == 'new-title'
287

  
288
    resp = app.get('/backoffice/forms/1/')
289
    resp = resp.click('change title')
290
    assert not 'data-slug-sync' in resp.text
291
    assert not 'change-nevertheless' in resp.text
292

  
293
    formdef.data_class()().store()
294
    resp = app.get('/backoffice/forms/1/')
295
    resp = resp.click('change title')
296
    assert 'change-nevertheless' in resp.text
297

  
298
    formdef2 = FormDef()
299
    formdef2.name = 'other title'
300
    formdef2.fields = []
301
    formdef2.store()
302

  
303
    resp = app.get('/backoffice/forms/%s/' % formdef2.id)
304
    resp = resp.click('change title')
305
    assert resp.form['name'].value == 'other title'
306
    resp.form['url_name'] = formdef.url_name
307
    resp = resp.form.submit()
308
    assert 'This identifier is already used.' in resp.text
309

  
310
    resp.form['url_name'] = 'foobar'
311
    resp = resp.form.submit().follow()
312
    assert FormDef.get(formdef2.id).url_name == 'foobar'
313

  
314

  
315
def test_forms_edit_publication_date(pub):
316
    create_superuser(pub)
317
    create_role()
318

  
319
    FormDef.wipe()
320
    formdef = FormDef()
321
    formdef.name = 'form title'
322
    formdef.fields = []
323
    formdef.store()
324

  
325
    app = login(get_app(pub))
326
    resp = app.get('/backoffice/forms/1/options/online_status')
327
    resp.form['publication_date$date'] = '2020-01-01'
328
    resp = resp.form.submit()
329
    assert FormDef.get(formdef.id).publication_date == '2020-01-01 00:00'
330

  
331
    resp = app.get('/backoffice/forms/1/options/online_status')
332
    assert resp.form['publication_date$date'].value == '2020-01-01'
333
    resp.form['publication_date$time'] = '12:00'
334
    resp = resp.form.submit()
335
    assert FormDef.get(formdef.id).publication_date == '2020-01-01 12:00'
336

  
337
    resp = app.get('/backoffice/forms/1/options/online_status')
338
    assert resp.form['publication_date$date'].value == '2020-01-01'
339
    assert resp.form['publication_date$time'].value == '12:00'
340

  
341
    formdef.publication_date = None
342
    formdef.store()
343

  
344
    resp = app.get('/backoffice/forms/1/options/online_status')
345
    resp.form['publication_date$time'] = '12:00'
346
    resp = resp.form.submit()
347
    assert 'invalid value' in resp
348

  
349

  
350
def test_form_category(pub):
351
    create_superuser(pub)
352
    create_role()
353

  
354
    FormDef.wipe()
355
    formdef = FormDef()
356
    formdef.name = 'form title'
357
    formdef.fields = []
358
    formdef.store()
359

  
360
    app = login(get_app(pub))
361
    resp = app.get('/backoffice/forms/1/')
362
    assert_option_display(resp, 'Category', 'None')
363

  
364
    Category.wipe()
365
    cat = Category(name='Foo')
366
    cat.store()
367
    cat = Category(name='Bar')
368
    cat.store()
369
    resp = app.get('/backoffice/forms/1/')
370
    assert 'Category' in resp.text
371
    assert_option_display(resp, 'Category', 'None')
372

  
373

  
374
def test_form_category_select(pub):
375
    create_superuser(pub)
376
    create_role()
377

  
378
    FormDef.wipe()
379
    formdef = FormDef()
380
    formdef.name = 'form title'
381
    formdef.fields = []
382
    formdef.store()
383

  
384
    Category.wipe()
385
    cat = Category(name='Foo')
386
    cat.store()
387
    cat = Category(name='Bar')
388
    cat.store()
389

  
390
    app = login(get_app(pub))
391
    resp = app.get('/backoffice/forms/1/')
392
    resp = resp.click(href='category')
393
    resp = resp.forms[0].submit('cancel')
394
    assert FormDef.get(formdef.id).category_id is None
395

  
396
    resp = app.get('/backoffice/forms/1/')
397
    resp = resp.click(href='category')
398
    resp.forms[0]['category_id'] = cat.id
399
    resp = resp.forms[0].submit('submit')
400
    assert FormDef.get(formdef.id).category_id == cat.id
401

  
402

  
403
def test_form_workflow(pub):
404
    create_superuser(pub)
405
    create_role()
406

  
407
    FormDef.wipe()
408
    formdef = FormDef()
409
    formdef.name = 'form title'
410
    formdef.fields = []
411
    formdef.store()
412

  
413
    app = login(get_app(pub))
414
    resp = app.get('/backoffice/forms/1/')
415
    assert_option_display(resp, 'Workflow', 'Default')
416

  
417
    Workflow.wipe()
418
    workflow = Workflow(name='Workflow One')
419
    workflow.store()
420
    workflow = Workflow(name='Workflow Two')
421
    workflow.store()
422

  
423
    resp = app.get('/backoffice/forms/1/')
424
    assert_option_display(resp, 'Workflow', 'Default')
425

  
426

  
427
def test_form_workflow_change(pub):
428
    create_superuser(pub)
429
    create_role()
430

  
431
    FormDef.wipe()
432
    formdef = FormDef()
433
    formdef.name = 'form title'
434
    formdef.fields = []
435
    formdef.store()
436

  
437
    Workflow.wipe()
438
    workflow = Workflow(name='Workflow One')
439
    workflow.store()
440
    workflow = Workflow(name='Workflow Two')
441
    workflow.possible_status = Workflow.get_default_workflow().possible_status[:]
442
    workflow.store()
443

  
444
    app = login(get_app(pub))
445
    resp = app.get('/backoffice/forms/1/')
446
    resp = resp.click(href='workflow', index=1)
447
    resp = resp.forms[0].submit('cancel')
448
    assert FormDef.get(formdef.id).workflow_id is None
449

  
450
    resp = app.get('/backoffice/forms/1/')
451
    resp = resp.click(href='workflow', index=1)
452
    assert 'Workflow One' not in resp.text # this workflow doesn't have any status
453
    resp.forms[0]['workflow_id'] = workflow.id
454
    resp = resp.forms[0].submit('submit')
455
    assert FormDef.get(formdef.id).workflow_id == workflow.id
456

  
457

  
458
def test_form_workflow_link(pub):
459
    create_superuser(pub)
460
    create_role()
461

  
462
    FormDef.wipe()
463
    formdef = FormDef()
464
    formdef.name = 'form title'
465
    formdef.fields = []
466
    formdef.store()
467

  
468
    Workflow.wipe()
469
    workflow = Workflow(name='Workflow One')
470
    workflow.store()
471

  
472
    app = login(get_app(pub))
473

  
474
    resp = app.get('/backoffice/forms/%s/' % formdef.id)
475
    assert '../workflows/_default/' in resp.text
476

  
477
    formdef.workflow = workflow
478
    formdef.store()
479

  
480
    resp = app.get('/backoffice/forms/%s/' % formdef.id)
481
    assert '../workflows/%s/' % workflow.id in resp.text
482

  
483
    # check workflow link is not displayed if user has no access right
484
    pub.cfg['admin-permissions'] = {'workflows': ['x']}  #  block access
485
    pub.write_cfg()
486
    resp = app.get('/backoffice/forms/%s/' % formdef.id)
487
    assert '../workflows/%s/' % workflow.id not in resp.text
488

  
489

  
490
def test_form_workflow_remapping(pub):
491
    create_superuser(pub)
492
    create_role()
493

  
494
    FormDef.wipe()
495
    formdef = FormDef()
496
    formdef.name = 'form title'
497
    formdef.fields = []
498
    formdef.store()
499

  
500
    data_class = formdef.data_class()
501
    data_class.wipe()
502
    formdata1 = data_class()
503
    formdata1.status = 'wf-new'
504
    formdata1.store()
505

  
506
    formdata2 = data_class()
507
    formdata2.status = 'draft'
508
    formdata2.store()
509

  
510
    Workflow.wipe()
511
    workflow = Workflow(name='Workflow One')
512
    workflow.store()
513
    workflow = Workflow(name='Workflow Two')
514
    # create it with a single status
515
    workflow.possible_status = [Workflow.get_default_workflow().possible_status[-1]]
516
    workflow.store()
517

  
518
    app = login(get_app(pub))
519
    resp = app.get('/backoffice/forms/1/')
520
    resp = resp.click(href='workflow', index=1)
521
    resp.forms[0]['workflow_id'] = workflow.id
522
    resp = resp.forms[0].submit('submit')
523
    assert resp.location == 'http://example.net/backoffice/forms/1/workflow-status-remapping?new=2'
524
    resp = resp.follow()
525
    for status in Workflow.get_default_workflow().possible_status:
526
        assert resp.forms[0]['mapping-%s' % status.id]
527
        # there's only one possible new status
528
        assert len(resp.forms[0]['mapping-%s' % status.id].options) == 1
529
    assert data_class.get(formdata1.id).status == 'wf-new'
530
    assert data_class.get(formdata2.id).status == 'draft'
531
    resp = resp.forms[0].submit()
532
    assert data_class.get(formdata1.id).status == 'wf-finished'
533
    assert data_class.get(formdata2.id).status == 'draft'
534

  
535
    # change to another workflow, with no mapping change
536
    workflow2 = workflow
537
    workflow = Workflow(name='Workflow Three')
538
    workflow.possible_status = Workflow.get_default_workflow().possible_status[-2:][:]
539
    workflow.store()
540

  
541
    resp = app.get('/backoffice/forms/1/')
542
    resp = resp.click(href='workflow', index=1)
543
    resp.forms[0]['workflow_id'] = workflow.id
544
    resp = resp.forms[0].submit('submit')
545
    assert resp.location == 'http://example.net/backoffice/forms/1/workflow-status-remapping?new=3'
546
    resp = resp.follow()
547
    for status in workflow2.possible_status:
548
        assert resp.forms[0]['mapping-%s' % status.id]
549
        # there are two status
550
        assert len(resp.forms[0]['mapping-%s' % status.id].options) == 2
551
    resp = resp.forms[0].submit()
552
    assert data_class.get(formdata1.id).status == 'wf-finished'
553
    assert data_class.get(formdata2.id).status == 'draft'
554

  
555

  
556
def test_form_submitter_roles(pub):
557
    create_superuser(pub)
558
    role = create_role()
559

  
560
    FormDef.wipe()
561
    formdef = FormDef()
562
    formdef.name = 'form title'
563
    formdef.fields = []
564
    formdef.store()
565

  
566
    app = login(get_app(pub))
567
    resp = app.get('/backoffice/forms/1/')
568
    resp = resp.click(href=re.compile('^roles$'))
569
    resp.form['roles$element0'] = 'logged-users'
570
    assert not 'required_authentication_contexts' in resp.text
571
    resp = resp.form.submit()
572
    assert FormDef.get(formdef.id).roles == ['logged-users']
573

  
574
    # add auth contexts support
575
    if not pub.site_options.has_section('options'):
576
        pub.site_options.add_section('options')
577
    pub.site_options.set('options', 'auth-contexts', 'fedict')
578
    with open(os.path.join(pub.app_dir, 'site-options.cfg'), 'w') as fd:
579
        pub.site_options.write(fd)
580

  
581
    app = login(get_app(pub))
582
    resp = app.get('/backoffice/forms/1/')
583
    resp = resp.click(href=re.compile('^roles$'))
584
    assert 'required_authentication_contexts' in resp.text
585
    resp.form['required_authentication_contexts$element0'].checked = True
586
    resp = resp.form.submit()
587
    resp = resp.follow()
588
    assert FormDef.get(formdef.id).required_authentication_contexts == ['fedict']
589

  
590
    # check internal roles are not advertised
591
    role2 = Role(name='internal')
592
    role2.internal = True
593
    role2.store()
594

  
595
    resp = app.get('/backoffice/forms/1/')
596
    resp = resp.click(href=re.compile('^roles$'))
597
    assert len(resp.form['roles$element0'].options) == 3  # None, Logged users, foobar
598
    with pytest.raises(ValueError):
599
        resp.form['roles$element0'] = str(role2.id)
600

  
601

  
602
def test_form_workflow_role(pub):
603
    create_superuser(pub)
604
    role = create_role()
605

  
606
    FormDef.wipe()
607
    formdef = FormDef()
608
    formdef.name = 'form title'
609
    formdef.fields = []
610
    formdef.store()
611

  
612
    app = login(get_app(pub))
613
    resp = app.get('/backoffice/forms/1/')
614
    resp = resp.click(href='role/_receiver')
615
    resp = resp.forms[0].submit('cancel')
616

  
617
    resp = app.get('/backoffice/forms/1/')
618
    resp = resp.click(href='role/_receiver')
619
    resp.forms[0]['role_id'] = role.id
620
    resp = resp.forms[0].submit('submit')
621
    assert FormDef.get(1).workflow_roles == {'_receiver': '1'}
622

  
623
    # check it doesn't fail if a second role with the same name exists
624
    role = Role(name='foobar')
625
    role.store()
626
    resp = app.get('/backoffice/forms/1/')
627
    resp = resp.click(href='role/_receiver')
628

  
629

  
630
def test_form_workflow_options(pub):
631
    create_superuser(pub)
632
    create_role()
633

  
634
    Workflow.wipe()
635
    workflow = Workflow(name='Workflow One')
636
    workflow.store()
637

  
638
    FormDef.wipe()
639
    formdef = FormDef()
640
    formdef.name = 'form title'
641
    formdef.fields = []
642
    formdef.workflow_id = workflow.id
643
    formdef.workflow_options = {'2*1*body': 'xxx'}
644
    formdef.store()
645

  
646
    app = login(get_app(pub))
647
    resp = app.get('/backoffice/forms/1/')
648
    assert '"workflow-options"' in resp.text
649

  
650

  
651
def test_form_workflow_variables(pub):
652
    create_superuser(pub)
653
    create_role()
654

  
655
    Workflow.wipe()
656
    workflow = Workflow(name='Workflow One')
657
    from wcs.workflows import WorkflowVariablesFieldsFormDef
658
    workflow.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=workflow)
659
    workflow.variables_formdef.fields.append(
660
            fields.StringField(id='1', varname='test', label='Test', type='string'))
661
    workflow.store()
662

  
663
    FormDef.wipe()
664
    formdef = FormDef()
665
    formdef.name = 'form title'
666
    formdef.fields = []
667
    formdef.workflow_id = workflow.id
668
    formdef.store()
669

  
670
    app = login(get_app(pub))
671
    resp = app.get('/backoffice/forms/1/')
672
    assert '"workflow-variables"' in resp.text
673

  
674
    # visit the variables page
675
    resp = resp.click(href='workflow-variables')
676

  
677
    # and set a value
678
    resp.forms[0]['f1'] = 'foobar'
679
    resp = resp.forms[0].submit()
680
    assert resp.location == 'http://example.net/backoffice/forms/1/'
681

  
682
    # check the value has been correctly saved
683
    assert FormDef.get(formdef.id).workflow_options == {'test': 'foobar'}
684

  
685
    # go back to the variables page, also check value
686
    resp = resp.follow()
687
    resp = resp.click(href='workflow-variables')
688
    assert resp.forms[0]['f1'].value == 'foobar'
689
    resp.forms[0]['f1'] = 'barbaz'
690
    resp = resp.forms[0].submit('cancel')
691
    assert resp.location == 'http://example.net/backoffice/forms/1/'
692

  
693
    # check with a date field
694
    workflow.variables_formdef.fields.append(
695
            fields.DateField(id='2', varname='test2', label='Test2', type='date'))
696
    workflow.store()
697

  
698
    resp = app.get('/backoffice/forms/1/')
699
    resp = resp.click(href='workflow-variables')
700
    resp.form['f2'] = '2016-06-17'
701
    resp = resp.form.submit()
702
    assert time.strftime('%d %m %y', FormDef.get(formdef.id).workflow_options.get('test2')) == '17 06 16'
703

  
704

  
705
def test_form_workflow_table_variables(pub):
706
    create_superuser(pub)
707
    create_role()
708

  
709
    Workflow.wipe()
710
    workflow = Workflow(name='Workflow One')
711
    from wcs.workflows import WorkflowVariablesFieldsFormDef
712
    workflow.variables_formdef = WorkflowVariablesFieldsFormDef(workflow=workflow)
713
    workflow.variables_formdef.fields.append(
714
            fields.TableRowsField(id='1', varname='test', label='Test2',
715
                type='tablerows', columns=['a']))
716
    workflow.variables_formdef.fields.append(
717
            fields.StringField(id='2', varname='test2', label='Test', type='string'))
718
    workflow.store()
719

  
720
    FormDef.wipe()
721
    formdef = FormDef()
722
    formdef.name = 'form title'
723
    formdef.fields = []
724
    formdef.workflow_id = workflow.id
725
    formdef.store()
726

  
727
    app = login(get_app(pub))
728
    resp = app.get('/backoffice/forms/1/')
729
    assert '"workflow-variables"' in resp.text
730

  
731
    # visit the variables page
732
    resp = resp.click(href='workflow-variables')
733

  
734
    # and set a value
735
    resp.form['f1$element0$col0'] = 'foobar'
736
    resp.form['f2'] = 'foobar'
737
    resp = resp.form.submit('submit')
738
    assert resp.location == 'http://example.net/backoffice/forms/1/'
739

  
740
    # check the value has been correctly saved
741
    assert FormDef.get(formdef.id).workflow_options == {
742
            'test': [['foobar']],
743
            'test2': 'foobar'}
744

  
745
    # go back to the variables page, also check value
746
    resp = resp.follow()
747
    resp = resp.click(href='workflow-variables')
748
    assert resp.form['f1$element0$col0'].value == 'foobar'
749
    assert resp.form['f2'].value == 'foobar'
750

  
751

  
752
def test_form_roles(pub):
753
    create_superuser(pub)
754
    role = create_role()
755

  
756
    FormDef.wipe()
757
    formdef = FormDef()
758
    formdef.name = 'form title'
759
    formdef.fields = []
760
    formdef.store()
761

  
762
    app = login(get_app(pub))
763
    resp = app.get('/backoffice/forms/1/')
764

  
765
    resp = resp.click('User Roles')
766
    resp = resp.forms[0].submit('cancel')
767

  
768
    resp = app.get('/backoffice/forms/1/')
769
    resp = resp.click('User Roles')
770
    resp.forms[0]['roles$element0'].value = role.id
771
    resp = resp.forms[0].submit('submit')
772
    assert FormDef.get(1).roles == [role.id]
773

  
774

  
775
def test_form_always_advertise(pub):
776
    create_superuser(pub)
777
    role = create_role()
778

  
779
    FormDef.wipe()
780
    formdef = FormDef()
781
    formdef.name = 'form title'
782
    formdef.fields = []
783
    formdef.store()
784

  
785
    app = login(get_app(pub))
786
    resp = app.get('/backoffice/forms/1/')
787

  
788
    # Display to unlogged users
789
    formdef.roles = [role.id]
790
    formdef.store()
791
    resp = app.get('/backoffice/forms/1/')
792
    assert_option_display(resp, 'Display to unlogged users', 'Disabled')
793
    resp = resp.click('Display to unlogged users')
794
    assert resp.forms[0]['always_advertise'].checked is False
795
    resp.forms[0]['always_advertise'].checked = True
796
    resp = resp.forms[0].submit()
797
    assert resp.location == 'http://example.net/backoffice/forms/1/'
798
    resp = resp.follow()
799
    assert_option_display(resp, 'Display to unlogged users', 'Enabled')
800
    assert FormDef.get(1).always_advertise is True
801

  
802

  
803
def test_form_digest_template(pub):
804
    create_superuser(pub)
805
    role = create_role()
806

  
807
    FormDef.wipe()
808
    formdef = FormDef()
809
    formdef.name = 'form title'
810
    formdef.fields = [fields.StringField(id='1', varname='test', label='Test', type='string')]
811
    formdef.store()
812

  
813
    formdata = formdef.data_class()()
814
    formdata.just_created()
815
    formdata.data = {'1': 'hello'}
816
    formdata.store()
817

  
818
    app = login(get_app(pub))
819
    resp = app.get('/backoffice/forms/1/')
820

  
821
    # Display to unlogged users
822
    assert_option_display(resp, 'Digest Template', 'None')
823
    resp = resp.click('Digest Template')
824
    resp.form['digest_template'] = 'X{{form_var_test}}Y'
825
    resp = resp.form.submit()
826
    assert resp.location == 'http://example.net/backoffice/forms/1/'
827
    resp = resp.follow()
828
    assert_option_display(resp, 'Digest Template', 'Custom')
829
    formdef = FormDef.get(formdef.id)
830
    assert formdef.digest_template == 'X{{form_var_test}}Y'
831

  
832
    assert 'Existing forms will be updated in the background.' in resp.text
833
    # afterjobs are actually run synchronously during tests; we don't have
834
    # to wait to check the digest has been updated:
835
    assert formdef.data_class().get(formdata.id).digest == 'XhelloY'
836

  
837

  
838
def test_form_delete(pub):
839
    create_superuser(pub)
840
    create_role()
841

  
842
    FormDef.wipe()
843
    formdef = FormDef()
844
    formdef.name = 'form title'
845
    formdef.fields = []
846
    formdef.store()
847

  
848
    app = login(get_app(pub))
849
    resp = app.get('/backoffice/forms/1/')
850

  
851
    resp = resp.click(href='delete')
852
    resp = resp.forms[0].submit()
853
    assert resp.location == 'http://example.net/backoffice/forms/'
854
    resp = resp.follow()
855
    assert FormDef.count() == 0
856

  
857

  
858
def test_form_duplicate(pub):
859
    create_superuser(pub)
860
    create_role()
861

  
862
    FormDef.wipe()
863
    formdef = FormDef()
864
    formdef.name = 'form title'
865
    formdef.fields = []
866
    formdef.store()
867

  
868
    app = login(get_app(pub))
869
    resp = app.get('/backoffice/forms/1/')
870

  
871
    resp = resp.click(href='duplicate')
872
    assert resp.location == 'http://example.net/backoffice/forms/2/'
873
    resp = resp.follow()
874
    assert FormDef.count() == 2
875
    assert FormDef.get(2).name == 'form title (copy)'
876

  
877
    resp = app.get('/backoffice/forms/1/')
878
    resp = resp.click(href='duplicate')
879
    assert resp.location == 'http://example.net/backoffice/forms/3/'
880
    resp = resp.follow()
881
    assert FormDef.count() == 3
882
    assert FormDef.get(3).name == 'form title (copy 2)'
883

  
884

  
885
def test_form_export(pub):
886
    create_superuser(pub)
887
    create_role()
888

  
889
    FormDef.wipe()
890
    formdef = FormDef()
891
    formdef.name = 'form title'
892
    formdef.fields = []
893
    formdef.store()
894

  
895
    app = login(get_app(pub))
896
    resp = app.get('/backoffice/forms/1/')
897

  
898
    resp = resp.click(href='export')
899
    xml_export = resp.text
900

  
901
    fd = StringIO(xml_export)
902
    formdef2 = FormDef.import_from_xml(fd)
903
    assert formdef2.name == 'form title'
904

  
905

  
906
def test_form_import(pub):
907
    user = create_superuser(pub)
908
    role = create_role()
909

  
910
    FormDef.wipe()
911
    formdef = FormDef()
912
    formdef.name = 'form title'
913
    formdef.fields = []
914
    formdef.store()
915
    formdef_xml = ET.tostring(formdef.export_to_xml(include_id=True))
916

  
917
    FormDef.wipe()
918
    assert FormDef.count() == 0
919

  
920
    app = login(get_app(pub))
921
    resp = app.get('/backoffice/forms/')
922
    resp = resp.click(href='import')
923
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef_xml)
924
    resp = resp.forms[0].submit()
925
    assert FormDef.count() == 1
926

  
927
    # import the same formdef a second time, make sure url name and internal
928
    # identifier are not reused
929
    resp = app.get('/backoffice/forms/')
930
    resp = resp.click(href='import')
931
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef_xml)
932
    resp = resp.forms[0].submit()
933
    assert FormDef.count() == 2
934
    assert FormDef.get(1).url_name == 'form-title'
935
    assert FormDef.get(2).url_name == 'form-title-1'
936
    assert FormDef.get(1).internal_identifier == 'form-title'
937
    assert FormDef.get(2).internal_identifier == 'form-title-1'
938

  
939
    # import a formdef with an url name that doesn't match its title,
940
    # it should be kept intact.
941
    formdef.url_name = 'xxx-other-form-title'
942
    formdef_xml = ET.tostring(formdef.export_to_xml(include_id=True))
943

  
944
    resp = app.get('/backoffice/forms/')
945
    resp = resp.click(href='import')
946
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef_xml)
947
    resp = resp.forms[0].submit()
948
    assert FormDef.get(3).url_name == 'xxx-other-form-title'
949
    assert FormDef.get(3).internal_identifier == 'form-title-2'
950

  
951
    # import an invalid file
952
    resp = app.get('/backoffice/forms/')
953
    resp = resp.click(href='import')
954
    resp.form['file'] = Upload('formdef.wcs', b'garbage')
955
    resp = resp.form.submit()
956
    assert 'Invalid File' in resp.text
957

  
958
    # xml with duplicate id, fix it
959
    formdef = FormDef()
960
    formdef.name = 'form title'
961
    formdef.fields = [
962
        fields.StringField(id='42', label='1st field', type='string'),
963
        fields.StringField(id='42', label='2nd field', type='string'),
964
    ]
965
    formdef_xml = ET.tostring(formdef.export_to_xml(include_id=True))
966
    FormDef.wipe()
967
    resp = app.get('/backoffice/forms/')
968
    resp = resp.click(href='import')
969
    resp.form['file'] = Upload('formdef.wcs', formdef_xml)
970
    resp = resp.form.submit()
971
    resp = resp.follow()
972
    assert 'form contained errors and has been automatically fixed' in resp.text
973
    assert FormDef.count() == 1
974
    assert FormDef.get(1).fields[0].id == '1'
975
    assert FormDef.get(1).fields[1].id == '2'
976

  
977

  
978
def test_form_qrcode(pub):
979
    create_superuser(pub)
980
    create_role()
981

  
982
    FormDef.wipe()
983
    formdef = FormDef()
984
    formdef.name = 'form title'
985
    formdef.fields = []
986
    formdef.store()
987

  
988
    app = login(get_app(pub))
989
    resp = app.get('/backoffice/forms/1/')
990

  
991
    resp = resp.click(href='qrcode')
992
    assert '<div id="qrcode">' in resp.text
993
    resp = resp.click('Download')
994
    assert resp.content_type == 'image/png'
995

  
996

  
997
def test_form_description(pub):
998
    create_superuser(pub)
999
    create_role()
1000

  
1001
    FormDef.wipe()
1002
    formdef = FormDef()
1003
    formdef.name = 'form title'
1004
    formdef.fields = []
1005
    formdef.store()
1006

  
1007
    app = login(get_app(pub))
1008
    resp = app.get('/backoffice/forms/1/')
1009
    assert_option_display(resp, 'Description', 'None')
1010

  
1011
    resp = resp.click('Description')
1012
    resp.forms[0]['description'].value = '<p>Hello World</p>'
1013
    resp = resp.forms[0].submit()
1014
    assert resp.location == 'http://example.net/backoffice/forms/1/'
1015
    resp = resp.follow()
1016
    assert_option_display(resp, 'Description', 'On')
1017

  
1018

  
1019
def test_form_new_field(pub):
1020
    create_superuser(pub)
1021
    create_role()
1022

  
1023
    FormDef.wipe()
1024
    formdef = FormDef()
1025
    formdef.name = 'form title'
1026
    formdef.fields = []
1027
    formdef.store()
1028

  
1029
    app = login(get_app(pub))
1030
    resp = app.get('/backoffice/forms/1/')
1031
    resp = resp.click(href='fields/')
1032
    assert 'There are not yet any fields for this form' in resp.text
1033

  
1034
    resp.forms[0]['label'] = 'foobar'
1035
    resp.forms[0]['type'] = 'string'
1036
    resp = resp.forms[0].submit()
1037
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/'
1038
    resp = resp.follow()
1039
    assert 'foobar' in resp.text
1040
    assert 'Use drag and drop' in resp.text
1041

  
1042
    assert len(FormDef.get(1).fields) == 1
1043
    assert FormDef.get(1).fields[0].key == 'string'
1044
    assert FormDef.get(1).fields[0].label == 'foobar'
1045

  
1046
    # add a title too
1047
    resp.forms[0]['label'] = 'baz'
1048
    resp.forms[0]['type'] = 'title'
1049
    resp = resp.forms[0].submit()
1050
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/'
1051
    resp = resp.follow()
1052

  
1053
    # check it's in the preview
1054
    resp = app.get('/backoffice/forms/1/')
1055
    assert '<h3 data-field-id="1">baz</h3>' in resp.text
1056

  
1057

  
1058
def test_form_delete_field(pub):
1059
    create_superuser(pub)
1060
    create_role()
1061

  
1062
    FormDef.wipe()
1063
    formdef = FormDef()
1064
    formdef.name = 'form title'
1065
    formdef.fields = [fields.StringField(id='1', label='1st field', type='string')]
1066
    formdef.store()
1067
    formdef.data_class().wipe()
1068

  
1069
    app = login(get_app(pub))
1070
    resp = app.get('/backoffice/forms/1/')
1071
    resp = resp.click(href='fields/')
1072
    assert '1st field' in resp.text
1073
    assert 'Use drag and drop' in resp.text
1074
    assert 'Also remove all fields from the page' not in resp.text
1075

  
1076
    resp = resp.click(href='1/delete')
1077
    assert 'You are about to remove the "1st field" field.' in resp.text
1078
    assert 'Warning:' not in resp.text
1079
    resp = resp.forms[0].submit()
1080
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/'
1081
    resp = resp.follow()
1082
    assert len(FormDef.get(1).fields) == 0
1083

  
1084

  
1085
def test_form_delete_field_existing_data(pub):
1086
    create_superuser(pub)
1087
    create_role()
1088

  
1089
    FormDef.wipe()
1090
    formdef = FormDef()
1091
    formdef.name = 'form title'
1092
    formdef.fields = [
1093
        fields.StringField(id='1', label='1st field', type='string'),
1094
        fields.CommentField(id='2', label='comment field', type='comment'),
1095
    ]
1096
    formdef.store()
1097
    formdef.data_class().wipe()
1098

  
1099
    formdata = formdef.data_class()()
1100
    formdata.just_created()
1101
    formdata.data = {'1': 'hello'}
1102
    formdata.store()
1103

  
1104
    app = login(get_app(pub))
1105
    resp = app.get('/backoffice/forms/1/')
1106
    resp = resp.click(href='fields/')
1107
    resp = resp.click(href='1/delete')
1108
    assert 'You are about to remove the "1st field" field.' in resp.text
1109
    assert 'Warning:' in resp.text
1110
    resp = resp.forms[0].submit()
1111
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_2'
1112
    resp = resp.follow()
1113
    assert len(FormDef.get(1).fields) == 1
1114

  
1115
    # check non-data fields do not show this warning
1116
    resp = app.get('/backoffice/forms/1/')
1117
    resp = resp.click(href='fields/')
1118
    resp = resp.click(href='2/delete')
1119
    assert 'You are about to remove the "comment field" field.' in resp.text
1120
    assert 'Warning:' not in resp.text
1121
    resp = resp.forms[0].submit()
1122
    resp = resp.follow()
1123
    assert len(FormDef.get(1).fields) == 0
1124

  
1125

  
1126
def test_form_delete_page_field(pub):
1127
    create_superuser(pub)
1128
    create_role()
1129

  
1130
    FormDef.wipe()
1131
    formdef = FormDef()
1132
    formdef.name = 'form title'
1133
    formdef.fields = [
1134
        fields.PageField(id='1', label='page 1', type='page'),
1135
        fields.StringField(id='2', label='field 1 1', type='string'),
1136
        fields.StringField(id='3', label='field 1 2', type='string'),
1137
        fields.PageField(id='4', label='page 2', type='page'),
1138
        fields.PageField(id='5', label='page 3', type='page'),
1139
        fields.StringField(id='6', label='field 3 1', type='string'),
1140
        fields.StringField(id='7', label='field 3 2', type='string'),
1141
    ]
1142
    formdef.store()
1143
    formdef.data_class().wipe()
1144

  
1145
    app = login(get_app(pub))
1146

  
1147
    # delete fields from the page
1148
    resp = app.get('/backoffice/forms/1/fields/1/delete')
1149
    assert 'You are about to remove the "page 1" page.' in resp.text
1150
    assert 'Also remove all fields from the page' in resp.text
1151
    resp.forms[0]['delete_fields'] = True
1152
    resp = resp.forms[0].submit()
1153
    resp = resp.follow()
1154
    assert len(FormDef.get(1).fields) == 4
1155

  
1156
    # empty page
1157
    resp = app.get('/backoffice/forms/1/fields/4/delete')
1158
    assert 'You are about to remove the "page 2" page.' in resp.text
1159
    assert 'Also remove all fields from the page' not in resp.text
1160
    resp = resp.forms[0].submit()
1161
    resp = resp.follow()
1162
    assert len(FormDef.get(1).fields) == 3
1163

  
1164
    # keep fields
1165
    resp = app.get('/backoffice/forms/1/fields/5/delete')
1166
    assert 'You are about to remove the "page 3" page.' in resp.text
1167
    assert 'Also remove all fields from the page' in resp.text
1168
    resp.forms[0]['delete_fields'] = False
1169
    resp = resp.forms[0].submit()
1170
    resp = resp.follow()
1171
    assert len(FormDef.get(1).fields) == 2
1172

  
1173

  
1174
def test_form_duplicate_field(pub):
1175
    user = create_superuser(pub)
1176
    create_role()
1177

  
1178
    FormDef.wipe()
1179
    formdef = FormDef()
1180
    formdef.name = 'form title'
1181
    formdef.fields = [fields.StringField(id='1', label='1st field', type='string')]
1182
    formdef.store()
1183

  
1184
    app = login(get_app(pub))
1185
    resp = app.get('/backoffice/forms/1/')
1186
    resp = resp.click(href='fields/')
1187
    assert '1st field' in resp.text
1188

  
1189
    resp = resp.click(href='1/duplicate')
1190
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_2'
1191
    resp = resp.follow()
1192
    assert len(FormDef.get(1).fields) == 2
1193
    assert FormDef.get(1).fields[0].label == '1st field'
1194
    assert FormDef.get(1).fields[1].label == '1st field'
1195

  
1196

  
1197
def test_form_duplicate_file_field(pub):
1198
    create_superuser(pub)
1199
    create_role()
1200

  
1201
    FormDef.wipe()
1202
    formdef = FormDef()
1203
    formdef.name = 'form title'
1204
    formdef.fields = []
1205
    formdef.store()
1206

  
1207
    app = login(get_app(pub))
1208
    resp = app.get('/backoffice/forms/1/')
1209
    resp = resp.click(href='fields/')
1210

  
1211
    # add a first field
1212
    resp.forms[0]['label'] = 'foobar'
1213
    resp.forms[0]['type'] = 'file'
1214
    resp = resp.forms[0].submit()
1215
    assert resp.location == 'http://example.net/backoffice/forms/%s/fields/' % formdef.id
1216
    resp = resp.follow()
1217
    assert 'foobar' in resp.text
1218

  
1219
    resp = resp.click(href='%s/duplicate' % FormDef.get(formdef.id).fields[0].id)
1220
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_2'
1221
    resp = resp.follow()
1222

  
1223

  
1224
def test_form_edit_field(pub):
1225
    create_superuser(pub)
1226
    create_role()
1227

  
1228
    FormDef.wipe()
1229
    formdef = FormDef()
1230
    formdef.name = 'form title'
1231
    formdef.fields = [fields.StringField(id='1', label='1st field', type='string')]
1232
    formdef.store()
1233

  
1234
    app = login(get_app(pub))
1235
    resp = app.get('/backoffice/forms/1/')
1236
    resp = resp.click(href='fields/')
1237
    assert '1st field' in resp.text
1238

  
1239
    resp = resp.click('Edit', href='1/')
1240
    assert resp.forms[0]['label'].value == '1st field'
1241
    resp.forms[0]['label'] = 'changed field'
1242
    resp.forms[0]['required'] = False
1243
    resp = resp.forms[0].submit('submit')
1244
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1'
1245

  
1246
    assert FormDef.get(1).fields[0].label == 'changed field'
1247
    assert FormDef.get(1).fields[0].required == False
1248

  
1249

  
1250
def test_form_edit_field_advanced(pub):
1251
    create_superuser(pub)
1252
    create_role()
1253

  
1254
    FormDef.wipe()
1255
    formdef = FormDef()
1256
    formdef.name = 'form title'
1257
    formdef.fields = [fields.StringField(id='1', label='1st field', type='string')]
1258
    formdef.store()
1259

  
1260
    app = login(get_app(pub))
1261
    resp = app.get('/backoffice/forms/1/')
1262
    resp = resp.click(href='fields/')
1263
    assert '1st field' in resp.text
1264

  
1265
    resp = resp.click('Edit', href='1/')
1266
    assert resp.forms[0]['label'].value == '1st field'
1267
    assert '<legend>Additional parameters</legend>' in resp.text
1268
    assert '>Prefill</label>' in resp.text
1269
    # check the "prefill" field is under additional parameters
1270
    assert resp.text.index('<legend>Additional parameters</legend>') < \
1271
            resp.text.index('>Prefill</label>')
1272

  
1273
    # complete the "prefill" field
1274
    resp.forms[0]['prefill$type'] = 'String / Template'
1275
    resp.forms[0]['prefill$value_string'] = 'test'
1276
    resp = resp.forms[0].submit('submit')
1277
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1'
1278
    resp = resp.follow()
1279

  
1280
    assert FormDef.get(formdef.id).fields[0].prefill == {'type': 'string', 'value': 'test', 'locked': False}
1281

  
1282
    # do the same with 'data sources' field
1283
    resp = resp.click('Edit', href='1/')
1284
    assert resp.forms[0]['label'].value == '1st field'
1285
    assert '<legend>Additional parameters</legend>' in resp.text
1286
    assert '>Data Source</label>' in resp.text
1287
    # check the "data source" field is under additional parameters
1288
    assert resp.text.index('<legend>Additional parameters</legend>') < \
1289
            resp.text.index('>Data Source</label>')
1290

  
1291
    # start filling the "data source" field
1292
    resp.forms[0]['data_source$type'] = 'json'
1293
    resp.forms[0]['data_source$value'] = 'http://example.net'
1294
    resp = resp.forms[0].submit('submit')
1295
    resp = resp.follow()
1296

  
1297
    # it should now appear before the additional parameters section
1298
    resp = resp.click('Edit', href='1/')
1299
    assert resp.text.index('<legend>Additional parameters</legend>') > resp.text.index('>Data Source</label>')
1300

  
1301

  
1302
def test_form_prefill_field(pub):
1303
    create_superuser(pub)
1304
    create_role()
1305

  
1306
    FormDef.wipe()
1307
    formdef = FormDef()
1308
    formdef.name = 'form title'
1309
    formdef.fields = [fields.StringField(id='1', label='1st field', type='string')]
1310
    formdef.store()
1311

  
1312
    app = login(get_app(pub))
1313

  
1314
    resp = app.get('/backoffice/forms/1/fields/1/')
1315
    resp.form['prefill$type'] = 'String / Template'
1316
    resp.form['prefill$value_string'] = 'test'
1317
    resp = resp.form.submit('submit').follow()
1318
    assert FormDef.get(formdef.id).fields[0].prefill == {'type': 'string', 'value': 'test', 'locked': False}
1319

  
1320
    resp = app.get('/backoffice/forms/1/fields/1/')
1321
    resp.form['prefill$type'] = 'Python Expression'
1322
    resp.form['prefill$value_formula'] = 'True'
1323
    resp = resp.form.submit('submit').follow()
1324
    assert FormDef.get(formdef.id).fields[0].prefill == {'type': 'formula', 'value': 'True', 'locked': False}
1325

  
1326
    resp = app.get('/backoffice/forms/1/fields/1/')
1327
    resp.form['prefill$type'] = 'String / Template'
1328
    resp.form['prefill$value_string'] = '{{form_var_toto}}'
1329
    resp = resp.form.submit('submit').follow()
1330
    assert FormDef.get(formdef.id).fields[0].prefill == {'type': 'string', 'value': '{{form_var_toto}}', 'locked': False}
1331

  
1332
    # check error handling
1333
    resp = app.get('/backoffice/forms/1/fields/1/')
1334
    resp.form['prefill$type'] = 'Python Expression'
1335
    resp.form['prefill$value_formula'] = ':'
1336
    resp = resp.form.submit('submit')
1337
    assert 'invalid expression: unexpected EOF while parsing' in resp.text
1338

  
1339
    resp = app.get('/backoffice/forms/1/fields/1/')
1340
    resp.form['prefill$type'] = 'String / Template'
1341
    resp.form['prefill$value_string'] = '{% if %}'
1342
    resp = resp.form.submit('submit')
1343
    assert 'syntax error in Django template: Unexpected end of expression' in resp.text
1344

  
1345

  
1346
def test_form_edit_string_field_validation(pub):
1347
    create_superuser(pub)
1348
    create_role()
1349

  
1350
    FormDef.wipe()
1351
    formdef = FormDef()
1352
    formdef.name = 'form title'
1353
    formdef.fields = [fields.StringField(id='1', label='1st field', type='string')]
1354
    formdef.store()
1355

  
1356
    app = login(get_app(pub))
1357
    resp = app.get('/backoffice/forms/1/')
1358
    resp = resp.click(href='fields/')
1359
    assert '1st field' in resp.text
1360

  
1361
    resp = resp.click('Edit', href='1/')
1362
    resp.form['validation$type'] = 'Regular Expression'
1363
    resp.form['validation$value_regex'] = r'\d+'
1364
    resp = resp.form.submit('submit').follow()
1365
    assert FormDef.get(formdef.id).fields[0].validation == {'type': 'regex', 'value': r'\d+'}
1366

  
1367
    resp = resp.click('Edit', href='1/')
1368
    resp.form['validation$type'] = 'None'
1369
    resp = resp.form.submit('submit').follow()
1370
    assert FormDef.get(formdef.id).fields[0].validation is None
1371

  
1372
    resp = resp.click('Edit', href='1/')
1373
    resp.form['validation$type'] = 'Django Condition'
1374
    resp.form['validation$value_django'] = 'value|decimal < 20'
1375
    resp = resp.form.submit('submit').follow()
1376
    assert FormDef.get(formdef.id).fields[0].validation == {'type': 'django', 'value': 'value|decimal < 20'}
1377

  
1378
    resp = resp.click('Edit', href='1/')
1379
    resp.form['validation$type'] = 'Django Condition'
1380
    resp.form['validation$value_django'] = '{{ value|decimal < 20 }}'
1381
    resp = resp.form.submit('submit')
1382
    assert 'syntax error' in resp.text
1383

  
1384

  
1385
def test_form_edit_item_field(pub):
1386
    create_superuser(pub)
1387
    create_role()
1388

  
1389
    FormDef.wipe()
1390
    formdef = FormDef()
1391
    formdef.name = 'form title'
1392
    formdef.fields = [fields.ItemField(id='1', label='1st field', type='item')]
1393
    formdef.store()
1394

  
1395
    app = login(get_app(pub))
1396
    resp = app.get('/backoffice/forms/1/')
1397
    resp = resp.click(href='fields/')
1398
    assert '1st field' in resp.text
1399

  
1400
    resp = resp.click('Edit', href='1/')
1401
    assert resp.forms[0]['label'].value == '1st field'
1402
    resp.forms[0]['label'] = 'changed field'
1403
    resp.forms[0]['required'] = False
1404
    resp = resp.forms[0].submit('items$add_element')
1405
    # this adds a second field
1406
    assert 'items$element0' in resp.form.fields
1407
    assert 'items$element1' in resp.form.fields
1408
    # but don't fill anything
1409
    resp = resp.forms[0].submit('submit')
1410
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1'
1411
    resp = resp.follow()
1412

  
1413
    assert FormDef.get(1).fields[0].label == 'changed field'
1414
    assert FormDef.get(1).fields[0].required == False
1415
    assert FormDef.get(1).fields[0].items is None
1416

  
1417
    # edit and fill with one item
1418
    resp = resp.click('Edit', href='1/')
1419
    assert resp.forms[0]['label'].value == 'changed field'
1420
    resp.forms[0]['items$element0'] = 'XXX'
1421
    resp = resp.forms[0].submit('submit')
1422
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1'
1423
    assert FormDef.get(1).fields[0].items == ['XXX']
1424

  
1425

  
1426
def test_form_edit_item_field_data_source(pub):
1427
    create_superuser(pub)
1428
    create_role()
1429

  
1430
    FormDef.wipe()
1431
    formdef = FormDef()
1432
    formdef.name = 'form title'
1433
    formdef.fields = [fields.ItemField(id='1', label='1st field', type='item')]
1434
    formdef.store()
1435

  
1436
    app = login(get_app(pub))
1437
    resp = app.get('/backoffice/forms/1/fields/1/')
1438
    assert resp.form['data_source$type'].options == [
1439
        (u'None', True, u'None'),
1440
        (u'json', False, u'JSON URL'),
1441
        (u'jsonp', False, u'JSONP URL'),
1442
        (u'python', False, u'Python Expression')
1443
    ]
1444
    resp = resp.form.submit('submit').follow()
1445

  
1446
    data_source = NamedDataSource(name='Foobar')
1447
    data_source.data_source = {'type': 'formula', 'value': '[]'}
1448
    data_source.store()
1449

  
1450
    resp = app.get('/backoffice/forms/1/fields/1/')
1451
    assert resp.form['data_source$type'].options == [
1452
        (u'None', True, u'None'),
1453
        (u'foobar', False, u'Foobar'),
1454
        (u'json', False, u'JSON URL'),
1455
        (u'jsonp', False, u'JSONP URL'),
1456
        (u'python', False, u'Python Expression')
1457
    ]
1458
    resp.form['data_source$type'].value = 'foobar'
1459
    resp = resp.form.submit('submit').follow()
1460
    assert FormDef.get(formdef.id).fields[0].data_source == {'type': 'foobar'}
1461

  
1462
    carddef = CardDef()
1463
    carddef.name = 'Baz'
1464
    carddef.store()
1465

  
1466
    resp = app.get('/backoffice/forms/1/fields/1/')
1467
    assert resp.form['data_source$type'].options == [
1468
        (u'None', False, u'None'),
1469
        (u'foobar', True, u'Foobar'),
1470
        (u'json', False, u'JSON URL'),
1471
        (u'jsonp', False, u'JSONP URL'),
1472
        (u'python', False, u'Python Expression')
1473
    ]
1474

  
1475
    carddef.digest_template = 'plop'
1476
    carddef.store()
1477

  
1478
    resp = app.get('/backoffice/forms/1/fields/1/')
1479
    assert resp.form['data_source$type'].options == [
1480
        (u'None', False, u'None'),
1481
        (u'carddef:%s' % carddef.url_name, False, u'Baz'),
1482
        (u'foobar', True, u'Foobar'),
1483
        (u'json', False, u'JSON URL'),
1484
        (u'jsonp', False, u'JSONP URL'),
1485
        (u'python', False, u'Python Expression')
1486
    ]
1487

  
1488
    resp.form['data_source$type'].value = 'carddef:%s' % carddef.url_name
1489
    resp = resp.form.submit('submit').follow()
1490
    assert FormDef.get(formdef.id).fields[0].data_source == {'type': 'carddef:%s' % carddef.url_name}
1491

  
1492
    # set json source then back to none
1493
    resp = app.get('/backoffice/forms/1/fields/1/')
1494
    resp.form['data_source$type'].value = 'json'
1495
    resp.form['data_source$value'].value = 'http://whatever'
1496
    resp = resp.form.submit('submit').follow()
1497
    assert FormDef.get(formdef.id).fields[0].data_source == {'type': 'json', 'value': 'http://whatever'}
1498

  
1499
    resp = app.get('/backoffice/forms/1/fields/1/')
1500
    resp.form['data_source$type'].value = 'None'
1501
    resp = resp.form.submit('submit').follow()
1502
    resp = app.get('/backoffice/forms/1/')
1503

  
1504

  
1505
def test_form_edit_items_field(pub):
1506
    create_superuser(pub)
1507
    create_role()
1508

  
1509
    FormDef.wipe()
1510
    formdef = FormDef()
1511
    formdef.name = 'form title'
1512
    formdef.fields = [fields.ItemsField(id='1', label='1st field', type='items')]
1513
    formdef.store()
1514

  
1515
    app = login(get_app(pub))
1516
    resp = app.get('/backoffice/forms/1/')
1517
    resp = resp.click(href='fields/')
1518
    assert '1st field' in resp.text
1519

  
1520
    resp = resp.click('Edit', href='1/')
1521
    assert resp.forms[0]['label'].value == '1st field'
1522
    resp.forms[0]['label'] = 'changed field'
1523
    resp.forms[0]['required'] = False
1524
    resp = resp.forms[0].submit('items$add_element')
1525
    # this adds a second field
1526
    assert 'items$element0' in resp.form.fields
1527
    assert 'items$element1' in resp.form.fields
1528
    # but don't fill anything
1529
    resp = resp.forms[0].submit('submit')
1530
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1'
1531
    resp = resp.follow()
1532

  
1533
    assert FormDef.get(1).fields[0].label == 'changed field'
1534
    assert FormDef.get(1).fields[0].required == False
1535
    assert FormDef.get(1).fields[0].items is None
1536

  
1537
    # edit and fill with one item
1538
    resp = resp.click('Edit', href='1/')
1539
    assert resp.forms[0]['label'].value == 'changed field'
1540
    resp.forms[0]['items$element0'] = 'XXX'
1541
    resp = resp.forms[0].submit('submit')
1542
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/#itemId_1'
1543
    assert FormDef.get(1).fields[0].items == ['XXX']
1544

  
1545
    # check prefilling is only possible with Python
1546
    resp = resp.follow()
1547
    resp = resp.click('Edit', href='1/')
1548
    assert resp.forms[0]['prefill$type'].options == [
1549
            (u'None', True, u'None'), (u'Python Expression', False, u'Python Expression')]
1550

  
1551

  
1552
def test_form_edit_page_field(pub):
1553
    create_superuser(pub)
1554
    create_role()
1555

  
1556
    FormDef.wipe()
1557
    formdef = FormDef()
1558
    formdef.name = 'form title'
1559
    formdef.fields = []
1560
    formdef.store()
1561

  
1562
    app = login(get_app(pub))
1563
    resp = app.get('/backoffice/forms/1/')
1564
    resp = resp.click(href='fields/')
1565
    assert 'There are not yet any fields for this form' in resp.text
1566

  
1567
    resp.forms[0]['label'] = 'foobar'
1568
    resp.forms[0]['type'] = 'page'
1569
    resp = resp.forms[0].submit()
1570
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/'
1571
    resp = resp.follow()
1572
    assert 'Page #1' in resp.text
1573
    assert 'foobar' in resp.text
1574
    assert 'Use drag and drop' in resp.text
1575

  
1576
    assert len(FormDef.get(1).fields) == 1
1577
    assert FormDef.get(1).fields[0].key == 'page'
1578
    assert FormDef.get(1).fields[0].label == 'foobar'
1579

  
1580
    resp = resp.click('Edit', href='1/')
1581
    resp.form['post_conditions$element0$condition$type'] = 'python'
1582
    resp.form['post_conditions$element0$condition$value_python'] = 'foo'
1583
    resp.form['post_conditions$element0$error_message'] = 'bar'
1584
    resp = resp.form.submit('post_conditions$add_element')
1585
    resp.form['post_conditions$element1$condition$type'] = 'python'
1586
    resp.form['post_conditions$element1$condition$value_python'] = 'foo2'
1587
    resp = resp.form.submit('submit')
1588
    assert 'Both condition and error message are required.' in resp.text
1589
    resp.form['post_conditions$element1$error_message'] = 'bar2'
1590
    resp = resp.form.submit('submit').follow()
1591

  
1592
    assert FormDef.get(1).fields[0].post_conditions == [
1593
            {'condition': {'type': 'python', 'value': 'foo'}, 'error_message': 'bar'},
1594
            {'condition': {'type': 'python', 'value': 'foo2'}, 'error_message': 'bar2'},
1595
    ]
1596

  
1597
    resp = resp.click('Edit', href='1/')
1598
    resp.form['post_conditions$element1$condition$type'] = 'django'
1599
    resp.form['post_conditions$element1$condition$value_django'] = 'foo3'
1600
    resp = resp.form.submit('submit').follow()
1601
    assert FormDef.get(1).fields[0].post_conditions == [
1602
            {'condition': {'type': 'python', 'value': 'foo'}, 'error_message': 'bar'},
1603
            {'condition': {'type': 'django', 'value': 'foo3'}, 'error_message': 'bar2'},
1604
    ]
1605

  
1606

  
1607
def test_form_edit_comment_field(pub):
1608
    create_superuser(pub)
1609
    create_role()
1610

  
1611
    FormDef.wipe()
1612
    formdef = FormDef()
1613
    formdef.name = 'form title'
1614
    formdef.fields = [fields.CommentField(id='1', label='a comment field', type='comment')]
1615
    formdef.store()
1616

  
1617
    app = login(get_app(pub))
1618
    resp = app.get('/backoffice/forms/1/fields/1/')
1619
    assert 'a comment field' in resp.text
1620
    assert 'WysiwygTextWidget' in resp.text
1621

  
1622
    # legacy, double line breaks will be converted to paragraphs
1623
    formdef.fields = [fields.CommentField(id='1', type='comment',
1624
        label='a comment field\n\na second line')]
1625
    formdef.store()
1626
    resp = app.get('/backoffice/forms/1/fields/1/')
1627
    assert 'WysiwygTextWidget' in resp.text
1628
    resp = resp.form.submit('submit')
1629
    assert FormDef.get(formdef.id).fields[0].label == '<p>a comment field</p>\n<p>a second line</p>'
1630

  
1631
    # starting with a <
1632
    formdef.fields = [fields.CommentField(id='1', type='comment',
1633
        label='<strong>a comment field\n\na second line</strong>')]
1634
    formdef.store()
1635
    resp = app.get('/backoffice/forms/1/fields/1/')
1636
    assert 'WysiwygTextWidget' in resp.text
1637

  
1638
    # legacy, ezt syntax in a non-html field will be presented as a textarea
1639
    formdef.fields = [fields.CommentField(id='1', type='comment',
1640
        label='[if-any toto]hello world[end]')]
1641
    formdef.store()
1642
    resp = app.get('/backoffice/forms/1/fields/1/')
1643
    assert 'WysiwygTextWidget' not in resp.text
1644

  
1645
    # check a new field is created with label as HTML, enclosing label in <p>
1646
    resp = app.get('/backoffice/forms/1/fields/')
1647
    resp.forms[0]['label'] = 'foobar'
1648
    resp.forms[0]['type'] = 'comment'
1649
    resp = resp.forms[0].submit()
1650
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/'
1651
    assert FormDef.get(formdef.id).fields[-1].label == '<p>foobar</p>'
1652

  
1653
    # unless label is already given as HTML
1654
    resp = app.get('/backoffice/forms/1/fields/')
1655
    resp.forms[0]['label'] = '<div>blah</div>'
1656
    resp.forms[0]['type'] = 'comment'
1657
    resp = resp.forms[0].submit()
1658
    assert resp.location == 'http://example.net/backoffice/forms/1/fields/'
1659
    assert FormDef.get(formdef.id).fields[-1].label == '<div>blah</div>'
1660

  
1661

  
1662
def test_form_comment_field_textwidget_validation(pub):
1663
    create_superuser(pub)
1664
    FormDef.wipe()
1665
    formdef = FormDef()
1666
    formdef.name = 'form title'
1667
    # legacy, ezt syntax in a non-html field will be presented as a textarea
1668
    formdef.fields = [fields.CommentField(id='1', type='comment',
1669
        label='[if-any toto]hello world[end]')]
1670
    formdef.store()
1671
    app = login(get_app(pub))
1672
    resp = app.get('/backoffice/forms/1/fields/1/')
1673

  
1674
    # bad {% %} Django template syntax
1675
    assert 'WysiwygTextWidget' not in resp.text
1676
    resp.form.fields['label'][0].value = '{% if cond %}no endif provided'
1677
    resp = resp.form.submit('submit')
1678
    assert 'syntax error in Django template: Unclosed tag on line 1' in resp.text
1679

  
1680
    # bad {{ }} Django template syntax
1681
    assert 'WysiwygTextWidget' not in resp.text
1682
    resp.form.fields['label'][0].value = '{{0+0}}'
1683
    resp = resp.form.submit('submit')
1684
    assert 'syntax error in Django template: Could not parse' in resp.text
1685

  
1686
    # bad EZT syntax
1687
    assert 'WysiwygTextWidget' not in resp.text
1688
    resp.form.fields['label'][0].value = '[end]'
1689
    resp = resp.form.submit('submit')
1690
    assert 'syntax error in ezt template: unmatched [end]' in resp.text
1691

  
1692
    # good syntax
1693
    assert 'WysiwygTextWidget' not in resp.text
1694
    resp.form.fields['label'][0].value = '{{variable}}'
1695
    resp = resp.form.submit('submit')
1696
    assert FormDef.get(formdef.id).fields[0].label == '{{variable}}'
1697

  
1698
def test_form_comment_field_wysiwygtextwidget_validation(pub):
1699
    create_superuser(pub)
1700
    create_role()
1701

  
1702
    FormDef.wipe()
1703
    formdef = FormDef()
1704
    formdef.name = 'form title'
1705
    formdef.fields = [fields.CommentField(id='1', label='a comment field', type='comment')]
1706
    formdef.store()
1707

  
1708
    app = login(get_app(pub))
1709
    resp = app.get('/backoffice/forms/1/fields/1/')
1710
    assert 'a comment field' in resp.text
1711

  
1712
    # bad {% %} Django template syntax
1713
    assert 'WysiwygTextWidget' in resp.text
1714
    resp.form.fields['label'][0].value = '{% if cond %}no endif provided'
1715
    resp = resp.form.submit('submit')
1716
    assert 'syntax error in Django template: Unclosed tag on line 1' in resp.text
1717

  
1718
    # bad {{ }} Django template syntax
1719
    assert 'WysiwygTextWidget' in resp.text
1720
    resp.form.fields['label'][0].value = '{{0+0}}'
1721
    resp = resp.form.submit('submit')
1722
    assert 'syntax error in Django template: Could not parse' in resp.text
1723

  
1724
    # bad EZT syntax
1725
    assert 'WysiwygTextWidget' in resp.text
1726
    resp.form.fields['label'][0].value = '[end]'
1727
    resp = resp.form.submit('submit')
1728
    assert 'syntax error in ezt template: unmatched [end]' in resp.text
1729

  
1730
    # good syntax
1731
    assert 'WysiwygTextWidget' in resp.text
1732
    resp.form.fields['label'][0].value = '{{variable}}'
1733
    resp = resp.form.submit('submit')
1734
    assert FormDef.get(formdef.id).fields[0].label == '{{variable}}'
1735

  
1736
def test_form_edit_map_field(pub):
1737
    create_superuser(pub)
1738
    create_role()
1739

  
1740
    FormDef.wipe()
1741
    formdef = FormDef()
1742
    formdef.name = 'form title'
1743
    formdef.fields = [fields.MapField(id='1', label='a field', type='map')]
1744
    formdef.store()
1745

  
1746
    app = login(get_app(pub))
1747

  
1748
    resp = app.get('/backoffice/forms/1/fields/1/')
1749
    resp = resp.form.submit('submit')
1750
    assert resp.location
1751

  
1752
    # min
1753
    formdef.store()
1754
    resp = app.get('/backoffice/forms/1/fields/1/')
1755
    resp.form['min_zoom'] = 'Wide area'
1756
    resp = resp.form.submit('submit')
1757
    assert FormDef.get(formdef.id).fields[0].min_zoom == '9'
1758

  
1759
    # max
1760
    formdef.store()
1761
    resp = app.get('/backoffice/forms/1/fields/1/')
1762
    resp.form['max_zoom'] = 'Small road'
1763
    resp = resp.form.submit('submit')
1764
    assert FormDef.get(formdef.id).fields[0].max_zoom == '16'
1765

  
1766
    # both
1767
    formdef.store()
1768
    resp = app.get('/backoffice/forms/1/fields/1/')
1769
    resp.form['min_zoom'] = 'Wide area'
1770
    resp.form['max_zoom'] = 'Small road'
1771
    resp = resp.form.submit('submit')
1772
    assert FormDef.get(formdef.id).fields[0].min_zoom == '9'
1773
    assert FormDef.get(formdef.id).fields[0].max_zoom == '16'
1774

  
1775
    # inverted
1776
    formdef.store()
1777
    resp = app.get('/backoffice/forms/1/fields/1/')
1778
    resp.form['min_zoom'] = 'Small road'
1779
    resp.form['max_zoom'] = 'Wide area'
1780
    resp = resp.form.submit('submit')
1781
    assert 'widget-with-error' in resp.text
1782

  
1783
    # initial out of range
1784
    formdef.store()
1785
    resp = app.get('/backoffice/forms/1/fields/1/')
1786
    resp.form['initial_zoom'] = 'Whole world'
1787
    resp.form['min_zoom'] = 'Wide area'
1788
    resp.form['max_zoom'] = 'Small road'
1789
    resp = resp.form.submit('submit')
1790
    assert 'widget-with-error' in resp.text
1791

  
1792
    # prefill fields
1793
    resp = app.get('/backoffice/forms/1/fields/1/')
1794
    resp.form['prefill$type'].value = 'Geolocation'
1795
    resp.form['prefill$value_geolocation'].value = 'Position'
1796
    resp = resp.form.submit('submit')
1797
    assert FormDef.get(formdef.id).fields[0].prefill == {
1798
            'type': 'geolocation', 'value': 'position', 'locked': False}
1799

  
1800

  
1801
def test_form_edit_field_warnings(pub):
1802
    create_superuser(pub)
1803
    create_role()
1804

  
1805
    FormDef.wipe()
1806
    formdef = FormDef()
1807
    formdef.name = 'form title'
1808
    formdef.fields = [fields.StringField(id='%d' % i, label='field %d' % i, type='string')
1809
                      for i in range(1,10)]
1810
    formdef.store()
1811

  
1812
    app = login(get_app(pub))
1813
    resp = app.get('/backoffice/forms/1/')
1814
    resp = resp.click(href='fields/')
1815
    assert 'more than 500 fields' not in resp.text
1816
    assert 'first field should be of type "page"' not in resp.text
1817

  
1818
    formdef.fields.append(fields.PageField(id='1000', label='page', type='page'))
1819
    formdef.store()
1820
    resp = app.get('/backoffice/forms/1/')
1821
    resp = resp.click(href='fields/')
1822
    assert 'more than 500 fields' not in resp.text
1823
    assert 'first field should be of type "page"' in resp.text
1824

  
1825
    formdef.fields.extend([fields.StringField(id='%d' % i, label='field %d' % i, type='string')
1826
                      for i in range(10,510)])
1827
    formdef.store()
1828
    resp = app.get('/backoffice/forms/1/')
1829
    resp = resp.click(href='fields/')
1830
    assert 'more than 500 fields' in resp.text
1831
    assert 'first field should be of type "page"' in resp.text
1832

  
1833
    FormDef.wipe()
1834

  
1835

  
1836
def test_form_limit_display_to_page(pub):
1837
    create_superuser(pub)
1838
    create_role()
1839

  
1840
    FormDef.wipe()
1841
    formdef = FormDef()
1842
    formdef.name = 'form title'
1843
    formdef.fields = [fields.PageField(id='0', label='1st page', type='page'),
1844
            fields.StringField(id='1', label='string', type='string', varname='foobar'),
1845
            fields.PageField(id='2', label='2nd page', type='page'),
1846
            fields.StringField(id='3', label='string 2', type='string', varname='baz')]
1847
    formdef.store()
1848

  
1849
    app = login(get_app(pub))
1850
    resp = app.get('/backoffice/forms/1/fields/')
1851
    assert '{{form_var_foobar}}' in resp.text
1852
    assert '2nd page' in resp.text
1853
    resp = resp.click('Limit display to this page', index=0)
1854
    hidden_fields = ''.join(re.findall('display:none.*', resp.text))
1855
    assert 'Display all pages' in resp.text
1856
    assert '{{form_var_foobar}}' not in hidden_fields
1857
    assert '{{form_var_baz}}' in hidden_fields
1858

  
1859

  
1860
def test_form_legacy_int_id(pub):
1861
    create_superuser(pub)
1862
    create_role()
1863

  
1864
    Category.wipe()
1865
    cat = Category(name='Foo')
1866
    cat.store()
1867

  
1868
    Workflow.wipe()
1869
    workflow = Workflow(name='Workflow One')
1870
    # create it with a single status
1871
    workflow.possible_status = [Workflow.get_default_workflow().possible_status[-1]]
1872
    workflow.store()
1873

  
1874
    FormDef.wipe()
1875
    formdef = FormDef()
1876
    formdef.name = 'form title'
1877
    formdef.fields = []
1878

  
1879
    role = Role(name='ZAB') # Z to get sorted last
1880
    role.store()
1881

  
1882
    # set attributes using integers
1883
    formdef.category_id = int(cat.id)
1884
    formdef.workflow_id = int(workflow.id)
1885
    formdef.workflow_roles = {'_receiver': int(role.id)}
1886
    formdef.roles = ['logged-users', int(role.id)]
1887

  
1888
    formdef.store()
1889

  
1890
    formdef = FormDef.get(formdef.id) # will run migrate
1891

  
1892
    app = login(get_app(pub))
1893
    resp = app.get('/backoffice/forms/1/')
1894

  
1895
    resp = resp.click(href='category')
1896
    assert resp.forms[0]['category_id'].value
1897

  
1898
    resp = app.get('/backoffice/forms/1/')
1899
    resp = resp.click(href='workflow', index=1)
1900
    assert resp.forms[0]['workflow_id'].value
1901

  
1902
    resp = app.get('/backoffice/forms/1/')
1903
    resp = resp.click('User Roles')
1904
    assert resp.forms[0]['roles$element0'].value == 'logged-users'
1905
    assert resp.forms[0]['roles$element1'].value == role.id
1906

  
1907
    resp = app.get('/backoffice/forms/1/')
1908
    resp = resp.click('Recipient')
1909
    assert resp.forms[0]['role_id'].value == role.id
1910

  
1911

  
1912
def test_form_anonymise(pub):
1913
    create_superuser(pub)
1914
    create_role()
1915

  
1916
    FormDef.wipe()
1917
    formdef = FormDef()
1918
    formdef.name = 'form title'
1919
    formdef.fields = []
1920
    formdef.store()
1921

  
1922
    data_class = formdef.data_class()
1923
    data_class.wipe()
1924
    for i in range(10):
1925
        formdata = data_class()
1926
        formdata.just_created()
1927
        if i < 3:
1928
            formdata.status = 'wf-new'
1929
        else:
1930
            formdata.status = 'wf-rejected'
1931
        formdata.store()
1932

  
1933
    app = login(get_app(pub))
1934
    resp = app.get('/backoffice/forms/1/')
1935
    resp = resp.click(href='anonymise')
1936
    resp = resp.form.submit('cancel')
1937
    assert len([x for x in formdef.data_class().select() if x.anonymised]) == 0
1938
    assert resp.location == 'http://example.net/backoffice/forms/1/'
1939

  
1940
    resp = app.get('/backoffice/forms/1/')
1941
    resp = resp.click(href='anonymise')
1942
    resp = resp.form.submit('submit')
1943
    assert resp.location == 'http://example.net/backoffice/forms/1/'
1944
    assert len([x for x in formdef.data_class().select() if x.anonymised]) == 0
1945

  
1946
    resp = app.get('/backoffice/forms/1/')
1947
    resp = resp.click(href='anonymise')
1948
    resp.form['before_request_date'].value = (datetime.datetime.today() +
1949
            datetime.timedelta(days=1)).strftime('%Y-%m-%d')
1950
    resp = resp.form.submit('submit')
1951
    assert resp.location == 'http://example.net/backoffice/forms/1/'
1952
    assert len([x for x in formdef.data_class().select() if x.anonymised]) == 7
1953

  
1954
    data_class.wipe()
1955
    for i in range(110):
1956
        formdata = data_class()
1957
        formdata.just_created()
1958
        if i < 3:
1959
            formdata.status = 'wf-rejected'
1960
        else:
1961
            formdata.status = 'wf-finished'
1962
        formdata.store()
1963

  
1964
    resp = app.get('/backoffice/forms/1/')
1965
    resp = resp.click(href='anonymise')
1966
    resp.form['before_request_date'].value = (datetime.datetime.today() +
1967
            datetime.timedelta(days=1)).strftime('%Y-%m-%d')
1968
    resp.form['endpoints$elementfinished'].checked = False
1969
    resp = resp.form.submit('submit')
1970
    assert '?job=' in resp.location
1971
    resp = resp.follow()
1972
    assert 'job-status' in resp.text
1973
    assert 'completed' in resp.text
1974
    assert len([x for x in formdef.data_class().select() if x.anonymised]) == 3
1975

  
1976

  
1977
def test_form_public_url(pub):
1978
    create_superuser(pub)
1979
    create_role()
1980

  
1981
    FormDef.wipe()
1982
    formdef = FormDef()
1983
    formdef.name = 'form title'
1984
    formdef.fields = []
1985
    formdef.store()
1986

  
1987
    app = login(get_app(pub))
1988
    resp = app.get('/backoffice/forms/1/')
1989
    resp = resp.click('Display public URL')
1990
    assert 'http://example.net/form-title/' in resp.text
1991

  
1992

  
1993
def test_form_archive(pub):
1994
    create_superuser(pub)
1995
    create_role()
1996

  
1997
    if pub.is_using_postgresql():
1998
        # this doesn't exist in SQL
1999
        pytest.skip('no archive in SQL mode')
2000
        return
2001

  
2002
    FormDef.wipe()
2003
    formdef = FormDef()
2004
    formdef.name = 'form title'
2005
    formdef.fields = []
2006
    formdef.store()
2007

  
2008
    data_class = formdef.data_class()
2009
    data_class.wipe()
2010
    for i in range(10):
2011
        formdata = data_class()
2012
        formdata.just_created()
2013
        if i < 3:
2014
            formdata.status = 'wf-new'
2015
        else:
2016
            formdata.status = 'wf-rejected'
2017
        formdata.store()
2018

  
2019
    app = login(get_app(pub))
2020
    resp = app.get('/backoffice/forms/1/')
2021
    resp = resp.click(href='archive')
2022
    resp = resp.form.submit('cancel')
2023
    assert data_class.count() == 10
2024
    assert resp.location == 'http://example.net/backoffice/forms/1/'
2025

  
2026
    resp = app.get('/backoffice/forms/1/')
2027
    resp = resp.click(href='archive')
2028
    resp = resp.form.submit('submit')
2029
    assert resp.content_type == 'application/x-wcs-archive'
2030
    tf = tarfile.open(fileobj=BytesIO(resp.body))
2031
    assert 'formdef' in [x.name for x in tf.getmembers()]
2032
    assert len(tf.getmembers()) == 8 # 7 formdata + 1 formdef
2033

  
2034
    # second archive, it shouldn't get anything (but the formdef)
2035
    resp = app.get('/backoffice/forms/1/')
2036
    resp = resp.click(href='archive')
2037
    resp = resp.form.submit('submit')
2038
    assert resp.content_type == 'application/x-wcs-archive'
2039
    tf = tarfile.open(fileobj=BytesIO(resp.body))
2040
    assert 'formdef' in [x.name for x in tf.getmembers()]
2041
    assert len(tf.getmembers()) == 1 # 0 formdata + 1 formdef
2042

  
2043

  
2044
def test_form_overwrite(pub):
2045
    user = create_superuser(pub)
2046
    role = create_role()
2047

  
2048
    FormDef.wipe()
2049
    formdef = FormDef()
2050
    formdef.name = 'form test'
2051
    formdef.table_name = 'xxx'
2052
    formdef.fields = [fields.StringField(id='1', label='1st field', type='string'),
2053
            fields.StringField(id='2', label='2nd field', type='string')]
2054
    formdef.store()
2055

  
2056
    formdata = formdef.data_class()()
2057
    formdata.data = {'1': 'foo', '2': 'bar'}
2058
    formdata.just_created()
2059
    formdata.store()
2060

  
2061
    formdef_id = formdef.id
2062
    formdef.fields[0].label = '1st modified field'
2063
    formdef_xml = ET.tostring(formdef.export_to_xml(include_id=True))
2064

  
2065
    app = login(get_app(pub))
2066
    resp = app.get('/backoffice/forms/%s/' % formdef_id)
2067
    resp = resp.click(href='overwrite')
2068
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef_xml)
2069
    resp = resp.forms[0].submit()
2070
    assert 'Overwrite - Summary of changes' in resp.text
2071
    resp = resp.forms[0].submit()
2072
    assert FormDef.get(formdef_id).fields[0].label == '1st modified field'
2073
    resp = resp.follow()
2074
    assert 'The form has been successfully overwritten.' in resp.text
2075

  
2076
    # check with added/removed field
2077
    new_formdef = FormDef()
2078
    new_formdef.name = 'form test overwrite'
2079
    new_formdef.fields = [
2080
            fields.StringField(id='2', label='2nd field', type='string'),
2081
            fields.StringField(id='3', label='3rd field', type='string')]
2082
    new_formdef_xml = ET.tostring(new_formdef.export_to_xml(include_id=True))
2083

  
2084
    # and no data within
2085
    formdef.data_class().wipe()
2086
    app = login(get_app(pub))
2087
    resp = app.get('/backoffice/forms/%s/' % formdef_id)
2088
    resp = resp.click(href='overwrite')
2089
    resp.forms[0]['file'] = Upload('formdef.wcs', new_formdef_xml)
2090
    resp = resp.forms[0].submit()
2091
    assert FormDef.get(formdef_id).fields[0].id == '2'
2092
    assert FormDef.get(formdef_id).fields[0].label == '2nd field'
2093
    assert FormDef.get(formdef_id).fields[1].id == '3'
2094
    assert FormDef.get(formdef_id).fields[1].label == '3rd field'
2095

  
2096
    # and data within
2097
    formdef.store()
2098
    formdata.data = {'1': 'foo', '2': 'bar'}
2099
    formdata.just_created()
2100
    formdata.store()
2101

  
2102
    resp = app.get('/backoffice/forms/%s/' % formdef_id)
2103
    resp = resp.click(href='overwrite')
2104
    resp.forms[0]['file'] = Upload('formdef.wcs', new_formdef_xml)
2105
    resp = resp.forms[0].submit()
2106
    assert 'The form removes or changes fields' in resp.text
2107
    assert resp.forms[0]['force'].checked is False
2108
    resp = resp.forms[0].submit()  # without checkbox (back to same form)
2109
    resp.forms[0]['force'].checked = True
2110
    resp = resp.forms[0].submit()
2111

  
2112
    assert FormDef.get(formdef_id).fields[0].id == '2'
2113
    assert FormDef.get(formdef_id).fields[0].label == '2nd field'
2114
    assert FormDef.get(formdef_id).fields[1].id == '3'
2115
    assert FormDef.get(formdef_id).fields[1].label == '3rd field'
2116

  
2117
    # check with a field of different type
2118
    formdef = FormDef.get(formdef_id)
2119
    formdata = formdef.data_class()()
2120
    formdata.data = {'1': 'foo', '2': 'bar', '3': 'baz'}
2121
    formdata.just_created()
2122
    formdata.store()
2123

  
2124
    new_formdef = FormDef()
2125
    new_formdef.name = 'form test overwrite'
2126
    new_formdef.fields = [
2127
            fields.StringField(id='2', label='2nd field', type='string'),
2128
            fields.DateField(id='3', label='3rd field, date', type='date')]  # (string -> date)
2129
    new_formdef_xml = ET.tostring(new_formdef.export_to_xml(include_id=True))
2130

  
2131
    app = login(get_app(pub))
2132
    resp = app.get('/backoffice/forms/%s/' % formdef_id)
2133
    resp = resp.click(href='overwrite', index=0)
2134
    resp.forms[0]['file'] = Upload('formdef.wcs', new_formdef_xml)
2135
    resp = resp.forms[0].submit()
2136
    assert 'The form removes or changes fields' in resp.text
2137
    resp.forms[0]['force'].checked = True
2138
    resp = resp.forms[0].submit()
2139
    assert FormDef.get(formdef_id).fields[1].id == '3'
2140
    assert FormDef.get(formdef_id).fields[1].label == '3rd field, date'
2141
    assert FormDef.get(formdef_id).fields[1].type == 'date'
2142

  
2143
    # check we kept stable references
2144
    assert FormDef.get(formdef_id).url_name == 'form-test'
2145
    assert FormDef.get(formdef_id).table_name == 'xxx'
2146

  
2147
    # check existing data
2148
    data = FormDef.get(formdef_id).data_class().get(formdata.id).data
2149
    assert data.get('2') == 'bar'
2150
    if pub.is_using_postgresql():
2151
        # in SQL, check data with different type has been removed
2152
        assert data.get('3') is None
2153

  
2154

  
2155
def test_form_export_import_export_overwrite(pub):
2156
    create_superuser(pub)
2157
    create_role()
2158

  
2159
    FormDef.wipe()
2160
    formdef = FormDef()
2161
    formdef.name = 'form title'
2162
    formdef.table_name = 'xxx'
2163
    formdef.fields = [  # unordered id
2164
        fields.StringField(id='1', label='field 1', type='string'),
2165
        fields.DateField(id='12', label='field 2', type='date'),
2166
        fields.ItemField(id='4', label='field 3', type='item'),
2167
    ]
2168
    formdef.store()
2169

  
2170
    # add data
2171
    formdata = formdef.data_class()()
2172
    formdata.data = {'1': 'foo'}
2173
    formdata.just_created()
2174
    formdata.store()
2175

  
2176
    formdef_xml = ET.tostring(formdef.export_to_xml(include_id=True))
2177

  
2178
    assert FormDef.count() == 1
2179
    assert formdef.url_name == 'form-title'
2180

  
2181
    app = login(get_app(pub))
2182
    resp = app.get('/backoffice/forms/')
2183
    resp = resp.click(href='import')
2184
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef_xml)
2185
    resp = resp.forms[0].submit()
2186
    assert FormDef.count() == 2
2187

  
2188
    formdef2 = FormDef.get(2)
2189
    assert formdef2.url_name == 'form-title-1'
2190
    # fields are imported with original ids
2191
    for i, field in enumerate(formdef.fields):
2192
        field2 = formdef2.fields[i]
2193
        assert (field.id, field.label, field.type) == (field2.id, field2.label, field2.type)
2194

  
2195
    # modify imported formdef, then overwrite original formdef with it
2196
    formdef2.fields.insert(2, fields.StringField(id='2', label='field 4', type='string'))
2197
    formdef2.fields.insert(3, fields.DateField(id='3', label='field 5', type='date'))
2198
    formdef2.fields.append(fields.ItemField(id='5', label='field 6', type='item'))
2199
    formdef2.store()
2200
    formdef2_xml = ET.tostring(formdef2.export_to_xml(include_id=True))
2201
    resp = app.get('/backoffice/forms/%s/' % formdef.id)
2202
    resp = resp.click(href='overwrite')
2203
    resp.forms[0]['file'] = Upload('formdef.wcs', formdef2_xml)
2204
    resp = resp.forms[0].submit()
2205
    assert 'Overwrite - Summary of changes' in resp.text
2206
    resp = resp.forms[0].submit()
2207
    formdef_overwrited = FormDef.get(formdef.id)
2208
    for i, field in enumerate(formdef2.fields):
2209
        field_ow = formdef_overwrited.fields[i]
2210
        assert (field.id, field.label, field.type) == (field_ow.id, field_ow.label, field_ow.type)
2211

  
2212

  
2213
def test_form_comment_with_error_in_wscall(http_requests, pub):
2214
    create_superuser(pub)
2215
    NamedWsCall.wipe()
2216

  
2217
    wscall = NamedWsCall(name='xxx')
2218
    wscall.description = 'description'
2219
    wscall.request = {
2220
            'url': 'http://remote.example.net/404',
2221
            'request_signature_key': 'xxx',
2222
            'qs_data': {'a': 'b'},
2223
            'method': 'POST',
2224
            'post_data': {'c': 'd'},
2225
    }
2226
    wscall.store()
2227

  
2228
    FormDef.wipe()
2229
    formdef = FormDef()
2230
    formdef.name = 'form title'
2231
    formdef.fields = [fields.CommentField(id='1',
2232
        label='x [webservice.xxx.foobar] x', type='comment')]
2233
    formdef.store()
2234

  
2235
    app = login(get_app(pub))
2236
    resp = app.get('/backoffice/forms/%s/' % formdef.id)
2237
    assert 'x [webservice.xxx.foobar] x' in resp.text
0
-