def test_can_export_zip(self, browser): dossier = create(Builder('dossier').titled(u'Dossier')) task = create( Builder("task").within(dossier).titled(u'Aufgabe').having( text='Text blabla', task_type='comment', deadline=datetime(2010, 1, 1), issuer=TEST_USER_ID, responsible=TEST_USER_ID, )) document = create( Builder('document').titled(u'Some document').within( task).with_dummy_content()) data = { 'zip_selected:method': 1, 'paths:list': ['/'.join(document.getPhysicalPath())] } browser.login().open(task, view='zip_export') zipfile = ZipFile(StringIO(browser.contents), 'r') self.assertEquals([document.file.filename], zipfile.namelist()) browser.open(task, data=data) zipfile = ZipFile(StringIO(browser.contents), 'r') self.assertEquals([document.file.filename], zipfile.namelist())
def test_can_export_zip(self, browser): dossier = create(Builder('dossier').titled(u'Dossier')) task = create(Builder("task") .within(dossier) .titled(u'Aufgabe') .having(text='Text blabla', task_type='comment', deadline=datetime(2010, 1, 1), issuer=TEST_USER_ID, responsible=TEST_USER_ID,)) document = create(Builder('document') .titled(u'Some document') .within(task) .with_dummy_content()) data = {'zip_selected:method': 1, 'paths:list': ['/'.join(document.getPhysicalPath())]} browser.login().open(task, view='zip_export') zipfile = ZipFile(StringIO(browser.contents), 'r') self.assertEquals([document.file.filename], zipfile.namelist()) browser.open(task, data=data) zipfile = ZipFile(StringIO(browser.contents), 'r') self.assertEquals([document.file.filename], zipfile.namelist())
class ZipGenerator(object): """ Generates the zip. Acts as context manager to ensure that all temporary files are deleted after usage. """ def __init__(self): self.empty = True def __enter__(self): self.tmp_file = NamedTemporaryFile(prefix="plone_zipexport_") self.tmp_file.__enter__() self.zip_file = ZipFile(self.tmp_file.name, "w", allowZip64=True) self.zip_file.__enter__() return self def __exit__(self, exc_type, exc_value, traceback): self.zip_file.__exit__(exc_type, exc_value, traceback) self.tmp_file.__exit__(exc_type, exc_value, traceback) def add_file(self, file_path, file_pointer): # paths in zipfile do not have a / at the root file_path = file_path.strip('/') file_path = self.generate_unique_filepath(file_path) try: self.zip_file.writefile(file_pointer, file_path) except RuntimeError: raise StandardError("ZipFile already generated/closed. " "Please add all files before generating.") self.empty = False def generate_unique_filepath(self, file_path): if file_path not in self.zip_file.namelist(): return file_path path, name = os.path.split(file_path) name, ext = os.path.splitext(name) for i in xrange(2, sys.maxint): new_filename = os.path.join(path, '%s (%d)%s' % (name, i, ext)) if new_filename not in self.zip_file.namelist(): return new_filename @property def is_empty(self): return self.empty def generate(self): if self.tmp_file is None: raise StandardError( "Please use ZipGenerator as a context manager.") self.zip_file.close() return self.tmp_file
def test_zip_export_generate_protocol_if_outdated(self, browser): self.login(self.committee_responsible, browser) browser.open(self.meeting, view='export-meeting-zip') zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertIn('Protocol-9. Sitzung der Rechnungsprufungskommission.docx', zip_file.namelist()) browser.open(self.meeting, view='edit-meeting') browser.fill({'Title': 'New Meeting Title'}).save() browser.open(self.meeting, view='export-meeting-zip') zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertIn('Agendaitem list-New Meeting Title.docx', zip_file.namelist())
def test_zip_export_excerpt_is_not_exported(self, browser): excerpt = create(Builder('document') .titled(u'Excerpt') .attach_file_containing(u"excerpt", u"excerpt.docx") .within(self.dossier)) generated_excerpt = create(Builder('generated_excerpt') .for_document(excerpt)) # restore session by refreshing instance generated_excerpt = GeneratedExcerpt.get(generated_excerpt.document_id) meeting = create( Builder('meeting') .having(committee=self.committee.load_model(), start=self.localized_datetime(2013, 1, 1, 8, 30), end=self.localized_datetime(2013, 1, 1, 10, 30), location='There', presidency=self.hugo, participants=[self.peter, self.hans, self.roland], secretary=self.sile, excerpt_documents=[generated_excerpt], ) .link_with(self.meeting_dossier)) browser.login().open(meeting.get_url(view='zipexport')) zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertNotIn('excerpt.docx', zip_file.namelist())
def test_directory_tree_gets_builded_correctly_in_zip(self): self.browser.open("%s/zip_export" % self.superfolder.absolute_url()) zipfile = ZipFile(StringIO(self.browser.contents), 'r') self.assertEquals([ 'SUPERFILE', 'Folder/testdata.txt', 'Folder/moretest.data', u'Empty f\xf6lder/' ], zipfile.namelist())
def test_zip_export_agenda_items_list(self, browser): self.proposal_a = create( Builder('proposal') .titled(u'Proposal A') .within(self.dossier) .as_submitted() .having(committee=self.committee.load_model()) ) meeting = create( Builder('meeting') .having(committee=self.committee.load_model(), start=self.localized_datetime(2013, 1, 1, 8, 30), end=self.localized_datetime(2013, 1, 1, 10, 30), location='There', presidency=self.hugo, participants=[self.peter, self.hans, self.roland], secretary=self.sile) .scheduled_proposals([self.proposal_a, ]) .link_with(self.meeting_dossier)) browser.login().open(meeting.get_url(view='zipexport')) zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertIn('Agendaitem list-community-meeting.docx', zip_file.namelist())
def test_zip_export_generate_protocol_if_there_is_none(self, browser): self.login(self.committee_responsible, browser) browser.open(self.meeting, view='export-meeting-zip') zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertFalse(self.meeting.model.has_protocol_document()) self.assertIn('Protocol-9. Sitzung der Rechnungsprufungskommission.docx', zip_file.namelist())
def test_zip_export_agenda_items_list(self, browser): self.login(self.committee_responsible, browser) browser.open(self.meeting, view='export-meeting-zip') zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertIn( 'Agendaitem list-9. Sitzung der Rechnungsprufungskommission.docx', zip_file.namelist())
def test_filename_conflicts_are_avoided_by_prefixing_attachment_number(self, browser): set_preferred_language(self.portal.REQUEST, 'de-ch') browser.append_request_header('Accept-Language', 'de-ch') self.login(self.committee_responsible, browser) documents = [ create(Builder('document') .within(self.dossier) .titled('The same title') .with_dummy_content()) for i in range(3)] proposal, submitted_proposal = create(Builder('proposal') .within(self.dossier) .having(committee=self.committee.load_model()) .with_submitted() .relate_to(*documents)) self.schedule_proposal(self.meeting, submitted_proposal) browser.open(self.meeting, view='export-meeting-zip') self.assertEquals('application/zip', browser.contenttype) zip_file = ZipFile(StringIO(browser.contents), 'r') meeting_json = json.loads(zip_file.read('meeting.json')) expected_file_names = [u'Traktandum 1/Beilage/1_The same title.doc', u'Traktandum 1/Beilage/2_The same title.doc', u'Traktandum 1/Beilage/3_The same title.doc'] json_file_names = [attachment.get("file") for attachment in meeting_json["meetings"][0]['agenda_items'][0]["attachments"]] self.assertItemsEqual(expected_file_names, json_file_names) expected_file_names.extend(['meeting.json', 'Traktandum 1/Fooo.docx']) file_names = zip_file.namelist() self.assertItemsEqual(expected_file_names, file_names)
def test_zip_export_generated_protocol(self, browser): meeting = create( Builder('meeting') .having(committee=self.committee.load_model(), start=self.localized_datetime(2013, 1, 1, 8, 30), end=self.localized_datetime(2013, 1, 1, 10, 30), location='There', presidency=self.hugo, participants=[self.peter, self.hans, self.roland], secretary=self.sile) .link_with(self.meeting_dossier)) # Add new protocol browser.login().visit(meeting.get_url()) browser.css('a[href*="@@generate_protocol"]').first.click() browser.open(meeting.get_url(view='zipexport')) zip_file = ZipFile(StringIO(browser.contents), 'r') meeting = Meeting.query.get(meeting.meeting_id) self.assertTrue(meeting.has_protocol_document()) self.assertIn('Protocol-Community meeting.docx', zip_file.namelist())
def test_zip_export_agenda_items_attachments(self, browser): self.login(self.committee_responsible, browser) self.schedule_proposal(self.meeting, self.submitted_proposal) browser.open(self.meeting, view='export-meeting-zip') zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertIn( '1. Vertragsentwurf fur weitere Bearbeitung bewilligen/Vertragsentwurf.docx', zip_file.namelist())
def test_export_proposal_word_documents(self, browser): self.login(self.committee_responsible, browser) self.schedule_proposal(self.meeting, self.submitted_word_proposal) browser.open(self.meeting, view='export-meeting-zip') zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertIn( '1. Anderungen am Personalreglement/Anderungen am Personalreglement.docx', zip_file.namelist())
def test_zip_selected_files(self): postdata = "zip_selected:method=1&paths:list=%s&paths:list=%s" % ( '/'.join(self.folderfile.getPhysicalPath()), '/'.join( self.folderfile2.getPhysicalPath())) self.browser.open(self.superfolder.absolute_url(), postdata) zipfile = ZipFile(StringIO(self.browser.contents), 'r') self.assertEquals(['testdata.txt', 'moretest.data'], zipfile.namelist())
def test_zip_selected_files(self): postdata = "zip_selected:method=1&paths:list=%s&paths:list=%s" % ( '/'.join(self.folderfile.getPhysicalPath()), '/'.join(self.folderfile2.getPhysicalPath())) self.browser.open(self.superfolder.absolute_url(), postdata) zipfile = ZipFile(StringIO(self.browser.contents), 'r') self.assertEquals( ['testdata.txt', 'moretest.data'], zipfile.namelist())
def test_zip_export_includes_generated_protocol(self, browser): self.login(self.committee_responsible, browser) browser.open(GenerateProtocol.url_for(self.meeting.model)) self.assertTrue(self.meeting.model.has_protocol_document()) browser.open(self.meeting, view='export-meeting-zip') zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertIn('Protocol-9. Sitzung der Rechnungsprufungskommission.docx', zip_file.namelist())
def test_can_export_zip(self, browser): self.login(self.regular_user, browser=browser) browser.open(self.task, view='zip_export') zipfile = ZipFile(StringIO(browser.contents), 'r') self.assertEquals( [u'Task - Rechtliche Grundlagen in Vertragsentwurf \xdcberpr\xfcfen/', 'Feedback zum Vertragsentwurf.docx'], zipfile.namelist()) data = {'zip_selected:method': 1, 'paths:list': ['/'.join(self.taskdocument.getPhysicalPath())]} browser.open(self.task, data=data) zipfile = ZipFile(StringIO(browser.contents), 'r') self.assertEquals( [self.taskdocument.file.filename], zipfile.namelist())
def test_export_proposal_word_documents(self, browser): browser.append_request_header('Accept-Language', 'de-ch') self.login(self.committee_responsible, browser) self.schedule_proposal(self.meeting, self.submitted_proposal) browser.open(self.meeting, view='export-meeting-zip') zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertIn( 'Traktandum 1/Vertraege.docx', zip_file.namelist())
def test_exported_meeting_contains_json(self, browser): self.login(self.committee_responsible, browser) browser.open(self.meeting, view='export-meeting-zip') self.assertEquals('application/zip', browser.contenttype) zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertEquals( ['meeting.json'], zip_file.namelist())
def test_can_export_zip(self, browser): self.login(self.regular_user, browser=browser) browser.open(self.task, view='zip_export') zipfile = ZipFile(StringIO(browser.contents), 'r') self.assertEquals([ u'Task - Rechtliche Grundlagen in Vertragsentwurf \xdcberpr\xfcfen/', 'feedback-zum-vertragsentwurf.docx' ], zipfile.namelist()) data = { 'zip_selected:method': 1, 'paths:list': ['/'.join(self.taskdocument.getPhysicalPath())] } browser.open(self.task, data=data) zipfile = ZipFile(StringIO(browser.contents), 'r') self.assertEquals([self.taskdocument.file.filename], zipfile.namelist())
def test_exclude_empty_folders_if_setting_is_deactivated(self): registry = getUtility(IRegistry) registry.forInterface(IZipExportSettings).include_empty_folders = False transaction.commit() self.browser.open("%s/zip_export" % self.superfolder.absolute_url()) zipfile = ZipFile(StringIO(self.browser.contents), 'r') self.assertEquals( ['SUPERFILE', 'Folder/testdata.txt', 'Folder/moretest.data'], zipfile.namelist())
def test_exported_meeting_contains_json(self, browser): self.login(self.committee_responsible, browser) browser.open(self.meeting, view='export-meeting-zip') self.assertEquals('application/zip', browser.contenttype) zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertEquals( ['Protocol-9. Sitzung der Rechnungsprufungskommission.docx', 'Agendaitem list-9. Sitzung der Rechnungsprufungskommission.docx', 'meeting.json'], zip_file.namelist())
def test_zip_selected_files(self, browser): self.login(self.regular_user, browser=browser) docs = [self.document, self.subdocument] data = {'zip_selected:method': 1} data.update(self.make_path_param(*docs)) # /plone/ordnungssystem/... browser.open(self.dossier, data=data) zipfile = ZipFile(StringIO(browser.contents), 'r') self.assertEquals([doc.file.filename for doc in docs], zipfile.namelist())
def test_excerpt_is_not_exported(self, browser): browser.append_request_header('Accept-Language', 'de-ch') self.login(self.committee_responsible, browser) agenda_item = self.schedule_proposal(self.meeting, self.submitted_proposal) agenda_item.decide() agenda_item.generate_excerpt(title='Ahoi McEnroe!') browser.open(self.meeting, view='export-meeting-zip') zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertItemsEqual( ['Traktandum 1/Beilage/1_Vertraegsentwurf.docx', 'Traktandum 1/Vertraege.docx', 'meeting.json'], zip_file.namelist())
def test_excerpt_is_not_exported(self, browser): self.login(self.committee_responsible, browser) agenda_item = self.schedule_proposal(self.meeting, self.submitted_word_proposal) agenda_item.decide() agenda_item.generate_excerpt(title='Ahoi McEnroe!') browser.open(self.meeting, view='export-meeting-zip') zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertEquals( ['Protocol-9. Sitzung der Rechnungsprufungskommission.docx', '1. Anderungen am Personalreglement/Vertragsentwurf.docx', '1. Anderungen am Personalreglement/Anderungen am Personalreglement.docx', 'Agendaitem list-9. Sitzung der Rechnungsprufungskommission.docx', 'meeting.json'], zip_file.namelist())
def test_zip_export_skips_agenda_items_attachments_without_file(self, browser): browser.append_request_header('Accept-Language', 'de-ch') self.login(self.committee_responsible, browser) self.proposal.submit_additional_document(self.empty_document) self.proposal.submit_additional_document(self.subdocument) self.schedule_proposal(self.meeting, self.submitted_proposal) browser.open(self.meeting, view='export-meeting-zip') zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertItemsEqual( ['Traktandum 1/Vertraege.docx', 'Traktandum 1/Beilage/1_Vertraegsentwurf.docx', 'Traktandum 1/Beilage/2_Uebersicht der Vertraege von 2016.xlsx', 'meeting.json'], zip_file.namelist())
def test_zip_export_generate_protocol_if_outdated(self, browser): protocol = create(Builder('document') .titled(u'Protocol') .attach_file_containing(u"protocol", u"protocol.docx") .within(self.dossier)) generated_protocol = create(Builder('generated_protocol') .for_document(protocol)) meeting = create( Builder('meeting') .having(committee=self.committee.load_model(), start=self.localized_datetime(2013, 1, 1, 8, 30), end=self.localized_datetime(2013, 1, 1, 10, 30), location='There', presidency=self.hugo, participants=[self.peter, self.hans, self.roland], secretary=self.sile, protocol_document=generated_protocol) .link_with(self.meeting_dossier)) # Do a modification browser.login().open(meeting.get_url(view='protocol')) browser.fill({'Title': u'This is the modified different title than ' u'before'}).submit() browser.open(meeting.get_url(view='zipexport')) zip_file = ZipFile(StringIO(browser.contents), 'r') self.assertNotEquals(protocol.file.filename, zip_file.filelist[0].filename) self.assertNotEquals(protocol.file.getSize(), zip_file.filelist[0].file_size) self.assertIn('Protocol-This is the modified different title than' ' before.docx', zip_file.namelist())
class ZipGenerator(object): """ Generates the zip. Acts as context manager to ensure that all temporary files are deleted after usage. """ def __init__(self, path_normalizer=normalize_path): self.empty = True self.path_normalizer = path_normalizer def __enter__(self): self.tmp_file = NamedTemporaryFile(prefix="plone_zipexport_") self.tmp_file.__enter__() self.zip_file = ZipFile(self.tmp_file.name, "w", allowZip64=True) self.zip_file.__enter__() return self def __exit__(self, exc_type, exc_value, traceback): self.zip_file.__exit__(exc_type, exc_value, traceback) self.tmp_file.__exit__(exc_type, exc_value, traceback) def add_folder(self, folder_path): folder_path = safe_unicode(folder_path) # Always add a slash at the end of the path folder_path = u'{}/'.format(folder_path.strip('/')) # Creates a new empty folder self.zip_file.writestr(zipfile.ZipInfo(folder_path), '') self.empty = False def add_file(self, file_path, file_pointer): if self.path_normalizer is not None: file_path = self.path_normalizer(file_path) else: file_path = safe_unicode(file_path) # paths in zipfile do not have a / at the root file_path = file_path.strip('/') file_path = self.generate_unique_filepath(file_path) if not self.check_disk_has_space_for_file(file_pointer): raise NotEnoughSpaceOnDiskException() try: self.zip_file.writefile(file_pointer, file_path) except RuntimeError: raise StandardError("ZipFile already generated/closed. " "Please add all files before generating.") self.empty = False def generate_unique_filepath(self, file_path): if file_path not in self.zip_file.namelist(): return file_path path, name = os.path.split(file_path) name, ext = os.path.splitext(name) for i in xrange(2, sys.maxint): new_filename = os.path.join(path, '%s (%d)%s' % (name, i, ext)) if new_filename not in self.zip_file.namelist(): return new_filename def check_disk_has_space_for_file(self, file_d): disk_stat = os.statvfs(self.tmp_file.name) bytes_free = disk_stat.f_frsize * disk_stat.f_bavail position = file_d.tell() file_d.seek(0, os.SEEK_END) file_size = file_d.tell() - position file_d.seek(position) return file_size < bytes_free @property def is_empty(self): return self.empty def generate(self): if self.tmp_file is None: raise StandardError( "Please use ZipGenerator as a context manager.") self.zip_file.close() return self.tmp_file
def test_zip_multiple_files_in_folder(self): self.browser.open("%s/zip_export" % self.folder.absolute_url()) zipfile = ZipFile(StringIO(self.browser.contents), 'r') self.assertEquals( ['testdata.txt', 'moretest.data'], zipfile.namelist())
def test_exported_meeting_json_has_correct_file_names(self, browser): self.login(self.committee_responsible, browser) self.schedule_paragraph(self.meeting, u'A Gesch\xfcfte') with freeze(localized_datetime(2017, 12, 13)): self.schedule_ad_hoc( self.meeting, u'Ad-hoc Traktand\xfem' ).decide() self.schedule_proposal( self.meeting, self.submitted_word_proposal ).decide() with freeze(localized_datetime(2017, 12, 14)): self.meeting.model.close() browser.open(self.meeting, view='export-meeting-zip') self.assertEquals('application/zip', browser.contenttype) zip_file = ZipFile(StringIO(browser.contents), 'r') meeting_json = json.loads(zip_file.read('meeting.json')) # the protocol is generated during the tests and its checksum cannot # be predicted meeting_json['meetings'][0]['protocol']['checksum'] = 'unpredictable' self.assert_json_structure_equal({ 'meetings': [ {'agenda_items': [ {'title': u'A Gesch\xfcfte'}, {'number': '1.', 'proposal': { 'checksum': 'e00d6c8fb32c30d3ca3a3f8e5d873565482567561023016d9ca18243ff1cfa14', 'file': '1. Ad-hoc Traktandthm/Ad hoc agenda item Ad-hoc Traktandthm.docx', 'modified': '2017-12-12T23:00:00+01:00' }, 'title': u'Ad-hoc Traktand\xfem'}, {'attachments': [{ 'checksum': '51d6317494eccc4a73154625a6820cb6b50dc1455eb4cf26399299d4f9ce77b2', 'file': '2. Anderungen am Personalreglement/Vertragsentwurf.docx', 'modified': '2016-08-31T15:21:46+02:00', 'title': u'Vertr\xe4gsentwurf'}], 'number': '2.', 'proposal': { 'checksum': 'e00d6c8fb32c30d3ca3a3f8e5d873565482567561023016d9ca18243ff1cfa14', 'file': '2. Anderungen am Personalreglement/Anderungen am Personalreglement.docx', 'modified': '2016-08-31T15:21:44+02:00' }, 'title': u'\xc4nderungen am Personalreglement'} ], 'committee': {'oguid': 'plone:1009233300', 'title': u'Rechnungspr\xfcfungskommission'}, 'end': '2016-09-12T17:00:00+00:00', 'location': u'B\xfcren an der Aare', 'protocol': { 'checksum': 'unpredictable', 'file': 'Protocol-9. Sitzung der Rechnungsprufungskommission.docx', 'modified': '2017-12-13T23:00:00+01:00' }, 'start': '2016-09-12T15:30:00+00:00', 'title': u'9. Sitzung der Rechnungspr\xfcfungskommission'} ], 'version': '1.0.0' }, meeting_json) file_names = zip_file.namelist() for file_name in [ '1. Ad-hoc Traktandthm/Ad hoc agenda item Ad-hoc Traktandthm.docx', '2. Anderungen am Personalreglement/Vertragsentwurf.docx', '2. Anderungen am Personalreglement/Anderungen am Personalreglement.docx', 'Protocol-9. Sitzung der Rechnungsprufungskommission.docx']: self.assertIn(file_name, file_names)
def test_directory_tree_gets_builded_correctly_in_zip(self): self.browser.open("%s/zip_export" % self.superfolder.absolute_url()) zipfile = ZipFile(StringIO(self.browser.contents), 'r') self.assertEquals( ['SUPERFILE', 'Folder/testdata.txt', 'Folder/moretest.data'], zipfile.namelist())
def test_zip_multiple_files_in_folder(self): self.browser.open("%s/zip_export" % self.folder.absolute_url()) zipfile = ZipFile(StringIO(self.browser.contents), 'r') self.assertEquals(['testdata.txt', 'moretest.data'], zipfile.namelist())
def test_zip_single_file_download(self): self.browser.open("%s/zip_export" % self.folderfile.absolute_url()) zipfile = ZipFile(StringIO(self.browser.contents), 'r') self.assertEquals(["testdata.txt"], zipfile.namelist())
def test_zip_export_agenda_items_attachments(self, browser): attachement1 = create( Builder('document') .titled(u'Attachem\xe4nt 1') .attach_file_containing(u"attachement", u"attachement1.docx") .within(self.dossier)) attachement2 = create( Builder('document') .titled(u'Attachem\xe4nt 2') .attach_file_containing(u"attachement", u"attachement2.docx") .within(self.dossier)) self.proposal_a = create( Builder('proposal') .titled(u'Proposal \xc4') .within(self.dossier) .as_submitted() .having(committee=self.committee.load_model()) .relate_to(attachement1, attachement2)) self.proposal_b = create( Builder('proposal') .titled(u'Proposal B') .within(self.dossier) .as_submitted() .having(committee=self.committee.load_model()) .relate_to(attachement1)) self.proposal_c = create( Builder('proposal') .titled(u'Proposal C') .within(self.dossier) .as_submitted() .having(committee=self.committee.load_model()) ) meeting = create( Builder('meeting') .having(committee=self.committee.load_model(), start=self.localized_datetime(2013, 1, 1, 8, 30), end=self.localized_datetime(2013, 1, 1, 10, 30), location='There', presidency=self.hugo, participants=[self.peter, self.hans, self.roland], secretary=self.sile) .scheduled_proposals([self.proposal_a, self.proposal_b]) .link_with(self.meeting_dossier)) browser.login().visit(meeting.get_url()) browser.open(meeting.get_url(view='zipexport')) zip_file = ZipFile(StringIO(browser.contents), 'r') meeting = Meeting.query.get(meeting.meeting_id) self.assertIn('1. Proposal A/Attachemant 2.docx', zip_file.namelist()) self.assertIn('1. Proposal A/Attachemant 1.docx', zip_file.namelist()) self.assertIn('2. Proposal B/Attachemant 1.docx', zip_file.namelist()) self.assertNotIn('3. Proposal C', zip_file.namelist())
def test_exported_meeting_json_has_correct_file_names(self, browser): set_preferred_language(self.portal.REQUEST, 'de-ch') browser.append_request_header('Accept-Language', 'de-ch') self.login(self.committee_responsible, browser) self.meeting.model.title = u'9. Sitzung der Rechnungspr\xfcfungs' \ u'kommission, ordentlich' self.schedule_paragraph(self.meeting, u'A Gesch\xfcfte') with freeze(localized_datetime(2017, 12, 13)): self.schedule_ad_hoc( self.meeting, u'Ad-hoc Traktand\xfem' ).decide() agenda_item = self.schedule_proposal(self.meeting, self.submitted_proposal) self.decide_agendaitem_generate_and_return_excerpt(agenda_item) with freeze(localized_datetime(2017, 12, 14)): self.meeting.model.close() browser.open(self.meeting, view='export-meeting-zip') self.assertEquals('application/zip', browser.contenttype) zip_file = ZipFile(StringIO(browser.contents), 'r') meeting_json = json.loads(zip_file.read('meeting.json')) # the protocol is generated during the tests and its checksum cannot # be predicted meeting_json['meetings'][0]['protocol']['checksum'] = 'unpredictable' meeting_json['meetings'][0].pop('opengever_id') for agenda_item in meeting_json['meetings'][0]['agenda_items']: agenda_item.pop('opengever_id') expected_meeting_json = { u'meetings': [{ u'agenda_items': [ {u'sort_order': 1, u'title': u'A Gesch\xfcfte'}, { u'number': u'1.', u'number_raw': 1, u'proposal': { u'checksum': u'e00d6c8fb32c30d3ca3a3f8e5d873565482567561023016d9ca18243ff1cfa14', u'file': u'Traktandum 1/Ad-hoc Traktandthm.docx', u'modified': u'2017-12-13T00:00:00+01:00', }, u'sort_order': 2, u'title': u'Ad-hoc Traktand\xfem', }, { u'attachments': [{ u'checksum': u'51d6317494eccc4a73154625a6820cb6b50dc1455eb4cf26399299d4f9ce77b2', u'file': u'Traktandum 2/Beilage/1_Vertraegsentwurf.docx', u'modified': u'2016-08-31T16:09:37+02:00', u'title': u'Vertr\xe4gsentwurf', }], u'number': u'2.', u'number_raw': 2, u'proposal': { u'checksum': u'114e7a059dc34c7459dab90904685584e331089d80bb6310183a0de009b66c3b', u'file': u'Traktandum 2/Vertraege.docx', u'modified': u'2016-08-31T16:09:35+02:00', }, u'sort_order': 3, u'title': u'Vertr\xe4ge', }, ], u'committee': {u'oguid': u'plone:1009313300', u'title': u'Rechnungspr\xfcfungskommission'}, u'end': u'2016-09-12T17:00:00+00:00', u'location': u'B\xfcren an der Aare', u'protocol': { u'checksum': 'unpredictable', u'file': u'Protokoll-9. Sitzung der Rechnungspruefungskommission- ordentlich.docx', u'modified': u'2017-12-14T00:00:00+01:00', }, u'start': u'2016-09-12T15:30:00+00:00', u'title': u'9. Sitzung der Rechnungspr\xfcfungskommission, ordentlich', }], u'version': u'1.0.0', } self.assert_json_structure_equal(expected_meeting_json, meeting_json) expected_file_names = [ 'Protokoll-9. Sitzung der Rechnungspruefungskommission- ordentlich.docx', 'Traktandum 1/Ad-hoc Traktandthm.docx', 'Traktandum 2/Beilage/1_Vertraegsentwurf.docx', 'Traktandum 2/Vertraege.docx', 'meeting.json', ] file_names = sorted(zip_file.namelist()) self.assertEqual(expected_file_names, file_names)