|
1 | 1 | # -*- coding: utf-8 -*- |
2 | 2 | """Test views.""" |
3 | 3 |
|
| 4 | +from AccessControl import Unauthorized |
| 5 | +from collective.dms.mailcontent.dmsmail import internalReferenceOutgoingMailDefaultValue |
| 6 | +from collective.iconifiedcategory.utils import calculate_category_id |
4 | 7 | from collective.MockMailHost.MockMailHost import MockMailHost |
5 | 8 | from datetime import datetime |
| 9 | +from HTMLParser import HTMLParser |
6 | 10 | from imio.dms.mail import PERIODS |
| 11 | +from imio.dms.mail import PRODUCT_DIR |
7 | 12 | from imio.dms.mail.browser.views import parse_query |
| 13 | +from imio.dms.mail.browser.views import SigningAnnotationInfoView |
| 14 | +from imio.dms.mail.interfaces import IOMApproval |
8 | 15 | from imio.dms.mail.testing import change_user |
9 | 16 | from imio.dms.mail.testing import DMSMAIL_INTEGRATION_TESTING |
| 17 | +from imio.dms.mail.utils import DummyView |
| 18 | +from imio.dms.mail.utils import sub_create |
| 19 | +from imio.esign.config import set_registry_file_url |
| 20 | +from imio.esign.utils import get_session_annotation |
10 | 21 | from imio.helpers.content import get_object |
11 | 22 | from imio.helpers.content import richtextval |
12 | 23 | from imio.helpers.emailer import get_mail_host |
| 24 | +from imio.helpers.test_helpers import ImioTestHelpers |
13 | 25 | from plone import api |
| 26 | +from plone.app.testing import login |
| 27 | +from plone.dexterity.utils import createContentInContainer |
| 28 | +from plone.namedfile.file import NamedBlobFile |
| 29 | +from Products.CMFPlone.utils import safe_unicode |
| 30 | +from z3c.relationfield import RelationValue |
| 31 | +from zope.component import getUtility |
14 | 32 | from zope.i18n import translate |
| 33 | +from zope.intid import IIntIds |
15 | 34 |
|
16 | 35 | import json |
17 | 36 | import unittest |
@@ -297,3 +316,286 @@ def test_call(self): |
297 | 316 | self.assertIn(u">012/34.56.79<", rendered) |
298 | 317 | self.assertIn(u">Rue Léon Morel, 1<", rendered) |
299 | 318 | self.assertIn(u">5032 Isnes<", rendered) |
| 319 | + |
| 320 | + |
| 321 | +class TestSigningAnnotationInfoView(unittest.TestCase, ImioTestHelpers): |
| 322 | + """Test SigningAnnotationInfoView""" |
| 323 | + |
| 324 | + layer = DMSMAIL_INTEGRATION_TESTING |
| 325 | + |
| 326 | + def setUp(self): |
| 327 | + self.portal = self.layer["portal"] |
| 328 | + change_user(self.portal) |
| 329 | + self.om1 = get_object(oid="reponse1", ptype="dmsoutgoingmail") |
| 330 | + self.view = SigningAnnotationInfoView(self.om1, self.portal.REQUEST) |
| 331 | + self.pf = self.portal["contacts"]["personnel-folder"] |
| 332 | + self.pgof = self.portal["contacts"]["plonegroup-organization"] |
| 333 | + |
| 334 | + def _setup_esign_omail(self): |
| 335 | + """Create a new outgoing mail with esign enabled and two files.""" |
| 336 | + login(self.layer["app"], "admin") |
| 337 | + self.portal.portal_setup.runImportStepFromProfile( |
| 338 | + "profile-imio.dms.mail:singles", "imiodmsmail-activate-esigning", run_dependencies=False |
| 339 | + ) |
| 340 | + set_registry_file_url("https://downloads.files.com") |
| 341 | + intids = getUtility(IIntIds) |
| 342 | + params = { |
| 343 | + "title": u"Courrier test esign", |
| 344 | + "internal_reference_no": internalReferenceOutgoingMailDefaultValue( |
| 345 | + DummyView(self.portal, self.portal.REQUEST) |
| 346 | + ), |
| 347 | + "mail_type": "courrier", |
| 348 | + "treating_groups": self.pgof["direction-generale"]["grh"].UID(), |
| 349 | + "recipients": [RelationValue(intids.getId(self.portal["contacts"]["jeancourant"]))], |
| 350 | + "assigned_user": "agent", |
| 351 | + "sender": self.portal["contacts"]["jeancourant"]["agent-electrabel"].UID(), |
| 352 | + "send_modes": u"post", |
| 353 | + "signers": [ |
| 354 | + { |
| 355 | + "number": 1, |
| 356 | + "signer": self.pf["dirg"]["directeur-general"].UID(), |
| 357 | + "approvings": [u"_themself_"], |
| 358 | + "editor": True, |
| 359 | + }, |
| 360 | + { |
| 361 | + "number": 2, |
| 362 | + "signer": self.pf["bourgmestre"]["bourgmestre"].UID(), |
| 363 | + "approvings": [u"_themself_"], |
| 364 | + "editor": False, |
| 365 | + }, |
| 366 | + ], |
| 367 | + "esign": True, |
| 368 | + } |
| 369 | + omail = sub_create(self.portal["outgoing-mail"], "dmsoutgoingmail", datetime.now(), "om-esign", **params) |
| 370 | + filename = u"Réponse salle.odt" |
| 371 | + ct = self.portal["annexes_types"]["outgoing_dms_files"]["outgoing-dms-file"] |
| 372 | + files = [] |
| 373 | + for i in range(2): |
| 374 | + with open("%s/batchimport/toprocess/outgoing-mail/%s" % (PRODUCT_DIR, filename), "rb") as fo: |
| 375 | + file_object = NamedBlobFile(fo.read(), filename=filename) |
| 376 | + files.append( |
| 377 | + createContentInContainer( |
| 378 | + omail, |
| 379 | + "dmsommainfile", |
| 380 | + id="file%s" % i, |
| 381 | + scan_id="012999900000601", |
| 382 | + file=file_object, |
| 383 | + content_category=calculate_category_id(ct), |
| 384 | + ) |
| 385 | + ) |
| 386 | + return omail, files, IOMApproval(omail) |
| 387 | + |
| 388 | + def _approve_all_files(self, omail, files, approval): |
| 389 | + """Approve all files through the full two-signer approval process.""" |
| 390 | + pw = self.portal.portal_workflow |
| 391 | + pw.doActionFor(omail, "propose_to_approve") |
| 392 | + approval.approve_file(files[0], "dirg", transition="propose_to_be_signed") |
| 393 | + approval.approve_file(files[1], "dirg", transition="propose_to_be_signed") |
| 394 | + approval.approve_file(files[1], "bourgmestre", transition="propose_to_be_signed") |
| 395 | + approval.approve_file(files[0], "bourgmestre", transition="propose_to_be_signed") |
| 396 | + |
| 397 | + def test_call(self): |
| 398 | + with self.assertRaises(Unauthorized): |
| 399 | + self.view() |
| 400 | + login(self.portal.aq_parent, "admin") |
| 401 | + self.assertIsInstance(self.view(), basestring) |
| 402 | + |
| 403 | + def test_render_value(self): |
| 404 | + # Dict |
| 405 | + self.assertEqual(self.view._render_value({}), u"{}") |
| 406 | + self.assertEqual( |
| 407 | + self.view._render_value({"key": "val"}), |
| 408 | + u"{\n 'key': 'val',\n}", |
| 409 | + ) |
| 410 | + |
| 411 | + # Indentation: nested value increases indent level |
| 412 | + self.assertEqual( |
| 413 | + self.view._render_value({"key": ["a"]}), |
| 414 | + u"{\n 'key': [\n 'a',\n ],\n}", |
| 415 | + ) |
| 416 | + |
| 417 | + # List |
| 418 | + self.assertEqual(self.view._render_value([]), u"[]") |
| 419 | + self.assertEqual( |
| 420 | + self.view._render_value(["a", "b"]), |
| 421 | + u"[\n 'a',\n 'b',\n]", |
| 422 | + ) |
| 423 | + |
| 424 | + # Tuple |
| 425 | + self.assertEqual(self.view._render_value(()), u"[]") |
| 426 | + |
| 427 | + # String |
| 428 | + self.assertEqual(self.view._render_value(u"hello"), u"u'hello'") |
| 429 | + |
| 430 | + # UID not found |
| 431 | + fake_uid = u"a" * 32 |
| 432 | + self.assertEqual( |
| 433 | + self.view._render_value(fake_uid), |
| 434 | + u"<span title='not found'>aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</span>", |
| 435 | + ) |
| 436 | + |
| 437 | + # UID found |
| 438 | + self.assertEqual( |
| 439 | + self.view._render_value(self.om1.UID()), |
| 440 | + u"<a href='http://nohost/plone/outgoing-mail/202608/reponse1' title='/plone/outgoing-mail/202608/reponse1'>R\xe9ponse 1</a>", |
| 441 | + ) |
| 442 | + |
| 443 | + def test_uid_to_link(self): |
| 444 | + uid = self.om1.UID() |
| 445 | + result = self.view._uid_to_link(uid) |
| 446 | + self.assertIn(u"<a href=", result) |
| 447 | + self.assertIn(self.om1.absolute_url(), result) |
| 448 | + |
| 449 | + result = self.view._uid_to_link(u"a" * 32) |
| 450 | + self.assertIn(u"<span", result) |
| 451 | + self.assertIn(u"not found", result) |
| 452 | + |
| 453 | + def test_approval_and_esign_sessions(self): |
| 454 | + """Test approval_annot_html and esign_session_html after a true approval process.""" |
| 455 | + omail, files, approval = self._setup_esign_omail() |
| 456 | + self._approve_all_files(omail, files, approval) |
| 457 | + |
| 458 | + view = SigningAnnotationInfoView(omail, self.portal.REQUEST) |
| 459 | + |
| 460 | + # approval annot html |
| 461 | + self.assertEqual( |
| 462 | + HTMLParser().unescape(view.approval_annot_html), |
| 463 | + u"""{{ |
| 464 | + 'approval': [ |
| 465 | + [ |
| 466 | + {{ |
| 467 | + 'approved_by': 'dirg', |
| 468 | + 'approved_on': {}, |
| 469 | + 'status': 'a', |
| 470 | + }}, |
| 471 | + {{ |
| 472 | + 'approved_by': 'dirg', |
| 473 | + 'approved_on': {}, |
| 474 | + 'status': 'a', |
| 475 | + }}, |
| 476 | + ], |
| 477 | + [ |
| 478 | + {{ |
| 479 | + 'approved_by': 'bourgmestre', |
| 480 | + 'approved_on': {}, |
| 481 | + 'status': 'a', |
| 482 | + }}, |
| 483 | + {{ |
| 484 | + 'approved_by': 'bourgmestre', |
| 485 | + 'approved_on': {}, |
| 486 | + 'status': 'a', |
| 487 | + }}, |
| 488 | + ], |
| 489 | + ], |
| 490 | + 'approvers': [ |
| 491 | + [ |
| 492 | + 'dirg', |
| 493 | + ], |
| 494 | + [ |
| 495 | + 'bourgmestre', |
| 496 | + ], |
| 497 | + ], |
| 498 | + 'current_nb': -1, |
| 499 | + 'editors': [ |
| 500 | + True, |
| 501 | + False, |
| 502 | + ], |
| 503 | + 'files': [ |
| 504 | + <a href='http://nohost/plone/outgoing-mail/202608/om-esign/file0' title='/plone/outgoing-mail/202608/om-esign/file0'>Réponse salle.odt</a>, |
| 505 | + <a href='http://nohost/plone/outgoing-mail/202608/om-esign/file1' title='/plone/outgoing-mail/202608/om-esign/file1'>Réponse salle.odt</a>, |
| 506 | + ], |
| 507 | + 'pdf_files': [ |
| 508 | + [ |
| 509 | + <a href='http://nohost/plone/outgoing-mail/202608/om-esign/reponse-salle.pdf' title='/plone/outgoing-mail/202608/om-esign/reponse-salle.pdf'>Réponse salle.pdf</a>, |
| 510 | + ], |
| 511 | + [ |
| 512 | + <a href='http://nohost/plone/outgoing-mail/202608/om-esign/reponse-salle-1.pdf' title='/plone/outgoing-mail/202608/om-esign/reponse-salle-1.pdf'>Réponse salle.pdf</a>, |
| 513 | + ], |
| 514 | + ], |
| 515 | + 'session_ids': [ |
| 516 | + 0, |
| 517 | + ], |
| 518 | + 'signers': [ |
| 519 | + [ |
| 520 | + 'dirg', |
| 521 | + u'Maxime DG', |
| 522 | + u'Directeur G\\xe9n\\xe9ral', |
| 523 | + ], |
| 524 | + [ |
| 525 | + 'bourgmestre', |
| 526 | + u'Paul BM', |
| 527 | + u'Bourgmestre', |
| 528 | + ], |
| 529 | + ], |
| 530 | +}}""".format( |
| 531 | + repr(approval.annot["approval"][0][0]["approved_on"]), |
| 532 | + repr(approval.annot["approval"][0][1]["approved_on"]), |
| 533 | + repr(approval.annot["approval"][1][0]["approved_on"]), |
| 534 | + repr(approval.annot["approval"][1][1]["approved_on"]), |
| 535 | + ), |
| 536 | + ) |
| 537 | + |
| 538 | + # esign essions property |
| 539 | + esign_sessions = view.esign_sessions |
| 540 | + self.assertEqual(len(esign_sessions), 1) |
| 541 | + esign_session = esign_sessions[0] |
| 542 | + self.assertIsInstance(esign_session, tuple) |
| 543 | + self.assertEqual(esign_session[0], 0) |
| 544 | + |
| 545 | + # esign session html |
| 546 | + self.assertEqual( |
| 547 | + HTMLParser().unescape(view.esign_session_html(esign_session[1])), |
| 548 | + u"""{{ |
| 549 | + 'acroform': True, |
| 550 | + 'client_id': '0129999', |
| 551 | + 'discriminators': [], |
| 552 | + 'files': [ |
| 553 | + {{ |
| 554 | + 'context_uid': <a href='http://nohost/plone/outgoing-mail/{folder_name}/om-esign' title='/plone/outgoing-mail/{folder_name}/om-esign'>Courrier test esign</a>, |
| 555 | + 'filename': u'R\\xe9ponse salle__{pdf1_uid}.pdf', |
| 556 | + 'scan_id': '012999900000601', |
| 557 | + 'status': '', |
| 558 | + 'title': u'R\\xe9ponse salle.pdf', |
| 559 | + 'uid': <a href='http://nohost/plone/outgoing-mail/{folder_name}/om-esign/reponse-salle.pdf' title='/plone/outgoing-mail/{folder_name}/om-esign/reponse-salle.pdf'>Réponse salle.pdf</a>, |
| 560 | + }}, |
| 561 | + {{ |
| 562 | + 'context_uid': <a href='http://nohost/plone/outgoing-mail/{folder_name}/om-esign' title='/plone/outgoing-mail/{folder_name}/om-esign'>Courrier test esign</a>, |
| 563 | + 'filename': u'R\\xe9ponse salle__{pdf2_uid}.pdf', |
| 564 | + 'scan_id': '012999900000601', |
| 565 | + 'status': '', |
| 566 | + 'title': u'R\\xe9ponse salle.pdf', |
| 567 | + 'uid': <a href='http://nohost/plone/outgoing-mail/{folder_name}/om-esign/reponse-salle-1.pdf' title='/plone/outgoing-mail/{folder_name}/om-esign/reponse-salle-1.pdf'>Réponse salle.pdf</a>, |
| 568 | + }}, |
| 569 | + ], |
| 570 | + 'last_update': {last_update}, |
| 571 | + 'returns': [], |
| 572 | + 'seal': False, |
| 573 | + 'sign_id': '012999900000', |
| 574 | + 'sign_url': None, |
| 575 | + 'signers': [ |
| 576 | + {{ |
| 577 | + 'email': 'dirg@macommune.be', |
| 578 | + 'fullname': u'Maxime DG', |
| 579 | + 'position': u'Directeur G\\xe9n\\xe9ral', |
| 580 | + 'status': '', |
| 581 | + 'userid': 'dirg', |
| 582 | + }}, |
| 583 | + {{ |
| 584 | + 'email': 'bourgmestre@macommune.be', |
| 585 | + 'fullname': u'Paul BM', |
| 586 | + 'position': u'Bourgmestre', |
| 587 | + 'status': '', |
| 588 | + 'userid': 'bourgmestre', |
| 589 | + }}, |
| 590 | + ], |
| 591 | + 'size': 54660, |
| 592 | + 'state': 'draft', |
| 593 | + 'title': u'[ia.docs] Session 012999900000', |
| 594 | + 'watchers': [], |
| 595 | +}}""".format( |
| 596 | + pdf1_uid=api.content.get(omail.absolute_url_path() + "/reponse-salle.pdf").UID(), |
| 597 | + pdf2_uid=api.content.get(omail.absolute_url_path() + "/reponse-salle-1.pdf").UID(), |
| 598 | + folder_name=omail.__parent__.__name__, |
| 599 | + last_update=repr(get_session_annotation()["sessions"][0]["last_update"]), |
| 600 | + ), |
| 601 | + ) |
0 commit comments